]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #101021 - MingyuChen1:diagnostic, r=davidtwco
authorDylan DPC <99973273+Dylan-DPC@users.noreply.github.com>
Tue, 6 Sep 2022 11:04:42 +0000 (16:34 +0530)
committerGitHub <noreply@github.com>
Tue, 6 Sep 2022 11:04:42 +0000 (16:34 +0530)
Migrate ``rustc_middle`` diagnostic

Part of #100717

853 files changed:
.gitignore
Cargo.lock
compiler/rustc_ast/src/ast.rs
compiler/rustc_ast/src/lib.rs
compiler/rustc_ast/src/util/literal.rs
compiler/rustc_ast_lowering/src/asm.rs
compiler/rustc_ast_lowering/src/expr.rs
compiler/rustc_ast_lowering/src/index.rs
compiler/rustc_ast_lowering/src/item.rs
compiler/rustc_ast_lowering/src/lib.rs
compiler/rustc_ast_lowering/src/pat.rs
compiler/rustc_ast_lowering/src/path.rs
compiler/rustc_ast_passes/src/ast_validation.rs
compiler/rustc_ast_passes/src/feature_gate.rs
compiler/rustc_ast_passes/src/lib.rs
compiler/rustc_ast_pretty/src/pprust/state.rs
compiler/rustc_ast_pretty/src/pprust/state/item.rs
compiler/rustc_attr/src/builtin.rs
compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs
compiler/rustc_borrowck/src/diagnostics/region_errors.rs
compiler/rustc_borrowck/src/diagnostics/region_name.rs
compiler/rustc_borrowck/src/region_infer/mod.rs
compiler/rustc_borrowck/src/region_infer/opaque_types.rs
compiler/rustc_borrowck/src/universal_regions.rs
compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
compiler/rustc_builtin_macros/src/lib.rs
compiler/rustc_builtin_macros/src/test.rs
compiler/rustc_builtin_macros/src/test_harness.rs
compiler/rustc_codegen_cranelift/src/main_shim.rs
compiler/rustc_codegen_llvm/src/asm.rs
compiler/rustc_codegen_llvm/src/attributes.rs
compiler/rustc_codegen_llvm/src/back/archive.rs
compiler/rustc_codegen_llvm/src/back/lto.rs
compiler/rustc_codegen_llvm/src/back/write.rs
compiler/rustc_codegen_llvm/src/builder.rs
compiler/rustc_codegen_llvm/src/callee.rs
compiler/rustc_codegen_llvm/src/common.rs
compiler/rustc_codegen_llvm/src/consts.rs
compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
compiler/rustc_codegen_llvm/src/debuginfo/utils.rs
compiler/rustc_codegen_llvm/src/declare.rs
compiler/rustc_codegen_llvm/src/lib.rs
compiler/rustc_codegen_llvm/src/llvm_util.rs
compiler/rustc_codegen_llvm/src/mono_item.rs
compiler/rustc_codegen_llvm/src/type_of.rs
compiler/rustc_codegen_ssa/src/back/link.rs
compiler/rustc_codegen_ssa/src/back/linker.rs
compiler/rustc_codegen_ssa/src/base.rs
compiler/rustc_codegen_ssa/src/mir/block.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/intern.rs
compiler/rustc_const_eval/src/interpret/machine.rs
compiler/rustc_const_eval/src/interpret/terminator.rs
compiler/rustc_const_eval/src/interpret/validity.rs
compiler/rustc_const_eval/src/transform/validate.rs
compiler/rustc_driver/Cargo.toml
compiler/rustc_error_messages/locales/en-US/lint.ftl
compiler/rustc_error_messages/locales/en-US/metadata.ftl [new file with mode: 0644]
compiler/rustc_error_messages/locales/en-US/privacy.ftl
compiler/rustc_error_messages/locales/en-US/trait_selection.ftl [new file with mode: 0644]
compiler/rustc_error_messages/src/lib.rs
compiler/rustc_errors/Cargo.toml
compiler/rustc_errors/src/diagnostic.rs
compiler/rustc_errors/src/diagnostic_builder.rs
compiler/rustc_errors/src/emitter.rs
compiler/rustc_expand/src/build.rs
compiler/rustc_expand/src/lib.rs
compiler/rustc_expand/src/mbe/macro_rules.rs
compiler/rustc_feature/src/active.rs
compiler/rustc_feature/src/builtin_attrs.rs
compiler/rustc_feature/src/lib.rs
compiler/rustc_hir/src/def.rs
compiler/rustc_hir/src/definitions.rs
compiler/rustc_hir/src/hir.rs
compiler/rustc_hir/src/hir_id.rs
compiler/rustc_hir/src/intravisit.rs
compiler/rustc_hir/src/lang_items.rs
compiler/rustc_hir/src/lib.rs
compiler/rustc_hir/src/pat_util.rs
compiler/rustc_hir_pretty/src/lib.rs
compiler/rustc_infer/src/infer/combine.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/trait_impl_difference.rs
compiler/rustc_infer/src/infer/higher_ranked/mod.rs
compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
compiler/rustc_infer/src/infer/nll_relate/mod.rs
compiler/rustc_infer/src/infer/opaque_types.rs
compiler/rustc_infer/src/infer/opaque_types/table.rs
compiler/rustc_infer/src/infer/outlives/mod.rs
compiler/rustc_infer/src/infer/outlives/obligations.rs
compiler/rustc_infer/src/infer/outlives/test_type_match.rs
compiler/rustc_interface/src/interface.rs
compiler/rustc_interface/src/lib.rs
compiler/rustc_interface/src/passes.rs
compiler/rustc_interface/src/queries.rs
compiler/rustc_interface/src/tests.rs
compiler/rustc_interface/src/util.rs
compiler/rustc_lint/src/array_into_iter.rs
compiler/rustc_lint/src/builtin.rs
compiler/rustc_lint/src/context.rs
compiler/rustc_lint/src/early.rs
compiler/rustc_lint/src/internal.rs
compiler/rustc_lint/src/late.rs
compiler/rustc_lint/src/let_underscore.rs [new file with mode: 0644]
compiler/rustc_lint/src/levels.rs
compiler/rustc_lint/src/lib.rs
compiler/rustc_lint/src/methods.rs
compiler/rustc_lint/src/noop_method_call.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/subdiagnostic.rs
compiler/rustc_metadata/src/creader.rs
compiler/rustc_metadata/src/dependency_format.rs
compiler/rustc_metadata/src/errors.rs [new file with mode: 0644]
compiler/rustc_metadata/src/fs.rs
compiler/rustc_metadata/src/lib.rs
compiler/rustc_metadata/src/locator.rs
compiler/rustc_metadata/src/native_libs.rs
compiler/rustc_metadata/src/rmeta/decoder.rs
compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
compiler/rustc_metadata/src/rmeta/encoder.rs
compiler/rustc_metadata/src/rmeta/mod.rs
compiler/rustc_metadata/src/rmeta/table.rs
compiler/rustc_middle/src/arena.rs
compiler/rustc_middle/src/dep_graph/dep_node.rs
compiler/rustc_middle/src/hir/map/mod.rs
compiler/rustc_middle/src/mir/mod.rs
compiler/rustc_middle/src/query/mod.rs
compiler/rustc_middle/src/thir.rs
compiler/rustc_middle/src/thir/visit.rs
compiler/rustc_middle/src/ty/binding.rs
compiler/rustc_middle/src/ty/consts.rs
compiler/rustc_middle/src/ty/consts/kind.rs
compiler/rustc_middle/src/ty/consts/valtree.rs
compiler/rustc_middle/src/ty/context.rs
compiler/rustc_middle/src/ty/fold.rs
compiler/rustc_middle/src/ty/layout.rs
compiler/rustc_middle/src/ty/mod.rs
compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
compiler/rustc_middle/src/ty/parameterized.rs
compiler/rustc_middle/src/ty/sty.rs
compiler/rustc_middle/src/ty/trait_def.rs
compiler/rustc_middle/src/ty/util.rs
compiler/rustc_middle/src/ty/visit.rs
compiler/rustc_mir_build/src/build/block.rs
compiler/rustc_mir_build/src/build/expr/as_constant.rs
compiler/rustc_mir_build/src/build/expr/as_place.rs
compiler/rustc_mir_build/src/build/expr/into.rs
compiler/rustc_mir_build/src/build/matches/mod.rs
compiler/rustc_mir_build/src/build/matches/simplify.rs
compiler/rustc_mir_build/src/build/matches/test.rs
compiler/rustc_mir_build/src/build/matches/util.rs
compiler/rustc_mir_build/src/build/mod.rs
compiler/rustc_mir_build/src/check_unsafety.rs
compiler/rustc_mir_build/src/thir/cx/block.rs
compiler/rustc_mir_build/src/thir/cx/expr.rs
compiler/rustc_mir_build/src/thir/cx/mod.rs
compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
compiler/rustc_mir_build/src/thir/pattern/mod.rs
compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
compiler/rustc_mir_transform/src/lib.rs
compiler/rustc_monomorphize/src/collector.rs
compiler/rustc_monomorphize/src/polymorphize.rs
compiler/rustc_parse/src/lexer/mod.rs
compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
compiler/rustc_parse/src/parser/attr.rs
compiler/rustc_parse/src/parser/attr_wrapper.rs
compiler/rustc_parse/src/parser/diagnostics.rs
compiler/rustc_parse/src/parser/item.rs
compiler/rustc_parse/src/parser/mod.rs
compiler/rustc_parse/src/parser/pat.rs
compiler/rustc_parse/src/parser/path.rs
compiler/rustc_passes/src/check_attr.rs
compiler/rustc_passes/src/entry.rs
compiler/rustc_passes/src/hir_stats.rs
compiler/rustc_passes/src/lib_features.rs
compiler/rustc_passes/src/liveness.rs
compiler/rustc_passes/src/naked_functions.rs
compiler/rustc_passes/src/stability.rs
compiler/rustc_privacy/src/errors.rs
compiler/rustc_privacy/src/lib.rs
compiler/rustc_query_impl/src/plumbing.rs
compiler/rustc_query_system/src/query/config.rs
compiler/rustc_resolve/src/access_levels.rs
compiler/rustc_resolve/src/build_reduced_graph.rs
compiler/rustc_resolve/src/def_collector.rs
compiler/rustc_resolve/src/diagnostics.rs
compiler/rustc_resolve/src/ident.rs
compiler/rustc_resolve/src/imports.rs
compiler/rustc_resolve/src/late.rs
compiler/rustc_resolve/src/late/diagnostics.rs
compiler/rustc_resolve/src/late/lifetimes.rs
compiler/rustc_resolve/src/lib.rs
compiler/rustc_save_analysis/src/dump_visitor.rs
compiler/rustc_save_analysis/src/lib.rs
compiler/rustc_session/src/cgu_reuse_tracker.rs
compiler/rustc_session/src/config.rs
compiler/rustc_session/src/config/sigpipe.rs [new file with mode: 0644]
compiler/rustc_session/src/filesearch.rs
compiler/rustc_session/src/lib.rs
compiler/rustc_session/src/options.rs
compiler/rustc_session/src/parse.rs
compiler/rustc_session/src/session.rs
compiler/rustc_span/src/hygiene.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/lib.rs
compiler/rustc_target/src/spec/asmjs_unknown_emscripten.rs
compiler/rustc_target/src/spec/bpf_base.rs
compiler/rustc_target/src/spec/l4re_base.rs
compiler/rustc_target/src/spec/mod.rs
compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs
compiler/rustc_target/src/spec/tests/tests_impl.rs
compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs
compiler/rustc_trait_selection/src/autoderef.rs
compiler/rustc_trait_selection/src/errors.rs [new file with mode: 0644]
compiler/rustc_trait_selection/src/infer.rs
compiler/rustc_trait_selection/src/lib.rs
compiler/rustc_trait_selection/src/traits/auto_trait.rs
compiler/rustc_trait_selection/src/traits/codegen.rs
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/fulfill.rs
compiler/rustc_trait_selection/src/traits/mod.rs
compiler/rustc_trait_selection/src/traits/on_unimplemented.rs
compiler/rustc_trait_selection/src/traits/project.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/specialize/mod.rs
compiler/rustc_trait_selection/src/traits/wf.rs
compiler/rustc_transmute/Cargo.toml
compiler/rustc_transmute/src/layout/dfa.rs
compiler/rustc_transmute/src/layout/nfa.rs
compiler/rustc_transmute/src/layout/tree.rs
compiler/rustc_transmute/src/lib.rs
compiler/rustc_transmute/src/maybe_transmutable/mod.rs
compiler/rustc_transmute/src/maybe_transmutable/query_context.rs
compiler/rustc_transmute/src/maybe_transmutable/tests.rs
compiler/rustc_ty_utils/src/consts.rs
compiler/rustc_ty_utils/src/instance.rs
compiler/rustc_ty_utils/src/ty.rs
compiler/rustc_typeck/src/astconv/generics.rs
compiler/rustc_typeck/src/astconv/mod.rs
compiler/rustc_typeck/src/check/_match.rs
compiler/rustc_typeck/src/check/callee.rs
compiler/rustc_typeck/src/check/cast.rs
compiler/rustc_typeck/src/check/check.rs
compiler/rustc_typeck/src/check/closure.rs
compiler/rustc_typeck/src/check/compare_method.rs
compiler/rustc_typeck/src/check/demand.rs
compiler/rustc_typeck/src/check/expr.rs
compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
compiler/rustc_typeck/src/check/generator_interior.rs
compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs
compiler/rustc_typeck/src/check/generator_interior/drop_ranges/record_consumed_borrow.rs
compiler/rustc_typeck/src/check/inherited.rs
compiler/rustc_typeck/src/check/method/mod.rs
compiler/rustc_typeck/src/check/method/prelude2021.rs
compiler/rustc_typeck/src/check/method/probe.rs
compiler/rustc_typeck/src/check/method/suggest.rs
compiler/rustc_typeck/src/check/mod.rs
compiler/rustc_typeck/src/check/op.rs
compiler/rustc_typeck/src/check/pat.rs
compiler/rustc_typeck/src/check/region.rs
compiler/rustc_typeck/src/check/upvar.rs
compiler/rustc_typeck/src/check/wfcheck.rs
compiler/rustc_typeck/src/collect/type_of.rs
compiler/rustc_typeck/src/expr_use_visitor.rs
compiler/rustc_typeck/src/lib.rs
compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs
config.toml.example
library/alloc/src/collections/btree/dedup_sorted_iter.rs
library/alloc/src/lib.rs
library/alloc/src/vec/is_zero.rs
library/backtrace
library/core/src/any.rs
library/core/src/char/methods.rs
library/core/src/intrinsics.rs
library/core/src/lib.rs
library/core/src/mem/transmutability.rs
library/core/src/mem/valid_align.rs
library/core/src/num/f32.rs
library/core/src/num/f64.rs
library/core/src/num/nonzero.rs
library/core/src/ops/range.rs
library/core/src/ops/try_trait.rs
library/core/src/ptr/const_ptr.rs
library/core/src/ptr/mod.rs
library/core/src/slice/index.rs
library/core/src/slice/mod.rs
library/core/src/slice/raw.rs
library/core/src/str/mod.rs
library/core/src/unicode/unicode_data.rs
library/core/tests/any.rs
library/portable-simd/crates/std_float/src/lib.rs
library/proc_macro/src/bridge/server.rs
library/std/src/alloc.rs
library/std/src/collections/hash/set.rs
library/std/src/fs.rs
library/std/src/io/stdio.rs
library/std/src/os/fd/owned.rs
library/std/src/rt.rs
library/std/src/sync/mutex.rs
library/std/src/sync/once_lock.rs
library/std/src/sync/rwlock.rs
library/std/src/sys/hermit/mod.rs
library/std/src/sys/hermit/mutex.rs
library/std/src/sys/itron/mutex.rs
library/std/src/sys/sgx/mod.rs
library/std/src/sys/sgx/mutex.rs
library/std/src/sys/solid/mod.rs
library/std/src/sys/unix/locks/fuchsia_mutex.rs
library/std/src/sys/unix/locks/futex_mutex.rs
library/std/src/sys/unix/locks/pthread_mutex.rs
library/std/src/sys/unix/mod.rs
library/std/src/sys/unix/thread.rs
library/std/src/sys/unsupported/common.rs
library/std/src/sys/unsupported/locks/mutex.rs
library/std/src/sys/windows/c.rs
library/std/src/sys/windows/fs.rs
library/std/src/sys/windows/locks/mutex.rs
library/std/src/sys/windows/mod.rs
library/std/src/sys/windows/rand.rs
library/std/src/sys_common/remutex.rs
library/std/src/sys_common/remutex/tests.rs
src/bootstrap/bootstrap.py
src/bootstrap/compile.rs
src/bootstrap/config.rs
src/bootstrap/dist.rs
src/bootstrap/doc.rs
src/bootstrap/lib.rs
src/bootstrap/test.rs
src/ci/docker/host-x86_64/arm-android/Dockerfile
src/ci/docker/host-x86_64/dist-android/Dockerfile
src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile
src/ci/docker/host-x86_64/i686-gnu/Dockerfile
src/ci/docker/host-x86_64/mingw-check/Dockerfile
src/ci/docker/host-x86_64/x86_64-gnu-aux/Dockerfile
src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile
src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile
src/ci/docker/scripts/android-base-apt-get.sh
src/doc/rustc/src/platform-support/armv4t-none-eabi.md [new file with mode: 0644]
src/doc/rustc/src/platform-support/armv4t_none_eabi.md [deleted file]
src/doc/rustc/src/platform-support/fuchsia.md
src/doc/unstable-book/src/language-features/unix-sigpipe.md [new file with mode: 0644]
src/librustdoc/clean/mod.rs
src/librustdoc/clean/types.rs
src/librustdoc/clean/utils.rs
src/librustdoc/fold.rs
src/librustdoc/html/format.rs
src/librustdoc/html/render/mod.rs
src/librustdoc/html/render/print_item.rs
src/librustdoc/html/render/span_map.rs
src/librustdoc/html/render/write_shared.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/json/conversions.rs
src/librustdoc/passes/collect_intra_doc_links.rs
src/librustdoc/passes/propagate_doc_cfg.rs
src/librustdoc/passes/stripper.rs
src/librustdoc/scrape_examples.rs
src/librustdoc/visit.rs
src/llvm-project
src/rustdoc-json-types/lib.rs
src/test/incremental/const-generics/hash-tyvid-regression-1.rs
src/test/mir-opt/early_otherwise_branch_68867.rs
src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.before-SimplifyConstCondition-final.after.diff [deleted file]
src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff
src/test/mir-opt/issue-73223.rs
src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff [deleted file]
src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff [deleted file]
src/test/mir-opt/lower_array_len.array_bound.InstCombine.diff [deleted file]
src/test/mir-opt/lower_array_len.array_bound.SimplifyLocals.diff [deleted file]
src/test/mir-opt/lower_array_len.array_bound_mut.InstCombine.diff [deleted file]
src/test/mir-opt/lower_array_len.array_bound_mut.SimplifyLocals.diff [deleted file]
src/test/mir-opt/lower_array_len.array_len.InstCombine.diff [deleted file]
src/test/mir-opt/lower_array_len.array_len.SimplifyLocals.diff [deleted file]
src/test/mir-opt/lower_array_len.array_len_by_value.InstCombine.diff [deleted file]
src/test/mir-opt/lower_array_len.array_len_by_value.SimplifyLocals.diff [deleted file]
src/test/mir-opt/lower_array_len.rs
src/test/mir-opt/lower_array_len_e2e.array_bound.PreCodegen.after.mir [new file with mode: 0644]
src/test/mir-opt/lower_array_len_e2e.array_bound_mut.PreCodegen.after.mir [new file with mode: 0644]
src/test/mir-opt/lower_array_len_e2e.array_len.PreCodegen.after.mir [new file with mode: 0644]
src/test/mir-opt/lower_array_len_e2e.array_len_by_value.PreCodegen.after.mir [new file with mode: 0644]
src/test/mir-opt/lower_array_len_e2e.rs [new file with mode: 0644]
src/test/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.diff
src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff
src/test/mir-opt/lower_intrinsics.f_u64.PreCodegen.before.mir [deleted file]
src/test/mir-opt/lower_intrinsics.f_unit.PreCodegen.before.mir [deleted file]
src/test/mir-opt/lower_intrinsics.forget.LowerIntrinsics.diff
src/test/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.diff
src/test/mir-opt/lower_intrinsics.rs
src/test/mir-opt/lower_intrinsics.size_of.LowerIntrinsics.diff
src/test/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff
src/test/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.diff
src/test/mir-opt/lower_intrinsics_e2e.f_u64.PreCodegen.after.mir [new file with mode: 0644]
src/test/mir-opt/lower_intrinsics_e2e.f_unit.PreCodegen.after.mir [new file with mode: 0644]
src/test/mir-opt/lower_intrinsics_e2e.rs [new file with mode: 0644]
src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.32bit.diff
src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.64bit.diff
src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.32bit.diff
src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.64bit.diff
src/test/mir-opt/matches_reduce_branches.foo.PreCodegen.before.32bit.mir [deleted file]
src/test/mir-opt/matches_reduce_branches.foo.PreCodegen.before.64bit.mir [deleted file]
src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.32bit.diff
src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.64bit.diff
src/test/mir-opt/matches_reduce_branches.rs
src/test/mir-opt/matches_u8.rs
src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff
src/test/mir-opt/separate_const_switch.rs
src/test/mir-opt/simplify-arm-identity.rs
src/test/mir-opt/simplify-arm.rs
src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads.rs
src/test/mir-opt/simplify_arm.id.SimplifyArmIdentity.diff [deleted file]
src/test/mir-opt/simplify_arm.id.SimplifyBranchSame.diff [deleted file]
src/test/mir-opt/simplify_arm.id_result.SimplifyArmIdentity.diff [deleted file]
src/test/mir-opt/simplify_arm.id_result.SimplifyBranchSame.diff [deleted file]
src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.32bit.diff [deleted file]
src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.64bit.diff [deleted file]
src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.32bit.diff
src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.64bit.diff
src/test/mir-opt/simplify_try.rs [deleted file]
src/test/mir-opt/try_identity_e2e.new.PreCodegen.after.mir [new file with mode: 0644]
src/test/mir-opt/try_identity_e2e.old.PreCodegen.after.mir [new file with mode: 0644]
src/test/mir-opt/try_identity_e2e.rs [new file with mode: 0644]
src/test/rustdoc-gui/item-info-alignment.goml [new file with mode: 0644]
src/test/rustdoc-gui/search-form-elements.goml
src/test/rustdoc-gui/search-input.goml [deleted file]
src/test/rustdoc-gui/src/lib2/lib.rs
src/test/rustdoc-gui/type-declation-overflow.goml
src/test/rustdoc-gui/where-whitespace.goml [new file with mode: 0644]
src/test/rustdoc-json/enums/discriminant/basic.rs [new file with mode: 0644]
src/test/rustdoc-json/enums/discriminant/expr.rs [new file with mode: 0644]
src/test/rustdoc-json/enums/discriminant/limits.rs [new file with mode: 0644]
src/test/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs [new file with mode: 0644]
src/test/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs [new file with mode: 0644]
src/test/rustdoc/const-generics/const-generics-docs.rs
src/test/rustdoc/doc_auto_cfg_nested_impl.rs [new file with mode: 0644]
src/test/rustdoc/generic-associated-types/gats.rs
src/test/rustdoc/higher-ranked-trait-bounds.rs
src/test/rustdoc/impl-parts.rs
src/test/rustdoc/issue-20727-4.rs
src/test/rustdoc/issue-21801.rs
src/test/rustdoc/issue-29503.rs
src/test/rustdoc/issue-34928.rs
src/test/rustdoc/issue-50159.rs
src/test/rustdoc/issue-51236.rs
src/test/rustdoc/issue-54705.rs
src/test/rustdoc/issue-98697.rs
src/test/rustdoc/primitive-slice-auto-trait.rs
src/test/rustdoc/synthetic_auto/basic.rs
src/test/rustdoc/synthetic_auto/complex.rs
src/test/rustdoc/synthetic_auto/lifetimes.rs
src/test/rustdoc/synthetic_auto/manual.rs
src/test/rustdoc/synthetic_auto/nested.rs
src/test/rustdoc/synthetic_auto/no-redundancy.rs
src/test/rustdoc/synthetic_auto/project.rs
src/test/rustdoc/synthetic_auto/self-referential.rs
src/test/rustdoc/synthetic_auto/static-region.rs
src/test/rustdoc/where-clause-order.rs
src/test/rustdoc/where.rs
src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
src/test/ui/argument-suggestions/basic.stderr
src/test/ui/argument-suggestions/complex.stderr
src/test/ui/argument-suggestions/exotic-calls.stderr
src/test/ui/argument-suggestions/extra_arguments.stderr
src/test/ui/argument-suggestions/issue-96638.stderr
src/test/ui/argument-suggestions/issue-97197.stderr
src/test/ui/argument-suggestions/issue-97484.stderr
src/test/ui/argument-suggestions/issue-98894.stderr
src/test/ui/argument-suggestions/issue-98897.stderr
src/test/ui/argument-suggestions/issue-99482.stderr
src/test/ui/argument-suggestions/missing_arguments.stderr
src/test/ui/argument-suggestions/mixed_cases.stderr
src/test/ui/argument-suggestions/permuted_arguments.stderr
src/test/ui/argument-suggestions/swapped_arguments.stderr
src/test/ui/asm/unpretty-expanded.rs [new file with mode: 0644]
src/test/ui/asm/unpretty-expanded.stdout [new file with mode: 0644]
src/test/ui/associated-types/associated-types-path-2.rs
src/test/ui/associated-types/associated-types-path-2.stderr
src/test/ui/async-await/issue-73137.rs
src/test/ui/async-await/issues/issue-62009-1.stderr
src/test/ui/attributes/issue-100631.rs [new file with mode: 0644]
src/test/ui/attributes/issue-100631.stderr [new file with mode: 0644]
src/test/ui/attributes/unix_sigpipe/auxiliary/sigpipe-utils.rs [new file with mode: 0644]
src/test/ui/attributes/unix_sigpipe/unix_sigpipe-crate.rs [new file with mode: 0644]
src/test/ui/attributes/unix_sigpipe/unix_sigpipe-crate.stderr [new file with mode: 0644]
src/test/ui/attributes/unix_sigpipe/unix_sigpipe-duplicates.rs [new file with mode: 0644]
src/test/ui/attributes/unix_sigpipe/unix_sigpipe-duplicates.stderr [new file with mode: 0644]
src/test/ui/attributes/unix_sigpipe/unix_sigpipe-error.rs [new file with mode: 0644]
src/test/ui/attributes/unix_sigpipe/unix_sigpipe-inherit.rs [new file with mode: 0644]
src/test/ui/attributes/unix_sigpipe/unix_sigpipe-list.rs [new file with mode: 0644]
src/test/ui/attributes/unix_sigpipe/unix_sigpipe-list.stderr [new file with mode: 0644]
src/test/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.rs [new file with mode: 0644]
src/test/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.stderr [new file with mode: 0644]
src/test/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.rs [new file with mode: 0644]
src/test/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.stderr [new file with mode: 0644]
src/test/ui/attributes/unix_sigpipe/unix_sigpipe-not-used.rs [new file with mode: 0644]
src/test/ui/attributes/unix_sigpipe/unix_sigpipe-only-feature.rs [new file with mode: 0644]
src/test/ui/attributes/unix_sigpipe/unix_sigpipe-rustc_main.rs [new file with mode: 0644]
src/test/ui/attributes/unix_sigpipe/unix_sigpipe-sig_dfl.rs [new file with mode: 0644]
src/test/ui/attributes/unix_sigpipe/unix_sigpipe-start.rs [new file with mode: 0644]
src/test/ui/attributes/unix_sigpipe/unix_sigpipe-start.stderr [new file with mode: 0644]
src/test/ui/attributes/unix_sigpipe/unix_sigpipe-struct.rs [new file with mode: 0644]
src/test/ui/attributes/unix_sigpipe/unix_sigpipe-struct.stderr [new file with mode: 0644]
src/test/ui/attributes/unix_sigpipe/unix_sigpipe-wrong.rs [new file with mode: 0644]
src/test/ui/attributes/unix_sigpipe/unix_sigpipe-wrong.stderr [new file with mode: 0644]
src/test/ui/attributes/unix_sigpipe/unix_sigpipe.rs [new file with mode: 0644]
src/test/ui/attributes/unix_sigpipe/unix_sigpipe.stderr [new file with mode: 0644]
src/test/ui/binop/issue-77910-1.stderr
src/test/ui/borrowck/do-not-suggest-adding-move-when-closure-is-already-marked-as-move.rs [new file with mode: 0644]
src/test/ui/borrowck/do-not-suggest-adding-move-when-closure-is-already-marked-as-move.stderr [new file with mode: 0644]
src/test/ui/borrowck/issue-101119.rs [new file with mode: 0644]
src/test/ui/borrowck/issue-101119.stderr [new file with mode: 0644]
src/test/ui/c-variadic/variadic-ffi-1.stderr
src/test/ui/check-cfg/allow-at-crate-level.rs [new file with mode: 0644]
src/test/ui/check-cfg/invalid-cfg-value.stderr
src/test/ui/check-cfg/mix.rs
src/test/ui/check-cfg/mix.stderr
src/test/ui/closures/coerce-unsafe-to-closure.stderr
src/test/ui/coercion/issue-101066.rs [new file with mode: 0644]
src/test/ui/consts/const-float-bits-reject-conv.stderr
src/test/ui/error-codes/E0057.stderr
src/test/ui/error-codes/E0060.stderr
src/test/ui/error-codes/E0061.stderr
src/test/ui/extern/extern-wrong-value-type.stderr
src/test/ui/feature-gates/feature-gate-unix_sigpipe.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-unix_sigpipe.stderr [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr
src/test/ui/higher-rank-trait-bounds/issue-58451.stderr
src/test/ui/intrinsics/const-eval-select-backtrace-std.rs [new file with mode: 0644]
src/test/ui/intrinsics/const-eval-select-backtrace-std.run.stderr [new file with mode: 0644]
src/test/ui/intrinsics/const-eval-select-backtrace.rs [new file with mode: 0644]
src/test/ui/intrinsics/const-eval-select-backtrace.run.stderr [new file with mode: 0644]
src/test/ui/intrinsics/const-eval-select-bad.rs
src/test/ui/intrinsics/const-eval-select-bad.stderr
src/test/ui/issues/issue-16939.stderr
src/test/ui/issues/issue-18819.stderr
src/test/ui/issues/issue-41139.stderr
src/test/ui/issues/issue-4935.stderr
src/test/ui/issues/issue-59488.stderr
src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr
src/test/ui/issues/issue-99875.rs [new file with mode: 0644]
src/test/ui/issues/issue-99875.stderr [new file with mode: 0644]
src/test/ui/iterators/issue-28098.rs
src/test/ui/iterators/issue-28098.stderr
src/test/ui/let-else/let-else-drop-order.rs [new file with mode: 0644]
src/test/ui/let-else/let-else-drop-order.run.stdout [new file with mode: 0644]
src/test/ui/lifetimes/issue-26638.stderr
src/test/ui/lint/issue-101284.rs [new file with mode: 0644]
src/test/ui/lint/let_underscore/let_underscore_drop.rs [new file with mode: 0644]
src/test/ui/lint/let_underscore/let_underscore_drop.stderr [new file with mode: 0644]
src/test/ui/lint/let_underscore/let_underscore_lock.rs [new file with mode: 0644]
src/test/ui/lint/let_underscore/let_underscore_lock.stderr [new file with mode: 0644]
src/test/ui/methods/method-call-err-msg.stderr
src/test/ui/mir/issue-99866.rs [new file with mode: 0644]
src/test/ui/mismatched_types/overloaded-calls-bad.stderr
src/test/ui/modules/auxiliary/dummy_lib.rs [new file with mode: 0644]
src/test/ui/modules/special_module_name.rs [new file with mode: 0644]
src/test/ui/modules/special_module_name.stderr [new file with mode: 0644]
src/test/ui/modules/special_module_name_ignore.rs [new file with mode: 0644]
src/test/ui/namespace/namespace-mix.stderr
src/test/ui/not-enough-arguments.stderr
src/test/ui/object-lifetime/object-lifetime-default.rs
src/test/ui/object-lifetime/object-lifetime-default.stderr
src/test/ui/on-unimplemented/enclosing-scope.rs [deleted file]
src/test/ui/on-unimplemented/enclosing-scope.stderr [deleted file]
src/test/ui/on-unimplemented/multiple-impls.rs
src/test/ui/on-unimplemented/multiple-impls.stderr
src/test/ui/on-unimplemented/on-impl.rs
src/test/ui/on-unimplemented/on-impl.stderr
src/test/ui/on-unimplemented/parent-label.rs [new file with mode: 0644]
src/test/ui/on-unimplemented/parent-label.stderr [new file with mode: 0644]
src/test/ui/privacy/access_levels.rs [new file with mode: 0644]
src/test/ui/privacy/access_levels.stderr [new file with mode: 0644]
src/test/ui/proc-macro/auxiliary/expand-expr.rs
src/test/ui/proc-macro/signature.stderr
src/test/ui/resolve/resolve-primitive-fallback.stderr
src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr
src/test/ui/span/issue-34264.stderr
src/test/ui/span/missing-unit-argument.stderr
src/test/ui/stats/hir-stats.stderr
src/test/ui/suggestions/args-instead-of-tuple-errors.stderr
src/test/ui/suggestions/args-instead-of-tuple.stderr
src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
src/test/ui/suggestions/copied-and-cloned.fixed [new file with mode: 0644]
src/test/ui/suggestions/copied-and-cloned.rs [new file with mode: 0644]
src/test/ui/suggestions/copied-and-cloned.stderr [new file with mode: 0644]
src/test/ui/suggestions/deref-path-method.rs [new file with mode: 0644]
src/test/ui/suggestions/deref-path-method.stderr [new file with mode: 0644]
src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
src/test/ui/transmutability/abstraction/abstracted_assume.rs
src/test/ui/transmutability/abstraction/const_generic_fn.rs
src/test/ui/transmutability/arrays/should_have_correct_length.rs
src/test/ui/transmutability/arrays/should_inherit_alignment.rs
src/test/ui/transmutability/arrays/should_require_well_defined_layout.rs
src/test/ui/transmutability/arrays/should_require_well_defined_layout.stderr
src/test/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.rs
src/test/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.stderr
src/test/ui/transmutability/enums/repr/should_require_well_defined_layout.rs
src/test/ui/transmutability/enums/repr/should_require_well_defined_layout.stderr
src/test/ui/transmutability/enums/should_order_correctly.rs
src/test/ui/transmutability/enums/should_pad_variants.rs
src/test/ui/transmutability/enums/should_pad_variants.stderr
src/test/ui/transmutability/enums/should_respect_endianness.rs
src/test/ui/transmutability/enums/should_respect_endianness.stderr
src/test/ui/transmutability/malformed-program-gracefulness/unknown_dst.rs
src/test/ui/transmutability/malformed-program-gracefulness/unknown_src.rs
src/test/ui/transmutability/malformed-program-gracefulness/unknown_src_field.rs
src/test/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.rs
src/test/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.stderr
src/test/ui/transmutability/primitives/bool.rs
src/test/ui/transmutability/primitives/bool.stderr
src/test/ui/transmutability/primitives/numbers.rs
src/test/ui/transmutability/primitives/numbers.stderr
src/test/ui/transmutability/primitives/unit.rs
src/test/ui/transmutability/primitives/unit.stderr
src/test/ui/transmutability/references.rs
src/test/ui/transmutability/references.stderr
src/test/ui/transmutability/structs/repr/should_handle_align.rs
src/test/ui/transmutability/structs/repr/should_handle_packed.rs
src/test/ui/transmutability/structs/repr/should_require_well_defined_layout.rs
src/test/ui/transmutability/structs/repr/should_require_well_defined_layout.stderr
src/test/ui/transmutability/structs/should_order_fields_correctly.rs
src/test/ui/transmutability/unions/boolish.rs
src/test/ui/transmutability/unions/repr/should_handle_align.rs
src/test/ui/transmutability/unions/repr/should_handle_packed.rs
src/test/ui/transmutability/unions/repr/should_require_well_defined_layout.rs
src/test/ui/transmutability/unions/repr/should_require_well_defined_layout.stderr
src/test/ui/transmutability/unions/should_pad_variants.rs
src/test/ui/transmutability/unions/should_pad_variants.stderr
src/test/ui/transmutability/unions/should_permit_intersecting_if_validity_is_assumed.rs
src/test/ui/transmutability/unions/should_reject_contraction.rs
src/test/ui/transmutability/unions/should_reject_contraction.stderr
src/test/ui/transmutability/unions/should_reject_disjoint.rs
src/test/ui/transmutability/unions/should_reject_disjoint.stderr
src/test/ui/transmutability/unions/should_reject_intersecting.rs
src/test/ui/transmutability/unions/should_reject_intersecting.stderr
src/test/ui/transmutability/visibility/assume/should_accept_if_dst_has_private_field.rs
src/test/ui/transmutability/visibility/assume/should_accept_if_dst_has_private_variant.rs
src/test/ui/transmutability/visibility/assume/should_accept_if_dst_has_tricky_unreachable_field.rs
src/test/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_field.rs
src/test/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_ty.rs
src/test/ui/transmutability/visibility/should_accept_if_src_has_private_field.rs
src/test/ui/transmutability/visibility/should_accept_if_src_has_private_variant.rs
src/test/ui/transmutability/visibility/should_accept_if_src_has_unreachable_field.rs
src/test/ui/transmutability/visibility/should_accept_if_src_has_unreachable_field.stderr
src/test/ui/transmutability/visibility/should_accept_if_src_has_unreachable_ty.rs
src/test/ui/transmutability/visibility/should_accept_if_src_has_unreachable_ty.stderr
src/test/ui/transmutability/visibility/should_reject_if_dst_has_private_field.rs
src/test/ui/transmutability/visibility/should_reject_if_dst_has_private_field.stderr
src/test/ui/transmutability/visibility/should_reject_if_dst_has_private_variant.rs
src/test/ui/transmutability/visibility/should_reject_if_dst_has_private_variant.stderr
src/test/ui/transmutability/visibility/should_reject_if_dst_has_tricky_unreachable_field.rs
src/test/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_field.rs
src/test/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_field.stderr
src/test/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_ty.rs
src/test/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_ty.stderr
src/test/ui/try-trait/bad-interconversion.stderr
src/test/ui/try-trait/option-to-result.stderr
src/test/ui/try-trait/try-on-option-diagnostics.stderr
src/test/ui/try-trait/try-on-option.stderr
src/test/ui/try-trait/try-operator-on-main.stderr
src/test/ui/tuple/wrong_argument_ice-3.stderr
src/test/ui/tuple/wrong_argument_ice-4.stderr
src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr
src/test/ui/type/type-ascription-instead-of-initializer.stderr
src/test/ui/typeck/assign-non-lval-needs-deref.rs [new file with mode: 0644]
src/test/ui/typeck/assign-non-lval-needs-deref.stderr [new file with mode: 0644]
src/test/ui/typeck/point-at-type-param-in-path-expr.rs [new file with mode: 0644]
src/test/ui/typeck/point-at-type-param-in-path-expr.stderr [new file with mode: 0644]
src/test/ui/typeck/remove-extra-argument.stderr
src/test/ui/typeck/struct-enum-wrong-args.stderr
src/test/ui/ufcs/ufcs-qpath-self-mismatch.rs
src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr
src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr
src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr
src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr
src/test/ui/unsized/issue-30355.stderr
src/tools/cargo
src/tools/clippy/book/src/development/common_tools_writing_lints.md
src/tools/clippy/clippy_lints/src/assertions_on_result_states.rs
src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs
src/tools/clippy/clippy_lints/src/booleans.rs
src/tools/clippy/clippy_lints/src/casts/cast_abs_to_unsigned.rs
src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs
src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
src/tools/clippy/clippy_lints/src/dereference.rs
src/tools/clippy/clippy_lints/src/doc.rs
src/tools/clippy/clippy_lints/src/entry.rs
src/tools/clippy/clippy_lints/src/eta_reduction.rs
src/tools/clippy/clippy_lints/src/explicit_write.rs
src/tools/clippy/clippy_lints/src/fallible_impl_from.rs
src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
src/tools/clippy/clippy_lints/src/format_args.rs
src/tools/clippy/clippy_lints/src/format_impl.rs
src/tools/clippy/clippy_lints/src/format_push_string.rs
src/tools/clippy/clippy_lints/src/functions/must_use.rs
src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
src/tools/clippy/clippy_lints/src/if_let_mutex.rs
src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
src/tools/clippy/clippy_lints/src/infinite_iter.rs
src/tools/clippy/clippy_lints/src/len_zero.rs
src/tools/clippy/clippy_lints/src/let_if_seq.rs
src/tools/clippy/clippy_lints/src/loops/manual_find.rs
src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
src/tools/clippy/clippy_lints/src/loops/missing_spin_loop.rs
src/tools/clippy/clippy_lints/src/loops/mod.rs
src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
src/tools/clippy/clippy_lints/src/loops/needless_collect.rs
src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
src/tools/clippy/clippy_lints/src/loops/never_loop.rs
src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs
src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs
src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs
src/tools/clippy/clippy_lints/src/manual_bits.rs
src/tools/clippy/clippy_lints/src/manual_retain.rs
src/tools/clippy/clippy_lints/src/manual_string_new.rs
src/tools/clippy/clippy_lints/src/manual_strip.rs
src/tools/clippy/clippy_lints/src/map_unit_fn.rs
src/tools/clippy/clippy_lints/src/match_result_ok.rs
src/tools/clippy/clippy_lints/src/matches/manual_map.rs
src/tools/clippy/clippy_lints/src/matches/match_as_ref.rs
src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs
src/tools/clippy/clippy_lints/src/matches/needless_match.rs
src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
src/tools/clippy/clippy_lints/src/matches/single_match.rs
src/tools/clippy/clippy_lints/src/methods/bytecount.rs
src/tools/clippy/clippy_lints/src/methods/chars_cmp.rs
src/tools/clippy/clippy_lints/src/methods/chars_cmp_with_unwrap.rs
src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs
src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs
src/tools/clippy/clippy_lints/src/methods/collapsible_str_replace.rs
src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs
src/tools/clippy/clippy_lints/src/methods/extend_with_drain.rs
src/tools/clippy/clippy_lints/src/methods/filter_map.rs
src/tools/clippy/clippy_lints/src/methods/get_last_with_len.rs
src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs
src/tools/clippy/clippy_lints/src/methods/into_iter_on_ref.rs
src/tools/clippy/clippy_lints/src/methods/iter_skip_next.rs
src/tools/clippy/clippy_lints/src/methods/iter_with_drain.rs
src/tools/clippy/clippy_lints/src/methods/map_clone.rs
src/tools/clippy/clippy_lints/src/methods/mod.rs
src/tools/clippy/clippy_lints/src/methods/open_options.rs
src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
src/tools/clippy/clippy_lints/src/methods/range_zip_with_len.rs
src/tools/clippy/clippy_lints/src/methods/single_char_add_str.rs
src/tools/clippy/clippy_lints/src/methods/single_char_insert_string.rs
src/tools/clippy/clippy_lints/src/methods/single_char_pattern.rs
src/tools/clippy/clippy_lints/src/methods/single_char_push_string.rs
src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
src/tools/clippy/clippy_lints/src/methods/string_extend_chars.rs
src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs
src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs
src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs
src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
src/tools/clippy/clippy_lints/src/methods/utils.rs
src/tools/clippy/clippy_lints/src/minmax.rs
src/tools/clippy/clippy_lints/src/misc.rs
src/tools/clippy/clippy_lints/src/misc_early/redundant_pattern.rs
src/tools/clippy/clippy_lints/src/mut_reference.rs
src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs
src/tools/clippy/clippy_lints/src/needless_borrowed_ref.rs
src/tools/clippy/clippy_lints/src/needless_for_each.rs
src/tools/clippy/clippy_lints/src/needless_late_init.rs
src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs
src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs
src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs
src/tools/clippy/clippy_lints/src/operators/float_cmp.rs
src/tools/clippy/clippy_lints/src/operators/op_ref.rs
src/tools/clippy/clippy_lints/src/option_if_let_else.rs
src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
src/tools/clippy/clippy_lints/src/ptr.rs
src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs
src/tools/clippy/clippy_lints/src/question_mark.rs
src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs
src/tools/clippy/clippy_lints/src/ref_option_ref.rs
src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs
src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
src/tools/clippy/clippy_lints/src/strings.rs
src/tools/clippy/clippy_lints/src/strlen_on_c_strings.rs
src/tools/clippy/clippy_lints/src/to_digit_is_some.rs
src/tools/clippy/clippy_lints/src/trait_bounds.rs
src/tools/clippy/clippy_lints/src/uninit_vec.rs
src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs
src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs
src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
src/tools/clippy/clippy_lints/src/unused_io_amount.rs
src/tools/clippy/clippy_lints/src/unused_peekable.rs
src/tools/clippy/clippy_lints/src/unwrap.rs
src/tools/clippy/clippy_lints/src/unwrap_in_result.rs
src/tools/clippy/clippy_lints/src/useless_conversion.rs
src/tools/clippy/clippy_lints/src/utils/author.rs
src/tools/clippy/clippy_lints/src/utils/internal_lints.rs
src/tools/clippy/clippy_lints/src/vec_init_then_push.rs
src/tools/clippy/clippy_utils/src/check_proc_macro.rs
src/tools/clippy/clippy_utils/src/diagnostics.rs
src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
src/tools/clippy/clippy_utils/src/hir_utils.rs
src/tools/clippy/clippy_utils/src/lib.rs
src/tools/clippy/clippy_utils/src/ptr.rs
src/tools/clippy/clippy_utils/src/sugg.rs
src/tools/clippy/clippy_utils/src/visitors.rs
src/tools/clippy/tests/ui/author.stdout
src/tools/clippy/tests/ui/author/blocks.stdout
src/tools/clippy/tests/ui/author/loop.stdout
src/tools/clippy/tests/ui/author/matches.stdout
src/tools/clippy/tests/ui/author/struct.stdout
src/tools/error_index_generator/Cargo.toml
src/tools/error_index_generator/book_config.toml [new file with mode: 0644]
src/tools/error_index_generator/error-index.css [new file with mode: 0644]
src/tools/error_index_generator/error-index.js [new file with mode: 0644]
src/tools/error_index_generator/main.rs
src/tools/error_index_generator/redirect.js [new file with mode: 0644]
src/tools/lint-docs/src/groups.rs
src/tools/lld-wrapper/src/main.rs
src/tools/miri
src/tools/replace-version-placeholder/src/main.rs
src/tools/rustc-workspace-hack/Cargo.toml
src/tools/rustfmt/src/patterns.rs
src/tools/tidy/src/deps.rs
src/tools/unicode-table-generator/src/range_search.rs
src/tools/unicode-table-generator/src/raw_emitter.rs
triagebot.toml

index b16fb6341c2e50a2f37f04e563017a588365a4d7..37972532b361429f281f8d52f34ea4d1ca621540 100644 (file)
@@ -46,6 +46,7 @@ no_llvm_build
 /dist/
 /unicode-downloads
 /target
+/src/bootstrap/target
 /src/tools/x/target
 # Created by default with `src/ci/docker/run.sh`
 /obj/
index f83678f0ca67100de1f50a2e5387e0ae25d918be..68ea8b51c555c7e920f21cfddc989518b746ae65 100644 (file)
@@ -209,34 +209,13 @@ dependencies = [
  "typenum",
 ]
 
-[[package]]
-name = "block-buffer"
-version = "0.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
-dependencies = [
- "block-padding",
- "byte-tools",
- "byteorder",
- "generic-array 0.12.4",
-]
-
 [[package]]
 name = "block-buffer"
 version = "0.10.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324"
 dependencies = [
- "generic-array 0.14.4",
-]
-
-[[package]]
-name = "block-padding"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
-dependencies = [
- "byte-tools",
+ "generic-array",
 ]
 
 [[package]]
@@ -277,12 +256,6 @@ dependencies = [
  "toml",
 ]
 
-[[package]]
-name = "byte-tools"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
-
 [[package]]
 name = "bytecount"
 version = "0.6.2"
@@ -292,12 +265,6 @@ dependencies = [
  "packed_simd_2",
 ]
 
-[[package]]
-name = "byteorder"
-version = "1.3.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
-
 [[package]]
 name = "bytes"
 version = "1.0.1"
@@ -610,9 +577,9 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "3.2.5"
+version = "3.2.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d53da17d37dba964b9b3ecb5c5a1f193a2762c700e6829201e645b9381c99dc7"
+checksum = "23b71c3ce99b7611011217b366d923f1d0a7e07a92bb2dbf1e84508c673ca3bd"
 dependencies = [
  "atty",
  "bitflags",
@@ -636,9 +603,9 @@ dependencies = [
 
 [[package]]
 name = "clap_derive"
-version = "3.2.5"
+version = "3.2.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c11d40217d16aee8508cc8e5fde8b4ff24639758608e5374e731b53f85749fb9"
+checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65"
 dependencies = [
  "heck",
  "proc-macro-error",
@@ -771,9 +738,9 @@ dependencies = [
 
 [[package]]
 name = "combine"
-version = "4.6.3"
+version = "4.6.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50b727aacc797f9fc28e355d21f34709ac4fc9adecfe470ad07b8f4464f53062"
+checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4"
 dependencies = [
  "bytes",
  "memchr",
@@ -1011,7 +978,7 @@ version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a4600d695eb3f6ce1cd44e6e291adceb2cc3ab12f20a33777ecd0bf6eba34e06"
 dependencies = [
- "generic-array 0.14.4",
+ "generic-array",
 ]
 
 [[package]]
@@ -1036,16 +1003,6 @@ dependencies = [
  "quote",
 ]
 
-[[package]]
-name = "ctor"
-version = "0.1.22"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c"
-dependencies = [
- "quote",
- "syn",
-]
-
 [[package]]
 name = "curl"
 version = "0.4.43"
@@ -1106,22 +1063,13 @@ version = "2.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
 
-[[package]]
-name = "digest"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
-dependencies = [
- "generic-array 0.12.4",
-]
-
 [[package]]
 name = "digest"
 version = "0.10.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8cb780dce4f9a8f5c087362b3a4595936b2019e7c8b30f2c3e9a7e94e6ae9837"
 dependencies = [
- "block-buffer 0.10.2",
+ "block-buffer",
  "crypto-common",
 ]
 
@@ -1269,7 +1217,7 @@ dependencies = [
 name = "error_index_generator"
 version = "0.0.0"
 dependencies = [
- "rustdoc",
+ "mdbook",
 ]
 
 [[package]]
@@ -1300,12 +1248,6 @@ dependencies = [
  "once_cell",
 ]
 
-[[package]]
-name = "fake-simd"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
-
 [[package]]
 name = "fallible-iterator"
 version = "0.2.0"
@@ -1539,15 +1481,6 @@ dependencies = [
  "termcolor",
 ]
 
-[[package]]
-name = "generic-array"
-version = "0.12.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd"
-dependencies = [
- "typenum",
-]
-
 [[package]]
 name = "generic-array"
 version = "0.14.4"
@@ -1682,16 +1615,16 @@ dependencies = [
 
 [[package]]
 name = "handlebars"
-version = "4.1.0"
+version = "4.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72a0ffab8c36d0436114310c7e10b59b3307e650ddfabf6d006028e29a70c6e6"
+checksum = "360d9740069b2f6cbb63ce2dbaa71a20d3185350cbb990d7bebeb9318415eb17"
 dependencies = [
  "log",
  "pest",
  "pest_derive",
- "quick-error 2.0.0",
  "serde",
  "serde_json",
+ "thiserror",
 ]
 
 [[package]]
@@ -1781,7 +1714,7 @@ version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
 dependencies = [
- "quick-error 1.2.3",
+ "quick-error",
 ]
 
 [[package]]
@@ -1827,13 +1760,13 @@ dependencies = [
 
 [[package]]
 name = "im-rc"
-version = "15.0.0"
+version = "15.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ca8957e71f04a205cb162508f9326aea04676c8dfd0711220190d6b83664f3f"
+checksum = "af1955a75fa080c677d3972822ec4bad316169ab1cfc6c257a942c2265dbe5fe"
 dependencies = [
  "bitmaps",
- "rand_core 0.5.1",
- "rand_xoshiro 0.4.0",
+ "rand_core 0.6.2",
+ "rand_xoshiro",
  "sized-chunks",
  "typenum",
  "version_check",
@@ -2000,6 +1933,25 @@ dependencies = [
  "rustc-std-workspace-core",
 ]
 
+[[package]]
+name = "libffi"
+version = "3.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e454b3efb16fba3b17810ae5e41df02b649e564ab3c5a34b3b93ed07ad287e6"
+dependencies = [
+ "libc",
+ "libffi-sys",
+]
+
+[[package]]
+name = "libffi-sys"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab4106b7f09d7b87d021334d5618fac1dfcfb824d4c5fe111ff0074dfd242e15"
+dependencies = [
+ "cc",
+]
+
 [[package]]
 name = "libgit2-sys"
 version = "0.14.0+1.5.0"
@@ -2170,7 +2122,7 @@ version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e6a38fc55c8bbc10058782919516f88826e70320db6d206aebc49611d24216ae"
 dependencies = [
- "digest 0.10.2",
+ "digest",
 ]
 
 [[package]]
@@ -2294,6 +2246,8 @@ dependencies = [
  "getrandom 0.2.0",
  "lazy_static",
  "libc",
+ "libffi",
+ "libloading",
  "log",
  "measureme",
  "rand 0.8.5",
@@ -2396,12 +2350,6 @@ version = "1.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225"
 
-[[package]]
-name = "opaque-debug"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
-
 [[package]]
 name = "opener"
 version = "0.5.0"
@@ -2472,15 +2420,6 @@ version = "6.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64"
 
-[[package]]
-name = "output_vt100"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66"
-dependencies = [
- "winapi",
-]
-
 [[package]]
 name = "owo-colors"
 version = "3.4.0"
@@ -2591,18 +2530,19 @@ dependencies = [
 
 [[package]]
 name = "pest"
-version = "2.1.3"
+version = "2.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
+checksum = "4b0560d531d1febc25a3c9398a62a71256c0178f2e3443baedd9ad4bb8c9deb4"
 dependencies = [
+ "thiserror",
  "ucd-trie",
 ]
 
 [[package]]
 name = "pest_derive"
-version = "2.1.0"
+version = "2.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0"
+checksum = "905708f7f674518498c1f8d644481440f476d39ca6ecae83319bba7c6c12da91"
 dependencies = [
  "pest",
  "pest_generator",
@@ -2610,9 +2550,9 @@ dependencies = [
 
 [[package]]
 name = "pest_generator"
-version = "2.1.3"
+version = "2.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55"
+checksum = "5803d8284a629cc999094ecd630f55e91b561a1d1ba75e233b00ae13b91a69ad"
 dependencies = [
  "pest",
  "pest_meta",
@@ -2623,13 +2563,13 @@ dependencies = [
 
 [[package]]
 name = "pest_meta"
-version = "2.1.3"
+version = "2.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d"
+checksum = "1538eb784f07615c6d9a8ab061089c6c54a344c5b4301db51990ca1c241e8c04"
 dependencies = [
- "maplit",
+ "once_cell",
  "pest",
- "sha-1 0.8.2",
+ "sha-1",
 ]
 
 [[package]]
@@ -2721,18 +2661,6 @@ version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
 
-[[package]]
-name = "pretty_assertions"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c89f989ac94207d048d92db058e4f6ec7342b0971fc58d1271ca148b799b3563"
-dependencies = [
- "ansi_term",
- "ctor",
- "diff",
- "output_vt100",
-]
-
 [[package]]
 name = "pretty_env_logger"
 version = "0.4.0"
@@ -2831,12 +2759,6 @@ version = "1.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
 
-[[package]]
-name = "quick-error"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ac73b1112776fc109b2e61909bc46c7e1bf0d7f690ffb1676553acce16d5cda"
-
 [[package]]
 name = "quine-mc_cluskey"
 version = "0.2.4"
@@ -2932,15 +2854,6 @@ dependencies = [
  "rand_core 0.5.1",
 ]
 
-[[package]]
-name = "rand_xoshiro"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9fcdd2e881d02f1d9390ae47ad8e5696a9e4be7b547a1da2afbc61973217004"
-dependencies = [
- "rand_core 0.5.1",
-]
-
 [[package]]
 name = "rand_xoshiro"
 version = "0.6.0"
@@ -3173,7 +3086,6 @@ dependencies = [
  "bstr",
  "clap",
  "libz-sys",
- "memchr",
  "regex",
  "serde_json",
  "syn",
@@ -3519,6 +3431,7 @@ dependencies = [
  "rustc_macros",
  "rustc_serialize",
  "rustc_span",
+ "rustc_target",
  "serde",
  "serde_json",
  "termcolor",
@@ -3812,7 +3725,7 @@ dependencies = [
  "gsgdt",
  "polonius-engine",
  "rand 0.8.5",
- "rand_xoshiro 0.6.0",
+ "rand_xoshiro",
  "rustc-rayon",
  "rustc-rayon-core",
  "rustc_apfloat",
@@ -4151,7 +4064,7 @@ dependencies = [
  "rustc_macros",
  "rustc_serialize",
  "scoped-tls",
- "sha-1 0.10.0",
+ "sha-1",
  "sha2",
  "tracing",
  "unicode-width",
@@ -4243,6 +4156,7 @@ version = "0.1.0"
 dependencies = [
  "itertools",
  "rustc_data_structures",
+ "rustc_hir",
  "rustc_infer",
  "rustc_macros",
  "rustc_middle",
@@ -4539,18 +4453,6 @@ dependencies = [
  "serde",
 ]
 
-[[package]]
-name = "sha-1"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
-dependencies = [
- "block-buffer 0.7.3",
- "digest 0.8.1",
- "fake-simd",
- "opaque-debug",
-]
-
 [[package]]
 name = "sha-1"
 version = "0.10.0"
@@ -4559,7 +4461,7 @@ checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f"
 dependencies = [
  "cfg-if 1.0.0",
  "cpufeatures",
- "digest 0.10.2",
+ "digest",
 ]
 
 [[package]]
@@ -4570,7 +4472,7 @@ checksum = "99c3bd8169c58782adad9290a9af5939994036b76187f7b4f0e6de91dbbfc0ec"
 dependencies = [
  "cfg-if 1.0.0",
  "cpufeatures",
- "digest 0.10.2",
+ "digest",
 ]
 
 [[package]]
@@ -4901,18 +4803,18 @@ checksum = "104c2cb3180b6fb6d5b2278768e9b88b578d32ba751ea6e8d026688a40d7ed87"
 
 [[package]]
 name = "thiserror"
-version = "1.0.30"
+version = "1.0.33"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
+checksum = "3d0a539a918745651435ac7db7a18761589a94cd7e94cd56999f828bf73c8a57"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.30"
+version = "1.0.33"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
+checksum = "c251e90f708e16c49a16f4917dc2131e75222b72edfa9cb7f7c58ae56aae0c09"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -5135,14 +5037,16 @@ checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
 
 [[package]]
 name = "ui_test"
-version = "0.1.0"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d1f546a5883ae78da735bba529ec1116661e2f73582f23920d994dc97da3a22"
 dependencies = [
  "cargo_metadata 0.15.0",
  "color-eyre",
  "colored",
  "crossbeam",
+ "diff",
  "lazy_static",
- "pretty_assertions",
  "regex",
  "rustc_version",
  "serde",
index 3af6dee9e43f7fb888e6d5f5a95c1babc17b33a4..f25fdc942b0850db6590061f0956ba536b21302b 100644 (file)
@@ -594,7 +594,7 @@ pub fn to_ty(&self) -> Option<P<Ty>> {
             // In a type expression `_` is an inference variable.
             PatKind::Wild => TyKind::Infer,
             // An IDENT pattern with no binding mode would be valid as path to a type. E.g. `u32`.
-            PatKind::Ident(BindingMode::ByValue(Mutability::Not), ident, None) => {
+            PatKind::Ident(BindingAnnotation::NONE, ident, None) => {
                 TyKind::Path(None, Path::from_ident(*ident))
             }
             PatKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),
@@ -681,10 +681,43 @@ pub struct PatField {
     pub is_placeholder: bool,
 }
 
-#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy)]
-pub enum BindingMode {
-    ByRef(Mutability),
-    ByValue(Mutability),
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+#[derive(Encodable, Decodable, HashStable_Generic)]
+pub enum ByRef {
+    Yes,
+    No,
+}
+
+impl From<bool> for ByRef {
+    fn from(b: bool) -> ByRef {
+        match b {
+            false => ByRef::No,
+            true => ByRef::Yes,
+        }
+    }
+}
+
+/// Explicit binding annotations given in the HIR for a binding. Note
+/// that this is not the final binding *mode* that we infer after type
+/// inference.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+#[derive(Encodable, Decodable, HashStable_Generic)]
+pub struct BindingAnnotation(pub ByRef, pub Mutability);
+
+impl BindingAnnotation {
+    pub const NONE: Self = Self(ByRef::No, Mutability::Not);
+    pub const REF: Self = Self(ByRef::Yes, Mutability::Not);
+    pub const MUT: Self = Self(ByRef::No, Mutability::Mut);
+    pub const REF_MUT: Self = Self(ByRef::Yes, Mutability::Mut);
+
+    pub fn prefix_str(self) -> &'static str {
+        match self {
+            Self::NONE => "",
+            Self::REF => "ref ",
+            Self::MUT => "mut ",
+            Self::REF_MUT => "ref mut ",
+        }
+    }
 }
 
 #[derive(Clone, Encodable, Decodable, Debug)]
@@ -713,7 +746,7 @@ pub enum PatKind {
     /// or a unit struct/variant pattern, or a const pattern (in the last two cases the third
     /// field must be `None`). Disambiguation cannot be done with parser alone, so it happens
     /// during name resolution.
-    Ident(BindingMode, Ident, Option<P<Pat>>),
+    Ident(BindingAnnotation, Ident, Option<P<Pat>>),
 
     /// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`).
     /// The `bool` is `true` in the presence of a `..`.
@@ -2228,7 +2261,7 @@ pub enum SelfKind {
 impl Param {
     /// Attempts to cast parameter to `ExplicitSelf`.
     pub fn to_self(&self) -> Option<ExplicitSelf> {
-        if let PatKind::Ident(BindingMode::ByValue(mutbl), ident, _) = self.pat.kind {
+        if let PatKind::Ident(BindingAnnotation(ByRef::No, mutbl), ident, _) = self.pat.kind {
             if ident.name == kw::SelfLower {
                 return match self.ty.kind {
                     TyKind::ImplicitSelf => Some(respan(self.pat.span, SelfKind::Value(mutbl))),
@@ -2258,11 +2291,24 @@ pub fn is_self(&self) -> bool {
     pub fn from_self(attrs: AttrVec, eself: ExplicitSelf, eself_ident: Ident) -> Param {
         let span = eself.span.to(eself_ident.span);
         let infer_ty = P(Ty { id: DUMMY_NODE_ID, kind: TyKind::ImplicitSelf, span, tokens: None });
-        let param = |mutbl, ty| Param {
+        let (mutbl, ty) = match eself.node {
+            SelfKind::Explicit(ty, mutbl) => (mutbl, ty),
+            SelfKind::Value(mutbl) => (mutbl, infer_ty),
+            SelfKind::Region(lt, mutbl) => (
+                Mutability::Not,
+                P(Ty {
+                    id: DUMMY_NODE_ID,
+                    kind: TyKind::Rptr(lt, MutTy { ty: infer_ty, mutbl }),
+                    span,
+                    tokens: None,
+                }),
+            ),
+        };
+        Param {
             attrs,
             pat: P(Pat {
                 id: DUMMY_NODE_ID,
-                kind: PatKind::Ident(BindingMode::ByValue(mutbl), eself_ident, None),
+                kind: PatKind::Ident(BindingAnnotation(ByRef::No, mutbl), eself_ident, None),
                 span,
                 tokens: None,
             }),
@@ -2270,19 +2316,6 @@ pub fn from_self(attrs: AttrVec, eself: ExplicitSelf, eself_ident: Ident) -> Par
             ty,
             id: DUMMY_NODE_ID,
             is_placeholder: false,
-        };
-        match eself.node {
-            SelfKind::Explicit(ty, mutbl) => param(mutbl, ty),
-            SelfKind::Value(mutbl) => param(mutbl, infer_ty),
-            SelfKind::Region(lt, mutbl) => param(
-                Mutability::Not,
-                P(Ty {
-                    id: DUMMY_NODE_ID,
-                    kind: TyKind::Rptr(lt, MutTy { ty: infer_ty, mutbl }),
-                    span,
-                    tokens: None,
-                }),
-            ),
         }
     }
 }
@@ -3045,6 +3078,7 @@ mod size_asserts {
     static_assert_size!(Fn, 192);
     static_assert_size!(ForeignItem, 96);
     static_assert_size!(ForeignItemKind, 24);
+    static_assert_size!(GenericArg, 24);
     static_assert_size!(GenericBound, 88);
     static_assert_size!(Generics, 72);
     static_assert_size!(Impl, 200);
@@ -3052,6 +3086,8 @@ mod size_asserts {
     static_assert_size!(ItemKind, 112);
     static_assert_size!(Lit, 48);
     static_assert_size!(LitKind, 24);
+    static_assert_size!(Local, 72);
+    static_assert_size!(Param, 40);
     static_assert_size!(Pat, 120);
     static_assert_size!(PatKind, 96);
     static_assert_size!(Path, 40);
index 27061f300a2b20191e5906ed47ac7a683cfd8aa8..e5435e3a3d4fad4037927e7eaae246f1d8652f7e 100644 (file)
@@ -26,6 +26,9 @@
 #[macro_use]
 extern crate rustc_macros;
 
+#[macro_use]
+extern crate tracing;
+
 pub mod util {
     pub mod classify;
     pub mod comments;
index 69a78d165ef5895ad654b51103bd6efa21f5d016..6a1578498e6894468552c4729ecb0cf2c4b9531e 100644 (file)
@@ -9,7 +9,6 @@
 use rustc_span::Span;
 
 use std::ascii;
-use tracing::debug;
 
 pub enum LitError {
     NotLiteral,
index 0dba9da63da2a03d0d18c3ccfe2697d5b672252e..b0e9fe0469c41baab379f1b599301efda043f76f 100644 (file)
@@ -155,26 +155,26 @@ pub(crate) fn lower_inline_asm(
                 let op = match *op {
                     InlineAsmOperand::In { reg, ref expr } => hir::InlineAsmOperand::In {
                         reg: lower_reg(reg),
-                        expr: self.lower_expr_mut(expr),
+                        expr: self.lower_expr(expr),
                     },
                     InlineAsmOperand::Out { reg, late, ref expr } => hir::InlineAsmOperand::Out {
                         reg: lower_reg(reg),
                         late,
-                        expr: expr.as_ref().map(|expr| self.lower_expr_mut(expr)),
+                        expr: expr.as_ref().map(|expr| self.lower_expr(expr)),
                     },
                     InlineAsmOperand::InOut { reg, late, ref expr } => {
                         hir::InlineAsmOperand::InOut {
                             reg: lower_reg(reg),
                             late,
-                            expr: self.lower_expr_mut(expr),
+                            expr: self.lower_expr(expr),
                         }
                     }
                     InlineAsmOperand::SplitInOut { reg, late, ref in_expr, ref out_expr } => {
                         hir::InlineAsmOperand::SplitInOut {
                             reg: lower_reg(reg),
                             late,
-                            in_expr: self.lower_expr_mut(in_expr),
-                            out_expr: out_expr.as_ref().map(|expr| self.lower_expr_mut(expr)),
+                            in_expr: self.lower_expr(in_expr),
+                            out_expr: out_expr.as_ref().map(|expr| self.lower_expr(expr)),
                         }
                     }
                     InlineAsmOperand::Const { ref anon_const } => {
index 7df3520422c18b38cb14cb1ba979eb0024d487c3..77babeb5d39d186099b6b9f2505b6522c0d9a928 100644 (file)
@@ -68,10 +68,10 @@ pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
                         ParenthesizedGenericArgs::Err,
                         ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                     ));
-                    let args = self.arena.alloc_from_iter(
-                        [&*receiver].into_iter().chain(args.iter()).map(|x| self.lower_expr_mut(x)),
-                    );
-                    hir::ExprKind::MethodCall(hir_seg, args, self.lower_span(span))
+                    let receiver = self.lower_expr(receiver);
+                    let args =
+                        self.arena.alloc_from_iter(args.iter().map(|x| self.lower_expr_mut(x)));
+                    hir::ExprKind::MethodCall(hir_seg, receiver, args, self.lower_span(span))
                 }
                 ExprKind::Binary(binop, ref lhs, ref rhs) => {
                     let binop = self.lower_binop(binop);
@@ -577,7 +577,7 @@ pub(super) fn make_async_expr(
         let (pat, task_context_hid) = self.pat_ident_binding_mode(
             span,
             Ident::with_dummy_span(sym::_task_context),
-            hir::BindingAnnotation::Mutable,
+            hir::BindingAnnotation::MUT,
         );
         let param = hir::Param {
             hir_id: self.next_id(),
@@ -671,7 +671,7 @@ fn lower_expr_await(&mut self, dot_await_span: Span, expr: &Expr) -> hir::ExprKi
         // this name to identify what is being awaited by a suspended async functions.
         let awaitee_ident = Ident::with_dummy_span(sym::__awaitee);
         let (awaitee_pat, awaitee_pat_hid) =
-            self.pat_ident_binding_mode(span, awaitee_ident, hir::BindingAnnotation::Mutable);
+            self.pat_ident_binding_mode(span, awaitee_ident, hir::BindingAnnotation::MUT);
 
         let task_context_ident = Ident::with_dummy_span(sym::_task_context);
 
@@ -1433,7 +1433,7 @@ fn lower_expr_for(
         // `mut iter`
         let iter = Ident::with_dummy_span(sym::iter);
         let (iter_pat, iter_pat_nid) =
-            self.pat_ident_binding_mode(head_span, iter, hir::BindingAnnotation::Mutable);
+            self.pat_ident_binding_mode(head_span, iter, hir::BindingAnnotation::MUT);
 
         // `match Iterator::next(&mut iter) { ... }`
         let match_expr = {
@@ -1776,12 +1776,14 @@ fn expr_ident_with_attrs(
         binding: hir::HirId,
         attrs: AttrVec,
     ) -> hir::Expr<'hir> {
+        let hir_id = self.next_id();
+        let res = Res::Local(binding);
         let expr_path = hir::ExprKind::Path(hir::QPath::Resolved(
             None,
             self.arena.alloc(hir::Path {
                 span: self.lower_span(span),
-                res: Res::Local(binding),
-                segments: arena_vec![self; hir::PathSegment::from_ident(ident)],
+                res,
+                segments: arena_vec![self; hir::PathSegment::new(ident, hir_id, res)],
             }),
         ));
 
index 2b7431f0990570a004902099db789a36f65cd989..61470d93bdb2c3bb3411c5b4a78c54a346bcb4ea 100644 (file)
@@ -11,8 +11,6 @@
 use rustc_span::source_map::SourceMap;
 use rustc_span::{Span, DUMMY_SP};
 
-use tracing::debug;
-
 /// A visitor that walks over the HIR and collects `Node`s into a HIR map.
 pub(super) struct NodeCollector<'a, 'hir> {
     /// Source map
@@ -31,7 +29,7 @@ pub(super) struct NodeCollector<'a, 'hir> {
     definitions: &'a definitions::Definitions,
 }
 
-#[tracing::instrument(level = "debug", skip(sess, definitions, bodies))]
+#[instrument(level = "debug", skip(sess, definitions, bodies))]
 pub(super) fn index_hir<'hir>(
     sess: &Session,
     definitions: &definitions::Definitions,
@@ -67,7 +65,7 @@ pub(super) fn index_hir<'hir>(
 }
 
 impl<'a, 'hir> NodeCollector<'a, 'hir> {
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn insert(&mut self, span: Span, hir_id: HirId, node: Node<'hir>) {
         debug_assert_eq!(self.owner, hir_id.owner);
         debug_assert_ne!(hir_id.local_id.as_u32(), 0);
@@ -142,7 +140,7 @@ fn visit_param(&mut self, param: &'hir Param<'hir>) {
         });
     }
 
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn visit_item(&mut self, i: &'hir Item<'hir>) {
         debug_assert_eq!(i.def_id, self.owner);
         self.with_parent(i.hir_id(), |this| {
@@ -156,7 +154,7 @@ fn visit_item(&mut self, i: &'hir Item<'hir>) {
         });
     }
 
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn visit_foreign_item(&mut self, fi: &'hir ForeignItem<'hir>) {
         debug_assert_eq!(fi.def_id, self.owner);
         self.with_parent(fi.hir_id(), |this| {
@@ -175,7 +173,7 @@ fn visit_const_param_default(&mut self, param: HirId, ct: &'hir AnonConst) {
         })
     }
 
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn visit_trait_item(&mut self, ti: &'hir TraitItem<'hir>) {
         debug_assert_eq!(ti.def_id, self.owner);
         self.with_parent(ti.hir_id(), |this| {
@@ -183,7 +181,7 @@ fn visit_trait_item(&mut self, ti: &'hir TraitItem<'hir>) {
         });
     }
 
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn visit_impl_item(&mut self, ii: &'hir ImplItem<'hir>) {
         debug_assert_eq!(ii.def_id, self.owner);
         self.with_parent(ii.hir_id(), |this| {
@@ -248,9 +246,7 @@ fn visit_stmt(&mut self, stmt: &'hir Stmt<'hir>) {
     }
 
     fn visit_path_segment(&mut self, path_span: Span, path_segment: &'hir PathSegment<'hir>) {
-        if let Some(hir_id) = path_segment.hir_id {
-            self.insert(path_span, hir_id, Node::PathSegment(path_segment));
-        }
+        self.insert(path_span, path_segment.hir_id, Node::PathSegment(path_segment));
         intravisit::walk_path_segment(self, path_span, path_segment);
     }
 
index fd338ffc0c5e8b64c9ca0469cc25cb766070e671..76f63d1d78a90c284aa3df5ff290ee356f0df509 100644 (file)
@@ -85,6 +85,7 @@ fn with_lctx(
             allow_try_trait: Some([sym::try_trait_v2, sym::yeet_desugar_details][..].into()),
             allow_gen_future: Some([sym::gen_future][..].into()),
             allow_into_future: Some([sym::into_future][..].into()),
+            generics_def_id_map: Default::default(),
         };
         lctx.with_hir_id_owner(owner, |lctx| f(lctx));
 
@@ -120,7 +121,7 @@ fn lower_crate(&mut self, c: &Crate) {
         self.with_lctx(CRATE_NODE_ID, |lctx| {
             let module = lctx.lower_mod(&c.items, &c.spans);
             lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs);
-            hir::OwnerNode::Crate(lctx.arena.alloc(module))
+            hir::OwnerNode::Crate(module)
         })
     }
 
@@ -158,14 +159,18 @@ fn lower_foreign_item(&mut self, item: &ForeignItem) {
 }
 
 impl<'hir> LoweringContext<'_, 'hir> {
-    pub(super) fn lower_mod(&mut self, items: &[P<Item>], spans: &ModSpans) -> hir::Mod<'hir> {
-        hir::Mod {
+    pub(super) fn lower_mod(
+        &mut self,
+        items: &[P<Item>],
+        spans: &ModSpans,
+    ) -> &'hir hir::Mod<'hir> {
+        self.arena.alloc(hir::Mod {
             spans: hir::ModSpans {
                 inner_span: self.lower_span(spans.inner_span),
                 inject_use_span: self.lower_span(spans.inject_use_span),
             },
             item_ids: self.arena.alloc_from_iter(items.iter().flat_map(|x| self.lower_item_ref(x))),
-        }
+        })
     }
 
     pub(super) fn lower_item_ref(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> {
@@ -947,7 +952,11 @@ fn record_body(
         params: &'hir [hir::Param<'hir>],
         value: hir::Expr<'hir>,
     ) -> hir::BodyId {
-        let body = hir::Body { generator_kind: self.generator_kind, params, value };
+        let body = hir::Body {
+            generator_kind: self.generator_kind,
+            params,
+            value: self.arena.alloc(value),
+        };
         let id = body.id();
         debug_assert_eq!(id.hir_id.owner, self.current_hir_id_owner);
         self.bodies.push((id.hir_id.local_id, self.arena.alloc(body)));
@@ -1074,12 +1083,9 @@ fn lower_maybe_async_body(
                 // Check if this is a binding pattern, if so, we can optimize and avoid adding a
                 // `let <pat> = __argN;` statement. In this case, we do not rename the parameter.
                 let (ident, is_simple_parameter) = match parameter.pat.kind {
-                    hir::PatKind::Binding(
-                        hir::BindingAnnotation::Unannotated | hir::BindingAnnotation::Mutable,
-                        _,
-                        ident,
-                        _,
-                    ) => (ident, true),
+                    hir::PatKind::Binding(hir::BindingAnnotation(ByRef::No, _), _, ident, _) => {
+                        (ident, true)
+                    }
                     // For `ref mut` or wildcard arguments, we can't reuse the binding, but
                     // we can keep the same name for the parameter.
                     // This lets rustdoc render it correctly in documentation.
@@ -1144,7 +1150,7 @@ fn lower_maybe_async_body(
                     let (move_pat, move_id) = this.pat_ident_binding_mode(
                         desugared_span,
                         ident,
-                        hir::BindingAnnotation::Mutable,
+                        hir::BindingAnnotation::MUT,
                     );
                     let move_expr = this.expr_ident(desugared_span, ident, new_parameter_id);
                     let move_stmt = this.stmt_let_pat(
@@ -1431,10 +1437,14 @@ pub(super) fn lower_generic_bound_predicate(
             GenericParamKind::Const { .. } => None,
             GenericParamKind::Type { .. } => {
                 let def_id = self.local_def_id(id).to_def_id();
+                let hir_id = self.next_id();
+                let res = Res::Def(DefKind::TyParam, def_id);
                 let ty_path = self.arena.alloc(hir::Path {
                     span: param_span,
-                    res: Res::Def(DefKind::TyParam, def_id),
-                    segments: self.arena.alloc_from_iter([hir::PathSegment::from_ident(ident)]),
+                    res,
+                    segments: self
+                        .arena
+                        .alloc_from_iter([hir::PathSegment::new(ident, hir_id, res)]),
                 });
                 let ty_id = self.next_id();
                 let bounded_ty =
index a5957e2df2e5f56bdbaa89d4d0504ba1410ad409..3a94c7a91b23f7adf1c60e43ffd678decd950be6 100644 (file)
@@ -132,6 +132,12 @@ struct LoweringContext<'a, 'hir> {
     allow_try_trait: Option<Lrc<[Symbol]>>,
     allow_gen_future: Option<Lrc<[Symbol]>>,
     allow_into_future: Option<Lrc<[Symbol]>>,
+
+    /// Mapping from generics `def_id`s to TAIT generics `def_id`s.
+    /// For each captured lifetime (e.g., 'a), we create a new lifetime parameter that is a generic
+    /// defined on the TAIT, so we have type Foo<'a1> = ... and we establish a mapping in this
+    /// field from the original parameter 'a to the new parameter 'a1.
+    generics_def_id_map: Vec<FxHashMap<LocalDefId, LocalDefId>>,
 }
 
 trait ResolverAstLoweringExt {
@@ -142,12 +148,6 @@ trait ResolverAstLoweringExt {
     fn get_lifetime_res(&self, id: NodeId) -> Option<LifetimeRes>;
     fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)>;
     fn decl_macro_kind(&self, def_id: LocalDefId) -> MacroKind;
-    /// Record the map from `from` local def id to `to` local def id, on `generics_def_id_map`
-    /// field.
-    fn record_def_id_remap(&mut self, from: LocalDefId, to: LocalDefId);
-    /// Get the previously recorded `to` local def id given the `from` local def id, obtained using
-    /// `generics_def_id_map` field.
-    fn get_remapped_def_id(&self, local_def_id: LocalDefId) -> LocalDefId;
 }
 
 impl ResolverAstLoweringExt for ResolverAstLowering {
@@ -215,41 +215,6 @@ fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, Life
     fn decl_macro_kind(&self, def_id: LocalDefId) -> MacroKind {
         self.builtin_macro_kinds.get(&def_id).copied().unwrap_or(MacroKind::Bang)
     }
-
-    /// Push a remapping into the top-most map.
-    /// Panics if no map has been pushed.
-    /// Remapping is used when creating lowering `-> impl Trait` return
-    /// types to create the resulting opaque type.
-    #[tracing::instrument(level = "debug", skip(self))]
-    fn record_def_id_remap(&mut self, from: LocalDefId, to: LocalDefId) {
-        self.generics_def_id_map.last_mut().expect("no map pushed").insert(from, to);
-    }
-
-    fn get_remapped_def_id(&self, mut local_def_id: LocalDefId) -> LocalDefId {
-        // `generics_def_id_map` is a stack of mappings. As we go deeper in impl traits nesting we
-        // push new mappings so we need to try first the latest mappings, hence `iter().rev()`.
-        //
-        // Consider:
-        //
-        // `fn test<'a, 'b>() -> impl Trait<&'a u8, Ty = impl Sized + 'b> {}`
-        //
-        // We would end with a generics_def_id_map like:
-        //
-        // `[[fn#'b -> impl_trait#'b], [fn#'b -> impl_sized#'b]]`
-        //
-        // for the opaque type generated on `impl Sized + 'b`, We want the result to be:
-        // impl_sized#'b, so iterating forward is the wrong thing to do.
-        for map in self.generics_def_id_map.iter().rev() {
-            if let Some(r) = map.get(&local_def_id) {
-                debug!("def_id_remapper: remapping from `{local_def_id:?}` to `{r:?}`");
-                local_def_id = *r;
-            } else {
-                debug!("def_id_remapper: no remapping for `{local_def_id:?}` found in map");
-            }
-        }
-
-        local_def_id
-    }
 }
 
 /// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree,
@@ -522,13 +487,41 @@ fn opt_local_def_id(&self, node: NodeId) -> Option<LocalDefId> {
         self.resolver
             .node_id_to_def_id
             .get(&node)
-            .map(|local_def_id| self.resolver.get_remapped_def_id(*local_def_id))
+            .map(|local_def_id| self.get_remapped_def_id(*local_def_id))
     }
 
     fn local_def_id(&self, node: NodeId) -> LocalDefId {
         self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{:?}`", node))
     }
 
+    /// Get the previously recorded `to` local def id given the `from` local def id, obtained using
+    /// `generics_def_id_map` field.
+    fn get_remapped_def_id(&self, mut local_def_id: LocalDefId) -> LocalDefId {
+        // `generics_def_id_map` is a stack of mappings. As we go deeper in impl traits nesting we
+        // push new mappings so we need to try first the latest mappings, hence `iter().rev()`.
+        //
+        // Consider:
+        //
+        // `fn test<'a, 'b>() -> impl Trait<&'a u8, Ty = impl Sized + 'b> {}`
+        //
+        // We would end with a generics_def_id_map like:
+        //
+        // `[[fn#'b -> impl_trait#'b], [fn#'b -> impl_sized#'b]]`
+        //
+        // for the opaque type generated on `impl Sized + 'b`, We want the result to be:
+        // impl_sized#'b, so iterating forward is the wrong thing to do.
+        for map in self.generics_def_id_map.iter().rev() {
+            if let Some(r) = map.get(&local_def_id) {
+                debug!("def_id_remapper: remapping from `{local_def_id:?}` to `{r:?}`");
+                local_def_id = *r;
+            } else {
+                debug!("def_id_remapper: no remapping for `{local_def_id:?}` found in map");
+            }
+        }
+
+        local_def_id
+    }
+
     /// Freshen the `LoweringContext` and ready it to lower a nested item.
     /// The lowered item is registered into `self.children`.
     ///
@@ -597,9 +590,9 @@ fn with_remapping<R>(
         remap: FxHashMap<LocalDefId, LocalDefId>,
         f: impl FnOnce(&mut Self) -> R,
     ) -> R {
-        self.resolver.generics_def_id_map.push(remap);
+        self.generics_def_id_map.push(remap);
         let res = f(self);
-        self.resolver.generics_def_id_map.pop();
+        self.generics_def_id_map.pop();
         res
     }
 
@@ -771,7 +764,7 @@ fn lower_ident(&self, ident: Ident) -> Ident {
     }
 
     /// Converts a lifetime into a new generic parameter.
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn lifetime_res_to_generic_param(
         &mut self,
         ident: Ident,
@@ -815,7 +808,7 @@ fn lifetime_res_to_generic_param(
     /// name resolver owing to lifetime elision; this also populates the resolver's node-id->def-id
     /// map, so that later calls to `opt_node_id_to_def_id` that refer to these extra lifetime
     /// parameters will be successful.
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     #[inline]
     fn lower_lifetime_binder(
         &mut self,
@@ -1155,7 +1148,7 @@ fn lower_generic_arg(
                     }
                     _ => {}
                 }
-                GenericArg::Type(self.lower_ty_direct(&ty, itctx))
+                GenericArg::Type(self.lower_ty(&ty, itctx))
             }
             ast::GenericArg::Const(ct) => GenericArg::Const(ConstArg {
                 value: self.lower_anon_const(&ct),
@@ -1260,14 +1253,17 @@ fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir>
                 return self.lower_path_ty(t, qself, path, ParamMode::Explicit, itctx);
             }
             TyKind::ImplicitSelf => {
+                let hir_id = self.lower_node_id(t.id);
                 let res = self.expect_full_res(t.id);
                 let res = self.lower_res(res);
                 hir::TyKind::Path(hir::QPath::Resolved(
                     None,
                     self.arena.alloc(hir::Path {
                         res,
-                        segments: arena_vec![self; hir::PathSegment::from_ident(
-                            Ident::with_dummy_span(kw::SelfUpper)
+                        segments: arena_vec![self; hir::PathSegment::new(
+                            Ident::with_dummy_span(kw::SelfUpper),
+                            hir_id,
+                            res
                         )],
                         span: self.lower_span(t.span),
                     }),
@@ -1385,7 +1381,7 @@ fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir>
     /// added explicitly in the HIR). But this includes all the lifetimes, and we only want to
     /// capture the lifetimes that are referenced in the bounds. Therefore, we add *extra* lifetime parameters
     /// for the lifetimes that get captured (`'x`, in our example above) and reference those.
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn lower_opaque_impl_trait(
         &mut self,
         span: Span,
@@ -1621,7 +1617,7 @@ fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Ident] {
     // `make_ret_async`: if `Some`, converts `-> T` into `-> impl Future<Output = T>` in the
     //      return type. This is used for `async fn` declarations. The `NodeId` is the ID of the
     //      return type `impl Trait` item.
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn lower_fn_decl(
         &mut self,
         decl: &FnDecl,
@@ -1696,10 +1692,9 @@ fn lower_fn_decl(
             output,
             c_variadic,
             implicit_self: decl.inputs.get(0).map_or(hir::ImplicitSelfKind::None, |arg| {
-                use BindingMode::{ByRef, ByValue};
                 let is_mutable_pat = matches!(
                     arg.pat.kind,
-                    PatKind::Ident(ByValue(Mutability::Mut) | ByRef(Mutability::Mut), ..)
+                    PatKind::Ident(hir::BindingAnnotation(_, Mutability::Mut), ..)
                 );
 
                 match arg.ty.kind {
@@ -1730,7 +1725,7 @@ fn lower_fn_decl(
     // `output`: unlowered output type (`T` in `-> T`)
     // `fn_def_id`: `DefId` of the parent function (used to create child impl trait definition)
     // `opaque_ty_node_id`: `NodeId` of the opaque `impl Trait` type that should be created
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn lower_async_fn_ret_ty(
         &mut self,
         output: &FnRetTy,
@@ -2013,7 +2008,7 @@ fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime {
         self.new_named_lifetime(l.id, l.id, span, ident)
     }
 
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn new_named_lifetime_with_res(
         &mut self,
         id: NodeId,
@@ -2024,7 +2019,7 @@ fn new_named_lifetime_with_res(
         let name = match res {
             LifetimeRes::Param { param, .. } => {
                 let p_name = ParamName::Plain(ident);
-                let param = self.resolver.get_remapped_def_id(param);
+                let param = self.get_remapped_def_id(param);
 
                 hir::LifetimeName::Param(param, p_name)
             }
@@ -2044,7 +2039,7 @@ fn new_named_lifetime_with_res(
         hir::Lifetime { hir_id: self.lower_node_id(id), span: self.lower_span(span), name }
     }
 
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn new_named_lifetime(
         &mut self,
         id: NodeId,
@@ -2132,7 +2127,7 @@ fn lower_trait_ref(&mut self, p: &TraitRef, itctx: ImplTraitContext) -> hir::Tra
         hir::TraitRef { path, hir_ref_id: self.lower_node_id(p.ref_id) }
     }
 
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn lower_poly_trait_ref(
         &mut self,
         p: &PolyTraitRef,
@@ -2193,12 +2188,15 @@ fn lower_generic_and_bounds(
             hir::PredicateOrigin::ImplTrait,
         );
 
+        let hir_id = self.next_id();
+        let res = Res::Def(DefKind::TyParam, def_id.to_def_id());
         let ty = hir::TyKind::Path(hir::QPath::Resolved(
             None,
             self.arena.alloc(hir::Path {
                 span: self.lower_span(span),
-                res: Res::Def(DefKind::TyParam, def_id.to_def_id()),
-                segments: arena_vec![self; hir::PathSegment::from_ident(self.lower_ident(ident))],
+                res,
+                segments:
+                    arena_vec![self; hir::PathSegment::new(self.lower_ident(ident), hir_id, res)],
             }),
         ));
 
@@ -2361,11 +2359,11 @@ fn pat_lang_item_variant(
     }
 
     fn pat_ident(&mut self, span: Span, ident: Ident) -> (&'hir hir::Pat<'hir>, hir::HirId) {
-        self.pat_ident_binding_mode(span, ident, hir::BindingAnnotation::Unannotated)
+        self.pat_ident_binding_mode(span, ident, hir::BindingAnnotation::NONE)
     }
 
     fn pat_ident_mut(&mut self, span: Span, ident: Ident) -> (hir::Pat<'hir>, hir::HirId) {
-        self.pat_ident_binding_mode_mut(span, ident, hir::BindingAnnotation::Unannotated)
+        self.pat_ident_binding_mode_mut(span, ident, hir::BindingAnnotation::NONE)
     }
 
     fn pat_ident_binding_mode(
index 1efa19a3a828655d22f7721cb4357d3cb5a308ff..a1eee1be7984f63dfd174cc414d26c42820f50a5 100644 (file)
@@ -24,7 +24,7 @@ pub(crate) fn lower_pat_mut(&mut self, mut pattern: &Pat) -> hir::Pat<'hir> {
             let node = loop {
                 match pattern.kind {
                     PatKind::Wild => break hir::PatKind::Wild,
-                    PatKind::Ident(ref binding_mode, ident, ref sub) => {
+                    PatKind::Ident(binding_mode, ident, ref sub) => {
                         let lower_sub = |this: &mut Self| sub.as_ref().map(|s| this.lower_pat(&*s));
                         break self.lower_pat_ident(pattern, binding_mode, ident, lower_sub);
                     }
@@ -176,9 +176,9 @@ fn lower_pat_slice(&mut self, pats: &[P<Pat>]) -> hir::PatKind<'hir> {
         let mut prev_rest_span = None;
 
         // Lowers `$bm $ident @ ..` to `$bm $ident @ _`.
-        let lower_rest_sub = |this: &mut Self, pat, bm, ident, sub| {
+        let lower_rest_sub = |this: &mut Self, pat, ann, ident, sub| {
             let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub));
-            let node = this.lower_pat_ident(pat, bm, ident, lower_sub);
+            let node = this.lower_pat_ident(pat, ann, ident, lower_sub);
             this.pat_with_node_id_of(pat, node)
         };
 
@@ -194,9 +194,9 @@ fn lower_pat_slice(&mut self, pats: &[P<Pat>]) -> hir::PatKind<'hir> {
                 }
                 // Found a sub-slice pattern `$binding_mode $ident @ ..`.
                 // Record, lower it to `$binding_mode $ident @ _`, and stop here.
-                PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => {
+                PatKind::Ident(ann, ident, Some(ref sub)) if sub.is_rest() => {
                     prev_rest_span = Some(sub.span);
-                    slice = Some(self.arena.alloc(lower_rest_sub(self, pat, bm, ident, sub)));
+                    slice = Some(self.arena.alloc(lower_rest_sub(self, pat, ann, ident, sub)));
                     break;
                 }
                 // It was not a subslice pattern so lower it normally.
@@ -209,9 +209,9 @@ fn lower_pat_slice(&mut self, pats: &[P<Pat>]) -> hir::PatKind<'hir> {
             // There was a previous subslice pattern; make sure we don't allow more.
             let rest_span = match pat.kind {
                 PatKind::Rest => Some(pat.span),
-                PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => {
+                PatKind::Ident(ann, ident, Some(ref sub)) if sub.is_rest() => {
                     // #69103: Lower into `binding @ _` as above to avoid ICEs.
-                    after.push(lower_rest_sub(self, pat, bm, ident, sub));
+                    after.push(lower_rest_sub(self, pat, ann, ident, sub));
                     Some(sub.span)
                 }
                 _ => None,
@@ -235,7 +235,7 @@ fn lower_pat_slice(&mut self, pats: &[P<Pat>]) -> hir::PatKind<'hir> {
     fn lower_pat_ident(
         &mut self,
         p: &Pat,
-        binding_mode: &BindingMode,
+        annotation: BindingAnnotation,
         ident: Ident,
         lower_sub: impl FnOnce(&mut Self) -> Option<&'hir hir::Pat<'hir>>,
     ) -> hir::PatKind<'hir> {
@@ -248,29 +248,24 @@ fn lower_pat_ident(
                 };
 
                 hir::PatKind::Binding(
-                    self.lower_binding_mode(binding_mode),
+                    annotation,
                     self.lower_node_id(canonical_id),
                     self.lower_ident(ident),
                     lower_sub(self),
                 )
             }
-            Some(res) => hir::PatKind::Path(hir::QPath::Resolved(
-                None,
-                self.arena.alloc(hir::Path {
-                    span: self.lower_span(ident.span),
-                    res: self.lower_res(res),
-                    segments: arena_vec![self; hir::PathSegment::from_ident(self.lower_ident(ident))],
-                }),
-            )),
-        }
-    }
-
-    fn lower_binding_mode(&mut self, b: &BindingMode) -> hir::BindingAnnotation {
-        match *b {
-            BindingMode::ByValue(Mutability::Not) => hir::BindingAnnotation::Unannotated,
-            BindingMode::ByRef(Mutability::Not) => hir::BindingAnnotation::Ref,
-            BindingMode::ByValue(Mutability::Mut) => hir::BindingAnnotation::Mutable,
-            BindingMode::ByRef(Mutability::Mut) => hir::BindingAnnotation::RefMut,
+            Some(res) => {
+                let hir_id = self.next_id();
+                let res = self.lower_res(res);
+                hir::PatKind::Path(hir::QPath::Resolved(
+                    None,
+                    self.arena.alloc(hir::Path {
+                        span: self.lower_span(ident.span),
+                        res,
+                        segments: arena_vec![self; hir::PathSegment::new(self.lower_ident(ident), hir_id, res)],
+                    }),
+            ))
+            }
         }
     }
 
index 5874d08a94fe06bac55a516e8abef538f386aa58..de1467b1b07d6bee2031d423ca2b7d847e585ec5 100644 (file)
@@ -13,7 +13,6 @@
 use rustc_span::{BytePos, Span, DUMMY_SP};
 
 use smallvec::smallvec;
-use tracing::debug;
 
 impl<'a, 'hir> LoweringContext<'a, 'hir> {
     #[instrument(level = "trace", skip(self))]
@@ -251,16 +250,16 @@ pub(crate) fn lower_path_segment(
         }
 
         let res = self.expect_full_res(segment.id);
-        let id = self.lower_node_id(segment.id);
+        let hir_id = self.lower_node_id(segment.id);
         debug!(
             "lower_path_segment: ident={:?} original-id={:?} new-id={:?}",
-            segment.ident, segment.id, id,
+            segment.ident, segment.id, hir_id,
         );
 
         hir::PathSegment {
             ident: self.lower_ident(segment.ident),
-            hir_id: Some(id),
-            res: Some(self.lower_res(res)),
+            hir_id,
+            res: self.lower_res(res),
             infer_args,
             args: if generic_args.is_empty() && generic_args.span.is_empty() {
                 None
@@ -359,7 +358,7 @@ fn lower_parenthesized_parameter_data(
             }
             FnRetTy::Default(_) => self.arena.alloc(self.ty_tup(*span, &[])),
         };
-        let args = smallvec![GenericArg::Type(self.ty_tup(*inputs_span, inputs))];
+        let args = smallvec![GenericArg::Type(self.arena.alloc(self.ty_tup(*inputs_span, inputs)))];
         let binding = self.output_ty_binding(output_ty.span, output_ty);
         (
             GenericArgsCtor {
index 23464bf0a5a283e50039bf38ba77f2e9e741d673..d6d8881a53a146e0c4c62d8fb93123122fb735fe 100644 (file)
@@ -281,8 +281,8 @@ fn invalid_visibility(&self, vis: &Visibility, note: Option<InvalidVisibilityNot
     fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option<Ident>, bool)) {
         for Param { pat, .. } in &decl.inputs {
             match pat.kind {
-                PatKind::Ident(BindingMode::ByValue(Mutability::Not), _, None) | PatKind::Wild => {}
-                PatKind::Ident(BindingMode::ByValue(Mutability::Mut), ident, None) => {
+                PatKind::Ident(BindingAnnotation::NONE, _, None) | PatKind::Wild => {}
+                PatKind::Ident(BindingAnnotation::MUT, ident, None) => {
                     report_err(pat.span, Some(ident), true)
                 }
                 _ => report_err(pat.span, None, false),
index 6f7e88eb86f195e074a38cab814758c0f57d54d0..ca5b7a64155157f80c250cd9e8c8e07b9897ebbe 100644 (file)
@@ -11,8 +11,6 @@
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 
-use tracing::debug;
-
 macro_rules! gate_feature_fn {
     ($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $help: expr) => {{
         let (visitor, has_feature, span, name, explain, help) =
index f282ff251bda181ca8c7f97c961382c1cd1c1b95..af25982e2887bb33656b99017083f8c460d7a619 100644 (file)
@@ -12,6 +12,9 @@
 #![feature(let_else)]
 #![recursion_limit = "256"]
 
+#[macro_use]
+extern crate tracing;
+
 pub mod ast_validation;
 mod errors;
 pub mod feature_gate;
index 8749a13c5dde1ae1a6af2598bda8c8bdb14a2167..ed5e7dace4bc4ba1ea971d7c1d61e9e7e244672e 100644 (file)
@@ -11,8 +11,8 @@
 use rustc_ast::util::classify;
 use rustc_ast::util::comments::{gather_comments, Comment, CommentStyle};
 use rustc_ast::util::parser;
-use rustc_ast::{self as ast, BlockCheckMode, PatKind, RangeEnd, RangeSyntax};
-use rustc_ast::{attr, Term};
+use rustc_ast::{self as ast, BlockCheckMode, Mutability, PatKind, RangeEnd, RangeSyntax};
+use rustc_ast::{attr, BindingAnnotation, ByRef, Term};
 use rustc_ast::{GenericArg, MacArgs, MacArgsEq};
 use rustc_ast::{GenericBound, SelfKind, TraitBoundModifier};
 use rustc_ast::{InlineAsmOperand, InlineAsmRegOrRegClass};
@@ -1399,16 +1399,12 @@ pub(crate) fn print_pat(&mut self, pat: &ast::Pat) {
         is that it doesn't matter */
         match pat.kind {
             PatKind::Wild => self.word("_"),
-            PatKind::Ident(binding_mode, ident, ref sub) => {
-                match binding_mode {
-                    ast::BindingMode::ByRef(mutbl) => {
-                        self.word_nbsp("ref");
-                        self.print_mutability(mutbl, false);
-                    }
-                    ast::BindingMode::ByValue(ast::Mutability::Not) => {}
-                    ast::BindingMode::ByValue(ast::Mutability::Mut) => {
-                        self.word_nbsp("mut");
-                    }
+            PatKind::Ident(BindingAnnotation(by_ref, mutbl), ident, ref sub) => {
+                if by_ref == ByRef::Yes {
+                    self.word_nbsp("ref");
+                }
+                if mutbl == Mutability::Mut {
+                    self.word_nbsp("mut");
                 }
                 self.print_ident(ident);
                 if let Some(ref p) = *sub {
@@ -1487,12 +1483,10 @@ pub(crate) fn print_pat(&mut self, pat: &ast::Pat) {
             }
             PatKind::Ref(ref inner, mutbl) => {
                 self.word("&");
-                if mutbl == ast::Mutability::Mut {
+                if mutbl == Mutability::Mut {
                     self.word("mut ");
                 }
-                if let PatKind::Ident(ast::BindingMode::ByValue(ast::Mutability::Mut), ..) =
-                    inner.kind
-                {
+                if let PatKind::Ident(ast::BindingAnnotation::MUT, ..) = inner.kind {
                     self.popen();
                     self.print_pat(inner);
                     self.pclose();
index bd87987010e8fd2a15ae17ef490ef2547a3c6077..54bac29a6cee0fd7fe05a7445367f920e910c42d 100644 (file)
@@ -218,6 +218,8 @@ pub(crate) fn print_item(&mut self, item: &ast::Item) {
             ast::ItemKind::GlobalAsm(ref asm) => {
                 self.head(visibility_qualified(&item.vis, "global_asm!"));
                 self.print_inline_asm(asm);
+                self.word(";");
+                self.end();
                 self.end();
             }
             ast::ItemKind::TyAlias(box ast::TyAlias {
index 65edab78ce74ece4c3b2cb1098b7db250851346b..a8ed510866d89832fed560be07bf534f2fbfda84 100644 (file)
 
 use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause};
 
+/// The version placeholder that recently stabilized features contain inside the
+/// `since` field of the `#[stable]` attribute.
+///
+/// For more, see [this pull request](https://github.com/rust-lang/rust/pull/100591).
+pub const VERSION_PLACEHOLDER: &str = "CURRENT_RUSTC_VERSION";
+
 pub fn is_builtin_attr(attr: &Attribute) -> bool {
     attr.is_doc_comment() || attr.ident().filter(|ident| is_builtin_attr_name(ident.name)).is_some()
 }
@@ -483,6 +489,12 @@ fn find_stability_generic<'a, I>(
                         }
                     }
 
+                    if let Some(s) = since && s.as_str() == VERSION_PLACEHOLDER {
+                        let version = option_env!("CFG_VERSION").unwrap_or("<current>");
+                        let version = version.split(' ').next().unwrap();
+                        since = Some(Symbol::intern(&version));
+                    }
+
                     match (feature, since) {
                         (Some(feature), Some(since)) => {
                             let level = Stable { since, allowed_through_unstable_modules: false };
index 5971f7623f215a4c3ed8c1a1832d8b31f32ba134..f2204c24263ce3f3c792d6b453ad63c67ebb634a 100644 (file)
@@ -258,7 +258,8 @@ pub(crate) fn report_use_of_moved_or_uninitialized(
             let ty = place.ty(self.body, self.infcx.tcx).ty;
 
             // If we're in pattern, we do nothing in favor of the previous suggestion (#80913).
-            if is_loop_move & !in_pattern {
+            // Same for if we're in a loop, see #101119.
+            if is_loop_move & !in_pattern && !matches!(use_spans, UseSpans::ClosureUse { .. }) {
                 if let ty::Ref(_, _, hir::Mutability::Mut) = ty.kind() {
                     // We have a `&mut` ref, we need to reborrow on each iteration (#62112).
                     err.span_suggestion_verbose(
index dd9590016b990f27f98f64cd04cd49b3a3e005ea..2c6c461267a916a689aca507388dd11c37195f13 100644 (file)
@@ -367,7 +367,7 @@ pub(crate) fn report_mutability_error(
 
                 if let Some(Node::Pat(pat)) = self.infcx.tcx.hir().find(upvar_hir_id)
                     && let hir::PatKind::Binding(
-                        hir::BindingAnnotation::Unannotated,
+                        hir::BindingAnnotation::NONE,
                         _,
                         upvar_ident,
                         _,
@@ -711,8 +711,8 @@ fn visit_stmt(&mut self, stmt: &'hir hir::Stmt<'hir>) {
                             Applicability::MachineApplicable,
                         );
                         self.suggested = true;
-                    } else if let hir::ExprKind::MethodCall(_path, args @ [_, ..], sp) = expr.kind
-                        && let hir::ExprKind::Index(val, index) = args[0].kind
+                    } else if let hir::ExprKind::MethodCall(_path, receiver, _, sp) = expr.kind
+                        && let hir::ExprKind::Index(val, index) = receiver.kind
                         && expr.span == self.assign_span
                     {
                         // val[index].path(args..);
@@ -724,7 +724,7 @@ fn visit_stmt(&mut self, stmt: &'hir hir::Stmt<'hir>) {
                                     ".get_mut(".to_string(),
                                 ),
                                 (
-                                    index.span.shrink_to_hi().with_hi(args[0].span.hi()),
+                                    index.span.shrink_to_hi().with_hi(receiver.span.hi()),
                                     ").map(|val| val".to_string(),
                                 ),
                                 (sp.shrink_to_hi(), ")".to_string()),
@@ -911,11 +911,7 @@ fn maybe_body_id_of_fn(hir_map: Map<'_>, id: HirId) -> Option<BodyId> {
                                                         [
                                                             Expr {
                                                                 kind:
-                                                                    MethodCall(
-                                                                        path_segment,
-                                                                        _args,
-                                                                        span,
-                                                                    ),
+                                                                    MethodCall(path_segment, _, _, span),
                                                                 hir_id,
                                                                 ..
                                                             },
@@ -935,10 +931,11 @@ fn maybe_body_id_of_fn(hir_map: Map<'_>, id: HirId) -> Option<BodyId> {
                 _,
             ) = hir_map.body(fn_body_id).value.kind
             {
-                let opt_suggestions = path_segment
-                    .hir_id
-                    .map(|path_hir_id| self.infcx.tcx.typeck(path_hir_id.owner))
-                    .and_then(|typeck| typeck.type_dependent_def_id(*hir_id))
+                let opt_suggestions = self
+                    .infcx
+                    .tcx
+                    .typeck(path_segment.hir_id.owner)
+                    .type_dependent_def_id(*hir_id)
                     .and_then(|def_id| self.infcx.tcx.impl_of_method(def_id))
                     .map(|def_id| self.infcx.tcx.associated_items(def_id))
                     .map(|assoc_items| {
index d359d7efb626801905958a91c983f866105a1fce..35c3df768995a0d2907db1cb174122666596a9cc 100644 (file)
@@ -6,7 +6,6 @@
 use rustc_middle::ty::RegionVid;
 use smallvec::SmallVec;
 use std::collections::BTreeMap;
-use tracing::debug;
 
 use crate::MirBorrowckCtxt;
 
index 00fdf331ca60ce8c270a3ce98ec6a41d35baafa6..9615025fa5767b43e86e57b57ba9ca2c977cad46 100644 (file)
@@ -900,10 +900,13 @@ fn suggest_move_on_borrowing_closure(&self, diag: &mut Diagnostic) {
         let mut closure_span = None::<rustc_span::Span>;
         match expr.kind {
             hir::ExprKind::MethodCall(.., args, _) => {
-                // only the first closre parameter of the method. args[0] is MethodCall PathSegment
-                for i in 1..args.len() {
-                    if let hir::ExprKind::Closure(..) = args[i].kind {
-                        closure_span = Some(args[i].span.shrink_to_lo());
+                for arg in args {
+                    if let hir::ExprKind::Closure(hir::Closure {
+                        capture_clause: hir::CaptureBy::Ref,
+                        ..
+                    }) = arg.kind
+                    {
+                        closure_span = Some(arg.span.shrink_to_lo());
                         break;
                     }
                 }
@@ -911,7 +914,11 @@ fn suggest_move_on_borrowing_closure(&self, diag: &mut Diagnostic) {
             hir::ExprKind::Block(blk, _) => {
                 if let Some(ref expr) = blk.expr {
                     // only when the block is a closure
-                    if let hir::ExprKind::Closure(..) = expr.kind {
+                    if let hir::ExprKind::Closure(hir::Closure {
+                        capture_clause: hir::CaptureBy::Ref,
+                        ..
+                    }) = expr.kind
+                    {
                         closure_span = Some(expr.span.shrink_to_lo());
                     }
                 }
@@ -921,7 +928,7 @@ fn suggest_move_on_borrowing_closure(&self, diag: &mut Diagnostic) {
         if let Some(closure_span) = closure_span {
             diag.span_suggestion_verbose(
                 closure_span,
-                format!("consider adding 'move' keyword before the nested closure"),
+                "consider adding 'move' keyword before the nested closure",
                 "move ",
                 Applicability::MaybeIncorrect,
             );
index a87e8bd5ba16fc276183bc1366a121107141dd94..75fde53b6cdecd24452e0293db2118ad598f9620 100644 (file)
@@ -265,7 +265,7 @@ pub(crate) fn give_region_a_name(&self, fr: RegionVid) -> Option<RegionName> {
     /// *user* has a name for. In that case, we'll be able to map
     /// `fr` to a `Region<'tcx>`, and that region will be one of
     /// named variants.
-    #[tracing::instrument(level = "trace", skip(self))]
+    #[instrument(level = "trace", skip(self))]
     fn give_name_from_error_region(&self, fr: RegionVid) -> Option<RegionName> {
         let error_region = self.to_error_region(fr)?;
 
@@ -373,7 +373,7 @@ fn give_name_from_error_region(&self, fr: RegionVid) -> Option<RegionName> {
     ///  | fn foo(x: &u32) { .. }
     ///           ------- fully elaborated type of `x` is `&'1 u32`
     /// ```
-    #[tracing::instrument(level = "trace", skip(self))]
+    #[instrument(level = "trace", skip(self))]
     fn give_name_if_anonymous_region_appears_in_arguments(
         &self,
         fr: RegionVid,
@@ -662,7 +662,7 @@ fn try_match_adt_and_generic_args<'hir>(
     ///  | let x = Some(&22);
     ///        - fully elaborated type of `x` is `Option<&'1 u32>`
     /// ```
-    #[tracing::instrument(level = "trace", skip(self))]
+    #[instrument(level = "trace", skip(self))]
     fn give_name_if_anonymous_region_appears_in_upvars(&self, fr: RegionVid) -> Option<RegionName> {
         let upvar_index = self.regioncx.get_upvar_index_for_region(self.infcx.tcx, fr)?;
         let (upvar_name, upvar_span) = self.regioncx.get_upvar_name_and_span_for_region(
@@ -682,7 +682,7 @@ fn give_name_if_anonymous_region_appears_in_upvars(&self, fr: RegionVid) -> Opti
     /// must be a closure since, in a free fn, such an argument would
     /// have to either also appear in an argument (if using elision)
     /// or be early bound (named, not in argument).
-    #[tracing::instrument(level = "trace", skip(self))]
+    #[instrument(level = "trace", skip(self))]
     fn give_name_if_anonymous_region_appears_in_output(&self, fr: RegionVid) -> Option<RegionName> {
         let tcx = self.infcx.tcx;
         let hir = tcx.hir();
@@ -814,7 +814,7 @@ fn get_future_inner_return_ty(&self, hir_ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::
         }
     }
 
-    #[tracing::instrument(level = "trace", skip(self))]
+    #[instrument(level = "trace", skip(self))]
     fn give_name_if_anonymous_region_appears_in_yield_ty(
         &self,
         fr: RegionVid,
index f5bd5cd3beaed0ab0006c2ba688a5fc8009f743a..8dc9368a0b994d197943ea914fa19b6578b554dc 100644 (file)
@@ -1139,7 +1139,7 @@ fn non_local_universal_upper_bound(&self, r: RegionVid) -> RegionVid {
     ///   include the CFG anyhow.
     /// - For each `end('x)` element in `'r`, compute the mutual LUB, yielding
     ///   a result `'y`.
-    #[instrument(skip(self), level = "debug")]
+    #[instrument(skip(self), level = "debug", ret)]
     pub(crate) fn universal_upper_bound(&self, r: RegionVid) -> RegionVid {
         debug!(r = %self.region_value_str(r));
 
@@ -1151,8 +1151,6 @@ pub(crate) fn universal_upper_bound(&self, r: RegionVid) -> RegionVid {
             lub = self.universal_region_relations.postdom_upper_bound(lub, ur);
         }
 
-        debug!(?lub);
-
         lub
     }
 
@@ -1333,15 +1331,15 @@ fn eval_equal(&self, r1: RegionVid, r2: RegionVid) -> bool {
     }
 
     // Evaluate whether `sup_region: sub_region`.
-    #[instrument(skip(self), level = "debug")]
+    #[instrument(skip(self), level = "debug", ret)]
     fn eval_outlives(&self, sup_region: RegionVid, sub_region: RegionVid) -> bool {
         debug!(
-            "eval_outlives: sup_region's value = {:?} universal={:?}",
+            "sup_region's value = {:?} universal={:?}",
             self.region_value_str(sup_region),
             self.universal_regions.is_universal_region(sup_region),
         );
         debug!(
-            "eval_outlives: sub_region's value = {:?} universal={:?}",
+            "sub_region's value = {:?} universal={:?}",
             self.region_value_str(sub_region),
             self.universal_regions.is_universal_region(sub_region),
         );
@@ -1354,7 +1352,7 @@ fn eval_outlives(&self, sup_region: RegionVid, sub_region: RegionVid) -> bool {
         // true if `'sup` outlives static.
         if !self.universe_compatible(sub_region_scc, sup_region_scc) {
             debug!(
-                "eval_outlives: sub universe `{sub_region_scc:?}` is not nameable \
+                "sub universe `{sub_region_scc:?}` is not nameable \
                 by super `{sup_region_scc:?}`, promoting to static",
             );
 
@@ -1375,9 +1373,7 @@ fn eval_outlives(&self, sup_region: RegionVid, sub_region: RegionVid) -> bool {
             });
 
         if !universal_outlives {
-            debug!(
-                "eval_outlives: returning false because sub region contains a universal region not present in super"
-            );
+            debug!("sub region contains a universal region not present in super");
             return false;
         }
 
@@ -1386,15 +1382,13 @@ fn eval_outlives(&self, sup_region: RegionVid, sub_region: RegionVid) -> bool {
 
         if self.universal_regions.is_universal_region(sup_region) {
             // Micro-opt: universal regions contain all points.
-            debug!(
-                "eval_outlives: returning true because super is universal and hence contains all points"
-            );
+            debug!("super is universal and hence contains all points");
             return true;
         }
 
-        let result = self.scc_values.contains_points(sup_region_scc, sub_region_scc);
-        debug!("returning {} because of comparison between points in sup/sub", result);
-        result
+        debug!("comparison between points in sup/sub");
+
+        self.scc_values.contains_points(sup_region_scc, sub_region_scc)
     }
 
     /// Once regions have been propagated, this method is used to see
@@ -1971,7 +1965,7 @@ pub(crate) fn find_constraint_paths_between_regions(
     }
 
     /// Finds some region R such that `fr1: R` and `R` is live at `elem`.
-    #[instrument(skip(self), level = "trace")]
+    #[instrument(skip(self), level = "trace", ret)]
     pub(crate) fn find_sub_region_live_at(&self, fr1: RegionVid, elem: Location) -> RegionVid {
         trace!(scc = ?self.constraint_sccs.scc(fr1));
         trace!(universe = ?self.scc_universes[self.constraint_sccs.scc(fr1)]);
index 127cb4e408372e800e9ef7380f04c8ee59cf9e8d..0392367288c40544cad175913f68626a3ca9684d 100644 (file)
@@ -60,7 +60,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// Calling `universal_upper_bound` for such a region gives `fr_fn_body`,
     /// which has no `external_name` in which case we use `'empty` as the
     /// region to pass to `infer_opaque_definition_from_instantiation`.
-    #[instrument(level = "debug", skip(self, infcx))]
+    #[instrument(level = "debug", skip(self, infcx), ret)]
     pub(crate) fn infer_opaque_types(
         &self,
         infcx: &InferCtxt<'_, 'tcx>,
index 2a7713bc4df3b6d1e8be939ef07799a5c412f820..b9b181681ec4b7495cf63f925799d205cdaff281 100644 (file)
@@ -768,10 +768,9 @@ fn replace_late_bound_regions_with_nll_infer_vars(
         mir_def_id: LocalDefId,
         indices: &mut UniversalRegionIndices<'tcx>,
     ) {
-        debug!("replace_late_bound_regions_with_nll_infer_vars(mir_def_id={:?})", mir_def_id);
         let typeck_root_def_id = self.tcx.typeck_root_def_id(mir_def_id.to_def_id());
         for_each_late_bound_region_defined_on(self.tcx, typeck_root_def_id, |r| {
-            debug!("replace_late_bound_regions_with_nll_infer_vars: r={:?}", r);
+            debug!(?r);
             if !indices.indices.contains_key(&r) {
                 let region_vid = self.next_nll_region_var(FR);
                 debug!(?region_vid);
index adffebd3fd2850af0f0206ac03391d12940270a7..3cc160adb5397aa73ed3041e23e8f0d081db2fc5 100644 (file)
 
 use crate::deriving;
 use rustc_ast::ptr::P;
-use rustc_ast::{self as ast, EnumDef, Expr, Generics, PatKind};
+use rustc_ast::{
+    self as ast, BindingAnnotation, ByRef, EnumDef, Expr, Generics, Mutability, PatKind,
+};
 use rustc_ast::{GenericArg, GenericParamKind, VariantData};
 use rustc_attr as attr;
 use rustc_expand::base::{Annotatable, ExtCtxt};
@@ -1063,9 +1065,9 @@ fn expand_struct_method_body<'b>(
             let mut body = mk_body(cx, selflike_fields);
 
             let struct_path = cx.path(span, vec![Ident::new(kw::SelfUpper, type_ident.span)]);
-            let use_ref_pat = is_packed && !always_copy;
+            let by_ref = ByRef::from(is_packed && !always_copy);
             let patterns =
-                trait_.create_struct_patterns(cx, struct_path, struct_def, &prefixes, use_ref_pat);
+                trait_.create_struct_patterns(cx, struct_path, struct_def, &prefixes, by_ref);
 
             // Do the let-destructuring.
             let mut stmts: Vec<_> = iter::zip(selflike_args, patterns)
@@ -1247,13 +1249,13 @@ fn expand_enum_method_body<'b>(
 
                 let sp = variant.span.with_ctxt(trait_.span.ctxt());
                 let variant_path = cx.path(sp, vec![type_ident, variant.ident]);
-                let use_ref_pat = false; // because enums can't be repr(packed)
+                let by_ref = ByRef::No; // because enums can't be repr(packed)
                 let mut subpats: Vec<_> = trait_.create_struct_patterns(
                     cx,
                     variant_path,
                     &variant.data,
                     &prefixes,
-                    use_ref_pat,
+                    by_ref,
                 );
 
                 // `(VariantK, VariantK, ...)` or just `VariantK`.
@@ -1414,7 +1416,7 @@ fn create_struct_patterns(
         struct_path: ast::Path,
         struct_def: &'a VariantData,
         prefixes: &[String],
-        use_ref_pat: bool,
+        by_ref: ByRef,
     ) -> Vec<P<ast::Pat>> {
         prefixes
             .iter()
@@ -1422,17 +1424,19 @@ fn create_struct_patterns(
                 let pieces_iter =
                     struct_def.fields().iter().enumerate().map(|(i, struct_field)| {
                         let sp = struct_field.span.with_ctxt(self.span.ctxt());
-                        let binding_mode = if use_ref_pat {
-                            ast::BindingMode::ByRef(ast::Mutability::Not)
-                        } else {
-                            ast::BindingMode::ByValue(ast::Mutability::Not)
-                        };
                         let ident = self.mk_pattern_ident(prefix, i);
                         let path = ident.with_span_pos(sp);
                         (
                             sp,
                             struct_field.ident,
-                            cx.pat(path.span, PatKind::Ident(binding_mode, path, None)),
+                            cx.pat(
+                                path.span,
+                                PatKind::Ident(
+                                    BindingAnnotation(by_ref, Mutability::Not),
+                                    path,
+                                    None,
+                                ),
+                            ),
                         )
                     });
 
index 11565ba72d7555f1fb157468fd4c83b957eb873e..280fa70451141f85f821c2f2b02e0f87f82d5a83 100644 (file)
@@ -16,6 +16,9 @@
 
 extern crate proc_macro;
 
+#[macro_use]
+extern crate tracing;
+
 use crate::deriving::*;
 
 use rustc_expand::base::{MacroExpanderFn, ResolverExpand, SyntaxExtensionKind};
index 7eee80733666cf56e1657c6612ce31495032b9b4..7efb6cc61eecbb2325525c4696b5b5b7c9040c8a 100644 (file)
@@ -335,7 +335,7 @@ pub fn expand_test_or_bench(
     // extern crate test
     let test_extern = cx.item(sp, test_id, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None));
 
-    tracing::debug!("synthetic test item:\n{}\n", pprust::item_to_string(&test_const));
+    debug!("synthetic test item:\n{}\n", pprust::item_to_string(&test_const));
 
     if is_stmt {
         vec![
index 89b0d2cc9be2eed8df75ae903645553f5dfcf1b2..079c6ff37cfb53222caeaf79014ebda64fa65716 100644 (file)
@@ -15,7 +15,6 @@
 use rustc_target::spec::PanicStrategy;
 use smallvec::{smallvec, SmallVec};
 use thin_vec::thin_vec;
-use tracing::debug;
 
 use std::{iter, mem};
 
index c67b6e98b32c7daeeca8558ed2882f082cd0b103..3c024a84d9091f1fb3bf1533443d4ed5bed5a27d 100644 (file)
@@ -1,7 +1,7 @@
 use rustc_hir::LangItem;
 use rustc_middle::ty::subst::GenericArg;
 use rustc_middle::ty::AssocKind;
-use rustc_session::config::EntryFnType;
+use rustc_session::config::{sigpipe, EntryFnType};
 use rustc_span::symbol::Ident;
 
 use crate::prelude::*;
@@ -15,12 +15,12 @@ pub(crate) fn maybe_create_entry_wrapper(
     is_jit: bool,
     is_primary_cgu: bool,
 ) {
-    let (main_def_id, is_main_fn) = match tcx.entry_fn(()) {
+    let (main_def_id, (is_main_fn, sigpipe)) = match tcx.entry_fn(()) {
         Some((def_id, entry_ty)) => (
             def_id,
             match entry_ty {
-                EntryFnType::Main => true,
-                EntryFnType::Start => false,
+                EntryFnType::Main { sigpipe } => (true, sigpipe),
+                EntryFnType::Start => (false, sigpipe::DEFAULT),
             },
         ),
         None => return,
@@ -35,7 +35,7 @@ pub(crate) fn maybe_create_entry_wrapper(
         return;
     }
 
-    create_entry_fn(tcx, module, unwind_context, main_def_id, is_jit, is_main_fn);
+    create_entry_fn(tcx, module, unwind_context, main_def_id, is_jit, is_main_fn, sigpipe);
 
     fn create_entry_fn(
         tcx: TyCtxt<'_>,
@@ -44,6 +44,7 @@ fn create_entry_fn(
         rust_main_def_id: DefId,
         ignore_lang_start_wrapper: bool,
         is_main_fn: bool,
+        sigpipe: u8,
     ) {
         let main_ret_ty = tcx.fn_sig(rust_main_def_id).output();
         // Given that `main()` has no arguments,
@@ -83,6 +84,7 @@ fn create_entry_fn(
             bcx.switch_to_block(block);
             let arg_argc = bcx.append_block_param(block, m.target_config().pointer_type());
             let arg_argv = bcx.append_block_param(block, m.target_config().pointer_type());
+            let arg_sigpipe = bcx.ins().iconst(types::I8, sigpipe as i64);
 
             let main_func_ref = m.declare_func_in_func(main_func_id, &mut bcx.func);
 
@@ -143,7 +145,8 @@ fn create_entry_fn(
                 let main_val = bcx.ins().func_addr(m.target_config().pointer_type(), main_func_ref);
 
                 let func_ref = m.declare_func_in_func(start_func_id, &mut bcx.func);
-                let call_inst = bcx.ins().call(func_ref, &[main_val, arg_argc, arg_argv]);
+                let call_inst =
+                    bcx.ins().call(func_ref, &[main_val, arg_argc, arg_argv, arg_sigpipe]);
                 bcx.inst_results(call_inst)[0]
             } else {
                 // using user-defined start fn
index 2a6612eb86f12c62b41f516b41dfe18c5cd40806..5202ac697e9496f4551bb265de5732ed542fed72 100644 (file)
@@ -19,7 +19,6 @@
 
 use libc::{c_char, c_uint};
 use smallvec::SmallVec;
-use tracing::debug;
 
 impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
     fn codegen_inline_asm(
index aabbe8ac276d7ca7233618dcee8c3944da1fecdc..b38684a63e410d103150011d9ab452dfde04503d 100644 (file)
@@ -386,7 +386,8 @@ pub fn from_fn_attrs<'ll, 'tcx>(
     ) {
         let span = cx
             .tcx
-            .get_attr(instance.def_id(), sym::target_feature)
+            .get_attrs(instance.def_id(), sym::target_feature)
+            .next()
             .map_or_else(|| cx.tcx.def_span(instance.def_id()), |a| a.span);
         let msg = format!(
             "the target features {} must all be either enabled or disabled together",
index 2e614e5dd88e7fc18068974f22e1e7a3a8a34df7..38a366095b41da97c9fe8906b8ab626be71935e5 100644 (file)
@@ -190,10 +190,10 @@ fn create_dll_import_lib(
 
             let output_path_z = rustc_fs_util::path_to_c_string(&output_path);
 
-            tracing::trace!("invoking LLVMRustWriteImportLibrary");
-            tracing::trace!("  dll_name {:#?}", dll_name_z);
-            tracing::trace!("  output_path {}", output_path.display());
-            tracing::trace!(
+            trace!("invoking LLVMRustWriteImportLibrary");
+            trace!("  dll_name {:#?}", dll_name_z);
+            trace!("  output_path {}", output_path.display());
+            trace!(
                 "  import names: {}",
                 dll_imports
                     .iter()
index e4af6269abc5305870515a832baf27da3111b677..a89df00e248e30e385fe2bc35202e4879d866780 100644 (file)
@@ -18,7 +18,6 @@
 use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel};
 use rustc_session::cgu_reuse_tracker::CguReuse;
 use rustc_session::config::{self, CrateType, Lto};
-use tracing::{debug, info};
 
 use std::ffi::{CStr, CString};
 use std::fs::File;
index 740a68d0772c1632ba54061cc8bb783591eecfd6..a695df8409bb4621326aa87929be8851337a418a 100644 (file)
@@ -28,7 +28,6 @@
 use rustc_span::symbol::sym;
 use rustc_span::InnerSpan;
 use rustc_target::spec::{CodeModel, RelocModel, SanitizerSet, SplitDebuginfo};
-use tracing::debug;
 
 use libc::{c_char, c_int, c_uint, c_void, size_t};
 use std::ffi::CString;
index e7e373bf45d11043f9e3ba32bd18d09f10313322..63b63c6a1fab5d42d89c48ca7dea9dfc90ddd69e 100644 (file)
@@ -27,7 +27,6 @@
 use std::iter;
 use std::ops::Deref;
 use std::ptr;
-use tracing::{debug, instrument};
 
 // All Builders must have an llfn associated with them
 #[must_use]
index d55f995b933a6f6ec4935c8bf712247a0fcd9762..b83c1e8f08f3182ee2178faa1a03b98862d3985c 100644 (file)
@@ -11,7 +11,6 @@
 use crate::llvm;
 use crate::value::Value;
 use rustc_codegen_ssa::traits::*;
-use tracing::debug;
 
 use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
 use rustc_middle::ty::{self, Instance, TypeVisitable};
index 63d3bb40a3fe0c448463f9d32253b984b7476424..13e437cfbf7fb1b52d06589eb20c068ad140a131 100644 (file)
@@ -21,7 +21,6 @@
 
 use libc::{c_char, c_uint};
 use std::fmt::Write;
-use tracing::debug;
 
 /*
 * A note on nomenclature of linking: "extern", "foreign", and "upcall".
index d3e33da27993c6b3286765128fd0b7ca6ce04952..a559f7f3d57035a58da56542d948fdad98a9274a 100644 (file)
@@ -23,7 +23,6 @@
     AddressSpace, Align, HasDataLayout, Primitive, Scalar, Size, WrappingRange,
 };
 use std::ops::Range;
-use tracing::debug;
 
 pub fn const_alloc_to_llvm<'ll>(cx: &CodegenCx<'ll, '_>, alloc: ConstAllocation<'_>) -> &'ll Value {
     let alloc = alloc.inner();
index 58f391692c49c109bb59b7011109403a09625943..0d1df6fb1acd99e437c9fbcf3d4bc59b984b4578 100644 (file)
@@ -16,8 +16,6 @@
 
 use std::ffi::CString;
 
-use tracing::debug;
-
 /// Generates and exports the Coverage Map.
 ///
 /// Rust Coverage Map generation supports LLVM Coverage Mapping Format versions
index 98ba38356a4c30c8cafcd806115ebff394581817..964a632b6eeddc77a68711eed82bc4eef8c20e73 100644 (file)
@@ -28,7 +28,6 @@
 use std::ffi::CString;
 
 use std::iter;
-use tracing::debug;
 
 pub mod mapgen;
 
index d0a6f216858b61575238b6101f2a34fd151d8bd0..163ccd9460c54b58c9f1326fd3d186ae60496d9f 100644 (file)
@@ -42,7 +42,6 @@
 use rustc_symbol_mangling::typeid_for_trait_ref;
 use rustc_target::abi::{Align, Size};
 use smallvec::smallvec;
-use tracing::debug;
 
 use libc::{c_char, c_longlong, c_uint};
 use std::borrow::Cow;
@@ -51,7 +50,6 @@
 use std::iter;
 use std::path::{Path, PathBuf};
 use std::ptr;
-use tracing::instrument;
 
 impl PartialEq for llvm::Metadata {
     fn eq(&self, other: &Self) -> bool {
index cf591295b84680b57c660219f07e891a0c09a821..b23fe3fc9d5575ae8971c6dbb4b61cd1905512aa 100644 (file)
@@ -39,7 +39,6 @@
 use std::cell::OnceCell;
 use std::cell::RefCell;
 use std::iter;
-use tracing::debug;
 
 mod create_scope_map;
 pub mod gdb;
index 8f24367390775e1a8b43cac1024b7d093b17e4d3..a40cfc8b23fb32217f5b6b0897bea0e4f9e27373 100644 (file)
@@ -6,7 +6,7 @@
 use rustc_hir::def_id::DefId;
 use rustc_middle::ty::layout::{HasParamEnv, LayoutOf};
 use rustc_middle::ty::{self, DefIdTree, Ty};
-use tracing::trace;
+use trace;
 
 use crate::common::CodegenCx;
 use crate::llvm;
index fa0ecd18fc895bcd7908250d6b970a0834677243..0f663a26732bba8abf5094a095a859784f6f9012 100644 (file)
@@ -22,7 +22,6 @@
 use rustc_middle::ty::Ty;
 use rustc_symbol_mangling::typeid::typeid_for_fnabi;
 use smallvec::SmallVec;
-use tracing::debug;
 
 /// Declare a function.
 ///
index 636d689a34b5a900ef1ad0ae41484ac5147b4729..334425ae55b43300c1f3f7e06463b235a5ad3a28 100644 (file)
@@ -16,6 +16,8 @@
 
 #[macro_use]
 extern crate rustc_macros;
+#[macro_use]
+extern crate tracing;
 
 use back::write::{create_informational_target_machine, create_target_machine};
 
index f5d676c44e3428b83677bd237daf7e5ad9ca2782..1b049dfe9790444e300423cbbef45ccb27370168 100644 (file)
@@ -15,7 +15,6 @@
 use rustc_target::spec::{MergeFunctions, PanicStrategy};
 use smallvec::{smallvec, SmallVec};
 use std::ffi::{CStr, CString};
-use tracing::debug;
 
 use std::mem;
 use std::path::Path;
index 6e94284852f357970663599fbf08766576eef75c..1eceb7f5c87beb362760851e5ce31ae40a66c75f 100644 (file)
@@ -11,7 +11,6 @@
 use rustc_middle::ty::{self, Instance, TypeVisitable};
 use rustc_session::config::CrateType;
 use rustc_target::spec::RelocModel;
-use tracing::debug;
 
 impl<'tcx> PreDefineMethods<'tcx> for CodegenCx<'_, 'tcx> {
     fn predefine_static(
index 9f0e6c80b19a7f0108620d5fa07275f7dd90aaee..dc1165835e7ca271b38986619f20801fb8c5a71e 100644 (file)
@@ -11,7 +11,6 @@
 use rustc_target::abi::{Int, Pointer, F32, F64};
 use rustc_target::abi::{PointeeInfo, Scalar, Size, TyAbiInterface, Variants};
 use smallvec::{smallvec, SmallVec};
-use tracing::debug;
 
 use std::fmt::Write;
 
index d2f2c7bf7988ad84ea14ffd0563c5961fb631c7c..e9171823c242c7c1be928306c1b50d76025066a4 100644 (file)
@@ -1173,13 +1173,6 @@ fn infer_from(
             // only the linker flavor is known; use the default linker for the selected flavor
             (None, Some(flavor)) => Some((
                 PathBuf::from(match flavor {
-                    LinkerFlavor::Em => {
-                        if cfg!(windows) {
-                            "emcc.bat"
-                        } else {
-                            "emcc"
-                        }
-                    }
                     LinkerFlavor::Gcc => {
                         if cfg!(any(target_os = "solaris", target_os = "illumos")) {
                             // On historical Solaris systems, "cc" may have
@@ -1194,11 +1187,17 @@ fn infer_from(
                         }
                     }
                     LinkerFlavor::Ld => "ld",
-                    LinkerFlavor::Msvc => "link.exe",
                     LinkerFlavor::Lld(_) => "lld",
-                    LinkerFlavor::PtxLinker => "rust-ptx-linker",
-                    LinkerFlavor::BpfLinker => "bpf-linker",
-                    LinkerFlavor::L4Bender => "l4-bender",
+                    LinkerFlavor::Msvc => "link.exe",
+                    LinkerFlavor::EmCc => {
+                        if cfg!(windows) {
+                            "emcc.bat"
+                        } else {
+                            "emcc"
+                        }
+                    }
+                    LinkerFlavor::Bpf => "bpf-linker",
+                    LinkerFlavor::Ptx => "rust-ptx-linker",
                 }),
                 flavor,
             )),
@@ -1208,7 +1207,7 @@ fn infer_from(
                 });
 
                 let flavor = if stem == "emcc" {
-                    LinkerFlavor::Em
+                    LinkerFlavor::EmCc
                 } else if stem == "gcc"
                     || stem.ends_with("-gcc")
                     || stem == "clang"
@@ -1236,7 +1235,8 @@ fn infer_from(
 
     // linker and linker flavor specified via command line have precedence over what the target
     // specification specifies
-    if let Some(ret) = infer_from(sess, sess.opts.cg.linker.clone(), sess.opts.cg.linker_flavor) {
+    let linker_flavor = sess.opts.cg.linker_flavor.map(LinkerFlavor::from_cli);
+    if let Some(ret) = infer_from(sess, sess.opts.cg.linker.clone(), linker_flavor) {
         return ret;
     }
 
@@ -2113,11 +2113,11 @@ fn add_order_independent_options(
         });
     }
 
-    if flavor == LinkerFlavor::PtxLinker {
+    if flavor == LinkerFlavor::Ptx {
         // Provide the linker with fallback to internal `target-cpu`.
         cmd.arg("--fallback-arch");
         cmd.arg(&codegen_results.crate_info.target_cpu);
-    } else if flavor == LinkerFlavor::BpfLinker {
+    } else if flavor == LinkerFlavor::Bpf {
         cmd.arg("--cpu");
         cmd.arg(&codegen_results.crate_info.target_cpu);
         cmd.arg("--cpu-features");
@@ -2797,20 +2797,24 @@ fn add_gcc_ld_path(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
         if let LinkerFlavor::Gcc = flavor {
             match ld_impl {
                 LdImpl::Lld => {
-                    let tools_path = sess.get_tools_search_paths(false);
-                    let gcc_ld_dir = tools_path
-                        .into_iter()
-                        .map(|p| p.join("gcc-ld"))
-                        .find(|p| {
-                            p.join(if sess.host.is_like_windows { "ld.exe" } else { "ld" }).exists()
-                        })
-                        .unwrap_or_else(|| sess.fatal("rust-lld (as ld) not found"));
-                    cmd.arg({
-                        let mut arg = OsString::from("-B");
-                        arg.push(gcc_ld_dir);
-                        arg
-                    });
-                    cmd.arg(format!("-Wl,-rustc-lld-flavor={}", sess.target.lld_flavor.as_str()));
+                    // Implement the "self-contained" part of -Zgcc-ld
+                    // by adding rustc distribution directories to the tool search path.
+                    for path in sess.get_tools_search_paths(false) {
+                        cmd.arg({
+                            let mut arg = OsString::from("-B");
+                            arg.push(path.join("gcc-ld"));
+                            arg
+                        });
+                    }
+                    // Implement the "linker flavor" part of -Zgcc-ld
+                    // by asking cc to use some kind of lld.
+                    cmd.arg("-fuse-ld=lld");
+                    if sess.target.lld_flavor != LldFlavor::Ld {
+                        // Tell clang to use a non-default LLD flavor.
+                        // Gcc doesn't understand the target option, but we currently assume
+                        // that gcc is not used for Apple and Wasm targets (#97402).
+                        cmd.arg(format!("--target={}", sess.target.llvm_target));
+                    }
                 }
             }
         } else {
index ce51b2e9531fcedbe1520bb18736badb692a4de9..8c6f526b054bc5ec213eddf5fac9d8505029d9d5 100644 (file)
@@ -126,29 +126,26 @@ pub fn get_linker<'a>(
     // to the linker args construction.
     assert!(cmd.get_args().is_empty() || sess.target.vendor == "uwp");
     match flavor {
-        LinkerFlavor::Lld(LldFlavor::Link) | LinkerFlavor::Msvc => {
-            Box::new(MsvcLinker { cmd, sess }) as Box<dyn Linker>
-        }
-        LinkerFlavor::Em => Box::new(EmLinker { cmd, sess }) as Box<dyn Linker>,
         LinkerFlavor::Gcc => {
             Box::new(GccLinker { cmd, sess, target_cpu, hinted_static: false, is_ld: false })
                 as Box<dyn Linker>
         }
-
+        LinkerFlavor::Ld if sess.target.os == "l4re" => {
+            Box::new(L4Bender::new(cmd, sess)) as Box<dyn Linker>
+        }
         LinkerFlavor::Lld(LldFlavor::Ld)
         | LinkerFlavor::Lld(LldFlavor::Ld64)
         | LinkerFlavor::Ld => {
             Box::new(GccLinker { cmd, sess, target_cpu, hinted_static: false, is_ld: true })
                 as Box<dyn Linker>
         }
-
+        LinkerFlavor::Lld(LldFlavor::Link) | LinkerFlavor::Msvc => {
+            Box::new(MsvcLinker { cmd, sess }) as Box<dyn Linker>
+        }
         LinkerFlavor::Lld(LldFlavor::Wasm) => Box::new(WasmLd::new(cmd, sess)) as Box<dyn Linker>,
-
-        LinkerFlavor::PtxLinker => Box::new(PtxLinker { cmd, sess }) as Box<dyn Linker>,
-
-        LinkerFlavor::BpfLinker => Box::new(BpfLinker { cmd, sess }) as Box<dyn Linker>,
-
-        LinkerFlavor::L4Bender => Box::new(L4Bender::new(cmd, sess)) as Box<dyn Linker>,
+        LinkerFlavor::EmCc => Box::new(EmLinker { cmd, sess }) as Box<dyn Linker>,
+        LinkerFlavor::Bpf => Box::new(BpfLinker { cmd, sess }) as Box<dyn Linker>,
+        LinkerFlavor::Ptx => Box::new(PtxLinker { cmd, sess }) as Box<dyn Linker>,
     }
 }
 
index 4c6be3f910827d7886b48e2ebbada31c3d701a86..6e482062383d451884f06dd08dbe887dd2b73274 100644 (file)
@@ -389,15 +389,14 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
 
     let main_llfn = cx.get_fn_addr(instance);
 
-    let use_start_lang_item = EntryFnType::Start != entry_type;
-    let entry_fn = create_entry_fn::<Bx>(cx, main_llfn, main_def_id, use_start_lang_item);
+    let entry_fn = create_entry_fn::<Bx>(cx, main_llfn, main_def_id, entry_type);
     return Some(entry_fn);
 
     fn create_entry_fn<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
         cx: &'a Bx::CodegenCx,
         rust_main: Bx::Value,
         rust_main_def_id: DefId,
-        use_start_lang_item: bool,
+        entry_type: EntryFnType,
     ) -> Bx::Function {
         // The entry function is either `int main(void)` or `int main(int argc, char **argv)`,
         // depending on whether the target needs `argc` and `argv` to be passed in.
@@ -442,7 +441,7 @@ fn create_entry_fn<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
         let i8pp_ty = cx.type_ptr_to(cx.type_i8p());
         let (arg_argc, arg_argv) = get_argc_argv(cx, &mut bx);
 
-        let (start_fn, start_ty, args) = if use_start_lang_item {
+        let (start_fn, start_ty, args) = if let EntryFnType::Main { sigpipe } = entry_type {
             let start_def_id = cx.tcx().require_lang_item(LangItem::Start, None);
             let start_fn = cx.get_fn_addr(
                 ty::Instance::resolve(
@@ -454,8 +453,13 @@ fn create_entry_fn<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
                 .unwrap()
                 .unwrap(),
             );
-            let start_ty = cx.type_func(&[cx.val_ty(rust_main), isize_ty, i8pp_ty], isize_ty);
-            (start_fn, start_ty, vec![rust_main, arg_argc, arg_argv])
+
+            let i8_ty = cx.type_i8();
+            let arg_sigpipe = bx.const_u8(sigpipe);
+
+            let start_ty =
+                cx.type_func(&[cx.val_ty(rust_main), isize_ty, i8pp_ty, i8_ty], isize_ty);
+            (start_fn, start_ty, vec![rust_main, arg_argc, arg_argv, arg_sigpipe])
         } else {
             debug!("using user-defined start fn");
             let start_ty = cx.type_func(&[isize_ty, i8pp_ty], isize_ty);
index 5c67d3b6431fd5f346438bde0fe17ecb19904f72..3154f12a77964b2baacf13fb5f70718368e67073 100644 (file)
@@ -13,8 +13,7 @@
 use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_hir::lang_items::LangItem;
 use rustc_index::vec::Idx;
-use rustc_middle::mir::AssertKind;
-use rustc_middle::mir::{self, SwitchTargets};
+use rustc_middle::mir::{self, AssertKind, SwitchTargets};
 use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
 use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
 use rustc_middle::ty::{self, Instance, Ty, TypeVisitable};
index b46f71fc78a3b9164919ce9c3e2097e7764875d9..a2f14e753aebe7ca5cb6bf7b049123f7c746ff5d 100644 (file)
@@ -197,7 +197,7 @@ pub(super) fn op_to_const<'tcx>(
     }
 }
 
-#[instrument(skip(tcx), level = "debug")]
+#[instrument(skip(tcx), level = "debug", ret)]
 pub(crate) fn turn_into_const_value<'tcx>(
     tcx: TyCtxt<'tcx>,
     constant: ConstAlloc<'tcx>,
@@ -224,10 +224,7 @@ pub(crate) fn turn_into_const_value<'tcx>(
     );
 
     // Turn this into a proper constant.
-    let const_val = op_to_const(&ecx, &mplace.into());
-    debug!(?const_val);
-
-    const_val
+    op_to_const(&ecx, &mplace.into())
 }
 
 #[instrument(skip(tcx), level = "debug")]
index 9ea9fbe0e0e54188260281048bf8bfd11edfc308..6e5c840bdfd6a7bca628508b6366c6d54a8f1e60 100644 (file)
@@ -35,21 +35,7 @@ fn hook_special_const_fn(
         // All `#[rustc_do_not_const_check]` functions should be hooked here.
         let def_id = instance.def_id();
 
-        if Some(def_id) == self.tcx.lang_items().const_eval_select() {
-            // redirect to const_eval_select_ct
-            if let Some(const_eval_select) = self.tcx.lang_items().const_eval_select_ct() {
-                return Ok(Some(
-                    ty::Instance::resolve(
-                        *self.tcx,
-                        ty::ParamEnv::reveal_all(),
-                        const_eval_select,
-                        instance.substs,
-                    )
-                    .unwrap()
-                    .unwrap(),
-                ));
-            }
-        } else if Some(def_id) == self.tcx.lang_items().panic_display()
+        if Some(def_id) == self.tcx.lang_items().panic_display()
             || Some(def_id) == self.tcx.lang_items().begin_panic_fn()
         {
             // &str or &&str
index 373b139c86e424d941b779aaddbe7e5912db6301..8b7c3cf3377cc9108bc7a9e9f1f7f4763b35cdf8 100644 (file)
@@ -204,7 +204,7 @@ fn get_info_on_unsized_field<'tcx>(
     (unsized_inner_ty, num_elems)
 }
 
-#[instrument(skip(ecx), level = "debug")]
+#[instrument(skip(ecx), level = "debug", ret)]
 fn create_pointee_place<'tcx>(
     ecx: &mut CompileTimeEvalContext<'tcx, 'tcx>,
     ty: Ty<'tcx>,
@@ -237,14 +237,11 @@ fn create_pointee_place<'tcx>(
         let ptr = ecx.allocate_ptr(size, align, MemoryKind::Stack).unwrap();
         debug!(?ptr);
 
-        let place = MPlaceTy::from_aligned_ptr_with_meta(
+        MPlaceTy::from_aligned_ptr_with_meta(
             ptr.into(),
             layout,
             MemPlaceMeta::Meta(Scalar::from_machine_usize(num_elems as u64, &tcx)),
-        );
-        debug!(?place);
-
-        place
+        )
     } else {
         create_mplace_from_layout(ecx, ty)
     }
@@ -253,7 +250,7 @@ fn create_pointee_place<'tcx>(
 /// Converts a `ValTree` to a `ConstValue`, which is needed after mir
 /// construction has finished.
 // FIXME Merge `valtree_to_const_value` and `valtree_into_mplace` into one function
-#[instrument(skip(tcx), level = "debug")]
+#[instrument(skip(tcx), level = "debug", ret)]
 pub fn valtree_to_const_value<'tcx>(
     tcx: TyCtxt<'tcx>,
     param_env_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
@@ -294,7 +291,7 @@ pub fn valtree_to_const_value<'tcx>(
             dump_place(&ecx, place.into());
             intern_const_alloc_recursive(&mut ecx, InternKind::Constant, &place).unwrap();
 
-            let const_val = match ty.kind() {
+            match ty.kind() {
                 ty::Ref(_, _, _) => {
                     let ref_place = place.to_ref(&tcx);
                     let imm =
@@ -303,10 +300,7 @@ pub fn valtree_to_const_value<'tcx>(
                     op_to_const(&ecx, &imm.into())
                 }
                 _ => op_to_const(&ecx, &place.into()),
-            };
-            debug!(?const_val);
-
-            const_val
+            }
         }
         ty::Never
         | ty::Error(_)
index 66ab3f15716f2e5d7eb93782df478f32bf5f50e2..24dbc769529c3665a6e30da12c750226a21ffd19 100644 (file)
@@ -334,7 +334,7 @@ pub enum InternKind {
 /// tracks where in the value we are and thus can show much better error messages.
 /// Any errors here would anyway be turned into `const_err` lints, whereas validation failures
 /// are hard errors.
-#[tracing::instrument(level = "debug", skip(ecx))]
+#[instrument(level = "debug", skip(ecx))]
 pub fn intern_const_alloc_recursive<
     'mir,
     'tcx: 'mir,
index 5aabb14fba88454bc55bbf7c824e52d5a456a95a..530e252b7c077ed0a0f4d0cfdb2c0d5c3357a62b 100644 (file)
@@ -6,6 +6,7 @@
 use std::fmt::Debug;
 use std::hash::Hash;
 
+use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_middle::mir;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::def_id::DefId;
@@ -323,6 +324,15 @@ fn adjust_allocation<'b>(
         kind: Option<MemoryKind<Self::MemoryKind>>,
     ) -> InterpResult<'tcx, Cow<'b, Allocation<Self::Provenance, Self::AllocExtra>>>;
 
+    fn eval_inline_asm(
+        _ecx: &mut InterpCx<'mir, 'tcx, Self>,
+        _template: &'tcx [InlineAsmTemplatePiece],
+        _operands: &[mir::InlineAsmOperand<'tcx>],
+        _options: InlineAsmOptions,
+    ) -> InterpResult<'tcx> {
+        throw_unsup_format!("inline assembly is not supported")
+    }
+
     /// Hook for performing extra checks on a memory read access.
     ///
     /// Takes read-only access to the allocation so we can keep all the memory read
index ea366eba77245b90ec7a44dad831c7a3c68d60b4..50a82aa0e72c9c7fe55013f4f6e73cae8e55ba70 100644 (file)
@@ -1,5 +1,6 @@
 use std::borrow::Cow;
 
+use rustc_ast::ast::InlineAsmOptions;
 use rustc_middle::ty::layout::{FnAbiOf, LayoutOf};
 use rustc_middle::ty::Instance;
 use rustc_middle::{
@@ -166,8 +167,16 @@ pub(super) fn eval_terminator(
                 terminator.kind
             ),
 
-            // Inline assembly can't be interpreted.
-            InlineAsm { .. } => throw_unsup_format!("inline assembly is not supported"),
+            InlineAsm { template, ref operands, options, destination, .. } => {
+                M::eval_inline_asm(self, template, operands, options)?;
+                if options.contains(InlineAsmOptions::NORETURN) {
+                    throw_ub_format!("returned from noreturn inline assembly");
+                }
+                self.go_to_block(
+                    destination
+                        .expect("InlineAsm terminators without noreturn must have a destination"),
+                )
+            }
         }
 
         Ok(())
index 0382e2d5805aacb10148c56487e9694aa609a0bc..14aaee6ac3f9ea1168dccb5c502aa6e90dc0c0b0 100644 (file)
@@ -5,7 +5,7 @@
 //! to be const-safe.
 
 use std::convert::TryFrom;
-use std::fmt::Write;
+use std::fmt::{Display, Write};
 use std::num::NonZeroUsize;
 
 use rustc_ast::Mutability;
@@ -311,7 +311,7 @@ fn with_elem<R>(
     fn read_immediate(
         &self,
         op: &OpTy<'tcx, M::Provenance>,
-        expected: &str,
+        expected: impl Display,
     ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
         Ok(try_validation!(
             self.ecx.read_immediate(op),
@@ -323,7 +323,7 @@ fn read_immediate(
     fn read_scalar(
         &self,
         op: &OpTy<'tcx, M::Provenance>,
-        expected: &str,
+        expected: impl Display,
     ) -> InterpResult<'tcx, Scalar<M::Provenance>> {
         Ok(self.read_immediate(op, expected)?.to_scalar())
     }
@@ -368,7 +368,8 @@ fn check_safe_pointer(
         value: &OpTy<'tcx, M::Provenance>,
         kind: &str,
     ) -> InterpResult<'tcx> {
-        let place = self.ecx.ref_to_mplace(&self.read_immediate(value, &format!("a {kind}"))?)?;
+        let place =
+            self.ecx.ref_to_mplace(&self.read_immediate(value, format_args!("a {kind}"))?)?;
         // Handle wide pointers.
         // Check metadata early, for better diagnostics
         if place.layout.is_unsized() {
index b662513e70fbe6ee0d57ec27d50c651bd691c5c1..b798862583952eb5d1604a56750c14850ac8c6ab 100644 (file)
@@ -181,16 +181,23 @@ fn mir_assign_valid_types(&self, src: Ty<'tcx>, dest: Ty<'tcx>) -> bool {
         if (src, dest).has_opaque_types() {
             return true;
         }
-        // Normalize projections and things like that.
-        let param_env = self.param_env.with_reveal_all_normalized(self.tcx);
-        let src = self.tcx.normalize_erasing_regions(param_env, src);
-        let dest = self.tcx.normalize_erasing_regions(param_env, dest);
 
+        // Normalize projections and things like that.
         // Type-changing assignments can happen when subtyping is used. While
         // all normal lifetimes are erased, higher-ranked types with their
         // late-bound lifetimes are still around and can lead to type
         // differences. So we compare ignoring lifetimes.
-        equal_up_to_regions(self.tcx, param_env, src, dest)
+
+        // First, try with reveal_all. This might not work in some cases, as the predicates
+        // can be cleared in reveal_all mode. We try the reveal first anyways as it is used
+        // by some other passes like inlining as well.
+        let param_env = self.param_env.with_reveal_all_normalized(self.tcx);
+        if equal_up_to_regions(self.tcx, param_env, src, dest) {
+            return true;
+        }
+
+        // If this fails, we can try it without the reveal.
+        equal_up_to_regions(self.tcx, self.param_env, src, dest)
     }
 }
 
index 4570c1448337eec7b661868deb0d81d64f219916..d1d02ed73f9595a3847d38d96eb8665fc56badbc 100644 (file)
@@ -7,7 +7,7 @@ edition = "2021"
 crate-type = ["dylib"]
 
 [dependencies]
-tracing = { version = "0.1.28" }
+tracing = { version = "0.1.35" }
 serde_json = "1.0.59"
 rustc_log = { path = "../rustc_log" }
 rustc_middle = { path = "../rustc_middle" }
index 27ad3e453660188727a674a59593a4cf71d39397..7f9918e4f128f393f5ff626fdc5f920054ff19e6 100644 (file)
@@ -354,6 +354,12 @@ lint_builtin_unreachable_pub = unreachable `pub` {$what}
     .suggestion = consider restricting its visibility
     .help = or consider exporting it for use by other crates
 
+lint_builtin_unexpected_cli_config_name = unexpected `{$name}` as condition name
+    .help = was set with `--cfg` but isn't in the `--check-cfg` expected names
+
+lint_builtin_unexpected_cli_config_value = unexpected condition value `{$value}` for condition name `{$name}`
+    .help = was set with `--cfg` but isn't in the `--check-cfg` expected values
+
 lint_builtin_type_alias_bounds_help = use fully disambiguated paths (i.e., `<T as Trait>::Assoc`) to refer to associated types in type aliases
 
 lint_builtin_type_alias_where_clause = where clauses are not enforced in type aliases
diff --git a/compiler/rustc_error_messages/locales/en-US/metadata.ftl b/compiler/rustc_error_messages/locales/en-US/metadata.ftl
new file mode 100644 (file)
index 0000000..00067a1
--- /dev/null
@@ -0,0 +1,272 @@
+metadata_rlib_required =
+    crate `{$crate_name}` required to be available in rlib format, but was not found in this form
+
+metadata_lib_required =
+    crate `{$crate_name}` required to be available in {$kind} format, but was not found in this form
+
+metadata_crate_dep_multiple =
+    cannot satisfy dependencies so `{$crate_name}` only shows up once
+    .help = having upstream crates all available in one format will likely make this go away
+
+metadata_two_panic_runtimes =
+    cannot link together two panic runtimes: {$prev_name} and {$cur_name}
+
+metadata_bad_panic_strategy =
+    the linked panic runtime `{$runtime}` is not compiled with this crate's panic strategy `{$strategy}`
+
+metadata_required_panic_strategy =
+    the crate `{$crate_name}` requires panic strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}`
+
+metadata_incompatible_panic_in_drop_strategy =
+    the crate `{$crate_name}` is compiled with the panic-in-drop strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}`
+
+metadata_multiple_names_in_link =
+    multiple `name` arguments in a single `#[link]` attribute
+
+metadata_multiple_kinds_in_link =
+    multiple `kind` arguments in a single `#[link]` attribute
+
+metadata_link_name_form =
+    link name must be of the form `name = "string"`
+
+metadata_link_kind_form =
+    link kind must be of the form `kind = "string"`
+
+metadata_link_modifiers_form =
+    link modifiers must be of the form `modifiers = "string"`
+
+metadata_link_cfg_form =
+    link cfg must be of the form `cfg(/* predicate */)`
+
+metadata_wasm_import_form =
+    wasm import module must be of the form `wasm_import_module = "string"`
+
+metadata_empty_link_name =
+    link name must not be empty
+    .label = empty link name
+
+metadata_link_framework_apple =
+    link kind `framework` is only supported on Apple targets
+
+metadata_framework_only_windows =
+    link kind `raw-dylib` is only supported on Windows targets
+
+metadata_unknown_link_kind =
+    unknown link kind `{$kind}`, expected one of: static, dylib, framework, raw-dylib
+    .label = unknown link kind
+
+metadata_multiple_link_modifiers =
+    multiple `modifiers` arguments in a single `#[link]` attribute
+
+metadata_multiple_cfgs =
+    multiple `cfg` arguments in a single `#[link]` attribute
+
+metadata_link_cfg_single_predicate =
+    link cfg must have a single predicate argument
+
+metadata_multiple_wasm_import =
+    multiple `wasm_import_module` arguments in a single `#[link]` attribute
+
+metadata_unexpected_link_arg =
+    unexpected `#[link]` argument, expected one of: name, kind, modifiers, cfg, wasm_import_module, import_name_type
+
+metadata_invalid_link_modifier =
+    invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed
+
+metadata_multiple_modifiers =
+    multiple `{$modifier}` modifiers in a single `modifiers` argument
+
+metadata_bundle_needs_static =
+    linking modifier `bundle` is only compatible with `static` linking kind
+
+metadata_whole_archive_needs_static =
+    linking modifier `whole-archive` is only compatible with `static` linking kind
+
+metadata_as_needed_compatibility =
+    linking modifier `as-needed` is only compatible with `dylib` and `framework` linking kinds
+
+metadata_unknown_link_modifier =
+    unknown linking modifier `{$modifier}`, expected one of: bundle, verbatim, whole-archive, as-needed
+
+metadata_incompatible_wasm_link =
+    `wasm_import_module` is incompatible with other arguments in `#[link]` attributes
+
+metadata_link_requires_name =
+    `#[link]` attribute requires a `name = "string"` argument
+    .label = missing `name` argument
+
+metadata_raw_dylib_no_nul =
+    link name must not contain NUL characters if link kind is `raw-dylib`
+
+metadata_link_ordinal_raw_dylib =
+    `#[link_ordinal]` is only supported if link kind is `raw-dylib`
+
+metadata_lib_framework_apple =
+    library kind `framework` is only supported on Apple targets
+
+metadata_empty_renaming_target =
+    an empty renaming target was specified for library `{$lib_name}`
+
+metadata_renaming_no_link =
+    renaming of the library `{$lib_name}` was specified, however this crate contains no `#[link(...)]` attributes referencing this library
+
+metadata_multiple_renamings =
+    multiple renamings were specified for library `{$lib_name}`
+
+metadata_no_link_mod_override =
+    overriding linking modifiers from command line is not supported
+
+metadata_unsupported_abi_i686 =
+    ABI not supported by `#[link(kind = "raw-dylib")]` on i686
+
+metadata_unsupported_abi =
+    ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture
+
+metadata_fail_create_file_encoder =
+    failed to create file encoder: {$err}
+
+metadata_fail_seek_file =
+    failed to seek the file: {$err}
+
+metadata_fail_write_file =
+    failed to write to the file: {$err}
+
+metadata_crate_not_panic_runtime =
+    the crate `{$crate_name}` is not a panic runtime
+
+metadata_no_panic_strategy =
+    the crate `{$crate_name}` does not have the panic strategy `{$strategy}`
+
+metadata_profiler_builtins_needs_core =
+    `profiler_builtins` crate (required by compiler options) is not compatible with crate attribute `#![no_core]`
+
+metadata_not_profiler_runtime =
+    the crate `{$crate_name}` is not a profiler runtime
+
+metadata_no_multiple_global_alloc =
+    cannot define multiple global allocators
+    .label = cannot define a new global allocator
+
+metadata_prev_global_alloc =
+    previous global allocator defined here
+
+metadata_conflicting_global_alloc =
+    the `#[global_allocator]` in {$other_crate_name} conflicts with global allocator in: {$crate_name}
+
+metadata_global_alloc_required =
+    no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait
+
+metadata_no_transitive_needs_dep =
+    the crate `{$crate_name}` cannot depend on a crate that needs {$needs_crate_name}, but it depends on `{$deps_crate_name}`
+
+metadata_failed_write_error =
+    failed to write {$filename}: {$err}
+
+metadata_failed_create_tempdir =
+    couldn't create a temp dir: {$err}
+
+metadata_failed_create_file =
+    failed to create the file {$filename}: {$err}
+
+metadata_failed_create_encoded_metadata =
+    failed to create encoded metadata from file: {$err}
+
+metadata_non_ascii_name =
+    cannot load a crate with a non-ascii name `{$crate_name}`
+
+metadata_extern_location_not_exist =
+    extern location for {$crate_name} does not exist: {$location}
+
+metadata_extern_location_not_file =
+    extern location for {$crate_name} is not a file: {$location}
+
+metadata_multiple_candidates =
+    multiple {$flavor} candidates for `{$crate_name}` found
+
+metadata_multiple_matching_crates =
+    multiple matching crates for `{$crate_name}`
+    .note = candidates:{$candidates}
+
+metadata_symbol_conflicts_current =
+    the current crate is indistinguishable from one of its dependencies: it has the same crate-name `{$crate_name}` and was compiled with the same `-C metadata` arguments. This will result in symbol conflicts between the two.
+
+metadata_symbol_conflicts_others =
+    found two different crates with name `{$crate_name}` that are not distinguished by differing `-C metadata`. This will result in symbol conflicts between the two.
+
+metadata_stable_crate_id_collision =
+    found crates (`{$crate_name0}` and `{$crate_name1}`) with colliding StableCrateId values.
+
+metadata_dl_error =
+    {$err}
+
+metadata_newer_crate_version =
+    found possibly newer version of crate `{$crate_name}`{$add_info}
+    .note = perhaps that crate needs to be recompiled?
+
+metadata_found_crate_versions =
+    the following crate versions were found:{$found_crates}
+
+metadata_no_crate_with_triple =
+    couldn't find crate `{$crate_name}` with expected target triple {$locator_triple}{$add_info}
+
+metadata_found_staticlib =
+    found staticlib `{$crate_name}` instead of rlib or dylib{$add_info}
+    .help = please recompile that crate using --crate-type lib
+
+metadata_incompatible_rustc =
+    found crate `{$crate_name}` compiled by an incompatible version of rustc{$add_info}
+    .help = please recompile that crate using this compiler ({$rustc_version}) (consider running `cargo clean` first)
+
+metadata_invalid_meta_files =
+    found invalid metadata files for crate `{$crate_name}`{$add_info}
+
+metadata_cannot_find_crate =
+    can't find crate for `{$crate_name}`{$add_info}
+
+metadata_no_dylib_plugin =
+    plugin `{$crate_name}` only found in rlib format, but must be available in dylib format
+
+metadata_target_not_installed =
+    the `{$locator_triple}` target may not be installed
+
+metadata_target_no_std_support =
+    the `{$locator_triple}` target may not support the standard library
+
+metadata_consider_downloading_target =
+    consider downloading the target with `rustup target add {$locator_triple}`
+
+metadata_std_required =
+    `std` is required by `{$current_crate}` because it does not declare `#![no_std]`
+
+metadata_consider_building_std =
+    consider building the standard library from source with `cargo build -Zbuild-std`
+
+metadata_compiler_missing_profiler =
+    the compiler may have been built without the profiler runtime
+
+metadata_install_missing_components =
+    maybe you need to install the missing components with: `rustup component add rust-src rustc-dev llvm-tools-preview`
+
+metadata_cant_find_crate =
+    can't find crate
+
+metadata_crate_location_unknown_type =
+    extern location for {$crate_name} is of an unknown type: {$path}
+
+metadata_lib_filename_form =
+    file name should be lib*.rlib or {dll_prefix}*.{dll_suffix}
+
+metadata_multiple_import_name_type =
+    multiple `import_name_type` arguments in a single `#[link]` attribute
+
+metadata_import_name_type_form =
+    import name type must be of the form `import_name_type = "string"`
+
+metadata_import_name_type_x86 =
+    import name type is only supported on x86
+
+metadata_unknown_import_name_type =
+    unknown import name type `{$import_name_type}`, expected one of: decorated, noprefix, undecorated
+
+metadata_import_name_type_raw =
+    import name type can only be used with link kind `raw-dylib`
index 223092a74bd97cf00d62ed229dcbae3493e985c4..da987152ff66030dcdbba447d15dce67950c45b9 100644 (file)
@@ -11,6 +11,8 @@ privacy_in_public_interface = {$vis_descr} {$kind} `{$descr}` in public interfac
     .label = can't leak {$vis_descr} {$kind}
     .visibility_label = `{$descr}` declared as {$vis_descr}
 
+privacy_report_access_level = {$descr}
+
 privacy_from_private_dep_in_public_interface =
     {$kind} `{$descr}` from private dependency '{$krate}' in public interface
 
diff --git a/compiler/rustc_error_messages/locales/en-US/trait_selection.ftl b/compiler/rustc_error_messages/locales/en-US/trait_selection.ftl
new file mode 100644 (file)
index 0000000..004e0ab
--- /dev/null
@@ -0,0 +1,26 @@
+trait_selection_dump_vtable_entries = vtable entries for `{$trait_ref}`: {$entries}
+
+trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated}
+
+trait_selection_auto_deref_reached_recursion_limit = reached the recursion limit while auto-dereferencing `{$ty}`
+    .label = deref recursion limit reached
+    .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
+
+trait_selection_empty_on_clause_in_rustc_on_unimplemented = empty `on`-clause in `#[rustc_on_unimplemented]`
+    .label = empty on-clause here
+
+trait_selection_invalid_on_clause_in_rustc_on_unimplemented = invalid `on`-clause in `#[rustc_on_unimplemented]`
+    .label = invalid on-clause here
+
+trait_selection_no_value_in_rustc_on_unimplemented = this attribute must have a valid value
+    .label = expected value here
+    .note = eg `#[rustc_on_unimplemented(message="foo")]`
+
+trait_selection_negative_positive_conflict = found both positive and negative implementation of trait `{$trait_desc}`{$self_desc ->
+        [none] {""}
+       *[default] {" "}for type `{$self_desc}`
+    }:
+    .negative_implementation_here = negative implementation here
+    .negative_implementation_in_crate = negative implementation in crate `{$negative_impl_cname}`
+    .positive_implementation_here = positive implementation here
+    .positive_implementation_in_crate = positive implementation in crate `{$positive_impl_cname}`
index ebd56b4e084d9529503d0107476bc68e1e9e00fc..b6e0f3faa73cb919c48269c2131572dddbdff448 100644 (file)
@@ -5,6 +5,9 @@
 #![deny(rustc::untranslatable_diagnostic)]
 #![deny(rustc::diagnostic_outside_of_impl)]
 
+#[macro_use]
+extern crate tracing;
+
 use fluent_bundle::FluentResource;
 use fluent_syntax::parser::ParserError;
 use rustc_data_structures::sync::Lrc;
@@ -16,7 +19,6 @@
 use std::fs;
 use std::io;
 use std::path::{Path, PathBuf};
-use tracing::{instrument, trace};
 
 #[cfg(not(parallel_compiler))]
 use std::cell::LazyCell as Lazy;
     lint => "../locales/en-US/lint.ftl",
     middle => "../locales/en-US/middle.ftl",
     monomorphize => "../locales/en-US/monomorphize.ftl",
+    metadata => "../locales/en-US/metadata.ftl",
     parser => "../locales/en-US/parser.ftl",
     passes => "../locales/en-US/passes.ftl",
     plugin_impl => "../locales/en-US/plugin_impl.ftl",
     privacy => "../locales/en-US/privacy.ftl",
     query_system => "../locales/en-US/query_system.ftl",
+    trait_selection => "../locales/en-US/trait_selection.ftl",
     save_analysis => "../locales/en-US/save_analysis.ftl",
     ty_utils => "../locales/en-US/ty_utils.ftl",
     typeck => "../locales/en-US/typeck.ftl",
index 36805aa874fe7740961f1740f80317f74556e02e..4d207fd17fb2dfb9b2f16d3e9a9fa9f8a2a023f4 100644 (file)
@@ -15,13 +15,14 @@ rustc_macros = { path = "../rustc_macros" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_lint_defs = { path = "../rustc_lint_defs" }
+rustc_target = { path = "../rustc_target" }
 unicode-width = "0.1.4"
 atty = "0.2"
 termcolor = "1.0"
 annotate-snippets = "0.9"
 termize = "0.1.1"
-serde = { version = "1.0.125", features = ["derive"] }
+serde = { version = "1.0.125", features = [ "derive" ] }
 serde_json = "1.0.59"
 
 [target.'cfg(windows)'.dependencies]
-winapi = { version = "0.3", features = ["handleapi", "synchapi", "winbase"] }
+winapi = { version = "0.3", features = [ "handleapi", "synchapi", "winbase" ] }
index 95ae9765a4816fcd7a44102fb21c06545b69c962..a052aaee047567610702f244baf0a1910f193464 100644 (file)
@@ -10,6 +10,7 @@
 use rustc_span::edition::LATEST_STABLE_EDITION;
 use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent, Symbol};
 use rustc_span::{edition::Edition, Span, DUMMY_SP};
+use rustc_target::spec::PanicStrategy;
 use std::borrow::Cow;
 use std::fmt;
 use std::hash::{Hash, Hasher};
@@ -144,6 +145,12 @@ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
     }
 }
 
+impl IntoDiagnosticArg for PanicStrategy {
+    fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+        DiagnosticArgValue::Str(Cow::Owned(self.desc().to_string()))
+    }
+}
+
 impl<'source> Into<FluentValue<'source>> for DiagnosticArgValue<'source> {
     fn into(self) -> FluentValue<'source> {
         match self {
index 61d767a1cc6b4f97d806c45b8a0d3a127ec2d59a..7e29dc207accecca9a86275ec477cb9426c2b087 100644 (file)
@@ -12,7 +12,6 @@
 use std::marker::PhantomData;
 use std::ops::{Deref, DerefMut};
 use std::thread::panicking;
-use tracing::debug;
 
 /// Used for emitting structured error messages and other diagnostic information.
 ///
index 6c1bfcb9919eb9df89a3124f90bf16a655da2645..e79ce11a6fc075a8bdf162f7b63256b066c89a29 100644 (file)
@@ -34,7 +34,6 @@
 use std::path::Path;
 use termcolor::{Ansi, BufferWriter, ColorChoice, ColorSpec, StandardStream};
 use termcolor::{Buffer, Color, WriteColor};
-use tracing::*;
 
 /// Default column width, used in tests and when terminal dimensions cannot be determined.
 const DEFAULT_COLUMN_WIDTH: usize = 140;
index c4890b4a9c41378e14fdc07cf4ae6a2f883a9a45..cf2c023c2f89f3de35ffb9c5c2d43bd1a2be728f 100644 (file)
@@ -178,8 +178,7 @@ pub fn stmt_let_ty(
         ex: P<ast::Expr>,
     ) -> ast::Stmt {
         let pat = if mutbl {
-            let binding_mode = ast::BindingMode::ByValue(ast::Mutability::Mut);
-            self.pat_ident_binding_mode(sp, ident, binding_mode)
+            self.pat_ident_binding_mode(sp, ident, ast::BindingAnnotation::MUT)
         } else {
             self.pat_ident(sp, ident)
         };
@@ -445,17 +444,16 @@ pub fn pat_lit(&self, span: Span, expr: P<ast::Expr>) -> P<ast::Pat> {
         self.pat(span, PatKind::Lit(expr))
     }
     pub fn pat_ident(&self, span: Span, ident: Ident) -> P<ast::Pat> {
-        let binding_mode = ast::BindingMode::ByValue(ast::Mutability::Not);
-        self.pat_ident_binding_mode(span, ident, binding_mode)
+        self.pat_ident_binding_mode(span, ident, ast::BindingAnnotation::NONE)
     }
 
     pub fn pat_ident_binding_mode(
         &self,
         span: Span,
         ident: Ident,
-        bm: ast::BindingMode,
+        ann: ast::BindingAnnotation,
     ) -> P<ast::Pat> {
-        let pat = PatKind::Ident(bm, ident.with_span_pos(span), None);
+        let pat = PatKind::Ident(ann, ident.with_span_pos(span), None);
         self.pat(span, pat)
     }
     pub fn pat_path(&self, span: Span, path: ast::Path) -> P<ast::Pat> {
index 75dcbd69674d652c5897b8db9c596fc74307eabc..ac0e200b1b73ee783e22affe3e6b48ab2b4a435f 100644 (file)
@@ -15,6 +15,9 @@
 #[macro_use]
 extern crate rustc_macros;
 
+#[macro_use]
+extern crate tracing;
+
 extern crate proc_macro as pm;
 
 mod placeholders;
index 86dbd33a221f81c08b9d9ff6072814c411c69e90..7764ffd246e323d205c992bd61627c9652ce3b05 100644 (file)
@@ -32,7 +32,6 @@
 use std::borrow::Cow;
 use std::collections::hash_map::Entry;
 use std::{mem, slice};
-use tracing::debug;
 
 pub(crate) struct ParserAnyMacro<'a> {
     parser: Parser<'a>,
index e09c3ccbc75abdd9f873ab92e30c41c132e99455..f71b3d59e2c04cb8d41d5586bfe802d2156e258b 100644 (file)
@@ -519,6 +519,8 @@ pub fn set(&self, features: &mut Features, span: Span) {
     /// Allows creation of instances of a struct by moving fields that have
     /// not changed from prior instances of the same struct (RFC #2528)
     (active, type_changing_struct_update, "1.58.0", Some(86555), None),
+    /// Enables rustc to generate code that instructs libstd to NOT ignore SIGPIPE.
+    (active, unix_sigpipe, "CURRENT_RUSTC_VERSION", Some(97889), None),
     /// Allows unsized fn parameters.
     (active, unsized_fn_params, "1.49.0", Some(48055), None),
     /// Allows unsized rvalues at arguments and parameters.
index 0487270b52a9aaad0e0dce49ac753a2c8ba84b98..38a02cb1d7ce9f224e065897ae2b35f6caa464d9 100644 (file)
@@ -359,6 +359,7 @@ pub struct BuiltinAttribute {
     ),
 
     // Entry point:
+    gated!(unix_sigpipe, Normal, template!(Word, NameValueStr: "inherit|sig_ign|sig_dfl"), ErrorFollowing, experimental!(unix_sigpipe)),
     ungated!(start, Normal, template!(Word), WarnFollowing),
     ungated!(no_start, CrateLevel, template!(Word), WarnFollowing),
     ungated!(no_main, CrateLevel, template!(Word), WarnFollowing),
@@ -758,6 +759,7 @@ pub struct BuiltinAttribute {
     // Internal attributes, Testing:
     // ==========================================================================
 
+    rustc_attr!(TEST, rustc_access_level, Normal, template!(Word), WarnFollowing),
     rustc_attr!(TEST, rustc_outlives, Normal, template!(Word), WarnFollowing),
     rustc_attr!(TEST, rustc_capture_analysis, Normal, template!(Word), WarnFollowing),
     rustc_attr!(TEST, rustc_insignificant_dtor, Normal, template!(Word), WarnFollowing),
@@ -821,6 +823,14 @@ pub fn is_builtin_only_local(name: Symbol) -> bool {
     BUILTIN_ATTRIBUTE_MAP.get(&name).map_or(false, |attr| attr.only_local)
 }
 
+pub fn is_valid_for_get_attr(name: Symbol) -> bool {
+    BUILTIN_ATTRIBUTE_MAP.get(&name).map_or(false, |attr| match attr.duplicates {
+        WarnFollowing | ErrorFollowing | ErrorPreceding | FutureWarnFollowing
+        | FutureWarnPreceding => true,
+        DuplicatesOk | WarnFollowingWordOnly => false,
+    })
+}
+
 pub static BUILTIN_ATTRIBUTE_MAP: LazyLock<FxHashMap<Symbol, &BuiltinAttribute>> =
     LazyLock::new(|| {
         let mut map = FxHashMap::default();
index e44c9291f84838c7f66a152b05b211ee4d0171ac..bdaa0ee88eba19792cd89fdd7d5104ce271fdfe9 100644 (file)
@@ -151,7 +151,7 @@ pub fn find_feature_issue(feature: Symbol, issue: GateIssue) -> Option<NonZeroU3
 pub use builtin_attrs::AttributeDuplicates;
 pub use builtin_attrs::{
     deprecated_attributes, find_gated_cfg, is_builtin_attr_name, is_builtin_only_local,
-    AttributeGate, AttributeTemplate, AttributeType, BuiltinAttribute, GatedCfg,
-    BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP,
+    is_valid_for_get_attr, AttributeGate, AttributeTemplate, AttributeType, BuiltinAttribute,
+    GatedCfg, BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP,
 };
 pub use removed::{REMOVED_FEATURES, STABLE_REMOVED_FEATURES};
index 2d2648a8f35af5e586d70b998e4407a8e5251713..d5ac07f1e6315d23023a8679fca60331fa1d36c4 100644 (file)
@@ -308,6 +308,7 @@ pub enum Res<Id = hir::HirId> {
     ///
     /// **Belongs to the type namespace.**
     PrimTy(hir::PrimTy),
+
     /// The `Self` type, optionally with the [`DefId`] of the trait it belongs to and
     /// optionally with the [`DefId`] of the item introducing the `Self` type alias.
     ///
@@ -355,7 +356,8 @@ pub enum Res<Id = hir::HirId> {
     /// const fn baz<T>() -> usize { 10 }
     /// ```
     /// We do however allow `Self` in repeat expression even if it is generic to not break code
-    /// which already works on stable while causing the `const_evaluatable_unchecked` future compat lint:
+    /// which already works on stable while causing the `const_evaluatable_unchecked` future compat
+    /// lint:
     /// ```
     /// fn foo<T>() {
     ///     let _bar = [1_u8; std::mem::size_of::<*mut T>()];
@@ -370,6 +372,7 @@ pub enum Res<Id = hir::HirId> {
         /// from mentioning generics (i.e. when used in an anonymous constant).
         alias_to: Option<(DefId, bool)>,
     },
+
     /// A tool attribute module; e.g., the `rustfmt` in `#[rustfmt::skip]`.
     ///
     /// **Belongs to the type namespace.**
@@ -383,6 +386,7 @@ pub enum Res<Id = hir::HirId> {
     ///
     /// *See also [`Res::SelfTy`].*
     SelfCtor(DefId),
+
     /// A local variable or function parameter.
     ///
     /// **Belongs to the value namespace.**
index c2c551e78a41105af9ee32fe96fbabbd750a3b7e..d85ac960f9b2f10b415cb0a43d2eaa7de8bfc102 100644 (file)
@@ -15,7 +15,6 @@
 
 use std::fmt::{self, Write};
 use std::hash::Hash;
-use tracing::debug;
 
 /// The `DefPathTable` maps `DefIndex`es to `DefKey`s and vice versa.
 /// Internally the `DefPathTable` holds a tree of `DefKey`s, where each `DefKey`
index a069c49b0cc1eff6b8d8618a789bbcba1e0eba2b..50e7c5d2d04c8ba269584ac8d48001a3c2947ef6 100644 (file)
@@ -7,7 +7,7 @@
 use rustc_ast as ast;
 use rustc_ast::util::parser::ExprPrecedence;
 use rustc_ast::{Attribute, FloatTy, IntTy, Label, LitKind, TraitObjectSyntax, UintTy};
-pub use rustc_ast::{BorrowKind, ImplPolarity, IsAuto};
+pub use rustc_ast::{BindingAnnotation, BorrowKind, ByRef, ImplPolarity, IsAuto};
 pub use rustc_ast::{CaptureBy, Movability, Mutability};
 use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_data_structures::fingerprint::Fingerprint;
@@ -202,13 +202,8 @@ pub fn is_global(&self) -> bool {
 pub struct PathSegment<'hir> {
     /// The identifier portion of this path segment.
     pub ident: Ident,
-    // `id` and `res` are optional. We currently only use these in save-analysis,
-    // any path segments without these will not have save-analysis info and
-    // therefore will not have 'jump to def' in IDEs, but otherwise will not be
-    // affected. (In general, we don't bother to get the defs for synthesized
-    // segments, only for segments which have come from the AST).
-    pub hir_id: Option<HirId>,
-    pub res: Option<Res>,
+    pub hir_id: HirId,
+    pub res: Res,
 
     /// Type/lifetime parameters attached to this path. They come in
     /// two flavors: `Path<A,B,C>` and `Path(A,B) -> C`. Note that
@@ -226,12 +221,12 @@ pub struct PathSegment<'hir> {
 
 impl<'hir> PathSegment<'hir> {
     /// Converts an identifier to the corresponding segment.
-    pub fn from_ident(ident: Ident) -> PathSegment<'hir> {
-        PathSegment { ident, hir_id: None, res: None, infer_args: true, args: None }
+    pub fn new(ident: Ident, hir_id: HirId, res: Res) -> PathSegment<'hir> {
+        PathSegment { ident, hir_id, res, infer_args: true, args: None }
     }
 
     pub fn invalid() -> Self {
-        Self::from_ident(Ident::empty())
+        Self::new(Ident::empty(), HirId::INVALID, Res::Err)
     }
 
     pub fn args(&self) -> &GenericArgs<'hir> {
@@ -265,7 +260,7 @@ pub fn to_ty(&self) -> Ty<'_> {
 #[derive(Debug, HashStable_Generic)]
 pub enum GenericArg<'hir> {
     Lifetime(Lifetime),
-    Type(Ty<'hir>),
+    Type(&'hir Ty<'hir>),
     Const(ConstArg),
     Infer(InferArg),
 }
@@ -280,7 +275,7 @@ pub fn span(&self) -> Span {
         }
     }
 
-    pub fn id(&self) -> HirId {
+    pub fn hir_id(&self) -> HirId {
         match self {
             GenericArg::Lifetime(l) => l.hir_id,
             GenericArg::Type(t) => t.hir_id,
@@ -1049,30 +1044,6 @@ pub struct PatField<'hir> {
     pub span: Span,
 }
 
-/// Explicit binding annotations given in the HIR for a binding. Note
-/// that this is not the final binding *mode* that we infer after type
-/// inference.
-#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
-pub enum BindingAnnotation {
-    /// No binding annotation given: this means that the final binding mode
-    /// will depend on whether we have skipped through a `&` reference
-    /// when matching. For example, the `x` in `Some(x)` will have binding
-    /// mode `None`; if you do `let Some(x) = &Some(22)`, it will
-    /// ultimately be inferred to be by-reference.
-    ///
-    /// Note that implicit reference skipping is not implemented yet (#42640).
-    Unannotated,
-
-    /// Annotated with `mut x` -- could be either ref or not, similar to `None`.
-    Mutable,
-
-    /// Annotated as `ref`, like `ref x`
-    Ref,
-
-    /// Annotated as `ref mut x`.
-    RefMut,
-}
-
 #[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
 pub enum RangeEnd {
     Included,
@@ -1321,7 +1292,7 @@ pub enum StmtKind<'hir> {
     Semi(&'hir Expr<'hir>),
 }
 
-/// Represents a `let` statement (i.e., `let <pat>:<ty> = <expr>;`).
+/// Represents a `let` statement (i.e., `let <pat>:<ty> = <init>;`).
 #[derive(Debug, HashStable_Generic)]
 pub struct Local<'hir> {
     pub pat: &'hir Pat<'hir>,
@@ -1438,7 +1409,7 @@ pub struct BodyId {
 #[derive(Debug, HashStable_Generic)]
 pub struct Body<'hir> {
     pub params: &'hir [Param<'hir>],
-    pub value: Expr<'hir>,
+    pub value: &'hir Expr<'hir>,
     pub generator_kind: Option<GeneratorKind>,
 }
 
@@ -1881,11 +1852,11 @@ pub enum ExprKind<'hir> {
     ///
     /// The `PathSegment` represents the method name and its generic arguments
     /// (within the angle brackets).
-    /// The first element of the `&[Expr]` is the expression that evaluates
+    /// The `&Expr` is the expression that evaluates
     /// to the object on which the method is being called on (the receiver),
-    /// and the remaining elements are the rest of the arguments.
+    /// and the `&[Expr]` is the rest of the arguments.
     /// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
-    /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d], span)`.
+    /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, x, [a, b, c, d], span)`.
     /// The final `Span` represents the span of the function and arguments
     /// (e.g. `foo::<Bar, Baz>(a, b, c, d)` in `x.foo::<Bar, Baz>(a, b, c, d)`
     ///
@@ -1893,7 +1864,7 @@ pub enum ExprKind<'hir> {
     /// the `hir_id` of the `MethodCall` node itself.
     ///
     /// [`type_dependent_def_id`]: ../../rustc_middle/ty/struct.TypeckResults.html#method.type_dependent_def_id
-    MethodCall(&'hir PathSegment<'hir>, &'hir [Expr<'hir>], Span),
+    MethodCall(&'hir PathSegment<'hir>, &'hir Expr<'hir>, &'hir [Expr<'hir>], Span),
     /// A tuple (e.g., `(a, b, c, d)`).
     Tup(&'hir [Expr<'hir>]),
     /// A binary operation (e.g., `a + b`, `a * b`).
@@ -2561,23 +2532,23 @@ pub enum TyKind<'hir> {
 pub enum InlineAsmOperand<'hir> {
     In {
         reg: InlineAsmRegOrRegClass,
-        expr: Expr<'hir>,
+        expr: &'hir Expr<'hir>,
     },
     Out {
         reg: InlineAsmRegOrRegClass,
         late: bool,
-        expr: Option<Expr<'hir>>,
+        expr: Option<&'hir Expr<'hir>>,
     },
     InOut {
         reg: InlineAsmRegOrRegClass,
         late: bool,
-        expr: Expr<'hir>,
+        expr: &'hir Expr<'hir>,
     },
     SplitInOut {
         reg: InlineAsmRegOrRegClass,
         late: bool,
-        in_expr: Expr<'hir>,
-        out_expr: Option<Expr<'hir>>,
+        in_expr: &'hir Expr<'hir>,
+        out_expr: Option<&'hir Expr<'hir>>,
     },
     Const {
         anon_const: AnonConst,
@@ -2991,7 +2962,7 @@ pub enum ItemKind<'hir> {
     /// A MBE macro definition (`macro_rules!` or `macro`).
     Macro(ast::MacroDef, MacroKind),
     /// A module.
-    Mod(Mod<'hir>),
+    Mod(&'hir Mod<'hir>),
     /// An external module, e.g. `extern { .. }`.
     ForeignMod { abi: Abi, items: &'hir [ForeignItemRef] },
     /// Module-level inline assembly (from `global_asm!`).
@@ -3495,16 +3466,32 @@ pub fn tuple_fields(&self) -> Option<&'hir [FieldDef<'hir>]> {
 mod size_asserts {
     use super::*;
     // These are in alphabetical order, which is easy to maintain.
-    static_assert_size!(Block<'static>, 48);
-    static_assert_size!(Expr<'static>, 56);
-    static_assert_size!(ForeignItem<'static>, 72);
+    static_assert_size!(Block<'_>, 48);
+    static_assert_size!(Body<'_>, 32);
+    static_assert_size!(Expr<'_>, 64);
+    static_assert_size!(ExprKind<'_>, 48);
+    static_assert_size!(FnDecl<'_>, 40);
+    static_assert_size!(ForeignItem<'_>, 72);
+    static_assert_size!(ForeignItemKind<'_>, 40);
+    static_assert_size!(GenericArg<'_>, 40);
     static_assert_size!(GenericBound<'_>, 48);
-    static_assert_size!(Generics<'static>, 56);
-    static_assert_size!(ImplItem<'static>, 88);
-    static_assert_size!(Impl<'static>, 80);
-    static_assert_size!(Item<'static>, 80);
-    static_assert_size!(Pat<'static>, 88);
-    static_assert_size!(QPath<'static>, 24);
-    static_assert_size!(TraitItem<'static>, 96);
-    static_assert_size!(Ty<'static>, 72);
+    static_assert_size!(Generics<'_>, 56);
+    static_assert_size!(Impl<'_>, 80);
+    static_assert_size!(ImplItem<'_>, 88);
+    static_assert_size!(ImplItemKind<'_>, 40);
+    static_assert_size!(Item<'_>, 80);
+    static_assert_size!(ItemKind<'_>, 48);
+    static_assert_size!(Local<'_>, 64);
+    static_assert_size!(Param<'_>, 32);
+    static_assert_size!(Pat<'_>, 88);
+    static_assert_size!(PatKind<'_>, 64);
+    static_assert_size!(Path<'_>, 48);
+    static_assert_size!(PathSegment<'_>, 56);
+    static_assert_size!(QPath<'_>, 24);
+    static_assert_size!(Stmt<'_>, 32);
+    static_assert_size!(StmtKind<'_>, 16);
+    static_assert_size!(TraitItem<'_>, 96);
+    static_assert_size!(TraitItemKind<'_>, 56);
+    static_assert_size!(Ty<'_>, 72);
+    static_assert_size!(TyKind<'_>, 56);
 }
index 346ac9e96440abfb1eae0ec9932bf40d5b6fdd91..e586d5cd5d941baf999cb728095f8621d3786aa0 100644 (file)
@@ -20,6 +20,9 @@ pub struct HirId {
 }
 
 impl HirId {
+    /// Signal local id which should never be used.
+    pub const INVALID: HirId = HirId { owner: CRATE_DEF_ID, local_id: ItemLocalId::INVALID };
+
     #[inline]
     pub fn expect_owner(self) -> LocalDefId {
         assert_eq!(self.local_id.index(), 0);
index 3d5e22add7187db19a2a52c1245976c028b83bc4..20ec788463ac011e9938b6a4f0372125091afe1d 100644 (file)
@@ -724,7 +724,7 @@ pub fn walk_path_segment<'v, V: Visitor<'v>>(
     segment: &'v PathSegment<'v>,
 ) {
     visitor.visit_ident(segment.ident);
-    walk_list!(visitor, visit_id, segment.hir_id);
+    visitor.visit_id(segment.hir_id);
     if let Some(ref args) = segment.args {
         visitor.visit_generic_args(path_span, args);
     }
@@ -1094,8 +1094,9 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
             visitor.visit_expr(callee_expression);
             walk_list!(visitor, visit_expr, arguments);
         }
-        ExprKind::MethodCall(ref segment, arguments, _) => {
+        ExprKind::MethodCall(ref segment, receiver, arguments, _) => {
             visitor.visit_path_segment(expression.span, segment);
+            visitor.visit_expr(receiver);
             walk_list!(visitor, visit_expr, arguments);
         }
         ExprKind::Binary(_, ref left_expression, ref right_expression) => {
index 0c01326d0032ac61842af06569cf493b714d7ed5..bc1ea1c4c736f4f3ba1bcc1e040b3c6d0bec0c34 100644 (file)
@@ -193,7 +193,8 @@ pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> {
     DispatchFromDyn,         sym::dispatch_from_dyn,   dispatch_from_dyn_trait,    Target::Trait,          GenericRequirement::Minimum(1);
 
     // language items relating to transmutability
-    TransmuteTrait,          sym::transmute_trait,     transmute_trait,            Target::Trait,          GenericRequirement::Exact(6);
+    TransmuteOpts,           sym::transmute_opts,      transmute_opts,             Target::Struct,         GenericRequirement::Exact(0);
+    TransmuteTrait,          sym::transmute_trait,     transmute_trait,            Target::Trait,          GenericRequirement::Exact(3);
 
     Add(Op),                 sym::add,                 add_trait,                  Target::Trait,          GenericRequirement::Exact(1);
     Sub(Op),                 sym::sub,                 sub_trait,                  Target::Trait,          GenericRequirement::Exact(1);
@@ -268,8 +269,6 @@ pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> {
     DropInPlace,             sym::drop_in_place,       drop_in_place_fn,           Target::Fn,             GenericRequirement::Minimum(1);
     Oom,                     sym::oom,                 oom,                        Target::Fn,             GenericRequirement::None;
     AllocLayout,             sym::alloc_layout,        alloc_layout,               Target::Struct,         GenericRequirement::None;
-    ConstEvalSelect,         sym::const_eval_select,   const_eval_select,          Target::Fn,             GenericRequirement::Exact(4);
-    ConstConstEvalSelect,    sym::const_eval_select_ct,const_eval_select_ct,       Target::Fn,             GenericRequirement::Exact(4);
 
     Start,                   sym::start,               start_fn,                   Target::Fn,             GenericRequirement::Exact(1);
 
index 092029ef09ec80e6cab087b6b63838e94ed25f4e..1b33cb9c2da9cbcebbe4be41ca0bd6d1d7665e08 100644 (file)
@@ -17,6 +17,9 @@
 #[macro_use]
 extern crate rustc_macros;
 
+#[macro_use]
+extern crate tracing;
+
 #[macro_use]
 extern crate rustc_data_structures;
 
index 93112199b6030d0b0349c24df41eb79208c2ac37..9baaf9390f2c5aa181bfde02841de865236339af 100644 (file)
@@ -1,6 +1,6 @@
 use crate::def::{CtorOf, DefKind, Res};
 use crate::def_id::DefId;
-use crate::hir::{self, HirId, PatKind};
+use crate::hir::{self, BindingAnnotation, ByRef, HirId, PatKind};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_span::hygiene::DesugaringKind;
 use rustc_span::symbol::Ident;
@@ -93,12 +93,7 @@ pub fn each_binding_or_first(
 
     pub fn simple_ident(&self) -> Option<Ident> {
         match self.kind {
-            PatKind::Binding(
-                hir::BindingAnnotation::Unannotated | hir::BindingAnnotation::Mutable,
-                _,
-                ident,
-                None,
-            ) => Some(ident),
+            PatKind::Binding(BindingAnnotation(ByRef::No, _), _, ident, None) => Some(ident),
             _ => None,
         }
     }
@@ -135,11 +130,11 @@ pub fn necessary_variants(&self) -> Vec<DefId> {
     pub fn contains_explicit_ref_binding(&self) -> Option<hir::Mutability> {
         let mut result = None;
         self.each_binding(|annotation, _, _, _| match annotation {
-            hir::BindingAnnotation::Ref => match result {
+            hir::BindingAnnotation::REF => match result {
                 None | Some(hir::Mutability::Not) => result = Some(hir::Mutability::Not),
                 _ => {}
             },
-            hir::BindingAnnotation::RefMut => result = Some(hir::Mutability::Mut),
+            hir::BindingAnnotation::REF_MUT => result = Some(hir::Mutability::Mut),
             _ => {}
         });
         result
index 42663da8a3f9c173d400e46eca4660dcea8b0c5c..1220755f44b30866aa3394a31fc4588e55d1fd02 100644 (file)
@@ -9,7 +9,9 @@
 use rustc_ast_pretty::pprust::{Comments, PrintState};
 use rustc_hir as hir;
 use rustc_hir::LifetimeParamKind;
-use rustc_hir::{GenericArg, GenericParam, GenericParamKind, Node, Term};
+use rustc_hir::{
+    BindingAnnotation, ByRef, GenericArg, GenericParam, GenericParamKind, Mutability, Node, Term,
+};
 use rustc_hir::{GenericBound, PatKind, RangeEnd, TraitBoundModifier};
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::{kw, Ident, IdentPrinter, Symbol};
@@ -1181,15 +1183,20 @@ fn print_expr_call(&mut self, func: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
         self.print_call_post(args)
     }
 
-    fn print_expr_method_call(&mut self, segment: &hir::PathSegment<'_>, args: &[hir::Expr<'_>]) {
-        let base_args = &args[1..];
-        self.print_expr_maybe_paren(&args[0], parser::PREC_POSTFIX);
+    fn print_expr_method_call(
+        &mut self,
+        segment: &hir::PathSegment<'_>,
+        receiver: &hir::Expr<'_>,
+        args: &[hir::Expr<'_>],
+    ) {
+        let base_args = args;
+        self.print_expr_maybe_paren(&receiver, parser::PREC_POSTFIX);
         self.word(".");
         self.print_ident(segment.ident);
 
         let generic_args = segment.args();
         if !generic_args.args.is_empty() || !generic_args.bindings.is_empty() {
-            self.print_generic_args(generic_args, segment.infer_args, true);
+            self.print_generic_args(generic_args, true);
         }
 
         self.print_call_post(base_args)
@@ -1394,8 +1401,8 @@ pub fn print_expr(&mut self, expr: &hir::Expr<'_>) {
             hir::ExprKind::Call(func, args) => {
                 self.print_expr_call(func, args);
             }
-            hir::ExprKind::MethodCall(segment, args, _) => {
-                self.print_expr_method_call(segment, args);
+            hir::ExprKind::MethodCall(segment, receiver, args, _) => {
+                self.print_expr_method_call(segment, receiver, args);
             }
             hir::ExprKind::Binary(op, lhs, rhs) => {
                 self.print_expr_binary(op, lhs, rhs);
@@ -1592,7 +1599,7 @@ pub fn print_path(&mut self, path: &hir::Path<'_>, colons_before_params: bool) {
             }
             if segment.ident.name != kw::PathRoot {
                 self.print_ident(segment.ident);
-                self.print_generic_args(segment.args(), segment.infer_args, colons_before_params);
+                self.print_generic_args(segment.args(), colons_before_params);
             }
         }
     }
@@ -1600,7 +1607,7 @@ pub fn print_path(&mut self, path: &hir::Path<'_>, colons_before_params: bool) {
     pub fn print_path_segment(&mut self, segment: &hir::PathSegment<'_>) {
         if segment.ident.name != kw::PathRoot {
             self.print_ident(segment.ident);
-            self.print_generic_args(segment.args(), segment.infer_args, false);
+            self.print_generic_args(segment.args(), false);
         }
     }
 
@@ -1619,11 +1626,7 @@ pub fn print_qpath(&mut self, qpath: &hir::QPath<'_>, colons_before_params: bool
                     }
                     if segment.ident.name != kw::PathRoot {
                         self.print_ident(segment.ident);
-                        self.print_generic_args(
-                            segment.args(),
-                            segment.infer_args,
-                            colons_before_params,
-                        );
+                        self.print_generic_args(segment.args(), colons_before_params);
                     }
                 }
 
@@ -1631,11 +1634,7 @@ pub fn print_qpath(&mut self, qpath: &hir::QPath<'_>, colons_before_params: bool
                 self.word("::");
                 let item_segment = path.segments.last().unwrap();
                 self.print_ident(item_segment.ident);
-                self.print_generic_args(
-                    item_segment.args(),
-                    item_segment.infer_args,
-                    colons_before_params,
-                )
+                self.print_generic_args(item_segment.args(), colons_before_params)
             }
             hir::QPath::TypeRelative(qself, item_segment) => {
                 // If we've got a compound-qualified-path, let's push an additional pair of angle
@@ -1651,11 +1650,7 @@ pub fn print_qpath(&mut self, qpath: &hir::QPath<'_>, colons_before_params: bool
 
                 self.word("::");
                 self.print_ident(item_segment.ident);
-                self.print_generic_args(
-                    item_segment.args(),
-                    item_segment.infer_args,
-                    colons_before_params,
-                )
+                self.print_generic_args(item_segment.args(), colons_before_params)
             }
             hir::QPath::LangItem(lang_item, span, _) => {
                 self.word("#[lang = \"");
@@ -1668,7 +1663,6 @@ pub fn print_qpath(&mut self, qpath: &hir::QPath<'_>, colons_before_params: bool
     fn print_generic_args(
         &mut self,
         generic_args: &hir::GenericArgs<'_>,
-        infer_args: bool,
         colons_before_params: bool,
     ) {
         if generic_args.parenthesized {
@@ -1715,13 +1709,6 @@ fn print_generic_args(
                 );
             }
 
-            // FIXME(eddyb): this would leak into error messages (e.g.,
-            // "non-exhaustive patterns: `Some::<..>(_)` not covered").
-            if infer_args && false {
-                start_or_comma(self);
-                self.word("..");
-            }
-
             for binding in generic_args.bindings {
                 start_or_comma(self);
                 self.print_type_binding(binding);
@@ -1735,7 +1722,7 @@ fn print_generic_args(
 
     pub fn print_type_binding(&mut self, binding: &hir::TypeBinding<'_>) {
         self.print_ident(binding.ident);
-        self.print_generic_args(binding.gen_args, false, false);
+        self.print_generic_args(binding.gen_args, false);
         self.space();
         match binding.kind {
             hir::TypeBindingKind::Equality { ref term } => {
@@ -1758,20 +1745,12 @@ pub fn print_pat(&mut self, pat: &hir::Pat<'_>) {
         // is that it doesn't matter
         match pat.kind {
             PatKind::Wild => self.word("_"),
-            PatKind::Binding(binding_mode, _, ident, sub) => {
-                match binding_mode {
-                    hir::BindingAnnotation::Ref => {
-                        self.word_nbsp("ref");
-                        self.print_mutability(hir::Mutability::Not, false);
-                    }
-                    hir::BindingAnnotation::RefMut => {
-                        self.word_nbsp("ref");
-                        self.print_mutability(hir::Mutability::Mut, false);
-                    }
-                    hir::BindingAnnotation::Unannotated => {}
-                    hir::BindingAnnotation::Mutable => {
-                        self.word_nbsp("mut");
-                    }
+            PatKind::Binding(BindingAnnotation(by_ref, mutbl), _, ident, sub) => {
+                if by_ref == ByRef::Yes {
+                    self.word_nbsp("ref");
+                }
+                if mutbl == Mutability::Mut {
+                    self.word_nbsp("mut");
                 }
                 self.print_ident(ident);
                 if let Some(p) = sub {
@@ -2413,9 +2392,9 @@ fn contains_exterior_struct_lit(value: &hir::Expr<'_>) -> bool {
             contains_exterior_struct_lit(x)
         }
 
-        hir::ExprKind::MethodCall(.., exprs, _) => {
+        hir::ExprKind::MethodCall(_, receiver, ..) => {
             // `X { y: 1 }.bar(...)`
-            contains_exterior_struct_lit(&exprs[0])
+            contains_exterior_struct_lit(receiver)
         }
 
         _ => false,
index 8bf1de34a9b5cace73b66a13e3f888ebafc6fbb9..d4350aa5734dee4aefe5583a5f1e6233d0cf2303 100644 (file)
@@ -391,7 +391,7 @@ pub fn instantiate(
     /// Preconditions:
     ///
     /// - `for_vid` is a "root vid"
-    #[instrument(skip(self), level = "trace")]
+    #[instrument(skip(self), level = "trace", ret)]
     fn generalize(
         &self,
         ty: Ty<'tcx>,
@@ -435,15 +435,8 @@ fn generalize(
             cache: SsoHashMap::new(),
         };
 
-        let ty = match generalize.relate(ty, ty) {
-            Ok(ty) => ty,
-            Err(e) => {
-                debug!(?e, "failure");
-                return Err(e);
-            }
-        };
+        let ty = generalize.relate(ty, ty)?;
         let needs_wf = generalize.needs_wf;
-        trace!(?ty, ?needs_wf, "success");
         Ok(Generalization { ty, needs_wf })
     }
 
@@ -499,6 +492,7 @@ struct Generalizer<'cx, 'tcx> {
 /// Result from a generalization operation. This includes
 /// not only the generalized type, but also a bool flag
 /// indicating whether further WF checks are needed.
+#[derive(Debug)]
 struct Generalization<'tcx> {
     ty: Ty<'tcx>,
 
@@ -856,10 +850,9 @@ fn binders<T>(
         Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?))
     }
 
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self), ret)]
     fn tys(&mut self, t: Ty<'tcx>, _t: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
         debug_assert_eq!(t, _t);
-        debug!("ConstInferUnifier: t={:?}", t);
 
         match t.kind() {
             &ty::Infer(ty::TyVar(vid)) => {
@@ -883,12 +876,7 @@ fn tys(&mut self, t: Ty<'tcx>, _t: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
                             .borrow_mut()
                             .type_variables()
                             .new_var(self.for_universe, origin);
-                        let u = self.tcx().mk_ty_var(new_var_id);
-                        debug!(
-                            "ConstInferUnifier: replacing original vid={:?} with new={:?}",
-                            vid, u
-                        );
-                        Ok(u)
+                        Ok(self.tcx().mk_ty_var(new_var_id))
                     }
                 }
             }
@@ -932,14 +920,13 @@ fn regions(
         }
     }
 
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn consts(
         &mut self,
         c: ty::Const<'tcx>,
         _c: ty::Const<'tcx>,
     ) -> RelateResult<'tcx, ty::Const<'tcx>> {
         debug_assert_eq!(c, _c);
-        debug!("ConstInferUnifier: c={:?}", c);
 
         match c.kind() {
             ty::ConstKind::Infer(InferConst::Var(vid)) => {
index 3a6119a627368fb18da0c9e7f4638546ce339428..6dad9873d613404a124bac052236be887ecdb7f0 100644 (file)
@@ -1434,7 +1434,7 @@ fn lifetime_display(lifetime: Region<'_>) -> String {
     /// the message in `secondary_span` as the primary label, and apply the message that would
     /// otherwise be used for the primary label on the `secondary_span` `Span`. This applies on
     /// E0271, like `src/test/ui/issues/issue-39970.stderr`.
-    #[tracing::instrument(
+    #[instrument(
         level = "debug",
         skip(self, diag, secondary_span, swap_secondary_and_primary, prefer_label)
     )]
index 91a05367eee0242565e6cda3d03e4731e55d2a1a..232b9b11455db3612c44d68dd557ad6885b9a45e 100644 (file)
@@ -901,7 +901,7 @@ fn expr_inferred_subst_iter(
                     }
                 }
             }
-            hir::ExprKind::MethodCall(segment, _, _) => {
+            hir::ExprKind::MethodCall(segment, ..) => {
                 if let Some(def_id) = self.typeck_results.type_dependent_def_id(expr.hir_id) {
                     let generics = tcx.generics_of(def_id);
                     let insertable: Option<_> = try {
@@ -909,7 +909,7 @@ fn expr_inferred_subst_iter(
                             None?
                         }
                         let substs = self.node_substs_opt(expr.hir_id)?;
-                        let span = tcx.hir().span(segment.hir_id?);
+                        let span = tcx.hir().span(segment.hir_id);
                         let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi());
                         InsertableGenericArgs {
                             insert_span,
@@ -957,13 +957,13 @@ fn resolved_path_inferred_subst_iter(
         path.segments
             .iter()
             .filter_map(move |segment| {
-                let res = segment.res?;
+                let res = segment.res;
                 let generics_def_id = tcx.res_generics_def_id(res)?;
                 let generics = tcx.generics_of(generics_def_id);
                 if generics.has_impl_trait() {
                     return None;
                 }
-                let span = tcx.hir().span(segment.hir_id?);
+                let span = tcx.hir().span(segment.hir_id);
                 let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi());
                 Some(InsertableGenericArgs {
                     insert_span,
@@ -996,7 +996,7 @@ fn path_inferred_subst_iter(
                     if !segment.infer_args || generics.has_impl_trait() {
                         None?;
                     }
-                    let span = tcx.hir().span(segment.hir_id?);
+                    let span = tcx.hir().span(segment.hir_id);
                     let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi());
                     InsertableGenericArgs { insert_span, substs, generics_def_id: def_id, def_id }
                 };
@@ -1132,7 +1132,7 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
                 let generic_args = &generics.own_substs_no_defaults(tcx, substs)
                     [generics.own_counts().lifetimes..];
                 let span = match expr.kind {
-                    ExprKind::MethodCall(path, _, _) => path.ident.span,
+                    ExprKind::MethodCall(path, ..) => path.ident.span,
                     _ => expr.span,
                 };
 
@@ -1181,7 +1181,7 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
             })
             .any(|generics| generics.has_impl_trait())
         };
-        if let ExprKind::MethodCall(path, args, span) = expr.kind
+        if let ExprKind::MethodCall(path, receiver, args, span) = expr.kind
             && let Some(substs) = self.node_substs_opt(expr.hir_id)
             && substs.iter().any(|arg| self.generic_arg_contains_target(arg))
             && let Some(def_id) = self.typeck_results.type_dependent_def_id(expr.hir_id)
@@ -1189,12 +1189,12 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
             && !has_impl_trait(def_id)
         {
             let successor =
-                args.get(1).map_or_else(|| (")", span.hi()), |arg| (", ", arg.span.lo()));
+                args.get(0).map_or_else(|| (")", span.hi()), |arg| (", ", arg.span.lo()));
             let substs = self.infcx.resolve_vars_if_possible(substs);
             self.update_infer_source(InferSource {
                 span: path.ident.span,
                 kind: InferSourceKind::FullyQualifiedMethodCall {
-                    receiver: args.first().unwrap(),
+                    receiver,
                     successor,
                     substs,
                     def_id,
index da465a764299270ec845383fc8547f869631bef8..a6a39d062d51dadc9a0f2e173af676f563e4bdb7 100644 (file)
@@ -154,16 +154,11 @@ fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) {
             }
             hir::TyKind::Path(hir::QPath::Resolved(None, path)) => match &path.segments {
                 [segment]
-                    if segment
-                        .res
-                        .map(|res| {
-                            matches!(
-                                res,
-                                Res::SelfTy { trait_: _, alias_to: _ }
-                                    | Res::Def(hir::def::DefKind::TyParam, _)
-                            )
-                        })
-                        .unwrap_or(false) =>
+                    if matches!(
+                        segment.res,
+                        Res::SelfTy { trait_: _, alias_to: _ }
+                            | Res::Def(hir::def::DefKind::TyParam, _)
+                    ) =>
                 {
                     self.types.push(path.span);
                 }
index d0d9efe152cc04109799f78aa8df246f6db4a191..67426fcf0feda6c5a7664772c7dfffd8cd941ae1 100644 (file)
@@ -69,7 +69,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     /// For more details visit the relevant sections of the [rustc dev guide].
     ///
     /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
-    #[instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self), ret)]
     pub fn replace_bound_vars_with_placeholders<T>(&self, binder: ty::Binder<'tcx, T>) -> T
     where
         T: TypeFoldable<'tcx> + Copy,
@@ -104,9 +104,8 @@ pub fn replace_bound_vars_with_placeholders<T>(&self, binder: ty::Binder<'tcx, T
             },
         };
 
-        let result = self.tcx.replace_bound_vars_uncached(binder, delegate);
-        debug!(?next_universe, ?result);
-        result
+        debug!(?next_universe);
+        self.tcx.replace_bound_vars_uncached(binder, delegate)
     }
 
     /// See [RegionConstraintCollector::leak_check][1].
index 3783cfb4cc5c85c85aaf53e674bdfb7916a95ba8..13b7e8eb9643611e0a5678f9b936250e347ac216 100644 (file)
@@ -333,9 +333,9 @@ fn sub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> bool {
     ///
     /// Neither `a` nor `b` may be an inference variable (hence the
     /// term "concrete regions").
-    #[instrument(level = "trace", skip(self))]
+    #[instrument(level = "trace", skip(self), ret)]
     fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx> {
-        let r = match (*a, *b) {
+        match (*a, *b) {
             (ReLateBound(..), _) | (_, ReLateBound(..)) | (ReErased, _) | (_, ReErased) => {
                 bug!("cannot relate region: LUB({:?}, {:?})", a, b);
             }
@@ -399,11 +399,7 @@ fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx>
                     self.tcx().lifetimes.re_static
                 }
             }
-        };
-
-        debug!("lub_concrete_regions({:?}, {:?}) = {:?}", a, b, r);
-
-        r
+        }
     }
 
     /// After expansion is complete, go and check upper bounds (i.e.,
index e7e93116a66d146c9d3b74ad4bb5cd79324cc06b..bb6f6ae60e26ac27c05ad3e59c889122e90d6ef3 100644 (file)
@@ -542,7 +542,7 @@ fn a_is_expected(&self) -> bool {
         true
     }
 
-    #[instrument(skip(self, info), level = "trace")]
+    #[instrument(skip(self, info), level = "trace", ret)]
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         variance: ty::Variance,
@@ -560,8 +560,6 @@ fn relate_with_variance<T: Relate<'tcx>>(
 
         self.ambient_variance = old_ambient_variance;
 
-        debug!(?r);
-
         Ok(r)
     }
 
index 233a5004a3931f53444eaf75538edc8f89d65e6a..d45adf43abfcc0040f0feeb235604eff4cc422a9 100644 (file)
@@ -390,7 +390,7 @@ pub fn register_member_constraints(
         });
     }
 
-    #[instrument(skip(self), level = "trace")]
+    #[instrument(skip(self), level = "trace", ret)]
     pub fn opaque_type_origin(&self, def_id: LocalDefId, span: Span) -> Option<OpaqueTyOrigin> {
         let opaque_hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
         let parent_def_id = match self.defining_use_anchor {
@@ -421,16 +421,14 @@ pub fn opaque_type_origin(&self, def_id: LocalDefId, span: Span) -> Option<Opaqu
         in_definition_scope.then_some(*origin)
     }
 
-    #[instrument(skip(self), level = "trace")]
+    #[instrument(skip(self), level = "trace", ret)]
     fn opaque_ty_origin_unchecked(&self, def_id: LocalDefId, span: Span) -> OpaqueTyOrigin {
-        let origin = match self.tcx.hir().expect_item(def_id).kind {
+        match self.tcx.hir().expect_item(def_id).kind {
             hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => origin,
             ref itemkind => {
                 span_bug!(span, "weird opaque type: {:?}, {:#?}", def_id, itemkind)
             }
-        };
-        trace!(?origin);
-        origin
+        }
     }
 }
 
index fb12da0cc13f0aeb3661ff34d8c7781d92058d9f..4d124554afb94d3bb119275e9c415932dbc8131b 100644 (file)
@@ -29,7 +29,7 @@ pub(crate) fn remove(&mut self, key: OpaqueTypeKey<'tcx>, idx: Option<OpaqueHidd
         }
     }
 
-    #[instrument(level = "debug")]
+    #[instrument(level = "debug", ret)]
     pub fn take_opaque_types(&mut self) -> OpaqueTypeMap<'tcx> {
         std::mem::take(&mut self.opaque_types)
     }
index 2a085288fb7c069c8d58d8a776b9e758d0b4078c..2d19d1823fdfc2b04816cde419dd59aa3361009b 100644 (file)
@@ -9,7 +9,7 @@
 use rustc_middle::traits::query::OutlivesBound;
 use rustc_middle::ty;
 
-#[instrument(level = "debug", skip(param_env))]
+#[instrument(level = "debug", skip(param_env), ret)]
 pub fn explicit_outlives_bounds<'tcx>(
     param_env: ty::ParamEnv<'tcx>,
 ) -> impl Iterator<Item = OutlivesBound<'tcx>> + 'tcx {
index fe78890ff6ed7648b309d0b095b284b25c0dd4b3..74c8bd88d275dbfb79589c41d21eab3bd91d169b 100644 (file)
@@ -313,7 +313,7 @@ fn param_ty_must_outlive(
         self.delegate.push_verify(origin, generic, region, verify_bound);
     }
 
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn projection_must_outlive(
         &mut self,
         origin: infer::SubregionOrigin<'tcx>,
index be03c8b5bae98a507cec3b8581bd874cea47338c..a5c21f0fb9b50eadf775aac2a6840500f388a00d 100644 (file)
@@ -34,7 +34,7 @@
 /// like are used. This is a particular challenge since this function is invoked
 /// very late in inference and hence cannot make use of the normal inference
 /// machinery.
-#[tracing::instrument(level = "debug", skip(tcx, param_env))]
+#[instrument(level = "debug", skip(tcx, param_env))]
 pub fn extract_verify_if_eq<'tcx>(
     tcx: TyCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
@@ -71,7 +71,7 @@ pub fn extract_verify_if_eq<'tcx>(
 }
 
 /// True if a (potentially higher-ranked) outlives
-#[tracing::instrument(level = "debug", skip(tcx, param_env))]
+#[instrument(level = "debug", skip(tcx, param_env))]
 pub(super) fn can_match_erased_ty<'tcx>(
     tcx: TyCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
@@ -110,7 +110,7 @@ fn no_match<T>(&self) -> RelateResult<'tcx, T> {
 
     /// Binds the pattern variable `br` to `value`; returns an `Err` if the pattern
     /// is already bound to a different value.
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn bind(
         &mut self,
         br: ty::BoundRegion,
index 1c6243c275c01daed80196d81a77c072ec4af099..949bd02ad6839a8f1535e453efc2d08d1a704dcf 100644 (file)
@@ -332,7 +332,7 @@ pub fn create_compiler_and_run<R>(config: Config, f: impl FnOnce(&Compiler) -> R
 // JUSTIFICATION: before session exists, only config
 #[allow(rustc::bad_opt_access)]
 pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Send) -> R {
-    tracing::trace!("run_compiler");
+    trace!("run_compiler");
     util::run_in_thread_pool_with_globals(
         config.opts.edition,
         config.opts.unstable_opts.threads,
index 258e38c3bdb9e09197fc006865defaa66903149a..1a8d619fafb6212483b49ab045f40f6e07af901f 100644 (file)
@@ -8,6 +8,9 @@
 #![deny(rustc::untranslatable_diagnostic)]
 #![deny(rustc::diagnostic_outside_of_impl)]
 
+#[macro_use]
+extern crate tracing;
+
 mod callbacks;
 mod errors;
 pub mod interface;
index 66c6a229b89e4564b4e9130f3191eded516adcf7..bb534a3c7afce6399abb885ae5dfe2984e22aab9 100644 (file)
@@ -38,7 +38,6 @@
 use rustc_span::FileName;
 use rustc_trait_selection::traits;
 use rustc_typeck as typeck;
-use tracing::{info, warn};
 
 use std::any::Any;
 use std::cell::RefCell;
@@ -69,7 +68,7 @@ pub fn parse<'a>(sess: &'a Session, input: &Input) -> PResult<'a, ast::Crate> {
     }
 
     if sess.opts.unstable_opts.hir_stats {
-        hir_stats::print_ast_stats(&krate, "PRE EXPANSION AST STATS");
+        hir_stats::print_ast_stats(&krate, "PRE EXPANSION AST STATS", "ast-stats-1");
     }
 
     Ok(krate)
@@ -165,7 +164,7 @@ pub fn create_resolver(
     krate: &ast::Crate,
     crate_name: &str,
 ) -> BoxedResolver {
-    tracing::trace!("create_resolver");
+    trace!("create_resolver");
     BoxedResolver::new(sess, move |sess, resolver_arenas| {
         Resolver::new(sess, krate, crate_name, metadata_loader, resolver_arenas)
     })
@@ -279,7 +278,7 @@ pub fn configure_and_expand(
     crate_name: &str,
     resolver: &mut Resolver<'_>,
 ) -> Result<ast::Crate> {
-    tracing::trace!("configure_and_expand");
+    trace!("configure_and_expand");
     pre_expansion_lint(sess, lint_store, resolver.registered_tools(), &krate, crate_name);
     rustc_builtin_macros::register_builtin_macros(resolver);
 
@@ -416,7 +415,7 @@ pub fn configure_and_expand(
     }
 
     if sess.opts.unstable_opts.hir_stats {
-        hir_stats::print_ast_stats(&krate, "POST EXPANSION AST STATS");
+        hir_stats::print_ast_stats(&krate, "POST EXPANSION AST STATS", "ast-stats-2");
     }
 
     resolver.resolve_crate(&krate);
index 65fa8d7495a4bf16cc76277a97bf5593e3e29fd9..6c725a01b53151ccfb9325f876442a22920facbf 100644 (file)
@@ -166,7 +166,7 @@ pub fn crate_name(&self) -> Result<&Query<String>> {
     pub fn expansion(
         &self,
     ) -> Result<&Query<(Lrc<ast::Crate>, Rc<RefCell<BoxedResolver>>, Lrc<LintStore>)>> {
-        tracing::trace!("expansion");
+        trace!("expansion");
         self.expansion.compute(|| {
             let crate_name = self.crate_name()?.peek().clone();
             let (krate, lint_store) = self.register_plugins()?.take();
index 9207a0488623c94e9ef3aa5fd89280f20942666d..5df5ab3ddc032eb19ec354e3f1bcb012b8b32345 100644 (file)
 use rustc_span::edition::{Edition, DEFAULT_EDITION};
 use rustc_span::symbol::sym;
 use rustc_span::SourceFileHashAlgorithm;
-use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy};
-use rustc_target::spec::{
-    RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel,
-};
+use rustc_target::spec::{CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, RelocModel};
+use rustc_target::spec::{RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel};
 
 use std::collections::{BTreeMap, BTreeSet};
 use std::iter::FromIterator;
@@ -552,7 +550,7 @@ macro_rules! untracked {
     untracked!(link_args, vec![String::from("abc"), String::from("def")]);
     untracked!(link_self_contained, Some(true));
     untracked!(linker, Some(PathBuf::from("linker")));
-    untracked!(linker_flavor, Some(LinkerFlavor::Gcc));
+    untracked!(linker_flavor, Some(LinkerFlavorCli::Gcc));
     untracked!(no_stack_check, true);
     untracked!(remark, Passes::Some(vec![String::from("pass1"), String::from("pass2")]));
     untracked!(rpath, true);
index e74978485a21c818e780d1d3a923593a73de7b8c..f7e70d355cf86e6ff3ad519311676536ed3a6e24 100644 (file)
@@ -1,3 +1,4 @@
+use info;
 use libloading::Library;
 use rustc_ast as ast;
 use rustc_codegen_ssa::traits::CodegenBackend;
@@ -31,7 +32,6 @@
 use std::sync::atomic::{AtomicBool, Ordering};
 use std::sync::OnceLock;
 use std::thread;
-use tracing::info;
 
 /// Function pointer type that constructs a new CodegenBackend.
 pub type MakeBackendFn = fn() -> Box<dyn CodegenBackend>;
index 121fefdc6207a830041ea7b2d20c5f99a19b6986..b97f8acb37f8442d7152d0e12f01fe9fac4db493 100644 (file)
@@ -61,7 +61,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
         }
 
         // We only care about method call expressions.
-        if let hir::ExprKind::MethodCall(call, args, _) = &expr.kind {
+        if let hir::ExprKind::MethodCall(call, receiver_arg, ..) = &expr.kind {
             if call.ident.name != sym::into_iter {
                 return;
             }
@@ -75,7 +75,6 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
             };
 
             // As this is a method call expression, we have at least one argument.
-            let receiver_arg = &args[0];
             let receiver_ty = cx.typeck_results().expr_ty(receiver_arg);
             let adjustments = cx.typeck_results().expr_adjustments(receiver_arg);
 
index 868555a72b0d1284f94982c90cc8dcd600a9f486..f06bfa912ca5314480708ec9ff2f4f2762c32423 100644 (file)
@@ -59,7 +59,6 @@
 use crate::nonstandard_style::{method_context, MethodLateContext};
 
 use std::fmt::Write;
-use tracing::{debug, trace};
 
 // hardwired lints from librustc_middle
 pub use rustc_session::lint::builtin::*;
@@ -260,17 +259,8 @@ fn check_pat(&mut self, cx: &LateContext<'_>, pat: &hir::Pat<'_>) {
                         == Some(cx.tcx.field_index(fieldpat.hir_id, cx.typeck_results()))
                     {
                         cx.struct_span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span, |lint| {
-                            let binding = match binding_annot {
-                                hir::BindingAnnotation::Unannotated => None,
-                                hir::BindingAnnotation::Mutable => Some("mut"),
-                                hir::BindingAnnotation::Ref => Some("ref"),
-                                hir::BindingAnnotation::RefMut => Some("ref mut"),
-                            };
-                            let suggested_ident = if let Some(binding) = binding {
-                                format!("{} {}", binding, ident)
-                            } else {
-                                ident.to_string()
-                            };
+                            let suggested_ident =
+                                format!("{}{}", binding_annot.prefix_str(), ident);
                             lint.build(fluent::lint::builtin_non_shorthand_field_patterns)
                                 .set_arg("ident", ident.clone())
                                 .span_suggestion(
@@ -2413,13 +2403,13 @@ fn is_dangerous_init(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<InitK
                         _ => {}
                     }
                 }
-            } else if let hir::ExprKind::MethodCall(_, ref args, _) = expr.kind {
+            } else if let hir::ExprKind::MethodCall(_, receiver, ..) = expr.kind {
                 // Find problematic calls to `MaybeUninit::assume_init`.
                 let def_id = cx.typeck_results().type_dependent_def_id(expr.hir_id)?;
                 if cx.tcx.is_diagnostic_item(sym::assume_init, def_id) {
                     // This is a call to *some* method named `assume_init`.
                     // See if the `self` parameter is one of the dangerous constructors.
-                    if let hir::ExprKind::Call(ref path_expr, _) = args[0].kind {
+                    if let hir::ExprKind::Call(ref path_expr, _) = receiver.kind {
                         if let hir::ExprKind::Path(ref qpath) = path_expr.kind {
                             let def_id = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id()?;
                             match cx.tcx.get_diagnostic_name(def_id) {
@@ -3173,3 +3163,117 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
         }
     }
 }
+
+declare_lint! {
+    /// The `special_module_name` lint detects module
+    /// declarations for files that have a special meaning.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,compile_fail
+    /// mod lib;
+    ///
+    /// fn main() {
+    ///     lib::run();
+    /// }
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Cargo recognizes `lib.rs` and `main.rs` as the root of a
+    /// library or binary crate, so declaring them as modules
+    /// will lead to miscompilation of the crate unless configured
+    /// explicitly.
+    ///
+    /// To access a library from a binary target within the same crate,
+    /// use `your_crate_name::` as the path path instead of `lib::`:
+    ///
+    /// ```rust,compile_fail
+    /// // bar/src/lib.rs
+    /// fn run() {
+    ///     // ...
+    /// }
+    ///
+    /// // bar/src/main.rs
+    /// fn main() {
+    ///     bar::run();
+    /// }
+    /// ```
+    ///
+    /// Binary targets cannot be used as libraries and so declaring
+    /// one as a module is not allowed.
+    pub SPECIAL_MODULE_NAME,
+    Warn,
+    "module declarations for files with a special meaning",
+}
+
+declare_lint_pass!(SpecialModuleName => [SPECIAL_MODULE_NAME]);
+
+impl EarlyLintPass for SpecialModuleName {
+    fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &ast::Crate) {
+        for item in &krate.items {
+            if let ast::ItemKind::Mod(
+                _,
+                ast::ModKind::Unloaded | ast::ModKind::Loaded(_, ast::Inline::No, _),
+            ) = item.kind
+            {
+                if item.attrs.iter().any(|a| a.has_name(sym::path)) {
+                    continue;
+                }
+
+                match item.ident.name.as_str() {
+                    "lib" => cx.struct_span_lint(SPECIAL_MODULE_NAME, item.span, |lint| {
+                        lint.build("found module declaration for lib.rs")
+                            .note("lib.rs is the root of this crate's library target")
+                            .help("to refer to it from other targets, use the library's name as the path")
+                            .emit()
+                    }),
+                    "main" => cx.struct_span_lint(SPECIAL_MODULE_NAME, item.span, |lint| {
+                        lint.build("found module declaration for main.rs")
+                            .note("a binary crate cannot be used as library")
+                            .emit()
+                    }),
+                    _ => continue
+                }
+            }
+        }
+    }
+}
+
+pub use rustc_session::lint::builtin::UNEXPECTED_CFGS;
+
+declare_lint_pass!(UnexpectedCfgs => [UNEXPECTED_CFGS]);
+
+impl EarlyLintPass for UnexpectedCfgs {
+    fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) {
+        let cfg = &cx.sess().parse_sess.config;
+        let check_cfg = &cx.sess().parse_sess.check_config;
+        for &(name, value) in cfg {
+            if let Some(names_valid) = &check_cfg.names_valid {
+                if !names_valid.contains(&name) {
+                    cx.lookup(UNEXPECTED_CFGS, None::<MultiSpan>, |diag| {
+                        diag.build(fluent::lint::builtin_unexpected_cli_config_name)
+                            .help(fluent::lint::help)
+                            .set_arg("name", name)
+                            .emit();
+                    });
+                }
+            }
+            if let Some(value) = value {
+                if let Some(values) = &check_cfg.values_valid.get(&name) {
+                    if !values.contains(&value) {
+                        cx.lookup(UNEXPECTED_CFGS, None::<MultiSpan>, |diag| {
+                            diag.build(fluent::lint::builtin_unexpected_cli_config_value)
+                                .help(fluent::lint::help)
+                                .set_arg("name", name)
+                                .set_arg("value", value)
+                                .emit();
+                        });
+                    }
+                }
+            }
+        }
+    }
+}
index 002bba4759be820ace8e656cd52a36f9fe52edca..9a163cf207e97ba7dc6bc0a56d81c4af6c21edcc 100644 (file)
@@ -45,7 +45,6 @@
 use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::{BytePos, Span};
 use rustc_target::abi;
-use tracing::debug;
 
 use std::cell::Cell;
 use std::iter;
@@ -417,7 +416,7 @@ pub fn check_lint_name(
                     None => {
                         // 1. The tool is currently running, so this lint really doesn't exist.
                         // FIXME: should this handle tools that never register a lint, like rustfmt?
-                        tracing::debug!("lints={:?}", self.by_name.keys().collect::<Vec<_>>());
+                        debug!("lints={:?}", self.by_name.keys().collect::<Vec<_>>());
                         let tool_prefix = format!("{}::", tool_name);
                         return if self.by_name.keys().any(|lint| lint.starts_with(&tool_prefix)) {
                             self.no_lint_suggestion(&complete_name)
@@ -510,7 +509,7 @@ fn check_tool_name_for_backwards_compat(
                 CheckLintNameResult::Tool(Err((Some(slice::from_ref(id)), complete_name)))
             }
             Some(other) => {
-                tracing::debug!("got renamed lint {:?}", other);
+                debug!("got renamed lint {:?}", other);
                 CheckLintNameResult::NoLint(None)
             }
         }
@@ -843,7 +842,7 @@ fn lookup_with_diagnostics(
                     if let Some(positional_arg_to_replace) = position_sp_to_replace {
                         let name = if is_formatting_arg { named_arg_name + "$" } else { named_arg_name };
                         let span_to_replace = if let Ok(positional_arg_content) =
-                            self.sess().source_map().span_to_snippet(positional_arg_to_replace) && positional_arg_content.starts_with(":") {
+                            self.sess().source_map().span_to_snippet(positional_arg_to_replace) && positional_arg_content.starts_with(':') {
                             positional_arg_to_replace.shrink_to_lo()
                         } else {
                             positional_arg_to_replace
index cdb5b3c4284a8d37afc0dd2f6bb7b4f8c3006937..27d173ebde82a506d7c1f8493352b137b3fee634 100644 (file)
@@ -26,7 +26,6 @@
 use rustc_span::Span;
 
 use std::slice;
-use tracing::debug;
 
 macro_rules! run_early_pass { ($cx:expr, $f:ident, $($args:expr),*) => ({
     $cx.pass.$f(&$cx.context, $($args),*);
index 6d451f3090acb22c499aad8bd51c2eaab2eaa542..dd1fc5916dbff71edd2550d5aacaaa3b6bec2049 100644 (file)
@@ -12,7 +12,6 @@
 use rustc_span::hygiene::{ExpnKind, MacroKind};
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::Span;
-use tracing::debug;
 
 declare_tool_lint! {
     pub rustc::DEFAULT_HASH_TYPES,
@@ -52,7 +51,7 @@ fn typeck_results_of_method_fn<'tcx>(
     expr: &Expr<'_>,
 ) -> Option<(Span, DefId, ty::subst::SubstsRef<'tcx>)> {
     match expr.kind {
-        ExprKind::MethodCall(segment, _, _)
+        ExprKind::MethodCall(segment, ..)
             if let Some(def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) =>
         {
             Some((segment.ident.span, def_id, cx.typeck_results().node_substs(expr.hir_id)))
@@ -119,8 +118,7 @@ fn check_path(
         _: rustc_hir::HirId,
     ) {
         if let Some(segment) = path.segments.iter().nth_back(1)
-        && let Some(res) = &segment.res
-        && lint_ty_kind_usage(cx, res)
+        && lint_ty_kind_usage(cx, &segment.res)
         {
             let span = path.span.with_hi(
                 segment.args.map_or(segment.ident.span, |a| a.span_ext).hi()
index 5188ac633d3928b9bcf56cc63bcab58bd76ab4da..8a336844dc2fac73f02f7c0fb003ae23ac77181c 100644 (file)
@@ -29,7 +29,6 @@
 use std::any::Any;
 use std::cell::Cell;
 use std::slice;
-use tracing::debug;
 
 /// Extract the `LintStore` from the query context.
 /// This function exists because we've erased `LintStore` as `dyn Any` in the context.
diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs
new file mode 100644 (file)
index 0000000..7e885e6
--- /dev/null
@@ -0,0 +1,175 @@
+use crate::{LateContext, LateLintPass, LintContext};
+use rustc_errors::{Applicability, LintDiagnosticBuilder, MultiSpan};
+use rustc_hir as hir;
+use rustc_middle::ty;
+use rustc_span::Symbol;
+
+declare_lint! {
+    /// The `let_underscore_drop` lint checks for statements which don't bind
+    /// an expression which has a non-trivial Drop implementation to anything,
+    /// causing the expression to be dropped immediately instead of at end of
+    /// scope.
+    ///
+    /// ### Example
+    /// ```
+    /// struct SomeStruct;
+    /// impl Drop for SomeStruct {
+    ///     fn drop(&mut self) {
+    ///         println!("Dropping SomeStruct");
+    ///     }
+    /// }
+    ///
+    /// fn main() {
+    ///    #[warn(let_underscore_drop)]
+    ///     // SomeStuct is dropped immediately instead of at end of scope,
+    ///     // so "Dropping SomeStruct" is printed before "end of main".
+    ///     // The order of prints would be reversed if SomeStruct was bound to
+    ///     // a name (such as "_foo").
+    ///     let _ = SomeStruct;
+    ///     println!("end of main");
+    /// }
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Statements which assign an expression to an underscore causes the
+    /// expression to immediately drop instead of extending the expression's
+    /// lifetime to the end of the scope. This is usually unintended,
+    /// especially for types like `MutexGuard`, which are typically used to
+    /// lock a mutex for the duration of an entire scope.
+    ///
+    /// If you want to extend the expression's lifetime to the end of the scope,
+    /// assign an underscore-prefixed name (such as `_foo`) to the expression.
+    /// If you do actually want to drop the expression immediately, then
+    /// calling `std::mem::drop` on the expression is clearer and helps convey
+    /// intent.
+    pub LET_UNDERSCORE_DROP,
+    Allow,
+    "non-binding let on a type that implements `Drop`"
+}
+
+declare_lint! {
+    /// The `let_underscore_lock` lint checks for statements which don't bind
+    /// a mutex to anything, causing the lock to be released immediately instead
+    /// of at end of scope, which is typically incorrect.
+    ///
+    /// ### Example
+    /// ```compile_fail
+    /// use std::sync::{Arc, Mutex};
+    /// use std::thread;
+    /// let data = Arc::new(Mutex::new(0));
+    ///
+    /// thread::spawn(move || {
+    ///     // The lock is immediately released instead of at the end of the
+    ///     // scope, which is probably not intended.
+    ///     let _ = data.lock().unwrap();
+    ///     println!("doing some work");
+    ///     let mut lock = data.lock().unwrap();
+    ///     *lock += 1;
+    /// });
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Statements which assign an expression to an underscore causes the
+    /// expression to immediately drop instead of extending the expression's
+    /// lifetime to the end of the scope. This is usually unintended,
+    /// especially for types like `MutexGuard`, which are typically used to
+    /// lock a mutex for the duration of an entire scope.
+    ///
+    /// If you want to extend the expression's lifetime to the end of the scope,
+    /// assign an underscore-prefixed name (such as `_foo`) to the expression.
+    /// If you do actually want to drop the expression immediately, then
+    /// calling `std::mem::drop` on the expression is clearer and helps convey
+    /// intent.
+    pub LET_UNDERSCORE_LOCK,
+    Deny,
+    "non-binding let on a synchronization lock"
+}
+
+declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_DROP, LET_UNDERSCORE_LOCK]);
+
+const SYNC_GUARD_SYMBOLS: [Symbol; 3] = [
+    rustc_span::sym::MutexGuard,
+    rustc_span::sym::RwLockReadGuard,
+    rustc_span::sym::RwLockWriteGuard,
+];
+
+impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
+    fn check_local(&mut self, cx: &LateContext<'_>, local: &hir::Local<'_>) {
+        if !matches!(local.pat.kind, hir::PatKind::Wild) {
+            return;
+        }
+        if let Some(init) = local.init {
+            let init_ty = cx.typeck_results().expr_ty(init);
+            // If the type has a trivial Drop implementation, then it doesn't
+            // matter that we drop the value immediately.
+            if !init_ty.needs_drop(cx.tcx, cx.param_env) {
+                return;
+            }
+            let is_sync_lock = match init_ty.kind() {
+                ty::Adt(adt, _) => SYNC_GUARD_SYMBOLS
+                    .iter()
+                    .any(|guard_symbol| cx.tcx.is_diagnostic_item(*guard_symbol, adt.did())),
+                _ => false,
+            };
+
+            if is_sync_lock {
+                let mut span = MultiSpan::from_spans(vec![local.pat.span, init.span]);
+                span.push_span_label(
+                    local.pat.span,
+                    "this lock is not assigned to a binding and is immediately dropped".to_string(),
+                );
+                span.push_span_label(
+                    init.span,
+                    "this binding will immediately drop the value assigned to it".to_string(),
+                );
+                cx.struct_span_lint(LET_UNDERSCORE_LOCK, span, |lint| {
+                    build_and_emit_lint(
+                        lint,
+                        local,
+                        init.span,
+                        "non-binding let on a synchronization lock",
+                    )
+                })
+            } else {
+                cx.struct_span_lint(LET_UNDERSCORE_DROP, local.span, |lint| {
+                    build_and_emit_lint(
+                        lint,
+                        local,
+                        init.span,
+                        "non-binding let on a type that implements `Drop`",
+                    );
+                })
+            }
+        }
+    }
+}
+
+fn build_and_emit_lint(
+    lint: LintDiagnosticBuilder<'_, ()>,
+    local: &hir::Local<'_>,
+    init_span: rustc_span::Span,
+    msg: &str,
+) {
+    lint.build(msg)
+        .span_suggestion_verbose(
+            local.pat.span,
+            "consider binding to an unused variable to avoid immediately dropping the value",
+            "_unused",
+            Applicability::MachineApplicable,
+        )
+        .multipart_suggestion(
+            "consider immediately dropping the value",
+            vec![
+                (local.span.until(init_span), "drop(".to_string()),
+                (init_span.shrink_to_hi(), ")".to_string()),
+            ],
+            Applicability::MachineApplicable,
+        )
+        .emit();
+}
index 89409b58f88b90af3d5762e537c33ac986f7c131..f1d8ef2e47d31cb74d2f37a3056d1af66766f1e8 100644 (file)
@@ -21,7 +21,6 @@
 use rustc_session::Session;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{Span, DUMMY_SP};
-use tracing::debug;
 
 use crate::errors::{
     MalformedAttribute, MalformedAttributeSub, OverruledAttribute, OverruledAttributeSub,
index c3065e4a2d9383c13d7bb147f2540c5b6d3efef4..370a75cf700691d81485c3a13f15f54ccc40e93a 100644 (file)
@@ -42,6 +42,8 @@
 extern crate rustc_middle;
 #[macro_use]
 extern crate rustc_session;
+#[macro_use]
+extern crate tracing;
 
 mod array_into_iter;
 pub mod builtin;
@@ -53,6 +55,7 @@
 pub mod hidden_unicode_codepoints;
 mod internal;
 mod late;
+mod let_underscore;
 mod levels;
 mod methods;
 mod non_ascii_idents;
@@ -84,6 +87,7 @@
 use enum_intrinsics_non_enums::EnumIntrinsicsNonEnums;
 use hidden_unicode_codepoints::*;
 use internal::*;
+use let_underscore::*;
 use methods::*;
 use non_ascii_idents::*;
 use non_fmt_panic::NonPanicFmt;
@@ -131,6 +135,7 @@ macro_rules! early_lint_passes {
                 UnusedBraces: UnusedBraces,
                 UnusedImportBraces: UnusedImportBraces,
                 UnsafeCode: UnsafeCode,
+                SpecialModuleName: SpecialModuleName,
                 AnonymousParameters: AnonymousParameters,
                 EllipsisInclusiveRangePatterns: EllipsisInclusiveRangePatterns::default(),
                 NonCamelCaseTypes: NonCamelCaseTypes,
@@ -141,6 +146,7 @@ macro_rules! early_lint_passes {
                 IncompleteFeatures: IncompleteFeatures,
                 RedundantSemicolons: RedundantSemicolons,
                 UnusedDocComment: UnusedDocComment,
+                UnexpectedCfgs: UnexpectedCfgs,
             ]
         );
     };
@@ -186,6 +192,7 @@ macro_rules! late_lint_mod_passes {
                 VariantSizeDifferences: VariantSizeDifferences,
                 BoxPointers: BoxPointers,
                 PathStatements: PathStatements,
+                LetUnderscore: LetUnderscore,
                 // Depends on referenced function signatures in expressions
                 UnusedResults: UnusedResults,
                 NonUpperCaseGlobals: NonUpperCaseGlobals,
@@ -312,6 +319,8 @@ macro_rules! register_passes {
         REDUNDANT_SEMICOLONS
     );
 
+    add_lint_group!("let_underscore", LET_UNDERSCORE_DROP, LET_UNDERSCORE_LOCK);
+
     add_lint_group!(
         "rust_2018_idioms",
         BARE_TRAIT_OBJECTS,
index ff5a01749c19e66b5246c514c6a71f2307fe8826..5f7f03480c043b07e58815012b35ff2b8418705c 100644 (file)
@@ -44,9 +44,13 @@ fn in_macro(span: Span) -> bool {
 
 fn first_method_call<'tcx>(
     expr: &'tcx Expr<'tcx>,
-) -> Option<(&'tcx PathSegment<'tcx>, &'tcx [Expr<'tcx>])> {
-    if let ExprKind::MethodCall(path, args, _) = &expr.kind {
-        if args.iter().any(|e| e.span.from_expansion()) { None } else { Some((path, *args)) }
+) -> Option<(&'tcx PathSegment<'tcx>, &'tcx Expr<'tcx>)> {
+    if let ExprKind::MethodCall(path, receiver, args, ..) = &expr.kind {
+        if args.iter().any(|e| e.span.from_expansion()) || receiver.span.from_expansion() {
+            None
+        } else {
+            Some((path, *receiver))
+        }
     } else {
         None
     }
@@ -59,15 +63,13 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         }
 
         match first_method_call(expr) {
-            Some((path, args)) if path.ident.name == sym::as_ptr => {
-                let unwrap_arg = &args[0];
+            Some((path, unwrap_arg)) if path.ident.name == sym::as_ptr => {
                 let as_ptr_span = path.ident.span;
                 match first_method_call(unwrap_arg) {
-                    Some((path, args))
+                    Some((path, receiver))
                         if path.ident.name == sym::unwrap || path.ident.name == sym::expect =>
                     {
-                        let source_arg = &args[0];
-                        lint_cstring_as_ptr(cx, as_ptr_span, source_arg, unwrap_arg);
+                        lint_cstring_as_ptr(cx, as_ptr_span, receiver, unwrap_arg);
                     }
                     _ => return,
                 }
index 11a752ff09705547328d54b5f452e71b0d232c3f..d1449496d331578be434f7053145359d05767316 100644 (file)
@@ -41,7 +41,7 @@
 impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         // We only care about method calls.
-        let ExprKind::MethodCall(call, elements, _) = &expr.kind else {
+        let ExprKind::MethodCall(call, receiver, ..) = &expr.kind else {
             return
         };
         // We only care about method calls corresponding to the `Clone`, `Deref` and `Borrow`
@@ -81,7 +81,6 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         ) {
             return;
         }
-        let receiver = &elements[0];
         let receiver_ty = cx.typeck_results().expr_ty(receiver);
         let expr_ty = cx.typeck_results().expr_ty_adjusted(expr);
         if receiver_ty != expr_ty {
index 484e541afc5879c477a6fefc674ba50bd642e08a..9736b5557036c8093ca966819030b1ebb544bafc 100644 (file)
@@ -19,7 +19,6 @@
 use std::cmp;
 use std::iter;
 use std::ops::ControlFlow;
-use tracing::debug;
 
 declare_lint! {
     /// The `unused_comparisons` lint detects comparisons made useless by
@@ -1459,7 +1458,7 @@ fn inherent_atomic_method_call<'hir>(
             sym::AtomicI64,
             sym::AtomicI128,
         ];
-        if let ExprKind::MethodCall(ref method_path, args, _) = &expr.kind
+        if let ExprKind::MethodCall(ref method_path, _, args, _) = &expr.kind
             && recognized_names.contains(&method_path.ident.name)
             && let Some(m_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
             && let Some(impl_did) = cx.tcx.impl_of_method(m_def_id)
@@ -1495,8 +1494,8 @@ fn match_ordering(cx: &LateContext<'_>, ord_arg: &Expr<'_>) -> Option<Symbol> {
     fn check_atomic_load_store(cx: &LateContext<'_>, expr: &Expr<'_>) {
         if let Some((method, args)) = Self::inherent_atomic_method_call(cx, expr, &[sym::load, sym::store])
             && let Some((ordering_arg, invalid_ordering)) = match method {
-                sym::load => Some((&args[1], sym::Release)),
-                sym::store => Some((&args[2], sym::Acquire)),
+                sym::load => Some((&args[0], sym::Release)),
+                sym::store => Some((&args[1], sym::Acquire)),
                 _ => None,
             }
             && let Some(ordering) = Self::match_ordering(cx, ordering_arg)
@@ -1537,8 +1536,8 @@ fn check_atomic_compare_exchange(cx: &LateContext<'_>, expr: &Expr<'_>) {
             else {return };
 
         let fail_order_arg = match method {
-            sym::fetch_update => &args[2],
-            sym::compare_exchange | sym::compare_exchange_weak => &args[4],
+            sym::fetch_update => &args[1],
+            sym::compare_exchange | sym::compare_exchange_weak => &args[3],
             _ => return,
         };
 
index 1f4e5b480917d556c3245beaef3e9f82d831bd8d..9a7d722c05a90be163d3b8a83bc506889f0b095f 100644 (file)
@@ -751,7 +751,7 @@ fn check_unused_parens_pat(
         avoid_or: bool,
         avoid_mut: bool,
     ) {
-        use ast::{BindingMode, Mutability, PatKind};
+        use ast::{BindingAnnotation, PatKind};
 
         if let PatKind::Paren(inner) = &value.kind {
             match inner.kind {
@@ -763,7 +763,9 @@ fn check_unused_parens_pat(
                 // Avoid `p0 | .. | pn` if we should.
                 PatKind::Or(..) if avoid_or => return,
                 // Avoid `mut x` and `mut x @ p` if we should:
-                PatKind::Ident(BindingMode::ByValue(Mutability::Mut), ..) if avoid_mut => return,
+                PatKind::Ident(BindingAnnotation::MUT, ..) if avoid_mut => {
+                    return;
+                }
                 // Otherwise proceed with linting.
                 _ => {}
             }
index 845563338eaa992c91b1f2178783800da41c0b5e..2e3a06fcbb745c22fd3227986e080302a01355c2 100644 (file)
         DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
         DUPLICATE_MACRO_ATTRIBUTES,
         SUSPICIOUS_AUTO_TRAIT_IMPLS,
-        UNEXPECTED_CFGS,
         DEPRECATED_WHERE_CLAUSE_LOCATION,
         TEST_UNSTABLE_LINT,
         FFI_UNWIND_CALLS,
     ///
     /// ### Example of drop reorder
     ///
-    /// ```rust,compile_fail
+    /// ```rust,edition2018,compile_fail
     /// #![deny(rust_2021_incompatible_closure_captures)]
     /// # #![allow(unused)]
     ///
     ///
     /// ### Example of auto-trait
     ///
-    /// ```rust,compile_fail
+    /// ```rust,edition2018,compile_fail
     /// #![deny(rust_2021_incompatible_closure_captures)]
     /// use std::thread;
     ///
index c1b82abc1e064a8da1b8dd62e3610232f7722393..dce5d3cfb84ff05b87aeceb2f47148e9bb55eed1 100644 (file)
@@ -12,7 +12,7 @@
 use std::collections::HashMap;
 use std::fmt;
 use std::str::FromStr;
-use syn::{spanned::Spanned, Meta, MetaList, MetaNameValue, NestedMeta, Path};
+use syn::{spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, NestedMeta, Path};
 use synstructure::{BindingInfo, Structure, VariantInfo};
 
 /// Which kind of suggestion is being created?
@@ -28,8 +28,41 @@ enum SubdiagnosticSuggestionKind {
     Verbose,
 }
 
+impl FromStr for SubdiagnosticSuggestionKind {
+    type Err = ();
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        match s {
+            "" => Ok(SubdiagnosticSuggestionKind::Normal),
+            "_short" => Ok(SubdiagnosticSuggestionKind::Short),
+            "_hidden" => Ok(SubdiagnosticSuggestionKind::Hidden),
+            "_verbose" => Ok(SubdiagnosticSuggestionKind::Verbose),
+            _ => Err(()),
+        }
+    }
+}
+
+impl SubdiagnosticSuggestionKind {
+    pub fn to_suggestion_style(&self) -> TokenStream {
+        match self {
+            SubdiagnosticSuggestionKind::Normal => {
+                quote! { rustc_errors::SuggestionStyle::ShowCode }
+            }
+            SubdiagnosticSuggestionKind::Short => {
+                quote! { rustc_errors::SuggestionStyle::HideCodeInline }
+            }
+            SubdiagnosticSuggestionKind::Hidden => {
+                quote! { rustc_errors::SuggestionStyle::HideCodeAlways }
+            }
+            SubdiagnosticSuggestionKind::Verbose => {
+                quote! { rustc_errors::SuggestionStyle::ShowAlways }
+            }
+        }
+    }
+}
+
 /// Which kind of subdiagnostic is being created from a variant?
-#[derive(Clone, Copy)]
+#[derive(Clone)]
 enum SubdiagnosticKind {
     /// `#[label(...)]`
     Label,
@@ -40,31 +73,9 @@ enum SubdiagnosticKind {
     /// `#[warning(...)]`
     Warn,
     /// `#[suggestion{,_short,_hidden,_verbose}]`
-    Suggestion(SubdiagnosticSuggestionKind),
-}
-
-impl FromStr for SubdiagnosticKind {
-    type Err = ();
-
-    fn from_str(s: &str) -> Result<Self, Self::Err> {
-        match s {
-            "label" => Ok(SubdiagnosticKind::Label),
-            "note" => Ok(SubdiagnosticKind::Note),
-            "help" => Ok(SubdiagnosticKind::Help),
-            "warning" => Ok(SubdiagnosticKind::Warn),
-            "suggestion" => Ok(SubdiagnosticKind::Suggestion(SubdiagnosticSuggestionKind::Normal)),
-            "suggestion_short" => {
-                Ok(SubdiagnosticKind::Suggestion(SubdiagnosticSuggestionKind::Short))
-            }
-            "suggestion_hidden" => {
-                Ok(SubdiagnosticKind::Suggestion(SubdiagnosticSuggestionKind::Hidden))
-            }
-            "suggestion_verbose" => {
-                Ok(SubdiagnosticKind::Suggestion(SubdiagnosticSuggestionKind::Verbose))
-            }
-            _ => Err(()),
-        }
-    }
+    Suggestion { suggestion_kind: SubdiagnosticSuggestionKind, code: TokenStream },
+    /// `#[multipart_suggestion{,_short,_hidden,_verbose}]`
+    MultipartSuggestion { suggestion_kind: SubdiagnosticSuggestionKind },
 }
 
 impl quote::IdentFragment for SubdiagnosticKind {
@@ -74,17 +85,9 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             SubdiagnosticKind::Note => write!(f, "note"),
             SubdiagnosticKind::Help => write!(f, "help"),
             SubdiagnosticKind::Warn => write!(f, "warn"),
-            SubdiagnosticKind::Suggestion(SubdiagnosticSuggestionKind::Normal) => {
-                write!(f, "suggestion")
-            }
-            SubdiagnosticKind::Suggestion(SubdiagnosticSuggestionKind::Short) => {
-                write!(f, "suggestion_short")
-            }
-            SubdiagnosticKind::Suggestion(SubdiagnosticSuggestionKind::Hidden) => {
-                write!(f, "suggestion_hidden")
-            }
-            SubdiagnosticKind::Suggestion(SubdiagnosticSuggestionKind::Verbose) => {
-                write!(f, "suggestion_verbose")
+            SubdiagnosticKind::Suggestion { .. } => write!(f, "suggestion_with_style"),
+            SubdiagnosticKind::MultipartSuggestion { .. } => {
+                write!(f, "multipart_suggestion_with_style")
             }
         }
     }
@@ -148,11 +151,9 @@ pub(crate) fn into_tokens(self) -> TokenStream {
                     variant,
                     span,
                     fields: fields_map,
-                    kinds: Vec::new(),
-                    slugs: Vec::new(),
-                    code: None,
                     span_field: None,
                     applicability: None,
+                    has_suggestion_parts: false,
                 };
                 builder.into_tokens().unwrap_or_else(|v| v.to_compile_error())
             });
@@ -193,21 +194,15 @@ struct SessionSubdiagnosticDeriveBuilder<'a> {
     /// derive builder.
     fields: HashMap<String, TokenStream>,
 
-    /// Subdiagnostic kind of the type/variant.
-    kinds: Vec<(SubdiagnosticKind, proc_macro::Span)>,
-
-    /// Slugs of the subdiagnostic - corresponds to the Fluent identifier for the message - from the
-    /// `#[kind(slug)]` attribute on the type or variant.
-    slugs: Vec<(Path, proc_macro::Span)>,
-    /// If a suggestion, the code to suggest as a replacement - from the `#[kind(code = "...")]`
-    /// attribute on the type or variant.
-    code: Option<(TokenStream, proc_macro::Span)>,
-
     /// Identifier for the binding to the `#[primary_span]` field.
     span_field: Option<(proc_macro2::Ident, proc_macro::Span)>,
     /// If a suggestion, the identifier for the binding to the `#[applicability]` field or a
     /// `rustc_errors::Applicability::*` variant directly.
     applicability: Option<(TokenStream, proc_macro::Span)>,
+
+    /// Set to true when a `#[suggestion_part]` field is encountered, used to generate an error
+    /// during finalization if still `false`.
+    has_suggestion_parts: bool,
 }
 
 impl<'a> HasFieldMap for SessionSubdiagnosticDeriveBuilder<'a> {
@@ -216,125 +211,162 @@ fn get_field_binding(&self, field: &String) -> Option<&TokenStream> {
     }
 }
 
+/// Provides frequently-needed information about the diagnostic kinds being derived for this type.
+#[derive(Clone, Copy, Debug)]
+struct KindsStatistics {
+    has_multipart_suggestion: bool,
+    all_multipart_suggestions: bool,
+    has_normal_suggestion: bool,
+}
+
+impl<'a> FromIterator<&'a SubdiagnosticKind> for KindsStatistics {
+    fn from_iter<T: IntoIterator<Item = &'a SubdiagnosticKind>>(kinds: T) -> Self {
+        let mut ret = Self {
+            has_multipart_suggestion: false,
+            all_multipart_suggestions: true,
+            has_normal_suggestion: false,
+        };
+        for kind in kinds {
+            if let SubdiagnosticKind::MultipartSuggestion { .. } = kind {
+                ret.has_multipart_suggestion = true;
+            } else {
+                ret.all_multipart_suggestions = false;
+            }
+
+            if let SubdiagnosticKind::Suggestion { .. } = kind {
+                ret.has_normal_suggestion = true;
+            }
+        }
+        ret
+    }
+}
+
 impl<'a> SessionSubdiagnosticDeriveBuilder<'a> {
-    fn identify_kind(&mut self) -> Result<(), DiagnosticDeriveError> {
-        for (i, attr) in self.variant.ast().attrs.iter().enumerate() {
+    fn identify_kind(&mut self) -> Result<Vec<(SubdiagnosticKind, Path)>, DiagnosticDeriveError> {
+        let mut kind_slugs = vec![];
+
+        for attr in self.variant.ast().attrs {
             let span = attr.span().unwrap();
 
             let name = attr.path.segments.last().unwrap().ident.to_string();
             let name = name.as_str();
 
             let meta = attr.parse_meta()?;
-            let kind = match meta {
-                Meta::List(MetaList { ref nested, .. }) => {
-                    let mut nested_iter = nested.into_iter();
-                    if let Some(nested_attr) = nested_iter.next() {
-                        match nested_attr {
-                            NestedMeta::Meta(Meta::Path(path)) => {
-                                self.slugs.push((path.clone(), span));
-                            }
-                            NestedMeta::Meta(meta @ Meta::NameValue(_))
-                                if matches!(
-                                    meta.path().segments.last().unwrap().ident.to_string().as_str(),
-                                    "code" | "applicability"
-                                ) =>
-                            {
-                                // don't error for valid follow-up attributes
-                            }
-                            nested_attr => {
-                                throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
-                                    diag.help(
-                                        "first argument of the attribute should be the diagnostic \
-                                         slug",
-                                    )
-                                })
-                            }
-                        };
-                    }
+            let Meta::List(MetaList { ref nested, .. }) = meta else {
+                throw_invalid_attr!(attr, &meta);
+            };
 
-                    for nested_attr in nested_iter {
-                        let meta = match nested_attr {
-                            NestedMeta::Meta(ref meta) => meta,
-                            _ => throw_invalid_nested_attr!(attr, &nested_attr),
-                        };
-
-                        let span = meta.span().unwrap();
-                        let nested_name = meta.path().segments.last().unwrap().ident.to_string();
-                        let nested_name = nested_name.as_str();
-
-                        match meta {
-                            Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) => {
-                                match nested_name {
-                                    "code" => {
-                                        let formatted_str = self.build_format(&s.value(), s.span());
-                                        self.code.set_once((formatted_str, span));
-                                    }
-                                    "applicability" => {
-                                        let value = match Applicability::from_str(&s.value()) {
-                                            Ok(v) => v,
-                                            Err(()) => {
-                                                span_err(span, "invalid applicability").emit();
-                                                Applicability::Unspecified
-                                            }
-                                        };
-                                        self.applicability.set_once((quote! { #value }, span));
-                                    }
-                                    _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
-                                        diag.help(
-                                            "only `code` and `applicability` are valid nested \
-                                             attributes",
-                                        )
-                                    }),
-                                }
-                            }
-                            _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
-                                if matches!(meta, Meta::Path(_)) {
-                                    diag.help(
-                                        "a diagnostic slug must be the first argument to the \
-                                         attribute",
-                                    )
-                                } else {
-                                    diag
-                                }
-                            }),
-                        }
+            let mut kind = match name {
+                "label" => SubdiagnosticKind::Label,
+                "note" => SubdiagnosticKind::Note,
+                "help" => SubdiagnosticKind::Help,
+                "warning" => SubdiagnosticKind::Warn,
+                _ => {
+                    if let Some(suggestion_kind) =
+                        name.strip_prefix("suggestion").and_then(|s| s.parse().ok())
+                    {
+                        SubdiagnosticKind::Suggestion { suggestion_kind, code: TokenStream::new() }
+                    } else if let Some(suggestion_kind) =
+                        name.strip_prefix("multipart_suggestion").and_then(|s| s.parse().ok())
+                    {
+                        SubdiagnosticKind::MultipartSuggestion { suggestion_kind }
+                    } else {
+                        throw_invalid_attr!(attr, &meta);
                     }
-
-                    let Ok(kind) = SubdiagnosticKind::from_str(name) else {
-                        throw_invalid_attr!(attr, &meta)
-                    };
-
-                    kind
                 }
-                _ => throw_invalid_attr!(attr, &meta),
             };
 
-            if matches!(
-                kind,
-                SubdiagnosticKind::Label | SubdiagnosticKind::Help | SubdiagnosticKind::Note
-            ) && self.code.is_some()
-            {
-                throw_span_err!(
-                    span,
-                    &format!("`code` is not a valid nested attribute of a `{}` attribute", name)
-                );
+            let mut slug = None;
+            let mut code = None;
+
+            let mut nested_iter = nested.into_iter();
+            if let Some(nested_attr) = nested_iter.next() {
+                match nested_attr {
+                    NestedMeta::Meta(Meta::Path(path)) => {
+                        slug.set_once((path.clone(), span));
+                    }
+                    NestedMeta::Meta(meta @ Meta::NameValue(_))
+                        if matches!(
+                            meta.path().segments.last().unwrap().ident.to_string().as_str(),
+                            "code" | "applicability"
+                        ) =>
+                    {
+                        // Don't error for valid follow-up attributes.
+                    }
+                    nested_attr => {
+                        throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
+                            diag.help(
+                                "first argument of the attribute should be the diagnostic \
+                                 slug",
+                            )
+                        })
+                    }
+                };
             }
 
-            if matches!(
-                kind,
-                SubdiagnosticKind::Label | SubdiagnosticKind::Help | SubdiagnosticKind::Note
-            ) && self.applicability.is_some()
-            {
-                throw_span_err!(
-                    span,
-                    &format!(
-                        "`applicability` is not a valid nested attribute of a `{}` attribute",
-                        name
-                    )
-                );
+            for nested_attr in nested_iter {
+                let meta = match nested_attr {
+                    NestedMeta::Meta(ref meta) => meta,
+                    _ => throw_invalid_nested_attr!(attr, &nested_attr),
+                };
+
+                let span = meta.span().unwrap();
+                let nested_name = meta.path().segments.last().unwrap().ident.to_string();
+                let nested_name = nested_name.as_str();
+
+                let value = match meta {
+                    Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(value), .. }) => value,
+                    Meta::Path(_) => throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
+                        diag.help("a diagnostic slug must be the first argument to the attribute")
+                    }),
+                    _ => throw_invalid_nested_attr!(attr, &nested_attr),
+                };
+
+                match nested_name {
+                    "code" => {
+                        if matches!(kind, SubdiagnosticKind::Suggestion { .. }) {
+                            let formatted_str = self.build_format(&value.value(), value.span());
+                            code.set_once((formatted_str, span));
+                        } else {
+                            span_err(
+                                span,
+                                &format!(
+                                    "`code` is not a valid nested attribute of a `{}` attribute",
+                                    name
+                                ),
+                            )
+                            .emit();
+                        }
+                    }
+                    "applicability" => {
+                        if matches!(
+                            kind,
+                            SubdiagnosticKind::Suggestion { .. }
+                                | SubdiagnosticKind::MultipartSuggestion { .. }
+                        ) {
+                            let value =
+                                Applicability::from_str(&value.value()).unwrap_or_else(|()| {
+                                    span_err(span, "invalid applicability").emit();
+                                    Applicability::Unspecified
+                                });
+                            self.applicability.set_once((quote! { #value }, span));
+                        } else {
+                            span_err(
+                                span,
+                                &format!(
+                                    "`applicability` is not a valid nested attribute of a `{}` attribute",
+                                    name
+                                )
+                            ).emit();
+                        }
+                    }
+                    _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
+                        diag.help("only `code` and `applicability` are valid nested attributes")
+                    }),
+                }
             }
 
-            if self.slugs.len() != i + 1 {
+            let Some((slug, _)) = slug else {
                 throw_span_err!(
                     span,
                     &format!(
@@ -342,146 +374,334 @@ fn identify_kind(&mut self) -> Result<(), DiagnosticDeriveError> {
                         name
                     )
                 );
+            };
+
+            match kind {
+                SubdiagnosticKind::Suggestion { code: ref mut code_field, .. } => {
+                    let Some((code, _)) = code else {
+                        throw_span_err!(span, "suggestion without `code = \"...\"`");
+                    };
+                    *code_field = code;
+                }
+                SubdiagnosticKind::Label
+                | SubdiagnosticKind::Note
+                | SubdiagnosticKind::Help
+                | SubdiagnosticKind::Warn
+                | SubdiagnosticKind::MultipartSuggestion { .. } => {}
             }
 
-            self.kinds.push((kind, span));
+            kind_slugs.push((kind, slug))
         }
 
-        Ok(())
+        Ok(kind_slugs)
     }
 
-    fn generate_field_code(
+    /// Generates the code for a field with no attributes.
+    fn generate_field_set_arg(&mut self, binding: &BindingInfo<'_>) -> TokenStream {
+        let ast = binding.ast();
+        assert_eq!(ast.attrs.len(), 0, "field with attribute used as diagnostic arg");
+
+        let diag = &self.diag;
+        let ident = ast.ident.as_ref().unwrap();
+        quote! {
+            #diag.set_arg(
+                stringify!(#ident),
+                #binding
+            );
+        }
+    }
+
+    /// Generates the necessary code for all attributes on a field.
+    fn generate_field_attr_code(
         &mut self,
         binding: &BindingInfo<'_>,
-        have_suggestion: bool,
-    ) -> Result<TokenStream, DiagnosticDeriveError> {
+        kind_stats: KindsStatistics,
+    ) -> TokenStream {
         let ast = binding.ast();
+        assert!(ast.attrs.len() > 0, "field without attributes generating attr code");
 
+        // Abstract over `Vec<T>` and `Option<T>` fields using `FieldInnerTy`, which will
+        // apply the generated code on each element in the `Vec` or `Option`.
         let inner_ty = FieldInnerTy::from_type(&ast.ty);
-        let info = FieldInfo {
-            binding: binding,
-            ty: inner_ty.inner_type().unwrap_or(&ast.ty),
-            span: &ast.span(),
-        };
+        ast.attrs
+            .iter()
+            .map(|attr| {
+                let info = FieldInfo {
+                    binding,
+                    ty: inner_ty.inner_type().unwrap_or(&ast.ty),
+                    span: &ast.span(),
+                };
 
-        for attr in &ast.attrs {
-            let name = attr.path.segments.last().unwrap().ident.to_string();
-            let name = name.as_str();
-            let span = attr.span().unwrap();
+                let generated = self
+                    .generate_field_code_inner(kind_stats, attr, info)
+                    .unwrap_or_else(|v| v.to_compile_error());
 
-            let meta = attr.parse_meta()?;
-            match meta {
-                Meta::Path(_) => match name {
-                    "primary_span" => {
-                        report_error_if_not_applied_to_span(attr, &info)?;
-                        self.span_field.set_once((binding.binding.clone(), span));
-                        return Ok(quote! {});
-                    }
-                    "applicability" if have_suggestion => {
-                        report_error_if_not_applied_to_applicability(attr, &info)?;
-                        let binding = binding.binding.clone();
-                        self.applicability.set_once((quote! { #binding }, span));
-                        return Ok(quote! {});
-                    }
-                    "applicability" => {
-                        span_err(span, "`#[applicability]` is only valid on suggestions").emit();
-                        return Ok(quote! {});
-                    }
-                    "skip_arg" => {
-                        return Ok(quote! {});
-                    }
-                    _ => throw_invalid_attr!(attr, &meta, |diag| {
+                inner_ty.with(binding, generated)
+            })
+            .collect()
+    }
+
+    fn generate_field_code_inner(
+        &mut self,
+        kind_stats: KindsStatistics,
+        attr: &Attribute,
+        info: FieldInfo<'_>,
+    ) -> Result<TokenStream, DiagnosticDeriveError> {
+        let meta = attr.parse_meta()?;
+        match meta {
+            Meta::Path(path) => self.generate_field_code_inner_path(kind_stats, attr, info, path),
+            Meta::List(list @ MetaList { .. }) => {
+                self.generate_field_code_inner_list(kind_stats, attr, info, list)
+            }
+            _ => throw_invalid_attr!(attr, &meta),
+        }
+    }
+
+    /// Generates the code for a `[Meta::Path]`-like attribute on a field (e.g. `#[primary_span]`).
+    fn generate_field_code_inner_path(
+        &mut self,
+        kind_stats: KindsStatistics,
+        attr: &Attribute,
+        info: FieldInfo<'_>,
+        path: Path,
+    ) -> Result<TokenStream, DiagnosticDeriveError> {
+        let span = attr.span().unwrap();
+        let ident = &path.segments.last().unwrap().ident;
+        let name = ident.to_string();
+        let name = name.as_str();
+
+        match name {
+            "skip_arg" => Ok(quote! {}),
+            "primary_span" => {
+                if kind_stats.has_multipart_suggestion {
+                    throw_invalid_attr!(attr, &Meta::Path(path), |diag| {
                         diag.help(
-                            "only `primary_span`, `applicability` and `skip_arg` are valid field \
-                             attributes",
+                            "multipart suggestions use one or more `#[suggestion_part]`s rather \
+                            than one `#[primary_span]`",
                         )
-                    }),
-                },
-                _ => throw_invalid_attr!(attr, &meta),
+                    })
+                }
+
+                report_error_if_not_applied_to_span(attr, &info)?;
+
+                let binding = info.binding.binding.clone();
+                self.span_field.set_once((binding, span));
+
+                Ok(quote! {})
             }
+            "suggestion_part" => {
+                self.has_suggestion_parts = true;
+
+                if kind_stats.has_multipart_suggestion {
+                    span_err(span, "`#[suggestion_part(...)]` attribute without `code = \"...\"`")
+                        .emit();
+                    Ok(quote! {})
+                } else {
+                    throw_invalid_attr!(attr, &Meta::Path(path), |diag| {
+                        diag.help(
+                                "`#[suggestion_part(...)]` is only valid in multipart suggestions, use `#[primary_span]` instead",
+                            )
+                    });
+                }
+            }
+            "applicability" => {
+                if kind_stats.has_multipart_suggestion || kind_stats.has_normal_suggestion {
+                    report_error_if_not_applied_to_applicability(attr, &info)?;
+
+                    let binding = info.binding.binding.clone();
+                    self.applicability.set_once((quote! { #binding }, span));
+                } else {
+                    span_err(span, "`#[applicability]` is only valid on suggestions").emit();
+                }
+
+                Ok(quote! {})
+            }
+            _ => throw_invalid_attr!(attr, &Meta::Path(path), |diag| {
+                let mut span_attrs = vec![];
+                if kind_stats.has_multipart_suggestion {
+                    span_attrs.push("suggestion_part");
+                }
+                if !kind_stats.all_multipart_suggestions {
+                    span_attrs.push("primary_span")
+                }
+                diag.help(format!(
+                    "only `{}`, `applicability` and `skip_arg` are valid field attributes",
+                    span_attrs.join(", ")
+                ))
+            }),
         }
+    }
 
-        let ident = ast.ident.as_ref().unwrap();
+    /// Generates the code for a `[Meta::List]`-like attribute on a field (e.g.
+    /// `#[suggestion_part(code = "...")]`).
+    fn generate_field_code_inner_list(
+        &mut self,
+        kind_stats: KindsStatistics,
+        attr: &Attribute,
+        info: FieldInfo<'_>,
+        list: MetaList,
+    ) -> Result<TokenStream, DiagnosticDeriveError> {
+        let span = attr.span().unwrap();
+        let ident = &list.path.segments.last().unwrap().ident;
+        let name = ident.to_string();
+        let name = name.as_str();
+
+        match name {
+            "suggestion_part" => {
+                if !kind_stats.has_multipart_suggestion {
+                    throw_invalid_attr!(attr, &Meta::List(list), |diag| {
+                        diag.help(
+                            "`#[suggestion_part(...)]` is only valid in multipart suggestions",
+                        )
+                    })
+                }
 
-        let diag = &self.diag;
-        let generated = quote! {
-            #diag.set_arg(
-                stringify!(#ident),
-                #binding
-            );
-        };
+                self.has_suggestion_parts = true;
+
+                report_error_if_not_applied_to_span(attr, &info)?;
+
+                let mut code = None;
+                for nested_attr in list.nested.iter() {
+                    let NestedMeta::Meta(ref meta) = nested_attr else {
+                        throw_invalid_nested_attr!(attr, &nested_attr);
+                    };
+
+                    let span = meta.span().unwrap();
+                    let nested_name = meta.path().segments.last().unwrap().ident.to_string();
+                    let nested_name = nested_name.as_str();
 
-        Ok(inner_ty.with(binding, generated))
+                    let Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(value), .. }) = meta else {
+                        throw_invalid_nested_attr!(attr, &nested_attr);
+                    };
+
+                    match nested_name {
+                        "code" => {
+                            let formatted_str = self.build_format(&value.value(), value.span());
+                            code.set_once((formatted_str, span));
+                        }
+                        _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
+                            diag.help("`code` is the only valid nested attribute")
+                        }),
+                    }
+                }
+
+                let Some((code, _)) = code else {
+                    span_err(span, "`#[suggestion_part(...)]` attribute without `code = \"...\"`")
+                        .emit();
+                    return Ok(quote! {});
+                };
+                let binding = info.binding;
+
+                Ok(quote! { suggestions.push((#binding, #code)); })
+            }
+            _ => throw_invalid_attr!(attr, &Meta::List(list), |diag| {
+                let mut span_attrs = vec![];
+                if kind_stats.has_multipart_suggestion {
+                    span_attrs.push("suggestion_part");
+                }
+                if !kind_stats.all_multipart_suggestions {
+                    span_attrs.push("primary_span")
+                }
+                diag.help(format!(
+                    "only `{}`, `applicability` and `skip_arg` are valid field attributes",
+                    span_attrs.join(", ")
+                ))
+            }),
+        }
     }
 
-    fn into_tokens(&mut self) -> Result<TokenStream, DiagnosticDeriveError> {
-        self.identify_kind()?;
-        if self.kinds.is_empty() {
+    pub fn into_tokens(&mut self) -> Result<TokenStream, DiagnosticDeriveError> {
+        let kind_slugs = self.identify_kind()?;
+        if kind_slugs.is_empty() {
             throw_span_err!(
                 self.variant.ast().ident.span().unwrap(),
                 "subdiagnostic kind not specified"
             );
         };
-        let have_suggestion =
-            self.kinds.iter().any(|(k, _)| matches!(k, SubdiagnosticKind::Suggestion(_)));
-        let mut args = TokenStream::new();
-        for binding in self.variant.bindings() {
-            let arg = self
-                .generate_field_code(binding, have_suggestion)
-                .unwrap_or_else(|v| v.to_compile_error());
-            args.extend(arg);
-        }
-        let mut tokens = TokenStream::new();
-        for ((kind, _), (slug, _)) in self.kinds.iter().zip(&self.slugs) {
-            let code = match self.code.as_ref() {
-                Some((code, _)) => Some(quote! { #code }),
-                None if have_suggestion => {
-                    span_err(self.span, "suggestion without `code = \"...\"`").emit();
-                    Some(quote! { /* macro error */ "..." })
-                }
-                None => None,
-            };
 
-            let span_field = self.span_field.as_ref().map(|(span, _)| span);
-            let applicability = match self.applicability.clone() {
-                Some((applicability, _)) => Some(applicability),
-                None if have_suggestion => {
-                    span_err(self.span, "suggestion without `applicability`").emit();
-                    Some(quote! { rustc_errors::Applicability::Unspecified })
-                }
-                None => None,
-            };
+        let kind_stats: KindsStatistics = kind_slugs.iter().map(|(kind, _slug)| kind).collect();
+
+        let init = if kind_stats.has_multipart_suggestion {
+            quote! { let mut suggestions = Vec::new(); }
+        } else {
+            quote! {}
+        };
+
+        let attr_args: TokenStream = self
+            .variant
+            .bindings()
+            .iter()
+            .filter(|binding| !binding.ast().attrs.is_empty())
+            .map(|binding| self.generate_field_attr_code(binding, kind_stats))
+            .collect();
+
+        let span_field = self.span_field.as_ref().map(|(span, _)| span);
+        let applicability = self.applicability.take().map_or_else(
+            || quote! { rustc_errors::Applicability::Unspecified },
+            |(applicability, _)| applicability,
+        );
 
-            let diag = &self.diag;
+        let diag = &self.diag;
+        let mut calls = TokenStream::new();
+        for (kind, slug) in kind_slugs {
             let name = format_ident!("{}{}", if span_field.is_some() { "span_" } else { "" }, kind);
             let message = quote! { rustc_errors::fluent::#slug };
-            let call = if matches!(kind, SubdiagnosticKind::Suggestion(..)) {
-                if let Some(span) = span_field {
-                    quote! { #diag.#name(#span, #message, #code, #applicability); }
-                } else {
-                    span_err(self.span, "suggestion without `#[primary_span]` field").emit();
-                    quote! { unreachable!(); }
+            let call = match kind {
+                SubdiagnosticKind::Suggestion { suggestion_kind, code } => {
+                    if let Some(span) = span_field {
+                        let style = suggestion_kind.to_suggestion_style();
+
+                        quote! { #diag.#name(#span, #message, #code, #applicability, #style); }
+                    } else {
+                        span_err(self.span, "suggestion without `#[primary_span]` field").emit();
+                        quote! { unreachable!(); }
+                    }
                 }
-            } else if matches!(kind, SubdiagnosticKind::Label) {
-                if let Some(span) = span_field {
-                    quote! { #diag.#name(#span, #message); }
-                } else {
-                    span_err(self.span, "label without `#[primary_span]` field").emit();
-                    quote! { unreachable!(); }
+                SubdiagnosticKind::MultipartSuggestion { suggestion_kind } => {
+                    if !self.has_suggestion_parts {
+                        span_err(
+                            self.span,
+                            "multipart suggestion without any `#[suggestion_part(...)]` fields",
+                        )
+                        .emit();
+                    }
+
+                    let style = suggestion_kind.to_suggestion_style();
+
+                    quote! { #diag.#name(#message, suggestions, #applicability, #style); }
                 }
-            } else {
-                if let Some(span) = span_field {
-                    quote! { #diag.#name(#span, #message); }
-                } else {
-                    quote! { #diag.#name(#message); }
+                SubdiagnosticKind::Label => {
+                    if let Some(span) = span_field {
+                        quote! { #diag.#name(#span, #message); }
+                    } else {
+                        span_err(self.span, "label without `#[primary_span]` field").emit();
+                        quote! { unreachable!(); }
+                    }
+                }
+                _ => {
+                    if let Some(span) = span_field {
+                        quote! { #diag.#name(#span, #message); }
+                    } else {
+                        quote! { #diag.#name(#message); }
+                    }
                 }
             };
-            tokens.extend(quote! {
-                #call
-                #args
-            });
+            calls.extend(call);
         }
 
-        Ok(tokens)
+        let plain_args: TokenStream = self
+            .variant
+            .bindings()
+            .iter()
+            .filter(|binding| binding.ast().attrs.is_empty())
+            .map(|binding| self.generate_field_set_arg(binding))
+            .collect();
+
+        Ok(quote! {
+            #init
+            #attr_args
+            #calls
+            #plain_args
+        })
     }
 }
index 708d0b1fd8a301818b8b667233975772cfffe0ea..cfcceecbef40ee911e04d62d958d4d31076b4169 100644 (file)
@@ -1,5 +1,9 @@
 //! Validates all used crates and extern libraries and loads their metadata
 
+use crate::errors::{
+    ConflictingGlobalAlloc, CrateNotPanicRuntime, GlobalAllocRequired, NoMultipleGlobalAlloc,
+    NoPanicStrategy, NoTransitiveNeedsDep, NotProfilerRuntime, ProfilerBuiltinsNeedsCore,
+};
 use crate::locator::{CrateError, CrateLocator, CratePaths};
 use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob};
 
@@ -29,7 +33,6 @@
 use std::ops::Fn;
 use std::path::Path;
 use std::{cmp, env};
-use tracing::{debug, info};
 
 #[derive(Clone)]
 pub struct CStore {
@@ -263,7 +266,7 @@ pub fn into_cstore(self) -> CStore {
     fn existing_match(&self, name: Symbol, hash: Option<Svh>, kind: PathKind) -> Option<CrateNum> {
         for (cnum, data) in self.cstore.iter_crate_data() {
             if data.name() != name {
-                tracing::trace!("{} did not match {}", data.name(), name);
+                trace!("{} did not match {}", data.name(), name);
                 continue;
             }
 
@@ -746,15 +749,10 @@ fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
         // Sanity check the loaded crate to ensure it is indeed a panic runtime
         // and the panic strategy is indeed what we thought it was.
         if !data.is_panic_runtime() {
-            self.sess.err(&format!("the crate `{}` is not a panic runtime", name));
+            self.sess.emit_err(CrateNotPanicRuntime { crate_name: name });
         }
         if data.required_panic_strategy() != Some(desired_strategy) {
-            self.sess.err(&format!(
-                "the crate `{}` does not have the panic \
-                                    strategy `{}`",
-                name,
-                desired_strategy.desc()
-            ));
+            self.sess.emit_err(NoPanicStrategy { crate_name: name, strategy: desired_strategy });
         }
 
         self.cstore.injected_panic_runtime = Some(cnum);
@@ -774,10 +772,7 @@ fn inject_profiler_runtime(&mut self, krate: &ast::Crate) {
 
         let name = Symbol::intern(&self.sess.opts.unstable_opts.profiler_runtime);
         if name == sym::profiler_builtins && self.sess.contains_name(&krate.attrs, sym::no_core) {
-            self.sess.err(
-                "`profiler_builtins` crate (required by compiler options) \
-                        is not compatible with crate attribute `#![no_core]`",
-            );
+            self.sess.emit_err(ProfilerBuiltinsNeedsCore);
         }
 
         let Some(cnum) = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit) else { return; };
@@ -785,18 +780,14 @@ fn inject_profiler_runtime(&mut self, krate: &ast::Crate) {
 
         // Sanity check the loaded crate to ensure it is indeed a profiler runtime
         if !data.is_profiler_runtime() {
-            self.sess.err(&format!("the crate `{}` is not a profiler runtime", name));
+            self.sess.emit_err(NotProfilerRuntime { crate_name: name });
         }
     }
 
     fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
         self.cstore.has_global_allocator = match &*global_allocator_spans(&self.sess, krate) {
             [span1, span2, ..] => {
-                self.sess
-                    .struct_span_err(*span2, "cannot define multiple global allocators")
-                    .span_label(*span2, "cannot define a new global allocator")
-                    .span_label(*span1, "previous global allocator defined here")
-                    .emit();
+                self.sess.emit_err(NoMultipleGlobalAlloc { span2: *span2, span1: *span1 });
                 true
             }
             spans => !spans.is_empty(),
@@ -832,11 +823,10 @@ fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
             if data.has_global_allocator() {
                 match global_allocator {
                     Some(other_crate) => {
-                        self.sess.err(&format!(
-                        "the `#[global_allocator]` in {} conflicts with global allocator in: {}",
-                        other_crate,
-                        data.name()
-                    ));
+                        self.sess.emit_err(ConflictingGlobalAlloc {
+                            crate_name: data.name(),
+                            other_crate_name: other_crate,
+                        });
                     }
                     None => global_allocator = Some(data.name()),
                 }
@@ -855,10 +845,7 @@ fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
         if !self.sess.contains_name(&krate.attrs, sym::default_lib_allocator)
             && !self.cstore.iter_crate_data().any(|(_, data)| data.has_default_lib_allocator())
         {
-            self.sess.err(
-                "no global memory allocator found but one is required; link to std or add \
-                 `#[global_allocator]` to a static item that implements the GlobalAlloc trait",
-            );
+            self.sess.emit_err(GlobalAllocRequired);
         }
         self.cstore.allocator_kind = Some(AllocatorKind::Default);
     }
@@ -882,14 +869,11 @@ fn inject_dependency_if(
         for dep in self.cstore.crate_dependencies_in_reverse_postorder(krate) {
             let data = self.cstore.get_crate_data(dep);
             if needs_dep(&data) {
-                self.sess.err(&format!(
-                    "the crate `{}` cannot depend \
-                                        on a crate that needs {}, but \
-                                        it depends on `{}`",
-                    self.cstore.get_crate_data(krate).name(),
-                    what,
-                    data.name()
-                ));
+                self.sess.emit_err(NoTransitiveNeedsDep {
+                    crate_name: self.cstore.get_crate_data(krate).name(),
+                    needs_crate_name: what,
+                    deps_crate_name: data.name(),
+                });
             }
         }
 
index b765c34f8e364d2d4ec15846bd5d4daa5718a9a9..6112ec9e4e948b6b8d01068f57336c7f83d84067 100644 (file)
 //! than finding a number of solutions (there are normally quite a few).
 
 use crate::creader::CStore;
+use crate::errors::{
+    BadPanicStrategy, CrateDepMultiple, IncompatiblePanicInDropStrategy, LibRequired,
+    RequiredPanicStrategy, RlibRequired, TwoPanicRuntimes,
+};
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def_id::CrateNum;
@@ -136,11 +140,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
                 if src.rlib.is_some() {
                     continue;
                 }
-                sess.err(&format!(
-                    "crate `{}` required to be available in rlib format, \
-                                   but was not found in this form",
-                    tcx.crate_name(cnum)
-                ));
+                sess.emit_err(RlibRequired { crate_name: tcx.crate_name(cnum) });
             }
             return Vec::new();
         }
@@ -158,11 +158,11 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
         let name = tcx.crate_name(cnum);
         let src = tcx.used_crate_source(cnum);
         if src.dylib.is_some() {
-            tracing::info!("adding dylib: {}", name);
+            info!("adding dylib: {}", name);
             add_library(tcx, cnum, RequireDynamic, &mut formats);
             let deps = tcx.dylib_dependency_formats(cnum);
             for &(depnum, style) in deps.iter() {
-                tracing::info!("adding {:?}: {}", style, tcx.crate_name(depnum));
+                info!("adding {:?}: {}", style, tcx.crate_name(depnum));
                 add_library(tcx, depnum, style, &mut formats);
             }
         }
@@ -190,7 +190,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
             && tcx.dep_kind(cnum) == CrateDepKind::Explicit
         {
             assert!(src.rlib.is_some() || src.rmeta.is_some());
-            tracing::info!("adding staticlib: {}", tcx.crate_name(cnum));
+            info!("adding staticlib: {}", tcx.crate_name(cnum));
             add_library(tcx, cnum, RequireStatic, &mut formats);
             ret[cnum.as_usize() - 1] = Linkage::Static;
         }
@@ -224,12 +224,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
                     Linkage::Static => "rlib",
                     _ => "dylib",
                 };
-                sess.err(&format!(
-                    "crate `{}` required to be available in {} format, \
-                                   but was not found in this form",
-                    tcx.crate_name(cnum),
-                    kind
-                ));
+                sess.emit_err(LibRequired { crate_name: tcx.crate_name(cnum), kind: kind });
             }
         }
     }
@@ -253,17 +248,7 @@ fn add_library(
             // This error is probably a little obscure, but I imagine that it
             // can be refined over time.
             if link2 != link || link == RequireStatic {
-                tcx.sess
-                    .struct_err(&format!(
-                        "cannot satisfy dependencies so `{}` only \
-                                              shows up once",
-                        tcx.crate_name(cnum)
-                    ))
-                    .help(
-                        "having upstream crates all available in one format \
-                           will likely make this go away",
-                    )
-                    .emit();
+                tcx.sess.emit_err(CrateDepMultiple { crate_name: tcx.crate_name(cnum) });
             }
         }
         None => {
@@ -360,11 +345,7 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) {
             if let Some((prev, _)) = panic_runtime {
                 let prev_name = tcx.crate_name(prev);
                 let cur_name = tcx.crate_name(cnum);
-                sess.err(&format!(
-                    "cannot link together two \
-                                   panic runtimes: {} and {}",
-                    prev_name, cur_name
-                ));
+                sess.emit_err(TwoPanicRuntimes { prev_name, cur_name });
             }
             panic_runtime = Some((
                 cnum,
@@ -384,13 +365,10 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) {
         // First up, validate that our selected panic runtime is indeed exactly
         // our same strategy.
         if found_strategy != desired_strategy {
-            sess.err(&format!(
-                "the linked panic runtime `{}` is \
-                               not compiled with this crate's \
-                               panic strategy `{}`",
-                tcx.crate_name(runtime_cnum),
-                desired_strategy.desc()
-            ));
+            sess.emit_err(BadPanicStrategy {
+                runtime: tcx.crate_name(runtime_cnum),
+                strategy: desired_strategy,
+            });
         }
 
         // Next up, verify that all other crates are compatible with this panic
@@ -407,28 +385,19 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) {
             }
 
             if let Some(found_strategy) = tcx.required_panic_strategy(cnum) && desired_strategy != found_strategy {
-                sess.err(&format!(
-                    "the crate `{}` requires \
-                               panic strategy `{}` which is \
-                               incompatible with this crate's \
-                               strategy of `{}`",
-                    tcx.crate_name(cnum),
-                    found_strategy.desc(),
-                    desired_strategy.desc()
-                ));
+                sess.emit_err(RequiredPanicStrategy {
+                    crate_name: tcx.crate_name(cnum),
+                    found_strategy,
+                    desired_strategy});
             }
 
             let found_drop_strategy = tcx.panic_in_drop_strategy(cnum);
             if tcx.sess.opts.unstable_opts.panic_in_drop != found_drop_strategy {
-                sess.err(&format!(
-                    "the crate `{}` is compiled with the \
-                               panic-in-drop strategy `{}` which is \
-                               incompatible with this crate's \
-                               strategy of `{}`",
-                    tcx.crate_name(cnum),
-                    found_drop_strategy.desc(),
-                    tcx.sess.opts.unstable_opts.panic_in_drop.desc()
-                ));
+                sess.emit_err(IncompatiblePanicInDropStrategy {
+                    crate_name: tcx.crate_name(cnum),
+                    found_strategy: found_drop_strategy,
+                    desired_strategy: tcx.sess.opts.unstable_opts.panic_in_drop,
+                });
             }
         }
     }
diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs
new file mode 100644 (file)
index 0000000..18d0248
--- /dev/null
@@ -0,0 +1,672 @@
+use std::{
+    io::Error,
+    path::{Path, PathBuf},
+};
+
+use rustc_errors::{error_code, ErrorGuaranteed};
+use rustc_macros::SessionDiagnostic;
+use rustc_session::{config, SessionDiagnostic};
+use rustc_span::{sym, Span, Symbol};
+use rustc_target::spec::{PanicStrategy, TargetTriple};
+
+use crate::locator::CrateFlavor;
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::rlib_required)]
+pub struct RlibRequired {
+    pub crate_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::lib_required)]
+pub struct LibRequired<'a> {
+    pub crate_name: Symbol,
+    pub kind: &'a str,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::crate_dep_multiple)]
+#[help]
+pub struct CrateDepMultiple {
+    pub crate_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::two_panic_runtimes)]
+pub struct TwoPanicRuntimes {
+    pub prev_name: Symbol,
+    pub cur_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::bad_panic_strategy)]
+pub struct BadPanicStrategy {
+    pub runtime: Symbol,
+    pub strategy: PanicStrategy,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::required_panic_strategy)]
+pub struct RequiredPanicStrategy {
+    pub crate_name: Symbol,
+    pub found_strategy: PanicStrategy,
+    pub desired_strategy: PanicStrategy,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::incompatible_panic_in_drop_strategy)]
+pub struct IncompatiblePanicInDropStrategy {
+    pub crate_name: Symbol,
+    pub found_strategy: PanicStrategy,
+    pub desired_strategy: PanicStrategy,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::multiple_names_in_link)]
+pub struct MultipleNamesInLink {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::multiple_kinds_in_link)]
+pub struct MultipleKindsInLink {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::link_name_form)]
+pub struct LinkNameForm {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::link_kind_form)]
+pub struct LinkKindForm {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::link_modifiers_form)]
+pub struct LinkModifiersForm {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::link_cfg_form)]
+pub struct LinkCfgForm {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::wasm_import_form)]
+pub struct WasmImportForm {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::empty_link_name, code = "E0454")]
+pub struct EmptyLinkName {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::link_framework_apple, code = "E0455")]
+pub struct LinkFrameworkApple {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::framework_only_windows, code = "E0455")]
+pub struct FrameworkOnlyWindows {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::unknown_link_kind, code = "E0458")]
+pub struct UnknownLinkKind<'a> {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    pub kind: &'a str,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::multiple_link_modifiers)]
+pub struct MultipleLinkModifiers {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::multiple_cfgs)]
+pub struct MultipleCfgs {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::link_cfg_single_predicate)]
+pub struct LinkCfgSinglePredicate {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::multiple_wasm_import)]
+pub struct MultipleWasmImport {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::unexpected_link_arg)]
+pub struct UnexpectedLinkArg {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::invalid_link_modifier)]
+pub struct InvalidLinkModifier {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::multiple_modifiers)]
+pub struct MultipleModifiers<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub modifier: &'a str,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::bundle_needs_static)]
+pub struct BundleNeedsStatic {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::whole_archive_needs_static)]
+pub struct WholeArchiveNeedsStatic {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::as_needed_compatibility)]
+pub struct AsNeededCompatibility {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::unknown_link_modifier)]
+pub struct UnknownLinkModifier<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub modifier: &'a str,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::incompatible_wasm_link)]
+pub struct IncompatibleWasmLink {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::link_requires_name, code = "E0459")]
+pub struct LinkRequiresName {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::raw_dylib_no_nul)]
+pub struct RawDylibNoNul {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::link_ordinal_raw_dylib)]
+pub struct LinkOrdinalRawDylib {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::lib_framework_apple)]
+pub struct LibFrameworkApple;
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::empty_renaming_target)]
+pub struct EmptyRenamingTarget<'a> {
+    pub lib_name: &'a str,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::renaming_no_link)]
+pub struct RenamingNoLink<'a> {
+    pub lib_name: &'a str,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::multiple_renamings)]
+pub struct MultipleRenamings<'a> {
+    pub lib_name: &'a str,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::no_link_mod_override)]
+pub struct NoLinkModOverride {
+    #[primary_span]
+    pub span: Option<Span>,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::unsupported_abi_i686)]
+pub struct UnsupportedAbiI686 {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::unsupported_abi)]
+pub struct UnsupportedAbi {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::fail_create_file_encoder)]
+pub struct FailCreateFileEncoder {
+    pub err: Error,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::fail_seek_file)]
+pub struct FailSeekFile {
+    pub err: Error,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::fail_write_file)]
+pub struct FailWriteFile {
+    pub err: Error,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::crate_not_panic_runtime)]
+pub struct CrateNotPanicRuntime {
+    pub crate_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::no_panic_strategy)]
+pub struct NoPanicStrategy {
+    pub crate_name: Symbol,
+    pub strategy: PanicStrategy,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::profiler_builtins_needs_core)]
+pub struct ProfilerBuiltinsNeedsCore;
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::not_profiler_runtime)]
+pub struct NotProfilerRuntime {
+    pub crate_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::no_multiple_global_alloc)]
+pub struct NoMultipleGlobalAlloc {
+    #[primary_span]
+    #[label]
+    pub span2: Span,
+    #[label(metadata::prev_global_alloc)]
+    pub span1: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::conflicting_global_alloc)]
+pub struct ConflictingGlobalAlloc {
+    pub crate_name: Symbol,
+    pub other_crate_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::global_alloc_required)]
+pub struct GlobalAllocRequired;
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::no_transitive_needs_dep)]
+pub struct NoTransitiveNeedsDep<'a> {
+    pub crate_name: Symbol,
+    pub needs_crate_name: &'a str,
+    pub deps_crate_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::failed_write_error)]
+pub struct FailedWriteError {
+    pub filename: PathBuf,
+    pub err: Error,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::failed_create_tempdir)]
+pub struct FailedCreateTempdir {
+    pub err: Error,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::failed_create_file)]
+pub struct FailedCreateFile<'a> {
+    pub filename: &'a Path,
+    pub err: Error,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::failed_create_encoded_metadata)]
+pub struct FailedCreateEncodedMetadata {
+    pub err: Error,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::non_ascii_name)]
+pub struct NonAsciiName {
+    #[primary_span]
+    pub span: Span,
+    pub crate_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::extern_location_not_exist)]
+pub struct ExternLocationNotExist<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub crate_name: Symbol,
+    pub location: &'a Path,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::extern_location_not_file)]
+pub struct ExternLocationNotFile<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub crate_name: Symbol,
+    pub location: &'a Path,
+}
+
+pub(crate) struct MultipleCandidates {
+    pub span: Span,
+    pub flavor: CrateFlavor,
+    pub crate_name: Symbol,
+    pub candidates: Vec<PathBuf>,
+}
+
+impl SessionDiagnostic<'_> for MultipleCandidates {
+    fn into_diagnostic(
+        self,
+        sess: &'_ rustc_session::parse::ParseSess,
+    ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
+        let mut diag = sess.struct_err(rustc_errors::fluent::metadata::multiple_candidates);
+        diag.set_arg("crate_name", self.crate_name);
+        diag.set_arg("flavor", self.flavor);
+        diag.code(error_code!(E0465));
+        diag.set_span(self.span);
+        for (i, candidate) in self.candidates.iter().enumerate() {
+            diag.span_note(self.span, &format!("candidate #{}: {}", i + 1, candidate.display()));
+        }
+        diag
+    }
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::multiple_matching_crates, code = "E0464")]
+#[note]
+pub struct MultipleMatchingCrates {
+    #[primary_span]
+    pub span: Span,
+    pub crate_name: Symbol,
+    pub candidates: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::symbol_conflicts_current, code = "E0519")]
+pub struct SymbolConflictsCurrent {
+    #[primary_span]
+    pub span: Span,
+    pub crate_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::symbol_conflicts_others, code = "E0523")]
+pub struct SymbolConflictsOthers {
+    #[primary_span]
+    pub span: Span,
+    pub crate_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::stable_crate_id_collision)]
+pub struct StableCrateIdCollision {
+    #[primary_span]
+    pub span: Span,
+    pub crate_name0: Symbol,
+    pub crate_name1: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::dl_error)]
+pub struct DlError {
+    #[primary_span]
+    pub span: Span,
+    pub err: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::newer_crate_version, code = "E0460")]
+#[note]
+#[note(metadata::found_crate_versions)]
+pub struct NewerCrateVersion {
+    #[primary_span]
+    pub span: Span,
+    pub crate_name: Symbol,
+    pub add_info: String,
+    pub found_crates: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::no_crate_with_triple, code = "E0461")]
+#[note(metadata::found_crate_versions)]
+pub struct NoCrateWithTriple<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub crate_name: Symbol,
+    pub locator_triple: &'a str,
+    pub add_info: String,
+    pub found_crates: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::found_staticlib, code = "E0462")]
+#[note(metadata::found_crate_versions)]
+#[help]
+pub struct FoundStaticlib {
+    #[primary_span]
+    pub span: Span,
+    pub crate_name: Symbol,
+    pub add_info: String,
+    pub found_crates: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::incompatible_rustc, code = "E0514")]
+#[note(metadata::found_crate_versions)]
+#[help]
+pub struct IncompatibleRustc {
+    #[primary_span]
+    pub span: Span,
+    pub crate_name: Symbol,
+    pub add_info: String,
+    pub found_crates: String,
+    pub rustc_version: String,
+}
+
+pub struct InvalidMetadataFiles {
+    pub span: Span,
+    pub crate_name: Symbol,
+    pub add_info: String,
+    pub crate_rejections: Vec<String>,
+}
+
+impl SessionDiagnostic<'_> for InvalidMetadataFiles {
+    fn into_diagnostic(
+        self,
+        sess: &'_ rustc_session::parse::ParseSess,
+    ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
+        let mut diag = sess.struct_err(rustc_errors::fluent::metadata::invalid_meta_files);
+        diag.set_arg("crate_name", self.crate_name);
+        diag.set_arg("add_info", self.add_info);
+        diag.code(error_code!(E0786));
+        diag.set_span(self.span);
+        for crate_rejection in self.crate_rejections {
+            diag.note(crate_rejection);
+        }
+        diag
+    }
+}
+
+pub struct CannotFindCrate {
+    pub span: Span,
+    pub crate_name: Symbol,
+    pub add_info: String,
+    pub missing_core: bool,
+    pub current_crate: String,
+    pub is_nightly_build: bool,
+    pub profiler_runtime: Symbol,
+    pub locator_triple: TargetTriple,
+}
+
+impl SessionDiagnostic<'_> for CannotFindCrate {
+    fn into_diagnostic(
+        self,
+        sess: &'_ rustc_session::parse::ParseSess,
+    ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
+        let mut diag = sess.struct_err(rustc_errors::fluent::metadata::cannot_find_crate);
+        diag.set_arg("crate_name", self.crate_name);
+        diag.set_arg("add_info", self.add_info);
+        diag.set_arg("locator_triple", self.locator_triple.triple());
+        diag.code(error_code!(E0463));
+        diag.set_span(self.span);
+        if (self.crate_name == sym::std || self.crate_name == sym::core)
+            && self.locator_triple != TargetTriple::from_triple(config::host_triple())
+        {
+            if self.missing_core {
+                diag.note(rustc_errors::fluent::metadata::target_not_installed);
+            } else {
+                diag.note(rustc_errors::fluent::metadata::target_no_std_support);
+            }
+            // NOTE: this suggests using rustup, even though the user may not have it installed.
+            // That's because they could choose to install it; or this may give them a hint which
+            // target they need to install from their distro.
+            if self.missing_core {
+                diag.help(rustc_errors::fluent::metadata::consider_downloading_target);
+            }
+            // Suggest using #![no_std]. #[no_core] is unstable and not really supported anyway.
+            // NOTE: this is a dummy span if `extern crate std` was injected by the compiler.
+            // If it's not a dummy, that means someone added `extern crate std` explicitly and
+            // `#![no_std]` won't help.
+            if !self.missing_core && self.span.is_dummy() {
+                diag.note(rustc_errors::fluent::metadata::std_required);
+            }
+            if self.is_nightly_build {
+                diag.help(rustc_errors::fluent::metadata::consider_building_std);
+            }
+        } else if self.crate_name == self.profiler_runtime {
+            diag.note(rustc_errors::fluent::metadata::compiler_missing_profiler);
+        } else if self.crate_name.as_str().starts_with("rustc_") {
+            diag.help(rustc_errors::fluent::metadata::install_missing_components);
+        }
+        diag.span_label(self.span, rustc_errors::fluent::metadata::cant_find_crate);
+        diag
+    }
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::no_dylib_plugin, code = "E0457")]
+pub struct NoDylibPlugin {
+    #[primary_span]
+    pub span: Span,
+    pub crate_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::crate_location_unknown_type)]
+pub struct CrateLocationUnknownType<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub path: &'a Path,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::lib_filename_form)]
+pub struct LibFilenameForm<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub dll_prefix: &'a str,
+    pub dll_suffix: &'a str,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::multiple_import_name_type)]
+pub struct MultipleImportNameType {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::import_name_type_form)]
+pub struct ImportNameTypeForm {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::import_name_type_x86)]
+pub struct ImportNameTypeX86 {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::unknown_import_name_type)]
+pub struct UnknownImportNameType<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub import_name_type: &'a str,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(metadata::import_name_type_raw)]
+pub struct ImportNameTypeRaw {
+    #[primary_span]
+    pub span: Span,
+}
index e6072901aaa43df068a8df0f72d27de5f9980471..f360a586476e70bf4a2e9da3bd4426351d834880 100644 (file)
@@ -1,3 +1,6 @@
+use crate::errors::{
+    FailedCreateEncodedMetadata, FailedCreateFile, FailedCreateTempdir, FailedWriteError,
+};
 use crate::{encode_metadata, EncodedMetadata};
 
 use rustc_data_structures::temp_dir::MaybeTempDir;
@@ -23,8 +26,8 @@ pub fn emit_metadata(sess: &Session, metadata: &[u8], tmpdir: &MaybeTempDir) ->
     let out_filename = tmpdir.as_ref().join(METADATA_FILENAME);
     let result = fs::write(&out_filename, metadata);
 
-    if let Err(e) = result {
-        sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e));
+    if let Err(err) = result {
+        sess.emit_fatal(FailedWriteError { filename: out_filename, err });
     }
 
     out_filename
@@ -65,7 +68,7 @@ enum MetadataKind {
     let metadata_tmpdir = TempFileBuilder::new()
         .prefix("rmeta")
         .tempdir_in(out_filename.parent().unwrap_or_else(|| Path::new("")))
-        .unwrap_or_else(|err| tcx.sess.fatal(&format!("couldn't create a temp dir: {}", err)));
+        .unwrap_or_else(|err| tcx.sess.emit_fatal(FailedCreateTempdir { err }));
     let metadata_tmpdir = MaybeTempDir::new(metadata_tmpdir, tcx.sess.opts.cg.save_temps);
     let metadata_filename = metadata_tmpdir.as_ref().join(METADATA_FILENAME);
 
@@ -73,12 +76,8 @@ enum MetadataKind {
     // This simplifies the creation of the output `out_filename` when requested.
     match metadata_kind {
         MetadataKind::None => {
-            std::fs::File::create(&metadata_filename).unwrap_or_else(|e| {
-                tcx.sess.fatal(&format!(
-                    "failed to create the file {}: {}",
-                    metadata_filename.display(),
-                    e
-                ))
+            std::fs::File::create(&metadata_filename).unwrap_or_else(|err| {
+                tcx.sess.emit_fatal(FailedCreateFile { filename: &metadata_filename, err });
             });
         }
         MetadataKind::Uncompressed | MetadataKind::Compressed => {
@@ -93,8 +92,8 @@ enum MetadataKind {
     // this file always exists.
     let need_metadata_file = tcx.sess.opts.output_types.contains_key(&OutputType::Metadata);
     let (metadata_filename, metadata_tmpdir) = if need_metadata_file {
-        if let Err(e) = non_durable_rename(&metadata_filename, &out_filename) {
-            tcx.sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e));
+        if let Err(err) = non_durable_rename(&metadata_filename, &out_filename) {
+            tcx.sess.emit_fatal(FailedWriteError { filename: out_filename, err });
         }
         if tcx.sess.opts.json_artifact_notifications {
             tcx.sess
@@ -109,8 +108,8 @@ enum MetadataKind {
 
     // Load metadata back to memory: codegen may need to include it in object files.
     let metadata =
-        EncodedMetadata::from_path(metadata_filename, metadata_tmpdir).unwrap_or_else(|e| {
-            tcx.sess.fatal(&format!("failed to create encoded metadata from file: {}", e))
+        EncodedMetadata::from_path(metadata_filename, metadata_tmpdir).unwrap_or_else(|err| {
+            tcx.sess.emit_fatal(FailedCreateEncodedMetadata { err });
         });
 
     let need_metadata_module = metadata_kind == MetadataKind::Compressed;
index 6440f3e390cf1fde772fe34a0b50f79eef8faf20..8e0291fc3ad18291ada2d7e141762bb242142bb1 100644 (file)
@@ -16,6 +16,8 @@
 #![feature(never_type)]
 #![recursion_limit = "256"]
 #![allow(rustc::potential_query_instability)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
 
 extern crate proc_macro;
 
@@ -26,6 +28,9 @@
 #[macro_use]
 extern crate rustc_data_structures;
 
+#[macro_use]
+extern crate tracing;
+
 pub use rmeta::{provide, provide_extern};
 
 mod dependency_format;
@@ -34,6 +39,7 @@
 mod rmeta;
 
 pub mod creader;
+pub mod errors;
 pub mod fs;
 pub mod locator;
 
index 2c1c84b0be26a874d7d9e6657f6a05f105381460..35f9ef92a1c425fb74eb8b4866ee187df9b27957 100644 (file)
 //! metadata::locator or metadata::creader for all the juicy details!
 
 use crate::creader::Library;
+use crate::errors::{
+    CannotFindCrate, CrateLocationUnknownType, DlError, ExternLocationNotExist,
+    ExternLocationNotFile, FoundStaticlib, IncompatibleRustc, InvalidMetadataFiles,
+    LibFilenameForm, MultipleCandidates, MultipleMatchingCrates, NewerCrateVersion,
+    NoCrateWithTriple, NoDylibPlugin, NonAsciiName, StableCrateIdCollision, SymbolConflictsCurrent,
+    SymbolConflictsOthers,
+};
 use crate::rmeta::{rustc_version, MetadataBlob, METADATA_HEADER};
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::owning_ref::OwningRef;
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::MetadataRef;
-use rustc_errors::{struct_span_err, FatalError};
+use rustc_errors::{DiagnosticArgValue, FatalError, IntoDiagnosticArg};
 use rustc_session::config::{self, CrateType};
 use rustc_session::cstore::{CrateSource, MetadataLoader};
 use rustc_session::filesearch::FileSearch;
 use rustc_session::search_paths::PathKind;
 use rustc_session::utils::CanonicalizedPath;
 use rustc_session::Session;
-use rustc_span::symbol::{sym, Symbol};
+use rustc_span::symbol::Symbol;
 use rustc_span::Span;
 use rustc_target::spec::{Target, TargetTriple};
 
 use snap::read::FrameDecoder;
+use std::borrow::Cow;
 use std::fmt::Write as _;
 use std::io::{Read, Result as IoResult, Write};
 use std::path::{Path, PathBuf};
 use std::{cmp, fmt, fs};
-use tracing::{debug, info};
 
 #[derive(Clone)]
 pub(crate) struct CrateLocator<'a> {
@@ -288,6 +295,16 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
+impl IntoDiagnosticArg for CrateFlavor {
+    fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
+        match self {
+            CrateFlavor::Rlib => DiagnosticArgValue::Str(Cow::Borrowed("rlib")),
+            CrateFlavor::Rmeta => DiagnosticArgValue::Str(Cow::Borrowed("rmeta")),
+            CrateFlavor::Dylib => DiagnosticArgValue::Str(Cow::Borrowed("dylib")),
+        }
+    }
+}
+
 impl<'a> CrateLocator<'a> {
     pub(crate) fn new(
         sess: &'a Session,
@@ -938,41 +955,20 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 
 impl CrateError {
     pub(crate) fn report(self, sess: &Session, span: Span, missing_core: bool) {
-        let mut diag = match self {
-            CrateError::NonAsciiName(crate_name) => sess.struct_span_err(
-                span,
-                &format!("cannot load a crate with a non-ascii name `{}`", crate_name),
-            ),
-            CrateError::ExternLocationNotExist(crate_name, loc) => sess.struct_span_err(
-                span,
-                &format!("extern location for {} does not exist: {}", crate_name, loc.display()),
-            ),
-            CrateError::ExternLocationNotFile(crate_name, loc) => sess.struct_span_err(
-                span,
-                &format!("extern location for {} is not a file: {}", crate_name, loc.display()),
-            ),
+        match self {
+            CrateError::NonAsciiName(crate_name) => {
+                sess.emit_err(NonAsciiName { span, crate_name });
+            }
+            CrateError::ExternLocationNotExist(crate_name, loc) => {
+                sess.emit_err(ExternLocationNotExist { span, crate_name, location: &loc });
+            }
+            CrateError::ExternLocationNotFile(crate_name, loc) => {
+                sess.emit_err(ExternLocationNotFile { span, crate_name, location: &loc });
+            }
             CrateError::MultipleCandidates(crate_name, flavor, candidates) => {
-                let mut err = struct_span_err!(
-                    sess,
-                    span,
-                    E0465,
-                    "multiple {} candidates for `{}` found",
-                    flavor,
-                    crate_name,
-                );
-                for (i, candidate) in candidates.iter().enumerate() {
-                    err.span_note(span, &format!("candidate #{}: {}", i + 1, candidate.display()));
-                }
-                err
+                sess.emit_err(MultipleCandidates { span, flavor: flavor, crate_name, candidates });
             }
             CrateError::MultipleMatchingCrates(crate_name, libraries) => {
-                let mut err = struct_span_err!(
-                    sess,
-                    span,
-                    E0464,
-                    "multiple matching crates for `{}`",
-                    crate_name
-                );
                 let mut libraries: Vec<_> = libraries.into_values().collect();
                 // Make ordering of candidates deterministic.
                 // This has to `clone()` to work around lifetime restrictions with `sort_by_key()`.
@@ -1000,223 +996,142 @@ pub(crate) fn report(self, sess: &Session, span: Span, missing_core: bool) {
                         s
                     })
                     .collect::<String>();
-                err.note(&format!("candidates:{}", candidates));
-                err
+                sess.emit_err(MultipleMatchingCrates { span, crate_name, candidates });
+            }
+            CrateError::SymbolConflictsCurrent(root_name) => {
+                sess.emit_err(SymbolConflictsCurrent { span, crate_name: root_name });
+            }
+            CrateError::SymbolConflictsOthers(root_name) => {
+                sess.emit_err(SymbolConflictsOthers { span, crate_name: root_name });
             }
-            CrateError::SymbolConflictsCurrent(root_name) => struct_span_err!(
-                sess,
-                span,
-                E0519,
-                "the current crate is indistinguishable from one of its dependencies: it has the \
-                 same crate-name `{}` and was compiled with the same `-C metadata` arguments. \
-                 This will result in symbol conflicts between the two.",
-                root_name,
-            ),
-            CrateError::SymbolConflictsOthers(root_name) => struct_span_err!(
-                sess,
-                span,
-                E0523,
-                "found two different crates with name `{}` that are not distinguished by differing \
-                 `-C metadata`. This will result in symbol conflicts between the two.",
-                root_name,
-            ),
             CrateError::StableCrateIdCollision(crate_name0, crate_name1) => {
-                let msg = format!(
-                    "found crates (`{}` and `{}`) with colliding StableCrateId values.",
-                    crate_name0, crate_name1
-                );
-                sess.struct_span_err(span, &msg)
+                sess.emit_err(StableCrateIdCollision {
+                    span,
+                    crate_name0: crate_name0,
+                    crate_name1: crate_name1,
+                });
+            }
+            CrateError::DlOpen(s) | CrateError::DlSym(s) => {
+                sess.emit_err(DlError { span, err: s });
             }
-            CrateError::DlOpen(s) | CrateError::DlSym(s) => sess.struct_span_err(span, &s),
             CrateError::LocatorCombined(locator) => {
                 let crate_name = locator.crate_name;
-                let add = match &locator.root {
+                let add_info = match &locator.root {
                     None => String::new(),
                     Some(r) => format!(" which `{}` depends on", r.name),
                 };
-                let mut msg = "the following crate versions were found:".to_string();
-                let mut err = if !locator.crate_rejections.via_hash.is_empty() {
-                    let mut err = struct_span_err!(
-                        sess,
-                        span,
-                        E0460,
-                        "found possibly newer version of crate `{}`{}",
-                        crate_name,
-                        add,
-                    );
-                    err.note("perhaps that crate needs to be recompiled?");
+                // FIXME: There are no tests for CrateLocationUnknownType or LibFilenameForm
+                if !locator.crate_rejections.via_filename.is_empty() {
+                    let mismatches = locator.crate_rejections.via_filename.iter();
+                    for CrateMismatch { path, .. } in mismatches {
+                        sess.emit_err(CrateLocationUnknownType { span, path: &path });
+                        sess.emit_err(LibFilenameForm {
+                            span,
+                            dll_prefix: &locator.dll_prefix,
+                            dll_suffix: &locator.dll_suffix,
+                        });
+                    }
+                }
+                let mut found_crates = String::new();
+                if !locator.crate_rejections.via_hash.is_empty() {
                     let mismatches = locator.crate_rejections.via_hash.iter();
                     for CrateMismatch { path, .. } in mismatches {
-                        msg.push_str(&format!("\ncrate `{}`: {}", crate_name, path.display()));
+                        found_crates.push_str(&format!(
+                            "\ncrate `{}`: {}",
+                            crate_name,
+                            path.display()
+                        ));
                     }
                     if let Some(r) = locator.root {
                         for path in r.source.paths() {
-                            msg.push_str(&format!("\ncrate `{}`: {}", r.name, path.display()));
+                            found_crates.push_str(&format!(
+                                "\ncrate `{}`: {}",
+                                r.name,
+                                path.display()
+                            ));
                         }
                     }
-                    err.note(&msg);
-                    err
-                } else if !locator.crate_rejections.via_triple.is_empty() {
-                    let mut err = struct_span_err!(
-                        sess,
+                    sess.emit_err(NewerCrateVersion {
                         span,
-                        E0461,
-                        "couldn't find crate `{}` with expected target triple {}{}",
-                        crate_name,
-                        locator.triple,
-                        add,
-                    );
+                        crate_name: crate_name,
+                        add_info,
+                        found_crates,
+                    });
+                } else if !locator.crate_rejections.via_triple.is_empty() {
                     let mismatches = locator.crate_rejections.via_triple.iter();
                     for CrateMismatch { path, got } in mismatches {
-                        msg.push_str(&format!(
+                        found_crates.push_str(&format!(
                             "\ncrate `{}`, target triple {}: {}",
                             crate_name,
                             got,
                             path.display(),
                         ));
                     }
-                    err.note(&msg);
-                    err
-                } else if !locator.crate_rejections.via_kind.is_empty() {
-                    let mut err = struct_span_err!(
-                        sess,
+                    sess.emit_err(NoCrateWithTriple {
                         span,
-                        E0462,
-                        "found staticlib `{}` instead of rlib or dylib{}",
-                        crate_name,
-                        add,
-                    );
-                    err.help("please recompile that crate using --crate-type lib");
+                        crate_name: crate_name,
+                        locator_triple: locator.triple.triple(),
+                        add_info,
+                        found_crates,
+                    });
+                } else if !locator.crate_rejections.via_kind.is_empty() {
                     let mismatches = locator.crate_rejections.via_kind.iter();
                     for CrateMismatch { path, .. } in mismatches {
-                        msg.push_str(&format!("\ncrate `{}`: {}", crate_name, path.display()));
+                        found_crates.push_str(&format!(
+                            "\ncrate `{}`: {}",
+                            crate_name,
+                            path.display()
+                        ));
                     }
-                    err.note(&msg);
-                    err
+                    sess.emit_err(FoundStaticlib { span, crate_name, add_info, found_crates });
                 } else if !locator.crate_rejections.via_version.is_empty() {
-                    let mut err = struct_span_err!(
-                        sess,
-                        span,
-                        E0514,
-                        "found crate `{}` compiled by an incompatible version of rustc{}",
-                        crate_name,
-                        add,
-                    );
-                    err.help(&format!(
-                        "please recompile that crate using this compiler ({}) \
-                         (consider running `cargo clean` first)",
-                        rustc_version(),
-                    ));
                     let mismatches = locator.crate_rejections.via_version.iter();
                     for CrateMismatch { path, got } in mismatches {
-                        msg.push_str(&format!(
+                        found_crates.push_str(&format!(
                             "\ncrate `{}` compiled by {}: {}",
                             crate_name,
                             got,
                             path.display(),
                         ));
                     }
-                    err.note(&msg);
-                    err
-                } else if !locator.crate_rejections.via_invalid.is_empty() {
-                    let mut err = struct_span_err!(
-                        sess,
+                    sess.emit_err(IncompatibleRustc {
                         span,
-                        E0786,
-                        "found invalid metadata files for crate `{}`{}",
                         crate_name,
-                        add,
-                    );
+                        add_info,
+                        found_crates,
+                        rustc_version: rustc_version(),
+                    });
+                } else if !locator.crate_rejections.via_invalid.is_empty() {
+                    let mut crate_rejections = Vec::new();
                     for CrateMismatch { path: _, got } in locator.crate_rejections.via_invalid {
-                        err.note(&got);
+                        crate_rejections.push(got);
                     }
-                    err
+                    sess.emit_err(InvalidMetadataFiles {
+                        span,
+                        crate_name,
+                        add_info,
+                        crate_rejections,
+                    });
                 } else {
-                    let mut err = struct_span_err!(
-                        sess,
+                    sess.emit_err(CannotFindCrate {
                         span,
-                        E0463,
-                        "can't find crate for `{}`{}",
                         crate_name,
-                        add,
-                    );
-
-                    if (crate_name == sym::std || crate_name == sym::core)
-                        && locator.triple != TargetTriple::from_triple(config::host_triple())
-                    {
-                        if missing_core {
-                            err.note(&format!(
-                                "the `{}` target may not be installed",
-                                locator.triple
-                            ));
-                        } else {
-                            err.note(&format!(
-                                "the `{}` target may not support the standard library",
-                                locator.triple
-                            ));
-                        }
-                        // NOTE: this suggests using rustup, even though the user may not have it installed.
-                        // That's because they could choose to install it; or this may give them a hint which
-                        // target they need to install from their distro.
-                        if missing_core {
-                            err.help(&format!(
-                                "consider downloading the target with `rustup target add {}`",
-                                locator.triple
-                            ));
-                        }
-                        // Suggest using #![no_std]. #[no_core] is unstable and not really supported anyway.
-                        // NOTE: this is a dummy span if `extern crate std` was injected by the compiler.
-                        // If it's not a dummy, that means someone added `extern crate std` explicitly and `#![no_std]` won't help.
-                        if !missing_core && span.is_dummy() {
-                            let current_crate =
-                                sess.opts.crate_name.as_deref().unwrap_or("<unknown>");
-                            err.note(&format!(
-                                "`std` is required by `{}` because it does not declare `#![no_std]`",
-                                current_crate
-                            ));
-                        }
-                        if sess.is_nightly_build() {
-                            err.help("consider building the standard library from source with `cargo build -Zbuild-std`");
-                        }
-                    } else if crate_name
-                        == Symbol::intern(&sess.opts.unstable_opts.profiler_runtime)
-                    {
-                        err.note("the compiler may have been built without the profiler runtime");
-                    } else if crate_name.as_str().starts_with("rustc_") {
-                        err.help(
-                            "maybe you need to install the missing components with: \
-                             `rustup component add rust-src rustc-dev llvm-tools-preview`",
-                        );
-                    }
-                    err.span_label(span, "can't find crate");
-                    err
-                };
-
-                if !locator.crate_rejections.via_filename.is_empty() {
-                    let mismatches = locator.crate_rejections.via_filename.iter();
-                    for CrateMismatch { path, .. } in mismatches {
-                        err.note(&format!(
-                            "extern location for {} is of an unknown type: {}",
-                            crate_name,
-                            path.display(),
-                        ))
-                        .help(&format!(
-                            "file name should be lib*.rlib or {}*.{}",
-                            locator.dll_prefix, locator.dll_suffix
-                        ));
-                    }
+                        add_info,
+                        missing_core,
+                        current_crate: sess
+                            .opts
+                            .crate_name
+                            .clone()
+                            .unwrap_or("<unknown>".to_string()),
+                        is_nightly_build: sess.is_nightly_build(),
+                        profiler_runtime: Symbol::intern(&sess.opts.unstable_opts.profiler_runtime),
+                        locator_triple: locator.triple,
+                    });
                 }
-                err
             }
-            CrateError::NonDylibPlugin(crate_name) => struct_span_err!(
-                sess,
-                span,
-                E0457,
-                "plugin `{}` only found in rlib format, but must be available in dylib format",
-                crate_name,
-            ),
-        };
-
-        diag.emit();
+            CrateError::NonDylibPlugin(crate_name) => {
+                sess.emit_err(NoDylibPlugin { span, crate_name });
+            }
+        }
     }
 }
index 8bafe203748f37784dc703b62d22d601ad07e6f1..87b5e750f1cb14fba7110775e572e53af2aa34ae 100644 (file)
@@ -1,7 +1,6 @@
 use rustc_ast::{NestedMetaItem, CRATE_NODE_ID};
 use rustc_attr as attr;
 use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_middle::ty::{List, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_target::spec::abi::Abi;
 
+use crate::errors::{
+    AsNeededCompatibility, BundleNeedsStatic, EmptyLinkName, EmptyRenamingTarget,
+    FrameworkOnlyWindows, ImportNameTypeForm, ImportNameTypeRaw, ImportNameTypeX86,
+    IncompatibleWasmLink, InvalidLinkModifier, LibFrameworkApple, LinkCfgForm,
+    LinkCfgSinglePredicate, LinkFrameworkApple, LinkKindForm, LinkModifiersForm, LinkNameForm,
+    LinkOrdinalRawDylib, LinkRequiresName, MultipleCfgs, MultipleImportNameType,
+    MultipleKindsInLink, MultipleLinkModifiers, MultipleModifiers, MultipleNamesInLink,
+    MultipleRenamings, MultipleWasmImport, NoLinkModOverride, RawDylibNoNul, RenamingNoLink,
+    UnexpectedLinkArg, UnknownImportNameType, UnknownLinkKind, UnknownLinkModifier, UnsupportedAbi,
+    UnsupportedAbiI686, WasmImportForm, WholeArchiveNeedsStatic,
+};
+
 pub(crate) fn collect(tcx: TyCtxt<'_>) -> Vec<NativeLib> {
     let mut collector = Collector { tcx, libs: Vec::new() };
     for id in tcx.hir().items() {
@@ -66,32 +77,26 @@ fn process_item(&mut self, id: rustc_hir::ItemId) {
                 match item.name_or_empty() {
                     sym::name => {
                         if name.is_some() {
-                            let msg = "multiple `name` arguments in a single `#[link]` attribute";
-                            sess.span_err(item.span(), msg);
+                            sess.emit_err(MultipleNamesInLink { span: item.span() });
                             continue;
                         }
                         let Some(link_name) = item.value_str() else {
-                            let msg = "link name must be of the form `name = \"string\"`";
-                            sess.span_err(item.span(), msg);
+                            sess.emit_err(LinkNameForm { span: item.span() });
                             continue;
                         };
                         let span = item.name_value_literal_span().unwrap();
                         if link_name.is_empty() {
-                            struct_span_err!(sess, span, E0454, "link name must not be empty")
-                                .span_label(span, "empty link name")
-                                .emit();
+                            sess.emit_err(EmptyLinkName { span });
                         }
                         name = Some((link_name, span));
                     }
                     sym::kind => {
                         if kind.is_some() {
-                            let msg = "multiple `kind` arguments in a single `#[link]` attribute";
-                            sess.span_err(item.span(), msg);
+                            sess.emit_err(MultipleKindsInLink { span: item.span() });
                             continue;
                         }
                         let Some(link_kind) = item.value_str() else {
-                            let msg = "link kind must be of the form `kind = \"string\"`";
-                            sess.span_err(item.span(), msg);
+                            sess.emit_err(LinkKindForm { span: item.span() });
                             continue;
                         };
 
@@ -101,25 +106,13 @@ fn process_item(&mut self, id: rustc_hir::ItemId) {
                             "dylib" => NativeLibKind::Dylib { as_needed: None },
                             "framework" => {
                                 if !sess.target.is_like_osx {
-                                    struct_span_err!(
-                                        sess,
-                                        span,
-                                        E0455,
-                                        "link kind `framework` is only supported on Apple targets"
-                                    )
-                                    .emit();
+                                    sess.emit_err(LinkFrameworkApple { span });
                                 }
                                 NativeLibKind::Framework { as_needed: None }
                             }
                             "raw-dylib" => {
                                 if !sess.target.is_like_windows {
-                                    struct_span_err!(
-                                        sess,
-                                        span,
-                                        E0455,
-                                        "link kind `raw-dylib` is only supported on Windows targets"
-                                    )
-                                    .emit();
+                                    sess.emit_err(FrameworkOnlyWindows { span });
                                 } else if !features.raw_dylib {
                                     feature_err(
                                         &sess.parse_sess,
@@ -132,13 +125,7 @@ fn process_item(&mut self, id: rustc_hir::ItemId) {
                                 NativeLibKind::RawDylib
                             }
                             kind => {
-                                let msg = format!(
-                                    "unknown link kind `{kind}`, expected one of: \
-                                     static, dylib, framework, raw-dylib"
-                                );
-                                struct_span_err!(sess, span, E0458, "{}", msg)
-                                    .span_label(span, "unknown link kind")
-                                    .emit();
+                                sess.emit_err(UnknownLinkKind { span, kind });
                                 continue;
                             }
                         };
@@ -146,32 +133,26 @@ fn process_item(&mut self, id: rustc_hir::ItemId) {
                     }
                     sym::modifiers => {
                         if modifiers.is_some() {
-                            let msg =
-                                "multiple `modifiers` arguments in a single `#[link]` attribute";
-                            sess.span_err(item.span(), msg);
+                            sess.emit_err(MultipleLinkModifiers { span: item.span() });
                             continue;
                         }
                         let Some(link_modifiers) = item.value_str() else {
-                            let msg = "link modifiers must be of the form `modifiers = \"string\"`";
-                            sess.span_err(item.span(), msg);
+                            sess.emit_err(LinkModifiersForm { span: item.span() });
                             continue;
                         };
                         modifiers = Some((link_modifiers, item.name_value_literal_span().unwrap()));
                     }
                     sym::cfg => {
                         if cfg.is_some() {
-                            let msg = "multiple `cfg` arguments in a single `#[link]` attribute";
-                            sess.span_err(item.span(), msg);
+                            sess.emit_err(MultipleCfgs { span: item.span() });
                             continue;
                         }
                         let Some(link_cfg) = item.meta_item_list() else {
-                            let msg = "link cfg must be of the form `cfg(/* predicate */)`";
-                            sess.span_err(item.span(), msg);
+                            sess.emit_err(LinkCfgForm { span: item.span() });
                             continue;
                         };
                         let [NestedMetaItem::MetaItem(link_cfg)] = link_cfg else {
-                            let msg = "link cfg must have a single predicate argument";
-                            sess.span_err(item.span(), msg);
+                            sess.emit_err(LinkCfgSinglePredicate { span: item.span() });
                             continue;
                         };
                         if !features.link_cfg {
@@ -187,33 +168,26 @@ fn process_item(&mut self, id: rustc_hir::ItemId) {
                     }
                     sym::wasm_import_module => {
                         if wasm_import_module.is_some() {
-                            let msg = "multiple `wasm_import_module` arguments \
-                                       in a single `#[link]` attribute";
-                            sess.span_err(item.span(), msg);
+                            sess.emit_err(MultipleWasmImport { span: item.span() });
                             continue;
                         }
                         let Some(link_wasm_import_module) = item.value_str() else {
-                            let msg = "wasm import module must be of the form \
-                                       `wasm_import_module = \"string\"`";
-                            sess.span_err(item.span(), msg);
+                            sess.emit_err(WasmImportForm { span: item.span() });
                             continue;
                         };
                         wasm_import_module = Some((link_wasm_import_module, item.span()));
                     }
                     sym::import_name_type => {
                         if import_name_type.is_some() {
-                            let msg = "multiple `import_name_type` arguments in a single `#[link]` attribute";
-                            sess.span_err(item.span(), msg);
+                            sess.emit_err(MultipleImportNameType { span: item.span() });
                             continue;
                         }
                         let Some(link_import_name_type) = item.value_str() else {
-                            let msg = "import name type must be of the form `import_name_type = \"string\"`";
-                            sess.span_err(item.span(), msg);
+                            sess.emit_err(ImportNameTypeForm { span: item.span() });
                             continue;
                         };
                         if self.tcx.sess.target.arch != "x86" {
-                            let msg = "import name type is only supported on x86";
-                            sess.span_err(item.span(), msg);
+                            sess.emit_err(ImportNameTypeX86 { span: item.span() });
                             continue;
                         }
 
@@ -222,11 +196,10 @@ fn process_item(&mut self, id: rustc_hir::ItemId) {
                             "noprefix" => PeImportNameType::NoPrefix,
                             "undecorated" => PeImportNameType::Undecorated,
                             import_name_type => {
-                                let msg = format!(
-                                    "unknown import name type `{import_name_type}`, expected one of: \
-                                     decorated, noprefix, undecorated"
-                                );
-                                sess.span_err(item.span(), msg);
+                                sess.emit_err(UnknownImportNameType {
+                                    span: item.span(),
+                                    import_name_type,
+                                });
                                 continue;
                             }
                         };
@@ -243,9 +216,7 @@ fn process_item(&mut self, id: rustc_hir::ItemId) {
                         import_name_type = Some((link_import_name_type, item.span()));
                     }
                     _ => {
-                        let msg = "unexpected `#[link]` argument, expected one of: \
-                                   name, kind, modifiers, cfg, wasm_import_module, import_name_type";
-                        sess.span_err(item.span(), msg);
+                        sess.emit_err(UnexpectedLinkArg { span: item.span() });
                     }
                 }
             }
@@ -257,11 +228,7 @@ fn process_item(&mut self, id: rustc_hir::ItemId) {
                     let (modifier, value) = match modifier.strip_prefix(&['+', '-']) {
                         Some(m) => (m, modifier.starts_with('+')),
                         None => {
-                            sess.span_err(
-                                span,
-                                "invalid linking modifier syntax, expected '+' or '-' prefix \
-                                before one of: bundle, verbatim, whole-archive, as-needed",
-                            );
+                            sess.emit_err(InvalidLinkModifier { span });
                             continue;
                         }
                     };
@@ -279,10 +246,7 @@ fn process_item(&mut self, id: rustc_hir::ItemId) {
                     }
                     let assign_modifier = |dst: &mut Option<bool>| {
                         if dst.is_some() {
-                            let msg = format!(
-                                "multiple `{modifier}` modifiers in a single `modifiers` argument"
-                            );
-                            sess.span_err(span, &msg);
+                            sess.emit_err(MultipleModifiers { span, modifier });
                         } else {
                             *dst = Some(value);
                         }
@@ -292,11 +256,7 @@ fn process_item(&mut self, id: rustc_hir::ItemId) {
                             assign_modifier(bundle)
                         }
                         ("bundle", _) => {
-                            sess.span_err(
-                                span,
-                                "linking modifier `bundle` is only compatible with \
-                                 `static` linking kind",
-                            );
+                            sess.emit_err(BundleNeedsStatic { span });
                         }
 
                         ("verbatim", _) => {
@@ -308,11 +268,7 @@ fn process_item(&mut self, id: rustc_hir::ItemId) {
                             assign_modifier(whole_archive)
                         }
                         ("whole-archive", _) => {
-                            sess.span_err(
-                                span,
-                                "linking modifier `whole-archive` is only compatible with \
-                                 `static` linking kind",
-                            );
+                            sess.emit_err(WholeArchiveNeedsStatic { span });
                         }
 
                         ("as-needed", Some(NativeLibKind::Dylib { as_needed }))
@@ -321,21 +277,11 @@ fn process_item(&mut self, id: rustc_hir::ItemId) {
                             assign_modifier(as_needed)
                         }
                         ("as-needed", _) => {
-                            sess.span_err(
-                                span,
-                                "linking modifier `as-needed` is only compatible with \
-                                 `dylib` and `framework` linking kinds",
-                            );
+                            sess.emit_err(AsNeededCompatibility { span });
                         }
 
                         _ => {
-                            sess.span_err(
-                                span,
-                                format!(
-                                    "unknown linking modifier `{modifier}`, expected one of: \
-                                     bundle, verbatim, whole-archive, as-needed"
-                                ),
-                            );
+                            sess.emit_err(UnknownLinkModifier { span, modifier });
                         }
                     }
                 }
@@ -343,36 +289,23 @@ fn process_item(&mut self, id: rustc_hir::ItemId) {
 
             if let Some((_, span)) = wasm_import_module {
                 if name.is_some() || kind.is_some() || modifiers.is_some() || cfg.is_some() {
-                    let msg = "`wasm_import_module` is incompatible with \
-                               other arguments in `#[link]` attributes";
-                    sess.span_err(span, msg);
+                    sess.emit_err(IncompatibleWasmLink { span });
                 }
             } else if name.is_none() {
-                struct_span_err!(
-                    sess,
-                    m.span,
-                    E0459,
-                    "`#[link]` attribute requires a `name = \"string\"` argument"
-                )
-                .span_label(m.span, "missing `name` argument")
-                .emit();
+                sess.emit_err(LinkRequiresName { span: m.span });
             }
 
             // Do this outside of the loop so that `import_name_type` can be specified before `kind`.
             if let Some((_, span)) = import_name_type {
                 if kind != Some(NativeLibKind::RawDylib) {
-                    let msg = "import name type can only be used with link kind `raw-dylib`";
-                    sess.span_err(span, msg);
+                    sess.emit_err(ImportNameTypeRaw { span });
                 }
             }
 
             let dll_imports = match kind {
                 Some(NativeLibKind::RawDylib) => {
                     if let Some((name, span)) = name && name.as_str().contains('\0') {
-                        sess.span_err(
-                            span,
-                            "link name must not contain NUL characters if link kind is `raw-dylib`",
-                        );
+                        sess.emit_err(RawDylibNoNul { span });
                     }
                     foreign_mod_items
                         .iter()
@@ -401,10 +334,7 @@ fn process_item(&mut self, id: rustc_hir::ItemId) {
                                 .iter()
                                 .find(|a| a.has_name(sym::link_ordinal))
                                 .unwrap();
-                            sess.span_err(
-                                link_ordinal_attr.span,
-                                "`#[link_ordinal]` is only supported if link kind is `raw-dylib`",
-                            );
+                            sess.emit_err(LinkOrdinalRawDylib { span: link_ordinal_attr.span });
                         }
                     }
 
@@ -430,7 +360,7 @@ fn process_command_line(&mut self) {
         for lib in &self.tcx.sess.opts.libs {
             if let NativeLibKind::Framework { .. } = lib.kind && !self.tcx.sess.target.is_like_osx {
                 // Cannot check this when parsing options because the target is not yet available.
-                self.tcx.sess.err("library kind `framework` is only supported on Apple targets");
+                self.tcx.sess.emit_err(LibFrameworkApple);
             }
             if let Some(ref new_name) = lib.new_name {
                 let any_duplicate = self
@@ -439,23 +369,11 @@ fn process_command_line(&mut self) {
                     .filter_map(|lib| lib.name.as_ref())
                     .any(|n| n.as_str() == lib.name);
                 if new_name.is_empty() {
-                    self.tcx.sess.err(format!(
-                        "an empty renaming target was specified for library `{}`",
-                        lib.name
-                    ));
+                    self.tcx.sess.emit_err(EmptyRenamingTarget { lib_name: &lib.name });
                 } else if !any_duplicate {
-                    self.tcx.sess.err(format!(
-                        "renaming of the library `{}` was specified, \
-                                                however this crate contains no `#[link(...)]` \
-                                                attributes referencing this library",
-                        lib.name
-                    ));
+                    self.tcx.sess.emit_err(RenamingNoLink { lib_name: &lib.name });
                 } else if !renames.insert(&lib.name) {
-                    self.tcx.sess.err(format!(
-                        "multiple renamings were \
-                                                specified for library `{}`",
-                        lib.name
-                    ));
+                    self.tcx.sess.emit_err(MultipleRenamings { lib_name: &lib.name });
                 }
             }
         }
@@ -480,10 +398,13 @@ fn process_command_line(&mut self) {
                             // involved or not, library reordering and kind overriding without
                             // explicit `:rename` in particular.
                             if lib.has_modifiers() || passed_lib.has_modifiers() {
-                                let msg = "overriding linking modifiers from command line is not supported";
                                 match lib.foreign_module {
-                                    Some(def_id) => self.tcx.sess.span_err(self.tcx.def_span(def_id), msg),
-                                    None => self.tcx.sess.err(msg),
+                                    Some(def_id) => self.tcx.sess.emit_err(NoLinkModOverride {
+                                        span: Some(self.tcx.def_span(def_id)),
+                                    }),
+                                    None => {
+                                        self.tcx.sess.emit_err(NoLinkModOverride { span: None })
+                                    }
                                 };
                             }
                             if passed_lib.kind != NativeLibKind::Unspecified {
@@ -562,20 +483,14 @@ fn build_dll_import(
                     DllCallingConvention::Vectorcall(self.i686_arg_list_size(item))
                 }
                 _ => {
-                    self.tcx.sess.span_fatal(
-                        item.span,
-                        r#"ABI not supported by `#[link(kind = "raw-dylib")]` on i686"#,
-                    );
+                    self.tcx.sess.emit_fatal(UnsupportedAbiI686 { span: item.span });
                 }
             }
         } else {
             match abi {
                 Abi::C { .. } | Abi::Win64 { .. } | Abi::System { .. } => DllCallingConvention::C,
                 _ => {
-                    self.tcx.sess.span_fatal(
-                        item.span,
-                        r#"ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture"#,
-                    );
+                    self.tcx.sess.emit_fatal(UnsupportedAbi { span: item.span });
                 }
             }
         };
index d0e0aa91480c917eb56c5243795c9c5ef5c3c1f3..6f026678170b7af312fbde3ba26f97d40ebf3982 100644 (file)
@@ -4,7 +4,6 @@
 use crate::rmeta::*;
 
 use rustc_ast as ast;
-use rustc_ast::ptr::P;
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::svh::Svh;
@@ -33,7 +32,7 @@
 use rustc_session::Session;
 use rustc_span::hygiene::{ExpnIndex, MacroKind};
 use rustc_span::source_map::{respan, Spanned};
-use rustc_span::symbol::{sym, Ident, Symbol};
+use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{self, BytePos, ExpnId, Pos, Span, SyntaxContext, DUMMY_SP};
 
 use proc_macro::bridge::client::ProcMacro;
@@ -42,7 +41,6 @@
 use std::mem;
 use std::num::NonZeroUsize;
 use std::path::Path;
-use tracing::debug;
 
 pub(super) use cstore_impl::provide;
 pub use cstore_impl::provide_extern;
@@ -786,26 +784,11 @@ fn item_ident(self, item_index: DefIndex, sess: &Session) -> Ident {
         self.opt_item_ident(item_index, sess).expect("no encoded ident for item")
     }
 
-    fn maybe_kind(self, item_id: DefIndex) -> Option<EntryKind> {
-        self.root.tables.kind.get(self, item_id).map(|k| k.decode(self))
-    }
-
     #[inline]
     pub(super) fn map_encoded_cnum_to_current(self, cnum: CrateNum) -> CrateNum {
         if cnum == LOCAL_CRATE { self.cnum } else { self.cnum_map[cnum] }
     }
 
-    fn kind(self, item_id: DefIndex) -> EntryKind {
-        self.maybe_kind(item_id).unwrap_or_else(|| {
-            bug!(
-                "CrateMetadata::kind({:?}): id not found, in crate {:?} with number {}",
-                item_id,
-                self.root.name,
-                self.cnum,
-            )
-        })
-    }
-
     fn def_kind(self, item_id: DefIndex) -> DefKind {
         self.root.tables.opt_def_kind.get(self, item_id).unwrap_or_else(|| {
             bug!(
@@ -857,21 +840,16 @@ fn load_proc_macro(self, id: DefIndex, sess: &Session) -> SyntaxExtension {
         )
     }
 
-    fn get_variant(self, kind: &EntryKind, index: DefIndex, parent_did: DefId) -> ty::VariantDef {
-        let data = match kind {
-            EntryKind::Variant(data) | EntryKind::Struct(data) | EntryKind::Union(data) => {
-                data.decode(self)
-            }
-            _ => bug!(),
-        };
-
+    fn get_variant(self, kind: &DefKind, index: DefIndex, parent_did: DefId) -> ty::VariantDef {
         let adt_kind = match kind {
-            EntryKind::Variant(_) => ty::AdtKind::Enum,
-            EntryKind::Struct(..) => ty::AdtKind::Struct,
-            EntryKind::Union(..) => ty::AdtKind::Union,
+            DefKind::Variant => ty::AdtKind::Enum,
+            DefKind::Struct => ty::AdtKind::Struct,
+            DefKind::Union => ty::AdtKind::Union,
             _ => bug!(),
         };
 
+        let data = self.root.tables.variant_data.get(self, index).unwrap().decode(self);
+
         let variant_did =
             if adt_kind == ty::AdtKind::Enum { Some(self.local_def_id(index)) } else { None };
         let ctor_did = data.ctor.map(|index| self.local_def_id(index));
@@ -902,13 +880,13 @@ fn get_variant(self, kind: &EntryKind, index: DefIndex, parent_did: DefId) -> ty
     }
 
     fn get_adt_def(self, item_id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::AdtDef<'tcx> {
-        let kind = self.kind(item_id);
+        let kind = self.def_kind(item_id);
         let did = self.local_def_id(item_id);
 
         let adt_kind = match kind {
-            EntryKind::Enum => ty::AdtKind::Enum,
-            EntryKind::Struct(_) => ty::AdtKind::Struct,
-            EntryKind::Union(_) => ty::AdtKind::Union,
+            DefKind::Enum => ty::AdtKind::Enum,
+            DefKind::Struct => ty::AdtKind::Struct,
+            DefKind::Union => ty::AdtKind::Union,
             _ => bug!("get_adt_def called on a non-ADT {:?}", did),
         };
         let repr = self.root.tables.repr_options.get(self, item_id).unwrap().decode(self);
@@ -920,7 +898,7 @@ fn get_adt_def(self, item_id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::AdtDef<'tcx> {
                 .get(self, item_id)
                 .unwrap_or_else(LazyArray::empty)
                 .decode(self)
-                .map(|index| self.get_variant(&self.kind(index), index, did))
+                .map(|index| self.get_variant(&self.def_kind(index), index, did))
                 .collect()
         } else {
             std::iter::once(self.get_variant(&kind, item_id, did)).collect()
@@ -1030,10 +1008,9 @@ fn for_each_module_child(
                 let vis = self.get_visibility(child_index);
                 let span = self.get_span(child_index, sess);
                 let macro_rules = match kind {
-                    DefKind::Macro(..) => match self.kind(child_index) {
-                        EntryKind::MacroDef(_, macro_rules) => macro_rules,
-                        _ => unreachable!(),
-                    },
+                    DefKind::Macro(..) => {
+                        self.root.tables.macro_rules.get(self, child_index).is_some()
+                    }
                     _ => false,
                 };
 
@@ -1087,14 +1064,10 @@ fn for_each_module_child(
             }
         }
 
-        match self.kind(id) {
-            EntryKind::Mod(exports) => {
-                for exp in exports.decode((self, sess)) {
-                    callback(exp);
-                }
+        if let Some(exports) = self.root.tables.module_reexports.get(self, id) {
+            for exp in exports.decode((self, sess)) {
+                callback(exp);
             }
-            EntryKind::Enum | EntryKind::Trait => {}
-            _ => bug!("`for_each_module_child` is called on a non-module: {:?}", self.def_kind(id)),
         }
     }
 
@@ -1107,19 +1080,21 @@ fn is_item_mir_available(self, id: DefIndex) -> bool {
     }
 
     fn module_expansion(self, id: DefIndex, sess: &Session) -> ExpnId {
-        match self.kind(id) {
-            EntryKind::Mod(_) | EntryKind::Enum | EntryKind::Trait => {
-                self.get_expn_that_defined(id, sess)
-            }
+        match self.def_kind(id) {
+            DefKind::Mod | DefKind::Enum | DefKind::Trait => self.get_expn_that_defined(id, sess),
             _ => panic!("Expected module, found {:?}", self.local_def_id(id)),
         }
     }
 
-    fn get_fn_has_self_parameter(self, id: DefIndex) -> bool {
-        match self.kind(id) {
-            EntryKind::AssocFn { has_self, .. } => has_self,
-            _ => false,
-        }
+    fn get_fn_has_self_parameter(self, id: DefIndex, sess: &'a Session) -> bool {
+        self.root
+            .tables
+            .fn_arg_names
+            .get(self, id)
+            .unwrap_or_else(LazyArray::empty)
+            .decode((self, sess))
+            .nth(0)
+            .map_or(false, |ident| ident.name == kw::SelfLower)
     }
 
     fn get_associated_item_def_ids(
@@ -1136,15 +1111,17 @@ fn get_associated_item_def_ids(
             .map(move |child_index| self.local_def_id(child_index))
     }
 
-    fn get_associated_item(self, id: DefIndex) -> ty::AssocItem {
+    fn get_associated_item(self, id: DefIndex, sess: &'a Session) -> ty::AssocItem {
         let name = self.item_name(id);
 
-        let (kind, container, has_self) = match self.kind(id) {
-            EntryKind::AssocConst(container) => (ty::AssocKind::Const, container, false),
-            EntryKind::AssocFn { container, has_self } => (ty::AssocKind::Fn, container, has_self),
-            EntryKind::AssocType(container) => (ty::AssocKind::Type, container, false),
-            _ => bug!("cannot get associated-item of `{:?}`", id),
+        let kind = match self.def_kind(id) {
+            DefKind::AssocConst => ty::AssocKind::Const,
+            DefKind::AssocFn => ty::AssocKind::Fn,
+            DefKind::AssocTy => ty::AssocKind::Type,
+            _ => bug!("cannot get associated-item of `{:?}`", self.def_key(id)),
         };
+        let has_self = self.get_fn_has_self_parameter(id, sess);
+        let container = self.root.tables.assoc_container.get(self, id).unwrap();
 
         ty::AssocItem {
             name,
@@ -1157,9 +1134,9 @@ fn get_associated_item(self, id: DefIndex) -> ty::AssocItem {
     }
 
     fn get_ctor_def_id_and_kind(self, node_id: DefIndex) -> Option<(DefId, CtorKind)> {
-        match self.kind(node_id) {
-            EntryKind::Struct(data) | EntryKind::Variant(data) => {
-                let vdata = data.decode(self);
+        match self.def_kind(node_id) {
+            DefKind::Struct | DefKind::Variant => {
+                let vdata = self.root.tables.variant_data.get(self, node_id).unwrap().decode(self);
                 vdata.ctor.map(|index| (self.local_def_id(index), vdata.ctor_kind))
             }
             _ => None,
@@ -1347,18 +1324,22 @@ fn exported_symbols(
     }
 
     fn get_macro(self, id: DefIndex, sess: &Session) -> ast::MacroDef {
-        match self.kind(id) {
-            EntryKind::MacroDef(mac_args, macro_rules) => {
-                ast::MacroDef { body: P(mac_args.decode((self, sess))), macro_rules }
+        match self.def_kind(id) {
+            DefKind::Macro(_) => {
+                let macro_rules = self.root.tables.macro_rules.get(self, id).is_some();
+                let body =
+                    self.root.tables.macro_definition.get(self, id).unwrap().decode((self, sess));
+                ast::MacroDef { macro_rules, body: ast::ptr::P(body) }
             }
             _ => bug!(),
         }
     }
 
     fn is_foreign_item(self, id: DefIndex) -> bool {
-        match self.kind(id) {
-            EntryKind::ForeignStatic | EntryKind::ForeignFn => true,
-            _ => false,
+        if let Some(parent) = self.def_key(id).parent {
+            matches!(self.def_kind(parent), DefKind::ForeignMod)
+        } else {
+            false
         }
     }
 
index 9d201a0c799928174f80efd1f93135013ed01733..6b447ebd99910ae21f348d34728e24b00095168f 100644 (file)
@@ -233,7 +233,7 @@ fn into_args(self) -> (DefId, SimplifiedType) {
     associated_item_def_ids => {
         tcx.arena.alloc_from_iter(cdata.get_associated_item_def_ids(def_id.index, tcx.sess))
     }
-    associated_item => { cdata.get_associated_item(def_id.index) }
+    associated_item => { cdata.get_associated_item(def_id.index, tcx.sess) }
     inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) }
     is_foreign_item => { cdata.is_foreign_item(def_id.index) }
     item_attrs => { tcx.arena.alloc_from_iter(cdata.get_item_attrs(def_id.index, tcx.sess)) }
@@ -535,8 +535,8 @@ pub fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro {
         )
     }
 
-    pub fn fn_has_self_parameter_untracked(&self, def: DefId) -> bool {
-        self.get_crate_data(def.krate).get_fn_has_self_parameter(def.index)
+    pub fn fn_has_self_parameter_untracked(&self, def: DefId, sess: &Session) -> bool {
+        self.get_crate_data(def.krate).get_fn_has_self_parameter(def.index, sess)
     }
 
     pub fn crate_source_untracked(&self, cnum: CrateNum) -> Lrc<CrateSource> {
index 3482d9f04514e561b08c458639af28b7dde76292..039486ba02c37a466b580cfb163580f9c95a19ac 100644 (file)
@@ -1,3 +1,4 @@
+use crate::errors::{FailCreateFileEncoder, FailSeekFile, FailWriteFile};
 use crate::rmeta::def_path_hash_map::DefPathHashMapRef;
 use crate::rmeta::table::TableBuilder;
 use crate::rmeta::*;
@@ -16,7 +17,6 @@
 use rustc_hir::definitions::DefPathData;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::lang_items;
-use rustc_hir::{AnonConst, GenericParamKind};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::dependency_format::Linkage;
 use rustc_middle::middle::exported_symbols::{
@@ -44,7 +44,6 @@
 use std::iter;
 use std::num::NonZeroUsize;
 use std::path::{Path, PathBuf};
-use tracing::{debug, trace};
 
 pub(super) struct EncodeContext<'a, 'tcx> {
     opaque: opaque::FileEncoder,
@@ -1020,6 +1019,89 @@ fn should_encode_generics(def_kind: DefKind) -> bool {
     }
 }
 
+fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) -> bool {
+    match def_kind {
+        DefKind::Struct
+        | DefKind::Union
+        | DefKind::Enum
+        | DefKind::Variant
+        | DefKind::Ctor(..)
+        | DefKind::Field
+        | DefKind::Fn
+        | DefKind::Const
+        | DefKind::Static(..)
+        | DefKind::TyAlias
+        | DefKind::OpaqueTy
+        | DefKind::ForeignTy
+        | DefKind::Impl
+        | DefKind::AssocFn
+        | DefKind::AssocConst
+        | DefKind::Closure
+        | DefKind::Generator
+        | DefKind::ConstParam
+        | DefKind::AnonConst
+        | DefKind::InlineConst => true,
+
+        DefKind::AssocTy => {
+            let assoc_item = tcx.associated_item(def_id);
+            match assoc_item.container {
+                ty::AssocItemContainer::ImplContainer => true,
+                ty::AssocItemContainer::TraitContainer => assoc_item.defaultness(tcx).has_value(),
+            }
+        }
+        DefKind::TyParam => {
+            let hir::Node::GenericParam(param) = tcx.hir().get_by_def_id(def_id) else { bug!() };
+            let hir::GenericParamKind::Type { default, .. } = param.kind else { bug!() };
+            default.is_some()
+        }
+
+        DefKind::Trait
+        | DefKind::TraitAlias
+        | DefKind::Mod
+        | DefKind::ForeignMod
+        | DefKind::Macro(..)
+        | DefKind::Use
+        | DefKind::LifetimeParam
+        | DefKind::GlobalAsm
+        | DefKind::ExternCrate => false,
+    }
+}
+
+fn should_encode_const(def_kind: DefKind) -> bool {
+    match def_kind {
+        DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => true,
+
+        DefKind::Struct
+        | DefKind::Union
+        | DefKind::Enum
+        | DefKind::Variant
+        | DefKind::Ctor(..)
+        | DefKind::Field
+        | DefKind::Fn
+        | DefKind::Static(..)
+        | DefKind::TyAlias
+        | DefKind::OpaqueTy
+        | DefKind::ForeignTy
+        | DefKind::Impl
+        | DefKind::AssocFn
+        | DefKind::Closure
+        | DefKind::Generator
+        | DefKind::ConstParam
+        | DefKind::InlineConst
+        | DefKind::AssocTy
+        | DefKind::TyParam
+        | DefKind::Trait
+        | DefKind::TraitAlias
+        | DefKind::Mod
+        | DefKind::ForeignMod
+        | DefKind::Macro(..)
+        | DefKind::Use
+        | DefKind::LifetimeParam
+        | DefKind::GlobalAsm
+        | DefKind::ExternCrate => false,
+    }
+}
+
 impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
     fn encode_attrs(&mut self, def_id: LocalDefId) {
         let mut attrs = self
@@ -1045,7 +1127,8 @@ fn encode_def_ids(&mut self) {
             let def_kind = tcx.opt_def_kind(local_id);
             let Some(def_kind) = def_kind else { continue };
             self.tables.opt_def_kind.set(def_id.index, def_kind);
-            record!(self.tables.def_span[def_id] <- tcx.def_span(def_id));
+            let def_span = tcx.def_span(local_id);
+            record!(self.tables.def_span[def_id] <- def_span);
             self.encode_attrs(local_id);
             record!(self.tables.expn_that_defined[def_id] <- self.tcx.expn_that_defined(def_id));
             if let Some(ident_span) = tcx.def_ident_span(def_id) {
@@ -1076,10 +1159,12 @@ fn encode_def_ids(&mut self) {
                     record_array!(self.tables.inferred_outlives_of[def_id] <- inferred_outlives);
                 }
             }
-            if let DefKind::TyParam | DefKind::ConstParam = def_kind {
-                if let Some(default) = self.tcx.object_lifetime_default(def_id) {
-                    record!(self.tables.object_lifetime_default[def_id] <- default);
-                }
+            if should_encode_type(tcx, local_id, def_kind) {
+                record!(self.tables.type_of[def_id] <- self.tcx.type_of(def_id));
+            }
+            if let DefKind::TyParam = def_kind {
+                let default = self.tcx.object_lifetime_default(def_id);
+                record!(self.tables.object_lifetime_default[def_id] <- default);
             }
             if let DefKind::Trait | DefKind::TraitAlias = def_kind {
                 record!(self.tables.super_predicates_of[def_id] <- self.tcx.super_predicates_of(def_id));
@@ -1097,11 +1182,6 @@ fn encode_def_ids(&mut self) {
         }
     }
 
-    fn encode_item_type(&mut self, def_id: DefId) {
-        debug!("EncodeContext::encode_item_type({:?})", def_id);
-        record!(self.tables.type_of[def_id] <- self.tcx.type_of(def_id));
-    }
-
     fn encode_enum_variant_info(&mut self, def: ty::AdtDef<'tcx>, index: VariantIdx) {
         let tcx = self.tcx;
         let variant = &def.variant(index);
@@ -1115,13 +1195,12 @@ fn encode_enum_variant_info(&mut self, def: ty::AdtDef<'tcx>, index: VariantIdx)
             is_non_exhaustive: variant.is_field_list_non_exhaustive(),
         };
 
-        record!(self.tables.kind[def_id] <- EntryKind::Variant(self.lazy(data)));
+        record!(self.tables.variant_data[def_id] <- data);
         self.tables.constness.set(def_id.index, hir::Constness::Const);
         record_array!(self.tables.children[def_id] <- variant.fields.iter().map(|f| {
             assert!(f.did.is_local());
             f.did.index
         }));
-        self.encode_item_type(def_id);
         if variant.ctor_kind == CtorKind::Fn {
             // FIXME(eddyb) encode signature only in `encode_enum_variant_ctor`.
             if let Some(ctor_def_id) = variant.ctor_def_id {
@@ -1144,9 +1223,8 @@ fn encode_enum_variant_ctor(&mut self, def: ty::AdtDef<'tcx>, index: VariantIdx)
             is_non_exhaustive: variant.is_field_list_non_exhaustive(),
         };
 
-        record!(self.tables.kind[def_id] <- EntryKind::Variant(self.lazy(data)));
+        record!(self.tables.variant_data[def_id] <- data);
         self.tables.constness.set(def_id.index, hir::Constness::Const);
-        self.encode_item_type(def_id);
         if variant.ctor_kind == CtorKind::Fn {
             record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
         }
@@ -1163,15 +1241,12 @@ fn encode_info_for_mod(&mut self, local_def_id: LocalDefId, md: &hir::Mod<'_>) {
         // code uses it). However, we skip encoding anything relating to child
         // items - we encode information about proc-macros later on.
         let reexports = if !self.is_proc_macro {
-            match tcx.module_reexports(local_def_id) {
-                Some(exports) => self.lazy_array(exports),
-                _ => LazyArray::empty(),
-            }
+            tcx.module_reexports(local_def_id).unwrap_or(&[])
         } else {
-            LazyArray::empty()
+            &[]
         };
 
-        record!(self.tables.kind[def_id] <- EntryKind::Mod(reexports));
+        record_array!(self.tables.module_reexports[def_id] <- reexports);
         if self.is_proc_macro {
             // Encode this here because we don't do it in encode_def_ids.
             record!(self.tables.expn_that_defined[def_id] <- tcx.expn_that_defined(local_def_id));
@@ -1199,22 +1274,6 @@ fn encode_info_for_mod(&mut self, local_def_id: LocalDefId, md: &hir::Mod<'_>) {
         }
     }
 
-    fn encode_field(
-        &mut self,
-        adt_def: ty::AdtDef<'tcx>,
-        variant_index: VariantIdx,
-        field_index: usize,
-    ) {
-        let variant = &adt_def.variant(variant_index);
-        let field = &variant.fields[field_index];
-
-        let def_id = field.did;
-        debug!("EncodeContext::encode_field({:?})", def_id);
-
-        record!(self.tables.kind[def_id] <- EntryKind::Field);
-        self.encode_item_type(def_id);
-    }
-
     fn encode_struct_ctor(&mut self, adt_def: ty::AdtDef<'tcx>, def_id: DefId) {
         debug!("EncodeContext::encode_struct_ctor({:?})", def_id);
         let tcx = self.tcx;
@@ -1228,9 +1287,8 @@ fn encode_struct_ctor(&mut self, adt_def: ty::AdtDef<'tcx>, def_id: DefId) {
         };
 
         record!(self.tables.repr_options[def_id] <- adt_def.repr());
+        record!(self.tables.variant_data[def_id] <- data);
         self.tables.constness.set(def_id.index, hir::Constness::Const);
-        record!(self.tables.kind[def_id] <- EntryKind::Struct(self.lazy(data)));
-        self.encode_item_type(def_id);
         if variant.ctor_kind == CtorKind::Fn {
             record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
         }
@@ -1251,18 +1309,10 @@ fn encode_info_for_trait_item(&mut self, def_id: DefId) {
         let ast_item = tcx.hir().expect_trait_item(def_id.expect_local());
         self.tables.impl_defaultness.set(def_id.index, ast_item.defaultness);
         let trait_item = tcx.associated_item(def_id);
+        self.tables.assoc_container.set(def_id.index, trait_item.container);
 
         match trait_item.kind {
-            ty::AssocKind::Const => {
-                let rendered = rustc_hir_pretty::to_string(
-                    &(&self.tcx.hir() as &dyn intravisit::Map<'_>),
-                    |s| s.print_trait_item(ast_item),
-                );
-
-                record!(self.tables.kind[def_id] <- EntryKind::AssocConst(ty::AssocItemContainer::TraitContainer));
-                record!(self.tables.mir_const_qualif[def_id] <- mir::ConstQualifs::default());
-                record!(self.tables.rendered_const[def_id] <- rendered);
-            }
+            ty::AssocKind::Const => {}
             ty::AssocKind::Fn => {
                 let hir::TraitItemKind::Fn(m_sig, m) = &ast_item.kind else { bug!() };
                 match *m {
@@ -1275,24 +1325,9 @@ fn encode_info_for_trait_item(&mut self, def_id: DefId) {
                 };
                 self.tables.asyncness.set(def_id.index, m_sig.header.asyncness);
                 self.tables.constness.set(def_id.index, hir::Constness::NotConst);
-                record!(self.tables.kind[def_id] <- EntryKind::AssocFn {
-                    container: ty::AssocItemContainer::TraitContainer,
-                    has_self: trait_item.fn_has_self_parameter,
-                });
             }
             ty::AssocKind::Type => {
                 self.encode_explicit_item_bounds(def_id);
-                record!(self.tables.kind[def_id] <- EntryKind::AssocType(ty::AssocItemContainer::TraitContainer));
-            }
-        }
-        match trait_item.kind {
-            ty::AssocKind::Const | ty::AssocKind::Fn => {
-                self.encode_item_type(def_id);
-            }
-            ty::AssocKind::Type => {
-                if ast_item.defaultness.has_value() {
-                    self.encode_item_type(def_id);
-                }
             }
         }
         if trait_item.kind == ty::AssocKind::Fn {
@@ -1307,20 +1342,9 @@ fn encode_info_for_impl_item(&mut self, def_id: DefId) {
         let ast_item = self.tcx.hir().expect_impl_item(def_id.expect_local());
         self.tables.impl_defaultness.set(def_id.index, ast_item.defaultness);
         let impl_item = self.tcx.associated_item(def_id);
+        self.tables.assoc_container.set(def_id.index, impl_item.container);
 
         match impl_item.kind {
-            ty::AssocKind::Const => {
-                if let hir::ImplItemKind::Const(_, body_id) = ast_item.kind {
-                    let qualifs = self.tcx.at(ast_item.span).mir_const_qualif(def_id);
-                    let const_data = self.encode_rendered_const_for_body(body_id);
-
-                    record!(self.tables.kind[def_id] <- EntryKind::AssocConst(ty::AssocItemContainer::ImplContainer));
-                    record!(self.tables.mir_const_qualif[def_id] <- qualifs);
-                    record!(self.tables.rendered_const[def_id] <- const_data);
-                } else {
-                    bug!()
-                }
-            }
             ty::AssocKind::Fn => {
                 let hir::ImplItemKind::Fn(ref sig, body) = ast_item.kind else { bug!() };
                 self.tables.asyncness.set(def_id.index, sig.header.asyncness);
@@ -1332,16 +1356,9 @@ fn encode_info_for_impl_item(&mut self, def_id: DefId) {
                     hir::Constness::NotConst
                 };
                 self.tables.constness.set(def_id.index, constness);
-                record!(self.tables.kind[def_id] <- EntryKind::AssocFn {
-                    container: ty::AssocItemContainer::ImplContainer,
-                    has_self: impl_item.fn_has_self_parameter,
-                });
-            }
-            ty::AssocKind::Type => {
-                record!(self.tables.kind[def_id] <- EntryKind::AssocType(ty::AssocItemContainer::ImplContainer));
             }
+            ty::AssocKind::Const | ty::AssocKind::Type => {}
         }
-        self.encode_item_type(def_id);
         if let Some(trait_item_def_id) = impl_item.trait_item_def_id {
             self.tables.trait_item_def_id.set(def_id.index, trait_item_def_id.into());
         }
@@ -1358,40 +1375,43 @@ fn encode_mir(&mut self) {
             return;
         }
 
-        let keys_and_jobs = self
-            .tcx
-            .mir_keys(())
-            .iter()
-            .filter_map(|&def_id| {
-                let (encode_const, encode_opt) = should_encode_mir(self.tcx, def_id);
-                if encode_const || encode_opt {
-                    Some((def_id, encode_const, encode_opt))
-                } else {
-                    None
-                }
-            })
-            .collect::<Vec<_>>();
-        for (def_id, encode_const, encode_opt) in keys_and_jobs.into_iter() {
+        let tcx = self.tcx;
+
+        let keys_and_jobs = tcx.mir_keys(()).iter().filter_map(|&def_id| {
+            let (encode_const, encode_opt) = should_encode_mir(tcx, def_id);
+            if encode_const || encode_opt { Some((def_id, encode_const, encode_opt)) } else { None }
+        });
+        for (def_id, encode_const, encode_opt) in keys_and_jobs {
             debug_assert!(encode_const || encode_opt);
 
             debug!("EntryBuilder::encode_mir({:?})", def_id);
             if encode_opt {
-                record!(self.tables.optimized_mir[def_id.to_def_id()] <- self.tcx.optimized_mir(def_id));
+                record!(self.tables.optimized_mir[def_id.to_def_id()] <- tcx.optimized_mir(def_id));
             }
             if encode_const {
-                record!(self.tables.mir_for_ctfe[def_id.to_def_id()] <- self.tcx.mir_for_ctfe(def_id));
+                record!(self.tables.mir_for_ctfe[def_id.to_def_id()] <- tcx.mir_for_ctfe(def_id));
 
                 // FIXME(generic_const_exprs): this feels wrong to have in `encode_mir`
-                let abstract_const = self.tcx.thir_abstract_const(def_id);
+                let abstract_const = tcx.thir_abstract_const(def_id);
                 if let Ok(Some(abstract_const)) = abstract_const {
                     record!(self.tables.thir_abstract_const[def_id.to_def_id()] <- abstract_const);
                 }
+
+                if should_encode_const(tcx.def_kind(def_id)) {
+                    let qualifs = tcx.mir_const_qualif(def_id);
+                    record!(self.tables.mir_const_qualif[def_id.to_def_id()] <- qualifs);
+                    let body_id = tcx.hir().maybe_body_owned_by(def_id);
+                    if let Some(body_id) = body_id {
+                        let const_data = self.encode_rendered_const_for_body(body_id);
+                        record!(self.tables.rendered_const[def_id.to_def_id()] <- const_data);
+                    }
+                }
             }
-            record!(self.tables.promoted_mir[def_id.to_def_id()] <- self.tcx.promoted_mir(def_id));
+            record!(self.tables.promoted_mir[def_id.to_def_id()] <- tcx.promoted_mir(def_id));
 
             let instance =
                 ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id.to_def_id()));
-            let unused = self.tcx.unused_generic_params(instance);
+            let unused = tcx.unused_generic_params(instance);
             if !unused.is_empty() {
                 record!(self.tables.unused_generic_params[def_id.to_def_id()] <- unused);
             }
@@ -1454,38 +1474,27 @@ fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item<'tcx>) {
 
         debug!("EncodeContext::encode_info_for_item({:?})", def_id);
 
-        let entry_kind = match item.kind {
-            hir::ItemKind::Static(..) => EntryKind::Static,
-            hir::ItemKind::Const(_, body_id) => {
-                let qualifs = self.tcx.at(item.span).mir_const_qualif(def_id);
-                let const_data = self.encode_rendered_const_for_body(body_id);
-                record!(self.tables.mir_const_qualif[def_id] <- qualifs);
-                record!(self.tables.rendered_const[def_id] <- const_data);
-                EntryKind::Const
-            }
+        match item.kind {
             hir::ItemKind::Fn(ref sig, .., body) => {
                 self.tables.asyncness.set(def_id.index, sig.header.asyncness);
                 record_array!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body));
                 self.tables.constness.set(def_id.index, sig.header.constness);
-                EntryKind::Fn
             }
             hir::ItemKind::Macro(ref macro_def, _) => {
-                EntryKind::MacroDef(self.lazy(&*macro_def.body), macro_def.macro_rules)
+                if macro_def.macro_rules {
+                    self.tables.macro_rules.set(def_id.index, ());
+                }
+                record!(self.tables.macro_definition[def_id] <- &*macro_def.body);
             }
             hir::ItemKind::Mod(ref m) => {
                 return self.encode_info_for_mod(item.def_id, m);
             }
-            hir::ItemKind::ForeignMod { .. } => EntryKind::ForeignMod,
-            hir::ItemKind::GlobalAsm(..) => EntryKind::GlobalAsm,
-            hir::ItemKind::TyAlias(..) => EntryKind::Type,
             hir::ItemKind::OpaqueTy(..) => {
                 self.encode_explicit_item_bounds(def_id);
-                EntryKind::OpaqueTy
             }
             hir::ItemKind::Enum(..) => {
                 let adt_def = self.tcx.adt_def(def_id);
                 record!(self.tables.repr_options[def_id] <- adt_def.repr());
-                EntryKind::Enum
             }
             hir::ItemKind::Struct(ref struct_def, _) => {
                 let adt_def = self.tcx.adt_def(def_id);
@@ -1500,24 +1509,24 @@ fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item<'tcx>) {
                     .map(|ctor_hir_id| self.tcx.hir().local_def_id(ctor_hir_id).local_def_index);
 
                 let variant = adt_def.non_enum_variant();
-                EntryKind::Struct(self.lazy(VariantData {
+                record!(self.tables.variant_data[def_id] <- VariantData {
                     ctor_kind: variant.ctor_kind,
                     discr: variant.discr,
                     ctor,
                     is_non_exhaustive: variant.is_field_list_non_exhaustive(),
-                }))
+                });
             }
             hir::ItemKind::Union(..) => {
                 let adt_def = self.tcx.adt_def(def_id);
                 record!(self.tables.repr_options[def_id] <- adt_def.repr());
 
                 let variant = adt_def.non_enum_variant();
-                EntryKind::Union(self.lazy(VariantData {
+                record!(self.tables.variant_data[def_id] <- VariantData {
                     ctor_kind: variant.ctor_kind,
                     discr: variant.discr,
                     ctor: None,
                     is_non_exhaustive: variant.is_field_list_non_exhaustive(),
-                }))
+                });
             }
             hir::ItemKind::Impl(hir::Impl { defaultness, constness, .. }) => {
                 self.tables.impl_defaultness.set(def_id.index, *defaultness);
@@ -1543,26 +1552,24 @@ fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item<'tcx>) {
 
                 let polarity = self.tcx.impl_polarity(def_id);
                 self.tables.impl_polarity.set(def_id.index, polarity);
-
-                EntryKind::Impl
             }
             hir::ItemKind::Trait(..) => {
                 let trait_def = self.tcx.trait_def(def_id);
                 record!(self.tables.trait_def[def_id] <- trait_def);
-
-                EntryKind::Trait
             }
             hir::ItemKind::TraitAlias(..) => {
                 let trait_def = self.tcx.trait_def(def_id);
                 record!(self.tables.trait_def[def_id] <- trait_def);
-
-                EntryKind::TraitAlias
             }
             hir::ItemKind::ExternCrate(_) | hir::ItemKind::Use(..) => {
                 bug!("cannot encode info for item {:?}", item)
             }
+            hir::ItemKind::Static(..)
+            | hir::ItemKind::Const(..)
+            | hir::ItemKind::ForeignMod { .. }
+            | hir::ItemKind::GlobalAsm(..)
+            | hir::ItemKind::TyAlias(..) => {}
         };
-        record!(self.tables.kind[def_id] <- entry_kind);
         // FIXME(eddyb) there should be a nicer way to do this.
         match item.kind {
             hir::ItemKind::Enum(..) => record_array!(self.tables.children[def_id] <-
@@ -1590,18 +1597,6 @@ fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item<'tcx>) {
             }
             _ => {}
         }
-        match item.kind {
-            hir::ItemKind::Static(..)
-            | hir::ItemKind::Const(..)
-            | hir::ItemKind::Fn(..)
-            | hir::ItemKind::TyAlias(..)
-            | hir::ItemKind::OpaqueTy(..)
-            | hir::ItemKind::Enum(..)
-            | hir::ItemKind::Struct(..)
-            | hir::ItemKind::Union(..)
-            | hir::ItemKind::Impl { .. } => self.encode_item_type(def_id),
-            _ => {}
-        }
         if let hir::ItemKind::Fn(..) = item.kind {
             record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
             if tcx.is_intrinsic(def_id) {
@@ -1613,12 +1608,43 @@ fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item<'tcx>) {
                 record!(self.tables.impl_trait_ref[def_id] <- trait_ref);
             }
         }
-    }
+        // In some cases, along with the item itself, we also
+        // encode some sub-items. Usually we want some info from the item
+        // so it's easier to do that here then to wait until we would encounter
+        // normally in the visitor walk.
+        match item.kind {
+            hir::ItemKind::Enum(..) => {
+                let def = self.tcx.adt_def(item.def_id.to_def_id());
+                for (i, variant) in def.variants().iter_enumerated() {
+                    self.encode_enum_variant_info(def, i);
 
-    fn encode_info_for_generic_param(&mut self, def_id: DefId, kind: EntryKind, encode_type: bool) {
-        record!(self.tables.kind[def_id] <- kind);
-        if encode_type {
-            self.encode_item_type(def_id);
+                    if let Some(_ctor_def_id) = variant.ctor_def_id {
+                        self.encode_enum_variant_ctor(def, i);
+                    }
+                }
+            }
+            hir::ItemKind::Struct(ref struct_def, _) => {
+                let def = self.tcx.adt_def(item.def_id.to_def_id());
+                // If the struct has a constructor, encode it.
+                if let Some(ctor_hir_id) = struct_def.ctor_hir_id() {
+                    let ctor_def_id = self.tcx.hir().local_def_id(ctor_hir_id);
+                    self.encode_struct_ctor(def, ctor_def_id.to_def_id());
+                }
+            }
+            hir::ItemKind::Impl { .. } => {
+                for &trait_item_def_id in
+                    self.tcx.associated_item_def_ids(item.def_id.to_def_id()).iter()
+                {
+                    self.encode_info_for_impl_item(trait_item_def_id);
+                }
+            }
+            hir::ItemKind::Trait(..) => {
+                for &item_def_id in self.tcx.associated_item_def_ids(item.def_id.to_def_id()).iter()
+                {
+                    self.encode_info_for_trait_item(item_def_id);
+                }
+            }
+            _ => {}
         }
     }
 
@@ -1633,34 +1659,16 @@ fn encode_info_for_closure(&mut self, hir_id: hir::HirId) {
             ty::Generator(..) => {
                 let data = self.tcx.generator_kind(def_id).unwrap();
                 let generator_diagnostic_data = typeck_result.get_generator_diagnostic_data();
-                record!(self.tables.kind[def_id.to_def_id()] <- EntryKind::Generator);
                 record!(self.tables.generator_kind[def_id.to_def_id()] <- data);
                 record!(self.tables.generator_diagnostic_data[def_id.to_def_id()]  <- generator_diagnostic_data);
             }
 
-            ty::Closure(..) => {
-                record!(self.tables.kind[def_id.to_def_id()] <- EntryKind::Closure);
+            ty::Closure(_, substs) => {
+                record!(self.tables.fn_sig[def_id.to_def_id()] <- substs.as_closure().sig());
             }
 
             _ => bug!("closure that is neither generator nor closure"),
         }
-        self.encode_item_type(def_id.to_def_id());
-        if let ty::Closure(def_id, substs) = *ty.kind() {
-            record!(self.tables.fn_sig[def_id] <- substs.as_closure().sig());
-        }
-    }
-
-    fn encode_info_for_anon_const(&mut self, id: hir::HirId) {
-        let def_id = self.tcx.hir().local_def_id(id);
-        debug!("EncodeContext::encode_info_for_anon_const({:?})", def_id);
-        let body_id = self.tcx.hir().body_owned_by(def_id);
-        let const_data = self.encode_rendered_const_for_body(body_id);
-        let qualifs = self.tcx.mir_const_qualif(def_id);
-
-        record!(self.tables.kind[def_id.to_def_id()] <- EntryKind::AnonConst);
-        record!(self.tables.mir_const_qualif[def_id.to_def_id()] <- qualifs);
-        record!(self.tables.rendered_const[def_id.to_def_id()] <- const_data);
-        self.encode_item_type(def_id.to_def_id());
     }
 
     fn encode_native_libraries(&mut self) -> LazyArray<NativeLib> {
@@ -1758,7 +1766,7 @@ fn encode_proc_macros(&mut self) -> Option<ProcMacroData> {
 
                 let def_id = id.to_def_id();
                 self.tables.opt_def_kind.set(def_id.index, DefKind::Macro(macro_kind));
-                record!(self.tables.kind[def_id] <- EntryKind::ProcMacro(macro_kind));
+                self.tables.proc_macro.set(def_id.index, macro_kind);
                 self.encode_attrs(id);
                 record!(self.tables.def_keys[def_id] <- def_key);
                 record!(self.tables.def_ident_span[def_id] <- span);
@@ -1996,18 +2004,11 @@ fn encode_info_for_foreign_item(&mut self, def_id: DefId, nitem: &hir::ForeignIt
                     hir::Constness::NotConst
                 };
                 self.tables.constness.set(def_id.index, constness);
-                record!(self.tables.kind[def_id] <- EntryKind::ForeignFn);
-            }
-            hir::ForeignItemKind::Static(..) => {
-                record!(self.tables.kind[def_id] <- EntryKind::ForeignStatic);
-            }
-            hir::ForeignItemKind::Type => {
-                record!(self.tables.kind[def_id] <- EntryKind::ForeignType);
+                record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
             }
+            hir::ForeignItemKind::Static(..) | hir::ForeignItemKind::Type => {}
         }
-        self.encode_item_type(def_id);
         if let hir::ForeignItemKind::Fn(..) = nitem.kind {
-            record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
             if tcx.is_intrinsic(def_id) {
                 self.tables.is_intrinsic.set(def_id.index, ());
             }
@@ -2026,17 +2027,12 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
         intravisit::walk_expr(self, ex);
         self.encode_info_for_expr(ex);
     }
-    fn visit_anon_const(&mut self, c: &'tcx AnonConst) {
-        intravisit::walk_anon_const(self, c);
-        self.encode_info_for_anon_const(c.hir_id);
-    }
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
         intravisit::walk_item(self, item);
         match item.kind {
             hir::ItemKind::ExternCrate(_) | hir::ItemKind::Use(..) => {} // ignore these
             _ => self.encode_info_for_item(item.def_id.to_def_id(), item),
         }
-        self.encode_addl_info_for_item(item);
     }
     fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem<'tcx>) {
         intravisit::walk_foreign_item(self, ni);
@@ -2049,29 +2045,13 @@ fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
 }
 
 impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
-    fn encode_fields(&mut self, adt_def: ty::AdtDef<'tcx>) {
-        for (variant_index, variant) in adt_def.variants().iter_enumerated() {
-            for (field_index, _field) in variant.fields.iter().enumerate() {
-                self.encode_field(adt_def, variant_index, field_index);
-            }
-        }
-    }
-
     fn encode_info_for_generics(&mut self, generics: &hir::Generics<'tcx>) {
         for param in generics.params {
             let def_id = self.tcx.hir().local_def_id(param.hir_id);
             match param.kind {
-                GenericParamKind::Lifetime { .. } => continue,
-                GenericParamKind::Type { default, .. } => {
-                    self.encode_info_for_generic_param(
-                        def_id.to_def_id(),
-                        EntryKind::TypeParam,
-                        default.is_some(),
-                    );
-                }
-                GenericParamKind::Const { ref default, .. } => {
+                hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. } => {}
+                hir::GenericParamKind::Const { ref default, .. } => {
                     let def_id = def_id.to_def_id();
-                    self.encode_info_for_generic_param(def_id, EntryKind::ConstParam, true);
                     if default.is_some() {
                         record!(self.tables.const_param_default[def_id] <- self.tcx.const_param_default(def_id))
                     }
@@ -2085,68 +2065,6 @@ fn encode_info_for_expr(&mut self, expr: &hir::Expr<'_>) {
             self.encode_info_for_closure(expr.hir_id);
         }
     }
-
-    /// In some cases, along with the item itself, we also
-    /// encode some sub-items. Usually we want some info from the item
-    /// so it's easier to do that here then to wait until we would encounter
-    /// normally in the visitor walk.
-    fn encode_addl_info_for_item(&mut self, item: &hir::Item<'_>) {
-        match item.kind {
-            hir::ItemKind::Static(..)
-            | hir::ItemKind::Const(..)
-            | hir::ItemKind::Fn(..)
-            | hir::ItemKind::Macro(..)
-            | hir::ItemKind::Mod(..)
-            | hir::ItemKind::ForeignMod { .. }
-            | hir::ItemKind::GlobalAsm(..)
-            | hir::ItemKind::ExternCrate(..)
-            | hir::ItemKind::Use(..)
-            | hir::ItemKind::TyAlias(..)
-            | hir::ItemKind::OpaqueTy(..)
-            | hir::ItemKind::TraitAlias(..) => {
-                // no sub-item recording needed in these cases
-            }
-            hir::ItemKind::Enum(..) => {
-                let def = self.tcx.adt_def(item.def_id.to_def_id());
-                self.encode_fields(def);
-
-                for (i, variant) in def.variants().iter_enumerated() {
-                    self.encode_enum_variant_info(def, i);
-
-                    if let Some(_ctor_def_id) = variant.ctor_def_id {
-                        self.encode_enum_variant_ctor(def, i);
-                    }
-                }
-            }
-            hir::ItemKind::Struct(ref struct_def, _) => {
-                let def = self.tcx.adt_def(item.def_id.to_def_id());
-                self.encode_fields(def);
-
-                // If the struct has a constructor, encode it.
-                if let Some(ctor_hir_id) = struct_def.ctor_hir_id() {
-                    let ctor_def_id = self.tcx.hir().local_def_id(ctor_hir_id);
-                    self.encode_struct_ctor(def, ctor_def_id.to_def_id());
-                }
-            }
-            hir::ItemKind::Union(..) => {
-                let def = self.tcx.adt_def(item.def_id.to_def_id());
-                self.encode_fields(def);
-            }
-            hir::ItemKind::Impl { .. } => {
-                for &trait_item_def_id in
-                    self.tcx.associated_item_def_ids(item.def_id.to_def_id()).iter()
-                {
-                    self.encode_info_for_impl_item(trait_item_def_id);
-                }
-            }
-            hir::ItemKind::Trait(..) => {
-                for &item_def_id in self.tcx.associated_item_def_ids(item.def_id.to_def_id()).iter()
-                {
-                    self.encode_info_for_trait_item(item_def_id);
-                }
-            }
-        }
-    }
 }
 
 /// Used to prefetch queries which will be needed later by metadata encoding.
@@ -2269,7 +2187,7 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
 
 fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) {
     let mut encoder = opaque::FileEncoder::new(path)
-        .unwrap_or_else(|err| tcx.sess.fatal(&format!("failed to create file encoder: {}", err)));
+        .unwrap_or_else(|err| tcx.sess.emit_fatal(FailCreateFileEncoder { err }));
     encoder.emit_raw_bytes(METADATA_HEADER);
 
     // Will be filled with the root position after encoding everything.
@@ -2314,10 +2232,10 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) {
     // Encode the root position.
     let header = METADATA_HEADER.len();
     file.seek(std::io::SeekFrom::Start(header as u64))
-        .unwrap_or_else(|err| tcx.sess.fatal(&format!("failed to seek the file: {}", err)));
+        .unwrap_or_else(|err| tcx.sess.emit_fatal(FailSeekFile { err }));
     let pos = root.position.get();
     file.write_all(&[(pos >> 24) as u8, (pos >> 16) as u8, (pos >> 8) as u8, (pos >> 0) as u8])
-        .unwrap_or_else(|err| tcx.sess.fatal(&format!("failed to write to the file: {}", err)));
+        .unwrap_or_else(|err| tcx.sess.emit_fatal(FailWriteFile { err }));
 
     // Return to the position where we are before writing the root position.
     file.seek(std::io::SeekFrom::Start(pos_before_seek)).unwrap();
index aeffc85b507556648ed956d50937c91435949a48..6f849a58580e679550216f06ff690d75e11a8a8f 100644 (file)
@@ -334,7 +334,6 @@ fn encode(&self, buf: &mut FileEncoder) -> LazyTables {
 }
 
 define_tables! {
-    kind: Table<DefIndex, LazyValue<EntryKind>>,
     attributes: Table<DefIndex, LazyArray<ast::Attribute>>,
     children: Table<DefIndex, LazyArray<DefIndex>>,
 
@@ -393,39 +392,13 @@ fn encode(&self, buf: &mut FileEncoder) -> LazyTables {
     proc_macro_quoted_spans: Table<usize, LazyValue<Span>>,
     generator_diagnostic_data: Table<DefIndex, LazyValue<GeneratorDiagnosticData<'static>>>,
     may_have_doc_links: Table<DefIndex, ()>,
-}
-
-#[derive(Copy, Clone, MetadataEncodable, MetadataDecodable)]
-enum EntryKind {
-    AnonConst,
-    Const,
-    Static,
-    ForeignStatic,
-    ForeignMod,
-    ForeignType,
-    GlobalAsm,
-    Type,
-    TypeParam,
-    ConstParam,
-    OpaqueTy,
-    Enum,
-    Field,
-    Variant(LazyValue<VariantData>),
-    Struct(LazyValue<VariantData>),
-    Union(LazyValue<VariantData>),
-    Fn,
-    ForeignFn,
-    Mod(LazyArray<ModChild>),
-    MacroDef(LazyValue<ast::MacArgs>, /*macro_rules*/ bool),
-    ProcMacro(MacroKind),
-    Closure,
-    Generator,
-    Trait,
-    Impl,
-    AssocFn { container: ty::AssocItemContainer, has_self: bool },
-    AssocType(ty::AssocItemContainer),
-    AssocConst(ty::AssocItemContainer),
-    TraitAlias,
+    variant_data: Table<DefIndex, LazyValue<VariantData>>,
+    assoc_container: Table<DefIndex, ty::AssocItemContainer>,
+    // Slot is full when macro is macro_rules.
+    macro_rules: Table<DefIndex, ()>,
+    macro_definition: Table<DefIndex, LazyValue<ast::MacArgs>>,
+    proc_macro: Table<DefIndex, MacroKind>,
+    module_reexports: Table<DefIndex, LazyArray<ModChild>>,
 }
 
 #[derive(TyEncodable, TyDecodable)]
@@ -459,7 +432,6 @@ pub fn provide(providers: &mut Providers) {
 
 trivially_parameterized_over_tcx! {
     VariantData,
-    EntryKind,
     RawDefId,
     TraitImpls,
     IncoherentImpls,
index 21841ae2532a7b913f1da7b901c1417ae091cc84..d5f151f0ed8e50a4116de32d27be14044bf589eb 100644 (file)
@@ -10,7 +10,6 @@
 use std::convert::TryInto;
 use std::marker::PhantomData;
 use std::num::NonZeroUsize;
-use tracing::debug;
 
 /// Helper trait, for encoding to, and decoding from, a fixed number of bytes.
 /// Used mainly for Lazy positions and lengths.
@@ -51,7 +50,7 @@ impl FixedSizeEncoding for Option<$ty> {
                 }
                 match b[0] - 1 {
                     $(${index()} => Some($($pat)*),)*
-                    _ => panic!("Unexpected ImplPolarity code: {:?}", b[0]),
+                    _ => panic!("Unexpected {} code: {:?}", stringify!($ty), b[0]),
                 }
             }
 
@@ -141,6 +140,21 @@ impl FixedSizeEncoding for Option<$ty> {
     }
 }
 
+fixed_size_enum! {
+    ty::AssocItemContainer {
+        ( TraitContainer )
+        ( ImplContainer  )
+    }
+}
+
+fixed_size_enum! {
+    MacroKind {
+        ( Attr   )
+        ( Bang   )
+        ( Derive )
+    }
+}
+
 // We directly encode `DefPathHash` because a `LazyValue` would incur a 25% cost.
 impl FixedSizeEncoding for Option<DefPathHash> {
     type ByteArray = [u8; 16];
index b94de537dc81e5525e5c5b14889c496315eee470..65d5f755f72482173aafada909ce89241ff9ebaf 100644 (file)
@@ -100,7 +100,7 @@ macro_rules! arena_types {
             [decode] is_late_bound_map: rustc_data_structures::fx::FxIndexSet<rustc_hir::def_id::LocalDefId>,
             [decode] impl_source: rustc_middle::traits::ImplSource<'tcx, ()>,
 
-            [] dep_kind: rustc_middle::dep_graph::DepKindStruct,
+            [] dep_kind: rustc_middle::dep_graph::DepKindStruct<'tcx>,
         ]);
     )
 }
index 65fc8a2e9cf5a4413e309a96726c9ea85126aae2..7718906ac4ee7976aad733815b6d6637e66ce014 100644 (file)
@@ -74,7 +74,7 @@
 /// Information is retrieved by indexing the `DEP_KINDS` array using the integer value
 /// of the `DepKind`. Overall, this allows to implement `DepContext` using this manual
 /// jump table instead of large matches.
-pub struct DepKindStruct {
+pub struct DepKindStruct<'tcx> {
     /// Anonymous queries cannot be replayed from one compiler invocation to the next.
     /// When their result is needed, it is recomputed. They are useful for fine-grained
     /// dependency tracking, and caching within one compiler invocation.
@@ -124,10 +124,10 @@ pub struct DepKindStruct {
     /// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode`
     /// is actually a `DefPathHash`, and can therefore just look up the corresponding
     /// `DefId` in `tcx.def_path_hash_to_def_id`.
-    pub force_from_dep_node: Option<fn(tcx: TyCtxt<'_>, dep_node: DepNode) -> bool>,
+    pub force_from_dep_node: Option<fn(tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool>,
 
     /// Invoke a query to put the on-disk cached value in memory.
-    pub try_load_from_on_disk_cache: Option<fn(TyCtxt<'_>, DepNode)>,
+    pub try_load_from_on_disk_cache: Option<fn(TyCtxt<'tcx>, DepNode)>,
 }
 
 impl DepKind {
index 8f7877392483f27f0c6ad04321071c912a27ee13..6217bffb8f76c206b4df1840eb12dd9586c7277a 100644 (file)
@@ -291,6 +291,9 @@ pub(super) fn opt_def_kind(self, local_def_id: LocalDefId) -> Option<DefKind> {
         Some(def_kind)
     }
 
+    /// Finds the id of the parent node to this one.
+    ///
+    /// If calling repeatedly and iterating over parents, prefer [`Map::parent_iter`].
     pub fn find_parent_node(self, id: HirId) -> Option<HirId> {
         if id.local_id == ItemLocalId::from_u32(0) {
             Some(self.tcx.hir_owner_parent(id.owner))
index 560d9fde0492af646e4146f9960196049789d27a..f3676604bb0e64b34b6d6d6e38eea52be4768683 100644 (file)
@@ -2267,7 +2267,7 @@ pub fn from_anon_const(
         Self::from_opt_const_arg_anon_const(tcx, ty::WithOptConstParam::unknown(def_id), param_env)
     }
 
-    #[instrument(skip(tcx), level = "debug")]
+    #[instrument(skip(tcx), level = "debug", ret)]
     pub fn from_inline_const(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
         let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
         let body_id = match tcx.hir().get(hir_id) {
@@ -2305,21 +2305,18 @@ pub fn from_inline_const(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
         let substs =
             ty::InlineConstSubsts::new(tcx, ty::InlineConstSubstsParts { parent_substs, ty })
                 .substs;
-        let uneval_const = tcx.mk_const(ty::ConstS {
+        debug_assert!(!substs.has_free_regions());
+        Self::Ty(tcx.mk_const(ty::ConstS {
             kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
                 def: ty::WithOptConstParam::unknown(def_id).to_global(),
                 substs,
                 promoted: None,
             }),
             ty,
-        });
-        debug!(?uneval_const);
-        debug_assert!(!uneval_const.has_free_regions());
-
-        Self::Ty(uneval_const)
+        }))
     }
 
-    #[instrument(skip(tcx), level = "debug")]
+    #[instrument(skip(tcx), level = "debug", ret)]
     fn from_opt_const_arg_anon_const(
         tcx: TyCtxt<'tcx>,
         def: ty::WithOptConstParam<LocalDefId>,
@@ -2402,24 +2399,21 @@ fn from_opt_const_arg_anon_const(
 
         match tcx.const_eval_resolve(param_env, uneval, Some(span)) {
             Ok(val) => {
-                debug!("evaluated const value: {:?}", val);
+                debug!("evaluated const value");
                 Self::Val(val, ty)
             }
             Err(_) => {
                 debug!("error encountered during evaluation");
                 // Error was handled in `const_eval_resolve`. Here we just create a
                 // new unevaluated const and error hard later in codegen
-                let ty_const = tcx.mk_const(ty::ConstS {
+                Self::Ty(tcx.mk_const(ty::ConstS {
                     kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
                         def: def.to_global(),
                         substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
                         promoted: None,
                     }),
                     ty,
-                });
-                debug!(?ty_const);
-
-                Self::Ty(ty_const)
+                }))
             }
         }
     }
index abaef0354ade5b319f5ca9560aa19eced27113b8..8e7bacca262e10d7da0e6177720f57f7379b4ffd 100644 (file)
     query is_late_bound_map(_: LocalDefId) -> Option<&'tcx FxIndexSet<LocalDefId>> {
         desc { "testing if a region is late bound" }
     }
-    /// For a given item (like a struct), gets the default lifetimes to be used
+    /// For a given item's generic parameter, gets the default lifetimes to be used
     /// for each parameter if a trait object were to be passed for that parameter.
-    /// For example, for `struct Foo<'a, T, U>`, this would be `['static, 'static]`.
-    /// For `struct Foo<'a, T: 'a, U>`, this would instead be `['a, 'static]`.
-    query object_lifetime_default(key: DefId) -> Option<ObjectLifetimeDefault> {
-        desc { "looking up lifetime defaults for generic parameter `{:?}`", key }
+    /// For example, for `T` in `struct Foo<'a, T>`, this would be `'static`.
+    /// For `T` in `struct Foo<'a, T: 'a>`, this would instead be `'a`.
+    /// This query will panic if passed something that is not a type parameter.
+    query object_lifetime_default(key: DefId) -> ObjectLifetimeDefault {
+        desc { "looking up lifetime defaults for generic parameter `{}`", tcx.def_path_str(key) }
         separate_provide_extern
     }
     query late_bound_vars_map(_: LocalDefId)
index 0f2504e3d9afee0386b1240cee087a78851e92eb..59e14337f4ed86a55fc92120be7c81c5c06aa261 100644 (file)
@@ -180,7 +180,7 @@ pub enum StmtKind<'tcx> {
         /// `let <PAT> = ...`
         ///
         /// If a type annotation is included, it is added as an ascription pattern.
-        pattern: Pat<'tcx>,
+        pattern: Box<Pat<'tcx>>,
 
         /// `let pat: ty = <INIT>`
         initializer: Option<ExprId>,
@@ -301,7 +301,7 @@ pub enum ExprKind<'tcx> {
     },
     Let {
         expr: ExprId,
-        pat: Pat<'tcx>,
+        pat: Box<Pat<'tcx>>,
     },
     /// A `match` expression.
     Match {
@@ -467,7 +467,7 @@ pub struct FruInfo<'tcx> {
 /// A `match` arm.
 #[derive(Clone, Debug, HashStable)]
 pub struct Arm<'tcx> {
-    pub pattern: Pat<'tcx>,
+    pub pattern: Box<Pat<'tcx>>,
     pub guard: Option<Guard<'tcx>>,
     pub body: ExprId,
     pub lint_level: LintLevel,
@@ -479,7 +479,7 @@ pub struct Arm<'tcx> {
 #[derive(Clone, Debug, HashStable)]
 pub enum Guard<'tcx> {
     If(ExprId),
-    IfLet(Pat<'tcx>, ExprId),
+    IfLet(Box<Pat<'tcx>>, ExprId),
 }
 
 #[derive(Copy, Clone, Debug, HashStable)]
@@ -534,19 +534,19 @@ pub enum BindingMode {
 #[derive(Clone, Debug, HashStable)]
 pub struct FieldPat<'tcx> {
     pub field: Field,
-    pub pattern: Pat<'tcx>,
+    pub pattern: Box<Pat<'tcx>>,
 }
 
 #[derive(Clone, Debug, HashStable)]
 pub struct Pat<'tcx> {
     pub ty: Ty<'tcx>,
     pub span: Span,
-    pub kind: Box<PatKind<'tcx>>,
+    pub kind: PatKind<'tcx>,
 }
 
 impl<'tcx> Pat<'tcx> {
     pub fn wildcard_from_ty(ty: Ty<'tcx>) -> Self {
-        Pat { ty, span: DUMMY_SP, kind: Box::new(PatKind::Wild) }
+        Pat { ty, span: DUMMY_SP, kind: PatKind::Wild }
     }
 }
 
@@ -581,7 +581,7 @@ pub enum PatKind<'tcx> {
 
     AscribeUserType {
         ascription: Ascription<'tcx>,
-        subpattern: Pat<'tcx>,
+        subpattern: Box<Pat<'tcx>>,
     },
 
     /// `x`, `ref x`, `x @ P`, etc.
@@ -591,7 +591,7 @@ pub enum PatKind<'tcx> {
         mode: BindingMode,
         var: LocalVarId,
         ty: Ty<'tcx>,
-        subpattern: Option<Pat<'tcx>>,
+        subpattern: Option<Box<Pat<'tcx>>>,
         /// Is this the leftmost occurrence of the binding, i.e., is `var` the
         /// `HirId` of this pattern?
         is_primary: bool,
@@ -614,7 +614,7 @@ pub enum PatKind<'tcx> {
 
     /// `box P`, `&P`, `&mut P`, etc.
     Deref {
-        subpattern: Pat<'tcx>,
+        subpattern: Box<Pat<'tcx>>,
     },
 
     /// One of the following:
@@ -628,32 +628,32 @@ pub enum PatKind<'tcx> {
         value: mir::ConstantKind<'tcx>,
     },
 
-    Range(PatRange<'tcx>),
+    Range(Box<PatRange<'tcx>>),
 
     /// Matches against a slice, checking the length and extracting elements.
     /// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty.
     /// e.g., `&[ref xs @ ..]`.
     Slice {
-        prefix: Vec<Pat<'tcx>>,
-        slice: Option<Pat<'tcx>>,
-        suffix: Vec<Pat<'tcx>>,
+        prefix: Box<[Box<Pat<'tcx>>]>,
+        slice: Option<Box<Pat<'tcx>>>,
+        suffix: Box<[Box<Pat<'tcx>>]>,
     },
 
     /// Fixed match against an array; irrefutable.
     Array {
-        prefix: Vec<Pat<'tcx>>,
-        slice: Option<Pat<'tcx>>,
-        suffix: Vec<Pat<'tcx>>,
+        prefix: Box<[Box<Pat<'tcx>>]>,
+        slice: Option<Box<Pat<'tcx>>>,
+        suffix: Box<[Box<Pat<'tcx>>]>,
     },
 
     /// An or-pattern, e.g. `p | q`.
     /// Invariant: `pats.len() >= 2`.
     Or {
-        pats: Vec<Pat<'tcx>>,
+        pats: Box<[Box<Pat<'tcx>>]>,
     },
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, HashStable)]
+#[derive(Clone, Debug, PartialEq, HashStable)]
 pub struct PatRange<'tcx> {
     pub lo: mir::ConstantKind<'tcx>,
     pub hi: mir::ConstantKind<'tcx>,
@@ -674,7 +674,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         };
         let mut start_or_comma = || start_or_continue(", ");
 
-        match *self.kind {
+        match self.kind {
             PatKind::Wild => write!(f, "_"),
             PatKind::AscribeUserType { ref subpattern, .. } => write!(f, "{}: _", subpattern),
             PatKind::Binding { mutability, name, mode, ref subpattern, .. } => {
@@ -695,7 +695,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                 Ok(())
             }
             PatKind::Variant { ref subpatterns, .. } | PatKind::Leaf { ref subpatterns } => {
-                let variant = match *self.kind {
+                let variant = match self.kind {
                     PatKind::Variant { adt_def, variant_index, .. } => {
                         Some(adt_def.variant(variant_index))
                     }
@@ -714,7 +714,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 
                         let mut printed = 0;
                         for p in subpatterns {
-                            if let PatKind::Wild = *p.pattern.kind {
+                            if let PatKind::Wild = p.pattern.kind {
                                 continue;
                             }
                             let name = variant.fields[p.field.index()].name;
@@ -767,7 +767,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                 write!(f, "{}", subpattern)
             }
             PatKind::Constant { value } => write!(f, "{}", value),
-            PatKind::Range(PatRange { lo, hi, end }) => {
+            PatKind::Range(box PatRange { lo, hi, end }) => {
                 write!(f, "{}", lo)?;
                 write!(f, "{}", end)?;
                 write!(f, "{}", hi)
@@ -775,24 +775,24 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             PatKind::Slice { ref prefix, ref slice, ref suffix }
             | PatKind::Array { ref prefix, ref slice, ref suffix } => {
                 write!(f, "[")?;
-                for p in prefix {
+                for p in prefix.iter() {
                     write!(f, "{}{}", start_or_comma(), p)?;
                 }
                 if let Some(ref slice) = *slice {
                     write!(f, "{}", start_or_comma())?;
-                    match *slice.kind {
+                    match slice.kind {
                         PatKind::Wild => {}
                         _ => write!(f, "{}", slice)?,
                     }
                     write!(f, "..")?;
                 }
-                for p in suffix {
+                for p in suffix.iter() {
                     write!(f, "{}{}", start_or_comma(), p)?;
                 }
                 write!(f, "]")
             }
             PatKind::Or { ref pats } => {
-                for pat in pats {
+                for pat in pats.iter() {
                     write!(f, "{}{}", start_or_continue(" | "), pat)?;
                 }
                 Ok(())
@@ -809,8 +809,8 @@ mod size_asserts {
     static_assert_size!(Block, 56);
     static_assert_size!(Expr<'_>, 64);
     static_assert_size!(ExprKind<'_>, 40);
-    static_assert_size!(Pat<'_>, 24);
-    static_assert_size!(PatKind<'_>, 112);
-    static_assert_size!(Stmt<'_>, 72);
-    static_assert_size!(StmtKind<'_>, 64);
+    static_assert_size!(Pat<'_>, 72);
+    static_assert_size!(PatKind<'_>, 56);
+    static_assert_size!(Stmt<'_>, 56);
+    static_assert_size!(StmtKind<'_>, 48);
 }
index c5c48a6360925a151a3c50ca3ef457059c6bad8e..79a0e75aa7c788b6923047908692c748a3f8b417 100644 (file)
@@ -211,7 +211,7 @@ pub fn walk_arm<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, arm: &Arm<'
 
 pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<'tcx>) {
     use PatKind::*;
-    match pat.kind.as_ref() {
+    match &pat.kind {
         AscribeUserType { subpattern, ascription: _ }
         | Deref { subpattern }
         | Binding {
@@ -232,18 +232,18 @@ pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<'
         Constant { value: _ } => {}
         Range(_) => {}
         Slice { prefix, slice, suffix } | Array { prefix, slice, suffix } => {
-            for subpattern in prefix {
+            for subpattern in prefix.iter() {
                 visitor.visit_pat(&subpattern);
             }
             if let Some(pat) = slice {
-                visitor.visit_pat(pat);
+                visitor.visit_pat(&pat);
             }
-            for subpattern in suffix {
+            for subpattern in suffix.iter() {
                 visitor.visit_pat(&subpattern);
             }
         }
         Or { pats } => {
-            for pat in pats {
+            for pat in pats.iter() {
                 visitor.visit_pat(&pat);
             }
         }
index 3d65429f2e53cd97dd8643d525577af51160f902..a5b05a4f9b526a01fbeb9c67e5106e3e5635006f 100644 (file)
@@ -1,6 +1,4 @@
-use rustc_hir::BindingAnnotation;
-use rustc_hir::BindingAnnotation::*;
-use rustc_hir::Mutability;
+use rustc_hir::{BindingAnnotation, ByRef, Mutability};
 
 #[derive(Clone, PartialEq, TyEncodable, TyDecodable, Debug, Copy, HashStable)]
 pub enum BindingMode {
@@ -11,12 +9,10 @@ pub enum BindingMode {
 TrivialTypeTraversalAndLiftImpls! { BindingMode, }
 
 impl BindingMode {
-    pub fn convert(ba: BindingAnnotation) -> BindingMode {
-        match ba {
-            Unannotated => BindingMode::BindByValue(Mutability::Not),
-            Mutable => BindingMode::BindByValue(Mutability::Mut),
-            Ref => BindingMode::BindByReference(Mutability::Not),
-            RefMut => BindingMode::BindByReference(Mutability::Mut),
+    pub fn convert(BindingAnnotation(by_ref, mutbl): BindingAnnotation) -> BindingMode {
+        match by_ref {
+            ByRef::No => BindingMode::BindByValue(mutbl),
+            ByRef::Yes => BindingMode::BindByReference(mutbl),
         }
     }
 }
index f8792edc017b2d8d3a5da6affae1e10302511dce..2eb5cffa6bc44360a25dc9cb7f578ac7addc31ff 100644 (file)
@@ -65,8 +65,6 @@ pub fn from_opt_const_arg_anon_const(
         tcx: TyCtxt<'tcx>,
         def: ty::WithOptConstParam<LocalDefId>,
     ) -> Self {
-        debug!("Const::from_anon_const(def={:?})", def);
-
         let body_id = match tcx.hir().get_by_def_id(def.did) {
             hir::Node::AnonConst(ac) => ac.body,
             _ => span_bug!(
index cb0137d2e5e09c8b8f84cf5dee284db3873b0113..3840e79cebd84e8d577b412366a049f552270719 100644 (file)
@@ -20,6 +20,12 @@ pub struct Unevaluated<'tcx, P = Option<Promoted>> {
     pub promoted: P,
 }
 
+impl rustc_errors::IntoDiagnosticArg for Unevaluated<'_> {
+    fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
+        format!("{:?}", self).into_diagnostic_arg()
+    }
+}
+
 impl<'tcx> Unevaluated<'tcx> {
     #[inline]
     pub fn shrink(self) -> Unevaluated<'tcx, ()> {
index 93707bb18ceec4c4f6a0341edea391c07d2f2f68..a803fca0d5b8930bddefc80688bf8b791f8671e5 100644 (file)
@@ -18,7 +18,7 @@
 /// `ValTree` does not have this problem with representation, as it only contains integers or
 /// lists of (nested) `ValTree`.
 pub enum ValTree<'tcx> {
-    /// ZSTs, integers, `bool`, `char` are represented as scalars.
+    /// integers, `bool`, `char` are represented as scalars.
     /// See the `ScalarInt` documentation for how `ScalarInt` guarantees that equal values
     /// of these types have the same representation.
     Leaf(ScalarInt),
@@ -27,8 +27,11 @@ pub enum ValTree<'tcx> {
     // dont use SliceOrStr for now
     /// The fields of any kind of aggregate. Structs, tuples and arrays are represented by
     /// listing their fields' values in order.
+    ///
     /// Enums are represented by storing their discriminant as a field, followed by all
     /// the fields of the variant.
+    ///
+    /// ZST types are represented as an empty slice.
     Branch(&'tcx [ValTree<'tcx>]),
 }
 
index 052bb1263c98f8d022e4577b4c26d275f1bd4afa..262d59f8ff8a78963c95f2fbe60717215e465ebd 100644 (file)
@@ -874,7 +874,7 @@ pub struct UserTypeAnnotationIndex {
 
 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable, Lift)]
 pub struct CanonicalUserTypeAnnotation<'tcx> {
-    pub user_ty: CanonicalUserType<'tcx>,
+    pub user_ty: Box<CanonicalUserType<'tcx>>,
     pub span: Span,
     pub inferred_ty: Ty<'tcx>,
 }
@@ -1089,7 +1089,7 @@ pub struct GlobalCtxt<'tcx> {
 
     pub queries: &'tcx dyn query::QueryEngine<'tcx>,
     pub query_caches: query::QueryCaches<'tcx>,
-    query_kinds: &'tcx [DepKindStruct],
+    query_kinds: &'tcx [DepKindStruct<'tcx>],
 
     // Internal caches for metadata decoding. No need to track deps on this.
     pub ty_rcache: Lock<FxHashMap<ty::CReaderCacheKey, Ty<'tcx>>>,
@@ -1246,7 +1246,7 @@ pub fn create_global_ctxt(
         dep_graph: DepGraph,
         on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>,
         queries: &'tcx dyn query::QueryEngine<'tcx>,
-        query_kinds: &'tcx [DepKindStruct],
+        query_kinds: &'tcx [DepKindStruct<'tcx>],
         crate_name: &str,
         output_filenames: OutputFilenames,
     ) -> GlobalCtxt<'tcx> {
@@ -1296,7 +1296,7 @@ pub fn create_global_ctxt(
         }
     }
 
-    pub(crate) fn query_kind(self, k: DepKind) -> &'tcx DepKindStruct {
+    pub(crate) fn query_kind(self, k: DepKind) -> &'tcx DepKindStruct<'tcx> {
         &self.query_kinds[k as usize]
     }
 
index 5e96e278b9cad5f76008b2878a8bdfbe9c89b9af..cb46a9dba579fd6d40a75e0b835cba021d2a7661 100644 (file)
@@ -353,7 +353,7 @@ fn fold_binder<T: TypeFoldable<'tcx>>(
         t
     }
 
-    #[instrument(skip(self), level = "debug")]
+    #[instrument(skip(self), level = "debug", ret)]
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         match *r {
             ty::ReLateBound(debruijn, _) if debruijn < self.current_index => {
index 26b60e4f33988b4885dac0fc0d7cfb7a23fc549f..2c587b76f025f49a2a6d0a3b3853cec065ab3b39 100644 (file)
@@ -263,6 +263,7 @@ fn layout_of<'tcx>(
     Ok(layout)
 }
 
+#[derive(Clone, Copy)]
 pub struct LayoutCx<'tcx, C> {
     pub tcx: C,
     pub param_env: ty::ParamEnv<'tcx>,
@@ -3063,6 +3064,93 @@ fn fn_abi_of_instance<'tcx>(
     )
 }
 
+// Handle safe Rust thin and fat pointers.
+pub fn adjust_for_rust_scalar<'tcx>(
+    cx: LayoutCx<'tcx, TyCtxt<'tcx>>,
+    attrs: &mut ArgAttributes,
+    scalar: Scalar,
+    layout: TyAndLayout<'tcx>,
+    offset: Size,
+    is_return: bool,
+) {
+    // Booleans are always a noundef i1 that needs to be zero-extended.
+    if scalar.is_bool() {
+        attrs.ext(ArgExtension::Zext);
+        attrs.set(ArgAttribute::NoUndef);
+        return;
+    }
+
+    // Scalars which have invalid values cannot be undef.
+    if !scalar.is_always_valid(&cx) {
+        attrs.set(ArgAttribute::NoUndef);
+    }
+
+    // Only pointer types handled below.
+    let Scalar::Initialized { value: Pointer, valid_range} = scalar else { return };
+
+    if !valid_range.contains(0) {
+        attrs.set(ArgAttribute::NonNull);
+    }
+
+    if let Some(pointee) = layout.pointee_info_at(&cx, offset) {
+        if let Some(kind) = pointee.safe {
+            attrs.pointee_align = Some(pointee.align);
+
+            // `Box` (`UniqueBorrowed`) are not necessarily dereferenceable
+            // for the entire duration of the function as they can be deallocated
+            // at any time. Same for shared mutable references. If LLVM had a
+            // way to say "dereferenceable on entry" we could use it here.
+            attrs.pointee_size = match kind {
+                PointerKind::UniqueBorrowed
+                | PointerKind::UniqueBorrowedPinned
+                | PointerKind::Frozen => pointee.size,
+                PointerKind::SharedMutable | PointerKind::UniqueOwned => Size::ZERO,
+            };
+
+            // `Box`, `&T`, and `&mut T` cannot be undef.
+            // Note that this only applies to the value of the pointer itself;
+            // this attribute doesn't make it UB for the pointed-to data to be undef.
+            attrs.set(ArgAttribute::NoUndef);
+
+            // The aliasing rules for `Box<T>` are still not decided, but currently we emit
+            // `noalias` for it. This can be turned off using an unstable flag.
+            // See https://github.com/rust-lang/unsafe-code-guidelines/issues/326
+            let noalias_for_box = cx.tcx.sess.opts.unstable_opts.box_noalias.unwrap_or(true);
+
+            // `&mut` pointer parameters never alias other parameters,
+            // or mutable global data
+            //
+            // `&T` where `T` contains no `UnsafeCell<U>` is immutable,
+            // and can be marked as both `readonly` and `noalias`, as
+            // LLVM's definition of `noalias` is based solely on memory
+            // dependencies rather than pointer equality
+            //
+            // Due to past miscompiles in LLVM, we apply a separate NoAliasMutRef attribute
+            // for UniqueBorrowed arguments, so that the codegen backend can decide whether
+            // or not to actually emit the attribute. It can also be controlled with the
+            // `-Zmutable-noalias` debugging option.
+            let no_alias = match kind {
+                PointerKind::SharedMutable
+                | PointerKind::UniqueBorrowed
+                | PointerKind::UniqueBorrowedPinned => false,
+                PointerKind::UniqueOwned => noalias_for_box,
+                PointerKind::Frozen => !is_return,
+            };
+            if no_alias {
+                attrs.set(ArgAttribute::NoAlias);
+            }
+
+            if kind == PointerKind::Frozen && !is_return {
+                attrs.set(ArgAttribute::ReadOnly);
+            }
+
+            if kind == PointerKind::UniqueBorrowed && !is_return {
+                attrs.set(ArgAttribute::NoAliasMutRef);
+            }
+        }
+    }
+}
+
 impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
     // FIXME(eddyb) perhaps group the signature/type-containing (or all of them?)
     // arguments of this method, into a separate `struct`.
@@ -3118,91 +3206,6 @@ fn fn_abi_new_uncached(
         use SpecAbi::*;
         let rust_abi = matches!(sig.abi, RustIntrinsic | PlatformIntrinsic | Rust | RustCall);
 
-        // Handle safe Rust thin and fat pointers.
-        let adjust_for_rust_scalar = |attrs: &mut ArgAttributes,
-                                      scalar: Scalar,
-                                      layout: TyAndLayout<'tcx>,
-                                      offset: Size,
-                                      is_return: bool| {
-            // Booleans are always a noundef i1 that needs to be zero-extended.
-            if scalar.is_bool() {
-                attrs.ext(ArgExtension::Zext);
-                attrs.set(ArgAttribute::NoUndef);
-                return;
-            }
-
-            // Scalars which have invalid values cannot be undef.
-            if !scalar.is_always_valid(self) {
-                attrs.set(ArgAttribute::NoUndef);
-            }
-
-            // Only pointer types handled below.
-            let Scalar::Initialized { value: Pointer, valid_range} = scalar else { return };
-
-            if !valid_range.contains(0) {
-                attrs.set(ArgAttribute::NonNull);
-            }
-
-            if let Some(pointee) = layout.pointee_info_at(self, offset) {
-                if let Some(kind) = pointee.safe {
-                    attrs.pointee_align = Some(pointee.align);
-
-                    // `Box` (`UniqueBorrowed`) are not necessarily dereferenceable
-                    // for the entire duration of the function as they can be deallocated
-                    // at any time. Same for shared mutable references. If LLVM had a
-                    // way to say "dereferenceable on entry" we could use it here.
-                    attrs.pointee_size = match kind {
-                        PointerKind::UniqueBorrowed
-                        | PointerKind::UniqueBorrowedPinned
-                        | PointerKind::Frozen => pointee.size,
-                        PointerKind::SharedMutable | PointerKind::UniqueOwned => Size::ZERO,
-                    };
-
-                    // `Box`, `&T`, and `&mut T` cannot be undef.
-                    // Note that this only applies to the value of the pointer itself;
-                    // this attribute doesn't make it UB for the pointed-to data to be undef.
-                    attrs.set(ArgAttribute::NoUndef);
-
-                    // The aliasing rules for `Box<T>` are still not decided, but currently we emit
-                    // `noalias` for it. This can be turned off using an unstable flag.
-                    // See https://github.com/rust-lang/unsafe-code-guidelines/issues/326
-                    let noalias_for_box =
-                        self.tcx().sess.opts.unstable_opts.box_noalias.unwrap_or(true);
-
-                    // `&mut` pointer parameters never alias other parameters,
-                    // or mutable global data
-                    //
-                    // `&T` where `T` contains no `UnsafeCell<U>` is immutable,
-                    // and can be marked as both `readonly` and `noalias`, as
-                    // LLVM's definition of `noalias` is based solely on memory
-                    // dependencies rather than pointer equality
-                    //
-                    // Due to past miscompiles in LLVM, we apply a separate NoAliasMutRef attribute
-                    // for UniqueBorrowed arguments, so that the codegen backend can decide whether
-                    // or not to actually emit the attribute. It can also be controlled with the
-                    // `-Zmutable-noalias` debugging option.
-                    let no_alias = match kind {
-                        PointerKind::SharedMutable
-                        | PointerKind::UniqueBorrowed
-                        | PointerKind::UniqueBorrowedPinned => false,
-                        PointerKind::UniqueOwned => noalias_for_box,
-                        PointerKind::Frozen => !is_return,
-                    };
-                    if no_alias {
-                        attrs.set(ArgAttribute::NoAlias);
-                    }
-
-                    if kind == PointerKind::Frozen && !is_return {
-                        attrs.set(ArgAttribute::ReadOnly);
-                    }
-
-                    if kind == PointerKind::UniqueBorrowed && !is_return {
-                        attrs.set(ArgAttribute::NoAliasMutRef);
-                    }
-                }
-            }
-        };
-
         let arg_of = |ty: Ty<'tcx>, arg_idx: Option<usize>| -> Result<_, FnAbiError<'tcx>> {
             let is_return = arg_idx.is_none();
 
@@ -3218,7 +3221,7 @@ fn fn_abi_new_uncached(
 
             let mut arg = ArgAbi::new(self, layout, |layout, scalar, offset| {
                 let mut attrs = ArgAttributes::new();
-                adjust_for_rust_scalar(&mut attrs, scalar, *layout, offset, is_return);
+                adjust_for_rust_scalar(*self, &mut attrs, scalar, *layout, offset, is_return);
                 attrs
             });
 
index 5c38d7614119541e14104358d76cffdb9389772e..a3f7880b9a5684f3a044ea44218be79ec3aec958 100644 (file)
@@ -179,11 +179,6 @@ pub struct ResolverAstLowering {
     pub label_res_map: NodeMap<ast::NodeId>,
     /// Resolutions for lifetimes.
     pub lifetimes_res_map: NodeMap<LifetimeRes>,
-    /// Mapping from generics `def_id`s to TAIT generics `def_id`s.
-    /// For each captured lifetime (e.g., 'a), we create a new lifetime parameter that is a generic
-    /// defined on the TAIT, so we have type Foo<'a1> = ... and we establish a mapping in this
-    /// field from the original parameter 'a to the new parameter 'a1.
-    pub generics_def_id_map: Vec<FxHashMap<LocalDefId, LocalDefId>>,
     /// Lifetime parameters that lowering will have to introduce.
     pub extra_lifetime_params_map: NodeMap<Vec<(Ident, ast::NodeId, LifetimeRes)>>,
 
@@ -2272,7 +2267,11 @@ pub fn get_attrs(self, did: DefId, attr: Symbol) -> ty::Attributes<'tcx> {
     }
 
     pub fn get_attr(self, did: DefId, attr: Symbol) -> Option<&'tcx ast::Attribute> {
-        self.get_attrs(did, attr).next()
+        if cfg!(debug_assertions) && !rustc_feature::is_valid_for_get_attr(attr) {
+            bug!("get_attr: unexpected called with DefId `{:?}`, attr `{:?}`", did, attr);
+        } else {
+            self.get_attrs(did, attr).next()
+        }
     }
 
     /// Determines whether an item is annotated with an attribute.
index 9d8a811659433f6b36b4b2043f714a228d24545d..cac8560ce1c320229dfe789a27695b039160ab26 100644 (file)
@@ -188,13 +188,11 @@ struct NormalizeAfterErasingRegionsFolder<'tcx> {
 }
 
 impl<'tcx> NormalizeAfterErasingRegionsFolder<'tcx> {
-    #[instrument(skip(self), level = "debug")]
     fn normalize_generic_arg_after_erasing_regions(
         &self,
         arg: ty::GenericArg<'tcx>,
     ) -> ty::GenericArg<'tcx> {
         let arg = self.param_env.and(arg);
-        debug!(?arg);
 
         self.tcx.try_normalize_generic_arg_after_erasing_regions(arg).unwrap_or_else(|_| bug!(
                 "Failed to normalize {:?}, maybe try to call `try_normalize_erasing_regions` instead",
index 19b8f27bc95caae910d164128766cbefb533a254..ca24c0d1ce386fc5801be18526395b68e3589677 100644 (file)
@@ -55,6 +55,7 @@ impl $crate::ty::ParameterizedOverTcx for $ty {
     crate::middle::exported_symbols::SymbolExportInfo,
     crate::middle::resolve_lifetime::ObjectLifetimeDefault,
     crate::mir::ConstQualifs,
+    ty::AssocItemContainer,
     ty::Generics,
     ty::ImplPolarity,
     ty::ReprOptions,
index 80354a3f8a2260e8f61b39e37a89251470c10a75..9fb91b5fe8700032585acf97aaf3b88d4a38c116 100644 (file)
@@ -849,6 +849,12 @@ pub fn to_poly_trait_predicate_negative_polarity(&self) -> ty::PolyTraitPredicat
     }
 }
 
+impl rustc_errors::IntoDiagnosticArg for PolyTraitRef<'_> {
+    fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
+        self.to_string().into_diagnostic_arg()
+    }
+}
+
 /// An existential reference to a trait, where `Self` is erased.
 /// For example, the trait object `Trait<'a, 'b, X, Y>` is:
 /// ```ignore (illustrative)
index 541dace5cc2bb5f31964d42799e792ebdab6af2d..ac79949fca5cc40d7ed5391e8e96557ff459e36d 100644 (file)
@@ -256,7 +256,6 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait
 }
 
 // Query provider for `incoherent_impls`.
-#[instrument(level = "debug", skip(tcx))]
 pub(super) fn incoherent_impls_provider(tcx: TyCtxt<'_>, simp: SimplifiedType) -> &[DefId] {
     let mut impls = Vec::new();
 
index 591bb7831b5b6375ab98b17f28ecfb389dc26e5a..a3837512bce2652c1155ca2672e06bcb1cd07bdb 100644 (file)
@@ -627,7 +627,7 @@ pub fn static_ptr_ty(self, def_id: DefId) -> Ty<'tcx> {
     }
 
     /// Expands the given impl trait type, stopping if the type is recursive.
-    #[instrument(skip(self), level = "debug")]
+    #[instrument(skip(self), level = "debug", ret)]
     pub fn try_expand_impl_trait_type(
         self,
         def_id: DefId,
@@ -644,7 +644,6 @@ pub fn try_expand_impl_trait_type(
         };
 
         let expanded_type = visitor.expand_opaque_ty(def_id, substs).unwrap();
-        trace!(?expanded_type);
         if visitor.found_recursion { Err(expanded_type) } else { Ok(expanded_type) }
     }
 
index 5365067209af98042864cd0a8410a0a20170e722..5e042c3acfce25897621b4b4215df93554a266ed 100644 (file)
@@ -84,7 +84,7 @@ fn has_escaping_bound_vars(&self) -> bool {
         self.has_vars_bound_at_or_above(ty::INNERMOST)
     }
 
-    #[instrument(level = "trace")]
+    #[instrument(level = "trace", ret)]
     fn has_type_flags(&self, flags: TypeFlags) -> bool {
         self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() == Some(FoundFlags)
     }
@@ -560,7 +560,7 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
     type BreakTy = FoundFlags;
 
     #[inline]
-    #[instrument(skip(self), level = "trace")]
+    #[instrument(skip(self), level = "trace", ret)]
     fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
         let flags = t.flags();
         trace!(t.flags=?t.flags());
@@ -572,7 +572,7 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
     }
 
     #[inline]
-    #[instrument(skip(self), level = "trace")]
+    #[instrument(skip(self), level = "trace", ret)]
     fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
         let flags = r.type_flags();
         trace!(r.flags=?flags);
@@ -584,7 +584,7 @@ fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
     }
 
     #[inline]
-    #[instrument(level = "trace")]
+    #[instrument(level = "trace", ret)]
     fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
         let flags = FlagComputation::for_const(c);
         trace!(r.flags=?flags);
@@ -596,7 +596,7 @@ fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
     }
 
     #[inline]
-    #[instrument(level = "trace")]
+    #[instrument(level = "trace", ret)]
     fn visit_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> {
         let flags = FlagComputation::for_unevaluated_const(uv);
         trace!(r.flags=?flags);
@@ -608,7 +608,7 @@ fn visit_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::
     }
 
     #[inline]
-    #[instrument(level = "trace")]
+    #[instrument(level = "trace", ret)]
     fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
         debug!(
             "HasTypeFlagsVisitor: predicate={:?} predicate.flags={:?} self.flags={:?}",
index d5213dc0e0467869d797370d41ef0d564ccd0957..c8d4a1bf2c9e7eeb4ae48231f80208b6aeb8287c 100644 (file)
@@ -117,7 +117,7 @@ fn ast_block_stmts(
                     lint_level,
                     else_block,
                 } => {
-                    let ignores_expr_result = matches!(*pattern.kind, PatKind::Wild);
+                    let ignores_expr_result = matches!(pattern.kind, PatKind::Wild);
                     this.block_context.push(BlockFrame::Statement { ignores_expr_result });
 
                     // Enter the remainder scope, i.e., the bindings' destruction scope.
@@ -160,7 +160,7 @@ fn ast_block_stmts(
                                                 ArmHasGuard(false),
                                                 Some((None, initializer_span)),
                                             );
-                                            this.expr_into_pattern(block, pattern.clone(), init) // irrefutable pattern
+                                            this.expr_into_pattern(block, pattern, init) // irrefutable pattern
                                         }
                                     })
                                 },
index b316a6eeac1ca7e6bee507b919fd342af7edd4e1..3549b47478cbded136bc85a399c75439531a12e3 100644 (file)
@@ -42,10 +42,10 @@ pub(crate) fn as_constant(&mut self, expr: &Expr<'tcx>) -> Constant<'tcx> {
                 Constant { span, user_ty: None, literal }
             }
             ExprKind::NonHirLiteral { lit, ref user_ty } => {
-                let user_ty = user_ty.as_ref().map(|box user_ty| {
+                let user_ty = user_ty.as_ref().map(|user_ty| {
                     this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
                         span,
-                        user_ty: *user_ty,
+                        user_ty: user_ty.clone(),
                         inferred_ty: ty,
                     })
                 });
@@ -54,10 +54,10 @@ pub(crate) fn as_constant(&mut self, expr: &Expr<'tcx>) -> Constant<'tcx> {
                 Constant { span, user_ty: user_ty, literal }
             }
             ExprKind::ZstLiteral { ref user_ty } => {
-                let user_ty = user_ty.as_ref().map(|box user_ty| {
+                let user_ty = user_ty.as_ref().map(|user_ty| {
                     this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
                         span,
-                        user_ty: *user_ty,
+                        user_ty: user_ty.clone(),
                         inferred_ty: ty,
                     })
                 });
@@ -66,10 +66,10 @@ pub(crate) fn as_constant(&mut self, expr: &Expr<'tcx>) -> Constant<'tcx> {
                 Constant { span, user_ty: user_ty, literal }
             }
             ExprKind::NamedConst { def_id, substs, ref user_ty } => {
-                let user_ty = user_ty.as_ref().map(|box user_ty| {
+                let user_ty = user_ty.as_ref().map(|user_ty| {
                     this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
                         span,
-                        user_ty: *user_ty,
+                        user_ty: user_ty.clone(),
                         inferred_ty: ty,
                     })
                 });
index b8277f28cdc4300200b49dab6f758454996ad23a..46dbd8a136b52f1f10017e052c2bbcd68ffe0233 100644 (file)
@@ -522,11 +522,11 @@ fn expr_as_place(
                         fake_borrow_temps,
                     )
                 );
-                if let Some(box user_ty) = user_ty {
+                if let Some(user_ty) = user_ty {
                     let annotation_index =
                         this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
                             span: source_info.span,
-                            user_ty: *user_ty,
+                            user_ty: user_ty.clone(),
                             inferred_ty: expr.ty,
                         });
 
@@ -551,11 +551,11 @@ fn expr_as_place(
                 let source = &this.thir[source];
                 let temp =
                     unpack!(block = this.as_temp(block, source.temp_lifetime, source, mutability));
-                if let Some(box user_ty) = user_ty {
+                if let Some(user_ty) = user_ty {
                     let annotation_index =
                         this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
                             span: source_info.span,
-                            user_ty: *user_ty,
+                            user_ty: user_ty.clone(),
                             inferred_ty: expr.ty,
                         });
                     this.cfg.push(
index 48ec7a06724a11d0c11081d2da602d590681fe4c..74509646c17c698f6ca4dc810b2d84447123938b 100644 (file)
@@ -378,10 +378,10 @@ pub(crate) fn expr_into_dest(
                 };
 
                 let inferred_ty = expr.ty;
-                let user_ty = user_ty.as_ref().map(|box user_ty| {
+                let user_ty = user_ty.as_ref().map(|user_ty| {
                     this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
                         span: source_info.span,
-                        user_ty: *user_ty,
+                        user_ty: user_ty.clone(),
                         inferred_ty,
                     })
                 });
index 2ca6d7628466229c1ea5db3c678d47397d98aa45..a316c2e7d6e187bf1d25a5b7da4c33543cf89695 100644 (file)
@@ -155,7 +155,7 @@ pub(crate) fn then_else_break(
     ///
     /// * From each pre-binding block to the next pre-binding block.
     /// * From each otherwise block to the next pre-binding block.
-    #[tracing::instrument(level = "debug", skip(self, arms))]
+    #[instrument(level = "debug", skip(self, arms))]
     pub(crate) fn match_expr(
         &mut self,
         destination: Place<'tcx>,
@@ -490,10 +490,10 @@ fn bind_pattern(
     pub(super) fn expr_into_pattern(
         &mut self,
         mut block: BasicBlock,
-        irrefutable_pat: Pat<'tcx>,
+        irrefutable_pat: &Pat<'tcx>,
         initializer: &Expr<'tcx>,
     ) -> BlockAnd<()> {
-        match *irrefutable_pat.kind {
+        match irrefutable_pat.kind {
             // Optimize the case of `let x = ...` to write directly into `x`
             PatKind::Binding { mode: BindingMode::ByValue, var, subpattern: None, .. } => {
                 let place =
@@ -518,17 +518,14 @@ pub(super) fn expr_into_pattern(
             // broken.
             PatKind::AscribeUserType {
                 subpattern:
-                    Pat {
+                    box Pat {
                         kind:
-                            box PatKind::Binding {
-                                mode: BindingMode::ByValue,
-                                var,
-                                subpattern: None,
-                                ..
+                            PatKind::Binding {
+                                mode: BindingMode::ByValue, var, subpattern: None, ..
                             },
                         ..
                     },
-                ascription: thir::Ascription { annotation, variance: _ },
+                ascription: thir::Ascription { ref annotation, variance: _ },
             } => {
                 let place =
                     self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard, true);
@@ -541,7 +538,7 @@ pub(super) fn expr_into_pattern(
 
                 let ty_source_info = self.source_info(annotation.span);
 
-                let base = self.canonical_user_type_annotations.push(annotation);
+                let base = self.canonical_user_type_annotations.push(annotation.clone());
                 self.cfg.push(
                     block,
                     Statement {
@@ -581,7 +578,7 @@ pub(super) fn expr_into_pattern(
     pub(crate) fn place_into_pattern(
         &mut self,
         block: BasicBlock,
-        irrefutable_pat: Pat<'tcx>,
+        irrefutable_pat: &Pat<'tcx>,
         initializer: PlaceBuilder<'tcx>,
         set_match_place: bool,
     ) -> BlockAnd<()> {
@@ -744,7 +741,7 @@ pub(super) fn visit_primary_bindings(
             "visit_primary_bindings: pattern={:?} pattern_user_ty={:?}",
             pattern, pattern_user_ty
         );
-        match *pattern.kind {
+        match pattern.kind {
             PatKind::Binding {
                 mutability,
                 name,
@@ -767,7 +764,7 @@ pub(super) fn visit_primary_bindings(
             | PatKind::Slice { ref prefix, ref slice, ref suffix } => {
                 let from = u64::try_from(prefix.len()).unwrap();
                 let to = u64::try_from(suffix.len()).unwrap();
-                for subpattern in prefix {
+                for subpattern in prefix.iter() {
                     self.visit_primary_bindings(subpattern, pattern_user_ty.clone().index(), f);
                 }
                 for subpattern in slice {
@@ -777,7 +774,7 @@ pub(super) fn visit_primary_bindings(
                         f,
                     );
                 }
-                for subpattern in suffix {
+                for subpattern in suffix.iter() {
                     self.visit_primary_bindings(subpattern, pattern_user_ty.clone().index(), f);
                 }
             }
@@ -830,7 +827,7 @@ pub(super) fn visit_primary_bindings(
                 // may not all be in the leftmost subpattern. For example in
                 // `let (x | y) = ...`, the primary binding of `y` occurs in
                 // the right subpattern
-                for subpattern in pats {
+                for subpattern in pats.iter() {
                     self.visit_primary_bindings(subpattern, pattern_user_ty.clone(), f);
                 }
             }
@@ -982,7 +979,7 @@ enum TestKind<'tcx> {
     },
 
     /// Test whether the value falls within an inclusive or exclusive range
-    Range(PatRange<'tcx>),
+    Range(Box<PatRange<'tcx>>),
 
     /// Test that the length of the slice is equal to `len`.
     Len { len: u64, op: BinOp },
@@ -1330,7 +1327,7 @@ fn test_candidates_with_or(
 
         // All of the or-patterns have been sorted to the end, so if the first
         // pattern is an or-pattern we only have or-patterns.
-        match *first_candidate.match_pairs[0].pattern.kind {
+        match first_candidate.match_pairs[0].pattern.kind {
             PatKind::Or { .. } => (),
             _ => {
                 self.test_candidates(
@@ -1350,7 +1347,7 @@ fn test_candidates_with_or(
 
         let mut otherwise = None;
         for match_pair in match_pairs {
-            let PatKind::Or { ref pats } = &*match_pair.pattern.kind else {
+            let PatKind::Or { ref pats } = &match_pair.pattern.kind else {
                 bug!("Or-patterns should have been sorted to the end");
             };
             let or_span = match_pair.pattern.span;
@@ -1384,7 +1381,7 @@ fn test_or_pattern<'pat>(
         &mut self,
         candidate: &mut Candidate<'pat, 'tcx>,
         otherwise: &mut Option<BasicBlock>,
-        pats: &'pat [Pat<'tcx>],
+        pats: &'pat [Box<Pat<'tcx>>],
         or_span: Span,
         place: PlaceBuilder<'tcx>,
         fake_borrows: &mut Option<FxIndexSet<Place<'tcx>>>,
@@ -2289,7 +2286,7 @@ pub(crate) fn ast_let_else(
         let else_block_span = self.thir[else_block].span;
         let (matching, failure) = self.in_if_then_scope(remainder_scope, |this| {
             let scrutinee = unpack!(block = this.lower_scrutinee(block, init, initializer_span));
-            let pat = Pat { ty: init.ty, span: else_block_span, kind: Box::new(PatKind::Wild) };
+            let pat = Pat { ty: init.ty, span: else_block_span, kind: PatKind::Wild };
             let mut wildcard = Candidate::new(scrutinee.clone(), &pat, false);
             this.declare_bindings(
                 visibility_scope,
index c6298904140c39ef9166191ac078d9b597ba18ed..55ed09da64fb866162cddda8d9d6809d360c6f5f 100644 (file)
@@ -67,7 +67,7 @@ pub(super) fn simplify_candidate<'pat>(
         loop {
             let match_pairs = mem::take(&mut candidate.match_pairs);
 
-            if let [MatchPair { pattern: Pat { kind: box PatKind::Or { pats }, .. }, place }] =
+            if let [MatchPair { pattern: Pat { kind: PatKind::Or { pats }, .. }, place }] =
                 &*match_pairs
             {
                 existing_bindings.extend_from_slice(&new_bindings);
@@ -113,7 +113,7 @@ pub(super) fn simplify_candidate<'pat>(
                 // late as possible.
                 candidate
                     .match_pairs
-                    .sort_by_key(|pair| matches!(*pair.pattern.kind, PatKind::Or { .. }));
+                    .sort_by_key(|pair| matches!(pair.pattern.kind, PatKind::Or { .. }));
                 debug!(simplified = ?candidate, "simplify_candidate");
                 return false; // if we were not able to simplify any, done.
             }
@@ -127,10 +127,10 @@ fn create_or_subcandidates<'pat>(
         &mut self,
         candidate: &Candidate<'pat, 'tcx>,
         place: PlaceBuilder<'tcx>,
-        pats: &'pat [Pat<'tcx>],
+        pats: &'pat [Box<Pat<'tcx>>],
     ) -> Vec<Candidate<'pat, 'tcx>> {
         pats.iter()
-            .map(|pat| {
+            .map(|box pat| {
                 let mut candidate = Candidate::new(place.clone(), pat, candidate.has_guard);
                 self.simplify_candidate(&mut candidate);
                 candidate
@@ -149,7 +149,7 @@ fn simplify_match_pair<'pat>(
         candidate: &mut Candidate<'pat, 'tcx>,
     ) -> Result<(), MatchPair<'pat, 'tcx>> {
         let tcx = self.tcx;
-        match *match_pair.pattern.kind {
+        match match_pair.pattern.kind {
             PatKind::AscribeUserType {
                 ref subpattern,
                 ascription: thir::Ascription { ref annotation, variance },
@@ -208,7 +208,7 @@ fn simplify_match_pair<'pat>(
                 Err(match_pair)
             }
 
-            PatKind::Range(PatRange { lo, hi, end }) => {
+            PatKind::Range(box PatRange { lo, hi, end }) => {
                 let (range, bias) = match *lo.ty().kind() {
                     ty::Char => {
                         (Some(('\u{0000}' as u128, '\u{10FFFF}' as u128, Size::from_bits(32))), 0)
@@ -254,7 +254,7 @@ fn simplify_match_pair<'pat>(
                         &mut candidate.match_pairs,
                         &match_pair.place,
                         prefix,
-                        slice.as_ref(),
+                        slice,
                         suffix,
                     );
                     Ok(())
@@ -294,7 +294,7 @@ fn simplify_match_pair<'pat>(
                     &mut candidate.match_pairs,
                     &match_pair.place,
                     prefix,
-                    slice.as_ref(),
+                    slice,
                     suffix,
                 );
                 Ok(())
index 598da80c574aff45ba7d4684fb4d307c86f16dd0..19c303e0bab7400ba0d8e48552ccd0233db9dcc9 100644 (file)
@@ -29,7 +29,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     ///
     /// It is a bug to call this with a not-fully-simplified pattern.
     pub(super) fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> {
-        match *match_pair.pattern.kind {
+        match match_pair.pattern.kind {
             PatKind::Variant { adt_def, substs: _, variant_index: _, subpatterns: _ } => Test {
                 span: match_pair.pattern.span,
                 kind: TestKind::Switch {
@@ -58,10 +58,10 @@ pub(super) fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<
                 kind: TestKind::Eq { value, ty: match_pair.pattern.ty },
             },
 
-            PatKind::Range(range) => {
+            PatKind::Range(ref range) => {
                 assert_eq!(range.lo.ty(), match_pair.pattern.ty);
                 assert_eq!(range.hi.ty(), match_pair.pattern.ty);
-                Test { span: match_pair.pattern.span, kind: TestKind::Range(range) }
+                Test { span: match_pair.pattern.span, kind: TestKind::Range(range.clone()) }
             }
 
             PatKind::Slice { ref prefix, ref slice, ref suffix } => {
@@ -92,7 +92,7 @@ pub(super) fn add_cases_to_switch<'pat>(
             return false;
         };
 
-        match *match_pair.pattern.kind {
+        match match_pair.pattern.kind {
             PatKind::Constant { value } => {
                 options
                     .entry(value)
@@ -102,9 +102,9 @@ pub(super) fn add_cases_to_switch<'pat>(
             PatKind::Variant { .. } => {
                 panic!("you should have called add_variants_to_switch instead!");
             }
-            PatKind::Range(range) => {
+            PatKind::Range(ref range) => {
                 // Check that none of the switch values are in the range.
-                self.values_not_contained_in_range(range, options).unwrap_or(false)
+                self.values_not_contained_in_range(&*range, options).unwrap_or(false)
             }
             PatKind::Slice { .. }
             | PatKind::Array { .. }
@@ -130,7 +130,7 @@ pub(super) fn add_variants_to_switch<'pat>(
             return false;
         };
 
-        match *match_pair.pattern.kind {
+        match match_pair.pattern.kind {
             PatKind::Variant { adt_def: _, variant_index, .. } => {
                 // We have a pattern testing for variant `variant_index`
                 // set the corresponding index to true
@@ -272,7 +272,7 @@ pub(super) fn perform_test(
                 }
             }
 
-            TestKind::Range(PatRange { lo, hi, ref end }) => {
+            TestKind::Range(box PatRange { lo, hi, ref end }) => {
                 let lower_bound_success = self.cfg.start_new_block();
                 let target_blocks = make_target_blocks(self);
 
@@ -506,7 +506,7 @@ pub(super) fn sort_candidate<'pat>(
         let (match_pair_index, match_pair) =
             candidate.match_pairs.iter().enumerate().find(|&(_, mp)| mp.place == *test_place)?;
 
-        match (&test.kind, &*match_pair.pattern.kind) {
+        match (&test.kind, &match_pair.pattern.kind) {
             // If we are performing a variant switch, then this
             // informs variant patterns, but nothing else.
             (
@@ -540,9 +540,9 @@ pub(super) fn sort_candidate<'pat>(
                 Some(index)
             }
 
-            (&TestKind::SwitchInt { switch_ty: _, ref options }, &PatKind::Range(range)) => {
+            (&TestKind::SwitchInt { switch_ty: _, ref options }, &PatKind::Range(ref range)) => {
                 let not_contained =
-                    self.values_not_contained_in_range(range, options).unwrap_or(false);
+                    self.values_not_contained_in_range(&*range, options).unwrap_or(false);
 
                 if not_contained {
                     // No switch values are contained in the pattern range,
@@ -569,7 +569,7 @@ pub(super) fn sort_candidate<'pat>(
                             match_pair_index,
                             candidate,
                             prefix,
-                            slice.as_ref(),
+                            slice,
                             suffix,
                         );
                         Some(0)
@@ -607,7 +607,7 @@ pub(super) fn sort_candidate<'pat>(
                             match_pair_index,
                             candidate,
                             prefix,
-                            slice.as_ref(),
+                            slice,
                             suffix,
                         );
                         Some(0)
@@ -631,7 +631,7 @@ pub(super) fn sort_candidate<'pat>(
                 }
             }
 
-            (&TestKind::Range(test), &PatKind::Range(pat)) => {
+            (&TestKind::Range(ref test), &PatKind::Range(ref pat)) => {
                 use std::cmp::Ordering::*;
 
                 if test == pat {
@@ -658,8 +658,8 @@ pub(super) fn sort_candidate<'pat>(
                 no_overlap
             }
 
-            (&TestKind::Range(range), &PatKind::Constant { value }) => {
-                if let Some(false) = self.const_range_contains(range, value) {
+            (&TestKind::Range(ref range), &PatKind::Constant { value }) => {
+                if let Some(false) = self.const_range_contains(&*range, value) {
                     // `value` is not contained in the testing range,
                     // so `value` can be matched only if this test fails.
                     Some(1)
@@ -678,7 +678,7 @@ pub(super) fn sort_candidate<'pat>(
                 // However, at this point we can still encounter or-patterns that were extracted
                 // from previous calls to `sort_candidate`, so we need to manually address that
                 // case to avoid panicking in `self.test()`.
-                if let PatKind::Or { .. } = &*match_pair.pattern.kind {
+                if let PatKind::Or { .. } = &match_pair.pattern.kind {
                     return None;
                 }
 
@@ -708,9 +708,9 @@ fn candidate_after_slice_test<'pat>(
         &mut self,
         match_pair_index: usize,
         candidate: &mut Candidate<'pat, 'tcx>,
-        prefix: &'pat [Pat<'tcx>],
-        opt_slice: Option<&'pat Pat<'tcx>>,
-        suffix: &'pat [Pat<'tcx>],
+        prefix: &'pat [Box<Pat<'tcx>>],
+        opt_slice: &'pat Option<Box<Pat<'tcx>>>,
+        suffix: &'pat [Box<Pat<'tcx>>],
     ) {
         let removed_place = candidate.match_pairs.remove(match_pair_index).place;
         self.prefix_slice_suffix(
@@ -754,7 +754,7 @@ fn error_simplifyable<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> !
 
     fn const_range_contains(
         &self,
-        range: PatRange<'tcx>,
+        range: &PatRange<'tcx>,
         value: ConstantKind<'tcx>,
     ) -> Option<bool> {
         use std::cmp::Ordering::*;
@@ -772,7 +772,7 @@ fn const_range_contains(
 
     fn values_not_contained_in_range(
         &self,
-        range: PatRange<'tcx>,
+        range: &PatRange<'tcx>,
         options: &FxIndexMap<ConstantKind<'tcx>, u128>,
     ) -> Option<bool> {
         for &val in options.keys() {
index 9a1e98d3bb18ddc8d6b6e646a1de00610ae4ae33..06f24040f7be05d80cbd277c2f41dd947cb235d2 100644 (file)
@@ -26,9 +26,9 @@ pub(crate) fn prefix_slice_suffix<'pat>(
         &mut self,
         match_pairs: &mut SmallVec<[MatchPair<'pat, 'tcx>; 1]>,
         place: &PlaceBuilder<'tcx>,
-        prefix: &'pat [Pat<'tcx>],
-        opt_slice: Option<&'pat Pat<'tcx>>,
-        suffix: &'pat [Pat<'tcx>],
+        prefix: &'pat [Box<Pat<'tcx>>],
+        opt_slice: &'pat Option<Box<Pat<'tcx>>>,
+        suffix: &'pat [Box<Pat<'tcx>>],
     ) {
         let tcx = self.tcx;
         let (min_length, exact_size) = if let Ok(place_resolved) =
index 684b228e87fa983ef3b778fe587c41f354fc7c3b..763038c52d7fab8d54a003b1e94cc5fda9d47605 100644 (file)
@@ -1015,7 +1015,7 @@ fn args_and_body(
             let original_source_scope = self.source_scope;
             let span = pattern.span;
             self.set_correct_source_scope_for_arg(arg.hir_id, original_source_scope, span);
-            match *pattern.kind {
+            match pattern.kind {
                 // Don't introduce extra copies for simple bindings
                 PatKind::Binding {
                     mutability,
@@ -1052,7 +1052,10 @@ fn args_and_body(
                         Some((Some(&place), span)),
                     );
                     let place_builder = PlaceBuilder::from(local);
-                    unpack!(block = self.place_into_pattern(block, pattern, place_builder, false));
+                    unpack!(
+                        block =
+                            self.place_into_pattern(block, pattern.as_ref(), place_builder, false)
+                    );
                 }
             }
             self.source_scope = original_source_scope;
index bf5a2e7c73fabf8a36ac3e9a01bd0fc8f83cdbdb..495738ebe1c7ac9d392af26ac38f9e4bd6a309c1 100644 (file)
@@ -214,7 +214,7 @@ fn visit_block(&mut self, block: &Block) {
 
     fn visit_pat(&mut self, pat: &Pat<'tcx>) {
         if self.in_union_destructure {
-            match *pat.kind {
+            match pat.kind {
                 // binding to a variable allows getting stuff out of variable
                 PatKind::Binding { .. }
                 // match is conditional on having this value
@@ -236,7 +236,7 @@ fn visit_pat(&mut self, pat: &Pat<'tcx>) {
             }
         };
 
-        match &*pat.kind {
+        match &pat.kind {
             PatKind::Leaf { .. } => {
                 if let ty::Adt(adt_def, ..) = pat.ty.kind() {
                     if adt_def.is_union() {
index 54c4b9eda70dc16a8115c1a0a9ff8334ed383466..321353ca20bae01f30992f1137fe109c582afd29 100644 (file)
@@ -87,21 +87,21 @@ fn mirror_stmts(
                             {
                                 debug!("mirror_stmts: user_ty={:?}", user_ty);
                                 let annotation = CanonicalUserTypeAnnotation {
-                                    user_ty,
+                                    user_ty: Box::new(user_ty),
                                     span: ty.span,
                                     inferred_ty: self.typeck_results.node_type(ty.hir_id),
                                 };
-                                pattern = Pat {
+                                pattern = Box::new(Pat {
                                     ty: pattern.ty,
                                     span: pattern.span,
-                                    kind: Box::new(PatKind::AscribeUserType {
+                                    kind: PatKind::AscribeUserType {
                                         ascription: Ascription {
                                             annotation,
                                             variance: ty::Variance::Covariant,
                                         },
                                         subpattern: pattern,
-                                    }),
-                                };
+                                    },
+                                });
                             }
                         }
 
index 0c2b117453fe9ed5785a444d4ee0deff4186f34b..d059877f8e71fcb481258efc1c8aa5698835479c 100644 (file)
@@ -261,15 +261,19 @@ fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx>
 
         let kind = match expr.kind {
             // Here comes the interesting stuff:
-            hir::ExprKind::MethodCall(segment, ref args, fn_span) => {
+            hir::ExprKind::MethodCall(segment, receiver, ref args, fn_span) => {
                 // Rewrite a.b(c) into UFCS form like Trait::b(a, c)
                 let expr = self.method_callee(expr, segment.ident.span, None);
                 // When we apply adjustments to the receiver, use the span of
                 // the overall method call for better diagnostics. args[0]
                 // is guaranteed to exist, since a method call always has a receiver.
-                let old_adjustment_span = self.adjustment_span.replace((args[0].hir_id, expr_span));
-                tracing::info!("Using method span: {:?}", expr.span);
-                let args = self.mirror_exprs(args);
+                let old_adjustment_span =
+                    self.adjustment_span.replace((receiver.hir_id, expr_span));
+                info!("Using method span: {:?}", expr.span);
+                let args = std::iter::once(receiver)
+                    .chain(args.iter())
+                    .map(|expr| self.mirror_expr(expr))
+                    .collect();
                 self.adjustment_span = old_adjustment_span;
                 ExprKind::Call {
                     ty: expr.ty,
index f7351a4caa9545250d59dcbf5c21a146724fcc27..ae53df1f9b9a4166353f93f22b96d54791dfe52f 100644 (file)
@@ -77,8 +77,8 @@ fn new(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalDefId>) -> Cx<'tcx> {
         }
     }
 
-    #[tracing::instrument(level = "debug", skip(self))]
-    pub(crate) fn pattern_from_hir(&mut self, p: &hir::Pat<'_>) -> Pat<'tcx> {
+    #[instrument(level = "debug", skip(self))]
+    pub(crate) fn pattern_from_hir(&mut self, p: &hir::Pat<'_>) -> Box<Pat<'tcx>> {
         let p = match self.tcx.hir().get(p.hir_id) {
             Node::Pat(p) => p,
             node => bug!("pattern became {:?}", node),
index f2045ac19cac42920293ecc3b71d865cf5cb29a9..b58685e895809b266d76df47122f3add615fad3a 100644 (file)
@@ -19,21 +19,18 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
     /// Converts an evaluated constant to a pattern (if possible).
     /// This means aggregate values (like structs and enums) are converted
     /// to a pattern that matches the value (as if you'd compared via structural equality).
-    #[instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self), ret)]
     pub(super) fn const_to_pat(
         &self,
         cv: mir::ConstantKind<'tcx>,
         id: hir::HirId,
         span: Span,
         mir_structural_match_violation: bool,
-    ) -> Pat<'tcx> {
-        let pat = self.tcx.infer_ctxt().enter(|infcx| {
+    ) -> Box<Pat<'tcx>> {
+        self.tcx.infer_ctxt().enter(|infcx| {
             let mut convert = ConstToPat::new(self, id, span, infcx);
             convert.to_pat(cv, mir_structural_match_violation)
-        });
-
-        debug!(?pat);
-        pat
+        })
     }
 }
 
@@ -159,7 +156,7 @@ fn to_pat(
         &mut self,
         cv: mir::ConstantKind<'tcx>,
         mir_structural_match_violation: bool,
-    ) -> Pat<'tcx> {
+    ) -> Box<Pat<'tcx>> {
         trace!(self.treat_byte_string_as_slice);
         // This method is just a wrapper handling a validity check; the heavy lifting is
         // performed by the recursive `recur` method, which is not meant to be
@@ -169,10 +166,12 @@ fn to_pat(
         // level of indirection can be eliminated
 
         let inlined_const_as_pat =
-            self.recur(cv, mir_structural_match_violation).unwrap_or_else(|_| Pat {
-                span: self.span,
-                ty: cv.ty(),
-                kind: Box::new(PatKind::Constant { value: cv }),
+            self.recur(cv, mir_structural_match_violation).unwrap_or_else(|_| {
+                Box::new(Pat {
+                    span: self.span,
+                    ty: cv.ty(),
+                    kind: PatKind::Constant { value: cv },
+                })
             });
 
         if self.include_lint_checks && !self.saw_const_match_error.get() {
@@ -274,7 +273,7 @@ fn recur(
         &self,
         cv: mir::ConstantKind<'tcx>,
         mir_structural_match_violation: bool,
-    ) -> Result<Pat<'tcx>, FallbackToConstRef> {
+    ) -> Result<Box<Pat<'tcx>>, FallbackToConstRef> {
         let id = self.id;
         let span = self.span;
         let tcx = self.tcx();
@@ -401,7 +400,7 @@ fn recur(
                     .map(|val| self.recur(*val, false))
                     .collect::<Result<_, _>>()?,
                 slice: None,
-                suffix: Vec::new(),
+                suffix: Box::new([]),
             },
             ty::Ref(_, pointee_ty, ..) => match *pointee_ty.kind() {
                 // These are not allowed and will error elsewhere anyway.
@@ -428,8 +427,8 @@ fn recur(
                     let old = self.behind_reference.replace(true);
                     let array = tcx.deref_mir_constant(self.param_env.and(cv));
                     let val = PatKind::Deref {
-                        subpattern: Pat {
-                            kind: Box::new(PatKind::Array {
+                        subpattern: Box::new(Pat {
+                            kind: PatKind::Array {
                                 prefix: tcx
                                     .destructure_mir_constant(param_env, array)
                                     .fields
@@ -437,11 +436,11 @@ fn recur(
                                     .map(|val| self.recur(*val, false))
                                     .collect::<Result<_, _>>()?,
                                 slice: None,
-                                suffix: vec![],
-                            }),
+                                suffix: Box::new([]),
+                            },
                             span,
                             ty: *pointee_ty,
-                        },
+                        }),
                     };
                     self.behind_reference.set(old);
                     val
@@ -454,8 +453,8 @@ fn recur(
                     let old = self.behind_reference.replace(true);
                     let array = tcx.deref_mir_constant(self.param_env.and(cv));
                     let val = PatKind::Deref {
-                        subpattern: Pat {
-                            kind: Box::new(PatKind::Slice {
+                        subpattern: Box::new(Pat {
+                            kind: PatKind::Slice {
                                 prefix: tcx
                                     .destructure_mir_constant(param_env, array)
                                     .fields
@@ -463,11 +462,11 @@ fn recur(
                                     .map(|val| self.recur(*val, false))
                                     .collect::<Result<_, _>>()?,
                                 slice: None,
-                                suffix: vec![],
-                            }),
+                                suffix: Box::new([]),
+                            },
                             span,
                             ty: tcx.mk_slice(elem_ty),
-                        },
+                        }),
                     };
                     self.behind_reference.set(old);
                     val
@@ -601,6 +600,6 @@ fn recur(
             );
         }
 
-        Ok(Pat { span, ty: cv.ty(), kind: Box::new(kind) })
+        Ok(Box::new(Pat { span, ty: cv.ty(), kind }))
     }
 }
index 8d6f8efb6003f9fd7745b02e331859f14cc3ab77..5105f059f9b64797317ac251dc630389a8a1ceb8 100644 (file)
@@ -71,9 +71,9 @@
 /// Recursively expand this pattern into its subpatterns. Only useful for or-patterns.
 fn expand_or_pat<'p, 'tcx>(pat: &'p Pat<'tcx>) -> Vec<&'p Pat<'tcx>> {
     fn expand<'p, 'tcx>(pat: &'p Pat<'tcx>, vec: &mut Vec<&'p Pat<'tcx>>) {
-        if let PatKind::Or { pats } = pat.kind.as_ref() {
-            for pat in pats {
-                expand(pat, vec);
+        if let PatKind::Or { pats } = &pat.kind {
+            for pat in pats.iter() {
+                expand(&pat, vec);
             }
         } else {
             vec.push(pat)
@@ -252,10 +252,14 @@ fn to_pat<'tcx>(&self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Pat<'tcx> {
         let kind = if lo == hi {
             PatKind::Constant { value: lo_const }
         } else {
-            PatKind::Range(PatRange { lo: lo_const, hi: hi_const, end: RangeEnd::Included })
+            PatKind::Range(Box::new(PatRange {
+                lo: lo_const,
+                hi: hi_const,
+                end: RangeEnd::Included,
+            }))
         };
 
-        Pat { ty, span: DUMMY_SP, kind: Box::new(kind) }
+        Pat { ty, span: DUMMY_SP, kind }
     }
 
     /// Lint on likely incorrect range patterns (#63987)
@@ -1297,7 +1301,7 @@ pub(crate) fn from_pat(cx: &MatchCheckCtxt<'p, 'tcx>, pat: &Pat<'tcx>) -> Self {
         let mkpat = |pat| DeconstructedPat::from_pat(cx, pat);
         let ctor;
         let fields;
-        match pat.kind.as_ref() {
+        match &pat.kind {
             PatKind::AscribeUserType { subpattern, .. } => return mkpat(subpattern),
             PatKind::Binding { subpattern: Some(subpat), .. } => return mkpat(subpat),
             PatKind::Binding { subpattern: None, .. } | PatKind::Wild => {
@@ -1342,9 +1346,9 @@ pub(crate) fn from_pat(cx: &MatchCheckCtxt<'p, 'tcx>, pat: &Pat<'tcx>) -> Self {
                         fields = Fields::singleton(cx, pat);
                     }
                     ty::Adt(adt, _) => {
-                        ctor = match pat.kind.as_ref() {
+                        ctor = match pat.kind {
                             PatKind::Leaf { .. } => Single,
-                            PatKind::Variant { variant_index, .. } => Variant(*variant_index),
+                            PatKind::Variant { variant_index, .. } => Variant(variant_index),
                             _ => bug!(),
                         };
                         let variant = &adt.variant(ctor.variant_index_for_adt(*adt));
@@ -1402,7 +1406,7 @@ pub(crate) fn from_pat(cx: &MatchCheckCtxt<'p, 'tcx>, pat: &Pat<'tcx>) -> Self {
                     }
                 }
             }
-            &PatKind::Range(PatRange { lo, hi, end }) => {
+            &PatKind::Range(box PatRange { lo, hi, end }) => {
                 let ty = lo.ty();
                 ctor = if let Some(int_range) = IntRange::from_range(
                     cx.tcx,
@@ -1429,7 +1433,8 @@ pub(crate) fn from_pat(cx: &MatchCheckCtxt<'p, 'tcx>, pat: &Pat<'tcx>) -> Self {
                     FixedLen(prefix.len() + suffix.len())
                 };
                 ctor = Slice(Slice::new(array_len, kind));
-                fields = Fields::from_iter(cx, prefix.iter().chain(suffix).map(mkpat));
+                fields =
+                    Fields::from_iter(cx, prefix.iter().chain(suffix.iter()).map(|p| mkpat(&*p)));
             }
             PatKind::Or { .. } => {
                 ctor = Or;
@@ -1442,15 +1447,15 @@ pub(crate) fn from_pat(cx: &MatchCheckCtxt<'p, 'tcx>, pat: &Pat<'tcx>) -> Self {
 
     pub(crate) fn to_pat(&self, cx: &MatchCheckCtxt<'p, 'tcx>) -> Pat<'tcx> {
         let is_wildcard = |pat: &Pat<'_>| {
-            matches!(*pat.kind, PatKind::Binding { subpattern: None, .. } | PatKind::Wild)
+            matches!(pat.kind, PatKind::Binding { subpattern: None, .. } | PatKind::Wild)
         };
-        let mut subpatterns = self.iter_fields().map(|p| p.to_pat(cx));
-        let pat = match &self.ctor {
+        let mut subpatterns = self.iter_fields().map(|p| Box::new(p.to_pat(cx)));
+        let kind = match &self.ctor {
             Single | Variant(_) => match self.ty.kind() {
                 ty::Tuple(..) => PatKind::Leaf {
                     subpatterns: subpatterns
                         .enumerate()
-                        .map(|(i, p)| FieldPat { field: Field::new(i), pattern: p })
+                        .map(|(i, pattern)| FieldPat { field: Field::new(i), pattern })
                         .collect(),
                 },
                 ty::Adt(adt_def, _) if adt_def.is_box() => {
@@ -1485,7 +1490,7 @@ pub(crate) fn to_pat(&self, cx: &MatchCheckCtxt<'p, 'tcx>) -> Pat<'tcx> {
                     FixedLen(_) => PatKind::Slice {
                         prefix: subpatterns.collect(),
                         slice: None,
-                        suffix: vec![],
+                        suffix: Box::new([]),
                     },
                     VarLen(prefix, _) => {
                         let mut subpatterns = subpatterns.peekable();
@@ -1504,14 +1509,18 @@ pub(crate) fn to_pat(&self, cx: &MatchCheckCtxt<'p, 'tcx>) -> Pat<'tcx> {
                                 subpatterns.next();
                             }
                         }
-                        let suffix: Vec<_> = subpatterns.collect();
+                        let suffix: Box<[_]> = subpatterns.collect();
                         let wild = Pat::wildcard_from_ty(self.ty);
-                        PatKind::Slice { prefix, slice: Some(wild), suffix }
+                        PatKind::Slice {
+                            prefix: prefix.into_boxed_slice(),
+                            slice: Some(Box::new(wild)),
+                            suffix,
+                        }
                     }
                 }
             }
             &Str(value) => PatKind::Constant { value },
-            &FloatRange(lo, hi, end) => PatKind::Range(PatRange { lo, hi, end }),
+            &FloatRange(lo, hi, end) => PatKind::Range(Box::new(PatRange { lo, hi, end })),
             IntRange(range) => return range.to_pat(cx.tcx, self.ty),
             Wildcard | NonExhaustive => PatKind::Wild,
             Missing { .. } => bug!(
@@ -1523,7 +1532,7 @@ pub(crate) fn to_pat(&self, cx: &MatchCheckCtxt<'p, 'tcx>) -> Pat<'tcx> {
             }
         };
 
-        Pat { ty: self.ty, span: DUMMY_SP, kind: Box::new(pat) }
+        Pat { ty: self.ty, span: DUMMY_SP, kind }
     }
 
     pub(super) fn is_or_pat(&self) -> bool {
index a13748a2d474ad1b92e74f24de438222379b376b..d2f93b679acc596a89525e118f23a06dfcc385eb 100644 (file)
@@ -49,7 +49,7 @@ pub(crate) fn pat_from_hir<'a, 'tcx>(
     param_env: ty::ParamEnv<'tcx>,
     typeck_results: &'a ty::TypeckResults<'tcx>,
     pat: &'tcx hir::Pat<'tcx>,
-) -> Pat<'tcx> {
+) -> Box<Pat<'tcx>> {
     let mut pcx = PatCtxt::new(tcx, param_env, typeck_results);
     let result = pcx.lower_pattern(pat);
     if !pcx.errors.is_empty() {
@@ -74,7 +74,7 @@ pub(crate) fn include_lint_checks(&mut self) -> &mut Self {
         self
     }
 
-    pub(crate) fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Pat<'tcx> {
+    pub(crate) fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
         // When implicit dereferences have been inserted in this pattern, the unadjusted lowered
         // pattern has the type that results *after* dereferencing. For example, in this code:
         //
@@ -97,13 +97,13 @@ pub(crate) fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Pat<'tcx> {
         let unadjusted_pat = self.lower_pattern_unadjusted(pat);
         self.typeck_results.pat_adjustments().get(pat.hir_id).unwrap_or(&vec![]).iter().rev().fold(
             unadjusted_pat,
-            |pat, ref_ty| {
+            |pat: Box<_>, ref_ty| {
                 debug!("{:?}: wrapping pattern with type {:?}", pat, ref_ty);
-                Pat {
+                Box::new(Pat {
                     span: pat.span,
                     ty: *ref_ty,
-                    kind: Box::new(PatKind::Deref { subpattern: pat }),
-                }
+                    kind: PatKind::Deref { subpattern: pat },
+                })
             },
         )
     }
@@ -113,7 +113,7 @@ fn lower_range_expr(
         expr: &'tcx hir::Expr<'tcx>,
     ) -> (PatKind<'tcx>, Option<Ascription<'tcx>>) {
         match self.lower_lit(expr) {
-            PatKind::AscribeUserType { ascription, subpattern: Pat { kind: box kind, .. } } => {
+            PatKind::AscribeUserType { ascription, subpattern: box Pat { kind, .. } } => {
                 (kind, Some(ascription))
             }
             kind => (kind, None),
@@ -134,7 +134,9 @@ fn lower_pattern_range(
         match (end, cmp) {
             // `x..y` where `x < y`.
             // Non-empty because the range includes at least `x`.
-            (RangeEnd::Excluded, Some(Ordering::Less)) => PatKind::Range(PatRange { lo, hi, end }),
+            (RangeEnd::Excluded, Some(Ordering::Less)) => {
+                PatKind::Range(Box::new(PatRange { lo, hi, end }))
+            }
             // `x..y` where `x >= y`. The range is empty => error.
             (RangeEnd::Excluded, _) => {
                 struct_span_err!(
@@ -149,7 +151,9 @@ fn lower_pattern_range(
             // `x..=y` where `x == y`.
             (RangeEnd::Included, Some(Ordering::Equal)) => PatKind::Constant { value: lo },
             // `x..=y` where `x < y`.
-            (RangeEnd::Included, Some(Ordering::Less)) => PatKind::Range(PatRange { lo, hi, end }),
+            (RangeEnd::Included, Some(Ordering::Less)) => {
+                PatKind::Range(Box::new(PatRange { lo, hi, end }))
+            }
             // `x..=y` where `x > y` hence the range is empty => error.
             (RangeEnd::Included, _) => {
                 let mut err = struct_span_err!(
@@ -196,7 +200,7 @@ fn normalize_range_pattern_ends(
         }
     }
 
-    fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Pat<'tcx> {
+    fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
         let mut ty = self.typeck_results.node_type(pat.hir_id);
 
         let kind = match pat.kind {
@@ -228,7 +232,7 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Pat<'tcx> {
                 // constants somewhere. Have them on the range pattern.
                 for end in &[lo, hi] {
                     if let Some((_, Some(ascription))) = end {
-                        let subpattern = Pat { span: pat.span, ty, kind: Box::new(kind) };
+                        let subpattern = Box::new(Pat { span: pat.span, ty, kind });
                         kind =
                             PatKind::AscribeUserType { ascription: ascription.clone(), subpattern };
                     }
@@ -322,7 +326,7 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Pat<'tcx> {
             hir::PatKind::Or(ref pats) => PatKind::Or { pats: self.lower_patterns(pats) },
         };
 
-        Pat { span: pat.span, ty, kind: Box::new(kind) }
+        Box::new(Pat { span: pat.span, ty, kind })
     }
 
     fn lower_tuple_subpats(
@@ -340,11 +344,14 @@ fn lower_tuple_subpats(
             .collect()
     }
 
-    fn lower_patterns(&mut self, pats: &'tcx [hir::Pat<'tcx>]) -> Vec<Pat<'tcx>> {
+    fn lower_patterns(&mut self, pats: &'tcx [hir::Pat<'tcx>]) -> Box<[Box<Pat<'tcx>>]> {
         pats.iter().map(|p| self.lower_pattern(p)).collect()
     }
 
-    fn lower_opt_pattern(&mut self, pat: &'tcx Option<&'tcx hir::Pat<'tcx>>) -> Option<Pat<'tcx>> {
+    fn lower_opt_pattern(
+        &mut self,
+        pat: &'tcx Option<&'tcx hir::Pat<'tcx>>,
+    ) -> Option<Box<Pat<'tcx>>> {
         pat.as_ref().map(|p| self.lower_pattern(p))
     }
 
@@ -436,12 +443,12 @@ fn lower_variant_or_leaf(
         if let Some(user_ty) = self.user_substs_applied_to_ty_of_hir_id(hir_id) {
             debug!("lower_variant_or_leaf: kind={:?} user_ty={:?} span={:?}", kind, user_ty, span);
             let annotation = CanonicalUserTypeAnnotation {
-                user_ty,
+                user_ty: Box::new(user_ty),
                 span,
                 inferred_ty: self.typeck_results.node_type(hir_id),
             };
             kind = PatKind::AscribeUserType {
-                subpattern: Pat { span, ty, kind: Box::new(kind) },
+                subpattern: Box::new(Pat { span, ty, kind }),
                 ascription: Ascription { annotation, variance: ty::Variance::Covariant },
             };
         }
@@ -453,11 +460,11 @@ fn lower_variant_or_leaf(
     /// it to `const_to_pat`. Any other path (like enum variants without fields)
     /// is converted to the corresponding pattern via `lower_variant_or_leaf`.
     #[instrument(skip(self), level = "debug")]
-    fn lower_path(&mut self, qpath: &hir::QPath<'_>, id: hir::HirId, span: Span) -> Pat<'tcx> {
+    fn lower_path(&mut self, qpath: &hir::QPath<'_>, id: hir::HirId, span: Span) -> Box<Pat<'tcx>> {
         let ty = self.typeck_results.node_type(id);
         let res = self.typeck_results.qpath_res(qpath, id);
 
-        let pat_from_kind = |kind| Pat { span, ty, kind: Box::new(kind) };
+        let pat_from_kind = |kind| Box::new(Pat { span, ty, kind });
 
         let (def_id, is_associated_const) = match res {
             Res::Def(DefKind::Const, def_id) => (def_id, false),
@@ -505,13 +512,13 @@ fn lower_path(&mut self, qpath: &hir::QPath<'_>, id: hir::HirId, span: Span) ->
                 let user_provided_types = self.typeck_results().user_provided_types();
                 if let Some(&user_ty) = user_provided_types.get(id) {
                     let annotation = CanonicalUserTypeAnnotation {
-                        user_ty,
+                        user_ty: Box::new(user_ty),
                         span,
                         inferred_ty: self.typeck_results().node_type(id),
                     };
-                    Pat {
+                    Box::new(Pat {
                         span,
-                        kind: Box::new(PatKind::AscribeUserType {
+                        kind: PatKind::AscribeUserType {
                             subpattern: pattern,
                             ascription: Ascription {
                                 annotation,
@@ -519,9 +526,9 @@ fn lower_path(&mut self, qpath: &hir::QPath<'_>, id: hir::HirId, span: Span) ->
                                 /// `variance` field documentation for details.
                                 variance: ty::Variance::Contravariant,
                             },
-                        }),
+                        },
                         ty: const_.ty(),
-                    }
+                    })
                 } else {
                     pattern
                 }
@@ -569,7 +576,7 @@ fn lower_inline_const(
                     _ => bug!("Expected either ConstKind::Param or ConstKind::Unevaluated"),
                 }
             }
-            mir::ConstantKind::Val(_, _) => *self.const_to_pat(value, id, span, false).kind,
+            mir::ConstantKind::Val(_, _) => self.const_to_pat(value, id, span, false).kind,
         }
     }
 
@@ -580,7 +587,7 @@ fn lower_inline_const(
     fn lower_lit(&mut self, expr: &'tcx hir::Expr<'tcx>) -> PatKind<'tcx> {
         let (lit, neg) = match expr.kind {
             hir::ExprKind::Path(ref qpath) => {
-                return *self.lower_path(qpath, expr.hir_id, expr.span).kind;
+                return self.lower_path(qpath, expr.hir_id, expr.span).kind;
             }
             hir::ExprKind::ConstBlock(ref anon_const) => {
                 return self.lower_inline_const(anon_const, expr.hir_id, expr.span);
@@ -598,7 +605,7 @@ fn lower_lit(&mut self, expr: &'tcx hir::Expr<'tcx>) -> PatKind<'tcx> {
         let lit_input =
             LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg };
         match self.tcx.at(expr.span).lit_to_mir_constant(lit_input) {
-            Ok(constant) => *self.const_to_pat(constant, expr.hir_id, lit.span, false).kind,
+            Ok(constant) => self.const_to_pat(constant, expr.hir_id, lit.span, false).kind,
             Err(LitToConstError::Reported) => PatKind::Wild,
             Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"),
         }
@@ -646,6 +653,12 @@ fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
     }
 }
 
+impl<'tcx, T: PatternFoldable<'tcx>> PatternFoldable<'tcx> for Box<[T]> {
+    fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
+        self.iter().map(|t| t.fold_with(folder)).collect()
+    }
+}
+
 impl<'tcx, T: PatternFoldable<'tcx>> PatternFoldable<'tcx> for Option<T> {
     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
         self.as_ref().map(|t| t.fold_with(folder))
@@ -732,7 +745,7 @@ fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
                 PatKind::Deref { subpattern: subpattern.fold_with(folder) }
             }
             PatKind::Constant { value } => PatKind::Constant { value },
-            PatKind::Range(range) => PatKind::Range(range),
+            PatKind::Range(ref range) => PatKind::Range(range.clone()),
             PatKind::Slice { ref prefix, ref slice, ref suffix } => PatKind::Slice {
                 prefix: prefix.fold_with(folder),
                 slice: slice.fold_with(folder),
index 443626d14b9f67c636bed05f1a7483d9366ce79d..319183eb9b33fc7e0a81f15cedd6f87cd641ad88 100644 (file)
@@ -791,7 +791,7 @@ fn lint_non_exhaustive_omitted_patterns<'p, 'tcx>(
 /// `is_under_guard` is used to inform if the pattern has a guard. If it
 /// has one it must not be inserted into the matrix. This shouldn't be
 /// relied on for soundness.
-#[instrument(level = "debug", skip(cx, matrix, hir_id))]
+#[instrument(level = "debug", skip(cx, matrix, hir_id), ret)]
 fn is_useful<'p, 'tcx>(
     cx: &MatchCheckCtxt<'p, 'tcx>,
     matrix: &Matrix<'p, 'tcx>,
@@ -917,7 +917,6 @@ fn is_useful<'p, 'tcx>(
         v.head().set_reachable();
     }
 
-    debug!(?ret);
     ret
 }
 
index 0b674b38f32826f5a78cc2a561ea0eeed53888dd..162f7d969b181d8e01eeb22a9690f1e299c5f83e 100644 (file)
@@ -10,6 +10,7 @@
 #![feature(trusted_step)]
 #![feature(try_blocks)]
 #![feature(yeet_expr)]
+#![feature(if_let_guard)]
 #![recursion_limit = "256"]
 
 #[macro_use]
 use rustc_index::vec::IndexVec;
 use rustc_middle::mir::visit::Visitor as _;
 use rustc_middle::mir::{
-    traversal, AnalysisPhase, Body, ConstQualifs, MirPass, MirPhase, Promoted, RuntimePhase,
+    traversal, AnalysisPhase, Body, ConstQualifs, Constant, LocalDecl, MirPass, MirPhase, Operand,
+    Place, ProjectionElem, Promoted, RuntimePhase, Rvalue, SourceInfo, Statement, StatementKind,
+    TerminatorKind,
 };
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, TyCtxt, TypeVisitable};
+use rustc_span::sym;
 
 #[macro_use]
 mod pass_manager;
@@ -140,6 +144,64 @@ pub fn provide(providers: &mut Providers) {
     };
 }
 
+fn remap_mir_for_const_eval_select<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    mut body: Body<'tcx>,
+    context: hir::Constness,
+) -> Body<'tcx> {
+    for bb in body.basic_blocks.as_mut().iter_mut() {
+        let terminator = bb.terminator.as_mut().expect("invalid terminator");
+        match terminator.kind {
+            TerminatorKind::Call {
+                func: Operand::Constant(box Constant { ref literal, .. }),
+                ref mut args,
+                destination,
+                target,
+                cleanup,
+                fn_span,
+                ..
+            } if let ty::FnDef(def_id, _) = *literal.ty().kind()
+                && tcx.item_name(def_id) == sym::const_eval_select
+                && tcx.is_intrinsic(def_id) =>
+            {
+                let [tupled_args, called_in_const, called_at_rt]: [_; 3] = std::mem::take(args).try_into().unwrap();
+                let ty = tupled_args.ty(&body.local_decls, tcx);
+                let fields = ty.tuple_fields();
+                let num_args = fields.len();
+                let func = if context == hir::Constness::Const { called_in_const } else { called_at_rt };
+                let (method, place): (fn(Place<'tcx>) -> Operand<'tcx>, Place<'tcx>) = match tupled_args {
+                    Operand::Constant(_) => {
+                        // there is no good way of extracting a tuple arg from a constant (const generic stuff)
+                        // so we just create a temporary and deconstruct that.
+                        let local = body.local_decls.push(LocalDecl::new(ty, fn_span));
+                        bb.statements.push(Statement {
+                            source_info: SourceInfo::outermost(fn_span),
+                            kind: StatementKind::Assign(Box::new((local.into(), Rvalue::Use(tupled_args.clone())))),
+                        });
+                        (Operand::Move, local.into())
+                    }
+                    Operand::Move(place) => (Operand::Move, place),
+                    Operand::Copy(place) => (Operand::Copy, place),
+                };
+                let place_elems = place.projection;
+                let arguments = (0..num_args).map(|x| {
+                    let mut place_elems = place_elems.to_vec();
+                    place_elems.push(ProjectionElem::Field(x.into(), fields[x]));
+                    let projection = tcx.intern_place_elems(&place_elems);
+                    let place = Place {
+                        local: place.local,
+                        projection,
+                    };
+                    method(place)
+                }).collect();
+                terminator.kind = TerminatorKind::Call { func, args: arguments, destination, target, cleanup, from_hir_call: false, fn_span };
+            }
+            _ => {}
+        }
+    }
+    body
+}
+
 fn is_mir_available(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
     let def_id = def_id.expect_local();
     tcx.mir_keys(()).contains(&def_id)
@@ -325,7 +387,9 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -
         .body_const_context(def.did)
         .expect("mir_for_ctfe should not be used for runtime functions");
 
-    let mut body = tcx.mir_drops_elaborated_and_const_checked(def).borrow().clone();
+    let body = tcx.mir_drops_elaborated_and_const_checked(def).borrow().clone();
+
+    let mut body = remap_mir_for_const_eval_select(tcx, body, hir::Constness::Const);
 
     match context {
         // Do not const prop functions, either they get executed at runtime or exported to metadata,
@@ -558,8 +622,9 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> {
         Some(other) => panic!("do not use `optimized_mir` for constants: {:?}", other),
     }
     debug!("about to call mir_drops_elaborated...");
-    let mut body =
+    let body =
         tcx.mir_drops_elaborated_and_const_checked(ty::WithOptConstParam::unknown(did)).steal();
+    let mut body = remap_mir_for_const_eval_select(tcx, body, hir::Constness::NotConst);
     debug!("body: {:#?}", body);
     run_optimization_passes(tcx, &mut body);
 
index 170616d4b42ce76e62a6f12021907822b351e32c..be74a9d11e3c5abe6dcf4b4726785b65788d617a 100644 (file)
 //! method in operand position, we treat it as a neighbor of the current
 //! mono item. Calls are just a special case of that.
 //!
-//! #### Closures
-//! In a way, closures are a simple case. Since every closure object needs to be
-//! constructed somewhere, we can reliably discover them by observing
-//! `RValue::Aggregate` expressions with `AggregateKind::Closure`. This is also
-//! true for closures inlined from other crates.
-//!
 //! #### Drop glue
 //! Drop glue mono items are introduced by MIR drop-statements. The
 //! generated mono item will again have drop-glue item neighbors if the
@@ -419,7 +413,6 @@ fn collect_items_rec<'tcx>(
         // We've been here already, no need to search again.
         return;
     }
-    debug!("BEGIN collect_items_rec({})", starting_point.node);
 
     let mut neighbors = MonoItems { compute_inlining: true, tcx, items: Vec::new() };
     let recursion_depth_reset;
@@ -545,8 +538,6 @@ fn collect_items_rec<'tcx>(
     if let Some((def_id, depth)) = recursion_depth_reset {
         recursion_depths.insert(def_id, depth);
     }
-
-    debug!("END collect_items_rec({})", starting_point.node);
 }
 
 /// Format instance name that is already known to be too long for rustc.
@@ -838,7 +829,7 @@ fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Loc
             mir::TerminatorKind::Call { ref func, .. } => {
                 let callee_ty = func.ty(self.body, tcx);
                 let callee_ty = self.monomorphize(callee_ty);
-                visit_fn_use(self.tcx, callee_ty, true, source, &mut self.output);
+                visit_fn_use(self.tcx, callee_ty, true, source, &mut self.output)
             }
             mir::TerminatorKind::Drop { ref place, .. }
             | mir::TerminatorKind::DropAndReplace { ref place, .. } => {
@@ -1148,23 +1139,18 @@ fn find_vtable_types_for_unsizing<'tcx>(
     }
 }
 
-#[instrument(skip(tcx), level = "debug")]
+#[instrument(skip(tcx), level = "debug", ret)]
 fn create_fn_mono_item<'tcx>(
     tcx: TyCtxt<'tcx>,
     instance: Instance<'tcx>,
     source: Span,
 ) -> Spanned<MonoItem<'tcx>> {
-    debug!("create_fn_mono_item(instance={})", instance);
-
     let def_id = instance.def_id();
     if tcx.sess.opts.unstable_opts.profile_closures && def_id.is_local() && tcx.is_closure(def_id) {
         crate::util::dump_closure_profile(tcx, instance);
     }
 
-    let respanned = respan(source, MonoItem::Fn(instance.polymorphize(tcx)));
-    debug!(?respanned);
-
-    respanned
+    respan(source, MonoItem::Fn(instance.polymorphize(tcx)))
 }
 
 /// Creates a `MonoItem` for each method that is referenced by the vtable for
@@ -1309,7 +1295,7 @@ fn is_root(&self, def_id: LocalDefId) -> bool {
     #[instrument(skip(self), level = "debug")]
     fn push_if_root(&mut self, def_id: LocalDefId) {
         if self.is_root(def_id) {
-            debug!("RootCollector::push_if_root: found root def_id={:?}", def_id);
+            debug!("found root");
 
             let instance = Instance::mono(self.tcx, def_id.to_def_id());
             self.output.push(create_fn_mono_item(self.tcx, instance, DUMMY_SP));
@@ -1322,7 +1308,7 @@ fn push_if_root(&mut self, def_id: LocalDefId) {
     /// the return type of `main`. This is not needed when
     /// the user writes their own `start` manually.
     fn push_extra_entry_roots(&mut self) {
-        let Some((main_def_id, EntryFnType::Main)) = self.entry_fn else {
+        let Some((main_def_id, EntryFnType::Main { .. })) = self.entry_fn else {
             return;
         };
 
index 6e4ab2a35c3375e0c43b274ae285bf7fbd22f28d..af4b35db3bace8bbaefb9b7808e01bd05aaf75ed 100644 (file)
@@ -33,7 +33,6 @@ pub fn provide(providers: &mut Providers) {
 ///
 /// Returns a bitset where bits representing unused parameters are set (`is_empty` indicates all
 /// parameters are used).
-#[instrument(level = "debug", skip(tcx))]
 fn unused_generic_params<'tcx>(
     tcx: TyCtxt<'tcx>,
     instance: ty::InstanceDef<'tcx>,
index 848e142e59ce9b4dcc47b41a37fb4d46b073d330..63819a2f98df57b17a49a426500e48111befcfa4 100644 (file)
@@ -14,8 +14,6 @@
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{edition::Edition, BytePos, Pos, Span};
 
-use tracing::debug;
-
 mod tokentrees;
 mod unescape_error_reporting;
 mod unicode_chars;
index 273827864f1a405295e2f7f0499d605c82f290f0..77c4fadab45eacc9f61d5fd4cb4d361cedc62666 100644 (file)
@@ -20,13 +20,9 @@ pub(crate) fn emit_unescape_error(
     range: Range<usize>,
     error: EscapeError,
 ) {
-    tracing::debug!(
+    debug!(
         "emit_unescape_error: {:?}, {:?}, {:?}, {:?}, {:?}",
-        lit,
-        span_with_quotes,
-        mode,
-        range,
-        error
+        lit, span_with_quotes, mode, range, error
     );
     let last_char = || {
         let c = lit[range.clone()].chars().rev().next().unwrap();
index 72ab96b5ca67032aa9e4c83509e42a5b4ced6613..77a6bde1c164e43ac43c73d6a36e50929da3a671 100644 (file)
@@ -7,8 +7,6 @@
 use rustc_span::{sym, BytePos, Span};
 use std::convert::TryInto;
 
-use tracing::debug;
-
 // Public for rustfmt usage
 #[derive(Debug)]
 pub enum InnerAttrPolicy<'a> {
index f353ee6df9bc173f77a5d1e58117f9664fa145dd..2e58605cf19b00f431b93025dc5ff34a97aa79f9 100644 (file)
@@ -52,7 +52,7 @@ pub(crate) fn take_for_recovery(self) -> AttrVec {
     // Prepend `self.attrs` to `attrs`.
     // FIXME: require passing an NT to prevent misuse of this method
     pub(crate) fn prepend_to_nt_inner(self, attrs: &mut AttrVec) {
-        let mut self_attrs = self.attrs.clone();
+        let mut self_attrs = self.attrs;
         std::mem::swap(attrs, &mut self_attrs);
         attrs.extend(self_attrs);
     }
index f0ea1dfe297f2fb5c99da39460a21b693bc9c980..9b5dd09372cc8cd18a2746948e2f43a01f5ff54d 100644 (file)
@@ -10,9 +10,9 @@
 use rustc_ast::token::{self, Delimiter, Lit, LitKind, TokenKind};
 use rustc_ast::util::parser::AssocOp;
 use rustc_ast::{
-    AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingMode, Block,
-    BlockCheckMode, Expr, ExprKind, GenericArg, Generics, Item, ItemKind, Mutability, Param, Pat,
-    PatKind, Path, PathSegment, QSelf, Ty, TyKind,
+    AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingAnnotation, Block,
+    BlockCheckMode, Expr, ExprKind, GenericArg, Generics, Item, ItemKind, Param, Pat, PatKind,
+    Path, PathSegment, QSelf, Ty, TyKind,
 };
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxHashSet;
@@ -29,7 +29,6 @@
 use std::mem::take;
 
 use crate::parser;
-use tracing::{debug, trace};
 
 const TURBOFISH_SUGGESTION_STR: &str =
     "use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments";
@@ -38,7 +37,7 @@
 pub(super) fn dummy_arg(ident: Ident) -> Param {
     let pat = P(Pat {
         id: ast::DUMMY_NODE_ID,
-        kind: PatKind::Ident(BindingMode::ByValue(Mutability::Not), ident, None),
+        kind: PatKind::Ident(BindingAnnotation::NONE, ident, None),
         span: ident.span,
         tokens: None,
     });
@@ -2962,7 +2961,7 @@ pub(crate) fn maybe_recover_colon_colon_in_pat_typo(
                                 }
                                 _ => {}
                             },
-                            PatKind::Ident(BindingMode::ByValue(Mutability::Not), ident, None) => {
+                            PatKind::Ident(BindingAnnotation::NONE, ident, None) => {
                                 match &first_pat.kind {
                                     PatKind::Ident(_, old_ident, _) => {
                                         let path = PatKind::Path(
index b743162a7e4d0809a234454ccea601335bb9cc2a..dbdd85ea8e87d5feb428d5e5807b3d5962c0e669 100644 (file)
@@ -8,7 +8,7 @@
 use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
 use rustc_ast::{self as ast, AttrVec, Attribute, DUMMY_NODE_ID};
 use rustc_ast::{Async, Const, Defaultness, IsAuto, Mutability, Unsafe, UseTree, UseTreeKind};
-use rustc_ast::{BindingMode, Block, FnDecl, FnSig, Param, SelfKind};
+use rustc_ast::{BindingAnnotation, Block, FnDecl, FnSig, Param, SelfKind};
 use rustc_ast::{EnumDef, FieldDef, Generics, TraitRef, Ty, TyKind, Variant, VariantData};
 use rustc_ast::{FnHeader, ForeignItem, Path, PathSegment, Visibility, VisibilityKind};
 use rustc_ast::{MacArgs, MacCall, MacDelimiter};
@@ -22,7 +22,6 @@
 
 use std::convert::TryFrom;
 use std::mem;
-use tracing::debug;
 
 impl<'a> Parser<'a> {
     /// Parses a source module as a crate. This is the main entry point for the parser.
@@ -2323,7 +2322,7 @@ fn parse_param_general(&mut self, req_name: ReqName, first_param: bool) -> PResu
                 match ty {
                     Ok(ty) => {
                         let ident = Ident::new(kw::Empty, this.prev_token.span);
-                        let bm = BindingMode::ByValue(Mutability::Not);
+                        let bm = BindingAnnotation::NONE;
                         let pat = this.mk_pat_ident(ty.span, bm, ident);
                         (pat, ty)
                     }
index 5e79308464f6408bb22b6278c22aaef8f80ca42b..5c8f374255c7fc91635b88391161d743150ecced 100644 (file)
@@ -37,7 +37,6 @@
 use rustc_session::parse::ParseSess;
 use rustc_span::source_map::{Span, DUMMY_SP};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use tracing::debug;
 
 use std::ops::Range;
 use std::{cmp, mem, slice};
index 8b3200d45fccd76b99b17ebebf0150cdf47eee89..88bd57d37cb657cd1548b66ea24157b6482784ac 100644 (file)
@@ -4,8 +4,8 @@
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter};
 use rustc_ast::{
-    self as ast, AttrVec, BindingMode, Expr, ExprKind, MacCall, Mutability, Pat, PatField, PatKind,
-    Path, QSelf, RangeEnd, RangeSyntax,
+    self as ast, AttrVec, BindingAnnotation, ByRef, Expr, ExprKind, MacCall, Mutability, Pat,
+    PatField, PatKind, Path, QSelf, RangeEnd, RangeSyntax,
 };
 use rustc_ast_pretty::pprust;
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult};
@@ -353,7 +353,7 @@ fn parse_pat_with_range_pat(
         } else if self.eat_keyword(kw::Ref) {
             // Parse ref ident @ pat / ref mut ident @ pat
             let mutbl = self.parse_mutability();
-            self.parse_pat_ident(BindingMode::ByRef(mutbl))?
+            self.parse_pat_ident(BindingAnnotation(ByRef::Yes, mutbl))?
         } else if self.eat_keyword(kw::Box) {
             self.parse_pat_box()?
         } else if self.check_inline_const(0) {
@@ -369,7 +369,7 @@ fn parse_pat_with_range_pat(
             // Parse `ident @ pat`
             // This can give false positives and parse nullary enums,
             // they are dealt with later in resolve.
-            self.parse_pat_ident(BindingMode::ByValue(Mutability::Not))?
+            self.parse_pat_ident(BindingAnnotation::NONE)?
         } else if self.is_start_of_pat_with_path() {
             // Parse pattern starting with a path
             let (qself, path) = if self.eat_lt() {
@@ -578,7 +578,8 @@ fn parse_pat_ident_mut(&mut self) -> PResult<'a, PatKind> {
         let mut pat = self.parse_pat_no_top_alt(Some("identifier"))?;
 
         // If we don't have `mut $ident (@ pat)?`, error.
-        if let PatKind::Ident(BindingMode::ByValue(m @ Mutability::Not), ..) = &mut pat.kind {
+        if let PatKind::Ident(BindingAnnotation(ByRef::No, m @ Mutability::Not), ..) = &mut pat.kind
+        {
             // Don't recurse into the subpattern.
             // `mut` on the outer binding doesn't affect the inner bindings.
             *m = Mutability::Mut;
@@ -604,7 +605,7 @@ fn recover_mut_ref_ident(&mut self, lo: Span) -> PResult<'a, PatKind> {
             )
             .emit();
 
-        self.parse_pat_ident(BindingMode::ByRef(Mutability::Mut))
+        self.parse_pat_ident(BindingAnnotation::REF_MUT)
     }
 
     /// Turn all by-value immutable bindings in a pattern into mutable bindings.
@@ -613,7 +614,8 @@ fn make_all_value_bindings_mutable(pat: &mut P<Pat>) -> bool {
         struct AddMut(bool);
         impl MutVisitor for AddMut {
             fn visit_pat(&mut self, pat: &mut P<Pat>) {
-                if let PatKind::Ident(BindingMode::ByValue(m @ Mutability::Not), ..) = &mut pat.kind
+                if let PatKind::Ident(BindingAnnotation(ByRef::No, m @ Mutability::Not), ..) =
+                    &mut pat.kind
                 {
                     self.0 = true;
                     *m = Mutability::Mut;
@@ -838,7 +840,7 @@ fn can_be_ident_pat(&mut self) -> bool {
     /// Parses `ident` or `ident @ pat`.
     /// Used by the copy foo and ref foo patterns to give a good
     /// error message when parsing mistakes like `ref foo(a, b)`.
-    fn parse_pat_ident(&mut self, binding_mode: BindingMode) -> PResult<'a, PatKind> {
+    fn parse_pat_ident(&mut self, binding_annotation: BindingAnnotation) -> PResult<'a, PatKind> {
         let ident = self.parse_ident()?;
         let sub = if self.eat(&token::At) {
             Some(self.parse_pat_no_top_alt(Some("binding pattern"))?)
@@ -856,7 +858,7 @@ fn parse_pat_ident(&mut self, binding_mode: BindingMode) -> PResult<'a, PatKind>
                 .struct_span_err(self.prev_token.span, "expected identifier, found enum pattern"));
         }
 
-        Ok(PatKind::Ident(binding_mode, ident, sub))
+        Ok(PatKind::Ident(binding_annotation, ident, sub))
     }
 
     /// Parse a struct ("record") pattern (e.g. `Foo { ... }` or `Foo::Bar { ... }`).
@@ -936,11 +938,7 @@ fn parse_pat_box(&mut self) -> PResult<'a, PatKind> {
                 None
             };
 
-            Ok(PatKind::Ident(
-                BindingMode::ByValue(Mutability::Not),
-                Ident::new(kw::Box, box_span),
-                sub,
-            ))
+            Ok(PatKind::Ident(BindingAnnotation::NONE, Ident::new(kw::Box, box_span), sub))
         } else {
             let pat = self.parse_pat_with_range_pat(false, None)?;
             self.sess.gated_spans.gate(sym::box_patterns, box_span.to(self.prev_token.span));
@@ -1117,14 +1115,12 @@ fn parse_pat_field(&mut self, lo: Span, attrs: AttrVec) -> PResult<'a, PatField>
             let fieldname = self.parse_field_name()?;
             hi = self.prev_token.span;
 
-            let bind_type = match (is_ref, is_mut) {
-                (true, true) => BindingMode::ByRef(Mutability::Mut),
-                (true, false) => BindingMode::ByRef(Mutability::Not),
-                (false, true) => BindingMode::ByValue(Mutability::Mut),
-                (false, false) => BindingMode::ByValue(Mutability::Not),
+            let mutability = match is_mut {
+                false => Mutability::Not,
+                true => Mutability::Mut,
             };
-
-            let fieldpat = self.mk_pat_ident(boxed_span.to(hi), bind_type, fieldname);
+            let ann = BindingAnnotation(ByRef::from(is_ref), mutability);
+            let fieldpat = self.mk_pat_ident(boxed_span.to(hi), ann, fieldname);
             let subpat =
                 if is_box { self.mk_pat(lo.to(hi), PatKind::Box(fieldpat)) } else { fieldpat };
             (subpat, fieldname, true)
@@ -1141,8 +1137,8 @@ fn parse_pat_field(&mut self, lo: Span, attrs: AttrVec) -> PResult<'a, PatField>
         })
     }
 
-    pub(super) fn mk_pat_ident(&self, span: Span, bm: BindingMode, ident: Ident) -> P<Pat> {
-        self.mk_pat(span, PatKind::Ident(bm, ident, None))
+    pub(super) fn mk_pat_ident(&self, span: Span, ann: BindingAnnotation, ident: Ident) -> P<Pat> {
+        self.mk_pat(span, PatKind::Ident(ann, ident, None))
     }
 
     pub(super) fn mk_pat(&self, span: Span, kind: PatKind) -> P<Pat> {
index fc7fb866f110f5dd91e85fa1f0a0d79ea8a47cef..fdc1af27f82e4206e3e7d95eec13f6ffb59a4a92 100644 (file)
@@ -13,7 +13,6 @@
 use rustc_span::symbol::{kw, sym, Ident};
 
 use std::mem;
-use tracing::debug;
 
 /// Specifies how to parse a path.
 #[derive(Copy, Clone, PartialEq)]
index f376da29bd919e63b0250fcda94bfd9e58d53078..a63af4159e8cbd075bae75ff2f6a6be653bc0663 100644 (file)
@@ -173,9 +173,7 @@ fn check_attributes(
                 sym::no_implicit_prelude => {
                     self.check_generic_attr(hir_id, attr, target, &[Target::Mod])
                 }
-                sym::rustc_object_lifetime_default => {
-                    self.check_object_lifetime_default(hir_id, span)
-                }
+                sym::rustc_object_lifetime_default => self.check_object_lifetime_default(hir_id),
                 _ => {}
             }
 
@@ -415,26 +413,21 @@ fn check_cmse_nonsecure_entry(&self, attr: &Attribute, span: Span, target: Targe
     }
 
     /// Debugging aid for `object_lifetime_default` query.
-    fn check_object_lifetime_default(&self, hir_id: HirId, span: Span) {
+    fn check_object_lifetime_default(&self, hir_id: HirId) {
         let tcx = self.tcx;
         if let Some(generics) = tcx.hir().get_generics(tcx.hir().local_def_id(hir_id)) {
-            let object_lifetime_default_reprs: String = generics
-                .params
-                .iter()
-                .filter_map(|p| {
-                    let param_id = tcx.hir().local_def_id(p.hir_id);
-                    let default = tcx.object_lifetime_default(param_id)?;
-                    Some(match default {
-                        ObjectLifetimeDefault::Empty => "BaseDefault".to_owned(),
-                        ObjectLifetimeDefault::Static => "'static".to_owned(),
-                        ObjectLifetimeDefault::Param(def_id) => tcx.item_name(def_id).to_string(),
-                        ObjectLifetimeDefault::Ambiguous => "Ambiguous".to_owned(),
-                    })
-                })
-                .collect::<Vec<String>>()
-                .join(",");
-
-            tcx.sess.span_err(span, &object_lifetime_default_reprs);
+            for p in generics.params {
+                let hir::GenericParamKind::Type { .. } = p.kind else { continue };
+                let param_id = tcx.hir().local_def_id(p.hir_id);
+                let default = tcx.object_lifetime_default(param_id);
+                let repr = match default {
+                    ObjectLifetimeDefault::Empty => "BaseDefault".to_owned(),
+                    ObjectLifetimeDefault::Static => "'static".to_owned(),
+                    ObjectLifetimeDefault::Param(def_id) => tcx.item_name(def_id).to_string(),
+                    ObjectLifetimeDefault::Ambiguous => "Ambiguous".to_owned(),
+                };
+                tcx.sess.span_err(p.span, &repr);
+            }
         }
     }
 
@@ -2145,6 +2138,7 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
         sym::automatically_derived,
         sym::start,
         sym::rustc_main,
+        sym::unix_sigpipe,
         sym::derive,
         sym::test,
         sym::test_case,
index 7381019a620160ff782f0eb05e9e5d2593b35ba1..cd10170d3ba58756994049556beddc12bd6d18f3 100644 (file)
@@ -1,11 +1,11 @@
-use rustc_ast::{entry::EntryPointType, Attribute};
+use rustc_ast::entry::EntryPointType;
 use rustc_errors::struct_span_err;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::{ItemId, Node, CRATE_HIR_ID};
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{DefIdTree, TyCtxt};
-use rustc_session::config::{CrateType, EntryFnType};
+use rustc_session::config::{sigpipe, CrateType, EntryFnType};
 use rustc_session::parse::feature_err;
 use rustc_span::symbol::sym;
 use rustc_span::{Span, Symbol, DUMMY_SP};
@@ -71,14 +71,12 @@ fn entry_point_type(ctxt: &EntryContext<'_>, id: ItemId, at_root: bool) -> Entry
     }
 }
 
-fn err_if_attr_found(ctxt: &EntryContext<'_>, attrs: &[Attribute], sym: Symbol) {
+fn err_if_attr_found(ctxt: &EntryContext<'_>, id: ItemId, sym: Symbol, details: &str) {
+    let attrs = ctxt.tcx.hir().attrs(id.hir_id());
     if let Some(attr) = ctxt.tcx.sess.find_by_name(attrs, sym) {
         ctxt.tcx
             .sess
-            .struct_span_err(
-                attr.span,
-                &format!("`{}` attribute can only be used on functions", sym),
-            )
+            .struct_span_err(attr.span, &format!("`{}` attribute {}", sym, details))
             .emit();
     }
 }
@@ -87,14 +85,16 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
     let at_root = ctxt.tcx.opt_local_parent(id.def_id) == Some(CRATE_DEF_ID);
 
     match entry_point_type(ctxt, id, at_root) {
-        EntryPointType::None => (),
+        EntryPointType::None => {
+            err_if_attr_found(ctxt, id, sym::unix_sigpipe, "can only be used on `fn main()`");
+        }
         _ if !matches!(ctxt.tcx.def_kind(id.def_id), DefKind::Fn) => {
-            let attrs = ctxt.tcx.hir().attrs(id.hir_id());
-            err_if_attr_found(ctxt, attrs, sym::start);
-            err_if_attr_found(ctxt, attrs, sym::rustc_main);
+            err_if_attr_found(ctxt, id, sym::start, "can only be used on functions");
+            err_if_attr_found(ctxt, id, sym::rustc_main, "can only be used on functions");
         }
         EntryPointType::MainNamed => (),
         EntryPointType::OtherMain => {
+            err_if_attr_found(ctxt, id, sym::unix_sigpipe, "can only be used on root `fn main()`");
             ctxt.non_main_fns.push(ctxt.tcx.def_span(id.def_id));
         }
         EntryPointType::RustcMainAttr => {
@@ -116,6 +116,7 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
             }
         }
         EntryPointType::Start => {
+            err_if_attr_found(ctxt, id, sym::unix_sigpipe, "can only be used on `fn main()`");
             if ctxt.start_fn.is_none() {
                 ctxt.start_fn = Some((id.def_id, ctxt.tcx.def_span(id.def_id.to_def_id())));
             } else {
@@ -136,8 +137,9 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
 fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId, EntryFnType)> {
     if let Some((def_id, _)) = visitor.start_fn {
         Some((def_id.to_def_id(), EntryFnType::Start))
-    } else if let Some((def_id, _)) = visitor.attr_main_fn {
-        Some((def_id.to_def_id(), EntryFnType::Main))
+    } else if let Some((local_def_id, _)) = visitor.attr_main_fn {
+        let def_id = local_def_id.to_def_id();
+        Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx, def_id) }))
     } else {
         if let Some(main_def) = tcx.resolutions(()).main_def && let Some(def_id) = main_def.opt_fn_def_id() {
             // non-local main imports are handled below
@@ -161,13 +163,39 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId,
                 )
                 .emit();
             }
-            return Some((def_id, EntryFnType::Main));
+            return Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx, def_id) }));
         }
         no_main_err(tcx, visitor);
         None
     }
 }
 
+fn sigpipe(tcx: TyCtxt<'_>, def_id: DefId) -> u8 {
+    if let Some(attr) = tcx.get_attr(def_id, sym::unix_sigpipe) {
+        match (attr.value_str(), attr.meta_item_list()) {
+            (Some(sym::inherit), None) => sigpipe::INHERIT,
+            (Some(sym::sig_ign), None) => sigpipe::SIG_IGN,
+            (Some(sym::sig_dfl), None) => sigpipe::SIG_DFL,
+            (_, Some(_)) => {
+                // Keep going so that `fn emit_malformed_attribute()` can print
+                // an excellent error message
+                sigpipe::DEFAULT
+            }
+            _ => {
+                tcx.sess
+                    .struct_span_err(
+                        attr.span,
+                        "valid values for `#[unix_sigpipe = \"...\"]` are `inherit`, `sig_ign`, or `sig_dfl`",
+                    )
+                    .emit();
+                sigpipe::DEFAULT
+            }
+        }
+    } else {
+        sigpipe::DEFAULT
+    }
+}
+
 fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) {
     let sp = tcx.def_span(CRATE_DEF_ID);
     if *tcx.sess.parse_sess.reached_eof.borrow() {
index fb1d724d9d83b5a30a39cff45d5de51b6758af66..81ac0e1b6d445a5455a69a9e9782ff788a62728b 100644 (file)
@@ -74,16 +74,16 @@ pub fn print_hir_stats(tcx: TyCtxt<'_>) {
     };
     tcx.hir().walk_toplevel_module(&mut collector);
     tcx.hir().walk_attributes(&mut collector);
-    collector.print("HIR STATS");
+    collector.print("HIR STATS", "hir-stats");
 }
 
-pub fn print_ast_stats(krate: &ast::Crate, title: &str) {
+pub fn print_ast_stats(krate: &ast::Crate, title: &str, prefix: &str) {
     use rustc_ast::visit::Visitor;
 
     let mut collector =
         StatCollector { krate: None, nodes: FxHashMap::default(), seen: FxHashSet::default() };
     collector.visit_crate(krate);
-    collector.print(title);
+    collector.print(title, prefix);
 }
 
 impl<'k> StatCollector<'k> {
@@ -119,23 +119,26 @@ fn record_inner<T>(
         }
     }
 
-    fn print(&self, title: &str) {
+    fn print(&self, title: &str, prefix: &str) {
         let mut nodes: Vec<_> = self.nodes.iter().collect();
         nodes.sort_by_key(|&(_, ref node)| node.stats.count * node.stats.size);
 
         let total_size = nodes.iter().map(|(_, node)| node.stats.count * node.stats.size).sum();
 
-        eprintln!("\n{}\n", title);
-
-        eprintln!("{:<18}{:>18}{:>14}{:>14}", "Name", "Accumulated Size", "Count", "Item Size");
-        eprintln!("----------------------------------------------------------------");
+        eprintln!("{} {}", prefix, title);
+        eprintln!(
+            "{} {:<18}{:>18}{:>14}{:>14}",
+            prefix, "Name", "Accumulated Size", "Count", "Item Size"
+        );
+        eprintln!("{} ----------------------------------------------------------------", prefix);
 
         let percent = |m, n| (m * 100) as f64 / n as f64;
 
         for (label, node) in nodes {
             let size = node.stats.count * node.stats.size;
             eprintln!(
-                "{:<18}{:>10} ({:4.1}%){:>14}{:>14}",
+                "{} {:<18}{:>10} ({:4.1}%){:>14}{:>14}",
+                prefix,
                 label,
                 to_readable_str(size),
                 percent(size, total_size),
@@ -149,7 +152,8 @@ fn print(&self, title: &str) {
                 for (label, subnode) in subnodes {
                     let size = subnode.count * subnode.size;
                     eprintln!(
-                        "- {:<18}{:>10} ({:4.1}%){:>14}",
+                        "{} - {:<18}{:>10} ({:4.1}%){:>14}",
+                        prefix,
                         label,
                         to_readable_str(size),
                         percent(size, total_size),
@@ -158,11 +162,28 @@ fn print(&self, title: &str) {
                 }
             }
         }
-        eprintln!("----------------------------------------------------------------");
-        eprintln!("{:<18}{:>10}\n", "Total", to_readable_str(total_size));
+        eprintln!("{} ----------------------------------------------------------------", prefix);
+        eprintln!("{} {:<18}{:>10}", prefix, "Total", to_readable_str(total_size));
+        eprintln!("{}", prefix);
     }
 }
 
+// Used to avoid boilerplate for types with many variants.
+macro_rules! record_variants {
+    (
+        ($self:ident, $val:expr, $kind:expr, $id:expr, $mod:ident, $ty:ty, $tykind:ident),
+        [$($variant:ident),*]
+    ) => {
+        match $kind {
+            $(
+                $mod::$tykind::$variant { .. } => {
+                    $self.record_variant(stringify!($ty), stringify!($variant), $id, $val)
+                }
+            )*
+        }
+    };
+}
+
 impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
     fn visit_param(&mut self, param: &'v hir::Param<'v>) {
         self.record("Param", Id::Node(param.hir_id), param);
@@ -195,12 +216,46 @@ fn visit_nested_body(&mut self, body_id: hir::BodyId) {
     }
 
     fn visit_item(&mut self, i: &'v hir::Item<'v>) {
-        self.record("Item", Id::Node(i.hir_id()), i);
+        record_variants!(
+            (self, i, i.kind, Id::Node(i.hir_id()), hir, Item, ItemKind),
+            [
+                ExternCrate,
+                Use,
+                Static,
+                Const,
+                Fn,
+                Macro,
+                Mod,
+                ForeignMod,
+                GlobalAsm,
+                TyAlias,
+                OpaqueTy,
+                Enum,
+                Struct,
+                Union,
+                Trait,
+                TraitAlias,
+                Impl
+            ]
+        );
         hir_visit::walk_item(self, i)
     }
 
+    fn visit_body(&mut self, b: &'v hir::Body<'v>) {
+        self.record("Body", Id::None, b);
+        hir_visit::walk_body(self, b);
+    }
+
+    fn visit_mod(&mut self, m: &'v hir::Mod<'v>, _s: Span, n: HirId) {
+        self.record("Mod", Id::None, m);
+        hir_visit::walk_mod(self, m, n)
+    }
+
     fn visit_foreign_item(&mut self, i: &'v hir::ForeignItem<'v>) {
-        self.record("ForeignItem", Id::Node(i.hir_id()), i);
+        record_variants!(
+            (self, i, i.kind, Id::Node(i.hir_id()), hir, ForeignItem, ForeignItemKind),
+            [Fn, Static, Type]
+        );
         hir_visit::walk_foreign_item(self, i)
     }
 
@@ -215,7 +270,10 @@ fn visit_block(&mut self, b: &'v hir::Block<'v>) {
     }
 
     fn visit_stmt(&mut self, s: &'v hir::Stmt<'v>) {
-        self.record("Stmt", Id::Node(s.hir_id), s);
+        record_variants!(
+            (self, s, s.kind, Id::Node(s.hir_id), hir, Stmt, StmtKind),
+            [Local, Item, Expr, Semi]
+        );
         hir_visit::walk_stmt(self, s)
     }
 
@@ -225,20 +283,80 @@ fn visit_arm(&mut self, a: &'v hir::Arm<'v>) {
     }
 
     fn visit_pat(&mut self, p: &'v hir::Pat<'v>) {
-        self.record("Pat", Id::Node(p.hir_id), p);
+        record_variants!(
+            (self, p, p.kind, Id::Node(p.hir_id), hir, Pat, PatKind),
+            [Wild, Binding, Struct, TupleStruct, Or, Path, Tuple, Box, Ref, Lit, Range, Slice]
+        );
         hir_visit::walk_pat(self, p)
     }
 
-    fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
-        self.record("Expr", Id::Node(ex.hir_id), ex);
-        hir_visit::walk_expr(self, ex)
+    fn visit_pat_field(&mut self, f: &'v hir::PatField<'v>) {
+        self.record("PatField", Id::Node(f.hir_id), f);
+        hir_visit::walk_pat_field(self, f)
+    }
+
+    fn visit_expr(&mut self, e: &'v hir::Expr<'v>) {
+        record_variants!(
+            (self, e, e.kind, Id::Node(e.hir_id), hir, Expr, ExprKind),
+            [
+                Box, ConstBlock, Array, Call, MethodCall, Tup, Binary, Unary, Lit, Cast, Type,
+                DropTemps, Let, If, Loop, Match, Closure, Block, Assign, AssignOp, Field, Index,
+                Path, AddrOf, Break, Continue, Ret, InlineAsm, Struct, Repeat, Yield, Err
+            ]
+        );
+        hir_visit::walk_expr(self, e)
+    }
+
+    fn visit_let_expr(&mut self, lex: &'v hir::Let<'v>) {
+        self.record("Let", Id::Node(lex.hir_id), lex);
+        hir_visit::walk_let_expr(self, lex)
+    }
+
+    fn visit_expr_field(&mut self, f: &'v hir::ExprField<'v>) {
+        self.record("ExprField", Id::Node(f.hir_id), f);
+        hir_visit::walk_expr_field(self, f)
     }
 
     fn visit_ty(&mut self, t: &'v hir::Ty<'v>) {
-        self.record("Ty", Id::Node(t.hir_id), t);
+        record_variants!(
+            (self, t, t.kind, Id::Node(t.hir_id), hir, Ty, TyKind),
+            [
+                Slice,
+                Array,
+                Ptr,
+                Rptr,
+                BareFn,
+                Never,
+                Tup,
+                Path,
+                OpaqueDef,
+                TraitObject,
+                Typeof,
+                Infer,
+                Err
+            ]
+        );
         hir_visit::walk_ty(self, t)
     }
 
+    fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) {
+        self.record("GenericParam", Id::Node(p.hir_id), p);
+        hir_visit::walk_generic_param(self, p)
+    }
+
+    fn visit_generics(&mut self, g: &'v hir::Generics<'v>) {
+        self.record("Generics", Id::None, g);
+        hir_visit::walk_generics(self, g)
+    }
+
+    fn visit_where_predicate(&mut self, p: &'v hir::WherePredicate<'v>) {
+        record_variants!(
+            (self, p, p, Id::None, hir, WherePredicate, WherePredicate),
+            [BoundPredicate, RegionPredicate, EqPredicate]
+        );
+        hir_visit::walk_where_predicate(self, p)
+    }
+
     fn visit_fn(
         &mut self,
         fk: hir_visit::FnKind<'v>,
@@ -251,24 +369,49 @@ fn visit_fn(
         hir_visit::walk_fn(self, fk, fd, b, s, id)
     }
 
-    fn visit_where_predicate(&mut self, predicate: &'v hir::WherePredicate<'v>) {
-        self.record("WherePredicate", Id::None, predicate);
-        hir_visit::walk_where_predicate(self, predicate)
+    fn visit_use(&mut self, p: &'v hir::Path<'v>, hir_id: hir::HirId) {
+        // This is `visit_use`, but the type is `Path` so record it that way.
+        self.record("Path", Id::None, p);
+        hir_visit::walk_use(self, p, hir_id)
     }
 
     fn visit_trait_item(&mut self, ti: &'v hir::TraitItem<'v>) {
-        self.record("TraitItem", Id::Node(ti.hir_id()), ti);
+        record_variants!(
+            (self, ti, ti.kind, Id::Node(ti.hir_id()), hir, TraitItem, TraitItemKind),
+            [Const, Fn, Type]
+        );
         hir_visit::walk_trait_item(self, ti)
     }
 
+    fn visit_trait_item_ref(&mut self, ti: &'v hir::TraitItemRef) {
+        self.record("TraitItemRef", Id::Node(ti.id.hir_id()), ti);
+        hir_visit::walk_trait_item_ref(self, ti)
+    }
+
     fn visit_impl_item(&mut self, ii: &'v hir::ImplItem<'v>) {
-        self.record("ImplItem", Id::Node(ii.hir_id()), ii);
+        record_variants!(
+            (self, ii, ii.kind, Id::Node(ii.hir_id()), hir, ImplItem, ImplItemKind),
+            [Const, Fn, TyAlias]
+        );
         hir_visit::walk_impl_item(self, ii)
     }
 
-    fn visit_param_bound(&mut self, bounds: &'v hir::GenericBound<'v>) {
-        self.record("GenericBound", Id::None, bounds);
-        hir_visit::walk_param_bound(self, bounds)
+    fn visit_foreign_item_ref(&mut self, fi: &'v hir::ForeignItemRef) {
+        self.record("ForeignItemRef", Id::Node(fi.id.hir_id()), fi);
+        hir_visit::walk_foreign_item_ref(self, fi)
+    }
+
+    fn visit_impl_item_ref(&mut self, ii: &'v hir::ImplItemRef) {
+        self.record("ImplItemRef", Id::Node(ii.id.hir_id()), ii);
+        hir_visit::walk_impl_item_ref(self, ii)
+    }
+
+    fn visit_param_bound(&mut self, b: &'v hir::GenericBound<'v>) {
+        record_variants!(
+            (self, b, b, Id::None, hir, GenericBound, GenericBound),
+            [Trait, LangItemTrait, Outlives]
+        );
+        hir_visit::walk_param_bound(self, b)
     }
 
     fn visit_field_def(&mut self, s: &'v hir::FieldDef<'v>) {
@@ -281,14 +424,17 @@ fn visit_variant(&mut self, v: &'v hir::Variant<'v>) {
         hir_visit::walk_variant(self, v)
     }
 
-    fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
-        self.record("Lifetime", Id::Node(lifetime.hir_id), lifetime);
-        hir_visit::walk_lifetime(self, lifetime)
-    }
-
-    fn visit_qpath(&mut self, qpath: &'v hir::QPath<'v>, id: hir::HirId, span: Span) {
-        self.record("QPath", Id::None, qpath);
-        hir_visit::walk_qpath(self, qpath, id, span)
+    fn visit_generic_arg(&mut self, ga: &'v hir::GenericArg<'v>) {
+        record_variants!(
+            (self, ga, ga, Id::Node(ga.hir_id()), hir, GenericArg, GenericArg),
+            [Lifetime, Type, Const, Infer]
+        );
+        match ga {
+            hir::GenericArg::Lifetime(lt) => self.visit_lifetime(lt),
+            hir::GenericArg::Type(ty) => self.visit_ty(ty),
+            hir::GenericArg::Const(ct) => self.visit_anon_const(&ct.value),
+            hir::GenericArg::Infer(inf) => self.visit_infer(inf),
+        }
     }
 
     fn visit_path(&mut self, path: &'v hir::Path<'v>, _id: hir::HirId) {
@@ -296,15 +442,16 @@ fn visit_path(&mut self, path: &'v hir::Path<'v>, _id: hir::HirId) {
         hir_visit::walk_path(self, path)
     }
 
-    // `PathSegment` has one inline use (in `ast::ExprKind::MethodCall`) and
-    // one non-inline use (in `Path::segments`). The latter case is more common
-    // than the former case, so we implement this visitor and tolerate the
-    // double counting in the former case.
     fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v hir::PathSegment<'v>) {
         self.record("PathSegment", Id::None, path_segment);
         hir_visit::walk_path_segment(self, path_span, path_segment)
     }
 
+    fn visit_generic_args(&mut self, sp: Span, ga: &'v hir::GenericArgs<'v>) {
+        self.record("GenericArgs", Id::None, ga);
+        hir_visit::walk_generic_args(self, sp, ga)
+    }
+
     fn visit_assoc_type_binding(&mut self, type_binding: &'v hir::TypeBinding<'v>) {
         self.record("TypeBinding", Id::Node(type_binding.hir_id), type_binding);
         hir_visit::walk_assoc_type_binding(self, type_binding)
@@ -313,28 +460,17 @@ fn visit_assoc_type_binding(&mut self, type_binding: &'v hir::TypeBinding<'v>) {
     fn visit_attribute(&mut self, attr: &'v ast::Attribute) {
         self.record("Attribute", Id::Attr(attr.id), attr);
     }
-}
 
-// Used to avoid boilerplate for types with many variants.
-macro_rules! record_variants {
-    (
-        ($self:ident, $val:expr, $kind:expr, $ty:ty, $tykind:ident), // mandatory pieces
-        [$($variant:ident),*]
-    ) => {
-        match $kind {
-            $(
-                ast::$tykind::$variant { .. } => {
-                    $self.record_variant(stringify!($ty), stringify!($variant), Id::None, $val)
-                }
-            )*
-        }
-    };
+    fn visit_inline_asm(&mut self, asm: &'v hir::InlineAsm<'v>, id: HirId) {
+        self.record("InlineAsm", Id::None, asm);
+        hir_visit::walk_inline_asm(self, asm, id);
+    }
 }
 
 impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
     fn visit_foreign_item(&mut self, i: &'v ast::ForeignItem) {
         record_variants!(
-            (self, i, i.kind, ForeignItem, ForeignItemKind),
+            (self, i, i.kind, Id::None, ast, ForeignItem, ForeignItemKind),
             [Static, Fn, TyAlias, MacCall]
         );
         ast_visit::walk_foreign_item(self, i)
@@ -342,7 +478,7 @@ fn visit_foreign_item(&mut self, i: &'v ast::ForeignItem) {
 
     fn visit_item(&mut self, i: &'v ast::Item) {
         record_variants!(
-            (self, i, i.kind, Item, ItemKind),
+            (self, i, i.kind, Id::None, ast, Item, ItemKind),
             [
                 ExternCrate,
                 Use,
@@ -378,7 +514,7 @@ fn visit_block(&mut self, b: &'v ast::Block) {
 
     fn visit_stmt(&mut self, s: &'v ast::Stmt) {
         record_variants!(
-            (self, s, s.kind, Stmt, StmtKind),
+            (self, s, s.kind, Id::None, ast, Stmt, StmtKind),
             [Local, Item, Expr, Semi, Empty, MacCall]
         );
         ast_visit::walk_stmt(self, s)
@@ -396,7 +532,7 @@ fn visit_arm(&mut self, a: &'v ast::Arm) {
 
     fn visit_pat(&mut self, p: &'v ast::Pat) {
         record_variants!(
-            (self, p, p.kind, Pat, PatKind),
+            (self, p, p.kind, Id::None, ast, Pat, PatKind),
             [
                 Wild,
                 Ident,
@@ -420,7 +556,7 @@ fn visit_pat(&mut self, p: &'v ast::Pat) {
 
     fn visit_expr(&mut self, e: &'v ast::Expr) {
         record_variants!(
-            (self, e, e.kind, Expr, ExprKind),
+            (self, e, e.kind, Id::None, ast, Expr, ExprKind),
             [
                 Box, Array, ConstBlock, Call, MethodCall, Tup, Binary, Unary, Lit, Cast, Type, Let,
                 If, While, ForLoop, Loop, Match, Closure, Block, Async, Await, TryBlock, Assign,
@@ -433,7 +569,7 @@ fn visit_expr(&mut self, e: &'v ast::Expr) {
 
     fn visit_ty(&mut self, t: &'v ast::Ty) {
         record_variants!(
-            (self, t, t.kind, Ty, TyKind),
+            (self, t, t.kind, Id::None, ast, Ty, TyKind),
             [
                 Slice,
                 Array,
@@ -465,7 +601,7 @@ fn visit_generic_param(&mut self, g: &'v ast::GenericParam) {
 
     fn visit_where_predicate(&mut self, p: &'v ast::WherePredicate) {
         record_variants!(
-            (self, p, p, WherePredicate, WherePredicate),
+            (self, p, p, Id::None, ast, WherePredicate, WherePredicate),
             [BoundPredicate, RegionPredicate, EqPredicate]
         );
         ast_visit::walk_where_predicate(self, p)
@@ -478,14 +614,17 @@ fn visit_fn(&mut self, fk: ast_visit::FnKind<'v>, s: Span, _: NodeId) {
 
     fn visit_assoc_item(&mut self, i: &'v ast::AssocItem, ctxt: ast_visit::AssocCtxt) {
         record_variants!(
-            (self, i, i.kind, AssocItem, AssocItemKind),
+            (self, i, i.kind, Id::None, ast, AssocItem, AssocItemKind),
             [Const, Fn, TyAlias, MacCall]
         );
         ast_visit::walk_assoc_item(self, i, ctxt);
     }
 
     fn visit_param_bound(&mut self, b: &'v ast::GenericBound, _ctxt: BoundKind) {
-        record_variants!((self, b, b, GenericBound, GenericBound), [Trait, Outlives]);
+        record_variants!(
+            (self, b, b, Id::None, ast, GenericBound, GenericBound),
+            [Trait, Outlives]
+        );
         ast_visit::walk_param_bound(self, b)
     }
 
@@ -504,6 +643,10 @@ fn visit_variant(&mut self, v: &'v ast::Variant) {
     // common, so we don't implement `visit_use_tree` and tolerate the missed
     // coverage in the latter case.
 
+    // `PathSegment` has one inline use (in `ast::ExprKind::MethodCall`) and
+    // one non-inline use (in `ast::Path::segments`). The latter case is more
+    // common than the former case, so we implement this visitor and tolerate
+    // the double counting in the former case.
     fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v ast::PathSegment) {
         self.record("PathSegment", Id::None, path_segment);
         ast_visit::walk_path_segment(self, path_span, path_segment)
@@ -514,12 +657,18 @@ fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v ast::PathSeg
     // common, so we implement `visit_generic_args` and tolerate the double
     // counting in the former case.
     fn visit_generic_args(&mut self, sp: Span, g: &'v ast::GenericArgs) {
-        record_variants!((self, g, g, GenericArgs, GenericArgs), [AngleBracketed, Parenthesized]);
+        record_variants!(
+            (self, g, g, Id::None, ast, GenericArgs, GenericArgs),
+            [AngleBracketed, Parenthesized]
+        );
         ast_visit::walk_generic_args(self, sp, g)
     }
 
     fn visit_attribute(&mut self, attr: &'v ast::Attribute) {
-        record_variants!((self, attr, attr.kind, Attribute, AttrKind), [Normal, DocComment]);
+        record_variants!(
+            (self, attr, attr.kind, Id::None, ast, Attribute, AttrKind),
+            [Normal, DocComment]
+        );
         ast_visit::walk_attribute(self, attr)
     }
 
index 70b6bfd1e582d1422eb92148c145fe4725bb4016..5aac6943eef1eb2af321c9c34f995b095bb6fc16 100644 (file)
@@ -5,6 +5,7 @@
 //! collect them instead.
 
 use rustc_ast::{Attribute, MetaItemKind};
+use rustc_attr::VERSION_PLACEHOLDER;
 use rustc_errors::struct_span_err;
 use rustc_hir::intravisit::Visitor;
 use rustc_middle::hir::nested_filter;
@@ -54,7 +55,6 @@ fn extract(&self, attr: &Attribute) -> Option<(Symbol, Option<Symbol>, Span)> {
                         }
                     }
                 }
-                const VERSION_PLACEHOLDER: &str = "CURRENT_RUSTC_VERSION";
 
                 if let Some(s) = since && s.as_str() == VERSION_PLACEHOLDER {
                     let version = option_env!("CFG_VERSION").unwrap_or("<current>");
index 5b79dd3d3ef25d3a14e0760bcb2587773e14dacd..6a4cd79cde7128080ac4ce97922e65562aff3783 100644 (file)
@@ -1039,9 +1039,10 @@ fn propagate_through_expr(&mut self, expr: &Expr<'_>, succ: LiveNode) -> LiveNod
                 self.propagate_through_expr(&f, succ)
             }
 
-            hir::ExprKind::MethodCall(.., ref args, _) => {
+            hir::ExprKind::MethodCall(.., receiver, ref args, _) => {
                 let succ = self.check_is_ty_uninhabited(expr, succ);
-                self.propagate_through_exprs(args, succ)
+                let succ = self.propagate_through_exprs(args, succ);
+                self.propagate_through_expr(receiver, succ)
             }
 
             hir::ExprKind::Tup(ref exprs) => self.propagate_through_exprs(exprs, succ),
@@ -1573,7 +1574,7 @@ fn check_unused_vars_in_pat(
         }
     }
 
-    #[tracing::instrument(skip(self), level = "INFO")]
+    #[instrument(skip(self), level = "INFO")]
     fn report_unused(
         &self,
         hir_ids_and_spans: Vec<(HirId, Span, Span)>,
index 296b6ed5d99a69b5e5153a134d578d9218f12a47..607973446fc1e32c3818f682c746013b5e0e250a 100644 (file)
@@ -76,7 +76,7 @@ fn check_no_patterns(tcx: TyCtxt<'_>, params: &[hir::Param<'_>]) {
     for param in params {
         match param.pat.kind {
             hir::PatKind::Wild
-            | hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, _, None) => {}
+            | hir::PatKind::Binding(hir::BindingAnnotation::NONE, _, _, None) => {}
             _ => {
                 tcx.sess
                     .struct_span_err(
index f884e04a9511254977a3a96cf40142e8129f98ed..a24b191aebfc17db2de53d27992b0ce5fc2e82c5 100644 (file)
@@ -832,7 +832,7 @@ fn visit_path(&mut self, path: &'tcx hir::Path<'tcx>, id: hir::HirId) {
                 // added, such as `core::intrinsics::transmute`
                 let parents = path.segments.iter().rev().skip(1);
                 for path_segment in parents {
-                    if let Some(def_id) = path_segment.res.as_ref().and_then(Res::opt_def_id) {
+                    if let Some(def_id) = path_segment.res.opt_def_id() {
                         // use `None` for id to prevent deprecation check
                         self.tcx.check_stability_allow_unstable(
                             def_id,
index 1e423ddb7102cb753ae0bf8aefcc1d54664afc11..63f83f8965ec52c8a56e15123549eea3369dfef0 100644 (file)
@@ -75,6 +75,14 @@ pub struct InPublicInterface<'a> {
     pub vis_span: Span,
 }
 
+#[derive(SessionDiagnostic)]
+#[diag(privacy::report_access_level)]
+pub struct ReportAccessLevel {
+    #[primary_span]
+    pub span: Span,
+    pub descr: String,
+}
+
 #[derive(LintDiagnostic)]
 #[diag(privacy::from_private_dep_in_public_interface)]
 pub struct FromPrivateDependencyInPublicInterface<'a> {
index 5d562f18a815814785602fff35961933b7b32d0a..ba69bc23118b2527921188cdf8f7a595a97bef8b 100644 (file)
@@ -8,6 +8,9 @@
 #![deny(rustc::untranslatable_diagnostic)]
 #![deny(rustc::diagnostic_outside_of_impl)]
 
+#[macro_use]
+extern crate tracing;
+
 mod errors;
 
 use rustc_ast::MacroDef;
@@ -30,7 +33,7 @@
 use rustc_middle::ty::{TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
 use rustc_session::lint;
 use rustc_span::hygiene::Transparency;
-use rustc_span::symbol::{kw, Ident};
+use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::Span;
 
 use std::marker::PhantomData;
@@ -39,7 +42,8 @@
 
 use errors::{
     FieldIsPrivate, FieldIsPrivateLabel, FromPrivateDependencyInPublicInterface, InPublicInterface,
-    InPublicInterfaceTraits, ItemIsPrivate, PrivateInPublicLint, UnnamedItemIsPrivate,
+    InPublicInterfaceTraits, ItemIsPrivate, PrivateInPublicLint, ReportAccessLevel,
+    UnnamedItemIsPrivate,
 };
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -904,6 +908,60 @@ fn visit_def_id(
     }
 }
 
+////////////////////////////////////////////////////////////////////////////////
+/// Visitor, used for AccessLevels table checking
+////////////////////////////////////////////////////////////////////////////////
+pub struct TestReachabilityVisitor<'tcx, 'a> {
+    tcx: TyCtxt<'tcx>,
+    access_levels: &'a AccessLevels,
+}
+
+impl<'tcx, 'a> TestReachabilityVisitor<'tcx, 'a> {
+    fn access_level_diagnostic(&mut self, def_id: LocalDefId) {
+        if self.tcx.has_attr(def_id.to_def_id(), sym::rustc_access_level) {
+            let access_level = format!("{:?}", self.access_levels.map.get(&def_id));
+            let span = self.tcx.def_span(def_id.to_def_id());
+            self.tcx.sess.emit_err(ReportAccessLevel { span, descr: access_level });
+        }
+    }
+}
+
+impl<'tcx, 'a> Visitor<'tcx> for TestReachabilityVisitor<'tcx, 'a> {
+    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
+        self.access_level_diagnostic(item.def_id);
+
+        match item.kind {
+            hir::ItemKind::Enum(ref def, _) => {
+                for variant in def.variants.iter() {
+                    let variant_id = self.tcx.hir().local_def_id(variant.id);
+                    self.access_level_diagnostic(variant_id);
+                    for field in variant.data.fields() {
+                        let def_id = self.tcx.hir().local_def_id(field.hir_id);
+                        self.access_level_diagnostic(def_id);
+                    }
+                }
+            }
+            hir::ItemKind::Struct(ref def, _) | hir::ItemKind::Union(ref def, _) => {
+                for field in def.fields() {
+                    let def_id = self.tcx.hir().local_def_id(field.hir_id);
+                    self.access_level_diagnostic(def_id);
+                }
+            }
+            _ => {}
+        }
+    }
+
+    fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem<'tcx>) {
+        self.access_level_diagnostic(item.def_id);
+    }
+    fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem<'tcx>) {
+        self.access_level_diagnostic(item.def_id);
+    }
+    fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
+        self.access_level_diagnostic(item.def_id);
+    }
+}
+
 //////////////////////////////////////////////////////////////////////////////////////
 /// Name privacy visitor, checks privacy and reports violations.
 /// Most of name privacy checks are performed during the main resolution phase,
@@ -1784,7 +1842,7 @@ fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display)
     fn leaks_private_dep(&self, item_id: DefId) -> bool {
         let ret = self.required_visibility.is_public() && self.tcx.is_private_dep(item_id.krate);
 
-        tracing::debug!("leaks_private_dep(item_id={:?})={}", item_id, ret);
+        debug!("leaks_private_dep(item_id={:?})={}", item_id, ret);
         ret
     }
 }
@@ -2042,6 +2100,9 @@ fn privacy_access_levels(tcx: TyCtxt<'_>, (): ()) -> &AccessLevels {
         }
     }
 
+    let mut check_visitor = TestReachabilityVisitor { tcx, access_levels: &visitor.access_levels };
+    tcx.hir().visit_all_item_likes_in_crate(&mut check_visitor);
+
     tcx.arena.alloc(visitor.access_levels)
 }
 
index f38f29e14afd4c4fba99299f62117620e6805906..274df5b5e5e9415679ffd389b9ab3ee5626c9e18 100644 (file)
@@ -7,13 +7,16 @@
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::Lock;
 use rustc_errors::{Diagnostic, Handler};
-use rustc_middle::dep_graph::{self, DepKind, DepNodeIndex, SerializedDepNodeIndex};
+use rustc_middle::dep_graph::{
+    self, DepKind, DepKindStruct, DepNode, DepNodeIndex, SerializedDepNodeIndex,
+};
 use rustc_middle::ty::tls::{self, ImplicitCtxt};
 use rustc_middle::ty::{self, TyCtxt};
-use rustc_query_system::dep_graph::HasDepContext;
+use rustc_query_system::dep_graph::{DepNodeParams, HasDepContext};
 use rustc_query_system::ich::StableHashingContext;
 use rustc_query_system::query::{
-    QueryContext, QueryJobId, QueryMap, QuerySideEffects, QueryStackFrame,
+    force_query, QueryConfig, QueryContext, QueryDescription, QueryJobId, QueryMap,
+    QuerySideEffects, QueryStackFrame,
 };
 use std::any::Any;
 use std::num::NonZeroU64;
@@ -298,6 +301,66 @@ pub(crate) fn create_query_frame<
     QueryStackFrame::new(name, description, span, def_kind, hash)
 }
 
+fn try_load_from_on_disk_cache<'tcx, Q>(tcx: TyCtxt<'tcx>, dep_node: DepNode)
+where
+    Q: QueryDescription<QueryCtxt<'tcx>>,
+    Q::Key: DepNodeParams<TyCtxt<'tcx>>,
+{
+    debug_assert!(tcx.dep_graph.is_green(&dep_node));
+
+    let key = Q::Key::recover(tcx, &dep_node).unwrap_or_else(|| {
+        panic!("Failed to recover key for {:?} with hash {}", dep_node, dep_node.hash)
+    });
+    if Q::cache_on_disk(tcx, &key) {
+        let _ = Q::execute_query(tcx, key);
+    }
+}
+
+fn force_from_dep_node<'tcx, Q>(tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool
+where
+    Q: QueryDescription<QueryCtxt<'tcx>>,
+    Q::Key: DepNodeParams<TyCtxt<'tcx>>,
+{
+    if let Some(key) = Q::Key::recover(tcx, &dep_node) {
+        #[cfg(debug_assertions)]
+        let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered();
+        let tcx = QueryCtxt::from_tcx(tcx);
+        force_query::<Q, _>(tcx, key, dep_node);
+        true
+    } else {
+        false
+    }
+}
+
+pub(crate) fn query_callback<'tcx, Q: QueryConfig>(
+    is_anon: bool,
+    is_eval_always: bool,
+) -> DepKindStruct<'tcx>
+where
+    Q: QueryDescription<QueryCtxt<'tcx>>,
+    Q::Key: DepNodeParams<TyCtxt<'tcx>>,
+{
+    let fingerprint_style = Q::Key::fingerprint_style();
+
+    if is_anon || !fingerprint_style.reconstructible() {
+        return DepKindStruct {
+            is_anon,
+            is_eval_always,
+            fingerprint_style,
+            force_from_dep_node: None,
+            try_load_from_on_disk_cache: None,
+        };
+    }
+
+    DepKindStruct {
+        is_anon,
+        is_eval_always,
+        fingerprint_style,
+        force_from_dep_node: Some(force_from_dep_node::<Q>),
+        try_load_from_on_disk_cache: Some(try_load_from_on_disk_cache::<Q>),
+    }
+}
+
 // NOTE: `$V` isn't used here, but we still need to match on it so it can be passed to other macros
 // invoked by `rustc_query_append`.
 macro_rules! define_queries {
@@ -308,18 +371,6 @@ macro_rules! define_queries {
             input: ($(([$($modifiers)*] [$($attr)*] [$name]))*)
         }
 
-        mod make_query {
-            use super::*;
-
-            // Create an eponymous constructor for each query.
-            $(#[allow(nonstandard_style)] $(#[$attr])*
-            pub fn $name<'tcx>(tcx: QueryCtxt<'tcx>, key: <queries::$name<'tcx> as QueryConfig>::Key) -> QueryStackFrame {
-                let kind = dep_graph::DepKind::$name;
-                let name = stringify!($name);
-                $crate::plumbing::create_query_frame(tcx, queries::$name::describe, key, kind, name)
-            })*
-        }
-
         #[allow(nonstandard_style)]
         mod queries {
             use std::marker::PhantomData;
@@ -373,18 +424,19 @@ fn make_vtable(tcx: QueryCtxt<'tcx>, key: &Self::Key) ->
                     try_load_from_disk: Self::TRY_LOAD_FROM_DISK,
                 }
             }
+
+            fn execute_query(tcx: TyCtxt<'tcx>, k: Self::Key) -> Self::Stored {
+                tcx.$name(k)
+            }
         })*
 
         #[allow(nonstandard_style)]
         mod query_callbacks {
             use super::*;
-            use rustc_middle::dep_graph::DepNode;
-            use rustc_query_system::dep_graph::DepNodeParams;
-            use rustc_query_system::query::{force_query, QueryDescription};
             use rustc_query_system::dep_graph::FingerprintStyle;
 
             // We use this for most things when incr. comp. is turned off.
-            pub fn Null() -> DepKindStruct {
+            pub fn Null<'tcx>() -> DepKindStruct<'tcx> {
                 DepKindStruct {
                     is_anon: false,
                     is_eval_always: false,
@@ -395,7 +447,7 @@ pub fn Null() -> DepKindStruct {
             }
 
             // We use this for the forever-red node.
-            pub fn Red() -> DepKindStruct {
+            pub fn Red<'tcx>() -> DepKindStruct<'tcx> {
                 DepKindStruct {
                     is_anon: false,
                     is_eval_always: false,
@@ -405,7 +457,7 @@ pub fn Red() -> DepKindStruct {
                 }
             }
 
-            pub fn TraitSelect() -> DepKindStruct {
+            pub fn TraitSelect<'tcx>() -> DepKindStruct<'tcx> {
                 DepKindStruct {
                     is_anon: true,
                     is_eval_always: false,
@@ -415,7 +467,7 @@ pub fn TraitSelect() -> DepKindStruct {
                 }
             }
 
-            pub fn CompileCodegenUnit() -> DepKindStruct {
+            pub fn CompileCodegenUnit<'tcx>() -> DepKindStruct<'tcx> {
                 DepKindStruct {
                     is_anon: false,
                     is_eval_always: false,
@@ -425,7 +477,7 @@ pub fn CompileCodegenUnit() -> DepKindStruct {
                 }
             }
 
-            pub fn CompileMonoItem() -> DepKindStruct {
+            pub fn CompileMonoItem<'tcx>() -> DepKindStruct<'tcx> {
                 DepKindStruct {
                     is_anon: false,
                     is_eval_always: false,
@@ -435,60 +487,15 @@ pub fn CompileMonoItem() -> DepKindStruct {
                 }
             }
 
-            $(pub(crate) fn $name()-> DepKindStruct {
-                let is_anon = is_anon!([$($modifiers)*]);
-                let is_eval_always = is_eval_always!([$($modifiers)*]);
-
-                let fingerprint_style =
-                    <<queries::$name<'_> as QueryConfig>::Key as DepNodeParams<TyCtxt<'_>>>::fingerprint_style();
-
-                if is_anon || !fingerprint_style.reconstructible() {
-                    return DepKindStruct {
-                        is_anon,
-                        is_eval_always,
-                        fingerprint_style,
-                        force_from_dep_node: None,
-                        try_load_from_on_disk_cache: None,
-                    }
-                }
-
-                #[inline(always)]
-                fn recover<'tcx>(tcx: TyCtxt<'tcx>, dep_node: DepNode) -> Option<<queries::$name<'tcx> as QueryConfig>::Key> {
-                    <<queries::$name<'_> as QueryConfig>::Key as DepNodeParams<TyCtxt<'_>>>::recover(tcx, &dep_node)
-                }
-
-                fn force_from_dep_node(tcx: TyCtxt<'_>, dep_node: DepNode) -> bool {
-                    if let Some(key) = recover(tcx, dep_node) {
-                        #[cfg(debug_assertions)]
-                        let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered();
-                        let tcx = QueryCtxt::from_tcx(tcx);
-                        force_query::<queries::$name<'_>, _>(tcx, key, dep_node);
-                        true
-                    } else {
-                        false
-                    }
-                }
-
-                fn try_load_from_on_disk_cache(tcx: TyCtxt<'_>, dep_node: DepNode) {
-                    debug_assert!(tcx.dep_graph.is_green(&dep_node));
-
-                    let key = recover(tcx, dep_node).unwrap_or_else(|| panic!("Failed to recover key for {:?} with hash {}", dep_node, dep_node.hash));
-                    if queries::$name::cache_on_disk(tcx, &key) {
-                        let _ = tcx.$name(key);
-                    }
-                }
-
-                DepKindStruct {
-                    is_anon,
-                    is_eval_always,
-                    fingerprint_style,
-                    force_from_dep_node: Some(force_from_dep_node),
-                    try_load_from_on_disk_cache: Some(try_load_from_on_disk_cache),
-                }
+            $(pub(crate) fn $name<'tcx>()-> DepKindStruct<'tcx> {
+                $crate::plumbing::query_callback::<queries::$name<'tcx>>(
+                    is_anon!([$($modifiers)*]),
+                    is_eval_always!([$($modifiers)*]),
+                )
             })*
         }
 
-        pub fn query_callbacks<'tcx>(arena: &'tcx Arena<'tcx>) -> &'tcx [DepKindStruct] {
+        pub fn query_callbacks<'tcx>(arena: &'tcx Arena<'tcx>) -> &'tcx [DepKindStruct<'tcx>] {
             arena.alloc_from_iter(make_dep_kind_array!(query_callbacks))
         }
     }
@@ -531,9 +538,14 @@ pub(crate) fn try_collect_active_jobs(
                 let mut jobs = QueryMap::default();
 
                 $(
+                    let make_query = |tcx, key| {
+                        let kind = dep_graph::DepKind::$name;
+                        let name = stringify!($name);
+                        $crate::plumbing::create_query_frame(tcx, queries::$name::describe, key, kind, name)
+                    };
                     self.$name.try_collect_active_jobs(
                         tcx,
-                        make_query::$name,
+                        make_query,
                         &mut jobs,
                     )?;
                 )*
@@ -555,7 +567,7 @@ fn try_mark_green(&'tcx self, tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode)
 
             $($(#[$attr])*
             #[inline(always)]
-            #[tracing::instrument(level = "trace", skip(self, tcx))]
+            #[tracing::instrument(level = "trace", skip(self, tcx), ret)]
             fn $name(
                 &'tcx self,
                 tcx: TyCtxt<'tcx>,
index bd0fd7ac3503a16ede69e8faa1f30a5f8140916d..ea38df836cbf1e4a0f9b98b8cad319644a4ad8b6 100644 (file)
@@ -73,4 +73,7 @@ fn query_cache<'a>(tcx: CTX) -> &'a Self::Cache
     fn make_vtable(tcx: CTX, key: &Self::Key) -> QueryVTable<CTX, Self::Key, Self::Value>;
 
     fn cache_on_disk(tcx: CTX::DepContext, key: &Self::Key) -> bool;
+
+    // Don't use this method to compute query results, instead use the methods on TyCtxt
+    fn execute_query(tcx: CTX::DepContext, k: Self::Key) -> Self::Stored;
 }
index 3fba923d9fdf425c443300fb15eed97ba6ffdfd8..0a3add2e0f5328a7e7ff90ff20630d12408484e1 100644 (file)
@@ -1,25 +1,21 @@
+use crate::imports::ImportKind;
+use crate::NameBinding;
+use crate::NameBindingKind;
+use crate::Resolver;
 use rustc_ast::ast;
 use rustc_ast::visit;
 use rustc_ast::visit::Visitor;
 use rustc_ast::Crate;
 use rustc_ast::EnumDef;
-use rustc_ast::ForeignMod;
 use rustc_ast::NodeId;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::def_id::CRATE_DEF_ID;
 use rustc_middle::middle::privacy::AccessLevel;
-use rustc_middle::ty::Visibility;
+use rustc_middle::ty::DefIdTree;
 use rustc_span::sym;
 
-use crate::imports::ImportKind;
-use crate::BindingKey;
-use crate::NameBinding;
-use crate::NameBindingKind;
-use crate::Resolver;
-
 pub struct AccessLevelsVisitor<'r, 'a> {
     r: &'r mut Resolver<'a>,
-    prev_level: Option<AccessLevel>,
     changed: bool,
 }
 
@@ -28,31 +24,32 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> {
     /// For now, this doesn't resolve macros (FIXME) and cannot resolve Impl, as we
     /// need access to a TyCtxt for that.
     pub fn compute_access_levels<'c>(r: &'r mut Resolver<'a>, krate: &'c Crate) {
-        let mut visitor =
-            AccessLevelsVisitor { r, changed: false, prev_level: Some(AccessLevel::Public) };
+        let mut visitor = AccessLevelsVisitor { r, changed: false };
 
         visitor.set_access_level_def_id(CRATE_DEF_ID, Some(AccessLevel::Public));
-        visitor.set_exports_access_level(CRATE_DEF_ID);
+        visitor.set_bindings_access_level(CRATE_DEF_ID);
 
         while visitor.changed {
             visitor.reset();
             visit::walk_crate(&mut visitor, krate);
         }
 
-        tracing::info!("resolve::access_levels: {:#?}", r.access_levels);
+        info!("resolve::access_levels: {:#?}", r.access_levels);
     }
 
     fn reset(&mut self) {
         self.changed = false;
-        self.prev_level = Some(AccessLevel::Public);
     }
 
-    /// Update the access level of the exports of the given module accordingly. The module access
+    /// Update the access level of the bindings in the given module accordingly. The module access
     /// level has to be Exported or Public.
     /// This will also follow `use` chains (see PrivacyVisitor::set_import_binding_access_level).
-    fn set_exports_access_level(&mut self, module_id: LocalDefId) {
+    fn set_bindings_access_level(&mut self, module_id: LocalDefId) {
         assert!(self.r.module_map.contains_key(&&module_id.to_def_id()));
-
+        let module_level = self.r.access_levels.map.get(&module_id).copied();
+        if !module_level.is_some() {
+            return;
+        }
         // Set the given binding access level to `AccessLevel::Public` and
         // sets the rest of the `use` chain to `AccessLevel::Exported` until
         // we hit the actual exported item.
@@ -72,28 +69,20 @@ fn set_exports_access_level(&mut self, module_id: LocalDefId) {
                 }
             };
 
-        let module_level = self.r.access_levels.map.get(&module_id).copied();
-        assert!(module_level >= Some(AccessLevel::Exported));
-
-        if let Some(exports) = self.r.reexport_map.get(&module_id) {
-            let pub_exports = exports
-                .iter()
-                .filter(|ex| ex.vis == Visibility::Public)
-                .cloned()
-                .collect::<Vec<_>>();
-
-            let module = self.r.get_module(module_id.to_def_id()).unwrap();
-            for export in pub_exports.into_iter() {
-                if let Some(export_def_id) = export.res.opt_def_id().and_then(|id| id.as_local()) {
-                    self.set_access_level_def_id(export_def_id, Some(AccessLevel::Exported));
-                }
-
-                if let Some(ns) = export.res.ns() {
-                    let key = BindingKey { ident: export.ident, ns, disambiguator: 0 };
-                    let name_res = self.r.resolution(module, key);
-                    if let Some(binding) = name_res.borrow().binding() {
-                        set_import_binding_access_level(self, binding, module_level)
-                    }
+        let module = self.r.get_module(module_id.to_def_id()).unwrap();
+        let resolutions = self.r.resolutions(module);
+
+        for (.., name_resolution) in resolutions.borrow().iter() {
+            if let Some(binding) = name_resolution.borrow().binding() && binding.vis.is_public() && !binding.is_ambiguity() {
+                let access_level = match binding.is_import() {
+                    true => {
+                        set_import_binding_access_level(self, binding, module_level);
+                        Some(AccessLevel::Exported)
+                    },
+                    false => module_level,
+                };
+                if let Some(def_id) = binding.res().opt_def_id().and_then(|id| id.as_local()) {
+                    self.set_access_level_def_id(def_id, access_level);
                 }
             }
         }
@@ -127,97 +116,59 @@ fn set_access_level_def_id(
 
 impl<'r, 'ast> Visitor<'ast> for AccessLevelsVisitor<'ast, 'r> {
     fn visit_item(&mut self, item: &'ast ast::Item) {
-        let inherited_item_level = match item.kind {
+        let def_id = self.r.local_def_id(item.id);
+        // Set access level of nested items.
+        // If it's a mod, also make the visitor walk all of its items
+        match item.kind {
             // Resolved in rustc_privacy when types are available
             ast::ItemKind::Impl(..) => return,
 
-            // Only exported `macro_rules!` items are public, but they always are
-            ast::ItemKind::MacroDef(ref macro_def) if macro_def.macro_rules => {
-                let is_macro_export =
-                    item.attrs.iter().any(|attr| attr.has_name(sym::macro_export));
-                if is_macro_export { Some(AccessLevel::Public) } else { None }
-            }
-
-            // Foreign modules inherit level from parents.
-            ast::ItemKind::ForeignMod(..) => self.prev_level,
-
-            // Other `pub` items inherit levels from parents.
-            ast::ItemKind::ExternCrate(..)
-            | ast::ItemKind::Use(..)
-            | ast::ItemKind::Static(..)
-            | ast::ItemKind::Const(..)
-            | ast::ItemKind::Fn(..)
-            | ast::ItemKind::Mod(..)
-            | ast::ItemKind::GlobalAsm(..)
-            | ast::ItemKind::TyAlias(..)
-            | ast::ItemKind::Enum(..)
-            | ast::ItemKind::Struct(..)
-            | ast::ItemKind::Union(..)
-            | ast::ItemKind::Trait(..)
-            | ast::ItemKind::TraitAlias(..)
-            | ast::ItemKind::MacroDef(..) => {
-                if item.vis.kind.is_pub() {
-                    self.prev_level
-                } else {
-                    None
-                }
-            }
-
             // Should be unreachable at this stage
             ast::ItemKind::MacCall(..) => panic!(
                 "ast::ItemKind::MacCall encountered, this should not anymore appear at this stage"
             ),
-        };
 
-        let access_level = self.set_access_level(item.id, inherited_item_level);
+            // Foreign modules inherit level from parents.
+            ast::ItemKind::ForeignMod(..) => {
+                let parent_level =
+                    self.r.access_levels.map.get(&self.r.local_parent(def_id)).copied();
+                self.set_access_level(item.id, parent_level);
+            }
 
-        // Set access level of nested items.
-        // If it's a mod, also make the visitor walk all of its items
-        match item.kind {
-            ast::ItemKind::Mod(..) => {
-                if access_level.is_some() {
-                    self.set_exports_access_level(self.r.local_def_id(item.id));
+            // Only exported `macro_rules!` items are public, but they always are
+            ast::ItemKind::MacroDef(ref macro_def) if macro_def.macro_rules => {
+                if item.attrs.iter().any(|attr| attr.has_name(sym::macro_export)) {
+                    self.set_access_level(item.id, Some(AccessLevel::Public));
                 }
+            }
 
-                let orig_level = std::mem::replace(&mut self.prev_level, access_level);
+            ast::ItemKind::Mod(..) => {
+                self.set_bindings_access_level(def_id);
                 visit::walk_item(self, item);
-                self.prev_level = orig_level;
             }
 
-            ast::ItemKind::ForeignMod(ForeignMod { ref items, .. }) => {
-                for nested in items {
-                    if nested.vis.kind.is_pub() {
-                        self.set_access_level(nested.id, access_level);
-                    }
-                }
-            }
             ast::ItemKind::Enum(EnumDef { ref variants }, _) => {
+                self.set_bindings_access_level(def_id);
                 for variant in variants {
-                    let variant_level = self.set_access_level(variant.id, access_level);
-                    if let Some(ctor_id) = variant.data.ctor_id() {
-                        self.set_access_level(ctor_id, access_level);
-                    }
-
+                    let variant_def_id = self.r.local_def_id(variant.id);
+                    let variant_level = self.r.access_levels.map.get(&variant_def_id).copied();
                     for field in variant.data.fields() {
                         self.set_access_level(field.id, variant_level);
                     }
                 }
             }
-            ast::ItemKind::Struct(ref def, _) | ast::ItemKind::Union(ref def, _) => {
-                if let Some(ctor_id) = def.ctor_id() {
-                    self.set_access_level(ctor_id, access_level);
-                }
 
+            ast::ItemKind::Struct(ref def, _) | ast::ItemKind::Union(ref def, _) => {
+                let inherited_level = self.r.access_levels.map.get(&def_id).copied();
                 for field in def.fields() {
                     if field.vis.kind.is_pub() {
-                        self.set_access_level(field.id, access_level);
+                        self.set_access_level(field.id, inherited_level);
                     }
                 }
             }
-            ast::ItemKind::Trait(ref trait_kind) => {
-                for nested in trait_kind.items.iter() {
-                    self.set_access_level(nested.id, access_level);
-                }
+
+            ast::ItemKind::Trait(..) => {
+                self.set_bindings_access_level(def_id);
             }
 
             ast::ItemKind::ExternCrate(..)
@@ -229,9 +180,6 @@ fn visit_item(&mut self, item: &'ast ast::Item) {
             | ast::ItemKind::TraitAlias(..)
             | ast::ItemKind::MacroDef(..)
             | ast::ItemKind::Fn(..) => return,
-
-            // Unreachable kinds
-            ast::ItemKind::Impl(..) | ast::ItemKind::MacCall(..) => unreachable!(),
         }
     }
 }
index 8f3b6009bd6ef8a5f31fa6387c5badaceb443faf..51e8c24b9c25a51066088753bf4ec5b00a261798 100644 (file)
@@ -36,7 +36,6 @@
 
 use std::cell::Cell;
 use std::ptr;
-use tracing::debug;
 
 type Res = def::Res<NodeId>;
 
@@ -1030,7 +1029,7 @@ fn build_reduced_graph_for_external_crate_res(&mut self, child: ModChild) {
                 self.insert_field_names(def_id, field_names);
             }
             Res::Def(DefKind::AssocFn, def_id) => {
-                if cstore.fn_has_self_parameter_untracked(def_id) {
+                if cstore.fn_has_self_parameter_untracked(def_id, self.r.session) {
                     self.r.has_self.insert(def_id);
                 }
             }
index 66641fb2cb248dc15446f722b0bb88f6f530a536..5955d8df16ee1edfa34f6edf2af8fca6c3cfc69c 100644 (file)
@@ -8,7 +8,6 @@
 use rustc_span::hygiene::LocalExpnId;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
-use tracing::debug;
 
 pub(crate) fn collect_definitions(
     resolver: &mut Resolver<'_>,
index 2d15b1b0a1b94fbb23740e9248407b6732a2d570..ab71fa0bc1d4d2a407c3d3ea28db8a60496a63a2 100644 (file)
@@ -25,7 +25,6 @@
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{BytePos, Span};
-use tracing::debug;
 
 use crate::imports::{Import, ImportKind, ImportResolver};
 use crate::late::{PatternSource, Rib};
@@ -1394,7 +1393,7 @@ fn lookup_import_candidates_from_module<FilterFn>(
 
         // If only some candidates are accessible, take just them
         if !candidates.iter().all(|v: &ImportSuggestion| !v.accessible) {
-            candidates = candidates.into_iter().filter(|x| x.accessible).collect();
+            candidates.retain(|x| x.accessible)
         }
 
         candidates
index 2afba94d793af192258f03affa50a5c65e63093c..b84a610833ddf6a8faa398d6e070d0ef93b25136 100644 (file)
@@ -273,7 +273,7 @@ fn hygienic_lexical_parent(
     ///
     /// Invariant: This must only be called during main resolution, not during
     /// import resolution.
-    #[tracing::instrument(level = "debug", skip(self, ribs))]
+    #[instrument(level = "debug", skip(self, ribs))]
     pub(crate) fn resolve_ident_in_lexical_scope(
         &mut self,
         mut ident: Ident,
@@ -367,7 +367,7 @@ pub(crate) fn resolve_ident_in_lexical_scope(
     /// expansion and import resolution (perhaps they can be merged in the future).
     /// The function is used for resolving initial segments of macro paths (e.g., `foo` in
     /// `foo::bar!(); or `foo!();`) and also for import paths on 2018 edition.
-    #[tracing::instrument(level = "debug", skip(self, scope_set))]
+    #[instrument(level = "debug", skip(self, scope_set))]
     pub(crate) fn early_resolve_ident_in_lexical_scope(
         &mut self,
         orig_ident: Ident,
@@ -708,7 +708,7 @@ struct Flags: u8 {
         Err(Determinacy::determined(determinacy == Determinacy::Determined || force))
     }
 
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     pub(crate) fn maybe_resolve_ident_in_module(
         &mut self,
         module: ModuleOrUniformRoot<'a>,
@@ -720,7 +720,7 @@ pub(crate) fn maybe_resolve_ident_in_module(
             .map_err(|(determinacy, _)| determinacy)
     }
 
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     pub(crate) fn resolve_ident_in_module(
         &mut self,
         module: ModuleOrUniformRoot<'a>,
@@ -734,7 +734,7 @@ pub(crate) fn resolve_ident_in_module(
             .map_err(|(determinacy, _)| determinacy)
     }
 
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn resolve_ident_in_module_ext(
         &mut self,
         module: ModuleOrUniformRoot<'a>,
@@ -772,7 +772,7 @@ fn resolve_ident_in_module_ext(
         )
     }
 
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn resolve_ident_in_module_unadjusted(
         &mut self,
         module: ModuleOrUniformRoot<'a>,
@@ -796,7 +796,7 @@ fn resolve_ident_in_module_unadjusted(
 
     /// Attempts to resolve `ident` in namespaces `ns` of `module`.
     /// Invariant: if `finalize` is `Some`, expansion and import resolution must be complete.
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn resolve_ident_in_module_unadjusted_ext(
         &mut self,
         module: ModuleOrUniformRoot<'a>,
@@ -1059,7 +1059,7 @@ fn resolve_ident_in_module_unadjusted_ext(
     }
 
     /// Validate a local resolution (from ribs).
-    #[tracing::instrument(level = "debug", skip(self, all_ribs))]
+    #[instrument(level = "debug", skip(self, all_ribs))]
     fn validate_res_from_ribs(
         &mut self,
         rib_index: usize,
@@ -1294,7 +1294,7 @@ fn validate_res_from_ribs(
         res
     }
 
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     pub(crate) fn maybe_resolve_path(
         &mut self,
         path: &[Segment],
@@ -1304,7 +1304,7 @@ pub(crate) fn maybe_resolve_path(
         self.resolve_path_with_ribs(path, opt_ns, parent_scope, None, None, None)
     }
 
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     pub(crate) fn resolve_path(
         &mut self,
         path: &[Segment],
index c2491c6ebdec08892d03f255f2f991b4484b902a..27745cee52df7f3243630d103984205ecbb9db78 100644 (file)
@@ -23,8 +23,6 @@
 use rustc_span::symbol::{kw, Ident, Symbol};
 use rustc_span::Span;
 
-use tracing::*;
-
 use std::cell::Cell;
 use std::{mem, ptr};
 
@@ -1135,24 +1133,15 @@ fn finalize_resolutions_in(&mut self, module: Module<'b>) {
         if let Some(def_id) = module.opt_def_id() {
             let mut reexports = Vec::new();
 
-            module.for_each_child(self.r, |_, ident, _, binding| {
-                // FIXME: Consider changing the binding inserted by `#[macro_export] macro_rules`
-                // into the crate root to actual `NameBindingKind::Import`.
-                if binding.is_import()
-                    || matches!(binding.kind, NameBindingKind::Res(_, _is_macro_export @ true))
-                {
-                    let res = binding.res().expect_non_local();
-                    // Ambiguous imports are treated as errors at this point and are
-                    // not exposed to other crates (see #36837 for more details).
-                    if res != def::Res::Err && !binding.is_ambiguity() {
-                        reexports.push(ModChild {
-                            ident,
-                            res,
-                            vis: binding.vis,
-                            span: binding.span,
-                            macro_rules: false,
-                        });
-                    }
+            module.for_each_child(self.r, |this, ident, _, binding| {
+                if let Some(res) = this.is_reexport(binding) {
+                    reexports.push(ModChild {
+                        ident,
+                        res,
+                        vis: binding.vis,
+                        span: binding.span,
+                        macro_rules: false,
+                    });
                 }
             });
 
index 693ec86616ee431e3ff70e2bbeeef37228ba70f2..b37feb15890ba22ff080b55f34c231a67318536f 100644 (file)
@@ -20,7 +20,7 @@
 use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, PartialRes, PerNS};
 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
-use rustc_hir::{PrimTy, TraitCandidate};
+use rustc_hir::{BindingAnnotation, PrimTy, TraitCandidate};
 use rustc_middle::middle::resolve_lifetime::Set1;
 use rustc_middle::ty::DefIdTree;
 use rustc_middle::{bug, span_bug};
@@ -32,7 +32,6 @@
 use rustc_span::source_map::{respan, Spanned};
 use std::collections::{hash_map::Entry, BTreeSet};
 use std::mem::{replace, take};
-use tracing::debug;
 
 mod diagnostics;
 pub(crate) mod lifetimes;
@@ -51,7 +50,7 @@
 #[derive(Copy, Clone, Debug)]
 struct BindingInfo {
     span: Span,
-    binding_mode: BindingMode,
+    annotation: BindingAnnotation,
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
@@ -1390,7 +1389,7 @@ fn visit_generic_params(&mut self, params: &'ast [GenericParam], add_self_upper:
         })
     }
 
-    #[tracing::instrument(level = "debug", skip(self, work))]
+    #[instrument(level = "debug", skip(self, work))]
     fn with_lifetime_rib<T>(
         &mut self,
         kind: LifetimeRibKind,
@@ -1404,7 +1403,7 @@ fn with_lifetime_rib<T>(
         ret
     }
 
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn resolve_lifetime(&mut self, lifetime: &'ast Lifetime, use_ctxt: visit::LifetimeCtxt) {
         let ident = lifetime.ident;
 
@@ -1508,7 +1507,7 @@ fn resolve_lifetime(&mut self, lifetime: &'ast Lifetime, use_ctxt: visit::Lifeti
         self.record_lifetime_res(lifetime.id, LifetimeRes::Error, LifetimeElisionCandidate::Named);
     }
 
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn resolve_anonymous_lifetime(&mut self, lifetime: &Lifetime, elided: bool) {
         debug_assert_eq!(lifetime.ident.name, kw::UnderscoreLifetime);
 
@@ -1573,7 +1572,7 @@ fn resolve_anonymous_lifetime(&mut self, lifetime: &Lifetime, elided: bool) {
         self.report_missing_lifetime_specifiers(vec![missing_lifetime], None);
     }
 
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn resolve_elided_lifetime(&mut self, anchor_id: NodeId, span: Span) {
         let id = self.r.next_node_id();
         let lt = Lifetime { id, ident: Ident::new(kw::UnderscoreLifetime, span) };
@@ -1586,7 +1585,7 @@ fn resolve_elided_lifetime(&mut self, anchor_id: NodeId, span: Span) {
         self.resolve_anonymous_lifetime(&lt, true);
     }
 
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn create_fresh_lifetime(&mut self, id: NodeId, ident: Ident, binder: NodeId) -> LifetimeRes {
         debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
         debug!(?ident.span);
@@ -1604,7 +1603,7 @@ fn create_fresh_lifetime(&mut self, id: NodeId, ident: Ident, binder: NodeId) ->
         res
     }
 
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn resolve_elided_lifetimes_in_path(
         &mut self,
         path_id: NodeId,
@@ -1804,7 +1803,7 @@ fn resolve_elided_lifetimes_in_path(
         }
     }
 
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn record_lifetime_res(
         &mut self,
         id: NodeId,
@@ -1827,7 +1826,7 @@ fn record_lifetime_res(
         }
     }
 
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn record_lifetime_param(&mut self, id: NodeId, res: LifetimeRes) {
         if let Some(prev_res) = self.r.lifetimes_res_map.insert(id, res) {
             panic!(
@@ -1838,7 +1837,7 @@ fn record_lifetime_param(&mut self, id: NodeId, res: LifetimeRes) {
     }
 
     /// Perform resolution of a function signature, accounting for lifetime elision.
-    #[tracing::instrument(level = "debug", skip(self, inputs))]
+    #[instrument(level = "debug", skip(self, inputs))]
     fn resolve_fn_signature(
         &mut self,
         fn_id: NodeId,
@@ -2866,10 +2865,10 @@ fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap {
 
         pat.walk(&mut |pat| {
             match pat.kind {
-                PatKind::Ident(binding_mode, ident, ref sub_pat)
+                PatKind::Ident(annotation, ident, ref sub_pat)
                     if sub_pat.is_some() || self.is_base_res_local(pat.id) =>
                 {
-                    binding_map.insert(ident, BindingInfo { span: ident.span, binding_mode });
+                    binding_map.insert(ident, BindingInfo { span: ident.span, annotation });
                 }
                 PatKind::Or(ref ps) => {
                     // Check the consistency of this or-pattern and
@@ -2926,7 +2925,7 @@ fn check_consistent_bindings(&mut self, pats: &[P<Pat>]) -> Vec<BindingMap> {
                         binding_error.target.insert(pat_outer.span);
                     }
                     Some(binding_outer) => {
-                        if binding_outer.binding_mode != binding_inner.binding_mode {
+                        if binding_outer.annotation != binding_inner.annotation {
                             // The binding modes in the outer and inner bindings differ.
                             inconsistent_vars
                                 .entry(name)
@@ -3147,14 +3146,14 @@ fn innermost_rib_bindings(&mut self, ns: Namespace) -> &mut IdentMap<Res> {
     fn try_resolve_as_non_binding(
         &mut self,
         pat_src: PatternSource,
-        bm: BindingMode,
+        ann: BindingAnnotation,
         ident: Ident,
         has_sub: bool,
     ) -> Option<Res> {
         // An immutable (no `mut`) by-value (no `ref`) binding pattern without
         // a sub pattern (no `@ $pat`) is syntactically ambiguous as it could
         // also be interpreted as a path to e.g. a constant, variant, etc.
-        let is_syntactic_ambiguity = !has_sub && bm == BindingMode::ByValue(Mutability::Not);
+        let is_syntactic_ambiguity = !has_sub && ann == BindingAnnotation::NONE;
 
         let ls_binding = self.maybe_resolve_ident_in_lexical_scope(ident, ValueNS)?;
         let (res, binding) = match ls_binding {
@@ -3268,11 +3267,9 @@ fn smart_resolve_path_fragment(
         source: PathSource<'ast>,
         finalize: Finalize,
     ) -> PartialRes {
-        tracing::debug!(
+        debug!(
             "smart_resolve_path_fragment(qself={:?}, path={:?}, finalize={:?})",
-            qself,
-            path,
-            finalize,
+            qself, path, finalize,
         );
         let ns = source.namespace();
 
index 9fc637ddbbffae4cc939405cb4702105e8f59585..99d13acbae1b9aa5fd9afecc36f18949557bbc8b 100644 (file)
@@ -33,8 +33,6 @@
 use std::iter;
 use std::ops::Deref;
 
-use tracing::debug;
-
 type Res = def::Res<ast::NodeId>;
 
 /// A field or associated item from self type suggested in case of resolution failure.
index 661aadea94443022dbfc2f1a25368b4d4fcf1fa3..c72981ed96f6788b0c840ff7c420349aace8e42d 100644 (file)
@@ -278,7 +278,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
 /// lifetimes into a single binder.) This requires us to resolve the
 /// *trait definition* of `Sub`; basically just enough lifetime information
 /// to look at the supertraits.
-#[tracing::instrument(level = "debug", skip(tcx))]
+#[instrument(level = "debug", skip(tcx))]
 fn resolve_lifetimes_trait_definition(
     tcx: TyCtxt<'_>,
     local_def_id: LocalDefId,
@@ -289,7 +289,7 @@ fn resolve_lifetimes_trait_definition(
 /// Computes the `ResolveLifetimes` map that contains data for an entire `Item`.
 /// You should not read the result of this query directly, but rather use
 /// `named_region_map`, `is_late_bound_map`, etc.
-#[tracing::instrument(level = "debug", skip(tcx))]
+#[instrument(level = "debug", skip(tcx))]
 fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> ResolveLifetimes {
     convert_named_region_map(do_resolve(tcx, local_def_id, false))
 }
@@ -647,7 +647,7 @@ fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
         }
     }
 
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
         match ty.kind {
             hir::TyKind::BareFn(ref c) => {
@@ -930,7 +930,7 @@ fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
         }
     }
 
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
         match lifetime_ref.name {
             hir::LifetimeName::Static => self.insert_lifetime(lifetime_ref, Region::Static),
@@ -1148,21 +1148,18 @@ fn visit_poly_trait_ref(
     }
 }
 
-fn object_lifetime_default<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    param_def_id: DefId,
-) -> Option<ObjectLifetimeDefault> {
+fn object_lifetime_default<'tcx>(tcx: TyCtxt<'tcx>, param_def_id: DefId) -> ObjectLifetimeDefault {
+    debug_assert_eq!(tcx.def_kind(param_def_id), DefKind::TyParam);
     let param_def_id = param_def_id.expect_local();
     let parent_def_id = tcx.local_parent(param_def_id);
-    let generics = tcx.hir().get_generics(parent_def_id)?;
+    let generics = tcx.hir().get_generics(parent_def_id).unwrap();
     let param_hir_id = tcx.local_def_id_to_hir_id(param_def_id);
-    let param = generics.params.iter().find(|p| p.hir_id == param_hir_id)?;
+    let param = generics.params.iter().find(|p| p.hir_id == param_hir_id).unwrap();
 
     // Scan the bounds and where-clauses on parameters to extract bounds
     // of the form `T:'a` so as to determine the `ObjectLifetimeDefault`
     // for each type parameter.
     match param.kind {
-        GenericParamKind::Lifetime { .. } => None,
         GenericParamKind::Type { .. } => {
             let mut set = Set1::Empty;
 
@@ -1181,21 +1178,17 @@ fn object_lifetime_default<'tcx>(
                 }
             }
 
-            Some(match set {
+            match set {
                 Set1::Empty => ObjectLifetimeDefault::Empty,
                 Set1::One(hir::LifetimeName::Static) => ObjectLifetimeDefault::Static,
                 Set1::One(hir::LifetimeName::Param(param_def_id, _)) => {
                     ObjectLifetimeDefault::Param(param_def_id.to_def_id())
                 }
                 _ => ObjectLifetimeDefault::Ambiguous,
-            })
+            }
         }
-        GenericParamKind::Const { .. } => {
-            // Generic consts don't impose any constraints.
-            //
-            // We still store a dummy value here to allow generic parameters
-            // in an arbitrary order.
-            Some(ObjectLifetimeDefault::Empty)
+        _ => {
+            bug!("object_lifetime_default_raw must only be called on a type parameter")
         }
     }
 }
@@ -1212,7 +1205,7 @@ fn with<F>(&mut self, wrap_scope: Scope<'_>, f: F)
             scope: &wrap_scope,
             trait_definition_only: self.trait_definition_only,
         };
-        let span = tracing::debug_span!("scope", scope = ?TruncatedScopeDebug(&this.scope));
+        let span = debug_span!("scope", scope = ?TruncatedScopeDebug(&this.scope));
         {
             let _enter = span.enter();
             f(&mut this);
@@ -1287,7 +1280,7 @@ fn visit_early_late<F>(
         self.with(scope, walk);
     }
 
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn resolve_lifetime_ref(
         &mut self,
         region_def_id: LocalDefId,
@@ -1409,7 +1402,7 @@ fn resolve_lifetime_ref(
         );
     }
 
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn visit_segment_args(
         &mut self,
         res: Res,
@@ -1512,7 +1505,20 @@ fn visit_segment_args(
             generics
                 .params
                 .iter()
-                .filter_map(|param| self.tcx.object_lifetime_default(param.def_id))
+                .filter_map(|param| {
+                    match self.tcx.def_kind(param.def_id) {
+                        // Generic consts don't impose any constraints.
+                        //
+                        // We still store a dummy value here to allow generic parameters
+                        // in an arbitrary order.
+                        DefKind::ConstParam => Some(ObjectLifetimeDefault::Empty),
+                        DefKind::TyParam => Some(self.tcx.object_lifetime_default(param.def_id)),
+                        // We may also get a `Trait` or `TraitAlias` because of how generics `Self` parameter
+                        // works.  Ignore it because it can't have a meaningful lifetime default.
+                        DefKind::LifetimeParam | DefKind::Trait | DefKind::TraitAlias => None,
+                        dk => bug!("unexpected def_kind {:?}", dk),
+                    }
+                })
                 .map(set_to_region)
                 .collect()
         });
@@ -1659,7 +1665,7 @@ fn supertrait_hrtb_lifetimes(
         }
     }
 
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn visit_fn_like_elision(
         &mut self,
         inputs: &'tcx [hir::Ty<'tcx>],
@@ -1707,7 +1713,7 @@ fn resolve_object_lifetime_default(&mut self, lifetime_ref: &'tcx hir::Lifetime)
         self.insert_lifetime(lifetime_ref, lifetime.shifted(late_depth));
     }
 
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: Region) {
         debug!(
             node = ?self.tcx.hir().node_to_string(lifetime_ref.hir_id),
index 5c33cb694a7655356cef6ca54838423891e8fc04..aaa9ae6f32513cc639378f7a704d04e27d25ec46 100644 (file)
@@ -58,7 +58,6 @@
 use std::cell::{Cell, RefCell};
 use std::collections::BTreeSet;
 use std::{cmp, fmt, ptr};
-use tracing::debug;
 
 use diagnostics::{ImportSuggestion, LabelSuggestion, Suggestion};
 use imports::{Import, ImportKind, ImportResolver, NameResolution};
@@ -912,11 +911,6 @@ pub struct Resolver<'a> {
     label_res_map: NodeMap<NodeId>,
     /// Resolutions for lifetimes.
     lifetimes_res_map: NodeMap<LifetimeRes>,
-    /// Mapping from generics `def_id`s to TAIT generics `def_id`s.
-    /// For each captured lifetime (e.g., 'a), we create a new lifetime parameter that is a generic
-    /// defined on the TAIT, so we have type Foo<'a1> = ... and we establish a mapping in this
-    /// field from the original parameter 'a to the new parameter 'a1.
-    generics_def_id_map: Vec<FxHashMap<LocalDefId, LocalDefId>>,
     /// Lifetime parameters that lowering will have to introduce.
     extra_lifetime_params_map: NodeMap<Vec<(Ident, NodeId, LifetimeRes)>>,
 
@@ -1279,7 +1273,6 @@ pub fn new(
             import_res_map: Default::default(),
             label_res_map: Default::default(),
             lifetimes_res_map: Default::default(),
-            generics_def_id_map: Vec::new(),
             extra_lifetime_params_map: Default::default(),
             extern_crate_map: Default::default(),
             reexport_map: FxHashMap::default(),
@@ -1446,7 +1439,6 @@ pub fn into_outputs(
             import_res_map: self.import_res_map,
             label_res_map: self.label_res_map,
             lifetimes_res_map: self.lifetimes_res_map,
-            generics_def_id_map: self.generics_def_id_map,
             extra_lifetime_params_map: self.extra_lifetime_params_map,
             next_node_id: self.next_node_id,
             node_id_to_def_id: self.node_id_to_def_id,
@@ -1491,7 +1483,6 @@ pub fn clone_outputs(
             import_res_map: self.import_res_map.clone(),
             label_res_map: self.label_res_map.clone(),
             lifetimes_res_map: self.lifetimes_res_map.clone(),
-            generics_def_id_map: self.generics_def_id_map.clone(),
             extra_lifetime_params_map: self.extra_lifetime_params_map.clone(),
             next_node_id: self.next_node_id.clone(),
             node_id_to_def_id: self.node_id_to_def_id.clone(),
@@ -2021,6 +2012,24 @@ fn resolve_main(&mut self) {
         }
         self.main_def = Some(MainDefinition { res, is_import, span });
     }
+
+    // Items that go to reexport table encoded to metadata and visible through it to other crates.
+    fn is_reexport(&self, binding: &NameBinding<'a>) -> Option<def::Res<!>> {
+        // FIXME: Consider changing the binding inserted by `#[macro_export] macro_rules`
+        // into the crate root to actual `NameBindingKind::Import`.
+        if binding.is_import()
+            || matches!(binding.kind, NameBindingKind::Res(_, _is_macro_export @ true))
+        {
+            let res = binding.res().expect_non_local();
+            // Ambiguous imports are treated as errors at this point and are
+            // not exposed to other crates (see #36837 for more details).
+            if res != def::Res::Err && !binding.is_ambiguity() {
+                return Some(res);
+            }
+        }
+
+        return None;
+    }
 }
 
 fn names_to_string(names: &[Symbol]) -> String {
index e2e0e1f5b300ad345ef4bf9837bab4eb49c8b29a..6658892881d4b9bbf365734f6d83a9e938890c2c 100644 (file)
@@ -44,8 +44,6 @@
     RefKind, Relation, RelationKind, SpanData,
 };
 
-use tracing::{debug, error};
-
 #[rustfmt::skip] // https://github.com/rust-lang/rustfmt/issues/5213
 macro_rules! down_cast_data {
     ($id:ident, $kind:ident, $sp:expr) => {
@@ -805,6 +803,7 @@ fn process_method_call(
         &mut self,
         ex: &'tcx hir::Expr<'tcx>,
         seg: &'tcx hir::PathSegment<'tcx>,
+        receiver: &'tcx hir::Expr<'tcx>,
         args: &'tcx [hir::Expr<'tcx>],
     ) {
         debug!("process_method_call {:?} {:?}", ex, ex.span);
@@ -825,6 +824,7 @@ fn process_method_call(
         }
 
         // walk receiver and args
+        self.visit_expr(receiver);
         walk_list!(self, visit_expr, args);
     }
 
@@ -914,7 +914,10 @@ fn process_var_decl(&mut self, pat: &'tcx hir::Pat<'tcx>) {
                     _,
                 )
                 | Res::SelfTy { .. } => {
-                    self.dump_path_segment_ref(id, &hir::PathSegment::from_ident(ident));
+                    self.dump_path_segment_ref(
+                        id,
+                        &hir::PathSegment::new(ident, hir::HirId::INVALID, Res::Err),
+                    );
                 }
                 def => {
                     error!("unexpected definition kind when processing collected idents: {:?}", def)
@@ -974,7 +977,7 @@ fn process_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>, trait_i
         self.process_macro_use(trait_item.span);
         match trait_item.kind {
             hir::TraitItemKind::Const(ref ty, body) => {
-                let body = body.map(|b| &self.tcx.hir().body(b).value);
+                let body = body.map(|b| self.tcx.hir().body(b).value);
                 let attrs = self.tcx.hir().attrs(trait_item.hir_id());
                 self.process_assoc_const(
                     trait_item.def_id,
@@ -1342,7 +1345,9 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
                 let res = self.save_ctxt.get_path_res(hir_expr.hir_id);
                 self.process_struct_lit(ex, path, fields, adt.variant_of_res(res), *rest)
             }
-            hir::ExprKind::MethodCall(ref seg, args, _) => self.process_method_call(ex, seg, args),
+            hir::ExprKind::MethodCall(ref seg, receiver, args, _) => {
+                self.process_method_call(ex, seg, receiver, args)
+            }
             hir::ExprKind::Field(ref sub_ex, _) => {
                 self.visit_expr(&sub_ex);
 
index 619e083d89ad398b1991ecbf49e808e37409321a..89bca39512f52554250cab4ad0894128cae84752 100644 (file)
@@ -7,6 +7,9 @@
 #![deny(rustc::untranslatable_diagnostic)]
 #![deny(rustc::diagnostic_outside_of_impl)]
 
+#[macro_use]
+extern crate tracing;
+
 mod dump_visitor;
 mod dumper;
 #[macro_use]
@@ -49,8 +52,6 @@
     RefKind, Relation, RelationKind, SpanData,
 };
 
-use tracing::{debug, error, info};
-
 pub struct SaveContext<'tcx> {
     tcx: TyCtxt<'tcx>,
     maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>,
@@ -595,13 +596,14 @@ pub fn get_path_res(&self, hir_id: hir::HirId) -> Res {
             Node::TraitRef(tr) => tr.path.res,
 
             Node::Item(&hir::Item { kind: hir::ItemKind::Use(path, _), .. }) => path.res,
-            Node::PathSegment(seg) => match seg.res {
-                Some(res) if res != Res::Err => res,
-                _ => {
+            Node::PathSegment(seg) => {
+                if seg.res != Res::Err {
+                    seg.res
+                } else {
                     let parent_node = self.tcx.hir().get_parent_node(hir_id);
                     self.get_path_res(parent_node)
                 }
-            },
+            }
 
             Node::Expr(&hir::Expr { kind: hir::ExprKind::Struct(ref qpath, ..), .. }) => {
                 self.typeck_results().qpath_res(qpath, hir_id)
@@ -647,7 +649,7 @@ pub fn get_path_data(&self, id: hir::HirId, path: &hir::QPath<'_>) -> Option<Ref
     }
 
     pub fn get_path_segment_data(&self, path_seg: &hir::PathSegment<'_>) -> Option<Ref> {
-        self.get_path_segment_data_with_id(path_seg, path_seg.hir_id?)
+        self.get_path_segment_data_with_id(path_seg, path_seg.hir_id)
     }
 
     pub fn get_path_segment_data_with_id(
@@ -864,23 +866,12 @@ fn visit_pat(&mut self, p: &'l hir::Pat<'l>) {
             hir::PatKind::TupleStruct(ref path, ..) | hir::PatKind::Path(ref path) => {
                 self.collected_paths.push((p.hir_id, path));
             }
-            hir::PatKind::Binding(bm, _, ident, _) => {
+            hir::PatKind::Binding(hir::BindingAnnotation(_, mutbl), _, ident, _) => {
                 debug!(
                     "PathCollector, visit ident in pat {}: {:?} {:?}",
                     ident, p.span, ident.span
                 );
-                let immut = match bm {
-                    // Even if the ref is mut, you can't change the ref, only
-                    // the data pointed at, so showing the initialising expression
-                    // is still worthwhile.
-                    hir::BindingAnnotation::Unannotated | hir::BindingAnnotation::Ref => {
-                        hir::Mutability::Not
-                    }
-                    hir::BindingAnnotation::Mutable | hir::BindingAnnotation::RefMut => {
-                        hir::Mutability::Mut
-                    }
-                };
-                self.collected_idents.push((p.hir_id, ident, immut));
+                self.collected_idents.push((p.hir_id, ident, mutbl));
             }
             _ => {}
         }
index 2a4a772f61085dfe13dfba1a48d4944cd39e0f56..2336d99363fd3d8ed639b61d96d9891dcb293439 100644 (file)
@@ -10,7 +10,6 @@
 use std::borrow::Cow;
 use std::fmt::{self};
 use std::sync::{Arc, Mutex};
-use tracing::debug;
 
 #[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
 pub enum CguReuse {
index 162fc9aa0a6ea622e3202fb47a2fe2f967777ebe..04bd685f19001ed99d9bb01e4ba4cd55389ba3c7 100644 (file)
@@ -12,8 +12,8 @@
 
 use rustc_data_structures::stable_hasher::ToStableHashKey;
 use rustc_target::abi::{Align, TargetDataLayout};
-use rustc_target::spec::{LinkerFlavor, SplitDebuginfo, Target, TargetTriple, TargetWarnings};
-use rustc_target::spec::{PanicStrategy, SanitizerSet, TARGETS};
+use rustc_target::spec::{PanicStrategy, SanitizerSet, SplitDebuginfo};
+use rustc_target::spec::{Target, TargetTriple, TargetWarnings, TARGETS};
 
 use crate::parse::{CrateCheckConfig, CrateConfig};
 use rustc_feature::UnstableFeatures;
@@ -36,6 +36,8 @@
 use std::path::{Path, PathBuf};
 use std::str::{self, FromStr};
 
+pub mod sigpipe;
+
 /// The different settings that the `-C strip` flag can have.
 #[derive(Clone, Copy, PartialEq, Hash, Debug)]
 pub enum Strip {
@@ -798,7 +800,15 @@ pub fn diagnostic_handler_flags(&self, can_emit_warnings: bool) -> HandlerFlags
 // The type of entry function, so users can have their own entry functions
 #[derive(Copy, Clone, PartialEq, Hash, Debug, HashStable_Generic)]
 pub enum EntryFnType {
-    Main,
+    Main {
+        /// Specifies what to do with `SIGPIPE` before calling `fn main()`.
+        ///
+        /// What values that are valid and what they mean must be in sync
+        /// across rustc and libstd, but we don't want it public in libstd,
+        /// so we take a bit of an unusual approach with simple constants
+        /// and an `include!()`.
+        sigpipe: u8,
+    },
     Start,
 }
 
@@ -891,7 +901,7 @@ fn default_configuration(sess: &Session) -> CrateConfig {
         sess.fatal(&err);
     });
 
-    let mut ret = FxHashSet::default();
+    let mut ret = CrateConfig::default();
     ret.reserve(7); // the minimum number of insertions
     // Target bindings.
     ret.insert((sym::target_os, Some(Symbol::intern(os))));
@@ -2379,16 +2389,6 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         }
     }
 
-    if cg.linker_flavor == Some(LinkerFlavor::L4Bender)
-        && !nightly_options::is_unstable_enabled(matches)
-    {
-        early_error(
-            error_format,
-            "`l4-bender` linker flavor is unstable, `-Z unstable-options` \
-             flag must also be passed to explicitly use it",
-        );
-    }
-
     let prints = collect_print_requests(&mut cg, &mut unstable_opts, matches, error_format);
 
     let cg = cg;
@@ -2530,7 +2530,7 @@ fn parse_pretty(unstable_opts: &UnstableOptions, efmt: ErrorOutputType) -> Optio
             ),
         ),
     };
-    tracing::debug!("got unpretty option: {first:?}");
+    debug!("got unpretty option: {first:?}");
     Some(first)
 }
 
diff --git a/compiler/rustc_session/src/config/sigpipe.rs b/compiler/rustc_session/src/config/sigpipe.rs
new file mode 100644 (file)
index 0000000..a5c9411
--- /dev/null
@@ -0,0 +1,22 @@
+//! NOTE: Keep these constants in sync with `library/std/src/sys/unix/mod.rs`!
+
+/// Do not touch `SIGPIPE`. Use whatever the parent process uses.
+#[allow(dead_code)]
+pub const INHERIT: u8 = 1;
+
+/// Change `SIGPIPE` to `SIG_IGN` so that failed writes results in `EPIPE`
+/// that are eventually converted to `ErrorKind::BrokenPipe`.
+#[allow(dead_code)]
+pub const SIG_IGN: u8 = 2;
+
+/// Change `SIGPIPE` to `SIG_DFL` so that the process is killed when trying
+/// to write to a closed pipe. This is usually the desired behavior for CLI
+/// apps that produce textual output that you want to pipe to other programs
+/// such as `head -n 1`.
+#[allow(dead_code)]
+pub const SIG_DFL: u8 = 3;
+
+/// `SIG_IGN` has been the Rust default since 2014. See
+/// <https://github.com/rust-lang/rust/issues/62569>.
+#[allow(dead_code)]
+pub const DEFAULT: u8 = SIG_IGN;
index c973e3140cef97b596545cdfb3d536fa6bd6eef1..e8edb38f5038ea1f4c55d949a5dc3558050efbbe 100644 (file)
@@ -7,7 +7,6 @@
 
 use crate::search_paths::{PathKind, SearchPath};
 use rustc_fs_util::fix_windows_verbatim_for_gcc;
-use tracing::debug;
 
 #[derive(Copy, Clone)]
 pub enum FileMatch {
index 429475c573c8e8d01202e46d7ed7a1c8957ffd97..02d5d33c8d5ba24727b27fec54a3a42bbd511fe4 100644 (file)
@@ -14,6 +14,9 @@
 extern crate rustc_macros;
 pub mod errors;
 
+#[macro_use]
+extern crate tracing;
+
 pub mod cgu_reuse_tracker;
 pub mod utils;
 pub use lint::{declare_lint, declare_lint_pass, declare_tool_lint, impl_lint_pass};
index 46bba02537dc7b830f20d03450c307b964c0c301..9f07394b61ab8fc0808ee5397d4bfd7e20b5deec 100644 (file)
@@ -5,7 +5,7 @@
 use crate::search_paths::SearchPath;
 use crate::utils::NativeLib;
 use rustc_errors::LanguageIdentifier;
-use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy, SanitizerSet};
+use rustc_target::spec::{CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, SanitizerSet};
 use rustc_target::spec::{
     RelocModel, RelroLevel, SplitDebuginfo, StackProtector, TargetTriple, TlsModel,
 };
@@ -382,7 +382,7 @@ mod desc {
         "either a boolean (`yes`, `no`, `on`, `off`, etc), `checks`, or `nochecks`";
     pub const parse_cfprotection: &str = "`none`|`no`|`n` (default), `branch`, `return`, or `full`|`yes`|`y` (equivalent to `branch` and `return`)";
     pub const parse_strip: &str = "either `none`, `debuginfo`, or `symbols`";
-    pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavor::one_of();
+    pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavorCli::one_of();
     pub const parse_optimization_fuel: &str = "crate=integer";
     pub const parse_mir_spanview: &str = "`statement` (default), `terminator`, or `block`";
     pub const parse_instrument_coverage: &str =
@@ -763,8 +763,8 @@ pub(crate) fn parse_cfprotection(slot: &mut CFProtection, v: Option<&str>) -> bo
         true
     }
 
-    pub(crate) fn parse_linker_flavor(slot: &mut Option<LinkerFlavor>, v: Option<&str>) -> bool {
-        match v.and_then(LinkerFlavor::from_str) {
+    pub(crate) fn parse_linker_flavor(slot: &mut Option<LinkerFlavorCli>, v: Option<&str>) -> bool {
+        match v.and_then(LinkerFlavorCli::from_str) {
             Some(lf) => *slot = Some(lf),
             _ => return false,
         }
@@ -1139,7 +1139,7 @@ pub(crate) fn parse_proc_macro_execution_strategy(
         on C toolchain installed in the system"),
     linker: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED],
         "system linker to link outputs with"),
-    linker_flavor: Option<LinkerFlavor> = (None, parse_linker_flavor, [UNTRACKED],
+    linker_flavor: Option<LinkerFlavorCli> = (None, parse_linker_flavor, [UNTRACKED],
         "linker flavor"),
     linker_plugin_lto: LinkerPluginLto = (LinkerPluginLto::Disabled,
         parse_linker_plugin_lto, [TRACKED],
index ebec754dcffb841b063ed5ea0b4415bee8822345..5b95d73bd4d3810f1486f949b29a76958d46810c 100644 (file)
@@ -8,7 +8,7 @@
 };
 use crate::SessionDiagnostic;
 use rustc_ast::node_id::NodeId;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
 use rustc_data_structures::sync::{Lock, Lrc};
 use rustc_errors::{emitter::SilentEmitter, ColorConfig, Handler};
 use rustc_errors::{
@@ -25,7 +25,7 @@
 
 /// The set of keys (and, optionally, values) that define the compilation
 /// environment of the crate, used to drive conditional compilation.
-pub type CrateConfig = FxHashSet<(Symbol, Option<Symbol>)>;
+pub type CrateConfig = FxIndexSet<(Symbol, Option<Symbol>)>;
 pub type CrateCheckConfig = CheckCfg<Symbol>;
 
 /// Collected spans during parsing for places where a certain feature was
@@ -241,7 +241,7 @@ pub fn with_span_handler(handler: Handler, source_map: Lrc<SourceMap>) -> Self {
         Self {
             span_diagnostic: handler,
             unstable_features: UnstableFeatures::from_environment(None),
-            config: FxHashSet::default(),
+            config: FxIndexSet::default(),
             check_config: CrateCheckConfig::default(),
             edition: ExpnId::root().expn_data().edition,
             raw_identifier_spans: Lock::new(Vec::new()),
index ec5e5170d359494fbeae05002849ef132dd91c1d..a49af23be2316d7ad1a839bd27d115522d3a765e 100644 (file)
@@ -110,6 +110,12 @@ fn mul(self, rhs: usize) -> Self::Output {
     }
 }
 
+impl rustc_errors::IntoDiagnosticArg for Limit {
+    fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
+        self.to_string().into_diagnostic_arg()
+    }
+}
+
 #[derive(Clone, Copy, Debug, HashStable_Generic)]
 pub struct Limits {
     /// The maximum recursion limit for potentially infinitely recursive
index e169d3c7cfb7c2553d583f7686c30a9e73383798..e8ddb4ed17a3e6da5af4e922736fa11dbe4c029f 100644 (file)
@@ -41,7 +41,6 @@
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use std::fmt;
 use std::hash::Hash;
-use tracing::*;
 
 /// A `SyntaxContext` represents a chain of pairs `(ExpnId, Transparency)` named "marks".
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
index 860af7fe93a077959f1377c70d642af5e8709a9e..34e2e92bdfce1efa6fc203f15245ac5d76104a04 100644 (file)
@@ -76,8 +76,6 @@
 use sha1::Sha1;
 use sha2::Sha256;
 
-use tracing::debug;
-
 #[cfg(test)]
 mod tests;
 
index a32cabab4c407281a0190e9dba473a863086b8bf..4d94c92d3f2b182ce8521d059210527bf784d62d 100644 (file)
@@ -23,7 +23,6 @@
 
 use std::fs;
 use std::io;
-use tracing::debug;
 
 #[cfg(test)]
 mod tests;
@@ -1060,13 +1059,13 @@ pub fn map_prefix(&self, path: PathBuf) -> (PathBuf, bool) {
 
         return remap_path_prefix(&self.mapping, path);
 
-        #[instrument(level = "debug", skip(mapping))]
+        #[instrument(level = "debug", skip(mapping), ret)]
         fn remap_path_prefix(mapping: &[(PathBuf, PathBuf)], path: PathBuf) -> (PathBuf, bool) {
             // 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() {
-                debug!("Trying to apply {:?} => {:?}", from, to);
+                debug!("Trying to apply {from:?} => {to:?}");
 
                 if let Ok(rest) = path.strip_prefix(from) {
                     let remapped = if rest.as_os_str().is_empty() {
@@ -1080,15 +1079,15 @@ fn remap_path_prefix(mapping: &[(PathBuf, PathBuf)], path: PathBuf) -> (PathBuf,
                     } else {
                         to.join(rest)
                     };
-                    debug!("Match - remapped {:?} => {:?}", path, remapped);
+                    debug!("Match - remapped");
 
                     return (remapped, true);
                 } else {
-                    debug!("No match - prefix {:?} does not match {:?}", from, path);
+                    debug!("No match - prefix {from:?} does not match");
                 }
             }
 
-            debug!("Path {:?} was not remapped", path);
+            debug!("not remapped");
             (path, false)
         }
     }
index 6eca7dc52b26ac7d47d5fb83c6676ea9665a7b93..75b1dfc856ac715c0877b252b45df38dbf01dd25 100644 (file)
         LinkedList,
         LintPass,
         Mutex,
+        MutexGuard,
         N,
         NonZeroI128,
         NonZeroI16,
         Rust,
         RustcDecodable,
         RustcEncodable,
+        RwLockReadGuard,
+        RwLockWriteGuard,
         Send,
         SeqCst,
         SessionDiagnostic,
         alias,
         align,
         align_offset,
+        alignment,
         alignstack,
         all,
         alloc,
         const_deallocate,
         const_eval_limit,
         const_eval_select,
-        const_eval_select_ct,
         const_evaluatable_checked,
         const_extern_fn,
         const_fn,
         emit_struct,
         emit_struct_field,
         enable,
-        enclosing_scope,
         encode,
         end,
         env,
         infer_outlives_requirements,
         infer_static_outlives_requirements,
         inherent_associated_types,
+        inherit,
         inlateout,
         inline,
         inline_const,
         lib,
         libc,
         lifetime,
+        lifetimes,
         likely,
         line,
         line_macro,
         panic_unwind,
         panicking,
         param_attrs,
+        parent_label,
         partial_cmp,
         partial_ord,
         passes,
         rust_eh_unregister_frames,
         rust_oom,
         rustc,
+        rustc_access_level,
         rustc_allocator,
         rustc_allocator_nounwind,
         rustc_allocator_zeroed,
         rustfmt,
         rvalue_static_promotion,
         s,
+        safety,
         sanitize,
         sanitizer_runtime,
         saturating_add,
         should_panic,
         shr,
         shr_assign,
+        sig_dfl,
+        sig_ign,
         simd,
         simd_add,
         simd_and,
         trait_alias,
         trait_upcasting,
         transmute,
+        transmute_opts,
         transmute_trait,
         transparent,
         transparent_enums,
         unit,
         universal_impl_trait,
         unix,
+        unix_sigpipe,
         unlikely,
         unmarked_api,
         unpin,
         va_list,
         va_start,
         val,
+        validity,
         values,
         var,
         variant_count,
index 9241fd82c745fde4a857c5598faaba111c2edd34..46c5fe78ffbf65697085e5bcd7874ed70e50595a 100644 (file)
@@ -6,8 +6,6 @@
 use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeVisitable};
 use rustc_middle::util::common::record_time;
 
-use tracing::debug;
-
 use std::fmt::{self, Write};
 use std::mem::{self, discriminant};
 
index 0c6489acb34835085ceb32cd02f2223c5d05f8cf..62f44a48032efd93301b704bf538bdea53813c8f 100644 (file)
@@ -97,6 +97,9 @@
 #[macro_use]
 extern crate rustc_middle;
 
+#[macro_use]
+extern crate tracing;
+
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::ty::{self, Instance, TyCtxt};
 use rustc_session::config::SymbolManglingVersion;
 
-use tracing::debug;
-
 mod legacy;
 mod v0;
 
index b4cf2c5ee229496f71f65ba2eebb2af13b208913..f492c3451a4182dcb18dbf991980f5089cd27a39 100644 (file)
@@ -2,6 +2,6 @@
 
 pub fn target() -> Target {
     let mut target = wasm32_unknown_emscripten::target();
-    target.add_post_link_args(LinkerFlavor::Em, &["-sWASM=0", "--memory-init-file", "0"]);
+    target.add_post_link_args(LinkerFlavor::EmCc, &["-sWASM=0", "--memory-init-file", "0"]);
     target
 }
index 3c4da6f883d9dab420e3520d582ff68ff12a1ede..baf36587147a690d4ecbeba0066468e4f5af6c2f 100644 (file)
@@ -5,7 +5,7 @@ pub fn opts(endian: Endian) -> TargetOptions {
     TargetOptions {
         allow_asm: true,
         endian,
-        linker_flavor: LinkerFlavor::BpfLinker,
+        linker_flavor: LinkerFlavor::Bpf,
         atomic_cas: false,
         dynamic_linking: true,
         no_builtins: true,
index cab4dd333d43dbc5edb34d0f634616d7af6597bb..b7bc1072bf3280c0b496ce057c09dabef754f47f 100644 (file)
@@ -4,7 +4,7 @@ pub fn opts() -> TargetOptions {
     TargetOptions {
         os: "l4re".into(),
         env: "uclibc".into(),
-        linker_flavor: LinkerFlavor::L4Bender,
+        linker_flavor: LinkerFlavor::Ld,
         panic_strategy: PanicStrategy::Abort,
         linker: Some("l4-bender".into()),
         linker_is_gnu: false,
index 2459b0280cd66df3e2f5ca94a8193f4b9364f7f1..47eb5fc6a1dcbc6d5beac04d65a6fae9d2709b49 100644 (file)
 
 #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
 pub enum LinkerFlavor {
-    Em,
     Gcc,
-    L4Bender,
     Ld,
+    Lld(LldFlavor),
     Msvc,
+    EmCc,
+    Bpf,
+    Ptx,
+}
+
+#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
+pub enum LinkerFlavorCli {
+    Gcc,
+    Ld,
     Lld(LldFlavor),
-    PtxLinker,
+    Msvc,
+    Em,
     BpfLinker,
+    PtxLinker,
 }
 
 #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
@@ -137,19 +147,40 @@ fn to_json(&self) -> Json {
     }
 }
 
-impl ToJson for LinkerFlavor {
-    fn to_json(&self) -> Json {
-        self.desc().to_json()
+impl LinkerFlavor {
+    pub fn from_cli(cli: LinkerFlavorCli) -> LinkerFlavor {
+        match cli {
+            LinkerFlavorCli::Gcc => LinkerFlavor::Gcc,
+            LinkerFlavorCli::Ld => LinkerFlavor::Ld,
+            LinkerFlavorCli::Lld(lld_flavor) => LinkerFlavor::Lld(lld_flavor),
+            LinkerFlavorCli::Msvc => LinkerFlavor::Msvc,
+            LinkerFlavorCli::Em => LinkerFlavor::EmCc,
+            LinkerFlavorCli::BpfLinker => LinkerFlavor::Bpf,
+            LinkerFlavorCli::PtxLinker => LinkerFlavor::Ptx,
+        }
+    }
+
+    fn to_cli(self) -> LinkerFlavorCli {
+        match self {
+            LinkerFlavor::Gcc => LinkerFlavorCli::Gcc,
+            LinkerFlavor::Ld => LinkerFlavorCli::Ld,
+            LinkerFlavor::Lld(lld_flavor) => LinkerFlavorCli::Lld(lld_flavor),
+            LinkerFlavor::Msvc => LinkerFlavorCli::Msvc,
+            LinkerFlavor::EmCc => LinkerFlavorCli::Em,
+            LinkerFlavor::Bpf => LinkerFlavorCli::BpfLinker,
+            LinkerFlavor::Ptx => LinkerFlavorCli::PtxLinker,
+        }
     }
 }
-macro_rules! flavor_mappings {
-    ($((($($flavor:tt)*), $string:expr),)*) => (
-        impl LinkerFlavor {
+
+macro_rules! linker_flavor_cli_impls {
+    ($(($($flavor:tt)*) $string:literal)*) => (
+        impl LinkerFlavorCli {
             pub const fn one_of() -> &'static str {
                 concat!("one of: ", $($string, " ",)*)
             }
 
-            pub fn from_str(s: &str) -> Option<Self> {
+            pub fn from_str(s: &str) -> Option<LinkerFlavorCli> {
                 Some(match s {
                     $($string => $($flavor)*,)*
                     _ => return None,
@@ -165,18 +196,23 @@ pub fn desc(&self) -> &str {
     )
 }
 
-flavor_mappings! {
-    ((LinkerFlavor::Em), "em"),
-    ((LinkerFlavor::Gcc), "gcc"),
-    ((LinkerFlavor::L4Bender), "l4-bender"),
-    ((LinkerFlavor::Ld), "ld"),
-    ((LinkerFlavor::Msvc), "msvc"),
-    ((LinkerFlavor::PtxLinker), "ptx-linker"),
-    ((LinkerFlavor::BpfLinker), "bpf-linker"),
-    ((LinkerFlavor::Lld(LldFlavor::Wasm)), "wasm-ld"),
-    ((LinkerFlavor::Lld(LldFlavor::Ld64)), "ld64.lld"),
-    ((LinkerFlavor::Lld(LldFlavor::Ld)), "ld.lld"),
-    ((LinkerFlavor::Lld(LldFlavor::Link)), "lld-link"),
+linker_flavor_cli_impls! {
+    (LinkerFlavorCli::Gcc) "gcc"
+    (LinkerFlavorCli::Ld) "ld"
+    (LinkerFlavorCli::Lld(LldFlavor::Ld)) "ld.lld"
+    (LinkerFlavorCli::Lld(LldFlavor::Ld64)) "ld64.lld"
+    (LinkerFlavorCli::Lld(LldFlavor::Link)) "lld-link"
+    (LinkerFlavorCli::Lld(LldFlavor::Wasm)) "wasm-ld"
+    (LinkerFlavorCli::Msvc) "msvc"
+    (LinkerFlavorCli::Em) "em"
+    (LinkerFlavorCli::BpfLinker) "bpf-linker"
+    (LinkerFlavorCli::PtxLinker) "ptx-linker"
+}
+
+impl ToJson for LinkerFlavorCli {
+    fn to_json(&self) -> Json {
+        self.desc().to_json()
+    }
 }
 
 #[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable, HashStable_Generic)]
@@ -467,6 +503,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 }
 
 pub type LinkArgs = BTreeMap<LinkerFlavor, Vec<StaticCow<str>>>;
+pub type LinkArgsCli = BTreeMap<LinkerFlavorCli, Vec<StaticCow<str>>>;
 
 /// Which kind of debuginfo does the target use?
 ///
@@ -1210,19 +1247,21 @@ pub struct TargetOptions {
     pub abi: StaticCow<str>,
     /// Vendor name to use for conditional compilation (`target_vendor`). Defaults to "unknown".
     pub vendor: StaticCow<str>,
-    /// Default linker flavor used if `-C linker-flavor` or `-C linker` are not passed
-    /// on the command line. Defaults to `LinkerFlavor::Gcc`.
-    pub linker_flavor: LinkerFlavor,
 
     /// Linker to invoke
     pub linker: Option<StaticCow<str>>,
-
+    /// Default linker flavor used if `-C linker-flavor` or `-C linker` are not passed
+    /// on the command line. Defaults to `LinkerFlavor::Gcc`.
+    pub linker_flavor: LinkerFlavor,
+    linker_flavor_json: LinkerFlavorCli,
     /// LLD flavor used if `lld` (or `rust-lld`) is specified as a linker
     /// without clarifying its flavor in any way.
+    /// FIXME: Merge this into `LinkerFlavor`.
     pub lld_flavor: LldFlavor,
+    /// Whether the linker support GNU-like arguments such as -O. Defaults to true.
+    /// FIXME: Merge this into `LinkerFlavor`.
+    pub linker_is_gnu: bool,
 
-    /// Linker arguments that are passed *before* any user-defined libraries.
-    pub pre_link_args: LinkArgs,
     /// Objects to link before and after all other object code.
     pub pre_link_objects: CrtObjects,
     pub post_link_objects: CrtObjects,
@@ -1231,24 +1270,31 @@ pub struct TargetOptions {
     pub post_link_objects_self_contained: CrtObjects,
     pub link_self_contained: LinkSelfContainedDefault,
 
+    /// Linker arguments that are passed *before* any user-defined libraries.
+    pub pre_link_args: LinkArgs,
+    pre_link_args_json: LinkArgsCli,
     /// Linker arguments that are unconditionally passed after any
     /// user-defined but before post-link objects. Standard platform
     /// libraries that should be always be linked to, usually go here.
     pub late_link_args: LinkArgs,
+    late_link_args_json: LinkArgsCli,
     /// Linker arguments used in addition to `late_link_args` if at least one
     /// Rust dependency is dynamically linked.
     pub late_link_args_dynamic: LinkArgs,
+    late_link_args_dynamic_json: LinkArgsCli,
     /// Linker arguments used in addition to `late_link_args` if all Rust
     /// dependencies are statically linked.
     pub late_link_args_static: LinkArgs,
+    late_link_args_static_json: LinkArgsCli,
     /// Linker arguments that are unconditionally passed *after* any
     /// user-defined libraries.
     pub post_link_args: LinkArgs,
+    post_link_args_json: LinkArgsCli,
+
     /// Optional link script applied to `dylib` and `executable` crate types.
     /// This is a string containing the script, not a path. Can only be applied
     /// to linkers where `linker_is_gnu` is true.
     pub link_script: Option<StaticCow<str>>,
-
     /// Environment variables to be set for the linker invocation.
     pub link_env: StaticCow<[(StaticCow<str>, StaticCow<str>)]>,
     /// Environment variables to be removed for the linker invocation.
@@ -1333,8 +1379,6 @@ pub struct TargetOptions {
     /// Default supported version of DWARF on this platform.
     /// Useful because some platforms (osx, bsd) only want up to DWARF2.
     pub default_dwarf_version: u32,
-    /// Whether the linker support GNU-like arguments such as -O. Defaults to true.
-    pub linker_is_gnu: bool,
     /// The MinGW toolchain has a known issue that prevents it from correctly
     /// handling COFF object files with more than 2<sup>15</sup> sections. Since each weak
     /// symbol needs its own COMDAT section, weak linkage implies a large
@@ -1532,11 +1576,7 @@ fn add_link_args(link_args: &mut LinkArgs, flavor: LinkerFlavor, args: &[&'stati
         LinkerFlavor::Lld(lld_flavor) => {
             panic!("add_link_args: use non-LLD flavor for {:?}", lld_flavor)
         }
-        LinkerFlavor::Gcc
-        | LinkerFlavor::Em
-        | LinkerFlavor::L4Bender
-        | LinkerFlavor::BpfLinker
-        | LinkerFlavor::PtxLinker => {}
+        LinkerFlavor::Gcc | LinkerFlavor::EmCc | LinkerFlavor::Bpf | LinkerFlavor::Ptx => {}
     }
 }
 
@@ -1554,6 +1594,36 @@ fn add_pre_link_args(&mut self, flavor: LinkerFlavor, args: &[&'static str]) {
     fn add_post_link_args(&mut self, flavor: LinkerFlavor, args: &[&'static str]) {
         add_link_args(&mut self.post_link_args, flavor, args);
     }
+
+    fn update_from_cli(&mut self) {
+        self.linker_flavor = LinkerFlavor::from_cli(self.linker_flavor_json);
+        for (args, args_json) in [
+            (&mut self.pre_link_args, &self.pre_link_args_json),
+            (&mut self.late_link_args, &self.late_link_args_json),
+            (&mut self.late_link_args_dynamic, &self.late_link_args_dynamic_json),
+            (&mut self.late_link_args_static, &self.late_link_args_static_json),
+            (&mut self.post_link_args, &self.post_link_args_json),
+        ] {
+            *args = args_json
+                .iter()
+                .map(|(flavor, args)| (LinkerFlavor::from_cli(*flavor), args.clone()))
+                .collect();
+        }
+    }
+
+    fn update_to_cli(&mut self) {
+        self.linker_flavor_json = self.linker_flavor.to_cli();
+        for (args, args_json) in [
+            (&self.pre_link_args, &mut self.pre_link_args_json),
+            (&self.late_link_args, &mut self.late_link_args_json),
+            (&self.late_link_args_dynamic, &mut self.late_link_args_dynamic_json),
+            (&self.late_link_args_static, &mut self.late_link_args_static_json),
+            (&self.post_link_args, &mut self.post_link_args_json),
+        ] {
+            *args_json =
+                args.iter().map(|(flavor, args)| (flavor.to_cli(), args.clone())).collect();
+        }
+    }
 }
 
 impl Default for TargetOptions {
@@ -1568,11 +1638,11 @@ fn default() -> TargetOptions {
             env: "".into(),
             abi: "".into(),
             vendor: "unknown".into(),
-            linker_flavor: LinkerFlavor::Gcc,
             linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.into()),
+            linker_flavor: LinkerFlavor::Gcc,
+            linker_flavor_json: LinkerFlavorCli::Gcc,
             lld_flavor: LldFlavor::Ld,
-            pre_link_args: LinkArgs::new(),
-            post_link_args: LinkArgs::new(),
+            linker_is_gnu: true,
             link_script: None,
             asm_args: cvs![],
             cpu: "generic".into(),
@@ -1599,7 +1669,6 @@ fn default() -> TargetOptions {
             is_like_msvc: false,
             is_like_wasm: false,
             default_dwarf_version: 4,
-            linker_is_gnu: true,
             allows_weak_linkage: true,
             has_rpath: false,
             no_default_libraries: true,
@@ -1612,9 +1681,16 @@ fn default() -> TargetOptions {
             pre_link_objects_self_contained: Default::default(),
             post_link_objects_self_contained: Default::default(),
             link_self_contained: LinkSelfContainedDefault::False,
+            pre_link_args: LinkArgs::new(),
+            pre_link_args_json: LinkArgsCli::new(),
             late_link_args: LinkArgs::new(),
+            late_link_args_json: LinkArgsCli::new(),
             late_link_args_dynamic: LinkArgs::new(),
+            late_link_args_dynamic_json: LinkArgsCli::new(),
             late_link_args_static: LinkArgs::new(),
+            late_link_args_static_json: LinkArgsCli::new(),
+            post_link_args: LinkArgs::new(),
+            post_link_args_json: LinkArgsCli::new(),
             link_env: cvs![],
             link_env_remove: cvs![],
             archive_format: "gnu".into(),
@@ -2019,13 +2095,13 @@ macro_rules! key {
                     Some(Ok(()))
                 })).unwrap_or(Ok(()))
             } );
-            ($key_name:ident, LinkerFlavor) => ( {
-                let name = (stringify!($key_name)).replace("_", "-");
-                obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
-                    match LinkerFlavor::from_str(s) {
+            ($key_name:ident = $json_name:expr, LinkerFlavor) => ( {
+                let name = $json_name;
+                obj.remove(name).and_then(|o| o.as_str().and_then(|s| {
+                    match LinkerFlavorCli::from_str(s) {
                         Some(linker_flavor) => base.$key_name = linker_flavor,
                         _ => return Some(Err(format!("'{}' is not a valid value for linker-flavor. \
-                                                      Use {}", s, LinkerFlavor::one_of()))),
+                                                      Use {}", s, LinkerFlavorCli::one_of()))),
                     }
                     Some(Ok(()))
                 })).unwrap_or(Ok(()))
@@ -2106,14 +2182,14 @@ macro_rules! key {
                     base.$key_name = args;
                 }
             } );
-            ($key_name:ident, link_args) => ( {
-                let name = (stringify!($key_name)).replace("_", "-");
-                if let Some(val) = obj.remove(&name) {
+            ($key_name:ident = $json_name:expr, link_args) => ( {
+                let name = $json_name;
+                if let Some(val) = obj.remove(name) {
                     let obj = val.as_object().ok_or_else(|| format!("{}: expected a \
                         JSON object with fields per linker-flavor.", name))?;
-                    let mut args = LinkArgs::new();
+                    let mut args = LinkArgsCli::new();
                     for (k, v) in obj {
-                        let flavor = LinkerFlavor::from_str(&k).ok_or_else(|| {
+                        let flavor = LinkerFlavorCli::from_str(&k).ok_or_else(|| {
                             format!("{}: '{}' is not a valid value for linker-flavor. \
                                      Use 'em', 'gcc', 'ld' or 'msvc'", name, k)
                         })?;
@@ -2199,19 +2275,20 @@ macro_rules! key {
         key!(env);
         key!(abi);
         key!(vendor);
-        key!(linker_flavor, LinkerFlavor)?;
         key!(linker, optional);
+        key!(linker_flavor_json = "linker-flavor", LinkerFlavor)?;
         key!(lld_flavor, LldFlavor)?;
+        key!(linker_is_gnu, bool);
         key!(pre_link_objects = "pre-link-objects", link_objects);
         key!(post_link_objects = "post-link-objects", link_objects);
         key!(pre_link_objects_self_contained = "pre-link-objects-fallback", link_objects);
         key!(post_link_objects_self_contained = "post-link-objects-fallback", link_objects);
         key!(link_self_contained = "crt-objects-fallback", link_self_contained)?;
-        key!(pre_link_args, link_args);
-        key!(late_link_args, link_args);
-        key!(late_link_args_dynamic, link_args);
-        key!(late_link_args_static, link_args);
-        key!(post_link_args, link_args);
+        key!(pre_link_args_json = "pre-link-args", link_args);
+        key!(late_link_args_json = "late-link-args", link_args);
+        key!(late_link_args_dynamic_json = "late-link-args-dynamic", link_args);
+        key!(late_link_args_static_json = "late-link-args-static", link_args);
+        key!(post_link_args_json = "post-link-args", link_args);
         key!(link_script, optional);
         key!(link_env, env);
         key!(link_env_remove, list);
@@ -2239,7 +2316,6 @@ macro_rules! key {
         key!(is_like_msvc, bool);
         key!(is_like_wasm, bool);
         key!(default_dwarf_version, u32);
-        key!(linker_is_gnu, bool);
         key!(allows_weak_linkage, bool);
         key!(has_rpath, bool);
         key!(no_default_libraries, bool);
@@ -2296,6 +2372,8 @@ macro_rules! key {
             // This can cause unfortunate ICEs later down the line.
             return Err("may not set is_builtin for targets not built-in".into());
         }
+        base.update_from_cli();
+
         // Each field should have been read using `Json::remove` so any keys remaining are unused.
         let remaining_keys = obj.keys();
         Ok((
@@ -2387,42 +2465,44 @@ impl ToJson for Target {
     fn to_json(&self) -> Json {
         let mut d = serde_json::Map::new();
         let default: TargetOptions = Default::default();
+        let mut target = self.clone();
+        target.update_to_cli();
 
         macro_rules! target_val {
             ($attr:ident) => {{
                 let name = (stringify!($attr)).replace("_", "-");
-                d.insert(name, self.$attr.to_json());
+                d.insert(name, target.$attr.to_json());
             }};
         }
 
         macro_rules! target_option_val {
             ($attr:ident) => {{
                 let name = (stringify!($attr)).replace("_", "-");
-                if default.$attr != self.$attr {
-                    d.insert(name, self.$attr.to_json());
+                if default.$attr != target.$attr {
+                    d.insert(name, target.$attr.to_json());
                 }
             }};
-            ($attr:ident, $key_name:expr) => {{
-                let name = $key_name;
-                if default.$attr != self.$attr {
-                    d.insert(name.into(), self.$attr.to_json());
+            ($attr:ident, $json_name:expr) => {{
+                let name = $json_name;
+                if default.$attr != target.$attr {
+                    d.insert(name.into(), target.$attr.to_json());
                 }
             }};
-            (link_args - $attr:ident) => {{
-                let name = (stringify!($attr)).replace("_", "-");
-                if default.$attr != self.$attr {
-                    let obj = self
+            (link_args - $attr:ident, $json_name:expr) => {{
+                let name = $json_name;
+                if default.$attr != target.$attr {
+                    let obj = target
                         .$attr
                         .iter()
                         .map(|(k, v)| (k.desc().to_string(), v.clone()))
                         .collect::<BTreeMap<_, _>>();
-                    d.insert(name, obj.to_json());
+                    d.insert(name.to_string(), obj.to_json());
                 }
             }};
             (env - $attr:ident) => {{
                 let name = (stringify!($attr)).replace("_", "-");
-                if default.$attr != self.$attr {
-                    let obj = self
+                if default.$attr != target.$attr {
+                    let obj = target
                         .$attr
                         .iter()
                         .map(|&(ref k, ref v)| format!("{k}={v}"))
@@ -2444,19 +2524,20 @@ macro_rules! target_option_val {
         target_option_val!(env);
         target_option_val!(abi);
         target_option_val!(vendor);
-        target_option_val!(linker_flavor);
         target_option_val!(linker);
+        target_option_val!(linker_flavor_json, "linker-flavor");
         target_option_val!(lld_flavor);
+        target_option_val!(linker_is_gnu);
         target_option_val!(pre_link_objects);
         target_option_val!(post_link_objects);
         target_option_val!(pre_link_objects_self_contained, "pre-link-objects-fallback");
         target_option_val!(post_link_objects_self_contained, "post-link-objects-fallback");
         target_option_val!(link_self_contained, "crt-objects-fallback");
-        target_option_val!(link_args - pre_link_args);
-        target_option_val!(link_args - late_link_args);
-        target_option_val!(link_args - late_link_args_dynamic);
-        target_option_val!(link_args - late_link_args_static);
-        target_option_val!(link_args - post_link_args);
+        target_option_val!(link_args - pre_link_args_json, "pre-link-args");
+        target_option_val!(link_args - late_link_args_json, "late-link-args");
+        target_option_val!(link_args - late_link_args_dynamic_json, "late-link-args-dynamic");
+        target_option_val!(link_args - late_link_args_static_json, "late-link-args-static");
+        target_option_val!(link_args - post_link_args_json, "post-link-args");
         target_option_val!(link_script);
         target_option_val!(env - link_env);
         target_option_val!(link_env_remove);
@@ -2485,7 +2566,6 @@ macro_rules! target_option_val {
         target_option_val!(is_like_msvc);
         target_option_val!(is_like_wasm);
         target_option_val!(default_dwarf_version);
-        target_option_val!(linker_is_gnu);
         target_option_val!(allows_weak_linkage);
         target_option_val!(has_rpath);
         target_option_val!(no_default_libraries);
index 1c5b68001b957b00cc0b927c014022f3b1c25c95..6ab3a8b7eb5a06f688bc5505f1f0ddb9e6301bb8 100644 (file)
@@ -10,7 +10,7 @@ pub fn target() -> Target {
         options: TargetOptions {
             os: "cuda".into(),
             vendor: "nvidia".into(),
-            linker_flavor: LinkerFlavor::PtxLinker,
+            linker_flavor: LinkerFlavor::Ptx,
             // The linker can be installed from `crates.io`.
             linker: Some("rust-ptx-linker".into()),
             linker_is_gnu: false,
index 4a53b9c173d1ff43b492e886e3313ab410c23530..d03f959076de0c0ab5fe7691c1f70daf5756d2ab 100644 (file)
@@ -2,9 +2,11 @@
 use std::assert_matches::assert_matches;
 
 // Test target self-consistency and JSON encoding/decoding roundtrip.
-pub(super) fn test_target(target: Target, triple: &str) {
+pub(super) fn test_target(mut target: Target, triple: &str) {
+    let recycled_target = Target::from_json(target.to_json()).map(|(j, _)| j);
+    target.update_to_cli();
     target.check_consistency(triple);
-    assert_eq!(Target::from_json(target.to_json()).map(|(j, _)| j), Ok(target));
+    assert_eq!(recycled_target, Ok(target));
 }
 
 impl Target {
@@ -22,10 +24,9 @@ fn check_consistency(&self, triple: &str) {
         assert_eq!(self.is_like_osx, matches!(self.lld_flavor, LldFlavor::Ld64));
         assert_eq!(self.is_like_msvc, matches!(self.lld_flavor, LldFlavor::Link));
         assert_eq!(self.is_like_wasm, matches!(self.lld_flavor, LldFlavor::Wasm));
-        assert_eq!(self.os == "l4re", matches!(self.linker_flavor, LinkerFlavor::L4Bender));
-        assert_eq!(self.os == "emscripten", matches!(self.linker_flavor, LinkerFlavor::Em));
-        assert_eq!(self.arch == "bpf", matches!(self.linker_flavor, LinkerFlavor::BpfLinker));
-        assert_eq!(self.arch == "nvptx64", matches!(self.linker_flavor, LinkerFlavor::PtxLinker));
+        assert_eq!(self.os == "emscripten", matches!(self.linker_flavor, LinkerFlavor::EmCc));
+        assert_eq!(self.arch == "bpf", matches!(self.linker_flavor, LinkerFlavor::Bpf));
+        assert_eq!(self.arch == "nvptx64", matches!(self.linker_flavor, LinkerFlavor::Ptx));
 
         for args in [
             &self.pre_link_args,
@@ -65,17 +66,14 @@ fn check_consistency(&self, triple: &str) {
                             LinkerFlavor::Lld(LldFlavor::Wasm) | LinkerFlavor::Gcc
                         )
                     }
-                    (LinkerFlavor::L4Bender, LldFlavor::Ld) => {
-                        assert_matches!(flavor, LinkerFlavor::L4Bender)
+                    (LinkerFlavor::EmCc, LldFlavor::Wasm) => {
+                        assert_matches!(flavor, LinkerFlavor::EmCc)
                     }
-                    (LinkerFlavor::Em, LldFlavor::Wasm) => {
-                        assert_matches!(flavor, LinkerFlavor::Em)
+                    (LinkerFlavor::Bpf, LldFlavor::Ld) => {
+                        assert_matches!(flavor, LinkerFlavor::Bpf)
                     }
-                    (LinkerFlavor::BpfLinker, LldFlavor::Ld) => {
-                        assert_matches!(flavor, LinkerFlavor::BpfLinker)
-                    }
-                    (LinkerFlavor::PtxLinker, LldFlavor::Ld) => {
-                        assert_matches!(flavor, LinkerFlavor::PtxLinker)
+                    (LinkerFlavor::Ptx, LldFlavor::Ld) => {
+                        assert_matches!(flavor, LinkerFlavor::Ptx)
                     }
                     flavors => unreachable!("unexpected flavor combination: {:?}", flavors),
                 }
index c7e7d22108656ffab3264bc5263cb0a2575e9f12..6f77ef98c015df8c38dc5629d23fa5c496982be8 100644 (file)
@@ -5,13 +5,13 @@ pub fn target() -> Target {
     // Reset flags for non-Em flavors back to empty to satisfy sanity checking tests.
     let pre_link_args = LinkArgs::new();
     let post_link_args = TargetOptions::link_args(
-        LinkerFlavor::Em,
+        LinkerFlavor::EmCc,
         &["-sABORTING_MALLOC=0", "-Wl,--fatal-warnings"],
     );
 
     let opts = TargetOptions {
         os: "emscripten".into(),
-        linker_flavor: LinkerFlavor::Em,
+        linker_flavor: LinkerFlavor::EmCc,
         // emcc emits two files - a .js file to instantiate the wasm and supply platform
         // functionality, and a .wasm file.
         exe_suffix: ".js".into(),
index 8b7e8984a8adbf359b4be7882198932deea4413a..36ab8f3bd8845f6cf6bc754c1432fafccaf365bd 100644 (file)
@@ -1,6 +1,6 @@
+use crate::errors::AutoDerefReachedRecursionLimit;
 use crate::traits::query::evaluate_obligation::InferCtxtExt;
 use crate::traits::{self, TraitEngine};
-use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_infer::infer::InferCtxt;
 use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt};
@@ -222,19 +222,10 @@ pub fn report_autoderef_recursion_limit_error<'tcx>(tcx: TyCtxt<'tcx>, span: Spa
         Limit(0) => Limit(2),
         limit => limit * 2,
     };
-    struct_span_err!(
-        tcx.sess,
+    tcx.sess.emit_err(AutoDerefReachedRecursionLimit {
         span,
-        E0055,
-        "reached the recursion limit while auto-dereferencing `{:?}`",
-        ty
-    )
-    .span_label(span, "deref recursion limit reached")
-    .help(&format!(
-        "consider increasing the recursion limit by adding a \
-             `#![recursion_limit = \"{}\"]` attribute to your crate (`{}`)",
+        ty,
         suggested_limit,
-        tcx.crate_name(LOCAL_CRATE),
-    ))
-    .emit();
+        crate_name: tcx.crate_name(LOCAL_CRATE),
+    });
 }
diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs
new file mode 100644 (file)
index 0000000..81977f2
--- /dev/null
@@ -0,0 +1,102 @@
+use rustc_errors::{fluent, ErrorGuaranteed};
+use rustc_macros::SessionDiagnostic;
+use rustc_middle::ty::{PolyTraitRef, Ty, Unevaluated};
+use rustc_session::{parse::ParseSess, Limit, SessionDiagnostic};
+use rustc_span::{Span, Symbol};
+
+#[derive(SessionDiagnostic)]
+#[diag(trait_selection::dump_vtable_entries)]
+pub struct DumpVTableEntries<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub trait_ref: PolyTraitRef<'a>,
+    pub entries: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(trait_selection::unable_to_construct_constant_value)]
+pub struct UnableToConstructConstantValue<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub unevaluated: Unevaluated<'a>,
+}
+
+#[derive(SessionDiagnostic)]
+#[help]
+#[diag(trait_selection::auto_deref_reached_recursion_limit, code = "E0055")]
+pub struct AutoDerefReachedRecursionLimit<'a> {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    pub ty: Ty<'a>,
+    pub suggested_limit: Limit,
+    pub crate_name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(trait_selection::empty_on_clause_in_rustc_on_unimplemented, code = "E0232")]
+pub struct EmptyOnClauseInOnUnimplemented {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(trait_selection::invalid_on_clause_in_rustc_on_unimplemented, code = "E0232")]
+pub struct InvalidOnClauseInOnUnimplemented {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(trait_selection::no_value_in_rustc_on_unimplemented, code = "E0232")]
+#[note]
+pub struct NoValueInOnUnimplemented {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+pub struct NegativePositiveConflict<'a> {
+    pub impl_span: Span,
+    pub trait_desc: &'a str,
+    pub self_desc: &'a Option<String>,
+    pub negative_impl_span: Result<Span, Symbol>,
+    pub positive_impl_span: Result<Span, Symbol>,
+}
+
+impl SessionDiagnostic<'_> for NegativePositiveConflict<'_> {
+    fn into_diagnostic(
+        self,
+        sess: &ParseSess,
+    ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
+        let mut diag = sess.struct_err(fluent::trait_selection::negative_positive_conflict);
+        diag.set_arg("trait_desc", self.trait_desc);
+        diag.set_arg(
+            "self_desc",
+            self.self_desc.clone().map_or_else(|| String::from("none"), |ty| ty),
+        );
+        diag.set_span(self.impl_span);
+        diag.code(rustc_errors::error_code!(E0751));
+        match self.negative_impl_span {
+            Ok(span) => {
+                diag.span_label(span, fluent::trait_selection::negative_implementation_here);
+            }
+            Err(cname) => {
+                diag.note(fluent::trait_selection::negative_implementation_in_crate);
+                diag.set_arg("negative_impl_cname", cname.to_string());
+            }
+        }
+        match self.positive_impl_span {
+            Ok(span) => {
+                diag.span_label(span, fluent::trait_selection::positive_implementation_here);
+            }
+            Err(cname) => {
+                diag.note(fluent::trait_selection::positive_implementation_in_crate);
+                diag.set_arg("positive_impl_cname", cname.to_string());
+            }
+        }
+        diag
+    }
+}
index 9d30374f8b8aeac6bb0641558454f4f1c9c0bf46..ba403ab2da2bcd5e5951afbca84c795c10b11f0b 100644 (file)
@@ -24,6 +24,13 @@ fn type_is_copy_modulo_regions(
         span: Span,
     ) -> bool;
 
+    fn type_is_sized_modulo_regions(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        ty: Ty<'tcx>,
+        span: Span,
+    ) -> bool;
+
     fn partially_normalize_associated_types_in<T>(
         &self,
         cause: ObligationCause<'tcx>,
@@ -74,6 +81,16 @@ fn type_is_copy_modulo_regions(
         traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id, span)
     }
 
+    fn type_is_sized_modulo_regions(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        ty: Ty<'tcx>,
+        span: Span,
+    ) -> bool {
+        let lang_item = self.tcx.require_lang_item(LangItem::Sized, None);
+        traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, lang_item, span)
+    }
+
     /// Normalizes associated types in `value`, potentially returning
     /// new obligations that must further be processed.
     fn partially_normalize_associated_types_in<T>(
index 77cc2c164c34c052ca381491d7262a928c429c8f..f039b1fca1817d1069e24d0f489bd659c644b259 100644 (file)
@@ -37,5 +37,6 @@
 extern crate smallvec;
 
 pub mod autoderef;
+pub mod errors;
 pub mod infer;
 pub mod traits;
index 4bab99355012e0792b8e3135040db1be28f11032..1223c7ced7abcb9e04bdaeb1b879ec240092bcf7 100644 (file)
@@ -3,6 +3,7 @@
 
 use super::*;
 
+use crate::errors::UnableToConstructConstantValue;
 use crate::infer::region_constraints::{Constraint, RegionConstraintData};
 use crate::infer::InferCtxt;
 use crate::traits::project::ProjectAndUnifyResult;
@@ -830,8 +831,11 @@ fn evaluate_nested_obligations(
                                 Ok(None) => {
                                     let tcx = self.tcx;
                                     let def_id = unevaluated.def.did;
-                                    let reported = tcx.sess.struct_span_err(tcx.def_span(def_id), &format!("unable to construct a constant value for the unevaluated constant {:?}", unevaluated)).emit();
-
+                                    let reported =
+                                        tcx.sess.emit_err(UnableToConstructConstantValue {
+                                            span: tcx.def_span(def_id),
+                                            unevaluated,
+                                        });
                                     Err(ErrorHandled::Reported(reported))
                                 }
                                 Err(err) => Err(err),
index c0700748c79f9d7df78b0bf21458e92ebd509974..26f8e7d34c6eac056f1b06a4563b0e7c33497906 100644 (file)
@@ -18,7 +18,6 @@
 /// obligations *could be* resolved if we wanted to.
 ///
 /// This also expects that `trait_ref` is fully normalized.
-#[instrument(level = "debug", skip(tcx))]
 pub fn codegen_fulfill_obligation<'tcx>(
     tcx: TyCtxt<'tcx>,
     (param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>),
@@ -74,7 +73,6 @@ pub fn codegen_fulfill_obligation<'tcx>(
         // (ouz-a) This is required for `type-alias-impl-trait/assoc-projection-ice.rs` to pass
         let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
 
-        debug!("Cache miss: {trait_ref:?} => {impl_source:?}");
         Ok(&*tcx.arena.alloc(impl_source))
     })
 }
index e4af7022239b83fa2492b0754ea1688096a76854..9b8bb9e36201c4b72dc9f857660a37cee7bcf64b 100644 (file)
@@ -349,7 +349,7 @@ fn report_selection_error(
                             message,
                             label,
                             note,
-                            enclosing_scope,
+                            parent_label,
                             append_const_msg,
                         } = self.on_unimplemented_note(trait_ref, &obligation);
                         let have_alt_message = message.is_some() || label.is_some();
@@ -450,12 +450,27 @@ fn report_selection_error(
                         {
                             "consider using `()`, or a `Result`".to_owned()
                         } else {
-                            format!(
-                                "{}the trait `{}` is not implemented for `{}`",
-                                pre_message,
-                                trait_predicate.print_modifiers_and_trait_path(),
-                                trait_ref.skip_binder().self_ty(),
-                            )
+                            let ty_desc = match trait_ref.skip_binder().self_ty().kind() {
+                                ty::FnDef(_, _) => Some("fn item"),
+                                ty::Closure(_, _) => Some("closure"),
+                                _ => None,
+                            };
+
+                            match ty_desc {
+                                Some(desc) => format!(
+                                    "{}the trait `{}` is not implemented for {} `{}`",
+                                    pre_message,
+                                    trait_predicate.print_modifiers_and_trait_path(),
+                                    desc,
+                                    trait_ref.skip_binder().self_ty(),
+                                ),
+                                None => format!(
+                                    "{}the trait `{}` is not implemented for `{}`",
+                                    pre_message,
+                                    trait_predicate.print_modifiers_and_trait_path(),
+                                    trait_ref.skip_binder().self_ty(),
+                                ),
+                            }
                         };
 
                         if self.suggest_add_reference_to_arg(
@@ -515,7 +530,7 @@ fn report_selection_error(
                             // If it has a custom `#[rustc_on_unimplemented]` note, let's display it
                             err.note(s.as_str());
                         }
-                        if let Some(ref s) = enclosing_scope {
+                        if let Some(ref s) = parent_label {
                             let body = tcx
                                 .hir()
                                 .opt_local_def_id(obligation.cause.body_id)
@@ -524,11 +539,7 @@ fn report_selection_error(
                                         hir_id: obligation.cause.body_id,
                                     })
                                 });
-
-                            let enclosing_scope_span =
-                                tcx.hir().span_with_body(tcx.hir().local_def_id_to_hir_id(body));
-
-                            err.span_label(enclosing_scope_span, s);
+                            err.span_label(tcx.def_span(body), s);
                         }
 
                         self.suggest_floating_point_literal(&obligation, &mut err, &trait_ref);
@@ -1805,13 +1816,21 @@ fn report_similar_impl_candidates(
                 return false;
             }
             if candidates.len() == 1 {
+                let ty_desc = match candidates[0].self_ty().kind() {
+                    ty::FnPtr(_) => Some("fn pointer"),
+                    _ => None,
+                };
+                let the_desc = match ty_desc {
+                    Some(desc) => format!(" implemented for {} `", desc),
+                    None => " implemented for `".to_string(),
+                };
                 err.highlighted_help(vec![
                     (
                         format!("the trait `{}` ", candidates[0].print_only_trait_path()),
                         Style::NoStyle,
                     ),
                     ("is".to_string(), Style::Highlight),
-                    (" implemented for `".to_string(), Style::NoStyle),
+                    (the_desc, Style::NoStyle),
                     (candidates[0].self_ty().to_string(), Style::Highlight),
                     ("`".to_string(), Style::NoStyle),
                 ]);
@@ -2014,7 +2033,7 @@ fn maybe_report_ambiguity(
         let predicate = self.resolve_vars_if_possible(obligation.predicate);
         let span = obligation.cause.span;
 
-        debug!(?predicate, obligation.cause.code = tracing::field::debug(&obligation.cause.code()));
+        debug!(?predicate, obligation.cause.code = ?obligation.cause.code());
 
         // Ambiguity errors are often caused as fallout from earlier errors.
         // We ignore them if this `infcx` is tainted in some cases below.
@@ -2191,12 +2210,12 @@ fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
                         && let [
                             ..,
                             trait_path_segment @ hir::PathSegment {
-                                res: Some(rustc_hir::def::Res::Def(rustc_hir::def::DefKind::Trait, trait_id)),
+                                res: rustc_hir::def::Res::Def(rustc_hir::def::DefKind::Trait, trait_id),
                                 ..
                             },
                             hir::PathSegment {
                                 ident: assoc_item_name,
-                                res: Some(rustc_hir::def::Res::Def(_, item_id)),
+                                res: rustc_hir::def::Res::Def(_, item_id),
                                 ..
                             }
                         ] = path.segments
index 02adae5bde157f50c086e0b9c3784b1a9d126c0b..b012073f7719d2d4270ea7363483b9c393b75fcb 100644 (file)
@@ -774,7 +774,7 @@ fn get_closure_name(&self, def_id: DefId, err: &mut Diagnostic, msg: &str) -> Op
             // Get the local name of this closure. This can be inaccurate because
             // of the possibility of reassignment, but this should be good enough.
             match &kind {
-                hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, ident, None) => {
+                hir::PatKind::Binding(hir::BindingAnnotation::NONE, _, ident, None) => {
                     Some(ident.name)
                 }
                 _ => {
index d840677f1ca8b0d4c5e52d694a231789915a13b4..3763a98c488b766c11fc1e863a17e29f1c5c23d2 100644 (file)
@@ -135,7 +135,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
     /// `SomeTrait` or a where-clause that lets us unify `$0` with
     /// something concrete. If this fails, we'll unify `$0` with
     /// `projection_ty` again.
-    #[tracing::instrument(level = "debug", skip(self, infcx, param_env, cause))]
+    #[instrument(level = "debug", skip(self, infcx, param_env, cause))]
     fn normalize_projection_type(
         &mut self,
         infcx: &InferCtxt<'_, 'tcx>,
index e11ea7751aa731e93417895ba681a7f93a265bd2..14e078096783e39239cdb186325910f9df61dd8b 100644 (file)
@@ -23,6 +23,7 @@
 mod util;
 pub mod wf;
 
+use crate::errors::DumpVTableEntries;
 use crate::infer::outlives::env::OutlivesEnvironment;
 use crate::infer::{InferCtxt, TyCtxtInferExt};
 use crate::traits::error_reporting::InferCtxtExt as _;
@@ -763,8 +764,11 @@ fn dump_vtable_entries<'tcx>(
     trait_ref: ty::PolyTraitRef<'tcx>,
     entries: &[VtblEntry<'tcx>],
 ) {
-    let msg = format!("vtable entries for `{}`: {:#?}", trait_ref, entries);
-    tcx.sess.struct_span_err(sp, &msg).emit();
+    tcx.sess.emit_err(DumpVTableEntries {
+        span: sp,
+        trait_ref,
+        entries: format!("{:#?}", entries),
+    });
 }
 
 fn own_existential_vtable_entries<'tcx>(
index 9227bbf011dbfcb2c2d43475778289ed38f2bbf5..4a4f34b768059355ed43e33e7acf594c3e243f96 100644 (file)
@@ -8,6 +8,10 @@
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 
+use crate::errors::{
+    EmptyOnClauseInOnUnimplemented, InvalidOnClauseInOnUnimplemented, NoValueInOnUnimplemented,
+};
+
 #[derive(Clone, Debug)]
 pub struct OnUnimplementedFormatString(Symbol);
 
@@ -18,7 +22,7 @@ pub struct OnUnimplementedDirective {
     pub message: Option<OnUnimplementedFormatString>,
     pub label: Option<OnUnimplementedFormatString>,
     pub note: Option<OnUnimplementedFormatString>,
-    pub enclosing_scope: Option<OnUnimplementedFormatString>,
+    pub parent_label: Option<OnUnimplementedFormatString>,
     pub append_const_msg: Option<Option<Symbol>>,
 }
 
@@ -27,7 +31,7 @@ pub struct OnUnimplementedNote {
     pub message: Option<String>,
     pub label: Option<String>,
     pub note: Option<String>,
-    pub enclosing_scope: Option<String>,
+    pub parent_label: Option<String>,
     /// Append a message for `~const Trait` errors. `None` means not requested and
     /// should fallback to a generic message, `Some(None)` suggests using the default
     /// appended message, `Some(Some(s))` suggests use the `s` message instead of the
@@ -35,21 +39,6 @@ pub struct OnUnimplementedNote {
     pub append_const_msg: Option<Option<Symbol>>,
 }
 
-fn parse_error(
-    tcx: TyCtxt<'_>,
-    span: Span,
-    message: &str,
-    label: &str,
-    note: Option<&str>,
-) -> ErrorGuaranteed {
-    let mut diag = struct_span_err!(tcx.sess, span, E0232, "{}", message);
-    diag.span_label(span, label);
-    if let Some(note) = note {
-        diag.note(note);
-    }
-    diag.emit()
-}
-
 impl<'tcx> OnUnimplementedDirective {
     fn parse(
         tcx: TyCtxt<'tcx>,
@@ -70,25 +59,9 @@ fn parse(
         } else {
             let cond = item_iter
                 .next()
-                .ok_or_else(|| {
-                    parse_error(
-                        tcx,
-                        span,
-                        "empty `on`-clause in `#[rustc_on_unimplemented]`",
-                        "empty on-clause here",
-                        None,
-                    )
-                })?
+                .ok_or_else(|| tcx.sess.emit_err(EmptyOnClauseInOnUnimplemented { span }))?
                 .meta_item()
-                .ok_or_else(|| {
-                    parse_error(
-                        tcx,
-                        span,
-                        "invalid `on`-clause in `#[rustc_on_unimplemented]`",
-                        "invalid on-clause here",
-                        None,
-                    )
-                })?;
+                .ok_or_else(|| tcx.sess.emit_err(InvalidOnClauseInOnUnimplemented { span }))?;
             attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |cfg| {
                 if let Some(value) = cfg.value && let Err(guar) = parse_value(value) {
                     errored = Some(guar);
@@ -101,7 +74,7 @@ fn parse(
         let mut message = None;
         let mut label = None;
         let mut note = None;
-        let mut enclosing_scope = None;
+        let mut parent_label = None;
         let mut subcommands = vec![];
         let mut append_const_msg = None;
 
@@ -121,9 +94,9 @@ fn parse(
                     note = parse_value(note_)?;
                     continue;
                 }
-            } else if item.has_name(sym::enclosing_scope) && enclosing_scope.is_none() {
-                if let Some(enclosing_scope_) = item.value_str() {
-                    enclosing_scope = parse_value(enclosing_scope_)?;
+            } else if item.has_name(sym::parent_label) && parent_label.is_none() {
+                if let Some(parent_label_) = item.value_str() {
+                    parent_label = parse_value(parent_label_)?;
                     continue;
                 }
             } else if item.has_name(sym::on)
@@ -150,13 +123,7 @@ fn parse(
             }
 
             // nothing found
-            parse_error(
-                tcx,
-                item.span(),
-                "this attribute must have a valid value",
-                "expected value here",
-                Some(r#"eg `#[rustc_on_unimplemented(message="foo")]`"#),
-            );
+            tcx.sess.emit_err(NoValueInOnUnimplemented { span: item.span() });
         }
 
         if let Some(reported) = errored {
@@ -168,7 +135,7 @@ fn parse(
                 message,
                 label,
                 note,
-                enclosing_scope,
+                parent_label,
                 append_const_msg,
             })
         }
@@ -193,7 +160,7 @@ pub fn of_item(tcx: TyCtxt<'tcx>, item_def_id: DefId) -> Result<Option<Self>, Er
                     attr.span,
                 )?),
                 note: None,
-                enclosing_scope: None,
+                parent_label: None,
                 append_const_msg: None,
             }))
         } else {
@@ -214,7 +181,7 @@ pub fn evaluate(
         let mut message = None;
         let mut label = None;
         let mut note = None;
-        let mut enclosing_scope = None;
+        let mut parent_label = None;
         let mut append_const_msg = None;
         info!("evaluate({:?}, trait_ref={:?}, options={:?})", self, trait_ref, options);
 
@@ -250,8 +217,8 @@ pub fn evaluate(
                 note = Some(note_.clone());
             }
 
-            if let Some(ref enclosing_scope_) = command.enclosing_scope {
-                enclosing_scope = Some(enclosing_scope_.clone());
+            if let Some(ref parent_label_) = command.parent_label {
+                parent_label = Some(parent_label_.clone());
             }
 
             append_const_msg = command.append_const_msg;
@@ -261,7 +228,7 @@ pub fn evaluate(
             label: label.map(|l| l.format(tcx, trait_ref, &options_map)),
             message: message.map(|m| m.format(tcx, trait_ref, &options_map)),
             note: note.map(|n| n.format(tcx, trait_ref, &options_map)),
-            enclosing_scope: enclosing_scope.map(|e_s| e_s.format(tcx, trait_ref, &options_map)),
+            parent_label: parent_label.map(|e_s| e_s.format(tcx, trait_ref, &options_map)),
             append_const_msg,
         }
     }
index 444ca6471e2e4d51696f25da4abfd4a1881e4c76..398635674abcfd19a69c7de02f88af6787e209f9 100644 (file)
@@ -231,7 +231,7 @@ pub(super) fn poly_project_and_unify_type<'cx, 'tcx>(
 /// If successful, this may result in additional obligations.
 ///
 /// See [poly_project_and_unify_type] for an explanation of the return value.
-#[tracing::instrument(level = "debug", skip(selcx))]
+#[instrument(level = "debug", skip(selcx))]
 fn project_and_unify_type<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligation: &ProjectionObligation<'tcx>,
@@ -1206,7 +1206,7 @@ fn with_addl_obligations(mut self, mut obligations: Vec<PredicateObligation<'tcx
 ///
 /// IMPORTANT:
 /// - `obligation` must be fully normalized
-#[tracing::instrument(level = "info", skip(selcx))]
+#[instrument(level = "info", skip(selcx))]
 fn project<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
@@ -1368,7 +1368,7 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>(
     );
 }
 
-#[tracing::instrument(
+#[instrument(
     level = "debug",
     skip(selcx, candidate_set, ctor, env_predicates, potentially_unnormalized_candidates)
 )]
@@ -1419,7 +1419,7 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>(
     }
 }
 
-#[tracing::instrument(level = "debug", skip(selcx, obligation, candidate_set))]
+#[instrument(level = "debug", skip(selcx, obligation, candidate_set))]
 fn assemble_candidates_from_impls<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
index d67bd6292b434534556ea19f1896f3597294e377..e84c462ca816195e39badb321ed16c0a2135404b 100644 (file)
@@ -28,7 +28,7 @@
 use super::{EvaluatedCandidate, SelectionCandidateSet, SelectionContext, TraitObligationStack};
 
 impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
-    #[instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self), ret)]
     pub(super) fn candidate_from_obligation<'o>(
         &mut self,
         stack: &TraitObligationStack<'o, 'tcx>,
@@ -48,7 +48,7 @@ pub(super) fn candidate_from_obligation<'o>(
         if let Some(c) =
             self.check_candidate_cache(stack.obligation.param_env, cache_fresh_trait_pred)
         {
-            debug!(candidate = ?c, "CACHE HIT");
+            debug!("CACHE HIT");
             return c;
         }
 
@@ -61,7 +61,7 @@ pub(super) fn candidate_from_obligation<'o>(
         let (candidate, dep_node) =
             self.in_task(|this| this.candidate_from_obligation_no_cache(stack));
 
-        debug!(?candidate, "CACHE MISS");
+        debug!("CACHE MISS");
         self.insert_candidate_cache(
             stack.obligation.param_env,
             cache_fresh_trait_pred,
@@ -337,7 +337,7 @@ pub(super) fn assemble_candidates<'o>(
         Ok(candidates)
     }
 
-    #[tracing::instrument(level = "debug", skip(self, candidates))]
+    #[instrument(level = "debug", skip(self, candidates))]
     fn assemble_candidates_from_projected_tys(
         &mut self,
         obligation: &TraitObligation<'tcx>,
@@ -367,7 +367,7 @@ fn assemble_candidates_from_projected_tys(
     /// supplied to find out whether it is listed among them.
     ///
     /// Never affects the inference environment.
-    #[tracing::instrument(level = "debug", skip(self, stack, candidates))]
+    #[instrument(level = "debug", skip(self, stack, candidates))]
     fn assemble_candidates_from_caller_bounds<'o>(
         &mut self,
         stack: &TraitObligationStack<'o, 'tcx>,
@@ -880,7 +880,7 @@ fn assemble_candidates_for_unsizing(
         };
     }
 
-    #[tracing::instrument(level = "debug", skip(self, obligation, candidates))]
+    #[instrument(level = "debug", skip(self, obligation, candidates))]
     fn assemble_candidates_for_transmutability(
         &mut self,
         obligation: &TraitObligation<'tcx>,
@@ -898,7 +898,7 @@ fn assemble_candidates_for_transmutability(
         candidates.vec.push(TransmutabilityCandidate);
     }
 
-    #[tracing::instrument(level = "debug", skip(self, obligation, candidates))]
+    #[instrument(level = "debug", skip(self, obligation, candidates))]
     fn assemble_candidates_for_trait_alias(
         &mut self,
         obligation: &TraitObligation<'tcx>,
@@ -917,7 +917,7 @@ fn assemble_candidates_for_trait_alias(
 
     /// Assembles the trait which are built-in to the language itself:
     /// `Copy`, `Clone` and `Sized`.
-    #[tracing::instrument(level = "debug", skip(self, candidates))]
+    #[instrument(level = "debug", skip(self, candidates))]
     fn assemble_builtin_bound_candidates(
         &mut self,
         conditions: BuiltinImplConditions<'tcx>,
index 2a1099fc82abc5fe6312d03640aa514005294c96..e44f66657955e694e5e5c4a40dfda4a87b586324 100644 (file)
@@ -279,29 +279,17 @@ fn confirm_transmutability_candidate(
         let predicate = obligation.predicate;
 
         let type_at = |i| predicate.map_bound(|p| p.trait_ref.substs.type_at(i));
-        let bool_at = |i| {
-            predicate
-                .skip_binder()
-                .trait_ref
-                .substs
-                .const_at(i)
-                .try_eval_bool(self.tcx(), obligation.param_env)
-                .unwrap_or(true)
-        };
+        let const_at = |i| predicate.skip_binder().trait_ref.substs.const_at(i);
 
         let src_and_dst = predicate.map_bound(|p| rustc_transmute::Types {
-            src: p.trait_ref.substs.type_at(1),
             dst: p.trait_ref.substs.type_at(0),
+            src: p.trait_ref.substs.type_at(1),
         });
 
         let scope = type_at(2).skip_binder();
 
-        let assume = rustc_transmute::Assume {
-            alignment: bool_at(3),
-            lifetimes: bool_at(4),
-            validity: bool_at(5),
-            visibility: bool_at(6),
-        };
+        let assume =
+            rustc_transmute::Assume::from_const(self.infcx.tcx, obligation.param_env, const_at(3));
 
         let cause = obligation.cause.clone();
 
index 46b50dd92f1ef7a3ed17fa20b66ccaf9b7b7657b..5da8cfab0b13b77102197cf235c3503b1cef9533 100644 (file)
@@ -295,7 +295,7 @@ pub fn is_intercrate(&self) -> bool {
 
     /// Attempts to satisfy the obligation. If successful, this will affect the surrounding
     /// type environment by performing unification.
-    #[instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self), ret)]
     pub fn select(
         &mut self,
         obligation: &TraitObligation<'tcx>,
@@ -325,10 +325,7 @@ pub fn select(
                 Err(SelectionError::Overflow(OverflowError::Canonical))
             }
             Err(e) => Err(e),
-            Ok(candidate) => {
-                debug!(?candidate, "confirmed");
-                Ok(Some(candidate))
-            }
+            Ok(candidate) => Ok(Some(candidate)),
         }
     }
 
@@ -435,6 +432,7 @@ fn evaluate_predicates_recursively<'o, I>(
         level = "debug",
         skip(self, previous_stack),
         fields(previous_stack = ?previous_stack.head())
+        ret,
     )]
     fn evaluate_predicate_recursively<'o>(
         &mut self,
@@ -450,7 +448,7 @@ fn evaluate_predicate_recursively<'o>(
             None => self.check_recursion_limit(&obligation, &obligation)?,
         }
 
-        let result = ensure_sufficient_stack(|| {
+        ensure_sufficient_stack(|| {
             let bound_predicate = obligation.predicate.kind();
             match bound_predicate.skip_binder() {
                 ty::PredicateKind::Trait(t) => {
@@ -760,14 +758,10 @@ fn evaluate_predicate_recursively<'o>(
                     bug!("TypeWellFormedFromEnv is only used for chalk")
                 }
             }
-        });
-
-        debug!("finished: {:?} from {:?}", result, obligation);
-
-        result
+        })
     }
 
-    #[instrument(skip(self, previous_stack), level = "debug")]
+    #[instrument(skip(self, previous_stack), level = "debug", ret)]
     fn evaluate_trait_predicate_recursively<'o>(
         &mut self,
         previous_stack: TraitObligationStackList<'o, 'tcx>,
@@ -798,12 +792,12 @@ fn evaluate_trait_predicate_recursively<'o>(
         // If a trait predicate is in the (local or global) evaluation cache,
         // then we know it holds without cycles.
         if let Some(result) = self.check_evaluation_cache(param_env, fresh_trait_pred) {
-            debug!(?result, "CACHE HIT");
+            debug!("CACHE HIT");
             return Ok(result);
         }
 
         if let Some(result) = stack.cache().get_provisional(fresh_trait_pred) {
-            debug!(?result, "PROVISIONAL CACHE HIT");
+            debug!("PROVISIONAL CACHE HIT");
             stack.update_reached_depth(result.reached_depth);
             return Ok(result.result);
         }
@@ -826,11 +820,11 @@ fn evaluate_trait_predicate_recursively<'o>(
 
         let reached_depth = stack.reached_depth.get();
         if reached_depth >= stack.depth {
-            debug!(?result, "CACHE MISS");
+            debug!("CACHE MISS");
             self.insert_evaluation_cache(param_env, fresh_trait_pred, dep_node, result);
             stack.cache().on_completion(stack.dfn);
         } else {
-            debug!(?result, "PROVISIONAL");
+            debug!("PROVISIONAL");
             debug!(
                 "caching provisionally because {:?} \
                  is a cycle participant (at depth {}, reached depth {})",
@@ -1023,7 +1017,8 @@ fn coinductive_predicate(&self, predicate: ty::Predicate<'tcx>) -> bool {
     #[instrument(
         level = "debug",
         skip(self, stack),
-        fields(depth = stack.obligation.recursion_depth)
+        fields(depth = stack.obligation.recursion_depth),
+        ret
     )]
     fn evaluate_candidate<'o>(
         &mut self,
@@ -1056,7 +1051,6 @@ fn evaluate_candidate<'o>(
             result = result.max(EvaluatedToOkModuloRegions);
         }
 
-        debug!(?result);
         Ok(result)
     }
 
@@ -1405,7 +1399,7 @@ fn insert_candidate_cache(
     /// a projection, look at the bounds of `T::Bar`, see if we can find a
     /// `Baz` bound. We return indexes into the list returned by
     /// `tcx.item_bounds` for any applicable bounds.
-    #[instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self), ret)]
     fn match_projection_obligation_against_definition_bounds(
         &mut self,
         obligation: &TraitObligation<'tcx>,
@@ -1435,7 +1429,7 @@ fn match_projection_obligation_against_definition_bounds(
         // unnecessary ambiguity.
         let mut distinct_normalized_bounds = FxHashSet::default();
 
-        let matching_bounds = bounds
+        bounds
             .iter()
             .enumerate()
             .filter_map(|(idx, bound)| {
@@ -1462,10 +1456,7 @@ fn match_projection_obligation_against_definition_bounds(
                 }
                 None
             })
-            .collect();
-
-        debug!(?matching_bounds);
-        matching_bounds
+            .collect()
     }
 
     /// Equates the trait in `obligation` with trait bound. If the two traits
@@ -2153,7 +2144,7 @@ fn rematch_impl(
         }
     }
 
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self), ret)]
     fn match_impl(
         &mut self,
         impl_def_id: DefId,
@@ -2194,17 +2185,16 @@ fn match_impl(
             .at(&cause, obligation.param_env)
             .define_opaque_types(false)
             .eq(placeholder_obligation_trait_ref, impl_trait_ref)
-            .map_err(|e| debug!("match_impl: failed eq_trait_refs due to `{}`", e))?;
+            .map_err(|e| debug!("match_impl: failed eq_trait_refs due to `{e}`"))?;
         nested_obligations.extend(obligations);
 
         if !self.intercrate
             && self.tcx().impl_polarity(impl_def_id) == ty::ImplPolarity::Reservation
         {
-            debug!("match_impl: reservation impls only apply in intercrate mode");
+            debug!("reservation impls only apply in intercrate mode");
             return Err(());
         }
 
-        debug!(?impl_substs, ?nested_obligations, "match_impl: success");
         Ok(Normalized { value: impl_substs, obligations: nested_obligations })
     }
 
@@ -2335,7 +2325,7 @@ fn generator_trait_ref_unnormalized(
     /// impl or trait. The obligations are substituted and fully
     /// normalized. This is used when confirming an impl or default
     /// impl.
-    #[tracing::instrument(level = "debug", skip(self, cause, param_env))]
+    #[instrument(level = "debug", skip(self, cause, param_env))]
     fn impl_or_trait_obligations(
         &mut self,
         cause: &ObligationCause<'tcx>,
index 0f76fef0eee228168c49a3d5128776dd1338574f..7d299e30ae041290a3760f6295a0fff0da46c452 100644 (file)
@@ -12,6 +12,7 @@
 pub mod specialization_graph;
 use specialization_graph::GraphExt;
 
+use crate::errors::NegativePositiveConflict;
 use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt};
 use crate::traits::select::IntercrateAmbiguityCause;
 use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause};
@@ -327,35 +328,13 @@ fn report_negative_positive_conflict(
     positive_impl_def_id: DefId,
     sg: &mut specialization_graph::Graph,
 ) {
-    let impl_span = tcx.def_span(local_impl_def_id);
-
-    let mut err = struct_span_err!(
-        tcx.sess,
-        impl_span,
-        E0751,
-        "found both positive and negative implementation of trait `{}`{}:",
-        overlap.trait_desc,
-        overlap.self_desc.clone().map_or_else(String::new, |ty| format!(" for type `{}`", ty))
-    );
-
-    match tcx.span_of_impl(negative_impl_def_id) {
-        Ok(span) => {
-            err.span_label(span, "negative implementation here");
-        }
-        Err(cname) => {
-            err.note(&format!("negative implementation in crate `{}`", cname));
-        }
-    }
-
-    match tcx.span_of_impl(positive_impl_def_id) {
-        Ok(span) => {
-            err.span_label(span, "positive implementation here");
-        }
-        Err(cname) => {
-            err.note(&format!("positive implementation in crate `{}`", cname));
-        }
-    }
-
+    let mut err = tcx.sess.create_err(NegativePositiveConflict {
+        impl_span: tcx.def_span(local_impl_def_id),
+        trait_desc: &overlap.trait_desc,
+        self_desc: &overlap.self_desc,
+        negative_impl_span: tcx.span_of_impl(negative_impl_def_id),
+        positive_impl_span: tcx.span_of_impl(positive_impl_def_id),
+    });
     sg.has_errored = Some(err.emit());
 }
 
index 4bd179d23913143dd663bd7c7899677264f5c3ba..bb6009cb22a37b2df733bb9019e164eae8d5288b 100644 (file)
@@ -841,7 +841,7 @@ pub fn object_region_bounds<'tcx>(
 ///
 /// Requires that trait definitions have been processed so that we can
 /// elaborate predicates and walk supertraits.
-#[instrument(skip(tcx, predicates), level = "debug")]
+#[instrument(skip(tcx, predicates), level = "debug", ret)]
 pub(crate) fn required_region_bounds<'tcx>(
     tcx: TyCtxt<'tcx>,
     erased_self_ty: Ty<'tcx>,
index 9dc96e08a8e27a271ed93681221d8259ca2df0b2..aa6fe7d241968ffd239887c4ddd93d3326268be3 100644 (file)
@@ -7,7 +7,8 @@ edition = "2021"
 
 [dependencies]
 tracing = "0.1"
-rustc_data_structures = { path = "../rustc_data_structures", optional = true}
+rustc_data_structures = { path = "../rustc_data_structures"}
+rustc_hir = { path = "../rustc_hir", optional = true}
 rustc_infer = { path = "../rustc_infer", optional = true}
 rustc_macros = { path = "../rustc_macros", optional = true}
 rustc_middle = { path = "../rustc_middle", optional = true}
@@ -17,7 +18,7 @@ rustc_target = { path = "../rustc_target", optional = true}
 [features]
 rustc = [
     "rustc_middle",
-    "rustc_data_structures",
+    "rustc_hir",
     "rustc_infer",
     "rustc_macros",
     "rustc_span",
index b60ea6e7a24f222e842c49bdda98d348c1ec83e3..b8922696e3067248fee95c81d28d042a623a7c4f 100644 (file)
@@ -104,7 +104,6 @@ pub(crate) fn bool() -> Self {
     }
 
     #[instrument(level = "debug")]
-    #[cfg_attr(feature = "rustc", allow(rustc::potential_query_instability))]
     pub(crate) fn from_nfa(nfa: Nfa<R>) -> Self {
         let Nfa { transitions: nfa_transitions, start: nfa_start, accepting: nfa_accepting } = nfa;
 
index f25e3c1fd8a3014c36d27f38b251d2d8ab510e9e..c2bc47bc043a0d358bf77a7826423b05cad1cedb 100644 (file)
@@ -119,8 +119,6 @@ pub(crate) fn concat(self, other: Self) -> Self {
 
         let mut transitions: Map<State, Map<Transition<R>, Set<State>>> = self.transitions;
 
-        // the iteration order doesn't matter
-        #[cfg_attr(feature = "rustc", allow(rustc::potential_query_instability))]
         for (source, transition) in other.transitions {
             let fix_state = |state| if state == other.start { self.accepting } else { state };
             let entry = transitions.entry(fix_state(source)).or_default();
@@ -142,8 +140,6 @@ pub(crate) fn union(self, other: Self) -> Self {
 
         let mut transitions: Map<State, Map<Transition<R>, Set<State>>> = self.transitions.clone();
 
-        // the iteration order doesn't matter
-        #[cfg_attr(feature = "rustc", allow(rustc::potential_query_instability))]
         for (&(mut source), transition) in other.transitions.iter() {
             // if source is starting state of `other`, replace with starting state of `self`
             if source == other.start {
@@ -152,8 +148,6 @@ pub(crate) fn union(self, other: Self) -> Self {
             let entry = transitions.entry(source).or_default();
             for (edge, destinations) in transition {
                 let entry = entry.entry(edge.clone()).or_default();
-                // the iteration order doesn't matter
-                #[cfg_attr(feature = "rustc", allow(rustc::potential_query_instability))]
                 for &(mut destination) in destinations {
                     // if dest is accepting state of `other`, replace with accepting state of `self`
                     if destination == other.accepting {
index 4ab6d3737c5959c31c39d1b5bd272ea662672ce2..211c813b8001c8ae626bc5f783213c3c83fc2010 100644 (file)
@@ -317,7 +317,7 @@ pub fn from_ty(ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> Result<Self, Err> {
                             tcx,
                         )?,
                         AdtKind::Enum => {
-                            tracing::trace!(?adt_def, "treeifying enum");
+                            trace!(?adt_def, "treeifying enum");
                             let mut tree = Tree::uninhabited();
 
                             for (idx, discr) in adt_def.discriminants(tcx) {
@@ -381,7 +381,7 @@ fn from_repr_c_variant(
             let clamp =
                 |align: Align| align.clamp(min_align, max_align).bytes().try_into().unwrap();
 
-            let variant_span = tracing::trace_span!(
+            let variant_span = trace_span!(
                 "treeifying variant",
                 min_align = ?min_align,
                 max_align = ?max_align,
@@ -396,22 +396,22 @@ fn from_repr_c_variant(
 
             // The layout of the variant is prefixed by the discriminant, if any.
             if let Some(discr) = discr {
-                tracing::trace!(?discr, "treeifying discriminant");
+                trace!(?discr, "treeifying discriminant");
                 let discr_layout = alloc::Layout::from_size_align(
                     layout_summary.discriminant_size,
                     clamp(layout_summary.discriminant_align),
                 )
                 .unwrap();
-                tracing::trace!(?discr_layout, "computed discriminant layout");
+                trace!(?discr_layout, "computed discriminant layout");
                 variant_layout = variant_layout.extend(discr_layout).unwrap().0;
                 tree = tree.then(Self::from_disr(discr, tcx, layout_summary.discriminant_size));
             }
 
             // Next come fields.
-            let fields_span = tracing::trace_span!("treeifying fields").entered();
+            let fields_span = trace_span!("treeifying fields").entered();
             for field_def in variant_def.fields.iter() {
                 let field_ty = field_def.ty(tcx, substs_ref);
-                let _span = tracing::trace_span!("treeifying field", field = ?field_ty).entered();
+                let _span = trace_span!("treeifying field", field = ?field_ty).entered();
 
                 // begin with the field's visibility
                 tree = tree.then(Self::def(Def::Field(field_def)));
@@ -434,7 +434,7 @@ fn from_repr_c_variant(
             drop(fields_span);
 
             // finally: padding
-            let padding_span = tracing::trace_span!("adding trailing padding").entered();
+            let padding_span = trace_span!("adding trailing padding").entered();
             let padding_needed = layout_summary.total_size - variant_layout.size();
             if padding_needed > 0 {
                 tree = tree.then(Self::padding(padding_needed));
@@ -467,7 +467,7 @@ fn layout_of<'tcx>(
             layout.align().abi.bytes().try_into().unwrap(),
         )
         .unwrap();
-        tracing::trace!(?ty, ?layout, "computed layout for type");
+        trace!(?ty, ?layout, "computed layout for type");
         Ok(layout)
     }
 }
index 89b1ce5abe9e80d7a635d584ea7f2cf987964222..64cd70d3678777920897b2330d14b0b28d26c3fd 100644 (file)
@@ -6,11 +6,7 @@
 #[macro_use]
 extern crate tracing;
 
-#[cfg(feature = "rustc")]
-pub(crate) use rustc_data_structures::fx::{FxHashMap as Map, FxHashSet as Set};
-
-#[cfg(not(feature = "rustc"))]
-pub(crate) use std::collections::{HashMap as Map, HashSet as Set};
+pub(crate) use rustc_data_structures::fx::{FxIndexMap as Map, FxIndexSet as Set};
 
 pub(crate) mod layout;
 pub(crate) mod maybe_transmutable;
@@ -19,8 +15,8 @@
 pub struct Assume {
     pub alignment: bool,
     pub lifetimes: bool,
+    pub safety: bool,
     pub validity: bool,
-    pub visibility: bool,
 }
 
 /// The type encodes answers to the question: "Are these types transmutable?"
@@ -62,11 +58,17 @@ pub enum Reason {
 
 #[cfg(feature = "rustc")]
 mod rustc {
+    use super::*;
+
+    use rustc_hir::lang_items::LangItem;
     use rustc_infer::infer::InferCtxt;
     use rustc_macros::{TypeFoldable, TypeVisitable};
     use rustc_middle::traits::ObligationCause;
     use rustc_middle::ty::Binder;
+    use rustc_middle::ty::Const;
+    use rustc_middle::ty::ParamEnv;
     use rustc_middle::ty::Ty;
+    use rustc_middle::ty::TyCtxt;
 
     /// The source and destination types of a transmutation.
     #[derive(TypeFoldable, TypeVisitable, Debug, Clone, Copy)]
@@ -106,6 +108,54 @@ pub fn is_transmutable(
             .answer()
         }
     }
+
+    impl Assume {
+        /// Constructs an `Assume` from a given const-`Assume`.
+        pub fn from_const<'tcx>(
+            tcx: TyCtxt<'tcx>,
+            param_env: ParamEnv<'tcx>,
+            c: Const<'tcx>,
+        ) -> Self {
+            use rustc_middle::ty::ScalarInt;
+            use rustc_middle::ty::TypeVisitable;
+            use rustc_span::symbol::sym;
+
+            let c = c.eval(tcx, param_env);
+
+            if let Some(err) = c.error_reported() {
+                return Self { alignment: true, lifetimes: true, safety: true, validity: true };
+            }
+
+            let adt_def = c.ty().ty_adt_def().expect("The given `Const` must be an ADT.");
+
+            assert_eq!(
+                tcx.require_lang_item(LangItem::TransmuteOpts, None),
+                adt_def.did(),
+                "The given `Const` was not marked with the `{}` lang item.",
+                LangItem::TransmuteOpts.name(),
+            );
+
+            let variant = adt_def.non_enum_variant();
+            let fields = c.to_valtree().unwrap_branch();
+
+            let get_field = |name| {
+                let (field_idx, _) = variant
+                    .fields
+                    .iter()
+                    .enumerate()
+                    .find(|(_, field_def)| name == field_def.name)
+                    .expect(&format!("There were no fields named `{name}`."));
+                fields[field_idx].unwrap_leaf() == ScalarInt::TRUE
+            };
+
+            Self {
+                alignment: get_field(sym::alignment),
+                lifetimes: get_field(sym::lifetimes),
+                safety: get_field(sym::safety),
+                validity: get_field(sym::validity),
+            }
+        }
+    }
 }
 
 #[cfg(feature = "rustc")]
index 076d922d1b72b4157a47dd296dc15a3007252d8b..1186eac37abd9083144470f235b0f3965153a06d 100644 (file)
@@ -105,12 +105,12 @@ impl<C> MaybeTransmutableQuery<Tree<<C as QueryContext>::Def, <C as QueryContext
     #[inline(always)]
     #[instrument(level = "debug", skip(self), fields(src = ?self.src, dst = ?self.dst))]
     pub(crate) fn answer(self) -> Answer<<C as QueryContext>::Ref> {
-        let assume_visibility = self.assume.visibility;
+        let assume_visibility = self.assume.safety;
         let query_or_answer = self.map_layouts(|src, dst, scope, context| {
             // Remove all `Def` nodes from `src`, without checking their visibility.
             let src = src.prune(&|def| true);
 
-            tracing::trace!(?src, "pruned src");
+            trace!(?src, "pruned src");
 
             // Remove all `Def` nodes from `dst`, additionally...
             let dst = if assume_visibility {
@@ -121,7 +121,7 @@ pub(crate) fn answer(self) -> Answer<<C as QueryContext>::Ref> {
                 dst.prune(&|def| context.is_accessible_from(def, scope))
             };
 
-            tracing::trace!(?dst, "pruned dst");
+            trace!(?dst, "pruned dst");
 
             // Convert `src` from a tree-based representation to an NFA-based representation.
             // If the conversion fails because `src` is uninhabited, conclude that the transmutation
index 9c2cf4c9a92384821dc5c356372d351982213b83..adab343ac98aaa4b225a4b2bcb790d3000f3c2ea 100644 (file)
@@ -82,7 +82,7 @@ fn is_accessible_from(&self, def: Self::Def, scope: Self::Scope) -> bool {
                 false
             };
 
-            tracing::trace!(?ret, "ret");
+            trace!(?ret, "ret");
             ret
         }
 
index d9d125687f6566921a0d86dca9d0954e10b8c2e6..4d5772a4f2ea5d17366b852eca4418e40d0582f3 100644 (file)
@@ -13,7 +13,7 @@ fn should_permit_identity_transmutation_tree() {
             layout::Tree::<Def, !>::bool(),
             layout::Tree::<Def, !>::bool(),
             (),
-            crate::Assume { alignment: false, lifetimes: false, validity: true, visibility: false },
+            crate::Assume { alignment: false, lifetimes: false, validity: true, safety: false },
             UltraMinimal,
         )
         .answer();
@@ -26,7 +26,7 @@ fn should_permit_identity_transmutation_dfa() {
             layout::Dfa::<!>::bool(),
             layout::Dfa::<!>::bool(),
             (),
-            crate::Assume { alignment: false, lifetimes: false, validity: true, visibility: false },
+            crate::Assume { alignment: false, lifetimes: false, validity: true, safety: false },
             UltraMinimal,
         )
         .answer();
index 16c4d429129a9d499ba5c8524943ba6f520d899e..bb6b3e1ff5d7482f0700b3d324819ae2df70f3be 100644 (file)
@@ -155,9 +155,9 @@ fn pat_is_poly(&mut self, pat: &thir::Pat<'tcx>) -> bool {
                     return true;
                 }
 
-                match pat.kind.as_ref() {
+                match pat.kind {
                     thir::PatKind::Constant { value } => value.has_param_types_or_consts(),
-                    thir::PatKind::Range(thir::PatRange { lo, hi, .. }) => {
+                    thir::PatKind::Range(box thir::PatRange { lo, hi, .. }) => {
                         lo.has_param_types_or_consts() || hi.has_param_types_or_consts()
                     }
                     _ => false,
index bd1d568cd9a051079bae294ec74562a557c371ce..661e413fc5b8170defb0d06724fc0b62710b4573 100644 (file)
@@ -15,8 +15,6 @@
 use std::collections::BTreeMap;
 use std::ops::ControlFlow;
 
-use tracing::debug;
-
 // FIXME(#86795): `BoundVarsCollector` here should **NOT** be used
 // outside of `resolve_associated_item`. It's just to address #64494,
 // #83765, and #85848 which are creating bound types/regions that lose
index acfeefb4d12d535d9d7a03477a90049cde370ac6..9d640672cf92c8cd3bc2f7cc861c931a71b3edb7 100644 (file)
@@ -104,7 +104,6 @@ fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AdtSizedConstrain
 }
 
 /// See `ParamEnv` struct definition for details.
-#[instrument(level = "debug", skip(tcx))]
 fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
     // The param_env of an impl Trait type is its defining function's param_env
     if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) {
@@ -410,7 +409,6 @@ fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync {
 }
 
 /// Don't call this directly: use ``tcx.conservative_is_privately_uninhabited`` instead.
-#[instrument(level = "debug", skip(tcx))]
 pub fn conservative_is_privately_uninhabited_raw<'tcx>(
     tcx: TyCtxt<'tcx>,
     param_env_and: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
index ad0da4bed4573caf03c716f585f6bd8968a34a3b..afac75de2d96d8e831fab717695e89e896938bd7 100644 (file)
@@ -647,7 +647,7 @@ pub(crate) fn prohibit_explicit_late_bound_lifetimes(
                 multispan.push_span_label(span_late, note);
                 tcx.struct_span_lint_hir(
                     LATE_BOUND_LIFETIME_ARGUMENTS,
-                    args.args[0].id(),
+                    args.args[0].hir_id(),
                     multispan,
                     |lint| {
                         lint.build(msg).emit();
index 5c96f1c4623a6c9010633d79951b1af3023c96c4..14f04ddc8688bc2ae9b44b7ffa7e6e9ec61812c2 100644 (file)
@@ -144,7 +144,7 @@ enum ConvertedBindingKind<'a, 'tcx> {
 /// instantiated with some generic arguments providing `'a` explicitly,
 /// we taint those arguments with `ExplicitLateBound::Yes` so that we
 /// can provide an appropriate diagnostic later.
-#[derive(Copy, Clone, PartialEq)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 pub enum ExplicitLateBound {
     Yes,
     No,
@@ -167,7 +167,7 @@ pub(crate) enum GenericArgPosition {
 
 /// A marker denoting that the generic arguments that were
 /// provided did not match the respective generic parameters.
-#[derive(Clone, Default)]
+#[derive(Clone, Default, Debug)]
 pub struct GenericArgCountMismatch {
     /// Indicates whether a fatal error was reported (`Some`), or just a lint (`None`).
     pub reported: Option<ErrorGuaranteed>,
@@ -177,7 +177,7 @@ pub struct GenericArgCountMismatch {
 
 /// Decorates the result of a generic argument count mismatch
 /// check with whether explicit late bounds were provided.
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 pub struct GenericArgCountResult {
     pub explicit_late_bound: ExplicitLateBound,
     pub correct: Result<(), GenericArgCountMismatch>,
@@ -201,7 +201,7 @@ fn inferred_kind(
 }
 
 impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self), ret)]
     pub fn ast_region_to_region(
         &self,
         lifetime: &hir::Lifetime,
@@ -210,7 +210,7 @@ pub fn ast_region_to_region(
         let tcx = self.tcx();
         let lifetime_name = |def_id| tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id));
 
-        let r = match tcx.named_region(lifetime.hir_id) {
+        match tcx.named_region(lifetime.hir_id) {
             Some(rl::Region::Static) => tcx.lifetimes.re_static,
 
             Some(rl::Region::LateBound(debruijn, index, def_id)) => {
@@ -255,9 +255,7 @@ pub fn ast_region_to_region(
                     tcx.lifetimes.re_static
                 })
             }
-        };
-        debug!("ast_region_to_region(lifetime={:?}) yields {:?}", lifetime, r);
-        r
+        }
     }
 
     /// Given a path `path` that refers to an item `I` with the declared generics `decl_generics`,
@@ -317,7 +315,7 @@ pub fn ast_path_substs_for_ty(
     /// `[Vec<u8>, u8]` and `generic_args` are the arguments for the associated
     /// type itself: `['a]`. The returned `SubstsRef` concatenates these two
     /// lists: `[Vec<u8>, u8, 'a]`.
-    #[tracing::instrument(level = "debug", skip(self, span))]
+    #[instrument(level = "debug", skip(self, span), ret)]
     fn create_substs_for_ast_path<'a>(
         &self,
         span: Span,
@@ -399,7 +397,7 @@ fn provided_kind(
                     if has_default {
                         tcx.check_optional_stability(
                             param.def_id,
-                            Some(arg.id()),
+                            Some(arg.hir_id()),
                             arg.span(),
                             None,
                             AllowUnstable::No,
@@ -537,11 +535,6 @@ fn inferred_kind(
             &mut substs_ctx,
         );
 
-        debug!(
-            "create_substs_for_ast_path(generic_params={:?}, self_ty={:?}) -> {:?}",
-            generics, self_ty, substs
-        );
-
         (substs, arg_count)
     }
 
@@ -716,7 +709,7 @@ fn instantiate_poly_trait_ref_inner(
     /// where `'a` is a bound region at depth 0. Similarly, the `poly_trait_ref` would be
     /// `Bar<'a>`. The returned poly-trait-ref will have this binder instantiated explicitly,
     /// however.
-    #[tracing::instrument(level = "debug", skip(self, span, constness, bounds, speculative))]
+    #[instrument(level = "debug", skip(self, span, constness, bounds, speculative))]
     pub(crate) fn instantiate_poly_trait_ref(
         &self,
         trait_ref: &hir::TraitRef<'_>,
@@ -808,7 +801,7 @@ fn ast_path_to_mono_trait_ref(
         ty::TraitRef::new(trait_def_id, substs)
     }
 
-    #[tracing::instrument(level = "debug", skip(self, span))]
+    #[instrument(level = "debug", skip(self, span))]
     fn create_substs_for_ast_trait_ref<'a>(
         &self,
         span: Span,
@@ -922,7 +915,7 @@ pub(crate) fn add_implicitly_sized<'hir>(
     /// **A note on binders:** there is an implied binder around
     /// `param_ty` and `ast_bounds`. See `instantiate_poly_trait_ref`
     /// for more details.
-    #[tracing::instrument(level = "debug", skip(self, ast_bounds, bounds))]
+    #[instrument(level = "debug", skip(self, ast_bounds, bounds))]
     pub(crate) fn add_bounds<'hir, I: Iterator<Item = &'hir hir::GenericBound<'hir>>>(
         &self,
         param_ty: Ty<'tcx>,
@@ -1028,10 +1021,7 @@ fn compute_bounds_inner(
     /// **A note on binders:** given something like `T: for<'a> Iterator<Item = &'a u32>`, the
     /// `trait_ref` here will be `for<'a> T: Iterator`. The `binding` data however is from *inside*
     /// the binder (e.g., `&'a u32`) and hence may reference bound regions.
-    #[tracing::instrument(
-        level = "debug",
-        skip(self, bounds, speculative, dup_bindings, path_span)
-    )]
+    #[instrument(level = "debug", skip(self, bounds, speculative, dup_bindings, path_span))]
     fn add_predicates_for_ast_type_binding(
         &self,
         hir_ref_id: hir::HirId,
@@ -1123,8 +1113,8 @@ fn add_predicates_for_ast_type_binding(
             let ident = Ident::new(assoc_item.name, binding.item_name.span);
             let item_segment = hir::PathSegment {
                 ident,
-                hir_id: Some(binding.hir_id),
-                res: None,
+                hir_id: binding.hir_id,
+                res: Res::Err,
                 args: Some(binding.gen_args),
                 infer_args: false,
             };
@@ -1855,7 +1845,7 @@ pub fn associated_path_to_ty(
                                     [.., hir::PathSegment {
                                         ident,
                                         args,
-                                        res: Some(Res::Def(DefKind::Enum, _)),
+                                        res: Res::Def(DefKind::Enum, _),
                                         ..
                                     }, _] => (
                                         // We need to include the `::` in `Type::Variant::<Args>`
@@ -2137,24 +2127,22 @@ pub fn prohibit_generics<'a>(
             let types_and_spans: Vec<_> = segments
                 .clone()
                 .flat_map(|segment| {
-                    segment.res.and_then(|res| {
-                        if segment.args().args.is_empty() {
-                            None
-                        } else {
-                            Some((
-                            match res {
-                                Res::PrimTy(ty) => format!("{} `{}`", res.descr(), ty.name()),
+                    if segment.args().args.is_empty() {
+                        None
+                    } else {
+                        Some((
+                            match segment.res {
+                                Res::PrimTy(ty) => format!("{} `{}`", segment.res.descr(), ty.name()),
                                 Res::Def(_, def_id)
                                 if let Some(name) = self.tcx().opt_item_name(def_id) => {
-                                    format!("{} `{name}`", res.descr())
+                                    format!("{} `{name}`", segment.res.descr())
                                 }
                                 Res::Err => "this type".to_string(),
-                                _ => res.descr().to_string(),
+                                _ => segment.res.descr().to_string(),
                             },
                             segment.ident.span,
                         ))
-                        }
-                    })
+                    }
                 })
                 .collect();
             let this_type = match &types_and_spans[..] {
@@ -2599,7 +2587,7 @@ pub fn ast_ty_to_ty_in_path(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
 
     /// Turns a `hir::Ty` into a `Ty`. For diagnostics' purposes we keep track of whether trait
     /// objects are borrowed like `&dyn Trait` to avoid emitting redundant errors.
-    #[tracing::instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self), ret)]
     fn ast_ty_to_ty_inner(&self, ast_ty: &hir::Ty<'_>, borrowed: bool, in_path: bool) -> Ty<'tcx> {
         let tcx = self.tcx();
 
@@ -2703,8 +2691,6 @@ fn ast_ty_to_ty_inner(&self, ast_ty: &hir::Ty<'_>, borrowed: bool, in_path: bool
             hir::TyKind::Err => tcx.ty_error(),
         };
 
-        debug!(?result_ty);
-
         self.record_ty(ast_ty.hir_id, result_ty, ast_ty.span);
         result_ty
     }
index 2d50412007d909b493571c7d774bc4c82b729dd0..25bafdfe859b882af75dee0a021595a9db8f7670 100644 (file)
@@ -12,7 +12,7 @@
 };
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
-    #[instrument(skip(self), level = "debug")]
+    #[instrument(skip(self), level = "debug", ret)]
     pub fn check_match(
         &self,
         expr: &'tcx hir::Expr<'tcx>,
@@ -212,9 +212,7 @@ pub fn check_match(
         // We won't diverge unless the scrutinee or all arms diverge.
         self.diverges.set(scrut_diverges | all_arms_diverge);
 
-        let match_ty = coercion.complete(self);
-        debug!(?match_ty);
-        match_ty
+        coercion.complete(self)
     }
 
     /// When the previously checked expression (the scrutinee) diverges,
index 75f5aced85577ad2209fcd508d918acff5799dce..0d35c2479dda535a9e6d831b311b1713a2f68b1f 100644 (file)
@@ -1,5 +1,5 @@
 use super::method::MethodCallee;
-use super::{Expectation, FnCtxt, TupleArgumentsFlag};
+use super::{DefIdOrName, Expectation, FnCtxt, TupleArgumentsFlag};
 use crate::type_error_struct;
 
 use rustc_errors::{struct_span_err, Applicability, Diagnostic};
@@ -24,7 +24,8 @@
 use rustc_span::Span;
 use rustc_target::spec::abi;
 use rustc_trait_selection::autoderef::Autoderef;
-use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
+use rustc_trait_selection::infer::InferCtxtExt as _;
+use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
 
 use std::iter;
 
@@ -471,7 +472,25 @@ fn confirm_builtin_call(
                 };
 
                 if !self.maybe_suggest_bad_array_definition(&mut err, call_expr, callee_expr) {
-                    err.span_label(call_expr.span, "call expression requires function");
+                    if let Some((maybe_def, output_ty, _)) = self.extract_callable_info(callee_expr, callee_ty)
+                        && !self.type_is_sized_modulo_regions(self.param_env, output_ty, callee_expr.span)
+                    {
+                        let descr = match maybe_def {
+                            DefIdOrName::DefId(def_id) => self.tcx.def_kind(def_id).descr(def_id),
+                            DefIdOrName::Name(name) => name,
+                        };
+                        err.span_label(
+                            callee_expr.span,
+                            format!("this {descr} returns an unsized value `{output_ty}`, so it cannot be called")
+                        );
+                        if let DefIdOrName::DefId(def_id) = maybe_def
+                            && let Some(def_span) = self.tcx.hir().span_if_local(def_id)
+                        {
+                            err.span_label(def_span, "the callable type is defined here");
+                        }
+                    } else {
+                        err.span_label(call_expr.span, "call expression requires function");
+                    }
                 }
 
                 if let Some(span) = self.tcx.hir().res_span(def) {
index 6c7b2a2889fa49526241835a6ef0c43c6c358b83..a3fcda5864b3f600239614176393790e779093dd 100644 (file)
@@ -35,7 +35,6 @@
 use hir::def_id::LOCAL_CRATE;
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
 use rustc_hir as hir;
-use rustc_hir::lang_items::LangItem;
 use rustc_middle::mir::Mutability;
 use rustc_middle::ty::adjustment::AllowTwoPhase;
 use rustc_middle::ty::cast::{CastKind, CastTy};
@@ -47,7 +46,6 @@
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 use rustc_trait_selection::infer::InferCtxtExt;
-use rustc_trait_selection::traits;
 use rustc_trait_selection::traits::error_reporting::report_object_safety_error;
 
 /// Reifies a cast check to be checked once we have full type information for
@@ -97,7 +95,7 @@ fn pointer_kind(
             return Err(reported);
         }
 
-        if self.type_is_known_to_be_sized_modulo_regions(t, span) {
+        if self.type_is_sized_modulo_regions(self.param_env, t, span) {
             return Ok(Some(PointerKind::Thin));
         }
 
@@ -705,7 +703,7 @@ pub fn check(mut self, fcx: &FnCtxt<'a, 'tcx>) {
 
         debug!("check_cast({}, {:?} as {:?})", self.expr.hir_id, self.expr_ty, self.cast_ty);
 
-        if !fcx.type_is_known_to_be_sized_modulo_regions(self.cast_ty, self.span)
+        if !fcx.type_is_sized_modulo_regions(fcx.param_env, self.cast_ty, self.span)
             && !self.cast_ty.has_infer_types()
         {
             self.report_cast_to_unsized_type(fcx);
@@ -1084,10 +1082,3 @@ fn fuzzy_provenance_int2ptr_lint(&self, fcx: &FnCtxt<'a, 'tcx>) {
         );
     }
 }
-
-impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
-    fn type_is_known_to_be_sized_modulo_regions(&self, ty: Ty<'tcx>, span: Span) -> bool {
-        let lang_item = self.tcx.require_lang_item(LangItem::Sized, None);
-        traits::type_known_to_meet_bound_modulo_regions(self, self.param_env, ty, lang_item, span)
-    }
-}
index 29a128f27b840f5653dc3796f181f8f317d3d738..43893263be13898135f6b9211f461275f2162ce7 100644 (file)
@@ -610,12 +610,7 @@ fn nested_visit_map(&mut self) -> Self::Map {
         fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) {
             match arg.kind {
                 hir::TyKind::Path(hir::QPath::Resolved(None, path)) => match &path.segments {
-                    [
-                        PathSegment {
-                            res: Some(Res::SelfTy { trait_: _, alias_to: impl_ref }),
-                            ..
-                        },
-                    ] => {
+                    [PathSegment { res: Res::SelfTy { trait_: _, alias_to: impl_ref }, .. }] => {
                         let impl_ty_name =
                             impl_ref.map(|(def_id, _)| self.tcx.def_path_str(def_id));
                         self.selftys.push((path.span, impl_ty_name));
@@ -1464,7 +1459,7 @@ fn check_enum<'tcx>(tcx: TyCtxt<'tcx>, vs: &'tcx [hir::Variant<'tcx>], def_id: L
     def.destructor(tcx); // force the destructor to be evaluated
 
     if vs.is_empty() {
-        if let Some(attr) = tcx.get_attr(def_id.to_def_id(), sym::repr) {
+        if let Some(attr) = tcx.get_attrs(def_id.to_def_id(), sym::repr).next() {
             struct_span_err!(
                 tcx.sess,
                 attr.span,
index fee872155f5b2d1fa86c3ca4958a8c5d0384ce3a..bc3fec6e7d66a371dc57dfb0fd8a0039a30838fa 100644 (file)
@@ -58,7 +58,7 @@ pub fn check_expr_closure(
         self.check_closure(expr, expected_kind, decl, body, gen, expected_sig)
     }
 
-    #[instrument(skip(self, expr, body, decl), level = "debug")]
+    #[instrument(skip(self, expr, body, decl), level = "debug", ret)]
     fn check_closure(
         &self,
         expr: &hir::Expr<'_>,
@@ -158,11 +158,7 @@ fn check_closure(
             },
         );
 
-        let closure_type = self.tcx.mk_closure(expr_def_id.to_def_id(), closure_substs.substs);
-
-        debug!(?expr.hir_id, ?closure_type);
-
-        closure_type
+        self.tcx.mk_closure(expr_def_id.to_def_id(), closure_substs.substs)
     }
 
     /// Given the expected type, figures out what it can about this closure we
@@ -262,7 +258,7 @@ fn deduce_expectations_from_obligations(
     /// The `cause_span` should be the span that caused us to
     /// have this expected signature, or `None` if we can't readily
     /// know that.
-    #[instrument(level = "debug", skip(self, cause_span))]
+    #[instrument(level = "debug", skip(self, cause_span), ret)]
     fn deduce_sig_from_projection(
         &self,
         cause_span: Option<Span>,
@@ -317,7 +313,6 @@ fn deduce_sig_from_projection(
             hir::Unsafety::Normal,
             Abi::Rust,
         ));
-        debug!(?sig);
 
         Some(ExpectedSig { cause_span, sig })
     }
@@ -576,7 +571,7 @@ fn check_supplied_sig_against_expectation(
     /// types that the user gave into a signature.
     ///
     /// Also, record this closure signature for later.
-    #[instrument(skip(self, decl, body), level = "debug")]
+    #[instrument(skip(self, decl, body), level = "debug", ret)]
     fn supplied_sig_of_closure(
         &self,
         hir_id: hir::HirId,
@@ -629,8 +624,6 @@ fn supplied_sig_of_closure(
             bound_vars,
         );
 
-        debug!(?result);
-
         let c_result = self.inh.infcx.canonicalize_response(result);
         self.typeck_results.borrow_mut().user_provided_sigs.insert(expr_def_id, c_result);
 
@@ -643,7 +636,7 @@ fn supplied_sig_of_closure(
     /// user specified. The "desugared" return type is an `impl
     /// Future<Output = T>`, so we do this by searching through the
     /// obligations to extract the `T`.
-    #[instrument(skip(self), level = "debug")]
+    #[instrument(skip(self), level = "debug", ret)]
     fn deduce_future_output_from_obligations(
         &self,
         expr_def_id: DefId,
@@ -704,7 +697,6 @@ fn deduce_future_output_from_obligations(
             );
         self.register_predicates(obligations);
 
-        debug!("deduce_future_output_from_obligations: output_ty={:?}", output_ty);
         Some(output_ty)
     }
 
index 804306814a24127b2c352a21ec17364e31c0a077..b6bc244d2b14447a5c3d4a96c942a87f8ca0f58a 100644 (file)
@@ -1308,7 +1308,7 @@ fn compare_type_predicate_entailment<'tcx>(
 /// For default associated types the normalization is not possible (the value
 /// from the impl could be overridden). We also can't normalize generic
 /// associated types (yet) because they contain bound parameters.
-#[tracing::instrument(level = "debug", skip(tcx))]
+#[instrument(level = "debug", skip(tcx))]
 pub fn check_type_bounds<'tcx>(
     tcx: TyCtxt<'tcx>,
     trait_ty: &ty::AssocItem,
index 07046f3f0326b119185f836728bd3bf49df39873..d078252ebd4e2fadf6b9ce12eb9ac305706c7c61 100644 (file)
@@ -42,6 +42,7 @@ pub fn emit_coerce_suggestions(
         self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty);
         self.suggest_missing_parentheses(err, expr);
         self.suggest_block_to_brackets_peeling_refs(err, expr, expr_ty, expected);
+        self.suggest_copied_or_cloned(err, expr, expr_ty, expected);
         self.note_type_is_not_clone(err, expected, expr_ty, expr);
         self.note_need_for_fn_pointer(err, expected, expr_ty);
         self.note_internal_mutation_in_method(err, expr, expected, expr_ty);
@@ -130,7 +131,7 @@ pub fn demand_coerce(
     ///
     /// N.B., this code relies on `self.diverges` to be accurate. In particular, assignments to `!`
     /// will be permitted if the diverges flag is currently "always".
-    #[tracing::instrument(level = "debug", skip(self, expr, expected_ty_expr, allow_two_phase))]
+    #[instrument(level = "debug", skip(self, expr, expected_ty_expr, allow_two_phase))]
     pub fn demand_coerce_diag(
         &self,
         expr: &hir::Expr<'tcx>,
@@ -589,7 +590,7 @@ fn can_use_as_ref(&self, expr: &hir::Expr<'_>) -> Option<(Span, &'static str, St
         let closure_params_len = closure_fn_decl.inputs.len();
         let (
             Some(Node::Expr(hir::Expr {
-                kind: hir::ExprKind::MethodCall(method_path, method_expr, _),
+                kind: hir::ExprKind::MethodCall(method_path, receiver, ..),
                 ..
             })),
             1,
@@ -597,7 +598,7 @@ fn can_use_as_ref(&self, expr: &hir::Expr<'_>) -> Option<(Span, &'static str, St
             return None;
         };
 
-        let self_ty = self.typeck_results.borrow().expr_ty(&method_expr[0]);
+        let self_ty = self.typeck_results.borrow().expr_ty(receiver);
         let name = method_path.ident.name;
         let is_as_ref_able = match self_ty.peel_refs().kind() {
             ty::Adt(def, _) => {
@@ -766,22 +767,21 @@ pub fn check_ref(
                 };
                 if self.can_coerce(ref_ty, expected) {
                     let mut sugg_sp = sp;
-                    if let hir::ExprKind::MethodCall(ref segment, ref args, _) = expr.kind {
+                    if let hir::ExprKind::MethodCall(ref segment, receiver, args, _) = expr.kind {
                         let clone_trait =
                             self.tcx.require_lang_item(LangItem::Clone, Some(segment.ident.span));
-                        if let ([arg], Some(true), sym::clone) = (
-                            &args[..],
-                            self.typeck_results.borrow().type_dependent_def_id(expr.hir_id).map(
+                        if args.is_empty()
+                            && self.typeck_results.borrow().type_dependent_def_id(expr.hir_id).map(
                                 |did| {
                                     let ai = self.tcx.associated_item(did);
                                     ai.trait_container(self.tcx) == Some(clone_trait)
                                 },
-                            ),
-                            segment.ident.name,
-                        {
+                            ) == Some(true)
+                            && segment.ident.name == sym::clone
+                        {
                             // If this expression had a clone call when suggesting borrowing
                             // we want to suggest removing it because it'd now be unnecessary.
-                            sugg_sp = arg.span;
+                            sugg_sp = receiver.span;
                         }
                     }
                     if let Ok(src) = sm.span_to_snippet(sugg_sp) {
index f6596950c2a0deb1588da939c3e868914c4dc4e6..e4141647d7d2df66fd8b99a8e83ce89a68def8f9 100644 (file)
@@ -324,8 +324,8 @@ fn check_expr_kind(
             }
             ExprKind::Block(body, _) => self.check_block_with_expected(&body, expected),
             ExprKind::Call(callee, args) => self.check_call(expr, &callee, args, expected),
-            ExprKind::MethodCall(segment, args, _) => {
-                self.check_method_call(expr, segment, args, expected)
+            ExprKind::MethodCall(segment, receiver, args, _) => {
+                self.check_method_call(expr, segment, receiver, args, expected)
             }
             ExprKind::Cast(e, t) => self.check_expr_cast(e, t, expr),
             ExprKind::Type(e, t) => {
@@ -560,17 +560,16 @@ pub(crate) fn check_expr_path(
                     // We just want to check sizedness, so instead of introducing
                     // placeholder lifetimes with probing, we just replace higher lifetimes
                     // with fresh vars.
-                    let arg_span = args.get(i).map(|a| a.span);
-                    let span = arg_span.unwrap_or(expr.span);
+                    let span = args.get(i).map(|a| a.span).unwrap_or(expr.span);
                     let input = self.replace_bound_vars_with_fresh_vars(
                         span,
                         infer::LateBoundRegionConversionTime::FnCall,
                         fn_sig.input(i),
                     );
-                    self.require_type_is_sized(
-                        self.normalize_associated_types_in(span, input),
+                    self.require_type_is_sized_deferred(
+                        input,
                         span,
-                        traits::SizedArgumentType(arg_span),
+                        traits::SizedArgumentType(None),
                     );
                 }
             }
@@ -585,11 +584,7 @@ pub(crate) fn check_expr_path(
                 infer::LateBoundRegionConversionTime::FnCall,
                 fn_sig.output(),
             );
-            self.require_type_is_sized(
-                self.normalize_associated_types_in(expr.span, output),
-                expr.span,
-                traits::SizedReturnType,
-            );
+            self.require_type_is_sized_deferred(output, expr.span, traits::SizedReturnType);
         }
 
         // We always require that the type provided as the value for
@@ -1200,13 +1195,13 @@ fn check_method_call(
         &self,
         expr: &'tcx hir::Expr<'tcx>,
         segment: &hir::PathSegment<'_>,
+        rcvr: &'tcx hir::Expr<'tcx>,
         args: &'tcx [hir::Expr<'tcx>],
         expected: Expectation<'tcx>,
     ) -> Ty<'tcx> {
-        let rcvr = &args[0];
         let rcvr_t = self.check_expr(&rcvr);
         // no need to check for bot/err -- callee does that
-        let rcvr_t = self.structurally_resolved_type(args[0].span, rcvr_t);
+        let rcvr_t = self.structurally_resolved_type(rcvr.span, rcvr_t);
         let span = segment.ident.span;
 
         let method = match self.lookup_method(rcvr_t, segment, span, expr, rcvr, args) {
@@ -1223,9 +1218,9 @@ fn check_method_call(
                         span,
                         rcvr_t,
                         segment.ident,
-                        SelfSource::MethodCall(&args[0]),
+                        SelfSource::MethodCall(rcvr),
                         error,
-                        Some(args),
+                        Some((rcvr, args)),
                     ) {
                         err.emit();
                     }
@@ -1235,14 +1230,7 @@ fn check_method_call(
         };
 
         // Call the generic checker.
-        self.check_method_argument_types(
-            span,
-            expr,
-            method,
-            &args[1..],
-            DontTupleArguments,
-            expected,
-        )
+        self.check_method_argument_types(span, expr, method, &args, DontTupleArguments, expected)
     }
 
     fn check_expr_cast(
index 20d25d508d224e9749e631f3e8a4cfb5905cbe1e..c59638f5d6f9f77a6a98c0c4b6103342a0cad91b 100644 (file)
@@ -83,7 +83,7 @@ pub(in super::super) fn resolve_vars_with_obligations(&self, ty: Ty<'tcx>) -> Ty
         self.resolve_vars_with_obligations_and_mutate_fulfillment(ty, |_| {})
     }
 
-    #[instrument(skip(self, mutate_fulfillment_errors), level = "debug")]
+    #[instrument(skip(self, mutate_fulfillment_errors), level = "debug", ret)]
     pub(in super::super) fn resolve_vars_with_obligations_and_mutate_fulfillment(
         &self,
         mut ty: Ty<'tcx>,
@@ -107,10 +107,7 @@ pub(in super::super) fn resolve_vars_with_obligations_and_mutate_fulfillment(
         // indirect dependencies that don't seem worth tracking
         // precisely.
         self.select_obligations_where_possible(false, mutate_fulfillment_errors);
-        ty = self.resolve_vars_if_possible(ty);
-
-        debug!(?ty);
-        ty
+        self.resolve_vars_if_possible(ty)
     }
 
     pub(in super::super) fn record_deferred_call_resolution(
@@ -442,6 +439,17 @@ pub fn require_type_is_sized(
         }
     }
 
+    pub fn require_type_is_sized_deferred(
+        &self,
+        ty: Ty<'tcx>,
+        span: Span,
+        code: traits::ObligationCauseCode<'tcx>,
+    ) {
+        if !ty.references_error() {
+            self.deferred_sized_obligations.borrow_mut().push((ty, span, code));
+        }
+    }
+
     pub fn register_bound(
         &self,
         ty: Ty<'tcx>,
@@ -979,7 +987,7 @@ pub(in super::super) fn note_internal_mutation_in_method(
         if found != self.tcx.types.unit {
             return;
         }
-        if let ExprKind::MethodCall(path_segment, [rcvr, ..], _) = expr.kind {
+        if let ExprKind::MethodCall(path_segment, rcvr, ..) = expr.kind {
             if self
                 .typeck_results
                 .borrow()
@@ -1405,7 +1413,7 @@ pub(crate) fn add_required_obligations_for_hir(
         })
     }
 
-    #[tracing::instrument(level = "debug", skip(self, code, span, def_id, substs))]
+    #[instrument(level = "debug", skip(self, code, span, def_id, substs))]
     fn add_required_obligations_with_code(
         &self,
         span: Span,
index 7ff4aef2d25716a28c6fa44177c35512bcb140e2..311fcaadaa98b3b7bc815f879660f627efc6aaea 100644 (file)
@@ -31,7 +31,7 @@
 use rustc_middle::ty::{self, DefIdTree, IsSuggestable, Ty, TypeSuperVisitable, TypeVisitor};
 use rustc_session::Session;
 use rustc_span::symbol::Ident;
-use rustc_span::{self, Span};
+use rustc_span::{self, sym, Span};
 use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext};
 
 use std::iter;
@@ -224,6 +224,11 @@ pub(in super::super) fn check_argument_types(
         let minimum_input_count = expected_input_tys.len();
         let provided_arg_count = provided_args.len();
 
+        let is_const_eval_select = matches!(fn_def_id, Some(def_id) if
+            self.tcx.def_kind(def_id) == hir::def::DefKind::Fn
+            && self.tcx.is_intrinsic(def_id)
+            && self.tcx.item_name(def_id) == sym::const_eval_select);
+
         // We introduce a helper function to demand that a given argument satisfy a given input
         // This is more complicated than just checking type equality, as arguments could be coerced
         // This version writes those types back so further type checking uses the narrowed types
@@ -259,6 +264,32 @@ pub(in super::super) fn check_argument_types(
                 return Compatibility::Incompatible(coerce_error);
             }
 
+            // Check that second and third argument of `const_eval_select` must be `FnDef`, and additionally that
+            // the second argument must be `const fn`. The first argument must be a tuple, but this is already expressed
+            // in the function signature (`F: FnOnce<ARG>`), so I did not bother to add another check here.
+            //
+            // This check is here because there is currently no way to express a trait bound for `FnDef` types only.
+            if is_const_eval_select && (1..=2).contains(&idx) {
+                if let ty::FnDef(def_id, _) = checked_ty.kind() {
+                    if idx == 1 && !self.tcx.is_const_fn_raw(*def_id) {
+                        self.tcx
+                            .sess
+                            .struct_span_err(provided_arg.span, "this argument must be a `const fn`")
+                            .help("consult the documentation on `const_eval_select` for more information")
+                            .emit();
+                    }
+                } else {
+                    self.tcx
+                        .sess
+                        .struct_span_err(provided_arg.span, "this argument must be a function item")
+                        .note(format!("expected a function item, found {checked_ty}"))
+                        .help(
+                            "consult the documentation on `const_eval_select` for more information",
+                        )
+                        .emit();
+                }
+            }
+
             // 3. Check if the formal type is a supertype of the checked one
             //    and register any such obligations for future type checks
             let supertype_error = self
@@ -447,7 +478,7 @@ fn report_arg_errors(
                 }
             }
             hir::ExprKind::Call(hir::Expr { span, .. }, _) => (call_span, *span, None, false),
-            hir::ExprKind::MethodCall(path_segment, _, span) => {
+            hir::ExprKind::MethodCall(path_segment, _, _, span) => {
                 let ident_span = path_segment.ident.span;
                 let ident_span = if let Some(args) = path_segment.args {
                     ident_span.with_hi(args.span_ext.hi())
@@ -499,13 +530,13 @@ fn has_error_or_infer<'tcx>(tys: impl IntoIterator<Item = Ty<'tcx>>) -> bool {
             .collect();
         let callee_expr = match &call_expr.peel_blocks().kind {
             hir::ExprKind::Call(callee, _) => Some(*callee),
-            hir::ExprKind::MethodCall(_, callee, _) => {
+            hir::ExprKind::MethodCall(_, receiver, ..) => {
                 if let Some((DefKind::AssocFn, def_id)) =
                     self.typeck_results.borrow().type_dependent_def(call_expr.hir_id)
                     && let Some(assoc) = tcx.opt_associated_item(def_id)
                     && assoc.fn_has_self_parameter
                 {
-                    Some(&callee[0])
+                    Some(*receiver)
                 } else {
                     None
                 }
@@ -1056,11 +1087,22 @@ enum SuggestionText {
         };
         if let Some(suggestion_text) = suggestion_text {
             let source_map = self.sess().source_map();
-            let mut suggestion = format!(
-                "{}(",
-                source_map.span_to_snippet(full_call_span).unwrap_or_else(|_| fn_def_id
-                    .map_or("".to_string(), |fn_def_id| tcx.item_name(fn_def_id).to_string()))
-            );
+            let (mut suggestion, suggestion_span) =
+                if let Some(call_span) = full_call_span.find_ancestor_inside(error_span) {
+                    ("(".to_string(), call_span.shrink_to_hi().to(error_span.shrink_to_hi()))
+                } else {
+                    (
+                        format!(
+                            "{}(",
+                            source_map.span_to_snippet(full_call_span).unwrap_or_else(|_| {
+                                fn_def_id.map_or("".to_string(), |fn_def_id| {
+                                    tcx.item_name(fn_def_id).to_string()
+                                })
+                            })
+                        ),
+                        error_span,
+                    )
+                };
             let mut needs_comma = false;
             for (expected_idx, provided_idx) in matched_inputs.iter_enumerated() {
                 if needs_comma {
@@ -1088,7 +1130,7 @@ enum SuggestionText {
             }
             suggestion += ")";
             err.span_suggestion_verbose(
-                error_span,
+                suggestion_span,
                 &suggestion_text,
                 suggestion,
                 Applicability::HasPlaceholders,
@@ -1763,25 +1805,26 @@ fn adjust_fulfillment_error_for_expr_obligation(
                                 param,
                                 *call_hir_id,
                                 callee.span,
+                                None,
                                 args,
                             )
                         {
                             return true;
                         }
                     }
-                    // Notably, we only point to params that are local to the
-                    // item we're checking, since those are the ones we are able
-                    // to look in the final `hir::PathSegment` for. Everything else
-                    // would require a deeper search into the `qpath` than I think
-                    // is worthwhile.
-                    if let Some(param_to_point_at) = param_to_point_at
-                        && self.point_at_path_if_possible(error, def_id, param_to_point_at, qpath)
-                    {
-                        return true;
-                    }
+                }
+                // Notably, we only point to params that are local to the
+                // item we're checking, since those are the ones we are able
+                // to look in the final `hir::PathSegment` for. Everything else
+                // would require a deeper search into the `qpath` than I think
+                // is worthwhile.
+                if let Some(param_to_point_at) = param_to_point_at
+                    && self.point_at_path_if_possible(error, def_id, param_to_point_at, qpath)
+                {
+                    return true;
                 }
             }
-            hir::ExprKind::MethodCall(segment, args, ..) => {
+            hir::ExprKind::MethodCall(segment, receiver, args, ..) => {
                 for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
                     .into_iter()
                     .flatten()
@@ -1792,6 +1835,7 @@ fn adjust_fulfillment_error_for_expr_obligation(
                         param,
                         hir_id,
                         segment.ident.span,
+                        Some(receiver),
                         args,
                     ) {
                         return true;
@@ -1859,7 +1903,8 @@ fn point_at_arg_if_possible(
         param_to_point_at: ty::GenericArg<'tcx>,
         call_hir_id: hir::HirId,
         callee_span: Span,
-        args: &[hir::Expr<'tcx>],
+        receiver: Option<&'tcx hir::Expr<'tcx>>,
+        args: &'tcx [hir::Expr<'tcx>],
     ) -> bool {
         let sig = self.tcx.fn_sig(def_id).skip_binder();
         let args_referencing_param: Vec<_> = sig
@@ -1868,9 +1913,10 @@ fn point_at_arg_if_possible(
             .enumerate()
             .filter(|(_, ty)| find_param_in_ty(**ty, param_to_point_at))
             .collect();
-
         // If there's one field that references the given generic, great!
-        if let [(idx, _)] = args_referencing_param.as_slice() && let Some(arg) = args.get(*idx) {
+        if let [(idx, _)] = args_referencing_param.as_slice()
+            && let Some(arg) = receiver
+                .map_or(args.get(*idx), |rcvr| if *idx == 0 { Some(rcvr) } else { args.get(*idx - 1) }) {
             error.obligation.cause.span = arg.span.find_ancestor_in_same_ctxt(error.obligation.cause.span).unwrap_or(arg.span);
             error.obligation.cause.map_code(|parent_code| {
                 ObligationCauseCode::FunctionArgumentObligation {
index 939f4612d44ef6688010343717549e3ce8a0d2a6..2bfee9a536439cdcc10a0259de4c18a90761a914 100644 (file)
@@ -17,6 +17,7 @@
 use rustc_middle::ty::{self, Binder, IsSuggestable, Subst, ToPredicate, Ty};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
+use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -143,7 +144,10 @@ pub(crate) fn suggest_fn_call(
         false
     }
 
-    fn extract_callable_info(
+    /// Extracts information about a callable type for diagnostics. This is a
+    /// heuristic -- it doesn't necessarily mean that a type is always callable,
+    /// because the callable type must also be well-formed to be called.
+    pub(in super::super) fn extract_callable_info(
         &self,
         expr: &Expr<'_>,
         found: Ty<'tcx>,
@@ -925,6 +929,69 @@ pub(crate) fn suggest_block_to_brackets_peeling_refs(
         }
     }
 
+    pub(crate) fn suggest_copied_or_cloned(
+        &self,
+        diag: &mut Diagnostic,
+        expr: &hir::Expr<'_>,
+        expr_ty: Ty<'tcx>,
+        expected_ty: Ty<'tcx>,
+    ) {
+        let ty::Adt(adt_def, substs) = expr_ty.kind() else { return; };
+        let ty::Adt(expected_adt_def, expected_substs) = expected_ty.kind() else { return; };
+        if adt_def != expected_adt_def {
+            return;
+        }
+
+        let mut suggest_copied_or_cloned = || {
+            let expr_inner_ty = substs.type_at(0);
+            let expected_inner_ty = expected_substs.type_at(0);
+            if let ty::Ref(_, ty, hir::Mutability::Not) = expr_inner_ty.kind()
+                && self.can_eq(self.param_env, *ty, expected_inner_ty).is_ok()
+            {
+                let def_path = self.tcx.def_path_str(adt_def.did());
+                if self.type_is_copy_modulo_regions(self.param_env, *ty, expr.span) {
+                    diag.span_suggestion_verbose(
+                        expr.span.shrink_to_hi(),
+                        format!(
+                            "use `{def_path}::copied` to copy the value inside the `{def_path}`"
+                        ),
+                        ".copied()",
+                        Applicability::MachineApplicable,
+                    );
+                } else if let Some(clone_did) = self.tcx.lang_items().clone_trait()
+                    && rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions(
+                        self,
+                        self.param_env,
+                        *ty,
+                        clone_did,
+                        expr.span
+                    )
+                {
+                    diag.span_suggestion_verbose(
+                        expr.span.shrink_to_hi(),
+                        format!(
+                            "use `{def_path}::cloned` to clone the value inside the `{def_path}`"
+                        ),
+                        ".cloned()",
+                        Applicability::MachineApplicable,
+                    );
+                }
+            }
+        };
+
+        if let Some(result_did) = self.tcx.get_diagnostic_item(sym::Result)
+            && adt_def.did() == result_did
+            // Check that the error types are equal
+            && self.can_eq(self.param_env, substs.type_at(1), expected_substs.type_at(1)).is_ok()
+        {
+            suggest_copied_or_cloned();
+        } else if let Some(option_did) = self.tcx.get_diagnostic_item(sym::Option)
+            && adt_def.did() == option_did
+        {
+            suggest_copied_or_cloned();
+        }
+    }
+
     /// Suggest wrapping the block in square brackets instead of curly braces
     /// in case the block was mistaken array syntax, e.g. `{ 1 }` -> `[ 1 ]`.
     pub(crate) fn suggest_block_to_brackets(
@@ -985,7 +1052,7 @@ pub(crate) fn note_type_is_not_clone(
         found_ty: Ty<'tcx>,
         expr: &hir::Expr<'_>,
     ) {
-        let hir::ExprKind::MethodCall(segment, &[ref callee_expr], _) = expr.kind else { return; };
+        let hir::ExprKind::MethodCall(segment, callee_expr, &[], _) = expr.kind else { return; };
         let Some(clone_trait_did) = self.tcx.lang_items().clone_trait() else { return; };
         let ty::Ref(_, pointee_ty, _) = found_ty.kind() else { return };
         let results = self.typeck_results.borrow();
@@ -1066,7 +1133,7 @@ pub(crate) fn consider_removing_semicolon(
     }
 }
 
-enum DefIdOrName {
+pub enum DefIdOrName {
     DefId(DefId),
     Name(&'static str),
 }
index 85a0d4e44990602e6a6bcdb7172bf0057d0f685f..7fda6f79f238da477bbe80afdfb98098b76c25a0 100644 (file)
@@ -17,7 +17,6 @@
 use rustc_middle::ty::{self, RvalueScopes, Ty, TyCtxt, TypeVisitable};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
-use tracing::debug;
 
 mod drop_ranges;
 
@@ -409,8 +408,15 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
             }) {
             self.rvalue_scopes.temporary_scope(self.region_scope_tree, expr.hir_id.local_id)
         } else {
-            debug!("parent_node: {:?}", self.fcx.tcx.hir().find_parent_node(expr.hir_id));
-            match self.fcx.tcx.hir().find_parent_node(expr.hir_id) {
+            let parent_expr = self
+                .fcx
+                .tcx
+                .hir()
+                .parent_iter(expr.hir_id)
+                .find(|(_, node)| matches!(node, hir::Node::Expr(_)))
+                .map(|(id, _)| id);
+            debug!("parent_expr: {:?}", parent_expr);
+            match parent_expr {
                 Some(parent) => Some(Scope { id: parent.local_id, data: ScopeData::Node }),
                 None => {
                     self.rvalue_scopes.temporary_scope(self.region_scope_tree, expr.hir_id.local_id)
index 3e96b3ffb0940e7b41228728ab0bf58704872dd5..016f4056bd90302ad9aeb4553a9802d878c5e5b0 100644 (file)
@@ -434,7 +434,8 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
 
                 self.handle_uninhabited_return(expr);
             }
-            ExprKind::MethodCall(_, exprs, _) => {
+            ExprKind::MethodCall(_, receiver, exprs, _) => {
+                self.visit_expr(receiver);
                 for expr in exprs {
                     self.visit_expr(expr);
                 }
index ded0888c33e15db96d8139245f4fed5553d395ac..e22675e9d5f4e5ebc45155f2166788600eafc481 100644 (file)
@@ -159,8 +159,8 @@ fn borrow(
         bk: rustc_middle::ty::BorrowKind,
     ) {
         debug!(
-            "borrow: place_with_id = {place_with_id:?}, diag_expr_id={diag_expr_id:?}, \
-            borrow_kind={bk:?}"
+            "borrow: place_with_id = {place_with_id:#?}, diag_expr_id={diag_expr_id:#?}, \
+            borrow_kind={bk:#?}"
         );
 
         self.borrow_place(place_with_id);
index 1439baf54406d2e44d3700d73fecf8e6a3ea036a..37c830d4e3850f14c63e2ce1b918b8ae70ae0997 100644 (file)
@@ -38,6 +38,12 @@ pub struct Inherited<'a, 'tcx> {
 
     pub(super) fulfillment_cx: RefCell<Box<dyn TraitEngine<'tcx>>>,
 
+    // Some additional `Sized` obligations badly affect type inference.
+    // These obligations are added in a later stage of typeck.
+    // Removing these may also cause additional complications, see #101066.
+    pub(super) deferred_sized_obligations:
+        RefCell<Vec<(Ty<'tcx>, Span, traits::ObligationCauseCode<'tcx>)>>,
+
     // When we process a call like `c()` where `c` is a closure type,
     // we may not have decided yet whether `c` is a `Fn`, `FnMut`, or
     // `FnOnce` closure. In that case, we defer full resolution of the
@@ -137,6 +143,7 @@ fn new(infcx: InferCtxt<'a, 'tcx>, def_id: LocalDefId) -> Self {
             infcx,
             fulfillment_cx: RefCell::new(<dyn TraitEngine<'_>>::new(tcx)),
             locals: RefCell::new(Default::default()),
+            deferred_sized_obligations: RefCell::new(Vec::new()),
             deferred_call_resolutions: RefCell::new(Default::default()),
             deferred_cast_checks: RefCell::new(Vec::new()),
             deferred_transmute_checks: RefCell::new(Vec::new()),
index de26a9e56e2d6b57275d2060fb475c540677eda0..a9071cd1fd949efe57c2bfd122425fb0b5277dd7 100644 (file)
@@ -168,7 +168,7 @@ pub(crate) fn suggest_method_call(
     /// * `call_expr`:             the complete method call: (`foo.bar::<T1,...Tn>(...)`)
     /// * `self_expr`:             the self expression (`foo`)
     /// * `args`:                  the expressions of the arguments (`a, b + 1, ...`)
-    #[instrument(level = "debug", skip(self, call_expr, self_expr))]
+    #[instrument(level = "debug", skip(self))]
     pub fn lookup_method(
         &self,
         self_ty: Ty<'tcx>,
@@ -178,11 +178,6 @@ pub fn lookup_method(
         self_expr: &'tcx hir::Expr<'tcx>,
         args: &'tcx [hir::Expr<'tcx>],
     ) -> Result<MethodCallee<'tcx>, MethodError<'tcx>> {
-        debug!(
-            "lookup(method_name={}, self_ty={:?}, call_expr={:?}, self_expr={:?})",
-            segment.ident, self_ty, call_expr, self_expr
-        );
-
         let pick =
             self.lookup_probe(span, segment.ident, self_ty, call_expr, ProbeScope::TraitsInScope)?;
 
@@ -383,7 +378,7 @@ pub(super) fn obligation_for_op_method(
     /// In particular, it doesn't really do any probing: it simply constructs
     /// an obligation for a particular trait with the given self type and checks
     /// whether that trait is implemented.
-    #[instrument(level = "debug", skip(self, span, opt_input_types))]
+    #[instrument(level = "debug", skip(self, span))]
     pub(super) fn lookup_method_in_trait(
         &self,
         span: Span,
@@ -392,11 +387,6 @@ pub(super) fn lookup_method_in_trait(
         self_ty: Ty<'tcx>,
         opt_input_types: Option<&[Ty<'tcx>]>,
     ) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
-        debug!(
-            "lookup_in_trait_adjusted(self_ty={:?}, m_name={}, trait_def_id={:?}, opt_input_types={:?})",
-            self_ty, m_name, trait_def_id, opt_input_types
-        );
-
         let (obligation, substs) =
             self.obligation_for_method(span, trait_def_id, self_ty, opt_input_types);
         self.construct_obligation_for_trait(
@@ -576,7 +566,7 @@ fn construct_obligation_for_trait(
     /// * `self_ty`:               the type to search within (`Foo`)
     /// * `self_ty_span`           the span for the type being searched within (span of `Foo`)
     /// * `expr_id`:               the [`hir::HirId`] of the expression composing the entire call
-    #[instrument(level = "debug", skip(self))]
+    #[instrument(level = "debug", skip(self), ret)]
     pub fn resolve_fully_qualified_call(
         &self,
         span: Span,
@@ -585,11 +575,6 @@ pub fn resolve_fully_qualified_call(
         self_ty_span: Span,
         expr_id: hir::HirId,
     ) -> Result<(DefKind, DefId), MethodError<'tcx>> {
-        debug!(
-            "resolve_fully_qualified_call: method_name={:?} self_ty={:?} expr_id={:?}",
-            method_name, self_ty, expr_id,
-        );
-
         let tcx = self.tcx;
 
         // Check if we have an enum variant.
@@ -633,21 +618,17 @@ pub fn resolve_fully_qualified_call(
             &pick,
         );
 
-        debug!("resolve_fully_qualified_call: pick={:?}", pick);
+        debug!(?pick);
         {
             let mut typeck_results = self.typeck_results.borrow_mut();
             let used_trait_imports = Lrc::get_mut(&mut typeck_results.used_trait_imports).unwrap();
             for import_id in pick.import_ids {
-                debug!("resolve_fully_qualified_call: used_trait_import: {:?}", import_id);
+                debug!(used_trait_import=?import_id);
                 used_trait_imports.insert(import_id);
             }
         }
 
         let def_kind = pick.item.kind.as_def_kind();
-        debug!(
-            "resolve_fully_qualified_call: def_kind={:?}, def_id={:?}",
-            def_kind, pick.item.def_id
-        );
         tcx.check_stability(pick.item.def_id, Some(expr_id), span, Some(method_name.span));
         Ok((def_kind, pick.item.def_id))
     }
index 7c68d93040556fb8f74992e36bce3ff596e3d437..392695cca6849fd09ad026dce49981875915c645 100644 (file)
@@ -160,7 +160,6 @@ pub(super) fn lint_dot_call_from_2018(
                     if precise {
                         let args = args
                             .iter()
-                            .skip(1)
                             .map(|arg| {
                                 let span = arg.span.find_ancestor_inside(sp).unwrap_or_default();
                                 format!(
index d9870060a40bbb974922ac85bce1f00c9d21f838..e9f55ab3406f5df2ea9bc49c8e34985b479c36df 100644 (file)
@@ -253,7 +253,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// would result in an error (basically, the same criteria we
     /// would use to decide if a method is a plausible fit for
     /// ambiguity purposes).
-    #[instrument(level = "debug", skip(self, scope_expr_id))]
+    #[instrument(level = "debug", skip(self))]
     pub fn probe_for_return_type(
         &self,
         span: Span,
@@ -262,10 +262,6 @@ pub fn probe_for_return_type(
         self_ty: Ty<'tcx>,
         scope_expr_id: hir::HirId,
     ) -> Vec<ty::AssocItem> {
-        debug!(
-            "probe(self_ty={:?}, return_type={}, scope_expr_id={})",
-            self_ty, return_type, scope_expr_id
-        );
         let method_names = self
             .probe_op(
                 span,
@@ -299,7 +295,7 @@ pub fn probe_for_return_type(
             .collect()
     }
 
-    #[instrument(level = "debug", skip(self, scope_expr_id))]
+    #[instrument(level = "debug", skip(self))]
     pub fn probe_for_name(
         &self,
         span: Span,
@@ -310,10 +306,6 @@ pub fn probe_for_name(
         scope_expr_id: hir::HirId,
         scope: ProbeScope,
     ) -> PickResult<'tcx> {
-        debug!(
-            "probe(self_ty={:?}, item_name={}, scope_expr_id={})",
-            self_ty, item_name, scope_expr_id
-        );
         self.probe_op(
             span,
             mode,
index e99782fdc652c5e668064787420e8a96b4d70890..124ac5c24fa5cef0ae58199d2318a92a98b12446 100644 (file)
@@ -16,8 +16,8 @@
 use rustc_middle::traits::util::supertraits;
 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
 use rustc_middle::ty::print::with_crate_prefix;
-use rustc_middle::ty::ToPolyTraitRef;
 use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef};
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::Symbol;
 use rustc_span::{lev_distance, source_map, ExpnKind, FileName, MacroKind, Span};
@@ -30,7 +30,7 @@
 use std::cmp::Ordering;
 use std::iter;
 
-use super::probe::{Mode, ProbeScope};
+use super::probe::{IsSuggestion, Mode, ProbeScope};
 use super::{CandidateSource, MethodError, NoMatchData};
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -95,7 +95,7 @@ pub fn report_method_error(
         item_name: Ident,
         source: SelfSource<'tcx>,
         error: MethodError<'tcx>,
-        args: Option<&'tcx [hir::Expr<'tcx>]>,
+        args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
     ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
         // Avoid suggestions when we don't know what's going on.
         if rcvr_ty.references_error() {
@@ -998,7 +998,7 @@ trait bound{s}",
                         span,
                         rcvr_ty,
                         item_name,
-                        args.map(|args| args.len()),
+                        args.map(|(_, args)| args.len() + 1),
                         source,
                         out_of_scope_traits,
                         &unsatisfied_predicates,
@@ -1069,6 +1069,8 @@ trait bound{s}",
                     }
                 }
 
+                self.check_for_deref_method(&mut err, source, rcvr_ty, item_name);
+
                 return Some(err);
             }
 
@@ -1651,6 +1653,62 @@ fn suggest_derive(
         }
     }
 
+    fn check_for_deref_method(
+        &self,
+        err: &mut Diagnostic,
+        self_source: SelfSource<'tcx>,
+        rcvr_ty: Ty<'tcx>,
+        item_name: Ident,
+    ) {
+        let SelfSource::QPath(ty) = self_source else { return; };
+        for (deref_ty, _) in self.autoderef(rustc_span::DUMMY_SP, rcvr_ty).skip(1) {
+            if let Ok(pick) = self.probe_for_name(
+                ty.span,
+                Mode::Path,
+                item_name,
+                IsSuggestion(true),
+                deref_ty,
+                ty.hir_id,
+                ProbeScope::TraitsInScope,
+            ) {
+                if deref_ty.is_suggestable(self.tcx, true)
+                    // If this method receives `&self`, then the provided
+                    // argument _should_ coerce, so it's valid to suggest
+                    // just changing the path.
+                    && pick.item.fn_has_self_parameter
+                    && let Some(self_ty) =
+                        self.tcx.fn_sig(pick.item.def_id).inputs().skip_binder().get(0)
+                    && self_ty.is_ref()
+                {
+                    let suggested_path = match deref_ty.kind() {
+                        ty::Bool
+                        | ty::Char
+                        | ty::Int(_)
+                        | ty::Uint(_)
+                        | ty::Float(_)
+                        | ty::Adt(_, _)
+                        | ty::Str
+                        | ty::Projection(_)
+                        | ty::Param(_) => format!("{deref_ty}"),
+                        _ => format!("<{deref_ty}>"),
+                    };
+                    err.span_suggestion_verbose(
+                        ty.span,
+                        format!("the function `{item_name}` is implemented on `{deref_ty}`"),
+                        suggested_path,
+                        Applicability::MaybeIncorrect,
+                    );
+                } else {
+                    err.span_note(
+                        ty.span,
+                        format!("the function `{item_name}` is implemented on `{deref_ty}`"),
+                    );
+                }
+                return;
+            }
+        }
+    }
+
     /// Print out the type for use in value namespace.
     fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
         match ty.kind() {
@@ -2252,7 +2310,7 @@ pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
 
 fn print_disambiguation_help<'tcx>(
     item_name: Ident,
-    args: Option<&'tcx [hir::Expr<'tcx>]>,
+    args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
     err: &mut Diagnostic,
     trait_name: String,
     rcvr_ty: Ty<'_>,
@@ -2264,7 +2322,7 @@ fn print_disambiguation_help<'tcx>(
     fn_has_self_parameter: bool,
 ) {
     let mut applicability = Applicability::MachineApplicable;
-    let (span, sugg) = if let (ty::AssocKind::Fn, Some(args)) = (kind, args) {
+    let (span, sugg) = if let (ty::AssocKind::Fn, Some((receiver, args))) = (kind, args) {
         let args = format!(
             "({}{})",
             if rcvr_ty.is_region_ptr() {
@@ -2272,7 +2330,8 @@ fn print_disambiguation_help<'tcx>(
             } else {
                 ""
             },
-            args.iter()
+            std::iter::once(receiver)
+                .chain(args.iter())
                 .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
                     applicability = Applicability::HasPlaceholders;
                     "_".to_owned()
index 3281dd8298bc3000526cc5bb55fdd577e9235933..69eb34b5f802d25b6f5073377be737bf91893b7f 100644 (file)
@@ -341,7 +341,6 @@ fn diagnostic_only_typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::T
     typeck_with_fallback(tcx, def_id, fallback)
 }
 
-#[instrument(skip(tcx, fallback))]
 fn typeck_with_fallback<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: LocalDefId,
@@ -465,6 +464,11 @@ fn typeck_with_fallback<'tcx>(
         fcx.resolve_rvalue_scopes(def_id.to_def_id());
         fcx.resolve_generator_interiors(def_id.to_def_id());
 
+        for (ty, span, code) in fcx.deferred_sized_obligations.borrow_mut().drain(..) {
+            let ty = fcx.normalize_ty(span, ty);
+            fcx.require_type_is_sized(ty, span, code);
+        }
+
         fcx.select_all_obligations_or_error();
 
         if !fcx.infcx.is_tainted_by_errors() {
index 952086e898fc70011fa22d1a19402c0bfab75bb5..0d9dbb5bc11c24ece1ef00c329fff37c1cf5a55f 100644 (file)
@@ -57,9 +57,28 @@ pub fn check_binop_assign(
                     )
                     .is_ok()
                 {
-                    // Suppress this error, since we already emitted
-                    // a deref suggestion in check_overloaded_binop
-                    err.downgrade_to_delayed_bug();
+                    // If LHS += RHS is an error, but *LHS += RHS is successful, then we will have
+                    // emitted a better suggestion during error handling in check_overloaded_binop.
+                    if self
+                        .lookup_op_method(
+                            lhs_ty,
+                            Some(rhs_ty),
+                            Some(rhs),
+                            Op::Binary(op, IsAssign::Yes),
+                            expected,
+                        )
+                        .is_err()
+                    {
+                        err.downgrade_to_delayed_bug();
+                    } else {
+                        // Otherwise, it's valid to suggest dereferencing the LHS here.
+                        err.span_suggestion_verbose(
+                            lhs.span.shrink_to_lo(),
+                            "consider dereferencing the left-hand side of this operation",
+                            "*",
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
                 }
             }
         });
index 6dcc364bb50f7838df7687d5428d643313748e77..9096fc442d49398e882f60ed458b4a99e644f65d 100644 (file)
@@ -569,7 +569,7 @@ fn check_pat_ident(
     ) -> Ty<'tcx> {
         // Determine the binding mode...
         let bm = match ba {
-            hir::BindingAnnotation::Unannotated => def_bm,
+            hir::BindingAnnotation::NONE => def_bm,
             _ => BindingMode::convert(ba),
         };
         // ...and store it in a side table:
@@ -655,7 +655,7 @@ fn suggest_adding_missing_ref_or_removing_ref(
         ba: hir::BindingAnnotation,
     ) {
         match (expected.kind(), actual.kind(), ba) {
-            (ty::Ref(_, inner_ty, _), _, hir::BindingAnnotation::Unannotated)
+            (ty::Ref(_, inner_ty, _), _, hir::BindingAnnotation::NONE)
                 if self.can_eq(self.param_env, *inner_ty, actual).is_ok() =>
             {
                 err.span_suggestion_verbose(
@@ -665,7 +665,7 @@ fn suggest_adding_missing_ref_or_removing_ref(
                     Applicability::MaybeIncorrect,
                 );
             }
-            (_, ty::Ref(_, inner_ty, _), hir::BindingAnnotation::Ref)
+            (_, ty::Ref(_, inner_ty, _), hir::BindingAnnotation::REF)
                 if self.can_eq(self.param_env, expected, *inner_ty).is_ok() =>
             {
                 err.span_suggestion_verbose(
index 0081e9049eeca87a7cd612a06f4835c3c71f307f..b779713482e14872e63107276552672c5e06b269 100644 (file)
@@ -587,8 +587,7 @@ fn is_binding_pat(pat: &hir::Pat<'_>) -> bool {
         // & expression, and its lifetime would be extended to the end of the block (due
         // to a different rule, not the below code).
         match pat.kind {
-            PatKind::Binding(hir::BindingAnnotation::Ref, ..)
-            | PatKind::Binding(hir::BindingAnnotation::RefMut, ..) => true,
+            PatKind::Binding(hir::BindingAnnotation(hir::ByRef::Yes, _), ..) => true,
 
             PatKind::Struct(_, ref field_pats, _) => {
                 field_pats.iter().any(|fp| is_binding_pat(&fp.pat))
@@ -607,10 +606,7 @@ fn is_binding_pat(pat: &hir::Pat<'_>) -> bool {
             PatKind::Box(ref subpat) => is_binding_pat(&subpat),
 
             PatKind::Ref(_, _)
-            | PatKind::Binding(
-                hir::BindingAnnotation::Unannotated | hir::BindingAnnotation::Mutable,
-                ..,
-            )
+            | PatKind::Binding(hir::BindingAnnotation(hir::ByRef::No, _), ..)
             | PatKind::Wild
             | PatKind::Path(_)
             | PatKind::Lit(_)
index 0afc153300bf2449c381744a26b415ab3b8677e0..0b207a6c0bee1d8fbf3b5a1941bf565075c2ebc0 100644 (file)
@@ -2024,6 +2024,10 @@ fn should_do_rust_2021_incompatible_closure_captures_analysis(
     tcx: TyCtxt<'_>,
     closure_id: hir::HirId,
 ) -> bool {
+    if tcx.sess.rust_2021() {
+        return false;
+    }
+
     let (level, _) =
         tcx.lint_level_at_node(lint::builtin::RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES, closure_id);
 
index ba42453bd60e920286239085eeb96203479087a8..5c6c8aca173466902557d2094aca2ec48f109bfd 100644 (file)
@@ -768,7 +768,7 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
 fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool {
     match ty.kind {
         hir::TyKind::TraitObject([trait_ref], ..) => match trait_ref.trait_ref.path.segments {
-            [s] => s.res.and_then(|r| r.opt_def_id()) == Some(trait_def_id.to_def_id()),
+            [s] => s.res.opt_def_id() == Some(trait_def_id.to_def_id()),
             _ => false,
         },
         _ => false,
@@ -972,7 +972,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
     }
 }
 
-#[tracing::instrument(level = "debug", skip(tcx, span, sig_if_method))]
+#[instrument(level = "debug", skip(tcx, span, sig_if_method))]
 fn check_associated_item(
     tcx: TyCtxt<'_>,
     item_id: LocalDefId,
@@ -1225,7 +1225,7 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: LocalDefId, ty_span: Span, allow_fo
     });
 }
 
-#[tracing::instrument(level = "debug", skip(tcx, ast_self_ty, ast_trait_ref))]
+#[instrument(level = "debug", skip(tcx, ast_self_ty, ast_trait_ref))]
 fn check_impl<'tcx>(
     tcx: TyCtxt<'tcx>,
     item: &'tcx hir::Item<'tcx>,
@@ -1472,7 +1472,7 @@ fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
     wfcx.register_obligations(obligations);
 }
 
-#[tracing::instrument(level = "debug", skip(wfcx, span, hir_decl))]
+#[instrument(level = "debug", skip(wfcx, span, hir_decl))]
 fn check_fn_or_method<'tcx>(
     wfcx: &WfCheckingCtxt<'_, 'tcx>,
     span: Span,
@@ -1536,7 +1536,7 @@ fn check_fn_or_method<'tcx>(
      `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one \
      of the previous types except `Self`)";
 
-#[tracing::instrument(level = "debug", skip(wfcx))]
+#[instrument(level = "debug", skip(wfcx))]
 fn check_method_receiver<'tcx>(
     wfcx: &WfCheckingCtxt<'_, 'tcx>,
     fn_sig: &hir::FnSig<'_>,
index f1dbe64f13abbb33e3cb4a323abb015be0288489..a0280ddca4bd8dbdeb47e99d4364b3873584ef69 100644 (file)
@@ -1,6 +1,5 @@
 use rustc_errors::{Applicability, StashKey};
 use rustc_hir as hir;
-use rustc_hir::def::Res;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit;
 use rustc_hir::intravisit::Visitor;
@@ -19,7 +18,6 @@
 /// Computes the relevant generic parameter for a potential generic const argument.
 ///
 /// This should be called using the query `tcx.opt_const_param_of`.
-#[instrument(level = "debug", skip(tcx))]
 pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<DefId> {
     use hir::*;
     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
@@ -79,7 +77,7 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
                         args.args
                             .iter()
                             .filter(|arg| arg.is_ty_or_const())
-                            .position(|arg| arg.id() == hir_id)
+                            .position(|arg| arg.hir_id() == hir_id)
                     })
                     .unwrap_or_else(|| {
                         bug!("no arg matching AnonConst in segment");
@@ -112,7 +110,7 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
                     args.args
                         .iter()
                         .filter(|arg| arg.is_ty_or_const())
-                        .position(|arg| arg.id() == hir_id)
+                        .position(|arg| arg.hir_id() == hir_id)
                 })
                 .unwrap_or_else(|| {
                     bug!("no arg matching AnonConst in segment");
@@ -166,7 +164,7 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
                 args.args
                 .iter()
                 .filter(|arg| arg.is_ty_or_const())
-                .position(|arg| arg.id() == hir_id)
+                .position(|arg| arg.hir_id() == hir_id)
                 .map(|index| (index, seg)).or_else(|| args.bindings
                     .iter()
                     .filter_map(TypeBinding::opt_const)
@@ -180,15 +178,12 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
                 return None;
             };
 
-            // Try to use the segment resolution if it is valid, otherwise we
-            // default to the path resolution.
-            let res = segment.res.filter(|&r| r != Res::Err).unwrap_or(path.res);
-            let generics = match tcx.res_generics_def_id(res) {
+            let generics = match tcx.res_generics_def_id(segment.res) {
                 Some(def_id) => tcx.generics_of(def_id),
                 None => {
                     tcx.sess.delay_span_bug(
                         tcx.def_span(def_id),
-                        &format!("unexpected anon const res {:?} in path: {:?}", res, path),
+                        &format!("unexpected anon const res {:?} in path: {:?}", segment.res, path),
                     );
                     return None;
                 }
@@ -229,7 +224,7 @@ fn get_path_containing_arg_in_pat<'hir>(
             .iter()
             .filter_map(|seg| seg.args)
             .flat_map(|args| args.args)
-            .any(|arg| arg.id() == arg_id)
+            .any(|arg| arg.hir_id() == arg_id)
     };
     let mut arg_path = None;
     pat.walk(|pat| match pat.kind {
index bfc4f061b70f492f7ebfced4da35d8353328e9aa..f483342b445f60471f3c643dea136efd0b696cfa 100644 (file)
@@ -233,8 +233,9 @@ pub fn walk_expr(&mut self, expr: &hir::Expr<'_>) {
                 self.consume_exprs(args);
             }
 
-            hir::ExprKind::MethodCall(.., args, _) => {
+            hir::ExprKind::MethodCall(.., receiver, args, _) => {
                 // callee.m(args)
+                self.consume_expr(receiver);
                 self.consume_exprs(args);
             }
 
index 8e910441a5d99d7ab676305a17e30d6c5e37c79b..ac66819d2836f03fbd508c9c47c565da9ddc17eb 100644 (file)
@@ -444,7 +444,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
 
 fn check_for_entry_fn(tcx: TyCtxt<'_>) {
     match tcx.entry_fn(()) {
-        Some((def_id, EntryFnType::Main)) => check_main_fn_ty(tcx, def_id),
+        Some((def_id, EntryFnType::Main { .. })) => check_main_fn_ty(tcx, def_id),
         Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id),
         _ => {}
     }
index d4b5e5e2fe44df3e917c11a7d97d9fb72929e067..cddb0ce2346ad7a56f16ab714bdba9bcf9fd0944 100644 (file)
@@ -291,62 +291,60 @@ fn get_quantifier_and_bound(&self) -> (&'static str, usize) {
     // Creates lifetime name suggestions from the lifetime parameter names
     fn get_lifetime_args_suggestions_from_param_names(
         &self,
-        path_hir_id: Option<hir::HirId>,
+        path_hir_id: hir::HirId,
         num_params_to_take: usize,
     ) -> String {
         debug!(?path_hir_id);
 
-        if let Some(path_hir_id) = path_hir_id {
-            let mut ret = Vec::new();
-            for (id, node) in self.tcx.hir().parent_iter(path_hir_id) {
-                debug!(?id);
-                let params = if let Some(generics) = node.generics() {
-                    generics.params
-                } else if let hir::Node::Ty(ty) = node
-                    && let hir::TyKind::BareFn(bare_fn) = ty.kind
-                {
-                    bare_fn.generic_params
-                } else {
-                    &[]
-                };
-                ret.extend(params.iter().filter_map(|p| {
-                    let hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit }
-                        = p.kind
-                    else { return None };
-                    let hir::ParamName::Plain(name) = p.name else { return None };
-                    Some(name.to_string())
-                }));
-                // Suggest `'static` when in const/static item-like.
-                if let hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Static { .. } | hir::ItemKind::Const { .. },
-                    ..
-                })
-                | hir::Node::TraitItem(hir::TraitItem {
-                    kind: hir::TraitItemKind::Const { .. },
-                    ..
-                })
-                | hir::Node::ImplItem(hir::ImplItem {
-                    kind: hir::ImplItemKind::Const { .. },
-                    ..
-                })
-                | hir::Node::ForeignItem(hir::ForeignItem {
-                    kind: hir::ForeignItemKind::Static { .. },
-                    ..
-                })
-                | hir::Node::AnonConst(..) = node
-                {
-                    ret.extend(
-                        std::iter::repeat("'static".to_owned())
-                            .take(num_params_to_take.saturating_sub(ret.len())),
-                    );
-                }
-                if ret.len() >= num_params_to_take {
-                    return ret[..num_params_to_take].join(", ");
-                }
-                // We cannot refer to lifetimes defined in an outer function.
-                if let hir::Node::Item(_) = node {
-                    break;
-                }
+        let mut ret = Vec::new();
+        for (id, node) in self.tcx.hir().parent_iter(path_hir_id) {
+            debug!(?id);
+            let params = if let Some(generics) = node.generics() {
+                generics.params
+            } else if let hir::Node::Ty(ty) = node
+                && let hir::TyKind::BareFn(bare_fn) = ty.kind
+            {
+                bare_fn.generic_params
+            } else {
+                &[]
+            };
+            ret.extend(params.iter().filter_map(|p| {
+                let hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit }
+                    = p.kind
+                else { return None };
+                let hir::ParamName::Plain(name) = p.name else { return None };
+                Some(name.to_string())
+            }));
+            // Suggest `'static` when in const/static item-like.
+            if let hir::Node::Item(hir::Item {
+                kind: hir::ItemKind::Static { .. } | hir::ItemKind::Const { .. },
+                ..
+            })
+            | hir::Node::TraitItem(hir::TraitItem {
+                kind: hir::TraitItemKind::Const { .. },
+                ..
+            })
+            | hir::Node::ImplItem(hir::ImplItem {
+                kind: hir::ImplItemKind::Const { .. },
+                ..
+            })
+            | hir::Node::ForeignItem(hir::ForeignItem {
+                kind: hir::ForeignItemKind::Static { .. },
+                ..
+            })
+            | hir::Node::AnonConst(..) = node
+            {
+                ret.extend(
+                    std::iter::repeat("'static".to_owned())
+                        .take(num_params_to_take.saturating_sub(ret.len())),
+                );
+            }
+            if ret.len() >= num_params_to_take {
+                return ret[..num_params_to_take].join(", ");
+            }
+            // We cannot refer to lifetimes defined in an outer function.
+            if let hir::Node::Item(_) = node {
+                break;
             }
         }
 
@@ -690,8 +688,7 @@ fn suggest_moving_args_from_assoc_fn_to_trait(&self, err: &mut Diagnostic) {
             num = num_trait_generics_except_self,
         );
 
-        if let Some(hir_id) = self.path_segment.hir_id
-        && let Some(parent_node) = self.tcx.hir().find_parent_node(hir_id)
+        if let Some(parent_node) = self.tcx.hir().find_parent_node(self.path_segment.hir_id)
         && let Some(parent_node) = self.tcx.hir().find(parent_node)
         && let hir::Node::Expr(expr) = parent_node {
             match expr.kind {
@@ -758,13 +755,13 @@ fn suggest_moving_args_from_assoc_fn_to_trait_for_method_call(
         num_assoc_fn_excess_args: usize,
         num_trait_generics_except_self: usize,
     ) {
-        if let hir::ExprKind::MethodCall(_, args, _) = expr.kind {
-            assert_eq!(args.len(), 1);
+        if let hir::ExprKind::MethodCall(_, receiver, args, ..) = expr.kind {
+            assert_eq!(args.len(), 0);
             if num_assoc_fn_excess_args == num_trait_generics_except_self {
                 if let Some(gen_args) = self.gen_args.span_ext()
                 && let Ok(gen_args) = self.tcx.sess.source_map().span_to_snippet(gen_args)
-                && let Ok(args) = self.tcx.sess.source_map().span_to_snippet(args[0].span) {
-                    let sugg = format!("{}::{}::{}({})", self.tcx.item_name(trait_), gen_args, self.tcx.item_name(self.def_id), args);
+                && let Ok(receiver) = self.tcx.sess.source_map().span_to_snippet(receiver.span) {
+                    let sugg = format!("{}::{}::{}({})", self.tcx.item_name(trait_), gen_args, self.tcx.item_name(self.def_id), receiver);
                     err.span_suggestion(expr.span, msg, sugg, Applicability::MaybeIncorrect);
                 }
             }
index b320cdcc109ddc061fec4a33b2fea4b379ed89e3..a967d881b029b7facb6af929d2d18c3fc6bc6d93 100644 (file)
@@ -666,6 +666,10 @@ changelog-seen = 2
 # target.
 #llvm-config = <none> (path)
 
+# Override detection of whether this is a Rust-patched LLVM. This would be used
+# in conjunction with either an llvm-config or build.submodules = false.
+#llvm-has-rust-patches = if llvm-config { false } else { true }
+
 # Normally the build system can find LLVM's FileCheck utility, but if
 # not, you can specify an explicit file name for it.
 #llvm-filecheck = "/path/to/llvm-version/bin/FileCheck"
index 60bf83b8387c38c135d51b51329774d9638c836b..17ee78045a9b2b8d089f6880ecd21d35fda28111 100644 (file)
@@ -3,7 +3,9 @@
 /// A iterator for deduping the key of a sorted iterator.
 /// When encountering the duplicated key, only the last key-value pair is yielded.
 ///
-/// Used by [`BTreeMap::bulk_build_from_sorted_iter`].
+/// Used by [`BTreeMap::bulk_build_from_sorted_iter`][1].
+///
+/// [1]: crate::collections::BTreeMap::bulk_build_from_sorted_iter
 pub struct DedupSortedIter<K, V, I>
 where
     I: Iterator<Item = (K, V)>,
index ad6d19bbc6875203d6e721d85be0d53684e4048a..e5cf9033c86033caebd75a01cc3c6f54ebb55054 100644 (file)
 #![feature(ptr_metadata)]
 #![feature(ptr_sub_ptr)]
 #![feature(receiver_trait)]
+#![feature(saturating_int_impl)]
 #![feature(set_ptr_value)]
 #![feature(slice_from_ptr_range)]
 #![feature(slice_group_by)]
index 92a32779b8e64b4866e0fb9a9707b10a51c6c261..2e025c8a4a5d3fd843cbbbab43e3dd9c8533ab3d 100644 (file)
@@ -1,3 +1,5 @@
+use core::num::{Saturating, Wrapping};
+
 use crate::boxed::Box;
 
 #[rustc_specialization_trait]
@@ -144,3 +146,17 @@ fn is_zero(&self) -> bool {
     NonZeroUsize,
     NonZeroIsize,
 );
+
+unsafe impl<T: IsZero> IsZero for Wrapping<T> {
+    #[inline]
+    fn is_zero(&self) -> bool {
+        self.0.is_zero()
+    }
+}
+
+unsafe impl<T: IsZero> IsZero for Saturating<T> {
+    #[inline]
+    fn is_zero(&self) -> bool {
+        self.0.is_zero()
+    }
+}
index 4e5a3f72929f152752d5659e95bb15c8f6b41eff..07872f28cd8a65c3c7428811548dc85f1f2fb05b 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 4e5a3f72929f152752d5659e95bb15c8f6b41eff
+Subproject commit 07872f28cd8a65c3c7428811548dc85f1f2fb05b
index e54f6c912d5945eacdc096a27c4b5b52222a6575..1a379ecc11c01d7ae8cdfde75d8a591425eaa2ca 100644 (file)
@@ -796,7 +796,7 @@ pub trait Provider {
     /// impl Provider for SomeConcreteType {
     ///     fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
     ///         demand.provide_ref::<str>(&self.field)
-    ///             .provide_value::<i32>(|| self.num_field);
+    ///             .provide_value::<i32>(self.num_field);
     ///     }
     /// }
     /// ```
@@ -881,28 +881,55 @@ fn new<'b>(erased: &'b mut (dyn Erased<'a> + 'a)) -> &'b mut Demand<'a> {
     ///
     /// # Examples
     ///
+    /// Provides an `u8`.
+    ///
+    /// ```rust
+    /// #![feature(provide_any)]
+    ///
+    /// use std::any::{Provider, Demand};
+    /// # struct SomeConcreteType { field: u8 }
+    ///
+    /// impl Provider for SomeConcreteType {
+    ///     fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
+    ///         demand.provide_value::<u8>(self.field);
+    ///     }
+    /// }
+    /// ```
+    #[unstable(feature = "provide_any", issue = "96024")]
+    pub fn provide_value<T>(&mut self, value: T) -> &mut Self
+    where
+        T: 'static,
+    {
+        self.provide::<tags::Value<T>>(value)
+    }
+
+    /// Provide a value or other type with only static lifetimes computed using a closure.
+    ///
+    /// # Examples
+    ///
     /// Provides a `String` by cloning.
     ///
     /// ```rust
-    /// # #![feature(provide_any)]
+    /// #![feature(provide_any)]
+    ///
     /// use std::any::{Provider, Demand};
     /// # struct SomeConcreteType { field: String }
     ///
     /// impl Provider for SomeConcreteType {
     ///     fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
-    ///         demand.provide_value::<String>(|| self.field.clone());
+    ///         demand.provide_value_with::<String>(|| self.field.clone());
     ///     }
     /// }
     /// ```
     #[unstable(feature = "provide_any", issue = "96024")]
-    pub fn provide_value<T>(&mut self, fulfil: impl FnOnce() -> T) -> &mut Self
+    pub fn provide_value_with<T>(&mut self, fulfil: impl FnOnce() -> T) -> &mut Self
     where
         T: 'static,
     {
         self.provide_with::<tags::Value<T>>(fulfil)
     }
 
-    /// Provide a reference, note that the referee type must be bounded by `'static`,
+    /// Provide a reference. The referee type must be bounded by `'static`,
     /// but may be unsized.
     ///
     /// # Examples
@@ -910,7 +937,8 @@ pub fn provide_value<T>(&mut self, fulfil: impl FnOnce() -> T) -> &mut Self
     /// Provides a reference to a field as a `&str`.
     ///
     /// ```rust
-    /// # #![feature(provide_any)]
+    /// #![feature(provide_any)]
+    ///
     /// use std::any::{Provider, Demand};
     /// # struct SomeConcreteType { field: String }
     ///
@@ -925,6 +953,40 @@ pub fn provide_ref<T: ?Sized + 'static>(&mut self, value: &'a T) -> &mut Self {
         self.provide::<tags::Ref<tags::MaybeSizedValue<T>>>(value)
     }
 
+    /// Provide a reference computed using a closure. The referee type
+    /// must be bounded by `'static`, but may be unsized.
+    ///
+    /// # Examples
+    ///
+    /// Provides a reference to a field as a `&str`.
+    ///
+    /// ```rust
+    /// #![feature(provide_any)]
+    ///
+    /// use std::any::{Provider, Demand};
+    /// # struct SomeConcreteType { business: String, party: String }
+    /// # fn today_is_a_weekday() -> bool { true }
+    ///
+    /// impl Provider for SomeConcreteType {
+    ///     fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
+    ///         demand.provide_ref_with::<str>(|| {
+    ///             if today_is_a_weekday() {
+    ///                 &self.business
+    ///             } else {
+    ///                 &self.party
+    ///             }
+    ///         });
+    ///     }
+    /// }
+    /// ```
+    #[unstable(feature = "provide_any", issue = "96024")]
+    pub fn provide_ref_with<T: ?Sized + 'static>(
+        &mut self,
+        fulfil: impl FnOnce() -> &'a T,
+    ) -> &mut Self {
+        self.provide_with::<tags::Ref<tags::MaybeSizedValue<T>>>(fulfil)
+    }
+
     /// Provide a value with the given `Type` tag.
     fn provide<I>(&mut self, value: I::Reified) -> &mut Self
     where
@@ -946,6 +1008,156 @@ fn provide_with<I>(&mut self, fulfil: impl FnOnce() -> I::Reified) -> &mut Self
         }
         self
     }
+
+    /// Check if the `Demand` would be satisfied if provided with a
+    /// value of the specified type. If the type does not match or has
+    /// already been provided, returns false.
+    ///
+    /// # Examples
+    ///
+    /// Check if an `u8` still needs to be provided and then provides
+    /// it.
+    ///
+    /// ```rust
+    /// #![feature(provide_any)]
+    ///
+    /// use std::any::{Provider, Demand};
+    ///
+    /// struct Parent(Option<u8>);
+    ///
+    /// impl Provider for Parent {
+    ///     fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
+    ///         if let Some(v) = self.0 {
+    ///             demand.provide_value::<u8>(v);
+    ///         }
+    ///     }
+    /// }
+    ///
+    /// struct Child {
+    ///     parent: Parent,
+    /// }
+    ///
+    /// impl Child {
+    ///     // Pretend that this takes a lot of resources to evaluate.
+    ///     fn an_expensive_computation(&self) -> Option<u8> {
+    ///         Some(99)
+    ///     }
+    /// }
+    ///
+    /// impl Provider for Child {
+    ///     fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
+    ///         // In general, we don't know if this call will provide
+    ///         // an `u8` value or not...
+    ///         self.parent.provide(demand);
+    ///
+    ///         // ...so we check to see if the `u8` is needed before
+    ///         // we run our expensive computation.
+    ///         if demand.would_be_satisfied_by_value_of::<u8>() {
+    ///             if let Some(v) = self.an_expensive_computation() {
+    ///                 demand.provide_value::<u8>(v);
+    ///             }
+    ///         }
+    ///
+    ///         // The demand will be satisfied now, regardless of if
+    ///         // the parent provided the value or we did.
+    ///         assert!(!demand.would_be_satisfied_by_value_of::<u8>());
+    ///     }
+    /// }
+    ///
+    /// let parent = Parent(Some(42));
+    /// let child = Child { parent };
+    /// assert_eq!(Some(42), std::any::request_value::<u8>(&child));
+    ///
+    /// let parent = Parent(None);
+    /// let child = Child { parent };
+    /// assert_eq!(Some(99), std::any::request_value::<u8>(&child));
+    /// ```
+    #[unstable(feature = "provide_any", issue = "96024")]
+    pub fn would_be_satisfied_by_value_of<T>(&self) -> bool
+    where
+        T: 'static,
+    {
+        self.would_be_satisfied_by::<tags::Value<T>>()
+    }
+
+    /// Check if the `Demand` would be satisfied if provided with a
+    /// reference to a value of the specified type. If the type does
+    /// not match or has already been provided, returns false.
+    ///
+    /// # Examples
+    ///
+    /// Check if a `&str` still needs to be provided and then provides
+    /// it.
+    ///
+    /// ```rust
+    /// #![feature(provide_any)]
+    ///
+    /// use std::any::{Provider, Demand};
+    ///
+    /// struct Parent(Option<String>);
+    ///
+    /// impl Provider for Parent {
+    ///     fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
+    ///         if let Some(v) = &self.0 {
+    ///             demand.provide_ref::<str>(v);
+    ///         }
+    ///     }
+    /// }
+    ///
+    /// struct Child {
+    ///     parent: Parent,
+    ///     name: String,
+    /// }
+    ///
+    /// impl Child {
+    ///     // Pretend that this takes a lot of resources to evaluate.
+    ///     fn an_expensive_computation(&self) -> Option<&str> {
+    ///         Some(&self.name)
+    ///     }
+    /// }
+    ///
+    /// impl Provider for Child {
+    ///     fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
+    ///         // In general, we don't know if this call will provide
+    ///         // a `str` reference or not...
+    ///         self.parent.provide(demand);
+    ///
+    ///         // ...so we check to see if the `&str` is needed before
+    ///         // we run our expensive computation.
+    ///         if demand.would_be_satisfied_by_ref_of::<str>() {
+    ///             if let Some(v) = self.an_expensive_computation() {
+    ///                 demand.provide_ref::<str>(v);
+    ///             }
+    ///         }
+    ///
+    ///         // The demand will be satisfied now, regardless of if
+    ///         // the parent provided the reference or we did.
+    ///         assert!(!demand.would_be_satisfied_by_ref_of::<str>());
+    ///     }
+    /// }
+    ///
+    /// let parent = Parent(Some("parent".into()));
+    /// let child = Child { parent, name: "child".into() };
+    /// assert_eq!(Some("parent"), std::any::request_ref::<str>(&child));
+    ///
+    /// let parent = Parent(None);
+    /// let child = Child { parent, name: "child".into() };
+    /// assert_eq!(Some("child"), std::any::request_ref::<str>(&child));
+    /// ```
+    #[unstable(feature = "provide_any", issue = "96024")]
+    pub fn would_be_satisfied_by_ref_of<T>(&self) -> bool
+    where
+        T: ?Sized + 'static,
+    {
+        self.would_be_satisfied_by::<tags::Ref<tags::MaybeSizedValue<T>>>()
+    }
+
+    fn would_be_satisfied_by<I>(&self) -> bool
+    where
+        I: tags::Type<'a>,
+    {
+        matches!(self.0.downcast::<I>(), Some(TaggedOption(None)))
+    }
 }
 
 #[unstable(feature = "provide_any", issue = "96024")]
@@ -1050,6 +1262,21 @@ impl<'a> dyn Erased<'a> + 'a {
     /// Returns some reference to the dynamic value if it is tagged with `I`,
     /// or `None` otherwise.
     #[inline]
+    fn downcast<I>(&self) -> Option<&TaggedOption<'a, I>>
+    where
+        I: tags::Type<'a>,
+    {
+        if self.tag_id() == TypeId::of::<I>() {
+            // SAFETY: Just checked whether we're pointing to an I.
+            Some(unsafe { &*(self as *const Self).cast::<TaggedOption<'a, I>>() })
+        } else {
+            None
+        }
+    }
+
+    /// Returns some mutable reference to the dynamic value if it is tagged with `I`,
+    /// or `None` otherwise.
+    #[inline]
     fn downcast_mut<I>(&mut self) -> Option<&mut TaggedOption<'a, I>>
     where
         I: tags::Type<'a>,
index 2433139a592b568b9399c8ec0306ac1d9df1e01f..b7a63b7c675666d627f4ac9c504b89955390a56c 100644 (file)
@@ -746,10 +746,19 @@ pub fn is_alphabetic(self) -> bool {
     /// assert!(!'中'.is_lowercase());
     /// assert!(!' '.is_lowercase());
     /// ```
+    ///
+    /// In a const context:
+    ///
+    /// ```
+    /// #![feature(const_unicode_case_lookup)]
+    /// const CAPITAL_DELTA_IS_LOWERCASE: bool = 'Δ'.is_lowercase();
+    /// assert!(!CAPITAL_DELTA_IS_LOWERCASE);
+    /// ```
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_unstable(feature = "const_unicode_case_lookup", issue = "101400")]
     #[inline]
-    pub fn is_lowercase(self) -> bool {
+    pub const fn is_lowercase(self) -> bool {
         match self {
             'a'..='z' => true,
             c => c > '\x7f' && unicode::Lowercase(c),
@@ -779,10 +788,19 @@ pub fn is_lowercase(self) -> bool {
     /// assert!(!'中'.is_uppercase());
     /// assert!(!' '.is_uppercase());
     /// ```
+    ///
+    /// In a const context:
+    ///
+    /// ```
+    /// #![feature(const_unicode_case_lookup)]
+    /// const CAPITAL_DELTA_IS_UPPERCASE: bool = 'Δ'.is_uppercase();
+    /// assert!(CAPITAL_DELTA_IS_UPPERCASE);
+    /// ```
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_unstable(feature = "const_unicode_case_lookup", issue = "101400")]
     #[inline]
-    pub fn is_uppercase(self) -> bool {
+    pub const fn is_uppercase(self) -> bool {
         match self {
             'A'..='Z' => true,
             c => c > '\x7f' && unicode::Uppercase(c),
index d610f0a02f40310d8b1090e65395c432ce141fd9..56f5824efd4ca15e7fe9a705e929435af890a604 100644 (file)
@@ -54,7 +54,9 @@
 )]
 #![allow(missing_docs)]
 
-use crate::marker::{Destruct, DiscriminantKind};
+#[cfg(bootstrap)]
+use crate::marker::Destruct;
+use crate::marker::DiscriminantKind;
 use crate::mem;
 
 // These imports are used for simplifying intra-doc links
@@ -2085,6 +2087,65 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
     /// `ptr` must point to a vtable.
     /// The intrinsic will return the alignment stored in that vtable.
     pub fn vtable_align(ptr: *const ()) -> usize;
+
+    /// Selects which function to call depending on the context.
+    ///
+    /// If this function is evaluated at compile-time, then a call to this
+    /// intrinsic will be replaced with a call to `called_in_const`. It gets
+    /// replaced with a call to `called_at_rt` otherwise.
+    ///
+    /// # Type Requirements
+    ///
+    /// The two functions must be both function items. They cannot be function
+    /// pointers or closures. The first function must be a `const fn`.
+    ///
+    /// `arg` will be the tupled arguments that will be passed to either one of
+    /// the two functions, therefore, both functions must accept the same type of
+    /// arguments. Both functions must return RET.
+    ///
+    /// # Safety
+    ///
+    /// The two functions must behave observably equivalent. Safe code in other
+    /// crates may assume that calling a `const fn` at compile-time and at run-time
+    /// produces the same result. A function that produces a different result when
+    /// evaluated at run-time, or has any other observable side-effects, is
+    /// *unsound*.
+    ///
+    /// Here is an example of how this could cause a problem:
+    /// ```no_run
+    /// #![feature(const_eval_select)]
+    /// #![feature(core_intrinsics)]
+    /// use std::hint::unreachable_unchecked;
+    /// use std::intrinsics::const_eval_select;
+    ///
+    /// // Crate A
+    /// pub const fn inconsistent() -> i32 {
+    ///     fn runtime() -> i32 { 1 }
+    ///     const fn compiletime() -> i32 { 2 }
+    ///
+    ///     unsafe {
+    //          // ⚠ This code violates the required equivalence of `compiletime`
+    ///         // and `runtime`.
+    ///         const_eval_select((), compiletime, runtime)
+    ///     }
+    /// }
+    ///
+    /// // Crate B
+    /// const X: i32 = inconsistent();
+    /// let x = inconsistent();
+    /// if x != X { unsafe { unreachable_unchecked(); }}
+    /// ```
+    ///
+    /// This code causes Undefined Behavior when being run, since the
+    /// `unreachable_unchecked` is actually being reached. The bug is in *crate A*,
+    /// which violates the principle that a `const fn` must behave the same at
+    /// compile-time and at run-time. The unsafe code in crate B is fine.
+    #[cfg(not(bootstrap))]
+    #[rustc_const_unstable(feature = "const_eval_select", issue = "none")]
+    pub fn const_eval_select<ARG, F, G, RET>(arg: ARG, called_in_const: F, called_at_rt: G) -> RET
+    where
+        G: FnOnce<ARG, Output = RET>,
+        F: FnOnce<ARG, Output = RET>;
 }
 
 // Some functions are defined here because they accidentally got made
@@ -2095,6 +2156,11 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
 /// Check that the preconditions of an unsafe function are followed, if debug_assertions are on,
 /// and only at runtime.
 ///
+/// This macro should be called as `assert_unsafe_precondition!([Generics](name: Type) => Expression)`
+/// where the names specified will be moved into the macro as captured variables, and defines an item
+/// to call `const_eval_select` on. The tokens inside the square brackets are used to denote generics
+/// for the function declaractions and can be omitted if there is no generics.
+///
 /// # Safety
 ///
 /// Invoking this macro is only sound if the following code is already UB when the passed
@@ -2109,18 +2175,21 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
 /// the occasional mistake, and this check should help them figure things out.
 #[allow_internal_unstable(const_eval_select)] // permit this to be called in stably-const fn
 macro_rules! assert_unsafe_precondition {
-    ($e:expr) => {
+    ($([$($tt:tt)*])?($($i:ident:$ty:ty),*$(,)?) => $e:expr) => {
         if cfg!(debug_assertions) {
-            // Use a closure so that we can capture arbitrary expressions from the invocation
-            let runtime = || {
+            // allow non_snake_case to allow capturing const generics
+            #[allow(non_snake_case)]
+            #[inline(always)]
+            fn runtime$(<$($tt)*>)?($($i:$ty),*) {
                 if !$e {
                     // abort instead of panicking to reduce impact on code size
                     ::core::intrinsics::abort();
                 }
-            };
-            const fn comptime() {}
+            }
+            #[allow(non_snake_case)]
+            const fn comptime$(<$($tt)*>)?($(_:$ty),*) {}
 
-            ::core::intrinsics::const_eval_select((), comptime, runtime);
+            ::core::intrinsics::const_eval_select(($($i,)*), comptime, runtime);
         }
     };
 }
@@ -2243,7 +2312,7 @@ pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -
     // SAFETY: the safety contract for `copy_nonoverlapping` must be
     // upheld by the caller.
     unsafe {
-        assert_unsafe_precondition!(
+        assert_unsafe_precondition!([T](src: *const T, dst: *mut T, count: usize) =>
             is_aligned_and_not_null(src)
                 && is_aligned_and_not_null(dst)
                 && is_nonoverlapping(src, dst, count)
@@ -2329,7 +2398,8 @@ pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -
 
     // SAFETY: the safety contract for `copy` must be upheld by the caller.
     unsafe {
-        assert_unsafe_precondition!(is_aligned_and_not_null(src) && is_aligned_and_not_null(dst));
+        assert_unsafe_precondition!([T](src: *const T, dst: *mut T) =>
+            is_aligned_and_not_null(src) && is_aligned_and_not_null(dst));
         copy(src, dst, count)
     }
 }
@@ -2397,63 +2467,12 @@ pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -
 
     // SAFETY: the safety contract for `write_bytes` must be upheld by the caller.
     unsafe {
-        assert_unsafe_precondition!(is_aligned_and_not_null(dst));
+        assert_unsafe_precondition!([T](dst: *mut T) => is_aligned_and_not_null(dst));
         write_bytes(dst, val, count)
     }
 }
 
-/// Selects which function to call depending on the context.
-///
-/// If this function is evaluated at compile-time, then a call to this
-/// intrinsic will be replaced with a call to `called_in_const`. It gets
-/// replaced with a call to `called_at_rt` otherwise.
-///
-/// # Type Requirements
-///
-/// The two functions must be both function items. They cannot be function
-/// pointers or closures.
-///
-/// `arg` will be the arguments that will be passed to either one of the
-/// two functions, therefore, both functions must accept the same type of
-/// arguments. Both functions must return RET.
-///
-/// # Safety
-///
-/// The two functions must behave observably equivalent. Safe code in other
-/// crates may assume that calling a `const fn` at compile-time and at run-time
-/// produces the same result. A function that produces a different result when
-/// evaluated at run-time, or has any other observable side-effects, is
-/// *unsound*.
-///
-/// Here is an example of how this could cause a problem:
-/// ```no_run
-/// #![feature(const_eval_select)]
-/// #![feature(core_intrinsics)]
-/// use std::hint::unreachable_unchecked;
-/// use std::intrinsics::const_eval_select;
-///
-/// // Crate A
-/// pub const fn inconsistent() -> i32 {
-///     fn runtime() -> i32 { 1 }
-///     const fn compiletime() -> i32 { 2 }
-///
-///     unsafe {
-//          // ⚠ This code violates the required equivalence of `compiletime`
-///         // and `runtime`.
-///         const_eval_select((), compiletime, runtime)
-///     }
-/// }
-///
-/// // Crate B
-/// const X: i32 = inconsistent();
-/// let x = inconsistent();
-/// if x != X { unsafe { unreachable_unchecked(); }}
-/// ```
-///
-/// This code causes Undefined Behavior when being run, since the
-/// `unreachable_unchecked` is actually being reached. The bug is in *crate A*,
-/// which violates the principle that a `const fn` must behave the same at
-/// compile-time and at run-time. The unsafe code in crate B is fine.
+#[cfg(bootstrap)]
 #[unstable(
     feature = "const_eval_select",
     issue = "none",
@@ -2475,6 +2494,7 @@ pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -
     called_at_rt.call_once(arg)
 }
 
+#[cfg(bootstrap)]
 #[unstable(
     feature = "const_eval_select",
     issue = "none",
index bf75796f1fcb2d2bc6fedf979848b0e0f3854d9c..5b1e2045fff63e07df043843dfdd1872b635abdf 100644 (file)
@@ -93,6 +93,7 @@
 #![warn(missing_debug_implementations)]
 #![warn(missing_docs)]
 #![allow(explicit_outlives_requirements)]
+#![allow(incomplete_features)]
 //
 // Library features:
 #![feature(const_align_offset)]
 #![feature(const_type_id)]
 #![feature(const_type_name)]
 #![feature(const_default_impls)]
+#![feature(const_unicode_case_lookup)]
 #![feature(const_unsafecell_get_mut)]
 #![feature(core_panic)]
 #![feature(duration_consts_float)]
 //
 // Language features:
 #![feature(abi_unadjusted)]
+#![feature(adt_const_params)]
 #![feature(allow_internal_unsafe)]
 #![feature(allow_internal_unstable)]
 #![feature(associated_type_bounds)]
index b4fabedad7829e76e475b9abfd841318baa947f8..87a378631050a941a45094f29bc8735b0bb8ab3b 100644 (file)
@@ -4,25 +4,20 @@
 /// any value of type `Self` are safely transmutable into a value of type `Dst`, in a given `Context`,
 /// notwithstanding whatever safety checks you have asked the compiler to [`Assume`] are satisfied.
 #[unstable(feature = "transmutability", issue = "99571")]
-#[lang = "transmute_trait"]
+#[cfg_attr(not(bootstrap), lang = "transmute_trait")]
 #[rustc_on_unimplemented(
     message = "`{Src}` cannot be safely transmuted into `{Self}` in the defining scope of `{Context}`.",
     label = "`{Src}` cannot be safely transmuted into `{Self}` in the defining scope of `{Context}`."
 )]
-pub unsafe trait BikeshedIntrinsicFrom<
-    Src,
-    Context,
-    const ASSUME_ALIGNMENT: bool,
-    const ASSUME_LIFETIMES: bool,
-    const ASSUME_VALIDITY: bool,
-    const ASSUME_VISIBILITY: bool,
-> where
+pub unsafe trait BikeshedIntrinsicFrom<Src, Context, const ASSUME: Assume = { Assume::NOTHING }>
+where
     Src: ?Sized,
 {
 }
 
 /// What transmutation safety conditions shall the compiler assume that *you* are checking?
 #[unstable(feature = "transmutability", issue = "99571")]
+#[cfg_attr(not(bootstrap), lang = "transmute_opts")]
 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
 pub struct Assume {
     /// When `true`, the compiler assumes that *you* are ensuring (either dynamically or statically) that
@@ -33,11 +28,80 @@ pub struct Assume {
     /// that violates Rust's memory model.
     pub lifetimes: bool,
 
+    /// When `true`, the compiler assumes that *you* have ensured that it is safe for you to violate the
+    /// type and field privacy of the destination type (and sometimes of the source type, too).
+    pub safety: bool,
+
     /// When `true`, the compiler assumes that *you* are ensuring that the source type is actually a valid
     /// instance of the destination type.
     pub validity: bool,
+}
 
-    /// When `true`, the compiler assumes that *you* have ensured that it is safe for you to violate the
-    /// type and field privacy of the destination type (and sometimes of the source type, too).
-    pub visibility: bool,
+impl Assume {
+    /// Do not assume that *you* have ensured any safety properties are met.
+    #[unstable(feature = "transmutability", issue = "99571")]
+    pub const NOTHING: Self =
+        Self { alignment: false, lifetimes: false, safety: false, validity: false };
+
+    /// Assume only that alignment conditions are met.
+    #[unstable(feature = "transmutability", issue = "99571")]
+    pub const ALIGNMENT: Self = Self { alignment: true, ..Self::NOTHING };
+
+    /// Assume only that lifetime conditions are met.
+    #[unstable(feature = "transmutability", issue = "99571")]
+    pub const LIFETIMES: Self = Self { lifetimes: true, ..Self::NOTHING };
+
+    /// Assume only that safety conditions are met.
+    #[unstable(feature = "transmutability", issue = "99571")]
+    pub const SAFETY: Self = Self { safety: true, ..Self::NOTHING };
+
+    /// Assume only that dynamically-satisfiable validity conditions are met.
+    #[unstable(feature = "transmutability", issue = "99571")]
+    pub const VALIDITY: Self = Self { validity: true, ..Self::NOTHING };
+
+    /// Assume both `self` and `other_assumptions`.
+    #[unstable(feature = "transmutability", issue = "99571")]
+    pub const fn and(self, other_assumptions: Self) -> Self {
+        Self {
+            alignment: self.alignment || other_assumptions.alignment,
+            lifetimes: self.lifetimes || other_assumptions.lifetimes,
+            safety: self.safety || other_assumptions.safety,
+            validity: self.validity || other_assumptions.validity,
+        }
+    }
+
+    /// Assume `self`, excepting `other_assumptions`.
+    #[unstable(feature = "transmutability", issue = "99571")]
+    pub const fn but_not(self, other_assumptions: Self) -> Self {
+        Self {
+            alignment: self.alignment && !other_assumptions.alignment,
+            lifetimes: self.lifetimes && !other_assumptions.lifetimes,
+            safety: self.safety && !other_assumptions.safety,
+            validity: self.validity && !other_assumptions.validity,
+        }
+    }
+}
+
+// FIXME(jswrenn): This const op is not actually usable. Why?
+// https://github.com/rust-lang/rust/pull/100726#issuecomment-1219928926
+#[unstable(feature = "transmutability", issue = "99571")]
+#[rustc_const_unstable(feature = "transmutability", issue = "99571")]
+impl const core::ops::Add for Assume {
+    type Output = Assume;
+
+    fn add(self, other_assumptions: Assume) -> Assume {
+        self.and(other_assumptions)
+    }
+}
+
+// FIXME(jswrenn): This const op is not actually usable. Why?
+// https://github.com/rust-lang/rust/pull/100726#issuecomment-1219928926
+#[unstable(feature = "transmutability", issue = "99571")]
+#[rustc_const_unstable(feature = "transmutability", issue = "99571")]
+impl const core::ops::Sub for Assume {
+    type Output = Assume;
+
+    fn sub(self, other_assumptions: Assume) -> Assume {
+        self.but_not(other_assumptions)
+    }
 }
index b9ccc0b4c799f3763ce520805d16d034744bc24f..32b2afb72b0dc306bbca2f545b92d29eec6571b2 100644 (file)
@@ -28,7 +28,7 @@ impl ValidAlign {
     #[inline]
     pub(crate) const unsafe fn new_unchecked(align: usize) -> Self {
         // SAFETY: Precondition passed to the caller.
-        unsafe { assert_unsafe_precondition!(align.is_power_of_two()) };
+        unsafe { assert_unsafe_precondition!((align: usize) => align.is_power_of_two()) };
 
         // SAFETY: By precondition, this must be a power of two, and
         // our variants encompass all possible powers of two.
index da41ea536357a2f39415e206ec2cafb04e34ce49..c83b928efc18d6adafa90c12ec026d9749f816ca 100644 (file)
@@ -1033,10 +1033,14 @@ const fn ct_f32_to_u32(ct: f32) -> u32 {
                 }
             }
         }
-        // SAFETY: `u32` is a plain old datatype so we can always... uh...
-        // ...look, just pretend you forgot what you just read.
-        // Stability concerns.
-        let rt_f32_to_u32 = |rt| unsafe { mem::transmute::<f32, u32>(rt) };
+
+        #[inline(always)] // See https://github.com/rust-lang/compiler-builtins/issues/491
+        fn rt_f32_to_u32(x: f32) -> u32 {
+            // SAFETY: `u32` is a plain old datatype so we can always... uh...
+            // ...look, just pretend you forgot what you just read.
+            // Stability concerns.
+            unsafe { mem::transmute(x) }
+        }
         // SAFETY: We use internal implementations that either always work or fail at compile time.
         unsafe { intrinsics::const_eval_select((self,), ct_f32_to_u32, rt_f32_to_u32) }
     }
@@ -1121,10 +1125,14 @@ const fn ct_u32_to_f32(ct: u32) -> f32 {
                 }
             }
         }
-        // SAFETY: `u32` is a plain old datatype so we can always... uh...
-        // ...look, just pretend you forgot what you just read.
-        // Stability concerns.
-        let rt_u32_to_f32 = |rt| unsafe { mem::transmute::<u32, f32>(rt) };
+
+        #[inline(always)] // See https://github.com/rust-lang/compiler-builtins/issues/491
+        fn rt_u32_to_f32(x: u32) -> f32 {
+            // SAFETY: `u32` is a plain old datatype so we can always... uh...
+            // ...look, just pretend you forgot what you just read.
+            // Stability concerns.
+            unsafe { mem::transmute(x) }
+        }
         // SAFETY: We use internal implementations that either always work or fail at compile time.
         unsafe { intrinsics::const_eval_select((v,), ct_u32_to_f32, rt_u32_to_f32) }
     }
index 631d559df5f701be46c90957c9d7adca344f7f7e..28d23f733debd4b87e2ba2ac64567a4dd01b708e 100644 (file)
@@ -1026,10 +1026,14 @@ const fn ct_f64_to_u64(ct: f64) -> u64 {
                 }
             }
         }
-        // SAFETY: `u64` is a plain old datatype so we can always... uh...
-        // ...look, just pretend you forgot what you just read.
-        // Stability concerns.
-        let rt_f64_to_u64 = |rt| unsafe { mem::transmute::<f64, u64>(rt) };
+
+        #[inline(always)] // See https://github.com/rust-lang/compiler-builtins/issues/491
+        fn rt_f64_to_u64(rt: f64) -> u64 {
+            // SAFETY: `u64` is a plain old datatype so we can always... uh...
+            // ...look, just pretend you forgot what you just read.
+            // Stability concerns.
+            unsafe { mem::transmute::<f64, u64>(rt) }
+        }
         // SAFETY: We use internal implementations that either always work or fail at compile time.
         unsafe { intrinsics::const_eval_select((self,), ct_f64_to_u64, rt_f64_to_u64) }
     }
@@ -1119,10 +1123,14 @@ const fn ct_u64_to_f64(ct: u64) -> f64 {
                 }
             }
         }
-        // SAFETY: `u64` is a plain old datatype so we can always... uh...
-        // ...look, just pretend you forgot what you just read.
-        // Stability concerns.
-        let rt_u64_to_f64 = |rt| unsafe { mem::transmute::<u64, f64>(rt) };
+
+        #[inline(always)] // See https://github.com/rust-lang/compiler-builtins/issues/491
+        fn rt_u64_to_f64(rt: u64) -> f64 {
+            // SAFETY: `u64` is a plain old datatype so we can always... uh...
+            // ...look, just pretend you forgot what you just read.
+            // Stability concerns.
+            unsafe { mem::transmute::<u64, f64>(rt) }
+        }
         // SAFETY: We use internal implementations that either always work or fail at compile time.
         unsafe { intrinsics::const_eval_select((v,), ct_u64_to_f64, rt_u64_to_f64) }
     }
index 6196c4da4e32928670529a82433ff98baaea50ba..532a09736a7acf43c99859ca2c7f18552df0b363 100644 (file)
@@ -56,7 +56,7 @@ impl $Ty {
                 pub const unsafe fn new_unchecked(n: $Int) -> Self {
                     // SAFETY: this is guaranteed to be safe by the caller.
                     unsafe {
-                        core::intrinsics::assert_unsafe_precondition!(n != 0);
+                        core::intrinsics::assert_unsafe_precondition!((n: $Int) => n != 0);
                         Self(n)
                     }
                 }
@@ -309,8 +309,8 @@ macro_rules! nonzero_unsigned_operations {
     ( $( $Ty: ident($Int: ident); )+ ) => {
         $(
             impl $Ty {
-                /// Add an unsigned integer to a non-zero value.
-                /// Check for overflow and return [`None`] on overflow
+                /// Adds an unsigned integer to a non-zero value.
+                /// Checks for overflow and returns [`None`] on overflow.
                 /// As a consequence, the result cannot wrap to zero.
                 ///
                 ///
@@ -346,7 +346,7 @@ pub const fn checked_add(self, other: $Int) -> Option<$Ty> {
                     }
                 }
 
-                /// Add an unsigned integer to a non-zero value.
+                /// Adds an unsigned integer to a non-zero value.
                 #[doc = concat!("Return [`", stringify!($Int), "::MAX`] on overflow.")]
                 ///
                 /// # Examples
@@ -377,7 +377,7 @@ pub const fn saturating_add(self, other: $Int) -> $Ty {
                     unsafe { $Ty::new_unchecked(self.get().saturating_add(other)) }
                 }
 
-                /// Add an unsigned integer to a non-zero value,
+                /// Adds an unsigned integer to a non-zero value,
                 /// assuming overflow cannot occur.
                 /// Overflow is unchecked, and it is undefined behaviour to overflow
                 /// *even if the result would wrap to a non-zero value*.
@@ -409,7 +409,7 @@ pub const fn saturating_add(self, other: $Int) -> $Ty {
                 }
 
                 /// Returns the smallest power of two greater than or equal to n.
-                /// Check for overflow and return [`None`]
+                /// Checks for overflow and returns [`None`]
                 /// if the next power of two is greater than the type’s maximum value.
                 /// As a consequence, the result cannot wrap to zero.
                 ///
@@ -545,7 +545,7 @@ pub const fn abs(self) -> $Ty {
                 }
 
                 /// Checked absolute value.
-                /// Check for overflow and returns [`None`] if
+                /// Checks for overflow and returns [`None`] if
                 #[doc = concat!("`self == ", stringify!($Int), "::MIN`.")]
                 /// The result cannot be zero.
                 ///
@@ -740,8 +740,8 @@ macro_rules! nonzero_unsigned_signed_operations {
     ( $( $signedness:ident $Ty: ident($Int: ty); )+ ) => {
         $(
             impl $Ty {
-                /// Multiply two non-zero integers together.
-                /// Check for overflow and return [`None`] on overflow.
+                /// Multiplies two non-zero integers together.
+                /// Checks for overflow and returns [`None`] on overflow.
                 /// As a consequence, the result cannot wrap to zero.
                 ///
                 /// # Examples
@@ -777,7 +777,7 @@ pub const fn checked_mul(self, other: $Ty) -> Option<$Ty> {
                     }
                 }
 
-                /// Multiply two non-zero integers together.
+                /// Multiplies two non-zero integers together.
                 #[doc = concat!("Return [`", stringify!($Int), "::MAX`] on overflow.")]
                 ///
                 /// # Examples
@@ -809,7 +809,7 @@ pub const fn saturating_mul(self, other: $Ty) -> $Ty {
                     unsafe { $Ty::new_unchecked(self.get().saturating_mul(other.get())) }
                 }
 
-                /// Multiply two non-zero integers together,
+                /// Multiplies two non-zero integers together,
                 /// assuming overflow cannot occur.
                 /// Overflow is unchecked, and it is undefined behaviour to overflow
                 /// *even if the result would wrap to a non-zero value*.
@@ -849,8 +849,8 @@ pub const fn saturating_mul(self, other: $Ty) -> $Ty {
                     unsafe { $Ty::new_unchecked(self.get().unchecked_mul(other.get())) }
                 }
 
-                /// Raise non-zero value to an integer power.
-                /// Check for overflow and return [`None`] on overflow.
+                /// Raises non-zero value to an integer power.
+                /// Checks for overflow and returns [`None`] on overflow.
                 /// As a consequence, the result cannot wrap to zero.
                 ///
                 /// # Examples
index a3b14847342cbcdc4ad9f57e54165ac24b9fb327..728202835818436bcc8e1c05438c548603f091c9 100644 (file)
@@ -677,7 +677,7 @@ pub enum Bound<T> {
 impl<T> Bound<T> {
     /// Converts from `&Bound<T>` to `Bound<&T>`.
     #[inline]
-    #[unstable(feature = "bound_as_ref", issue = "80996")]
+    #[stable(feature = "bound_as_ref_shared", since = "CURRENT_RUSTC_VERSION")]
     pub fn as_ref(&self) -> Bound<&T> {
         match *self {
             Included(ref x) => Included(x),
index 02f7f62bfe221aedff0c7d83ae07bd0a5f574278..10f041344095c2f14614f914260b9ebe6a5160eb 100644 (file)
@@ -222,7 +222,87 @@ pub trait Try: FromResidual {
 /// Every `Try` type needs to be recreatable from its own associated
 /// `Residual` type, but can also have additional `FromResidual` implementations
 /// to support interconversion with other `Try` types.
-#[rustc_on_unimplemented(
+#[cfg_attr(not(bootstrap), rustc_on_unimplemented(
+    on(
+        all(
+            from_desugaring = "QuestionMark",
+            _Self = "std::result::Result<T, E>",
+            R = "std::option::Option<std::convert::Infallible>"
+        ),
+        message = "the `?` operator can only be used on `Result`s, not `Option`s, \
+            in {ItemContext} that returns `Result`",
+        label = "use `.ok_or(...)?` to provide an error compatible with `{Self}`",
+        parent_label = "this function returns a `Result`"
+    ),
+    on(
+        all(
+            from_desugaring = "QuestionMark",
+            _Self = "std::result::Result<T, E>",
+        ),
+        // There's a special error message in the trait selection code for
+        // `From` in `?`, so this is not shown for result-in-result errors,
+        // and thus it can be phrased more strongly than `ControlFlow`'s.
+        message = "the `?` operator can only be used on `Result`s \
+            in {ItemContext} that returns `Result`",
+        label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
+        parent_label = "this function returns a `Result`"
+    ),
+    on(
+        all(
+            from_desugaring = "QuestionMark",
+            _Self = "std::option::Option<T>",
+            R = "std::result::Result<T, E>",
+        ),
+        message = "the `?` operator can only be used on `Option`s, not `Result`s, \
+            in {ItemContext} that returns `Option`",
+        label = "use `.ok()?` if you want to discard the `{R}` error information",
+        parent_label = "this function returns an `Option`"
+    ),
+    on(
+        all(
+            from_desugaring = "QuestionMark",
+            _Self = "std::option::Option<T>",
+        ),
+        // `Option`-in-`Option` always works, as there's only one possible
+        // residual, so this can also be phrased strongly.
+        message = "the `?` operator can only be used on `Option`s \
+            in {ItemContext} that returns `Option`",
+        label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
+        parent_label = "this function returns an `Option`"
+    ),
+    on(
+        all(
+            from_desugaring = "QuestionMark",
+            _Self = "std::ops::ControlFlow<B, C>",
+            R = "std::ops::ControlFlow<B, C>",
+        ),
+        message = "the `?` operator in {ItemContext} that returns `ControlFlow<B, _>` \
+            can only be used on other `ControlFlow<B, _>`s (with the same Break type)",
+        label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
+        parent_label = "this function returns a `ControlFlow`",
+        note = "unlike `Result`, there's no `From`-conversion performed for `ControlFlow`"
+    ),
+    on(
+        all(
+            from_desugaring = "QuestionMark",
+            _Self = "std::ops::ControlFlow<B, C>",
+            // `R` is not a `ControlFlow`, as that case was matched previously
+        ),
+        message = "the `?` operator can only be used on `ControlFlow`s \
+            in {ItemContext} that returns `ControlFlow`",
+        label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
+        parent_label = "this function returns a `ControlFlow`",
+    ),
+    on(
+        all(from_desugaring = "QuestionMark"),
+        message = "the `?` operator can only be used in {ItemContext} \
+                    that returns `Result` or `Option` \
+                    (or another type that implements `{FromResidual}`)",
+        label = "cannot use the `?` operator in {ItemContext} that returns `{Self}`",
+        parent_label = "this function should return `Result` or `Option` to accept `?`"
+    ),
+))]
+#[cfg_attr(bootstrap, rustc_on_unimplemented(
     on(
         all(
             from_desugaring = "QuestionMark",
@@ -301,7 +381,7 @@ pub trait Try: FromResidual {
         label = "cannot use the `?` operator in {ItemContext} that returns `{Self}`",
         enclosing_scope = "this function should return `Result` or `Option` to accept `?`"
     ),
-)]
+))]
 #[rustc_diagnostic_item = "FromResidual"]
 #[unstable(feature = "try_trait_v2", issue = "84277")]
 pub trait FromResidual<R = <Self as Try>::Residual> {
index f5c72d797553450b5c103d6ff05c48e842a2c489..80bff74f3e9f4712c8d7e26ab320655a32e081cd 100644 (file)
@@ -755,9 +755,12 @@ pub fn mask(self, mask: usize) -> *const T {
     where
         T: Sized,
     {
+        let this = self;
         // SAFETY: The comparison has no side-effects, and the intrinsic
         // does this check internally in the CTFE implementation.
-        unsafe { assert_unsafe_precondition!(self >= origin) };
+        unsafe {
+            assert_unsafe_precondition!([T](this: *const T, origin: *const T) => this >= origin)
+        };
 
         let pointee_size = mem::size_of::<T>();
         assert!(0 < pointee_size && pointee_size <= isize::MAX as usize);
index 41a2685d361c805a1696cc39d899f6da3ff76fd1..e976abed774b8d21cd1a4b3b48fbe74f8e7cd8c1 100644 (file)
@@ -886,7 +886,7 @@ macro_rules! attempt_swap_as_chunks {
     // SAFETY: the caller must guarantee that `x` and `y` are
     // valid for writes and properly aligned.
     unsafe {
-        assert_unsafe_precondition!(
+        assert_unsafe_precondition!([T](x: *mut T, y: *mut T, count: usize) =>
             is_aligned_and_not_null(x)
                 && is_aligned_and_not_null(y)
                 && is_nonoverlapping(x, y, count)
@@ -983,7 +983,7 @@ macro_rules! attempt_swap_as_chunks {
     // and cannot overlap `src` since `dst` must point to a distinct
     // allocated object.
     unsafe {
-        assert_unsafe_precondition!(is_aligned_and_not_null(dst));
+        assert_unsafe_precondition!([T](dst: *mut T) => is_aligned_and_not_null(dst));
         mem::swap(&mut *dst, &mut src); // cannot overlap
     }
     src
@@ -1470,7 +1470,7 @@ macro_rules! attempt_swap_as_chunks {
 pub unsafe fn read_volatile<T>(src: *const T) -> T {
     // SAFETY: the caller must uphold the safety contract for `volatile_load`.
     unsafe {
-        assert_unsafe_precondition!(is_aligned_and_not_null(src));
+        assert_unsafe_precondition!([T](src: *const T) => is_aligned_and_not_null(src));
         intrinsics::volatile_load(src)
     }
 }
@@ -1541,7 +1541,7 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T {
 pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
     // SAFETY: the caller must uphold the safety contract for `volatile_store`.
     unsafe {
-        assert_unsafe_precondition!(is_aligned_and_not_null(dst));
+        assert_unsafe_precondition!([T](dst: *mut T) => is_aligned_and_not_null(dst));
         intrinsics::volatile_store(dst, src);
     }
 }
index fd7ecf3daf31604258bff8a3ff7eecc8b86fe457..3403a5a86f7cb8af4022bab30abaee5bb1ddd240 100644 (file)
@@ -48,10 +48,12 @@ const fn slice_start_index_len_fail(index: usize, len: usize) -> ! {
 }
 
 // FIXME const-hack
+#[track_caller]
 fn slice_start_index_len_fail_rt(index: usize, len: usize) -> ! {
     panic!("range start index {index} out of range for slice of length {len}");
 }
 
+#[track_caller]
 const fn slice_start_index_len_fail_ct(_: usize, _: usize) -> ! {
     panic!("slice start index is out of range for slice");
 }
@@ -69,10 +71,12 @@ const fn slice_end_index_len_fail(index: usize, len: usize) -> ! {
 }
 
 // FIXME const-hack
+#[track_caller]
 fn slice_end_index_len_fail_rt(index: usize, len: usize) -> ! {
     panic!("range end index {index} out of range for slice of length {len}");
 }
 
+#[track_caller]
 const fn slice_end_index_len_fail_ct(_: usize, _: usize) -> ! {
     panic!("slice end index is out of range for slice");
 }
@@ -88,10 +92,12 @@ const fn slice_index_order_fail(index: usize, end: usize) -> ! {
 }
 
 // FIXME const-hack
+#[track_caller]
 fn slice_index_order_fail_rt(index: usize, end: usize) -> ! {
     panic!("slice index starts at {index} but ends at {end}");
 }
 
+#[track_caller]
 const fn slice_index_order_fail_ct(_: usize, _: usize) -> ! {
     panic!("slice index start is larger than end");
 }
@@ -217,21 +223,23 @@ fn get_mut(self, slice: &mut [T]) -> Option<&mut T> {
 
     #[inline]
     unsafe fn get_unchecked(self, slice: *const [T]) -> *const T {
+        let this = self;
         // SAFETY: the caller guarantees that `slice` is not dangling, so it
         // cannot be longer than `isize::MAX`. They also guarantee that
         // `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
         // so the call to `add` is safe.
         unsafe {
-            assert_unsafe_precondition!(self < slice.len());
+            assert_unsafe_precondition!([T](this: usize, slice: *const [T]) => this < slice.len());
             slice.as_ptr().add(self)
         }
     }
 
     #[inline]
     unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut T {
+        let this = self;
         // SAFETY: see comments for `get_unchecked` above.
         unsafe {
-            assert_unsafe_precondition!(self < slice.len());
+            assert_unsafe_precondition!([T](this: usize, slice: *mut [T]) => this < slice.len());
             slice.as_mut_ptr().add(self)
         }
     }
@@ -276,22 +284,26 @@ fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
 
     #[inline]
     unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
+        let this = ops::Range { start: self.start, end: self.end };
         // SAFETY: the caller guarantees that `slice` is not dangling, so it
         // cannot be longer than `isize::MAX`. They also guarantee that
         // `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
         // so the call to `add` is safe.
 
         unsafe {
-            assert_unsafe_precondition!(self.end >= self.start && self.end <= slice.len());
+            assert_unsafe_precondition!([T](this: ops::Range<usize>, slice: *const [T]) =>
+            this.end >= this.start && this.end <= slice.len());
             ptr::slice_from_raw_parts(slice.as_ptr().add(self.start), self.end - self.start)
         }
     }
 
     #[inline]
     unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
+        let this = ops::Range { start: self.start, end: self.end };
         // SAFETY: see comments for `get_unchecked` above.
         unsafe {
-            assert_unsafe_precondition!(self.end >= self.start && self.end <= slice.len());
+            assert_unsafe_precondition!([T](this: ops::Range<usize>, slice: *mut [T]) =>
+                this.end >= this.start && this.end <= slice.len());
             ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start), self.end - self.start)
         }
     }
index 1958745b5868c79f240b45087db2c272608503ce..6a7150d2986edf50ef3e439ac23ea62d00d0a735 100644 (file)
@@ -656,10 +656,11 @@ pub const fn swap(&mut self, a: usize, b: usize) {
     #[unstable(feature = "slice_swap_unchecked", issue = "88539")]
     #[rustc_const_unstable(feature = "const_swap", issue = "83163")]
     pub const unsafe fn swap_unchecked(&mut self, a: usize, b: usize) {
-        let ptr = self.as_mut_ptr();
+        let this = self;
+        let ptr = this.as_mut_ptr();
         // SAFETY: caller has to guarantee that `a < self.len()` and `b < self.len()`
         unsafe {
-            assert_unsafe_precondition!(a < self.len() && b < self.len());
+            assert_unsafe_precondition!([T](a: usize, b: usize, this: &mut [T]) => a < this.len() && b < this.len());
             ptr::swap(ptr.add(a), ptr.add(b));
         }
     }
@@ -972,9 +973,10 @@ pub fn chunks_exact_mut(&mut self, chunk_size: usize) -> ChunksExactMut<'_, T> {
     #[inline]
     #[must_use]
     pub unsafe fn as_chunks_unchecked<const N: usize>(&self) -> &[[T; N]] {
+        let this = self;
         // SAFETY: Caller must guarantee that `N` is nonzero and exactly divides the slice length
         let new_len = unsafe {
-            assert_unsafe_precondition!(N != 0 && self.len() % N == 0);
+            assert_unsafe_precondition!([T](this: &[T], N: usize) => N != 0 && this.len() % N == 0);
             exact_div(self.len(), N)
         };
         // SAFETY: We cast a slice of `new_len * N` elements into
@@ -1111,10 +1113,11 @@ pub fn array_chunks<const N: usize>(&self) -> ArrayChunks<'_, T, N> {
     #[inline]
     #[must_use]
     pub unsafe fn as_chunks_unchecked_mut<const N: usize>(&mut self) -> &mut [[T; N]] {
+        let this = &*self;
         // SAFETY: Caller must guarantee that `N` is nonzero and exactly divides the slice length
         let new_len = unsafe {
-            assert_unsafe_precondition!(N != 0 && self.len() % N == 0);
-            exact_div(self.len(), N)
+            assert_unsafe_precondition!([T](this: &[T], N: usize) => N != 0 && this.len() % N == 0);
+            exact_div(this.len(), N)
         };
         // SAFETY: We cast a slice of `new_len * N` elements into
         // a slice of `new_len` many `N` elements chunks.
@@ -1687,7 +1690,7 @@ pub unsafe fn split_at_mut_unchecked(&mut self, mid: usize) -> (&mut [T], &mut [
         // `[ptr; mid]` and `[mid; len]` are not overlapping, so returning a mutable reference
         // is fine.
         unsafe {
-            assert_unsafe_precondition!(mid <= len);
+            assert_unsafe_precondition!((mid: usize, len: usize) => mid <= len);
             (from_raw_parts_mut(ptr, mid), from_raw_parts_mut(ptr.add(mid), len - mid))
         }
     }
index 107e71ab68b010a2be037eb92126f8971b3c7aef..f1e8bc79bf4a2d042d19a9ea90fd6a8e61e9482f 100644 (file)
@@ -90,7 +90,7 @@
 pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
     // SAFETY: the caller must uphold the safety contract for `from_raw_parts`.
     unsafe {
-        assert_unsafe_precondition!(
+        assert_unsafe_precondition!([T](data: *const T, len: usize) =>
             is_aligned_and_not_null(data)
                 && crate::mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize
         );
 pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] {
     // SAFETY: the caller must uphold the safety contract for `from_raw_parts_mut`.
     unsafe {
-        assert_unsafe_precondition!(
+        assert_unsafe_precondition!([T](data: *mut T, len: usize) =>
             is_aligned_and_not_null(data)
                 && crate::mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize
         );
index 2120bf61d759d739fb6b2ac7696bc7c6d29b4ee1..f673aa2a44b1023ee612a5e355ad4bbc59e25074 100644 (file)
@@ -91,10 +91,12 @@ const fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! {
     }
 }
 
+#[track_caller]
 const fn slice_error_fail_ct(_: &str, _: usize, _: usize) -> ! {
     panic!("failed to slice string");
 }
 
+#[track_caller]
 fn slice_error_fail_rt(s: &str, begin: usize, end: usize) -> ! {
     const MAX_DISPLAY_LENGTH: usize = 256;
     let trunc_len = s.floor_char_boundary(MAX_DISPLAY_LENGTH);
index c1eff3a36e6e15f5fdc0b296aef0280dfefef495..7301da2afec466e59140835acbd166859d0cca78 100644 (file)
@@ -1,7 +1,8 @@
 ///! This file is generated by src/tools/unicode-table-generator; do not edit manually!
 
+#[rustc_const_unstable(feature = "const_unicode_case_lookup", issue = "101400")]
 #[inline(always)]
-fn bitset_search<
+const fn bitset_search<
     const N: usize,
     const CHUNK_SIZE: usize,
     const N1: usize,
@@ -17,14 +18,18 @@ fn bitset_search<
     let bucket_idx = (needle / 64) as usize;
     let chunk_map_idx = bucket_idx / CHUNK_SIZE;
     let chunk_piece = bucket_idx % CHUNK_SIZE;
-    let chunk_idx = if let Some(&v) = chunk_idx_map.get(chunk_map_idx) {
-        v
+    // FIXME: const-hack: Revert to `slice::get` after `const_slice_index`
+    // feature stabilizes.
+    let chunk_idx = if chunk_map_idx < chunk_idx_map.len() {
+        chunk_idx_map[chunk_map_idx]
     } else {
         return false;
     };
     let idx = bitset_chunk_idx[chunk_idx as usize][chunk_piece] as usize;
-    let word = if let Some(word) = bitset_canonical.get(idx) {
-        *word
+    // FIXME: const-hack: Revert to `slice::get` after `const_slice_index`
+    // feature stabilizes.
+    let word = if idx < bitset_canonical.len() {
+        bitset_canonical[idx]
     } else {
         let (real_idx, mapping) = bitset_canonicalized[idx - bitset_canonical.len()];
         let mut word = bitset_canonical[real_idx as usize];
@@ -318,14 +323,14 @@ pub fn lookup(c: char) -> bool {
 
 #[rustfmt::skip]
 pub mod lowercase {
-    static BITSET_CHUNKS_MAP: [u8; 123] = [
+    const BITSET_CHUNKS_MAP: &'static [u8; 123] = &[
         14, 17, 0, 0, 9, 0, 0, 12, 13, 10, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 4, 1, 0, 15, 0, 8, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0,
         3, 0, 0, 7,
     ];
-    static BITSET_INDEX_CHUNKS: [[u8; 16]; 19] = [
+    const BITSET_INDEX_CHUNKS: &'static [[u8; 16]; 19] = &[
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 0, 0],
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 14, 55, 0],
@@ -346,7 +351,7 @@ pub mod lowercase {
         [16, 49, 2, 20, 66, 9, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0],
         [63, 39, 54, 12, 73, 61, 18, 1, 6, 62, 71, 19, 68, 69, 3, 44],
     ];
-    static BITSET_CANONICAL: [u64; 55] = [
+    const BITSET_CANONICAL: &'static [u64; 55] = &[
         0b0000000000000000000000000000000000000000000000000000000000000000,
         0b1111111111111111110000000000000000000000000011111111111111111111,
         0b1010101010101010101010101010101010101010101010101010100000000010,
@@ -403,13 +408,14 @@ pub mod lowercase {
         0b1110011111111111111111111111111111111111111111110000000000000000,
         0b1110101111000000000000000000000000001111111111111111111111111100,
     ];
-    static BITSET_MAPPING: [(u8, u8); 20] = [
+    const BITSET_MAPPING: &'static [(u8, u8); 20] = &[
         (0, 64), (1, 188), (1, 183), (1, 176), (1, 109), (1, 124), (1, 126), (1, 66), (1, 70),
         (1, 77), (2, 146), (2, 144), (2, 83), (3, 12), (3, 6), (4, 156), (4, 78), (5, 187),
         (6, 132), (7, 93),
     ];
 
-    pub fn lookup(c: char) -> bool {
+    #[rustc_const_unstable(feature = "const_unicode_case_lookup", issue = "101400")]
+    pub const fn lookup(c: char) -> bool {
         super::bitset_search(
             c as u32,
             &BITSET_CHUNKS_MAP,
@@ -454,14 +460,14 @@ pub fn lookup(c: char) -> bool {
 
 #[rustfmt::skip]
 pub mod uppercase {
-    static BITSET_CHUNKS_MAP: [u8; 125] = [
+    const BITSET_CHUNKS_MAP: &'static [u8; 125] = &[
         12, 15, 6, 6, 0, 6, 6, 2, 4, 11, 6, 16, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
         6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
         6, 6, 6, 5, 6, 14, 6, 10, 6, 6, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
         6, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 13, 6, 6,
         6, 6, 9, 6, 3,
     ];
-    static BITSET_INDEX_CHUNKS: [[u8; 16]; 17] = [
+    const BITSET_INDEX_CHUNKS: &'static [[u8; 16]; 17] = &[
         [43, 43, 5, 34, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 5, 1],
         [43, 43, 5, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43],
         [43, 43, 39, 43, 43, 43, 43, 43, 17, 17, 62, 17, 42, 29, 24, 23],
@@ -480,7 +486,7 @@ pub mod uppercase {
         [57, 19, 2, 18, 10, 47, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43],
         [57, 37, 17, 27, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43],
     ];
-    static BITSET_CANONICAL: [u64; 43] = [
+    const BITSET_CANONICAL: &'static [u64; 43] = &[
         0b0000011111111111111111111111111000000000000000000000000000000000,
         0b0000000000111111111111111111111111111111111111111111111111111111,
         0b0101010101010101010101010101010101010101010101010101010000000001,
@@ -525,13 +531,14 @@ pub mod uppercase {
         0b1111011111111111000000000000000000000000000000000000000000000000,
         0b1111111100000000111111110000000000111111000000001111111100000000,
     ];
-    static BITSET_MAPPING: [(u8, u8); 25] = [
+    const BITSET_MAPPING: &'static [(u8, u8); 25] = &[
         (0, 187), (0, 177), (0, 171), (0, 167), (0, 164), (0, 32), (0, 47), (0, 51), (0, 121),
         (0, 117), (0, 109), (1, 150), (1, 148), (1, 142), (1, 134), (1, 131), (1, 64), (2, 164),
         (2, 146), (2, 20), (3, 146), (3, 140), (3, 134), (4, 178), (4, 171),
     ];
 
-    pub fn lookup(c: char) -> bool {
+    #[rustc_const_unstable(feature = "const_unicode_case_lookup", issue = "101400")]
+    pub const fn lookup(c: char) -> bool {
         super::bitset_search(
             c as u32,
             &BITSET_CHUNKS_MAP,
index 8ed0c88808fe27fc47d36b4734dae75a0401e11b..9538b81394957be74e188531cb1d9e9b9f4fa9ad 100644 (file)
@@ -142,7 +142,7 @@ fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
         demand
             .provide_ref::<String>(&self.some_string)
             .provide_ref::<str>(&self.some_string)
-            .provide_value::<String>(|| "bye".to_owned());
+            .provide_value_with::<String>(|| "bye".to_owned());
     }
 }
 
index 4bd4d4c05e3b9cb9f1ad258577c6c31d3f0f67db..4ac60b10c92ef08a2fab4f648ae7271043f3d04b 100644 (file)
@@ -1,9 +1,5 @@
 #![cfg_attr(feature = "as_crate", no_std)] // We are std!
-#![cfg_attr(
-    feature = "as_crate",
-    feature(platform_intrinsics),
-    feature(portable_simd)
-)]
+#![cfg_attr(feature = "as_crate", feature(platform_intrinsics), feature(portable_simd))]
 #[cfg(not(feature = "as_crate"))]
 use core::simd;
 #[cfg(feature = "as_crate")]
index e47a77f6c1350530e4f985a31701bc0c28c96e39..8202c40d63170464fe96cb2bc49f8df605100c20 100644 (file)
@@ -2,6 +2,7 @@
 
 use super::*;
 
+use std::cell::Cell;
 use std::marker::PhantomData;
 
 // FIXME(eddyb) generate the definition of `HandleStore` in `server.rs`.
@@ -143,6 +144,38 @@ fn run_bridge_and_client(
     ) -> Buffer;
 }
 
+thread_local! {
+    /// While running a proc-macro with the same-thread executor, this flag will
+    /// be set, forcing nested proc-macro invocations (e.g. due to
+    /// `TokenStream::expand_expr`) to be run using a cross-thread executor.
+    ///
+    /// This is required as the thread-local state in the proc_macro client does
+    /// not handle being re-entered, and will invalidate all `Symbol`s when
+    /// entering a nested macro.
+    static ALREADY_RUNNING_SAME_THREAD: Cell<bool> = Cell::new(false);
+}
+
+/// Keep `ALREADY_RUNNING_SAME_THREAD` (see also its documentation)
+/// set to `true`, preventing same-thread reentrance.
+struct RunningSameThreadGuard(());
+
+impl RunningSameThreadGuard {
+    fn new() -> Self {
+        let already_running = ALREADY_RUNNING_SAME_THREAD.replace(true);
+        assert!(
+            !already_running,
+            "same-thread nesting (\"reentrance\") of proc macro executions is not supported"
+        );
+        RunningSameThreadGuard(())
+    }
+}
+
+impl Drop for RunningSameThreadGuard {
+    fn drop(&mut self) {
+        ALREADY_RUNNING_SAME_THREAD.set(false);
+    }
+}
+
 pub struct MaybeCrossThread<P> {
     cross_thread: bool,
     marker: PhantomData<P>,
@@ -165,7 +198,7 @@ fn run_bridge_and_client(
         run_client: extern "C" fn(BridgeConfig<'_>) -> Buffer,
         force_show_panics: bool,
     ) -> Buffer {
-        if self.cross_thread {
+        if self.cross_thread || ALREADY_RUNNING_SAME_THREAD.get() {
             <CrossThread<P>>::new().run_bridge_and_client(
                 dispatcher,
                 input,
@@ -188,6 +221,8 @@ fn run_bridge_and_client(
         run_client: extern "C" fn(BridgeConfig<'_>) -> Buffer,
         force_show_panics: bool,
     ) -> Buffer {
+        let _guard = RunningSameThreadGuard::new();
+
         let mut dispatch = |buf| dispatcher.dispatch(buf);
 
         run_client(BridgeConfig {
index a05e0db3af71663a3ff7596773e16940b90207dc..61c1ff578b2cad4ec3f8c46b09bd71ab80ef0d1b 100644 (file)
 /// The default memory allocator provided by the operating system.
 ///
 /// This is based on `malloc` on Unix platforms and `HeapAlloc` on Windows,
-/// plus related functions.
+/// plus related functions. However, it is not valid to mix use of the backing
+/// system allocator with `System`, as this implementation may include extra
+/// work, such as to serve alignment requests greater than the alignment
+/// provided directly by the backing system allocator.
 ///
 /// This type implements the `GlobalAlloc` trait and Rust programs by default
 /// work as if they had this definition:
index abff82788a38dc55d9a8cfbb3b5900c5ea9ac53d..5b6a415fadc1e2a83f737adbbdb6b95522553a7d 100644 (file)
@@ -239,7 +239,7 @@ pub fn is_empty(&self) -> bool {
     ///
     /// If the returned iterator is dropped before being fully consumed, it
     /// drops the remaining elements. The returned iterator keeps a mutable
-    /// borrow on the vector to optimize its implementation.
+    /// borrow on the set to optimize its implementation.
     ///
     /// # Examples
     ///
index 28a2c99f7e5e3e8d2ef77993fc6eb7e09564e5d8..c6c78dc3939e7b12ba4d49d2165539a8e574ed9c 100644 (file)
@@ -19,7 +19,7 @@
 use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
 use crate::time::SystemTime;
 
-/// A reference to an open file on the filesystem.
+/// An object providing access to an open file on the filesystem.
 ///
 /// An instance of a `File` can be read and/or written depending on what options
 /// it was opened with. Files also implement [`Seek`] to alter the logical cursor
index 4d3736f79146c8df36976ba06397e108ef532af7..91cff3217d21bce19ad24ebdd7632d66729a91e5 100644 (file)
@@ -8,7 +8,6 @@
 use crate::cell::{Cell, RefCell};
 use crate::fmt;
 use crate::io::{self, BufReader, IoSlice, IoSliceMut, LineWriter, Lines};
-use crate::pin::Pin;
 use crate::sync::atomic::{AtomicBool, Ordering};
 use crate::sync::{Arc, Mutex, MutexGuard, OnceLock};
 use crate::sys::stdio;
@@ -526,7 +525,7 @@ pub struct Stdout {
     // FIXME: this should be LineWriter or BufWriter depending on the state of
     //        stdout (tty or not). Note that if this is not line buffered it
     //        should also flush-on-panic or some form of flush-on-abort.
-    inner: Pin<&'static ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>>,
+    inner: &'static ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>,
 }
 
 /// A locked reference to the [`Stdout`] handle.
@@ -603,22 +602,27 @@ pub struct StdoutLock<'a> {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn stdout() -> Stdout {
     Stdout {
-        inner: Pin::static_ref(&STDOUT).get_or_init_pin(
-            || unsafe { ReentrantMutex::new(RefCell::new(LineWriter::new(stdout_raw()))) },
-            |mutex| unsafe { mutex.init() },
-        ),
+        inner: STDOUT
+            .get_or_init(|| ReentrantMutex::new(RefCell::new(LineWriter::new(stdout_raw())))),
     }
 }
 
+// Flush the data and disable buffering during shutdown
+// by replacing the line writer by one with zero
+// buffering capacity.
 pub fn cleanup() {
-    if let Some(instance) = STDOUT.get() {
-        // Flush the data and disable buffering during shutdown
-        // by replacing the line writer by one with zero
-        // buffering capacity.
+    let mut initialized = false;
+    let stdout = STDOUT.get_or_init(|| {
+        initialized = true;
+        ReentrantMutex::new(RefCell::new(LineWriter::with_capacity(0, stdout_raw())))
+    });
+
+    if !initialized {
+        // The buffer was previously initialized, overwrite it here.
         // We use try_lock() instead of lock(), because someone
         // might have leaked a StdoutLock, which would
         // otherwise cause a deadlock here.
-        if let Some(lock) = Pin::static_ref(instance).try_lock() {
+        if let Some(lock) = stdout.try_lock() {
             *lock.borrow_mut() = LineWriter::with_capacity(0, stdout_raw());
         }
     }
@@ -761,7 +765,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// standard library or via raw Windows API calls, will fail.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Stderr {
-    inner: Pin<&'static ReentrantMutex<RefCell<StderrRaw>>>,
+    inner: &'static ReentrantMutex<RefCell<StderrRaw>>,
 }
 
 /// A locked reference to the [`Stderr`] handle.
@@ -834,16 +838,12 @@ pub struct StderrLock<'a> {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn stderr() -> Stderr {
     // Note that unlike `stdout()` we don't use `at_exit` here to register a
-    // destructor. Stderr is not buffered , so there's no need to run a
+    // destructor. Stderr is not buffered, so there's no need to run a
     // destructor for flushing the buffer
-    static INSTANCE: OnceLock<ReentrantMutex<RefCell<StderrRaw>>> = OnceLock::new();
+    static INSTANCE: ReentrantMutex<RefCell<StderrRaw>> =
+        ReentrantMutex::new(RefCell::new(stderr_raw()));
 
-    Stderr {
-        inner: Pin::static_ref(&INSTANCE).get_or_init_pin(
-            || unsafe { ReentrantMutex::new(RefCell::new(stderr_raw())) },
-            |mutex| unsafe { mutex.init() },
-        ),
-    }
+    Stderr { inner: &INSTANCE }
 }
 
 impl Stderr {
@@ -986,10 +986,10 @@ pub fn set_output_capture(sink: Option<LocalStream>) -> Option<LocalStream> {
 /// otherwise. `label` identifies the stream in a panic message.
 ///
 /// This function is used to print error messages, so it takes extra
-/// care to avoid causing a panic when `local_s` is unusable.
-/// For instance, if the TLS key for the local stream is
-/// already destroyed, or if the local stream is locked by another
-/// thread, it will just fall back to the global stream.
+/// care to avoid causing a panic when `OUTPUT_CAPTURE` is unusable.
+/// For instance, if the TLS key for output capturing is already destroyed, or
+/// if the local stream is in use by another thread, it will just fall back to
+/// the global stream.
 ///
 /// However, if the actual I/O causes an error, this function does panic.
 fn print_to<T>(args: fmt::Arguments<'_>, global_s: fn() -> T, label: &str)
index a463bc41db7aa4b384a96de149253e1a306d12b5..71e33fb9ed86442b0797a3ce52ebf8c794007615 100644 (file)
@@ -104,7 +104,8 @@ pub fn try_clone_to_owned(&self) -> crate::io::Result<OwnedFd> {
         #[cfg(target_os = "espidf")]
         let cmd = libc::F_DUPFD;
 
-        let fd = cvt(unsafe { libc::fcntl(self.as_raw_fd(), cmd, 0) })?;
+        // Avoid using file descriptors below 3 as they are used for stdio
+        let fd = cvt(unsafe { libc::fcntl(self.as_raw_fd(), cmd, 3) })?;
         Ok(unsafe { OwnedFd::from_raw_fd(fd) })
     }
 
index 663537a05fa32f91c78545f732ec5837c60daef1..98f6cc7aa3ea152aa424a58f95e15046bf6dbfde 100644 (file)
@@ -72,10 +72,29 @@ macro_rules! rtunwrap {
 // Runs before `main`.
 // SAFETY: must be called only once during runtime initialization.
 // NOTE: this is not guaranteed to run, for example when Rust code is called externally.
+//
+// # The `sigpipe` parameter
+//
+// Since 2014, the Rust runtime on Unix has set the `SIGPIPE` handler to
+// `SIG_IGN`. Applications have good reasons to want a different behavior
+// though, so there is a `#[unix_sigpipe = "..."]` attribute on `fn main()` that
+// can be used to select how `SIGPIPE` shall be setup (if changed at all) before
+// `fn main()` is called. See <https://github.com/rust-lang/rust/issues/97889>
+// for more info.
+//
+// The `sigpipe` parameter to this function gets its value via the code that
+// rustc generates to invoke `fn lang_start()`. The reason we have `sigpipe` for
+// all platforms and not only Unix, is because std is not allowed to have `cfg`
+// directives as this high level. See the module docs in
+// `src/tools/tidy/src/pal.rs` for more info. On all other platforms, `sigpipe`
+// has a value, but its value is ignored.
+//
+// Even though it is an `u8`, it only ever has 3 values. These are documented in
+// `compiler/rustc_session/src/config/sigpipe.rs`.
 #[cfg_attr(test, allow(dead_code))]
-unsafe fn init(argc: isize, argv: *const *const u8) {
+unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
     unsafe {
-        sys::init(argc, argv);
+        sys::init(argc, argv, sigpipe);
 
         let main_guard = sys::thread::guard::init();
         // Next, set up the current Thread with the guard information we just
@@ -107,6 +126,7 @@ fn lang_start_internal(
     main: &(dyn Fn() -> i32 + Sync + crate::panic::RefUnwindSafe),
     argc: isize,
     argv: *const *const u8,
+    sigpipe: u8,
 ) -> Result<isize, !> {
     use crate::{mem, panic};
     let rt_abort = move |e| {
@@ -124,7 +144,7 @@ fn lang_start_internal(
     // prevent libstd from accidentally introducing a panic to these functions. Another is from
     // user code from `main` or, more nefariously, as described in e.g. issue #86030.
     // SAFETY: Only called once during runtime initialization.
-    panic::catch_unwind(move || unsafe { init(argc, argv) }).map_err(rt_abort)?;
+    panic::catch_unwind(move || unsafe { init(argc, argv, sigpipe) }).map_err(rt_abort)?;
     let ret_code = panic::catch_unwind(move || panic::catch_unwind(main).unwrap_or(101) as isize)
         .map_err(move |e| {
             mem::forget(e);
@@ -140,11 +160,16 @@ fn lang_start<T: crate::process::Termination + 'static>(
     main: fn() -> T,
     argc: isize,
     argv: *const *const u8,
+    #[cfg(not(bootstrap))] sigpipe: u8,
 ) -> isize {
     let Ok(v) = lang_start_internal(
         &move || crate::sys_common::backtrace::__rust_begin_short_backtrace(main).report().to_i32(),
         argc,
         argv,
+        #[cfg(bootstrap)]
+        2, // Temporary inlining of sigpipe::DEFAULT until bootstrap stops being special
+        #[cfg(not(bootstrap))]
+        sigpipe,
     );
     v
 }
index e0d13cd648c64ceeb003da18d1401e02104bccf2..de851c8fbbed51743776477b338dda1677fd925a 100644 (file)
@@ -192,6 +192,7 @@ unsafe impl<T: ?Sized + Send> Sync for Mutex<T> {}
                       and cause Futures to not implement `Send`"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[clippy::has_significant_drop]
+#[cfg_attr(not(test), rustc_diagnostic_item = "MutexGuard")]
 pub struct MutexGuard<'a, T: ?Sized + 'a> {
     lock: &'a Mutex<T>,
     poison: poison::Guard,
index 813516040cdb6f7c274ec7d20f9b80b3391407bd..37413ec62a717aae1c3009696db643df59d09403 100644 (file)
@@ -3,7 +3,6 @@
 use crate::marker::PhantomData;
 use crate::mem::MaybeUninit;
 use crate::panic::{RefUnwindSafe, UnwindSafe};
-use crate::pin::Pin;
 use crate::sync::Once;
 
 /// A synchronization primitive which can be written to only once.
@@ -223,60 +222,6 @@ pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
         Ok(unsafe { self.get_unchecked() })
     }
 
-    /// Internal-only API that gets the contents of the cell, initializing it
-    /// in two steps with `f` and `g` if the cell was empty.
-    ///
-    /// `f` is called to construct the value, which is then moved into the cell
-    /// and given as a (pinned) mutable reference to `g` to finish
-    /// initialization.
-    ///
-    /// This allows `g` to inspect an manipulate the value after it has been
-    /// moved into its final place in the cell, but before the cell is
-    /// considered initialized.
-    ///
-    /// # Panics
-    ///
-    /// If `f` or `g` panics, the panic is propagated to the caller, and the
-    /// cell remains uninitialized.
-    ///
-    /// With the current implementation, if `g` panics, the value from `f` will
-    /// not be dropped. This should probably be fixed if this is ever used for
-    /// a type where this matters.
-    ///
-    /// It is an error to reentrantly initialize the cell from `f`. The exact
-    /// outcome is unspecified. Current implementation deadlocks, but this may
-    /// be changed to a panic in the future.
-    pub(crate) fn get_or_init_pin<F, G>(self: Pin<&Self>, f: F, g: G) -> Pin<&T>
-    where
-        F: FnOnce() -> T,
-        G: FnOnce(Pin<&mut T>),
-    {
-        if let Some(value) = self.get_ref().get() {
-            // SAFETY: The inner value was already initialized, and will not be
-            // moved anymore.
-            return unsafe { Pin::new_unchecked(value) };
-        }
-
-        let slot = &self.value;
-
-        // Ignore poisoning from other threads
-        // If another thread panics, then we'll be able to run our closure
-        self.once.call_once_force(|_| {
-            let value = f();
-            // SAFETY: We use the Once (self.once) to guarantee unique access
-            // to the UnsafeCell (slot).
-            let value: &mut T = unsafe { (&mut *slot.get()).write(value) };
-            // SAFETY: The value has been written to its final place in
-            // self.value. We do not to move it anymore, which we promise here
-            // with a Pin<&mut T>.
-            g(unsafe { Pin::new_unchecked(value) });
-        });
-
-        // SAFETY: The inner value has been initialized, and will not be moved
-        // anymore.
-        unsafe { Pin::new_unchecked(self.get_ref().get_unchecked()) }
-    }
-
     /// Consumes the `OnceLock`, returning the wrapped value. Returns
     /// `None` if the cell was empty.
     ///
index 6e4a2cfc82afd07b80b1efd0d3a2e6a47ce2d35a..9ab781561e9b1280460d858bd36d737bfe5aa7e1 100644 (file)
@@ -101,6 +101,7 @@ unsafe impl<T: ?Sized + Send + Sync> Sync for RwLock<T> {}
                       and cause Futures to not implement `Send`"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[clippy::has_significant_drop]
+#[cfg_attr(not(test), rustc_diagnostic_item = "RwLockReadGuard")]
 pub struct RwLockReadGuard<'a, T: ?Sized + 'a> {
     // NB: we use a pointer instead of `&'a T` to avoid `noalias` violations, because a
     // `Ref` argument doesn't hold immutability for its whole scope, only until it drops.
@@ -130,6 +131,7 @@ unsafe impl<T: ?Sized + Sync> Sync for RwLockReadGuard<'_, T> {}
                       and cause Future's to not implement `Send`"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[clippy::has_significant_drop]
+#[cfg_attr(not(test), rustc_diagnostic_item = "RwLockWriteGuard")]
 pub struct RwLockWriteGuard<'a, T: ?Sized + 'a> {
     lock: &'a RwLock<T>,
     poison: poison::Guard,
index 60b7a973cc2c1d7c94a2c66640b6194e6e5b11dd..61da096ae163883f73370305916aea26aa48d8b5 100644 (file)
@@ -98,7 +98,7 @@ pub extern "C" fn __rust_abort() {
 
 // SAFETY: must be called only once during runtime initialization.
 // NOTE: this is not guaranteed to run, for example when Rust code is called externally.
-pub unsafe fn init(argc: isize, argv: *const *const u8) {
+pub unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {
     let _ = net::init();
     args::init(argc, argv);
 }
index eb15a04ffcffbf7056c77d5db09effab82eac595..e0184eb5baf69b03195945e0b385dbdcfcde5d7d 100644 (file)
@@ -174,9 +174,6 @@ pub const fn new() -> Mutex {
         Mutex { inner: Spinlock::new(MutexInner::new()) }
     }
 
-    #[inline]
-    pub unsafe fn init(&mut self) {}
-
     #[inline]
     pub unsafe fn lock(&self) {
         loop {
index 715e94c3b3d6a0928ba9497be25629c5d702a9a1..085662e6d44b86f55755a8c58b70a9e1d346bf44 100644 (file)
@@ -31,12 +31,6 @@ pub const fn new() -> Mutex {
         Mutex { mtx: SpinIdOnceCell::new() }
     }
 
-    pub unsafe fn init(&mut self) {
-        // Initialize `self.mtx` eagerly
-        let id = new_mtx().unwrap_or_else(|e| fail(e, &"acre_mtx"));
-        unsafe { self.mtx.set_unchecked((id, ())) };
-    }
-
     /// Get the inner mutex's ID, which is lazily created.
     fn raw(&self) -> abi::ID {
         match self.mtx.get_or_try_init(|| new_mtx().map(|id| (id, ()))) {
index 696400670e04d1f8f543b258602a258191e6158c..b1d32929ecfde469ee9a03ef2c9158f1cbd8a2ac 100644 (file)
@@ -47,7 +47,7 @@ pub mod locks {
 
 // SAFETY: must be called only once during runtime initialization.
 // NOTE: this is not guaranteed to run, for example when Rust code is called externally.
-pub unsafe fn init(argc: isize, argv: *const *const u8) {
+pub unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {
     unsafe {
         args::init(argc, argv);
     }
index 513cd77fd2aad17fff00752d6eba65d12b654929..aa747d56b0d3bf2b353ee3683c323e2f2e6ef12f 100644 (file)
@@ -20,9 +20,6 @@ pub const fn new() -> Mutex {
         Mutex { inner: SpinMutex::new(WaitVariable::new(false)) }
     }
 
-    #[inline]
-    pub unsafe fn init(&mut self) {}
-
     #[inline]
     pub unsafe fn lock(&self) {
         let mut guard = self.inner.lock();
index 778a589d1b724434f38d6f90eb51c370039f6027..5867979a2a729408db7b7be74eaf6d68499b5937 100644 (file)
@@ -56,7 +56,7 @@ pub mod locks {
 
 // SAFETY: must be called only once during runtime initialization.
 // NOTE: this is not guaranteed to run, for example when Rust code is called externally.
-pub unsafe fn init(_argc: isize, _argv: *const *const u8) {}
+pub unsafe fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) {}
 
 // SAFETY: must be called only once during runtime cleanup.
 pub unsafe fn cleanup() {}
index dbb9829bb666dc89cfbc789204c0b654079ffcd4..117611ce43f2490c891112fb79e727edc588166d 100644 (file)
@@ -85,9 +85,6 @@ pub const fn new() -> Mutex {
         Mutex { futex: AtomicU32::new(UNLOCKED) }
     }
 
-    #[inline]
-    pub unsafe fn init(&mut self) {}
-
     #[inline]
     pub unsafe fn try_lock(&self) -> bool {
         let thread_self = zx_thread_self();
index 1b5be46c6050230aab31e2bad89031ff6517ce13..33b13dad4d65d08a17941bf1a1209cd5913a76a2 100644 (file)
@@ -19,9 +19,6 @@ pub const fn new() -> Self {
         Self { futex: AtomicU32::new(0) }
     }
 
-    #[inline]
-    pub unsafe fn init(&mut self) {}
-
     #[inline]
     pub unsafe fn try_lock(&self) -> bool {
         self.futex.compare_exchange(0, 1, Acquire, Relaxed).is_ok()
index 98afee69ba622903bebc80f4775be49fedfe4193..5964935ddb541527c783f9fc551584d873f67d42 100644 (file)
@@ -52,7 +52,7 @@ pub const fn new() -> Mutex {
         Mutex { inner: UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER) }
     }
     #[inline]
-    pub unsafe fn init(&mut self) {
+    unsafe fn init(&mut self) {
         // Issue #33770
         //
         // A pthread mutex initialized with PTHREAD_MUTEX_INITIALIZER will have
index 3a3750930998509fca767f8decf488a8f30797d5..c84e292eac152b0dd45d65922fedd7aabc39868f 100644 (file)
 pub mod time;
 
 #[cfg(target_os = "espidf")]
-pub fn init(argc: isize, argv: *const *const u8) {}
+pub fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {}
 
 #[cfg(not(target_os = "espidf"))]
 // SAFETY: must be called only once during runtime initialization.
 // NOTE: this is not guaranteed to run, for example when Rust code is called externally.
-pub unsafe fn init(argc: isize, argv: *const *const u8) {
+// See `fn init()` in `library/std/src/rt.rs` for docs on `sigpipe`.
+pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
     // The standard streams might be closed on application startup. To prevent
     // std::io::{stdin, stdout,stderr} objects from using other unrelated file
     // resources opened later, we reopen standards streams when they are closed.
@@ -61,8 +62,9 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) {
     // want!
     //
     // Hence, we set SIGPIPE to ignore when the program starts up in order
-    // to prevent this problem.
-    reset_sigpipe();
+    // to prevent this problem. Add `#[unix_sigpipe = "..."]` above `fn main()` to
+    // alter this behavior.
+    reset_sigpipe(sigpipe);
 
     stack_overflow::init();
     args::init(argc, argv);
@@ -151,9 +153,31 @@ unsafe fn sanitize_standard_fds() {
         }
     }
 
-    unsafe fn reset_sigpipe() {
+    unsafe fn reset_sigpipe(#[allow(unused_variables)] sigpipe: u8) {
         #[cfg(not(any(target_os = "emscripten", target_os = "fuchsia", target_os = "horizon")))]
-        rtassert!(signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR);
+        {
+            // We don't want to add this as a public type to libstd, nor do we
+            // want to `include!` a file from the compiler (which would break
+            // Miri and xargo for example), so we choose to duplicate these
+            // constants from `compiler/rustc_session/src/config/sigpipe.rs`.
+            // See the other file for docs. NOTE: Make sure to keep them in
+            // sync!
+            mod sigpipe {
+                pub const INHERIT: u8 = 1;
+                pub const SIG_IGN: u8 = 2;
+                pub const SIG_DFL: u8 = 3;
+            }
+
+            let handler = match sigpipe {
+                sigpipe::INHERIT => None,
+                sigpipe::SIG_IGN => Some(libc::SIG_IGN),
+                sigpipe::SIG_DFL => Some(libc::SIG_DFL),
+                _ => unreachable!(),
+            };
+            if let Some(handler) = handler {
+                rtassert!(signal(libc::SIGPIPE, handler) != libc::SIG_ERR);
+            }
+        }
     }
 }
 
index 7db3065dee0838c1e014b43bf9694d1dc7ecaad0..56bb71b5dcbdee2c0e00e542126125192314bf26 100644 (file)
@@ -429,7 +429,7 @@ pub(super) fn quota() -> usize {
                         Some(b"") => Cgroup::V2,
                         Some(controllers)
                             if from_utf8(controllers)
-                                .is_ok_and(|c| c.split(",").any(|c| c == "cpu")) =>
+                                .is_ok_and(|c| c.split(',').any(|c| c == "cpu")) =>
                         {
                             Cgroup::V1
                         }
index 4c9ade4a8c7906714b84cd6437243a2501ab2d77..5cd9e57de19ee28e4763887b49d108fe7987b44c 100644 (file)
@@ -6,7 +6,7 @@ pub mod memchr {
 
 // SAFETY: must be called only once during runtime initialization.
 // NOTE: this is not guaranteed to run, for example when Rust code is called externally.
-pub unsafe fn init(_argc: isize, _argv: *const *const u8) {}
+pub unsafe fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) {}
 
 // SAFETY: must be called only once during runtime cleanup.
 // NOTE: this is not guaranteed to run, for example when the program aborts.
index d7cb12e0cf9a49ad0240620c32146a1b8ddb217b..2be0b34b985b9eeace983e7d7b0110c24b4deca2 100644 (file)
@@ -16,9 +16,6 @@ pub const fn new() -> Mutex {
         Mutex { locked: Cell::new(false) }
     }
 
-    #[inline]
-    pub unsafe fn init(&mut self) {}
-
     #[inline]
     pub unsafe fn lock(&self) {
         assert_eq!(self.locked.replace(true), false, "cannot recursively acquire mutex");
index c99c8efe4367f18ce174bc6c64d2e8abd66901f3..78d6ce3eff493452f934fcec8c23b4d8065bc9d1 100644 (file)
@@ -285,7 +285,7 @@ pub fn nt_success(status: NTSTATUS) -> bool {
     status >= 0
 }
 
-pub const BCRYPT_USE_SYSTEM_PREFERRED_RNG: DWORD = 0x00000002;
+pub const BCRYPT_RNG_ALG_HANDLE: usize = 0x81;
 
 #[repr(C)]
 pub struct UNICODE_STRING {
@@ -454,6 +454,12 @@ pub enum FILE_INFO_BY_HANDLE_CLASS {
     MaximumFileInfoByHandlesClass,
 }
 
+#[repr(C)]
+pub struct FILE_ATTRIBUTE_TAG_INFO {
+    pub FileAttributes: DWORD,
+    pub ReparseTag: DWORD,
+}
+
 #[repr(C)]
 pub struct FILE_DISPOSITION_INFO {
     pub DeleteFile: BOOLEAN,
index 98c8834d38403a9ce4dba30cc3c73b666c439c30..c2ad592dfea73379ca8a433aab2179307a7f2ab0 100644 (file)
@@ -326,10 +326,15 @@ pub fn file_attr(&self) -> io::Result<FileAttr> {
             cvt(c::GetFileInformationByHandle(self.handle.as_raw_handle(), &mut info))?;
             let mut reparse_tag = 0;
             if info.dwFileAttributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 {
-                let mut b =
-                    Align8([MaybeUninit::<u8>::uninit(); c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);
-                if let Ok((_, buf)) = self.reparse_point(&mut b) {
-                    reparse_tag = (*buf).ReparseTag;
+                let mut attr_tag: c::FILE_ATTRIBUTE_TAG_INFO = mem::zeroed();
+                cvt(c::GetFileInformationByHandleEx(
+                    self.handle.as_raw_handle(),
+                    c::FileAttributeTagInfo,
+                    ptr::addr_of_mut!(attr_tag).cast(),
+                    mem::size_of::<c::FILE_ATTRIBUTE_TAG_INFO>().try_into().unwrap(),
+                ))?;
+                if attr_tag.FileAttributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 {
+                    reparse_tag = attr_tag.ReparseTag;
                 }
             }
             Ok(FileAttr {
@@ -390,10 +395,15 @@ pub fn file_attr(&self) -> io::Result<FileAttr> {
             attr.file_size = info.AllocationSize as u64;
             attr.number_of_links = Some(info.NumberOfLinks);
             if attr.file_type().is_reparse_point() {
-                let mut b =
-                    Align8([MaybeUninit::<u8>::uninit(); c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);
-                if let Ok((_, buf)) = self.reparse_point(&mut b) {
-                    attr.reparse_tag = (*buf).ReparseTag;
+                let mut attr_tag: c::FILE_ATTRIBUTE_TAG_INFO = mem::zeroed();
+                cvt(c::GetFileInformationByHandleEx(
+                    self.handle.as_raw_handle(),
+                    c::FileAttributeTagInfo,
+                    ptr::addr_of_mut!(attr_tag).cast(),
+                    mem::size_of::<c::FILE_ATTRIBUTE_TAG_INFO>().try_into().unwrap(),
+                ))?;
+                if attr_tag.FileAttributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 {
+                    reparse_tag = attr_tag.ReparseTag;
                 }
             }
             Ok(attr)
index f91e8f9f59a140dbe58ff8f14581aff6112e04a7..91207f5f4665894349d4595a919e56ff8ee75cb8 100644 (file)
@@ -37,8 +37,6 @@ impl Mutex {
     pub const fn new() -> Mutex {
         Mutex { srwlock: UnsafeCell::new(c::SRWLOCK_INIT) }
     }
-    #[inline]
-    pub unsafe fn init(&mut self) {}
 
     #[inline]
     pub unsafe fn lock(&self) {
index 340cae4066bf44deb42f872769a37ffea7333afb..eab9b961279c9a60428c97fbdf05b43bff987a30 100644 (file)
@@ -48,7 +48,7 @@
 
 // SAFETY: must be called only once during runtime initialization.
 // NOTE: this is not guaranteed to run, for example when Rust code is called externally.
-pub unsafe fn init(_argc: isize, _argv: *const *const u8) {
+pub unsafe fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) {
     stack_overflow::init();
 
     // Normally, `thread::spawn` will call `Thread::set_name` but since this thread already
index f8fd93a7398e1b75c35d255e30e24447461b9cc4..8b9697884364c837ac44f8308d184ee7ab0eb78d 100644 (file)
@@ -1,16 +1,49 @@
+//! # Random key generation
+//!
+//! This module wraps the RNG provided by the OS. There are a few different
+//! ways to interface with the OS RNG so it's worth exploring each of the options.
+//! Note that at the time of writing these all go through the (undocumented)
+//! `bcryptPrimitives.dll` but they use different route to get there.
+//!
+//! Originally we were using [`RtlGenRandom`], however that function is
+//! deprecated and warns it "may be altered or unavailable in subsequent versions".
+//!
+//! So we switched to [`BCryptGenRandom`] with the `BCRYPT_USE_SYSTEM_PREFERRED_RNG`
+//! flag to query and find the system configured RNG. However, this change caused a small
+//! but significant number of users to experience panics caused by a failure of
+//! this function. See [#94098].
+//!
+//! The current version changes this to use the `BCRYPT_RNG_ALG_HANDLE`
+//! [Pseudo-handle], which gets the default RNG algorithm without querying the
+//! system preference thus hopefully avoiding the previous issue.
+//! This is only supported on Windows 10+ so a fallback is used for older versions.
+//!
+//! [#94098]: https://github.com/rust-lang/rust/issues/94098
+//! [`RtlGenRandom`]: https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom
+//! [`BCryptGenRandom`]: https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom
+//! [Pseudo-handle]: https://docs.microsoft.com/en-us/windows/win32/seccng/cng-algorithm-pseudo-handles
 use crate::io;
 use crate::mem;
 use crate::ptr;
 use crate::sys::c;
 
+/// Generates high quality secure random keys for use by [`HashMap`].
+///
+/// This is used to seed the default [`RandomState`].
+///
+/// [`HashMap`]: crate::collections::HashMap
+/// [`RandomState`]: crate::collections::hash_map::RandomState
 pub fn hashmap_random_keys() -> (u64, u64) {
     let mut v = (0, 0);
     let ret = unsafe {
+        let size = mem::size_of_val(&v).try_into().unwrap();
         c::BCryptGenRandom(
-            ptr::null_mut(),
-            &mut v as *mut _ as *mut u8,
-            mem::size_of_val(&v) as c::ULONG,
-            c::BCRYPT_USE_SYSTEM_PREFERRED_RNG,
+            // BCRYPT_RNG_ALG_HANDLE is only supported in Windows 10+.
+            // So for Windows 8.1 and Windows 7 we'll need a fallback when this fails.
+            ptr::invalid_mut(c::BCRYPT_RNG_ALG_HANDLE),
+            ptr::addr_of_mut!(v).cast(),
+            size,
+            0,
         )
     };
     if ret != 0 { fallback_rng() } else { v }
index 8921af311d4152bb7b6fc7b4c37763ce35e14915..b448ae3a99777162c35f930b64833baf34733427 100644 (file)
@@ -1,13 +1,11 @@
 #[cfg(all(test, not(target_os = "emscripten")))]
 mod tests;
 
+use super::mutex as sys;
 use crate::cell::UnsafeCell;
-use crate::marker::PhantomPinned;
 use crate::ops::Deref;
 use crate::panic::{RefUnwindSafe, UnwindSafe};
-use crate::pin::Pin;
 use crate::sync::atomic::{AtomicUsize, Ordering::Relaxed};
-use crate::sys::locks as sys;
 
 /// A re-entrant mutual exclusion
 ///
 /// synchronization is left to the mutex, making relaxed memory ordering for
 /// the `owner` field fine in all cases.
 pub struct ReentrantMutex<T> {
-    mutex: sys::Mutex,
+    mutex: sys::MovableMutex,
     owner: AtomicUsize,
     lock_count: UnsafeCell<u32>,
     data: T,
-    _pinned: PhantomPinned,
 }
 
 unsafe impl<T: Send> Send for ReentrantMutex<T> {}
@@ -68,39 +65,22 @@ impl<T> RefUnwindSafe for ReentrantMutex<T> {}
 /// guarded data.
 #[must_use = "if unused the ReentrantMutex will immediately unlock"]
 pub struct ReentrantMutexGuard<'a, T: 'a> {
-    lock: Pin<&'a ReentrantMutex<T>>,
+    lock: &'a ReentrantMutex<T>,
 }
 
 impl<T> !Send for ReentrantMutexGuard<'_, T> {}
 
 impl<T> ReentrantMutex<T> {
     /// Creates a new reentrant mutex in an unlocked state.
-    ///
-    /// # Unsafety
-    ///
-    /// This function is unsafe because it is required that `init` is called
-    /// once this mutex is in its final resting place, and only then are the
-    /// lock/unlock methods safe.
-    pub const unsafe fn new(t: T) -> ReentrantMutex<T> {
+    pub const fn new(t: T) -> ReentrantMutex<T> {
         ReentrantMutex {
-            mutex: sys::Mutex::new(),
+            mutex: sys::MovableMutex::new(),
             owner: AtomicUsize::new(0),
             lock_count: UnsafeCell::new(0),
             data: t,
-            _pinned: PhantomPinned,
         }
     }
 
-    /// Initializes this mutex so it's ready for use.
-    ///
-    /// # Unsafety
-    ///
-    /// Unsafe to call more than once, and must be called after this will no
-    /// longer move in memory.
-    pub unsafe fn init(self: Pin<&mut Self>) {
-        self.get_unchecked_mut().mutex.init()
-    }
-
     /// Acquires a mutex, blocking the current thread until it is able to do so.
     ///
     /// This function will block the caller until it is available to acquire the mutex.
@@ -113,15 +93,14 @@ pub unsafe fn init(self: Pin<&mut Self>) {
     /// If another user of this mutex panicked while holding the mutex, then
     /// this call will return failure if the mutex would otherwise be
     /// acquired.
-    pub fn lock(self: Pin<&Self>) -> ReentrantMutexGuard<'_, T> {
+    pub fn lock(&self) -> ReentrantMutexGuard<'_, T> {
         let this_thread = current_thread_unique_ptr();
-        // Safety: We only touch lock_count when we own the lock,
-        // and since self is pinned we can safely call the lock() on the mutex.
+        // Safety: We only touch lock_count when we own the lock.
         unsafe {
             if self.owner.load(Relaxed) == this_thread {
                 self.increment_lock_count();
             } else {
-                self.mutex.lock();
+                self.mutex.raw_lock();
                 self.owner.store(this_thread, Relaxed);
                 debug_assert_eq!(*self.lock_count.get(), 0);
                 *self.lock_count.get() = 1;
@@ -142,10 +121,9 @@ pub fn lock(self: Pin<&Self>) -> ReentrantMutexGuard<'_, T> {
     /// If another user of this mutex panicked while holding the mutex, then
     /// this call will return failure if the mutex would otherwise be
     /// acquired.
-    pub fn try_lock(self: Pin<&Self>) -> Option<ReentrantMutexGuard<'_, T>> {
+    pub fn try_lock(&self) -> Option<ReentrantMutexGuard<'_, T>> {
         let this_thread = current_thread_unique_ptr();
-        // Safety: We only touch lock_count when we own the lock,
-        // and since self is pinned we can safely call the try_lock on the mutex.
+        // Safety: We only touch lock_count when we own the lock.
         unsafe {
             if self.owner.load(Relaxed) == this_thread {
                 self.increment_lock_count();
@@ -179,12 +157,12 @@ fn deref(&self) -> &T {
 impl<T> Drop for ReentrantMutexGuard<'_, T> {
     #[inline]
     fn drop(&mut self) {
-        // Safety: We own the lock, and the lock is pinned.
+        // Safety: We own the lock.
         unsafe {
             *self.lock.lock_count.get() -= 1;
             if *self.lock.lock_count.get() == 0 {
                 self.lock.owner.store(0, Relaxed);
-                self.lock.mutex.unlock();
+                self.lock.mutex.raw_unlock();
             }
         }
     }
index 64873b850d3fa2e2a4dd46fcf3bd60042bb93b90..8e97ce11c34f5ed198b29044afa67049268f3e20 100644 (file)
@@ -1,18 +1,11 @@
-use crate::boxed::Box;
 use crate::cell::RefCell;
-use crate::pin::Pin;
 use crate::sync::Arc;
 use crate::sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
 use crate::thread;
 
 #[test]
 fn smoke() {
-    let m = unsafe {
-        let mut m = Box::pin(ReentrantMutex::new(()));
-        m.as_mut().init();
-        m
-    };
-    let m = m.as_ref();
+    let m = ReentrantMutex::new(());
     {
         let a = m.lock();
         {
@@ -29,20 +22,15 @@ fn smoke() {
 
 #[test]
 fn is_mutex() {
-    let m = unsafe {
-        // FIXME: Simplify this if Arc gets an Arc::get_pin_mut.
-        let mut m = Arc::new(ReentrantMutex::new(RefCell::new(0)));
-        Pin::new_unchecked(Arc::get_mut_unchecked(&mut m)).init();
-        Pin::new_unchecked(m)
-    };
+    let m = Arc::new(ReentrantMutex::new(RefCell::new(0)));
     let m2 = m.clone();
-    let lock = m.as_ref().lock();
+    let lock = m.lock();
     let child = thread::spawn(move || {
-        let lock = m2.as_ref().lock();
+        let lock = m2.lock();
         assert_eq!(*lock.borrow(), 4950);
     });
     for i in 0..100 {
-        let lock = m.as_ref().lock();
+        let lock = m.lock();
         *lock.borrow_mut() += i;
     }
     drop(lock);
@@ -51,22 +39,17 @@ fn is_mutex() {
 
 #[test]
 fn trylock_works() {
-    let m = unsafe {
-        // FIXME: Simplify this if Arc gets an Arc::get_pin_mut.
-        let mut m = Arc::new(ReentrantMutex::new(()));
-        Pin::new_unchecked(Arc::get_mut_unchecked(&mut m)).init();
-        Pin::new_unchecked(m)
-    };
+    let m = Arc::new(ReentrantMutex::new(()));
     let m2 = m.clone();
-    let _lock = m.as_ref().try_lock();
-    let _lock2 = m.as_ref().try_lock();
+    let _lock = m.try_lock();
+    let _lock2 = m.try_lock();
     thread::spawn(move || {
-        let lock = m2.as_ref().try_lock();
+        let lock = m2.try_lock();
         assert!(lock.is_none());
     })
     .join()
     .unwrap();
-    let _lock3 = m.as_ref().try_lock();
+    let _lock3 = m.try_lock();
 }
 
 pub struct Answer<'a>(pub ReentrantMutexGuard<'a, RefCell<u32>>);
index fe1b00a90fce25d229dfb62b76bc694ada48a86d..cc08ae5f99f0e80d03c36998ad02df043dcf10d0 100644 (file)
@@ -793,6 +793,8 @@ class RustBuild(object):
 
     def check_vendored_status(self):
         """Check that vendoring is configured properly"""
+        # keep this consistent with the equivalent check in rustbuild:
+        # https://github.com/rust-lang/rust/blob/a8a33cf27166d3eabaffc58ed3799e054af3b0c6/src/bootstrap/lib.rs#L399-L405
         if 'SUDO_USER' in os.environ and not self.use_vendored_sources:
             if os.getuid() == 0:
                 self.use_vendored_sources = True
index c3aabb16a9b9af131c70095d4ecc6e667efe5a07..c13e83f6c86126c82563b80f224f6252bf6dfc2e 100644 (file)
@@ -1281,7 +1281,9 @@ fn run(self, builder: &Builder<'_>) -> Compiler {
                 compiler: build_compiler,
                 target: target_compiler.host,
             });
-            builder.copy(&lld_wrapper_exe, &gcc_ld_dir.join(exe("ld", target_compiler.host)));
+            for name in crate::LLD_FILE_NAMES {
+                builder.copy(&lld_wrapper_exe, &gcc_ld_dir.join(exe(name, target_compiler.host)));
+            }
         }
 
         if builder.config.rust_codegen_backends.contains(&INTERNER.intern_str("llvm")) {
index 13e3049f2c81ff001a9bfbbce5efb075c676772c..7c062460c4f16e8eb21475c0e5da443bbc015f64 100644 (file)
@@ -388,6 +388,7 @@ fn eq(&self, other: &&str) -> bool {
 pub struct Target {
     /// Some(path to llvm-config) if using an external LLVM.
     pub llvm_config: Option<PathBuf>,
+    pub llvm_has_rust_patches: Option<bool>,
     /// Some(path to FileCheck) if one was specified.
     pub llvm_filecheck: Option<PathBuf>,
     pub llvm_libunwind: Option<LlvmLibunwind>,
@@ -733,6 +734,7 @@ struct TomlTarget {
         default_linker: Option<PathBuf> = "default-linker",
         linker: Option<String> = "linker",
         llvm_config: Option<String> = "llvm-config",
+        llvm_has_rust_patches: Option<bool> = "llvm-has-rust-patches",
         llvm_filecheck: Option<String> = "llvm-filecheck",
         llvm_libunwind: Option<String> = "llvm-libunwind",
         android_ndk: Option<String> = "android-ndk",
@@ -1109,6 +1111,7 @@ pub fn parse(args: &[String]) -> Config {
                 if let Some(ref s) = cfg.llvm_config {
                     target.llvm_config = Some(config.src.join(s));
                 }
+                target.llvm_has_rust_patches = cfg.llvm_has_rust_patches;
                 if let Some(ref s) = cfg.llvm_filecheck {
                     target.llvm_filecheck = Some(config.src.join(s));
                 }
index c01afa1fd3b75c3fbc07f38f4fcac5c158846e35..1a59b3958f1060844999fa0dac6ab6e7f30c3807 100644 (file)
@@ -423,8 +423,11 @@ fn prepare_image(builder: &Builder<'_>, compiler: Compiler, image: &Path) {
                 let gcc_lld_src_dir = src_dir.join("gcc-ld");
                 let gcc_lld_dst_dir = dst_dir.join("gcc-ld");
                 t!(fs::create_dir(&gcc_lld_dst_dir));
-                let exe_name = exe("ld", compiler.host);
-                builder.copy(&gcc_lld_src_dir.join(&exe_name), &gcc_lld_dst_dir.join(&exe_name));
+                for name in crate::LLD_FILE_NAMES {
+                    let exe_name = exe(name, compiler.host);
+                    builder
+                        .copy(&gcc_lld_src_dir.join(&exe_name), &gcc_lld_dst_dir.join(&exe_name));
+                }
             }
 
             // Man pages
index 2852442d0be6fbb7986a84f211a84a6494cde744..f909ecc0ab858404403aaa3edb7df83d6043df97 100644 (file)
@@ -793,7 +793,7 @@ fn run(self, builder: &Builder<'_>) {
         t!(fs::create_dir_all(&out));
         let mut index = tool::ErrorIndex::command(builder);
         index.arg("html");
-        index.arg(out.join("error-index.html"));
+        index.arg(out);
         index.arg(&builder.version);
 
         builder.run(&mut index);
index d111d945d6f2f5b439dd3c76aaf71d16e655b7d5..cc0cf12bd187a7fc48ed6c06bfa09a9af5e064b0 100644 (file)
 use std::process::Command;
 use std::str;
 
+use config::Target;
 use filetime::FileTime;
 use once_cell::sync::OnceCell;
 
@@ -186,6 +187,9 @@ pub unsafe fn setup(_build: &mut crate::Build) {}
     "opt",           // used to optimize LLVM bytecode
 ];
 
+/// LLD file names for all flavors.
+const LLD_FILE_NAMES: &[&str] = &["ld.lld", "ld64.lld", "lld-link", "wasm-ld"];
+
 pub const VERSION: usize = 2;
 
 /// Extra --check-cfg to add when building
@@ -395,13 +399,18 @@ pub fn new(config: Config) -> Build {
         let src = config.src.clone();
         let out = config.out.clone();
 
+        #[cfg(unix)]
+        // keep this consistent with the equivalent check in x.py:
+        // https://github.com/rust-lang/rust/blob/a8a33cf27166d3eabaffc58ed3799e054af3b0c6/src/bootstrap/bootstrap.py#L796-L797
         let is_sudo = match env::var_os("SUDO_USER") {
-            Some(sudo_user) => match env::var_os("USER") {
-                Some(user) => user != sudo_user,
-                None => false,
-            },
+            Some(_sudo_user) => {
+                let uid = unsafe { libc::getuid() };
+                uid == 0
+            }
             None => false,
         };
+        #[cfg(not(unix))]
+        let is_sudo = false;
 
         let ignore_git = config.ignore_git;
         let rust_info = channel::GitInfo::new(ignore_git, &src);
@@ -834,12 +843,13 @@ fn md_doc_out(&self, target: TargetSelection) -> Interned<PathBuf> {
     ///
     /// If no custom `llvm-config` was specified then Rust's llvm will be used.
     fn is_rust_llvm(&self, target: TargetSelection) -> bool {
-        if self.config.llvm_from_ci && target == self.config.build {
-            return true;
-        }
-
         match self.config.target_config.get(&target) {
-            Some(ref c) => c.llvm_config.is_none(),
+            Some(Target { llvm_has_rust_patches: Some(patched), .. }) => *patched,
+            Some(Target { llvm_config, .. }) => {
+                // If the user set llvm-config we assume Rust is not patched,
+                // but first check to see if it was configured by llvm-from-ci.
+                (self.config.llvm_from_ci && target == self.config.build) || llvm_config.is_none()
+            }
             None => true,
         }
     }
index f1c2a21de59f7fe39b03ca1df7715100c3683b31..f61c95830858fb6f4b869b79701305627c7adc55 100644 (file)
@@ -854,7 +854,10 @@ fn get_browser_ui_test_version_inner(npm: &Path, global: bool) -> Option<String>
         .output()
         .map(|output| String::from_utf8_lossy(&output.stdout).into_owned())
         .unwrap_or(String::new());
-    lines.lines().find_map(|l| l.split(":browser-ui-test@").skip(1).next()).map(|v| v.to_owned())
+    lines
+        .lines()
+        .find_map(|l| l.split(':').nth(1)?.strip_prefix("browser-ui-test@"))
+        .map(|v| v.to_owned())
 }
 
 fn get_browser_ui_test_version(npm: &Path) -> Option<String> {
index d0d367b39b493850cfce53e8095f2f05f7127905..7a875c960e13312d77d11983c0f4bab304b4c554 100644 (file)
@@ -1,5 +1,6 @@
-FROM ubuntu:16.04
+FROM ubuntu:22.04
 
+ARG DEBIAN_FRONTEND=noninteractive
 COPY scripts/android-base-apt-get.sh /scripts/
 RUN sh /scripts/android-base-apt-get.sh
 
@@ -13,7 +14,7 @@ RUN dpkg --add-architecture i386 && \
   libgl1-mesa-glx \
   libpulse0 \
   libstdc++6:i386 \
-  openjdk-9-jre-headless \
+  openjdk-8-jre-headless \
   tzdata \
   wget \
   python3
@@ -29,20 +30,12 @@ ENV PATH=$PATH:/android/sdk/platform-tools
 
 ENV TARGETS=arm-linux-androideabi
 
-# We are intentionally allowing an old toolchain on this builder (and that's
-# incompatible with LLVM downloads today).
-ENV NO_DOWNLOAD_CI_LLVM 1
-
-ENV RUST_CONFIGURE_ARGS --arm-linux-androideabi-ndk=/android/ndk/arm-14 \
-    --set llvm.allow-old-toolchain
+ENV RUST_CONFIGURE_ARGS --arm-linux-androideabi-ndk=/android/ndk/arm-14
 
 ENV SCRIPT python3 ../x.py --stage 2 test --host='' --target $TARGETS
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-COPY scripts/cmake.sh /scripts/
-RUN /scripts/cmake.sh
-
 COPY scripts/android-start-emulator.sh /scripts/
 ENTRYPOINT ["/scripts/android-start-emulator.sh"]
index c98fa496d4861d22c274e17d3f38c2ca12fc7ccf..2328db4ab8b1d126dd774a67a744afb990bde1e0 100644 (file)
@@ -1,4 +1,4 @@
-FROM ubuntu:16.04
+FROM ubuntu:22.04
 
 COPY scripts/android-base-apt-get.sh /scripts/
 RUN sh /scripts/android-base-apt-get.sh
@@ -32,13 +32,9 @@ ENV RUST_CONFIGURE_ARGS \
       --i686-linux-android-ndk=/android/ndk/x86-14 \
       --aarch64-linux-android-ndk=/android/ndk/arm64-21 \
       --x86_64-linux-android-ndk=/android/ndk/x86_64-21 \
-      --disable-docs \
-      --set llvm.allow-old-toolchain
+      --disable-docs
 
 ENV SCRIPT python3 ../x.py dist --host='' --target $TARGETS
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
-
-COPY scripts/cmake.sh /scripts/
-RUN /scripts/cmake.sh
index 71ea13071bd1f1345d0841f3208fa92f131b77a5..dd74726f856915a73311b92112066fe976d6e34a 100644 (file)
@@ -1,5 +1,6 @@
-FROM ubuntu:16.04
+FROM ubuntu:22.04
 
+ARG DEBIAN_FRONTEND=noninteractive
 RUN apt-get update && apt-get install -y --no-install-recommends \
   g++-multilib \
   make \
@@ -20,18 +21,10 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-COPY scripts/cmake.sh /scripts/
-RUN /scripts/cmake.sh
-
 RUN mkdir -p /config
 RUN echo "[rust]" > /config/nopt-std-config.toml
 RUN echo "optimize = false" >> /config/nopt-std-config.toml
 
-# We are intentionally allowing an old toolchain on this builder (and that's
-# incompatible with LLVM downloads today).
-ENV NO_DOWNLOAD_CI_LLVM 1
-
-ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu --disable-optimize-tests \
-    --set llvm.allow-old-toolchain
+ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu --disable-optimize-tests
 ENV SCRIPT python3 ../x.py test --stage 0 --config /config/nopt-std-config.toml library/std \
   && python3 ../x.py --stage 2 test
index ebeab3dbdb79913c87a55877c553e80e15dca62a..0c36cfd66bdef05ac0842102035c2288fc84b271 100644 (file)
@@ -1,5 +1,6 @@
-FROM ubuntu:16.04
+FROM ubuntu:22.04
 
+ARG DEBIAN_FRONTEND=noninteractive
 RUN apt-get update && apt-get install -y --no-install-recommends \
   g++-multilib \
   make \
@@ -20,14 +21,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-COPY scripts/cmake.sh /scripts/
-RUN /scripts/cmake.sh
-
-# We are intentionally allowing an old toolchain on this builder (and that's
-# incompatible with LLVM downloads today).
-ENV NO_DOWNLOAD_CI_LLVM 1
-ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu \
-    --set llvm.allow-old-toolchain
+ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu
 # Exclude some tests that are unlikely to be platform specific, to speed up
 # this slow job.
 ENV SCRIPT python3 ../x.py --stage 2 test \
index c6723d91c8bb4cd9632f52ec2a637783da620067..52a7776153dac353e3d2ca72f95a13958efff3dc 100644 (file)
@@ -45,7 +45,8 @@ ENV SCRIPT python3 ../x.py --stage 2 test src/tools/expand-yaml-anchors && \
            python3 ../x.py test --stage 0 src/tools/compiletest && \
            python3 ../x.py test --stage 2 src/tools/tidy && \
            python3 ../x.py test --stage 0 core alloc std test proc_macro && \
-           python3 ../x.py doc --stage 0 library/test && \
+           # Build both public and internal documentation.
+           RUSTDOCFLAGS="--document-private-items" python3 ../x.py doc --stage 0 library/test && \
            /scripts/validate-toolstate.sh && \
            /scripts/validate-error-codes.sh && \
            reuse lint && \
index 321b3d6ace486d84f5cc9bbe0cd6df052a96e7e0..d55d5b56ad3f5e8cccfced590d0d2c0a81dcbf0f 100644 (file)
@@ -1,5 +1,6 @@
-FROM ubuntu:16.04
+FROM ubuntu:22.04
 
+ARG DEBIAN_FRONTEND=noninteractive
 RUN apt-get update && apt-get install -y --no-install-recommends \
   g++ \
   make \
@@ -23,13 +24,5 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-COPY scripts/cmake.sh /scripts/
-RUN /scripts/cmake.sh
-
-# We are intentionally allowing an old toolchain on this builder (and that's
-# incompatible with LLVM downloads today).
-ENV NO_DOWNLOAD_CI_LLVM 1
-
-ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu \
-    --set llvm.allow-old-toolchain
+ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu
 ENV RUST_CHECK_TARGET check-aux
index be4def85f14c4735c41b63da42f00a317273d438..80a004501a81bb590553c4d77e8861587f331d07 100644 (file)
@@ -1,5 +1,6 @@
-FROM ubuntu:16.04
+FROM ubuntu:22.04
 
+ARG DEBIAN_FRONTEND=noninteractive
 RUN apt-get update && apt-get install -y --no-install-recommends \
   g++ \
   make \
@@ -19,14 +20,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-COPY scripts/cmake.sh /scripts/
-RUN /scripts/cmake.sh
-
-# We are intentionally allowing an old toolchain on this builder (and that's
-# incompatible with LLVM downloads today).
+# We are disabling CI LLVM since distcheck is an offline build.
 ENV NO_DOWNLOAD_CI_LLVM 1
 
-ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --set rust.ignore-git=false \
-    --set llvm.allow-old-toolchain
+ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --set rust.ignore-git=false
 ENV SCRIPT python3 ../x.py --stage 2 test distcheck
 ENV DIST_SRC 1
index e2ec4f275001b53d24fececc91607eaa810e1a75..4350ca205862ce742923d79c642b2511ad19f955 100644 (file)
@@ -1,5 +1,6 @@
-FROM ubuntu:16.04
+FROM ubuntu:22.04
 
+ARG DEBIAN_FRONTEND=noninteractive
 RUN apt-get update && apt-get install -y --no-install-recommends \
   g++ \
   make \
@@ -27,6 +28,7 @@ RUN apt-get install -y \
   libdbus-1-3 \
   libexpat1 \
   libfontconfig1 \
+  libgbm1 \
   libgcc1 \
   libgconf-2-4 \
   libgdk-pixbuf2.0-0 \
@@ -59,13 +61,10 @@ RUN apt-get install -y \
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-COPY scripts/cmake.sh /scripts/
-RUN /scripts/cmake.sh
-
 COPY host-x86_64/x86_64-gnu-tools/checktools.sh /tmp/
 
-RUN curl -sL https://nodejs.org/dist/v14.4.0/node-v14.4.0-linux-x64.tar.xz | tar -xJ
-ENV NODE_FOLDER=/node-v14.4.0-linux-x64/bin
+RUN curl -sL https://nodejs.org/dist/v14.20.0/node-v14.20.0-linux-x64.tar.xz | tar -xJ
+ENV NODE_FOLDER=/node-v14.20.0-linux-x64/bin
 ENV PATH="$NODE_FOLDER:${PATH}"
 
 COPY host-x86_64/x86_64-gnu-tools/browser-ui-test.version /tmp/
@@ -80,14 +79,10 @@ COPY host-x86_64/x86_64-gnu-tools/browser-ui-test.version /tmp/
 # the local version of the package is different than the one used by the CI.
 RUN npm install -g browser-ui-test@$(head -n 1 /tmp/browser-ui-test.version) --unsafe-perm=true
 
-# We are intentionally allowing an old toolchain on this builder (and that's
-# incompatible with LLVM downloads today).
-ENV NO_DOWNLOAD_CI_LLVM 1
-
 ENV RUST_CONFIGURE_ARGS \
-  --set llvm.allow-old-toolchain \
   --build=x86_64-unknown-linux-gnu \
   --save-toolstates=/tmp/toolstate/toolstates.json
 
 ENV SCRIPT /tmp/checktools.sh ../x.py && \
-  NODE_PATH=`npm root -g` python3 ../x.py test src/test/rustdoc-gui --stage 2
+  NODE_PATH=`npm root -g` python3 ../x.py test src/test/rustdoc-gui --stage 2 \
+    --test-args "'--no-sandbox --jobs 1'"
index f1761f80643ba32321af88365051aac4c49b6c52..22e2e243e430a0d7a9d103b3bcdb63ed697c2691 100644 (file)
@@ -10,6 +10,7 @@ apt-get install -y --no-install-recommends \
   g++ \
   git \
   libssl-dev \
+  libncurses5 \
   make \
   ninja-build \
   pkg-config \
diff --git a/src/doc/rustc/src/platform-support/armv4t-none-eabi.md b/src/doc/rustc/src/platform-support/armv4t-none-eabi.md
new file mode 100644 (file)
index 0000000..cf831e1
--- /dev/null
@@ -0,0 +1,70 @@
+# armv4t-none-eabi
+
+Tier 3
+
+Bare-metal target for any cpu in the ARMv4T architecture family, supporting
+ARM/Thumb code interworking (aka `a32`/`t32`), with ARM code as the default code
+generation.
+
+In particular this supports the Gameboy Advance (GBA), but there's nothing GBA
+specific with this target, so any ARMv4T device should work fine.
+
+## Target Maintainers
+
+* [@Lokathor](https://github.com/lokathor)
+
+## Requirements
+
+The target is cross-compiled, and uses static linking.
+
+The linker that comes with rustc cannot link for this platform (the platform is
+too old). You will need the `arm-none-eabi-ld` linker from a GNU Binutils
+targeting ARM. This can be obtained for Windows/Mac/Linux from the [ARM
+Developer Website][arm-dev], or possibly from your OS's package manager.
+
+[arm-dev]: https://developer.arm.com/Tools%20and%20Software/GNU%20Toolchain
+
+This target doesn't provide a linker script, you'll need to bring your own
+according to the specific device you want to target. Pass
+`-Clink-arg=-Tyour_script.ld` as a rustc argument to make the linker use
+`your_script.ld` during linking.
+
+## Building Rust Programs
+
+Because it is Tier 3, rust does not yet ship pre-compiled artifacts for this target.
+
+Just use the `build-std` nightly cargo feature to build the `core` library. You
+can pass this as a command line argument to cargo, or your `.cargo/config.toml`
+file might include the following lines:
+
+```toml
+[unstable]
+build-std = ["core"]
+```
+
+Most of `core` should work as expected, with the following notes:
+* the target is "soft float", so `f32` and `f64` operations are emulated in
+  software.
+* integer division is also emulated in software.
+* the target is old enough that it doesn't have atomic instructions.
+
+Rust programs are output as ELF files.
+
+For running on hardware, you'll generally need to extract the "raw" program code
+out of the ELF and into a file of its own. The `objcopy` program provided as
+part of the GNU Binutils can do this:
+
+```shell
+arm-none-eabi-objcopy --output-target binary [in_file] [out_file]
+```
+
+## Testing
+
+This is a cross-compiled target that you will need to emulate during testing.
+
+Because this is a device-agnostic target, and the exact emulator that you'll
+need depends on the specific device you want to run your code on.
+
+For example, when programming for the Gameboy Advance, the
+[mgba-test-runner](https://github.com/agbrs/agb) program could be used to make a
+normal set of rust tests be run within the `mgba` emulator.
diff --git a/src/doc/rustc/src/platform-support/armv4t_none_eabi.md b/src/doc/rustc/src/platform-support/armv4t_none_eabi.md
deleted file mode 100644 (file)
index cf831e1..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-# armv4t-none-eabi
-
-Tier 3
-
-Bare-metal target for any cpu in the ARMv4T architecture family, supporting
-ARM/Thumb code interworking (aka `a32`/`t32`), with ARM code as the default code
-generation.
-
-In particular this supports the Gameboy Advance (GBA), but there's nothing GBA
-specific with this target, so any ARMv4T device should work fine.
-
-## Target Maintainers
-
-* [@Lokathor](https://github.com/lokathor)
-
-## Requirements
-
-The target is cross-compiled, and uses static linking.
-
-The linker that comes with rustc cannot link for this platform (the platform is
-too old). You will need the `arm-none-eabi-ld` linker from a GNU Binutils
-targeting ARM. This can be obtained for Windows/Mac/Linux from the [ARM
-Developer Website][arm-dev], or possibly from your OS's package manager.
-
-[arm-dev]: https://developer.arm.com/Tools%20and%20Software/GNU%20Toolchain
-
-This target doesn't provide a linker script, you'll need to bring your own
-according to the specific device you want to target. Pass
-`-Clink-arg=-Tyour_script.ld` as a rustc argument to make the linker use
-`your_script.ld` during linking.
-
-## Building Rust Programs
-
-Because it is Tier 3, rust does not yet ship pre-compiled artifacts for this target.
-
-Just use the `build-std` nightly cargo feature to build the `core` library. You
-can pass this as a command line argument to cargo, or your `.cargo/config.toml`
-file might include the following lines:
-
-```toml
-[unstable]
-build-std = ["core"]
-```
-
-Most of `core` should work as expected, with the following notes:
-* the target is "soft float", so `f32` and `f64` operations are emulated in
-  software.
-* integer division is also emulated in software.
-* the target is old enough that it doesn't have atomic instructions.
-
-Rust programs are output as ELF files.
-
-For running on hardware, you'll generally need to extract the "raw" program code
-out of the ELF and into a file of its own. The `objcopy` program provided as
-part of the GNU Binutils can do this:
-
-```shell
-arm-none-eabi-objcopy --output-target binary [in_file] [out_file]
-```
-
-## Testing
-
-This is a cross-compiled target that you will need to emulate during testing.
-
-Because this is a device-agnostic target, and the exact emulator that you'll
-need depends on the specific device you want to run your code on.
-
-For example, when programming for the Gameboy Advance, the
-[mgba-test-runner](https://github.com/agbrs/agb) program could be used to make a
-normal set of rust tests be run within the `mgba` emulator.
index c2a1613f288c5c8a7db18addef22bb474d17209b..3c9eecbe128d6ca9b04272b1e1bbe6b454e4466c 100644 (file)
@@ -79,7 +79,7 @@ the following commands:
 
 ```sh
 rustup target add x86_64-fuchsia
-rustup target add aarch_64-fuchsia
+rustup target add aarch64-fuchsia
 ```
 
 After installing our Fuchsia targets, we can now compile a Rust binary that targets
@@ -125,13 +125,20 @@ during compilation:
 [target.x86_64-fuchsia]
 
 rustflags = [
-    "-Lnative", "<SDK_PATH>/arch/x64/sysroot/lib",
-    "-Lnative", "<SDK_PATH>/arch/x64/lib"
+    "-Lnative=<SDK_PATH>/arch/x64/lib",
+    "-Lnative=<SDK_PATH>/arch/x64/sysroot/lib"
 ]
 ```
 
 *Note: Make sure to fill out `<SDK_PATH>` with the path to the downloaded [Fuchsia SDK].*
 
+These options configure the following:
+
+* `-Lnative=${SDK_PATH}/arch/${ARCH}/lib`: Link against Fuchsia libraries from
+  the SDK
+* `-Lnative=${SDK_PATH}/arch/${ARCH}/sysroot/lib`: Link against Fuchsia kernel
+  libraries from the SDK
+
 In total, our new project will look like:
 
 **Current directory structure**
@@ -323,10 +330,18 @@ Now, create the following files inside:
 The `package` file describes our package's name and version number. Every
 package must contain one.
 
-**`pkg/hello_fuchsia.manifest`**
+**`pkg/hello_fuchsia.manifest` if using cargo**
+```txt
+bin/hello_fuchsia=target/x86_64-fuchsia/debug/hello_fuchsia
+lib/ld.so.1=<SDK_PATH>/arch/x64/sysroot/dist/lib/ld.so.1
+lib/libfdio.so=<SDK_PATH>/arch/x64/dist/libfdio.so
+meta/package=pkg/meta/package
+meta/hello_fuchsia.cm=pkg/meta/hello_fuchsia.cm
+```
+
+**`pkg/hello_fuchsia.manifest` if using rustc**
 ```txt
-bin/hello_fuchsia=target/x86_64-fuchsia/debug/hello_fuchsia     # If using cargo...
-bin/hello_fuchsia=bin/hello_fuchsia                             # If using rustc...
+bin/hello_fuchsia=bin/hello_fuchsia
 lib/ld.so.1=<SDK_PATH>/arch/x64/sysroot/dist/lib/ld.so.1
 lib/libfdio.so=<SDK_PATH>/arch/x64/dist/libfdio.so
 meta/package=pkg/meta/package
@@ -368,6 +383,7 @@ language called CML. The Fuchsia devsite contains an [overview of CML] and a
 }
 ```
 
+**Current directory structure**
 ```txt
 hello_fuchsia/
 ┗━ pkg/
@@ -386,6 +402,9 @@ ${SDK_PATH}/tools/${ARCH}/cmc compile \
     -o pkg/meta/hello_fuchsia.cm
 ```
 
+*Note: `--includepath` tells the compiler where to look for `include`s from our CML.
+In our case, we're only using `syslog/client.shard.cml`.*
+
 **Current directory structure**
 ```txt
 hello_fuchsia/
@@ -397,19 +416,16 @@ hello_fuchsia/
    ┗━ hello_fuchsia.cml
 ```
 
-*Note: `--includepath` tells the compiler where to look for `include`s from our CML.
-In our case, we're only using `syslog/client.shard.cml`.*
-
 ### Building a Fuchsia package
 
 Next, we'll build a package manifest as defined by our manifest:
 
 ```sh
 ${SDK_PATH}/tools/${ARCH}/pm \
-    -o hello_fuchsia_manifest \
+    -o pkg/hello_fuchsia_manifest \
     -m pkg/hello_fuchsia.manifest \
     build \
-    -output-package-manifest hello_fuchsia_package_manifest
+    -output-package-manifest pkg/hello_fuchsia_package_manifest
 ```
 
 This will produce `pkg/hello_fuchsia_manifest/` which is a package manifest we can
@@ -469,15 +485,15 @@ We can publish our new package to that repository with:
 
 ```sh
 ${SDK_PATH}/tools/${ARCH}/pm publish \
-    -repo repo \
-    -lp -f <(echo "hello_fuchsia_package_manifest")
+    -repo pkg/repo \
+    -lp -f <(echo "pkg/hello_fuchsia_package_manifest")
 ```
 
 Then we can add the repository to `ffx`'s package server as `hello-fuchsia` using:
 
 ```sh
 ${SDK_PATH}/tools/${ARCH}/ffx repository add-from-pm \
-    repo \
+    pkg/repo \
     -r hello-fuchsia
 ```
 
@@ -554,6 +570,7 @@ Finally, run the component:
 
 ```sh
 ${SDK_PATH}/tools/${ARCH}/ffx component run \
+    /core/ffx-laboratory:hello_fuchsia \
     fuchsia-pkg://hello-fuchsia/hello_fuchsia_manifest#meta/hello_fuchsia.cm
 ```
 
@@ -563,6 +580,7 @@ passed.
 ```sh
 ${SDK_PATH}/tools/${ARCH}/ffx component run \
     --recreate \
+    /core/ffx-laboratory:hello_fuchsia \
     fuchsia-pkg://hello-fuchsia/hello_fuchsia_manifest#meta/hello_fuchsia.cm
 ```
 
diff --git a/src/doc/unstable-book/src/language-features/unix-sigpipe.md b/src/doc/unstable-book/src/language-features/unix-sigpipe.md
new file mode 100644 (file)
index 0000000..aa39b6e
--- /dev/null
@@ -0,0 +1,54 @@
+# `unix_sigpipe`
+
+The tracking issue for this feature is: [#97889]
+
+[#97889]: https://github.com/rust-lang/rust/issues/97889
+
+---
+
+The `#[unix_sigpipe = "..."]` attribute on `fn main()` can be used to specify how libstd shall setup `SIGPIPE` on Unix platforms before invoking `fn main()`. This attribute is ignored on non-Unix targets. There are three variants:
+* `#[unix_sigpipe = "inherit"]`
+* `#[unix_sigpipe = "sig_dfl"]`
+* `#[unix_sigpipe = "sig_ign"]`
+
+## `#[unix_sigpipe = "inherit"]`
+
+Leave `SIGPIPE` untouched before entering `fn main()`. Unless the parent process has changed the default `SIGPIPE` handler from `SIG_DFL` to something else, this will behave the same as `#[unix_sigpipe = "sig_dfl"]`.
+
+## `#[unix_sigpipe = "sig_dfl"]`
+
+Set the `SIGPIPE` handler to `SIG_DFL`. This will result in your program getting killed if it tries to write to a closed pipe. This is normally what you want if your program produces textual output.
+
+### Example
+
+```rust,no_run
+#![feature(unix_sigpipe)]
+#[unix_sigpipe = "sig_dfl"]
+fn main() { loop { println!("hello world"); } }
+```
+
+```bash
+% ./main | head -n 1
+hello world
+```
+
+## `#[unix_sigpipe = "sig_ign"]`
+
+Set the `SIGPIPE` handler to `SIG_IGN` before invoking `fn main()`. This will result in `ErrorKind::BrokenPipe` errors if you program tries to write to a closed pipe. This is normally what you want if you for example write socket servers, socket clients, or pipe peers.
+
+This is what libstd has done by default since 2014. Omitting `#[unix_sigpipe = "..."]` is the same as having `#[unix_sigpipe = "sig_ign"]`.
+
+### Example
+
+```rust,no_run
+#![feature(unix_sigpipe)]
+#[unix_sigpipe = "sig_ign"]
+fn main() { loop { println!("hello world"); } }
+```
+
+```bash
+% ./main | head -n 1
+hello world
+thread 'main' panicked at 'failed printing to stdout: Broken pipe (os error 32)', library/std/src/io/stdio.rs:1016:9
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+```
index ebf6c55ee35df7ce96acd8617308df1b77681726..be2227f47af613c50797412a1f30d55160049c30 100644 (file)
@@ -1786,7 +1786,10 @@ pub(crate) fn clean_visibility(vis: ty::Visibility) -> Visibility {
 
 pub(crate) fn clean_variant_def<'tcx>(variant: &ty::VariantDef, cx: &mut DocContext<'tcx>) -> Item {
     let kind = match variant.ctor_kind {
-        CtorKind::Const => Variant::CLike,
+        CtorKind::Const => Variant::CLike(match variant.discr {
+            ty::VariantDiscr::Explicit(def_id) => Some(Discriminant { expr: None, value: def_id }),
+            ty::VariantDiscr::Relative(_) => None,
+        }),
         CtorKind::Fn => Variant::Tuple(
             variant.fields.iter().map(|field| clean_middle_field(field, cx)).collect(),
         ),
@@ -1803,6 +1806,7 @@ pub(crate) fn clean_variant_def<'tcx>(variant: &ty::VariantDef, cx: &mut DocCont
 
 fn clean_variant_data<'tcx>(
     variant: &hir::VariantData<'tcx>,
+    disr_expr: &Option<hir::AnonConst>,
     cx: &mut DocContext<'tcx>,
 ) -> Variant {
     match variant {
@@ -1813,7 +1817,10 @@ fn clean_variant_data<'tcx>(
         hir::VariantData::Tuple(..) => {
             Variant::Tuple(variant.fields().iter().map(|x| clean_field(x, cx)).collect())
         }
-        hir::VariantData::Unit(..) => Variant::CLike,
+        hir::VariantData::Unit(..) => Variant::CLike(disr_expr.map(|disr| Discriminant {
+            expr: Some(disr.body),
+            value: cx.tcx.hir().local_def_id(disr.hir_id).to_def_id(),
+        })),
     }
 }
 
@@ -1967,7 +1974,7 @@ fn clean_maybe_renamed_item<'tcx>(
 }
 
 fn clean_variant<'tcx>(variant: &hir::Variant<'tcx>, cx: &mut DocContext<'tcx>) -> Item {
-    let kind = VariantItem(clean_variant_data(&variant.data, cx));
+    let kind = VariantItem(clean_variant_data(&variant.data, &variant.disr_expr, cx));
     let what_rustc_thinks =
         Item::from_hir_id_and_parts(variant.id, Some(variant.ident.name), kind, cx);
     // don't show `pub` for variants, which are always public
index 2808b400a0b531fbfa462e53b565feb42e1f88f3..d6bb7c6c4fc89055e6540f6a19db0209aaebfbb1 100644 (file)
@@ -2098,7 +2098,7 @@ pub(crate) fn variants(&self) -> impl Iterator<Item = &Item> {
 
 #[derive(Clone, Debug)]
 pub(crate) enum Variant {
-    CLike,
+    CLike(Option<Discriminant>),
     Tuple(Vec<Item>),
     Struct(VariantStruct),
 }
@@ -2107,11 +2107,31 @@ impl Variant {
     pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
         match *self {
             Self::Struct(ref struct_) => Some(struct_.has_stripped_entries()),
-            Self::CLike | Self::Tuple(_) => None,
+            Self::CLike(..) | Self::Tuple(_) => None,
         }
     }
 }
 
+#[derive(Clone, Debug)]
+pub(crate) struct Discriminant {
+    // In the case of cross crate re-exports, we don't have the nessesary information
+    // to reconstruct the expression of the discriminant, only the value.
+    pub(super) expr: Option<BodyId>,
+    pub(super) value: DefId,
+}
+
+impl Discriminant {
+    /// Will be `None` in the case of cross-crate reexports, and may be
+    /// simplified
+    pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> Option<String> {
+        self.expr.map(|body| print_const_expr(tcx, body))
+    }
+    /// Will always be a machine readable number, without underscores or suffixes.
+    pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> String {
+        print_evaluated_const(tcx, self.value, false).unwrap()
+    }
+}
+
 /// Small wrapper around [`rustc_span::Span`] that adds helper methods
 /// and enforces calling [`rustc_span::Span::source_callsite()`].
 #[derive(Copy, Clone, Debug)]
@@ -2338,7 +2358,7 @@ pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
         match *self {
             ConstantKind::TyConst { .. } | ConstantKind::Anonymous { .. } => None,
             ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
-                print_evaluated_const(tcx, def_id)
+                print_evaluated_const(tcx, def_id, true)
             }
         }
     }
index ac9ab33961676c4b4bc90a387ceccc4240055402..a9d511ae11e8b92db472859e788db67d7b317d99 100644 (file)
@@ -261,7 +261,11 @@ pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
     }
 }
 
-pub(crate) fn print_evaluated_const(tcx: TyCtxt<'_>, def_id: DefId) -> Option<String> {
+pub(crate) fn print_evaluated_const(
+    tcx: TyCtxt<'_>,
+    def_id: DefId,
+    underscores_and_type: bool,
+) -> Option<String> {
     tcx.const_eval_poly(def_id).ok().and_then(|val| {
         let ty = tcx.type_of(def_id);
         match (val, ty.kind()) {
@@ -269,7 +273,7 @@ pub(crate) fn print_evaluated_const(tcx: TyCtxt<'_>, def_id: DefId) -> Option<St
             (ConstValue::Scalar(_), &ty::Adt(_, _)) => None,
             (ConstValue::Scalar(_), _) => {
                 let const_ = mir::ConstantKind::from_value(val, ty);
-                Some(print_const_with_custom_print_scalar(tcx, const_))
+                Some(print_const_with_custom_print_scalar(tcx, const_, underscores_and_type))
             }
             _ => None,
         }
@@ -302,23 +306,35 @@ fn format_integer_with_underscore_sep(num: &str) -> String {
         .collect()
 }
 
-fn print_const_with_custom_print_scalar(tcx: TyCtxt<'_>, ct: mir::ConstantKind<'_>) -> String {
+fn print_const_with_custom_print_scalar(
+    tcx: TyCtxt<'_>,
+    ct: mir::ConstantKind<'_>,
+    underscores_and_type: bool,
+) -> String {
     // Use a slightly different format for integer types which always shows the actual value.
     // For all other types, fallback to the original `pretty_print_const`.
     match (ct, ct.ty().kind()) {
         (mir::ConstantKind::Val(ConstValue::Scalar(int), _), ty::Uint(ui)) => {
-            format!("{}{}", format_integer_with_underscore_sep(&int.to_string()), ui.name_str())
+            if underscores_and_type {
+                format!("{}{}", format_integer_with_underscore_sep(&int.to_string()), ui.name_str())
+            } else {
+                int.to_string()
+            }
         }
         (mir::ConstantKind::Val(ConstValue::Scalar(int), _), ty::Int(i)) => {
             let ty = tcx.lift(ct.ty()).unwrap();
             let size = tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size;
             let data = int.assert_bits(size);
             let sign_extended_data = size.sign_extend(data) as i128;
-            format!(
-                "{}{}",
-                format_integer_with_underscore_sep(&sign_extended_data.to_string()),
-                i.name_str()
-            )
+            if underscores_and_type {
+                format!(
+                    "{}{}",
+                    format_integer_with_underscore_sep(&sign_extended_data.to_string()),
+                    i.name_str()
+                )
+            } else {
+                sign_extended_data.to_string()
+            }
         }
         _ => ct.to_string(),
     }
index 6b7e67e2ce34269eca68fdf136a10016c10a4587..ed702f5c4a9cca78b5a5c423d0eecc809eecdd75 100644 (file)
@@ -46,7 +46,7 @@ fn fold_inner_recur(&mut self, kind: ItemKind) -> ItemKind {
                     let fields = fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
                     VariantItem(Variant::Tuple(fields))
                 }
-                Variant::CLike => VariantItem(Variant::CLike),
+                Variant::CLike(disr) => VariantItem(Variant::CLike(disr)),
             },
             ExternCrateItem { src: _ }
             | ImportItem(_)
index 6f49f00f93e5eb98abd62017ee1adaf0c7ca62c3..be10a5c101f7ffa3e5ad5c9aa028f40201a07d45 100644 (file)
@@ -349,8 +349,7 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>(
         let where_preds = comma_sep(where_predicates, false);
         let clause = if f.alternate() {
             if ending == Ending::Newline {
-                // add a space so stripping <br> tags and breaking spaces still renders properly
-                format!(" where{where_preds}, ")
+                format!(" where{where_preds},")
             } else {
                 format!(" where{where_preds}")
             }
@@ -364,20 +363,16 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>(
 
             if ending == Ending::Newline {
                 let mut clause = "&nbsp;".repeat(indent.saturating_sub(1));
-                // add a space so stripping <br> tags and breaking spaces still renders properly
-                write!(
-                    clause,
-                    " <span class=\"where fmt-newline\">where{where_preds},&nbsp;</span>"
-                )?;
+                write!(clause, "<span class=\"where fmt-newline\">where{where_preds},</span>")?;
                 clause
             } else {
                 // insert a <br> tag after a single space but before multiple spaces at the start
                 if indent == 0 {
-                    format!(" <br><span class=\"where\">where{where_preds}</span>")
+                    format!("<br><span class=\"where\">where{where_preds}</span>")
                 } else {
                     let mut clause = br_with_padding;
                     clause.truncate(clause.len() - 5 * "&nbsp;".len());
-                    write!(clause, " <span class=\"where\">where{where_preds}</span>")?;
+                    write!(clause, "<span class=\"where\">where{where_preds}</span>")?;
                     clause
                 }
             }
index eff34047e3c8fb93ac5bfa1b2f72351ecfc892cc..1e6f20d2b491c4bce959b1e3bde66d37160128e9 100644 (file)
@@ -1737,8 +1737,8 @@ pub(crate) fn render_impl_summary(
     // in documentation pages for trait with automatic implementations like "Send" and "Sync".
     aliases: &[String],
 ) {
-    let id =
-        cx.derive_id(get_id_for_impl(&i.inner_impl().for_, i.inner_impl().trait_.as_ref(), cx));
+    let inner_impl = i.inner_impl();
+    let id = cx.derive_id(get_id_for_impl(&inner_impl.for_, inner_impl.trait_.as_ref(), cx));
     let aliases = if aliases.is_empty() {
         String::new()
     } else {
@@ -1750,9 +1750,9 @@ pub(crate) fn render_impl_summary(
     write!(w, "<h3 class=\"code-header in-band\">");
 
     if let Some(use_absolute) = use_absolute {
-        write!(w, "{}", i.inner_impl().print(use_absolute, cx));
+        write!(w, "{}", inner_impl.print(use_absolute, cx));
         if show_def_docs {
-            for it in &i.inner_impl().items {
+            for it in &inner_impl.items {
                 if let clean::AssocTypeItem(ref tydef, ref _bounds) = *it.kind {
                     w.write_str("<span class=\"where fmt-newline\">  ");
                     assoc_type(
@@ -1770,11 +1770,11 @@ pub(crate) fn render_impl_summary(
             }
         }
     } else {
-        write!(w, "{}", i.inner_impl().print(false, cx));
+        write!(w, "{}", inner_impl.print(false, cx));
     }
     write!(w, "</h3>");
 
-    let is_trait = i.inner_impl().trait_.is_some();
+    let is_trait = inner_impl.trait_.is_some();
     if is_trait {
         if let Some(portability) = portability(&i.impl_item, Some(parent)) {
             write!(w, "<span class=\"item-info\">{}</span>", portability);
@@ -2367,9 +2367,9 @@ pub(crate) fn get_filtered_impls_for_reference<'a>(
     let Some(v) = shared.cache.impls.get(&def_id) else { return (Vec::new(), Vec::new(), Vec::new()) };
     // Since there is no "direct implementation" on the reference primitive type, we filter out
     // every implementation which isn't a trait implementation.
-    let traits: Vec<_> = v.iter().filter(|i| i.inner_impl().trait_.is_some()).collect();
+    let traits = v.iter().filter(|i| i.inner_impl().trait_.is_some());
     let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) =
-        traits.into_iter().partition(|t| t.inner_impl().kind.is_auto());
+        traits.partition(|t| t.inner_impl().kind.is_auto());
 
     let (blanket_impl, concrete): (Vec<&Impl>, _) =
         concrete.into_iter().partition(|t| t.inner_impl().kind.is_blanket());
index d63d4c2d159bab355547cfca026cbbb61e4b52a3..cfa4509428f1099eb49edb35ce2ced8e7e9ee080 100644 (file)
@@ -1203,7 +1203,8 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
                     let name = v.name.unwrap();
                     match *v.kind {
                         clean::VariantItem(ref var) => match var {
-                            clean::Variant::CLike => write!(w, "{}", name),
+                            // FIXME(#101337): Show discriminant
+                            clean::Variant::CLike(..) => write!(w, "{}", name),
                             clean::Variant::Tuple(ref s) => {
                                 write!(w, "{}(", name);
                                 print_tuple_struct_fields(w, cx, s);
index 34d590fb2448c553a7f3f271c1e1f81dd8538ea8..151ec2b28adc9860b47e71fbb48edd0f69d399a7 100644 (file)
@@ -166,25 +166,23 @@ fn visit_mod(&mut self, m: &'tcx Mod<'tcx>, span: Span, id: HirId) {
 
     fn visit_expr(&mut self, expr: &'tcx rustc_hir::Expr<'tcx>) {
         if let ExprKind::MethodCall(segment, ..) = expr.kind {
-            if let Some(hir_id) = segment.hir_id {
-                let hir = self.tcx.hir();
-                let body_id = hir.enclosing_body_owner(hir_id);
-                // FIXME: this is showing error messages for parts of the code that are not
-                // compiled (because of cfg)!
-                //
-                // See discussion in https://github.com/rust-lang/rust/issues/69426#issuecomment-1019412352
-                let typeck_results = self.tcx.typeck_body(
-                    hir.maybe_body_owned_by(body_id).expect("a body which isn't a body"),
+            let hir = self.tcx.hir();
+            let body_id = hir.enclosing_body_owner(segment.hir_id);
+            // FIXME: this is showing error messages for parts of the code that are not
+            // compiled (because of cfg)!
+            //
+            // See discussion in https://github.com/rust-lang/rust/issues/69426#issuecomment-1019412352
+            let typeck_results = self
+                .tcx
+                .typeck_body(hir.maybe_body_owned_by(body_id).expect("a body which isn't a body"));
+            if let Some(def_id) = typeck_results.type_dependent_def_id(expr.hir_id) {
+                self.matches.insert(
+                    segment.ident.span,
+                    match hir.span_if_local(def_id) {
+                        Some(span) => LinkFromSrc::Local(clean::Span::new(span)),
+                        None => LinkFromSrc::External(def_id),
+                    },
                 );
-                if let Some(def_id) = typeck_results.type_dependent_def_id(expr.hir_id) {
-                    self.matches.insert(
-                        segment.ident.span,
-                        match hir.span_if_local(def_id) {
-                            Some(span) => LinkFromSrc::Local(clean::Span::new(span)),
-                            None => LinkFromSrc::External(def_id),
-                        },
-                    );
-                }
             }
         } else if self.handle_macro(expr.span) {
             // We don't want to go deeper into the macro.
index f9abb46207d748e957b70261d8fa2c4451425505..fc4d46fe6b6f191fbe54d6391c17837a643ca497 100644 (file)
@@ -312,7 +312,7 @@ fn collect(path: &Path, krate: &str) -> io::Result<(Vec<String>, Vec<String>)> {
                 if line.starts_with(&prefix) {
                     continue;
                 }
-                if line.ends_with(",") {
+                if line.ends_with(',') {
                     ret.push(line[..line.len() - 1].to_string());
                 } else {
                     // No comma (it's the case for the last added crate line)
index c117e3ac40dab57e22db93ab76b4e1046ce43edb..3502d97d470fecb56c39d3012db24cfb62ea1bb2 100644 (file)
@@ -207,7 +207,6 @@ h1, h2, h3, h4, h5, h6,
 a.source,
 .search-input,
 .search-results .result-name,
-.content table td:first-child > a,
 .item-left > a,
 .out-of-band,
 span.since,
@@ -216,7 +215,6 @@ details.rustdoc-toggle > summary::before,
 div.impl-items > div:not(.docblock):not(.item-info),
 .content ul.crate a.crate,
 a.srclink,
-#main-content > .since,
 #help-button > button,
 details.rustdoc-toggle.top-doc > summary,
 details.rustdoc-toggle.top-doc > summary::before,
@@ -759,14 +757,6 @@ pre, .rustdoc.source .example-wrap {
        margin-bottom: 15px;
 }
 
-.content .docblock > .impl-items {
-       margin-left: 20px;
-       margin-top: -34px;
-}
-.content .docblock >.impl-items table td {
-       padding: 0;
-}
-
 .item-info {
        display: block;
 }
@@ -788,18 +778,6 @@ pre, .rustdoc.source .example-wrap {
        margin-bottom: .6em;
 }
 
-.content .impl-items > .item-info {
-       margin-left: 40px;
-}
-
-.methods > .item-info, .content .impl-items > .item-info {
-       margin-top: -8px;
-}
-
-.impl-items {
-       flex-basis: 100%;
-}
-
 #main-content > .item-info {
        margin-top: 0;
        margin-left: 0;
@@ -997,6 +975,9 @@ so that we can apply CSS-filters to change the arrow color in themes */
        width: 100%;
        background-color: var(--button-background-color);
 }
+.search-input:focus {
+       border-color: var(--search-input-focused-border-color);
+}
 
 .search-results {
        display: none;
@@ -1177,6 +1158,12 @@ so that we can apply CSS-filters to change the arrow color in themes */
        float: right;
 }
 
+.rightside:not(a),
+.out-of-band {
+       color: var(--right-side-color);
+}
+
+
 .impl-items .srclink, .impl .srclink, .methods .srclink {
        /* Override header settings otherwise it's too bold */
        font-weight: normal;
@@ -1215,6 +1202,7 @@ a.test-arrow:hover {
 
 .code-attribute {
        font-weight: 300;
+       color: var(--code-attribute-color);
 }
 
 .item-spacer {
@@ -1251,12 +1239,6 @@ h3.variant {
        margin-left: 24px;
 }
 
-.toggle-label {
-       display: inline-block;
-       margin-left: 4px;
-       margin-top: 3px;
-}
-
 :target > code, :target > .code-header {
        opacity: 1;
 }
@@ -1494,6 +1476,16 @@ pre.rust {
        background-color: var(--button-background-color);
 }
 
+#copy-path {
+       color: var(--copy-path-button-color);
+}
+#copy-path > img {
+       filter: var(--copy-path-img-filter);
+}
+#copy-path:hover > img {
+       filter: var(--copy-path-img-hover-filter);
+}
+
 @keyframes rotating {
        from {
                transform: rotate(0deg);
@@ -1617,6 +1609,12 @@ details.rustdoc-toggle > summary::before {
        opacity: .5;
 }
 
+details.rustdoc-toggle > summary.hideme > span,
+details.rustdoc-toggle > summary::before,
+.more-examples-toggle summary, .more-examples-toggle .hide-more {
+       color: var(--toggles-color);
+}
+
 /* Screen readers see the text version at the end the line.
        Visual readers see the icon at the start of the line, but small and transparent. */
 details.rustdoc-toggle > summary::after {
@@ -1885,10 +1883,6 @@ in storage.js plus the media query with (min-width: 701px)
                background-color: var(--sidebar-background-color);
        }
 
-       .source nav:not(.sidebar).sub {
-               margin-left: 32px;
-       }
-
        .content {
                margin-left: 0px;
        }
@@ -2025,6 +2019,11 @@ in storage.js plus the media query with (min-width: 701px)
        #main-content > div > details.rustdoc-toggle > summary::before {
                left: -11px;
        }
+
+       /* Align summary-nested and unnested item-info gizmos. */
+       .content .impl-items > .item-info {
+               margin-left: 34px;
+       }
 }
 
 @media print {
index e301a793282eb56b9ff73a8c227be000bb976db8..be359a8e72d25d250631a2f651dfb343454b9f04 100644 (file)
@@ -16,6 +16,13 @@ Original by Dempfi (https://github.com/dempfi/ayu)
        --headings-border-bottom-color: #5c6773;
        --border-color: #5c6773;
        --button-background-color: #141920;
+       --right-side-color: grey;
+       --code-attribute-color: #999;
+       --toggles-color: #999;
+       --search-input-focused-border-color: #5c6773; /* Same as `--border-color`. */
+       --copy-path-button-color: #fff;
+       --copy-path-img-filter: invert(70%);
+       --copy-path-img-hover-filter: invert(100%);
 }
 
 .slider {
@@ -158,11 +165,6 @@ body.source .example-wrap pre.rust a {
        background: #333;
 }
 
-details.rustdoc-toggle > summary.hideme > span,
-details.rustdoc-toggle > summary::before {
-       color: #999;
-}
-
 details.rustdoc-toggle > summary::before {
        filter: invert(100%);
 }
@@ -197,11 +199,6 @@ details.rustdoc-toggle > summary::before {
        background: none;
 }
 
-.rightside:not(a),
-.out-of-band {
-       color: grey;
-}
-
 .result-name .primitive > i, .result-name .keyword > i {
        color: #788797;
 }
@@ -242,11 +239,6 @@ a.test-arrow:hover {
        color: #c5c5c5;
 }
 
-.toggle-label,
-.code-attribute {
-       color: #999;
-}
-
 :target {
        background: rgba(255, 236, 164, 0.06);
        border-right: 3px solid rgba(255, 180, 76, 0.85);
@@ -342,7 +334,6 @@ individually rather than as a group) */
 /* FIXME: these rules should be at the bottom of the file but currently must be
 above the `@media (max-width: 700px)` rules due to a bug in the css checker */
 /* see https://github.com/rust-lang/rust/pull/71237#issuecomment-618170143 */
-.search-input:focus {}
 .content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,
 .block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro {}
 .content span.struct,.content a.struct,.block a.current.struct {}
@@ -429,16 +420,6 @@ kbd {
        filter: invert(100);
 }
 
-#copy-path {
-       color: #fff;
-}
-#copy-path > img {
-       filter: invert(70%);
-}
-#copy-path:hover > img {
-       filter: invert(100%);
-}
-
 #settings-menu > a:hover, #settings-menu > a:focus,
 #help-button > button:hover, #help-button > button:focus {
        border-color: #e0e0e0;
@@ -472,9 +453,6 @@ kbd {
        border-color: white;
        color: white;
 }
-.more-examples-toggle summary, .more-examples-toggle .hide-more {
-       color: #999;
-}
 .scraped-example .example-wrap .rust span.highlight {
        background: rgb(91, 59, 1);
 }
index d5cd47c3e19d5f00c5c4245c7bd1195e4ea937a3..f633abe94e5af075b6b14973faadc2b88ab71623 100644 (file)
        --headings-border-bottom-color: #d2d2d2;
        --border-color: #e0e0e0;
        --button-background-color: #f0f0f0;
+       --right-side-color: grey;
+       --code-attribute-color: #999;
+       --toggles-color: #999;
+       --search-input-focused-border-color: #008dfd;
+       --copy-path-button-color: #999;
+       --copy-path-img-filter: invert(50%);
+       --copy-path-img-hover-filter: invert(65%);
 }
 
 .slider {
@@ -129,18 +136,12 @@ body.source .example-wrap pre.rust a {
        background: #333;
 }
 
-details.rustdoc-toggle > summary.hideme > span,
-details.rustdoc-toggle > summary::before {
-       color: #999;
-}
-
 details.rustdoc-toggle > summary::before {
        filter: invert(100%);
 }
 
 .search-input {
        color: #111;
-       border-color: #f0f0f0;
 }
 
 #crate-search-div::after {
@@ -154,10 +155,6 @@ details.rustdoc-toggle > summary::before {
        filter: invert(69%) sepia(60%) saturate(6613%) hue-rotate(184deg) brightness(100%) contrast(91%);
 }
 
-.search-input:focus {
-       border-color: #008dfd;
-}
-
 .stab { background: #314559; }
 
 .stab.portability > code {
@@ -165,11 +162,6 @@ details.rustdoc-toggle > summary::before {
        background: none;
 }
 
-.rightside:not(a),
-.out-of-band {
-       color: grey;
-}
-
 .line-numbers :target { background-color: transparent; }
 
 /* Code highlighting */
@@ -197,11 +189,6 @@ a.test-arrow:hover{
        background-color: #4e8bca;
 }
 
-.toggle-label,
-.code-attribute {
-       color: #999;
-}
-
 :target {
        background-color: #494a3d;
        border-right: 3px solid #bb7410;
@@ -302,16 +289,6 @@ kbd {
        border-color: #ffb900;
 }
 
-#copy-path {
-       color: #999;
-}
-#copy-path > img {
-       filter: invert(50%);
-}
-#copy-path:hover > img {
-       filter: invert(65%);
-}
-
 .search-results .result-name span.alias {
        color: #fff;
 }
@@ -335,9 +312,6 @@ kbd {
        border-color: white;
        color: white;
 }
-.more-examples-toggle summary, .more-examples-toggle .hide-more {
-       color: #999;
-}
 .scraped-example .example-wrap .rust span.highlight {
        background: rgb(91, 59, 1);
 }
index cff70268144f35852468925b80424e7c1fdcc47d..875bb79302560f4b1754ab6a5c78470123abf6cb 100644 (file)
        --headings-border-bottom-color: #ddd;
        --border-color: #e0e0e0;
        --button-background-color: #fff;
+       --right-side-color: grey;
+       --code-attribute-color: #999;
+       --toggles-color: #999;
+       --search-input-focused-border-color: #66afe9;
+       --copy-path-button-color: #999;
+       --copy-path-img-filter: invert(50%);
+       --copy-path-img-hover-filter: invert(35%);
 }
 
 .slider {
@@ -125,11 +132,6 @@ body.source .example-wrap pre.rust a {
        background: #eee;
 }
 
-details.rustdoc-toggle > summary.hideme > span,
-details.rustdoc-toggle > summary::before {
-       color: #999;
-}
-
 #crate-search-div::after {
        /* match border-color; uses https://codepen.io/sosuke/pen/Pjoqqp */
        filter: invert(100%) sepia(0%) saturate(4223%) hue-rotate(289deg) brightness(114%) contrast(76%);
@@ -141,18 +143,9 @@ details.rustdoc-toggle > summary::before {
        filter: invert(44%) sepia(18%) saturate(23%) hue-rotate(317deg) brightness(96%) contrast(93%);
 }
 
-.search-input:focus {
-       border-color: #66afe9;
-}
-
 .stab { background: #FFF5D6; border-color: #FFC600; }
 .stab.portability > code { background: none; }
 
-.rightside:not(a),
-.out-of-band {
-       color: grey;
-}
-
 .line-numbers :target { background-color: transparent; }
 
 /* Code highlighting */
@@ -182,11 +175,6 @@ a.test-arrow:hover{
        background-color: #4e8bca;
 }
 
-.toggle-label,
-.code-attribute {
-       color: #999;
-}
-
 :target {
        background: #FDFFD3;
        border-right: 3px solid #AD7C37;
@@ -282,16 +270,6 @@ kbd {
        border-color: #717171;
 }
 
-#copy-path {
-       color: #999;
-}
-#copy-path > img {
-       filter: invert(50%);
-}
-#copy-path:hover > img {
-       filter: invert(35%);
-}
-
 .search-results .result-name span.alias {
        color: #000;
 }
@@ -314,9 +292,6 @@ kbd {
        border-color: black;
        color: black;
 }
-.more-examples-toggle summary, .more-examples-toggle .hide-more {
-       color: #999;
-}
 .scraped-example .example-wrap .rust span.highlight {
        background: #fcffd6;
 }
index 20b9eb1c27e92cb046a2f55757e3c64e3e99ffd2..4d009316730067a246ed86d1f062c8bb497c6bf3 100644 (file)
@@ -486,7 +486,7 @@ fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self {
             },
             QPath(box clean::QPathData { assoc, self_type, trait_, .. }) => Type::QualifiedPath {
                 name: assoc.name.to_string(),
-                args: Box::new(assoc.args.clone().into_tcx(tcx)),
+                args: Box::new(assoc.args.into_tcx(tcx)),
                 self_type: Box::new(self_type.into_tcx(tcx)),
                 trait_: trait_.into_tcx(tcx),
             },
@@ -662,7 +662,7 @@ impl FromWithTcx<clean::Variant> for Variant {
     fn from_tcx(variant: clean::Variant, tcx: TyCtxt<'_>) -> Self {
         use clean::Variant::*;
         match variant {
-            CLike => Variant::Plain,
+            CLike(disr) => Variant::Plain(disr.map(|disr| disr.into_tcx(tcx))),
             Tuple(fields) => Variant::Tuple(
                 fields
                     .into_iter()
@@ -678,6 +678,18 @@ fn from_tcx(variant: clean::Variant, tcx: TyCtxt<'_>) -> Self {
     }
 }
 
+impl FromWithTcx<clean::Discriminant> for Discriminant {
+    fn from_tcx(disr: clean::Discriminant, tcx: TyCtxt<'_>) -> Self {
+        Discriminant {
+            // expr is only none if going throught the inlineing path, which gets
+            // `rustc_middle` types, not `rustc_hir`, but because JSON never inlines
+            // the expr is always some.
+            expr: disr.expr(tcx).unwrap(),
+            value: disr.value(tcx),
+        }
+    }
+}
+
 impl FromWithTcx<clean::Import> for Import {
     fn from_tcx(import: clean::Import, tcx: TyCtxt<'_>) -> Self {
         use clean::ImportKind::*;
index 39d3b43cf32e2aa1c5e5d083a1c04b83fb709a3a..c27f0ce18c1414d027453b4e8d2799105c980cfa 100644 (file)
@@ -750,7 +750,7 @@ fn resolve_associated_trait_item<'a>(
 ///
 /// This is just a wrapper around [`TyCtxt::impl_item_implementor_ids()`] and
 /// [`TyCtxt::associated_item()`] (with some helpful logging added).
-#[instrument(level = "debug", skip(tcx))]
+#[instrument(level = "debug", skip(tcx), ret)]
 fn trait_assoc_to_impl_assoc_item<'tcx>(
     tcx: TyCtxt<'tcx>,
     impl_id: DefId,
@@ -760,9 +760,7 @@ fn trait_assoc_to_impl_assoc_item<'tcx>(
     debug!(?trait_to_impl_assoc_map);
     let impl_assoc_id = *trait_to_impl_assoc_map.get(&trait_assoc_id)?;
     debug!(?impl_assoc_id);
-    let impl_assoc = tcx.associated_item(impl_assoc_id);
-    debug!(?impl_assoc);
-    Some(impl_assoc)
+    Some(tcx.associated_item(impl_assoc_id))
 }
 
 /// Given a type, return all trait impls in scope in `module` for that type.
index 2b12d118bca0e3968e0598e68a2a7a008fcb2599..765f7c61bd392dc433d5e2e5aa2c55ea95828992 100644 (file)
@@ -3,7 +3,7 @@
 
 use crate::clean::cfg::Cfg;
 use crate::clean::inline::{load_attrs, merge_attrs};
-use crate::clean::{Crate, Item};
+use crate::clean::{Crate, Item, ItemKind};
 use crate::core::DocContext;
 use crate::fold::DocFolder;
 use crate::passes::Pass;
@@ -26,30 +26,50 @@ struct CfgPropagator<'a, 'tcx> {
     cx: &'a mut DocContext<'tcx>,
 }
 
-impl<'a, 'tcx> DocFolder for CfgPropagator<'a, 'tcx> {
-    fn fold_item(&mut self, mut item: Item) -> Option<Item> {
-        let old_parent_cfg = self.parent_cfg.clone();
+impl<'a, 'tcx> CfgPropagator<'a, 'tcx> {
+    // Some items need to merge their attributes with their parents' otherwise a few of them
+    // (mostly `cfg` ones) will be missing.
+    fn merge_with_parent_attributes(&mut self, item: &mut Item) {
+        let check_parent = match &*item.kind {
+            // impl blocks can be in different modules with different cfg and we need to get them
+            // as well.
+            ItemKind::ImplItem(_) => false,
+            kind if kind.is_non_assoc() => true,
+            _ => return,
+        };
 
-        if item.kind.is_non_assoc() &&
-            let Some(def_id) = item.item_id.as_def_id().and_then(|def_id| def_id.as_local()) {
-            let hir = self.cx.tcx.hir();
-            let hir_id = hir.local_def_id_to_hir_id(def_id);
+        let Some(def_id) = item.item_id.as_def_id().and_then(|def_id| def_id.as_local())
+            else { return };
+
+        let hir = self.cx.tcx.hir();
+        let hir_id = hir.local_def_id_to_hir_id(def_id);
+
+        if check_parent {
             let expected_parent = hir.get_parent_item(hir_id);
+            // If parents are different, it means that `item` is a reexport and we need
+            // to compute the actual `cfg` by iterating through its "real" parents.
+            if self.parent == Some(expected_parent) {
+                return;
+            }
+        }
 
-            // If parents are different, it means that `item` is a reexport and we need to compute
-            // the actual `cfg` by iterating through its "real" parents.
-            if self.parent != Some(expected_parent) {
-                let mut attrs = Vec::new();
-                for (parent_hir_id, _) in hir.parent_iter(hir_id) {
-                    if let Some(def_id) = hir.opt_local_def_id(parent_hir_id) {
-                        attrs.extend_from_slice(load_attrs(self.cx, def_id.to_def_id()));
-                    }
-                }
-                let (_, cfg) =
-                    merge_attrs(self.cx, None, item.attrs.other_attrs.as_slice(), Some(&attrs));
-                item.cfg = cfg;
+        let mut attrs = Vec::new();
+        for (parent_hir_id, _) in hir.parent_iter(hir_id) {
+            if let Some(def_id) = hir.opt_local_def_id(parent_hir_id) {
+                attrs.extend_from_slice(load_attrs(self.cx, def_id.to_def_id()));
             }
         }
+        let (_, cfg) = merge_attrs(self.cx, None, item.attrs.other_attrs.as_slice(), Some(&attrs));
+        item.cfg = cfg;
+    }
+}
+
+impl<'a, 'tcx> DocFolder for CfgPropagator<'a, 'tcx> {
+    fn fold_item(&mut self, mut item: Item) -> Option<Item> {
+        let old_parent_cfg = self.parent_cfg.clone();
+
+        self.merge_with_parent_attributes(&mut item);
+
         let new_cfg = match (self.parent_cfg.take(), item.cfg.take()) {
             (None, None) => None,
             (Some(rc), None) | (None, Some(rc)) => Some(rc),
index 83ed3752a824cd541aa608be7c46fb97b1d234c3..a9d768f0149d6280d561806d47bb3d038f50e414 100644 (file)
@@ -91,7 +91,7 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
             clean::ExternCrateItem { .. } => {}
             clean::ImportItem(ref imp) => {
                 // Because json doesn't inline imports from private modules, we need to mark
-                // the imported item as retained so it's impls won't be stripped.i
+                // the imported item as retained so it's impls won't be stripped.
                 //
                 // FIXME: Is it necessary to check for json output here: See
                 // https://github.com/rust-lang/rust/pull/100325#discussion_r941495215
index 0d96840250332b5cb77c05c56334e2be8bdaa56a..ca86ac89e8583a7b16a3b52c4e34a7438c94901d 100644 (file)
@@ -159,7 +159,7 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
                     return;
                 }
             }
-            hir::ExprKind::MethodCall(path, _, call_span) => {
+            hir::ExprKind::MethodCall(path, _, _, call_span) => {
                 let types = tcx.typeck(ex.hir_id.owner);
                 let Some(def_id) = types.type_dependent_def_id(ex.hir_id) else {
                     trace!("type_dependent_def_id({}) = None", ex.hir_id);
index 0bb41977c97cac4d2bab4b8f61c02ca82898a663..c40274394f344ee976a5169b3ed89f3fa43067d2 100644 (file)
@@ -20,7 +20,7 @@ fn visit_inner_recur(&mut self, kind: &ItemKind) {
             VariantItem(i) => match i {
                 Variant::Struct(j) => j.fields.iter().for_each(|x| self.visit_item(x)),
                 Variant::Tuple(fields) => fields.iter().for_each(|x| self.visit_item(x)),
-                Variant::CLike => {}
+                Variant::CLike(_) => {}
             },
             ExternCrateItem { src: _ }
             | ImportItem(_)
index e3be3f64ecac101d14ceda759ba078ad0aaf3747..670e5f673acb736acbfce65e0ffe2c8cd115b93f 160000 (submodule)
@@ -1 +1 @@
-Subproject commit e3be3f64ecac101d14ceda759ba078ad0aaf3747
+Subproject commit 670e5f673acb736acbfce65e0ffe2c8cd115b93f
index 7dcad66b1f992b8df236aa0c59e23d7f275f622c..d25f68b3743d62d91c17617e53cd08a871d7c13d 100644 (file)
@@ -9,7 +9,7 @@
 use serde::{Deserialize, Serialize};
 
 /// rustdoc format-version.
-pub const FORMAT_VERSION: u32 = 18;
+pub const FORMAT_VERSION: u32 = 19;
 
 /// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information
 /// about the language items in the local crate, as well as info about external items to allow
@@ -308,11 +308,28 @@ pub struct Enum {
 #[serde(rename_all = "snake_case")]
 #[serde(tag = "variant_kind", content = "variant_inner")]
 pub enum Variant {
-    Plain,
+    Plain(Option<Discriminant>),
     Tuple(Vec<Type>),
     Struct(Vec<Id>),
 }
 
+#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
+pub struct Discriminant {
+    /// The expression that produced the discriminant.
+    ///
+    /// Unlike `value`, this preserves the original formatting (eg suffixes,
+    /// hexadecimal, and underscores), making it unsuitable to be machine
+    /// interpreted.
+    ///
+    /// In some cases, when the value is to complex, this may be `"{ _ }"`.
+    /// When this occurs is unstable, and may change without notice.
+    pub expr: String,
+    /// The numerical value of the discriminant. Stored as a string due to
+    /// JSON's poor support for large integers, and the fact that it would need
+    /// to store from [`i128::MIN`] to [`u128::MAX`].
+    pub value: String,
+}
+
 #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
 #[serde(rename_all = "snake_case")]
 pub enum StructType {
index 53358b183cbf527ad6d6476088aa71fc6e7ed6ec..5ff7b19d8945e635434250ddce7012c63f42e947 100644 (file)
@@ -9,6 +9,7 @@ fn c<T, const N: std::num::NonZeroUsize>()
     use std::convert::TryFrom;
     <[T; N.get()]>::try_from(())
     //~^ error: the trait bound
+    //~| error: the trait bound
     //~| error: mismatched types
 }
 
index ca298e9211d4864400aa0116975c4c86ad5c9f04..a6a56f3a95d18b302869fac8672cd620e0b68829 100644 (file)
@@ -1,4 +1,6 @@
-// compile-flags: -Z mir-opt-level=4 -Zunsound-mir-opts
+// unit-test: EarlyOtherwiseBranch
+
+// FIXME: This test was broken by the derefer change.
 
 // example from #68867
 type CSSFloat = f32;
@@ -11,7 +13,6 @@ pub enum ViewportPercentageLength {
 }
 
 // EMIT_MIR early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff
-// EMIT_MIR early_otherwise_branch_68867.try_sum EarlyOtherwiseBranch.before SimplifyConstCondition-final.after
 #[no_mangle]
 pub extern "C" fn try_sum(
     x: &ViewportPercentageLength,
diff --git a/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.before-SimplifyConstCondition-final.after.diff b/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.before-SimplifyConstCondition-final.after.diff
deleted file mode 100644 (file)
index 8b37fb7..0000000
+++ /dev/null
@@ -1,322 +0,0 @@
-- // MIR for `try_sum` before EarlyOtherwiseBranch
-+ // MIR for `try_sum` after SimplifyConstCondition-final
-  
-  fn try_sum(_1: &ViewportPercentageLength, _2: &ViewportPercentageLength) -> Result<ViewportPercentageLength, ()> {
-      debug x => _1;                       // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+1:5: +1:6
-      debug other => _2;                   // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+2:5: +2:10
-      let mut _0: std::result::Result<ViewportPercentageLength, ()>; // return place in scope 0 at $DIR/early_otherwise_branch_68867.rs:+3:6: +3:42
-      let mut _3: ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +11:6
-      let mut _4: (&ViewportPercentageLength, &ViewportPercentageLength); // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-      let mut _5: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:15: +5:16
-      let mut _6: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:18: +5:23
-      let mut _7: isize;                   // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:21: +6:30
-      let mut _8: isize;                   // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:21: +7:30
-      let mut _9: isize;                   // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:23: +8:34
-      let mut _10: isize;                  // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:23: +9:34
-      let mut _11: isize;                  // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:11: +6:18
-      let _12: f32;                        // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:14: +6:17
-      let _13: f32;                        // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:24: +6:29
-      let mut _14: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:38: +6:49
-      let mut _15: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:38: +6:41
-      let mut _16: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:44: +6:49
-      let _17: f32;                        // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:14: +7:17
-      let _18: f32;                        // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:24: +7:29
-      let mut _19: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:38: +7:49
-      let mut _20: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:38: +7:41
-      let mut _21: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:44: +7:49
-      let _22: f32;                        // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:16: +8:19
-      let _23: f32;                        // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:28: +8:33
-      let mut _24: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:44: +8:55
-      let mut _25: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:44: +8:47
-      let mut _26: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:50: +8:55
-      let _27: f32;                        // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:16: +9:19
-      let _28: f32;                        // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:28: +9:33
-      let mut _29: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:44: +9:55
-      let mut _30: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:44: +9:47
-      let mut _31: f32;                    // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:50: +9:55
-      let mut _32: !;                      // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:14: +10:28
-      let mut _33: ();                     // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:25: +10:27
-      let mut _34: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-      let mut _35: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-      let mut _36: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-      let mut _37: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-      let mut _38: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-      let mut _39: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-      let mut _40: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-      let mut _41: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-      let mut _42: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-      let mut _43: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-      let mut _44: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-      let mut _45: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-      let mut _46: &ViewportPercentageLength; // in scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-      scope 1 {
--         debug one => _12;                // in scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:14: +6:17
--         debug other => _13;              // in scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:24: +6:29
-+         debug one => _15;                // in scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:14: +6:17
-+         debug other => _16;              // in scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:24: +6:29
-      }
-      scope 2 {
--         debug one => _17;                // in scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:14: +7:17
--         debug other => _18;              // in scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:24: +7:29
-+         debug one => _20;                // in scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:14: +7:17
-+         debug other => _21;              // in scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:24: +7:29
-      }
-      scope 3 {
--         debug one => _22;                // in scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:16: +8:19
--         debug other => _23;              // in scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:28: +8:33
-+         debug one => _25;                // in scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:16: +8:19
-+         debug other => _26;              // in scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:28: +8:33
-      }
-      scope 4 {
--         debug one => _27;                // in scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:16: +9:19
--         debug other => _28;              // in scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:28: +9:33
-+         debug one => _30;                // in scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:16: +9:19
-+         debug other => _31;              // in scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:28: +9:33
-      }
-  
-      bb0: {
--         StorageLive(_3);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +11:6
--         StorageLive(_4);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
--         StorageLive(_5);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:15: +5:16
--         _5 = _1;                         // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:15: +5:16
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +11:6
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:15: +5:16
-+         (_4.0: &ViewportPercentageLength) = _1; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:15: +5:16
-          StorageLive(_6);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:18: +5:23
-          _6 = _2;                         // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:18: +5:23
-          Deinit(_4);                      // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
--         (_4.0: &ViewportPercentageLength) = move _5; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-          (_4.1: &ViewportPercentageLength) = move _6; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-          StorageDead(_6);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:23: +5:24
--         StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:23: +5:24
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:23: +5:24
-          _34 = deref_copy (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-          _11 = discriminant((*_34));      // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-          switchInt(move _11) -> [0_isize: bb1, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb11]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
-      }
-  
-      bb1: {
-          _35 = deref_copy (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-          _7 = discriminant((*_35));       // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-          switchInt(move _7) -> [0_isize: bb6, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
-      }
-  
-      bb2: {
-          StorageLive(_33);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:25: +10:27
-          nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:25: +10:27
-          Deinit(_0);                      // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28
-          nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28
-          discriminant(_0) = 1;            // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28
-          StorageDead(_33);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:27: +10:28
--         StorageDead(_3);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:+11:6: +11:7
--         StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:1: +12:2
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:+11:6: +11:7
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:1: +12:2
-          return;                          // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:2: +12:2
-      }
-  
-      bb3: {
-          _36 = deref_copy (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-          _8 = discriminant((*_36));       // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-          switchInt(move _8) -> [1_isize: bb7, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
-      }
-  
-      bb4: {
-          _37 = deref_copy (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-          _9 = discriminant((*_37));       // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-          switchInt(move _9) -> [2_isize: bb8, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
-      }
-  
-      bb5: {
-          _38 = deref_copy (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-          _10 = discriminant((*_38));      // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-          switchInt(move _10) -> [3_isize: bb9, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
-      }
-  
-      bb6: {
--         StorageLive(_12);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:14: +6:17
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:14: +6:17
-          _39 = deref_copy (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:14: +6:17
--         _12 = (((*_39) as Vw).0: f32);   // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:14: +6:17
--         StorageLive(_13);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:24: +6:29
-+         _15 = (((*_39) as Vw).0: f32);   // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:14: +6:17
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:24: +6:29
-          _40 = deref_copy (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:24: +6:29
--         _13 = (((*_40) as Vw).0: f32);   // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:24: +6:29
--         StorageLive(_14);                // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:38: +6:49
--         StorageLive(_15);                // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:38: +6:41
--         _15 = _12;                       // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:38: +6:41
--         StorageLive(_16);                // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:44: +6:49
--         _16 = _13;                       // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:44: +6:49
--         _14 = Add(move _15, move _16);   // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:38: +6:49
--         StorageDead(_16);                // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:48: +6:49
--         StorageDead(_15);                // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:48: +6:49
--         Deinit(_3);                      // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:35: +6:50
--         ((_3 as Vw).0: f32) = move _14;  // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:35: +6:50
--         discriminant(_3) = 0;            // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:35: +6:50
--         StorageDead(_14);                // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:49: +6:50
--         StorageDead(_13);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:49: +6:50
--         StorageDead(_12);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:49: +6:50
-+         _16 = (((*_40) as Vw).0: f32);   // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:24: +6:29
-+         nop;                             // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:38: +6:49
-+         nop;                             // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:38: +6:41
-+         nop;                             // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:38: +6:41
-+         nop;                             // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:44: +6:49
-+         nop;                             // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:44: +6:49
-+         ((((_0 as Ok).0: ViewportPercentageLength) as Vw).0: f32) = Add(move _15, move _16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:38: +6:49
-+         nop;                             // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:48: +6:49
-+         nop;                             // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:48: +6:49
-+         Deinit(((_0 as Ok).0: ViewportPercentageLength)); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:35: +6:50
-+         nop;                             // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:35: +6:50
-+         discriminant(((_0 as Ok).0: ViewportPercentageLength)) = 0; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:35: +6:50
-+         nop;                             // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:49: +6:50
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:49: +6:50
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:49: +6:50
-          goto -> bb10;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:49: +6:50
-      }
-  
-      bb7: {
--         StorageLive(_17);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:14: +7:17
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:14: +7:17
-          _41 = deref_copy (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:14: +7:17
--         _17 = (((*_41) as Vh).0: f32);   // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:14: +7:17
--         StorageLive(_18);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:24: +7:29
-+         _20 = (((*_41) as Vh).0: f32);   // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:14: +7:17
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:24: +7:29
-          _42 = deref_copy (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:24: +7:29
--         _18 = (((*_42) as Vh).0: f32);   // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:24: +7:29
--         StorageLive(_19);                // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:38: +7:49
--         StorageLive(_20);                // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:38: +7:41
--         _20 = _17;                       // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:38: +7:41
--         StorageLive(_21);                // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:44: +7:49
--         _21 = _18;                       // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:44: +7:49
--         _19 = Add(move _20, move _21);   // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:38: +7:49
--         StorageDead(_21);                // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:48: +7:49
--         StorageDead(_20);                // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:48: +7:49
--         Deinit(_3);                      // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:35: +7:50
--         ((_3 as Vh).0: f32) = move _19;  // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:35: +7:50
--         discriminant(_3) = 1;            // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:35: +7:50
--         StorageDead(_19);                // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:49: +7:50
--         StorageDead(_18);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:49: +7:50
--         StorageDead(_17);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:49: +7:50
-+         _21 = (((*_42) as Vh).0: f32);   // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:24: +7:29
-+         nop;                             // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:38: +7:49
-+         nop;                             // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:38: +7:41
-+         nop;                             // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:38: +7:41
-+         nop;                             // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:44: +7:49
-+         nop;                             // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:44: +7:49
-+         ((((_0 as Ok).0: ViewportPercentageLength) as Vh).0: f32) = Add(move _20, move _21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:38: +7:49
-+         nop;                             // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:48: +7:49
-+         nop;                             // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:48: +7:49
-+         Deinit(((_0 as Ok).0: ViewportPercentageLength)); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:35: +7:50
-+         nop;                             // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:35: +7:50
-+         discriminant(((_0 as Ok).0: ViewportPercentageLength)) = 1; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:35: +7:50
-+         nop;                             // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:49: +7:50
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:49: +7:50
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:49: +7:50
-          goto -> bb10;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:49: +7:50
-      }
-  
-      bb8: {
--         StorageLive(_22);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:16: +8:19
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:16: +8:19
-          _43 = deref_copy (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:16: +8:19
--         _22 = (((*_43) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:16: +8:19
--         StorageLive(_23);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:28: +8:33
-+         _25 = (((*_43) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:16: +8:19
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:28: +8:33
-          _44 = deref_copy (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:28: +8:33
--         _23 = (((*_44) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:28: +8:33
--         StorageLive(_24);                // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:44: +8:55
--         StorageLive(_25);                // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:44: +8:47
--         _25 = _22;                       // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:44: +8:47
--         StorageLive(_26);                // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:50: +8:55
--         _26 = _23;                       // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:50: +8:55
--         _24 = Add(move _25, move _26);   // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:44: +8:55
--         StorageDead(_26);                // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:54: +8:55
--         StorageDead(_25);                // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:54: +8:55
--         Deinit(_3);                      // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:39: +8:56
--         ((_3 as Vmin).0: f32) = move _24; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:39: +8:56
--         discriminant(_3) = 2;            // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:39: +8:56
--         StorageDead(_24);                // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:55: +8:56
--         StorageDead(_23);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:55: +8:56
--         StorageDead(_22);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:55: +8:56
-+         _26 = (((*_44) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:28: +8:33
-+         nop;                             // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:44: +8:55
-+         nop;                             // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:44: +8:47
-+         nop;                             // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:44: +8:47
-+         nop;                             // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:50: +8:55
-+         nop;                             // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:50: +8:55
-+         ((((_0 as Ok).0: ViewportPercentageLength) as Vmin).0: f32) = Add(move _25, move _26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:44: +8:55
-+         nop;                             // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:54: +8:55
-+         nop;                             // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:54: +8:55
-+         Deinit(((_0 as Ok).0: ViewportPercentageLength)); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:39: +8:56
-+         nop;                             // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:39: +8:56
-+         discriminant(((_0 as Ok).0: ViewportPercentageLength)) = 2; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:39: +8:56
-+         nop;                             // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:55: +8:56
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:55: +8:56
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:55: +8:56
-          goto -> bb10;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:55: +8:56
-      }
-  
-      bb9: {
--         StorageLive(_27);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:16: +9:19
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:16: +9:19
-          _45 = deref_copy (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:16: +9:19
--         _27 = (((*_45) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:16: +9:19
--         StorageLive(_28);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:28: +9:33
-+         _30 = (((*_45) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:16: +9:19
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:28: +9:33
-          _46 = deref_copy (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:28: +9:33
--         _28 = (((*_46) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:28: +9:33
--         StorageLive(_29);                // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:44: +9:55
--         StorageLive(_30);                // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:44: +9:47
--         _30 = _27;                       // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:44: +9:47
--         StorageLive(_31);                // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:50: +9:55
--         _31 = _28;                       // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:50: +9:55
--         _29 = Add(move _30, move _31);   // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:44: +9:55
--         StorageDead(_31);                // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:54: +9:55
--         StorageDead(_30);                // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:54: +9:55
--         Deinit(_3);                      // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:39: +9:56
--         ((_3 as Vmax).0: f32) = move _29; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:39: +9:56
--         discriminant(_3) = 3;            // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:39: +9:56
--         StorageDead(_29);                // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:55: +9:56
--         StorageDead(_28);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:55: +9:56
--         StorageDead(_27);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:55: +9:56
-+         _31 = (((*_46) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:28: +9:33
-+         nop;                             // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:44: +9:55
-+         nop;                             // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:44: +9:47
-+         nop;                             // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:44: +9:47
-+         nop;                             // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:50: +9:55
-+         nop;                             // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:50: +9:55
-+         ((((_0 as Ok).0: ViewportPercentageLength) as Vmax).0: f32) = Add(move _30, move _31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:44: +9:55
-+         nop;                             // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:54: +9:55
-+         nop;                             // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:54: +9:55
-+         Deinit(((_0 as Ok).0: ViewportPercentageLength)); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:39: +9:56
-+         nop;                             // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:39: +9:56
-+         discriminant(((_0 as Ok).0: ViewportPercentageLength)) = 3; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:39: +9:56
-+         nop;                             // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:55: +9:56
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:55: +9:56
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:55: +9:56
-          goto -> bb10;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:55: +9:56
-      }
-  
-      bb10: {
-          Deinit(_0);                      // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:5: +11:7
--         ((_0 as Ok).0: ViewportPercentageLength) = move _3; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:5: +11:7
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:5: +11:7
-          discriminant(_0) = 0;            // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:5: +11:7
--         StorageDead(_3);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:+11:6: +11:7
--         StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:1: +12:2
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:+11:6: +11:7
-+         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:1: +12:2
-          return;                          // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:2: +12:2
-      }
-  
-      bb11: {
-          unreachable;                     // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:2: +12:2
-      }
-  }
-  
index 50a58d4792a8d19ed25fafc1a2da11e30eac2592..6bc025bb5b204897dc703bc1ddfa995e634377de 100644 (file)
@@ -80,7 +80,7 @@
           StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:23: +5:24
           _34 = deref_copy (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
           _11 = discriminant((*_34));      // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-          switchInt(move _11) -> [0_isize: bb1, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb11]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
+          switchInt(move _11) -> [0_isize: bb1, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
       }
   
       bb1: {
   
       bb2: {
           StorageLive(_33);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:25: +10:27
-          nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:25: +10:27
+          Deinit(_33);                     // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:25: +10:27
           Deinit(_0);                      // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28
-          nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28
+          ((_0 as Err).0: ()) = move _33;  // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28
           discriminant(_0) = 1;            // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28
           StorageDead(_33);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:27: +10:28
           StorageDead(_3);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:+11:6: +11:7
           StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:1: +12:2
-          return;                          // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:2: +12:2
+          goto -> bb11;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:2: +12:2
       }
   
       bb3: {
           discriminant(_0) = 0;            // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:5: +11:7
           StorageDead(_3);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:+11:6: +11:7
           StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:1: +12:2
-          return;                          // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:2: +12:2
+          goto -> bb11;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:2: +12:2
       }
   
       bb11: {
-          unreachable;                     // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:2: +12:2
+          return;                          // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:2: +12:2
       }
   }
   
index 703b876123133a2f01e82f08d2096e6382ad6b8b..9e731c40908790c8a9c30440333ca8bc7c8bbca9 100644 (file)
@@ -10,4 +10,3 @@ fn main() {
 
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
 // EMIT_MIR issue_73223.main.SimplifyArmIdentity.diff
-// EMIT_MIR issue_73223.main.PreCodegen.diff
diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff
deleted file mode 100644 (file)
index be8e86a..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-- // MIR for `main` before PreCodegen
-+ // MIR for `main` after PreCodegen
-  
-  fn main() -> () {
-      let mut _0: ();                      // return place in scope 0 at $DIR/issue-73223.rs:+0:11: +0:11
-      let _1: i32;                         // in scope 0 at $DIR/issue-73223.rs:+1:9: +1:14
-      let mut _2: std::option::Option<i32>; // in scope 0 at $DIR/issue-73223.rs:+1:23: +1:30
-      let _3: i32;                         // in scope 0 at $DIR/issue-73223.rs:+2:14: +2:15
-      let mut _5: (&i32, &i32);            // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _6: &i32;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _7: &i32;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _10: bool;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _11: bool;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _12: i32;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let _14: !;                          // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _15: &i32;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let _16: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _17: &i32;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let _18: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _19: std::option::Option<std::fmt::Arguments>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      scope 1 {
-          debug split => _1;               // in scope 1 at $DIR/issue-73223.rs:+1:9: +1:14
-          let _4: std::option::Option<i32>; // in scope 1 at $DIR/issue-73223.rs:+6:9: +6:14
-          scope 3 {
-              debug _prev => _4;           // in scope 3 at $DIR/issue-73223.rs:+6:9: +6:14
-              let _8: &i32;                // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-              let _9: &i32;                // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-              let mut _20: &i32;           // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-              scope 4 {
-                  debug left_val => _8;    // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                  debug right_val => _9;   // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                  let _13: core::panicking::AssertKind; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                  scope 5 {
-                      debug kind => _13;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                  }
-              }
-          }
-      }
-      scope 2 {
-          debug v => _3;                   // in scope 2 at $DIR/issue-73223.rs:+2:14: +2:15
-      }
-  
-      bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/issue-73223.rs:+1:9: +1:14
-          StorageLive(_2);                 // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30
-          Deinit(_2);                      // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30
-          ((_2 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30
-          discriminant(_2) = 1;            // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30
-          StorageLive(_3);                 // scope 0 at $DIR/issue-73223.rs:+2:14: +2:15
-          _3 = ((_2 as Some).0: i32);      // scope 0 at $DIR/issue-73223.rs:+2:14: +2:15
-          _1 = _3;                         // scope 2 at $DIR/issue-73223.rs:+2:20: +2:21
-          StorageDead(_3);                 // scope 0 at $DIR/issue-73223.rs:+2:20: +2:21
-          StorageDead(_2);                 // scope 0 at $DIR/issue-73223.rs:+4:6: +4:7
-          StorageLive(_4);                 // scope 1 at $DIR/issue-73223.rs:+6:9: +6:14
-          StorageLive(_5);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_6);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _6 = &_1;                        // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_7);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _20 = const main::promoted[0];   // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                                           // mir::Constant
-                                           // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                                           // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) }
-          _7 = _20;                        // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          Deinit(_5);                      // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          (_5.0: &i32) = move _6;          // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          (_5.1: &i32) = move _7;          // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_7);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_6);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_8);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _8 = (_5.0: &i32);               // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_9);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _9 = (_5.1: &i32);               // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_10);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_11);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_12);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _12 = (*_8);                     // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _11 = Eq(move _12, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_12);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _10 = Not(move _11);             // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_11);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          switchInt(move _10) -> [false: bb2, otherwise: bb1]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      }
-  
-      bb1: {
-          StorageLive(_13);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_14);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_15);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_16);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _16 = _8;                        // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _15 = _16;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_17);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_18);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _18 = _9;                        // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _17 = _18;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_19);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          Deinit(_19);                     // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          discriminant(_19) = 0;           // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _14 = core::panicking::assert_failed::<i32, i32>(const core::panicking::AssertKind::Eq, move _15, move _17, move _19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                                           // mir::Constant
-                                           // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                                           // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, Option<Arguments<'t0>>) -> ! {core::panicking::assert_failed::<i32, i32>}, val: Value(<ZST>) }
-                                           // mir::Constant
-                                           // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                                           // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) }
-      }
-  
-      bb2: {
-          StorageDead(_10);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_9);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_8);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_5);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_4);                 // scope 1 at $DIR/issue-73223.rs:+8:1: +8:2
-          StorageDead(_1);                 // scope 0 at $DIR/issue-73223.rs:+8:1: +8:2
-          return;                          // scope 0 at $DIR/issue-73223.rs:+8:2: +8:2
-      }
-  }
-  
diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff
deleted file mode 100644 (file)
index be8e86a..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-- // MIR for `main` before PreCodegen
-+ // MIR for `main` after PreCodegen
-  
-  fn main() -> () {
-      let mut _0: ();                      // return place in scope 0 at $DIR/issue-73223.rs:+0:11: +0:11
-      let _1: i32;                         // in scope 0 at $DIR/issue-73223.rs:+1:9: +1:14
-      let mut _2: std::option::Option<i32>; // in scope 0 at $DIR/issue-73223.rs:+1:23: +1:30
-      let _3: i32;                         // in scope 0 at $DIR/issue-73223.rs:+2:14: +2:15
-      let mut _5: (&i32, &i32);            // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _6: &i32;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _7: &i32;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _10: bool;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _11: bool;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _12: i32;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let _14: !;                          // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _15: &i32;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let _16: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _17: &i32;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let _18: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _19: std::option::Option<std::fmt::Arguments>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      scope 1 {
-          debug split => _1;               // in scope 1 at $DIR/issue-73223.rs:+1:9: +1:14
-          let _4: std::option::Option<i32>; // in scope 1 at $DIR/issue-73223.rs:+6:9: +6:14
-          scope 3 {
-              debug _prev => _4;           // in scope 3 at $DIR/issue-73223.rs:+6:9: +6:14
-              let _8: &i32;                // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-              let _9: &i32;                // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-              let mut _20: &i32;           // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-              scope 4 {
-                  debug left_val => _8;    // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                  debug right_val => _9;   // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                  let _13: core::panicking::AssertKind; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                  scope 5 {
-                      debug kind => _13;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                  }
-              }
-          }
-      }
-      scope 2 {
-          debug v => _3;                   // in scope 2 at $DIR/issue-73223.rs:+2:14: +2:15
-      }
-  
-      bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/issue-73223.rs:+1:9: +1:14
-          StorageLive(_2);                 // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30
-          Deinit(_2);                      // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30
-          ((_2 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30
-          discriminant(_2) = 1;            // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30
-          StorageLive(_3);                 // scope 0 at $DIR/issue-73223.rs:+2:14: +2:15
-          _3 = ((_2 as Some).0: i32);      // scope 0 at $DIR/issue-73223.rs:+2:14: +2:15
-          _1 = _3;                         // scope 2 at $DIR/issue-73223.rs:+2:20: +2:21
-          StorageDead(_3);                 // scope 0 at $DIR/issue-73223.rs:+2:20: +2:21
-          StorageDead(_2);                 // scope 0 at $DIR/issue-73223.rs:+4:6: +4:7
-          StorageLive(_4);                 // scope 1 at $DIR/issue-73223.rs:+6:9: +6:14
-          StorageLive(_5);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_6);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _6 = &_1;                        // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_7);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _20 = const main::promoted[0];   // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                                           // mir::Constant
-                                           // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                                           // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) }
-          _7 = _20;                        // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          Deinit(_5);                      // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          (_5.0: &i32) = move _6;          // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          (_5.1: &i32) = move _7;          // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_7);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_6);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_8);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _8 = (_5.0: &i32);               // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_9);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _9 = (_5.1: &i32);               // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_10);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_11);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_12);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _12 = (*_8);                     // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _11 = Eq(move _12, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_12);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _10 = Not(move _11);             // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_11);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          switchInt(move _10) -> [false: bb2, otherwise: bb1]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      }
-  
-      bb1: {
-          StorageLive(_13);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_14);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_15);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_16);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _16 = _8;                        // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _15 = _16;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_17);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_18);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _18 = _9;                        // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _17 = _18;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_19);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          Deinit(_19);                     // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          discriminant(_19) = 0;           // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _14 = core::panicking::assert_failed::<i32, i32>(const core::panicking::AssertKind::Eq, move _15, move _17, move _19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                                           // mir::Constant
-                                           // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                                           // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, Option<Arguments<'t0>>) -> ! {core::panicking::assert_failed::<i32, i32>}, val: Value(<ZST>) }
-                                           // mir::Constant
-                                           // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                                           // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) }
-      }
-  
-      bb2: {
-          StorageDead(_10);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_9);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_8);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_5);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_4);                 // scope 1 at $DIR/issue-73223.rs:+8:1: +8:2
-          StorageDead(_1);                 // scope 0 at $DIR/issue-73223.rs:+8:1: +8:2
-          return;                          // scope 0 at $DIR/issue-73223.rs:+8:2: +8:2
-      }
-  }
-  
diff --git a/src/test/mir-opt/lower_array_len.array_bound.InstCombine.diff b/src/test/mir-opt/lower_array_len.array_bound.InstCombine.diff
deleted file mode 100644 (file)
index 2589c9f..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-- // MIR for `array_bound` before InstCombine
-+ // MIR for `array_bound` after InstCombine
-  
-  fn array_bound(_1: usize, _2: &[u8; N]) -> u8 {
-      debug index => _1;                   // in scope 0 at $DIR/lower_array_len.rs:+0:36: +0:41
-      debug slice => _2;                   // in scope 0 at $DIR/lower_array_len.rs:+0:50: +0:55
-      let mut _0: u8;                      // return place in scope 0 at $DIR/lower_array_len.rs:+0:70: +0:72
-      let mut _3: bool;                    // in scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
-      let mut _4: usize;                   // in scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13
-      let mut _5: usize;                   // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-      let mut _6: &[u8];                   // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-      let mut _7: &[u8; N];                // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-      let _8: usize;                       // in scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
-      let mut _9: usize;                   // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-      let mut _10: bool;                   // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-      let mut _11: &[u8; N];               // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-  
-      bb0: {
-          StorageLive(_3);                 // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
-          StorageLive(_4);                 // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13
-          _4 = _1;                         // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13
-          StorageLive(_5);                 // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-          StorageLive(_6);                 // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-          StorageLive(_7);                 // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
--         _7 = &(*_2);                     // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-+         _7 = _2;                         // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-          StorageLive(_11);                // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-          _11 = _7;                        // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-          _6 = move _7 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-          StorageDead(_7);                 // scope 0 at $DIR/lower_array_len.rs:+1:20: +1:21
--         _5 = Len((*_11));                // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-+         _5 = const N;                    // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-          StorageDead(_11);                // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-          StorageDead(_6);                 // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27
-          _3 = Lt(move _4, move _5);       // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
-          StorageDead(_5);                 // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27
-          StorageDead(_4);                 // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27
-          switchInt(move _3) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
-      }
-  
-      bb1: {
-          StorageLive(_8);                 // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
-          _8 = _1;                         // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
--         _9 = Len((*_2));                 // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-+         _9 = const N;                    // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-          _10 = Lt(_8, _9);                // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-          assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> bb2; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-      }
-  
-      bb2: {
-          _0 = (*_2)[_8];                  // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-          StorageDead(_8);                 // scope 0 at $DIR/lower_array_len.rs:+3:5: +3:6
-          goto -> bb4;                     // scope 0 at $DIR/lower_array_len.rs:+1:5: +5:6
-      }
-  
-      bb3: {
-          _0 = const 42_u8;                // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:11
-          goto -> bb4;                     // scope 0 at $DIR/lower_array_len.rs:+1:5: +5:6
-      }
-  
-      bb4: {
-          StorageDead(_3);                 // scope 0 at $DIR/lower_array_len.rs:+5:5: +5:6
-          return;                          // scope 0 at $DIR/lower_array_len.rs:+6:2: +6:2
-      }
-  }
-  
diff --git a/src/test/mir-opt/lower_array_len.array_bound.SimplifyLocals.diff b/src/test/mir-opt/lower_array_len.array_bound.SimplifyLocals.diff
deleted file mode 100644 (file)
index 8312db6..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-- // MIR for `array_bound` before SimplifyLocals
-+ // MIR for `array_bound` after SimplifyLocals
-  
-  fn array_bound(_1: usize, _2: &[u8; N]) -> u8 {
-      debug index => _1;                   // in scope 0 at $DIR/lower_array_len.rs:+0:36: +0:41
-      debug slice => _2;                   // in scope 0 at $DIR/lower_array_len.rs:+0:50: +0:55
-      let mut _0: u8;                      // return place in scope 0 at $DIR/lower_array_len.rs:+0:70: +0:72
-      let mut _3: bool;                    // in scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
-      let mut _4: usize;                   // in scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13
-      let mut _5: usize;                   // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
--     let mut _6: &[u8];                   // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
--     let mut _7: &[u8; N];                // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
--     let _8: usize;                       // in scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
--     let mut _9: usize;                   // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
--     let mut _10: bool;                   // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
--     let mut _11: &[u8; N];               // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-+     let _6: usize;                       // in scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
-+     let mut _7: usize;                   // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-+     let mut _8: bool;                    // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-  
-      bb0: {
-          StorageLive(_3);                 // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
-          StorageLive(_4);                 // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13
-          _4 = _1;                         // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13
-          StorageLive(_5);                 // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
--         StorageLive(_6);                 // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
--         StorageLive(_7);                 // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
--         StorageLive(_11);                // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
--         StorageDead(_7);                 // scope 0 at $DIR/lower_array_len.rs:+1:20: +1:21
-          _5 = const N;                    // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
--         StorageDead(_11);                // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
--         StorageDead(_6);                 // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27
-          _3 = Lt(move _4, move _5);       // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
-          StorageDead(_5);                 // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27
-          StorageDead(_4);                 // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27
-          switchInt(move _3) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
-      }
-  
-      bb1: {
--         StorageLive(_8);                 // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
--         _8 = _1;                         // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
--         _9 = const N;                    // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
--         _10 = Lt(_8, _9);                // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
--         assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> bb2; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-+         StorageLive(_6);                 // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
-+         _6 = _1;                         // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
-+         _7 = const N;                    // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-+         _8 = Lt(_6, _7);                 // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-+         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb2; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-      }
-  
-      bb2: {
--         _0 = (*_2)[_8];                  // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
--         StorageDead(_8);                 // scope 0 at $DIR/lower_array_len.rs:+3:5: +3:6
-+         _0 = (*_2)[_6];                  // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-+         StorageDead(_6);                 // scope 0 at $DIR/lower_array_len.rs:+3:5: +3:6
-          goto -> bb4;                     // scope 0 at $DIR/lower_array_len.rs:+1:5: +5:6
-      }
-  
-      bb3: {
-          _0 = const 42_u8;                // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:11
-          goto -> bb4;                     // scope 0 at $DIR/lower_array_len.rs:+1:5: +5:6
-      }
-  
-      bb4: {
-          StorageDead(_3);                 // scope 0 at $DIR/lower_array_len.rs:+5:5: +5:6
-          return;                          // scope 0 at $DIR/lower_array_len.rs:+6:2: +6:2
-      }
-  }
-  
diff --git a/src/test/mir-opt/lower_array_len.array_bound_mut.InstCombine.diff b/src/test/mir-opt/lower_array_len.array_bound_mut.InstCombine.diff
deleted file mode 100644 (file)
index 401d4ba..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-- // MIR for `array_bound_mut` before InstCombine
-+ // MIR for `array_bound_mut` after InstCombine
-  
-  fn array_bound_mut(_1: usize, _2: &mut [u8; N]) -> u8 {
-      debug index => _1;                   // in scope 0 at $DIR/lower_array_len.rs:+0:40: +0:45
-      debug slice => _2;                   // in scope 0 at $DIR/lower_array_len.rs:+0:54: +0:59
-      let mut _0: u8;                      // return place in scope 0 at $DIR/lower_array_len.rs:+0:78: +0:80
-      let mut _3: bool;                    // in scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
-      let mut _4: usize;                   // in scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13
-      let mut _5: usize;                   // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-      let mut _6: &[u8];                   // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-      let mut _7: &[u8; N];                // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-      let _8: usize;                       // in scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
-      let mut _9: usize;                   // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-      let mut _10: bool;                   // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-      let _11: usize;                      // in scope 0 at $DIR/lower_array_len.rs:+4:15: +4:16
-      let mut _12: usize;                  // in scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
-      let mut _13: bool;                   // in scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
-      let mut _14: &[u8; N];               // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-  
-      bb0: {
-          StorageLive(_3);                 // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
-          StorageLive(_4);                 // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13
-          _4 = _1;                         // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13
-          StorageLive(_5);                 // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-          StorageLive(_6);                 // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-          StorageLive(_7);                 // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-          _7 = &(*_2);                     // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-          StorageLive(_14);                // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-          _14 = _7;                        // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-          _6 = move _7 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-          StorageDead(_7);                 // scope 0 at $DIR/lower_array_len.rs:+1:20: +1:21
--         _5 = Len((*_14));                // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-+         _5 = const N;                    // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-          StorageDead(_14);                // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-          StorageDead(_6);                 // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27
-          _3 = Lt(move _4, move _5);       // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
-          StorageDead(_5);                 // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27
-          StorageDead(_4);                 // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27
-          switchInt(move _3) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
-      }
-  
-      bb1: {
-          StorageLive(_8);                 // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
-          _8 = _1;                         // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
--         _9 = Len((*_2));                 // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-+         _9 = const N;                    // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-          _10 = Lt(_8, _9);                // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-          assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> bb2; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-      }
-  
-      bb2: {
-          _0 = (*_2)[_8];                  // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-          StorageDead(_8);                 // scope 0 at $DIR/lower_array_len.rs:+3:5: +3:6
-          goto -> bb5;                     // scope 0 at $DIR/lower_array_len.rs:+1:5: +7:6
-      }
-  
-      bb3: {
-          StorageLive(_11);                // scope 0 at $DIR/lower_array_len.rs:+4:15: +4:16
-          _11 = const 0_usize;             // scope 0 at $DIR/lower_array_len.rs:+4:15: +4:16
--         _12 = Len((*_2));                // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
-+         _12 = const N;                   // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
-          _13 = Lt(_11, _12);              // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
-          assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, _11) -> bb4; // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
-      }
-  
-      bb4: {
-          (*_2)[_11] = const 42_u8;        // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:22
-          StorageDead(_11);                // scope 0 at $DIR/lower_array_len.rs:+4:22: +4:23
-          _0 = const 42_u8;                // scope 0 at $DIR/lower_array_len.rs:+6:9: +6:11
-          goto -> bb5;                     // scope 0 at $DIR/lower_array_len.rs:+1:5: +7:6
-      }
-  
-      bb5: {
-          StorageDead(_3);                 // scope 0 at $DIR/lower_array_len.rs:+7:5: +7:6
-          return;                          // scope 0 at $DIR/lower_array_len.rs:+8:2: +8:2
-      }
-  }
-  
diff --git a/src/test/mir-opt/lower_array_len.array_bound_mut.SimplifyLocals.diff b/src/test/mir-opt/lower_array_len.array_bound_mut.SimplifyLocals.diff
deleted file mode 100644 (file)
index 4f241d7..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-- // MIR for `array_bound_mut` before SimplifyLocals
-+ // MIR for `array_bound_mut` after SimplifyLocals
-  
-  fn array_bound_mut(_1: usize, _2: &mut [u8; N]) -> u8 {
-      debug index => _1;                   // in scope 0 at $DIR/lower_array_len.rs:+0:40: +0:45
-      debug slice => _2;                   // in scope 0 at $DIR/lower_array_len.rs:+0:54: +0:59
-      let mut _0: u8;                      // return place in scope 0 at $DIR/lower_array_len.rs:+0:78: +0:80
-      let mut _3: bool;                    // in scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
-      let mut _4: usize;                   // in scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13
-      let mut _5: usize;                   // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
--     let mut _6: &[u8];                   // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
--     let mut _7: &[u8; N];                // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
--     let _8: usize;                       // in scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
--     let mut _9: usize;                   // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
--     let mut _10: bool;                   // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
--     let _11: usize;                      // in scope 0 at $DIR/lower_array_len.rs:+4:15: +4:16
--     let mut _12: usize;                  // in scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
--     let mut _13: bool;                   // in scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
--     let mut _14: &[u8; N];               // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-+     let _6: usize;                       // in scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
-+     let mut _7: usize;                   // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-+     let mut _8: bool;                    // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-+     let _9: usize;                       // in scope 0 at $DIR/lower_array_len.rs:+4:15: +4:16
-+     let mut _10: usize;                  // in scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
-+     let mut _11: bool;                   // in scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
-  
-      bb0: {
-          StorageLive(_3);                 // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
-          StorageLive(_4);                 // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13
-          _4 = _1;                         // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:13
-          StorageLive(_5);                 // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
--         StorageLive(_6);                 // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
--         StorageLive(_7);                 // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
--         StorageLive(_14);                // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
--         StorageDead(_7);                 // scope 0 at $DIR/lower_array_len.rs:+1:20: +1:21
-          _5 = const N;                    // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
--         StorageDead(_14);                // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
--         StorageDead(_6);                 // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27
-          _3 = Lt(move _4, move _5);       // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
-          StorageDead(_5);                 // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27
-          StorageDead(_4);                 // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27
-          switchInt(move _3) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
-      }
-  
-      bb1: {
--         StorageLive(_8);                 // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
--         _8 = _1;                         // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
--         _9 = const N;                    // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
--         _10 = Lt(_8, _9);                // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
--         assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> bb2; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-+         StorageLive(_6);                 // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
-+         _6 = _1;                         // scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
-+         _7 = const N;                    // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-+         _8 = Lt(_6, _7);                 // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-+         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb2; // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-      }
-  
-      bb2: {
--         _0 = (*_2)[_8];                  // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
--         StorageDead(_8);                 // scope 0 at $DIR/lower_array_len.rs:+3:5: +3:6
-+         _0 = (*_2)[_6];                  // scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-+         StorageDead(_6);                 // scope 0 at $DIR/lower_array_len.rs:+3:5: +3:6
-          goto -> bb5;                     // scope 0 at $DIR/lower_array_len.rs:+1:5: +7:6
-      }
-  
-      bb3: {
--         StorageLive(_11);                // scope 0 at $DIR/lower_array_len.rs:+4:15: +4:16
--         _11 = const 0_usize;             // scope 0 at $DIR/lower_array_len.rs:+4:15: +4:16
--         _12 = const N;                   // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
--         _13 = Lt(const 0_usize, _12);    // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
--         assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, const 0_usize) -> bb4; // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
-+         StorageLive(_9);                 // scope 0 at $DIR/lower_array_len.rs:+4:15: +4:16
-+         _9 = const 0_usize;              // scope 0 at $DIR/lower_array_len.rs:+4:15: +4:16
-+         _10 = const N;                   // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
-+         _11 = Lt(const 0_usize, _10);    // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
-+         assert(move _11, "index out of bounds: the length is {} but the index is {}", move _10, const 0_usize) -> bb4; // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
-      }
-  
-      bb4: {
--         (*_2)[_11] = const 42_u8;        // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:22
--         StorageDead(_11);                // scope 0 at $DIR/lower_array_len.rs:+4:22: +4:23
-+         (*_2)[_9] = const 42_u8;         // scope 0 at $DIR/lower_array_len.rs:+4:9: +4:22
-+         StorageDead(_9);                 // scope 0 at $DIR/lower_array_len.rs:+4:22: +4:23
-          _0 = const 42_u8;                // scope 0 at $DIR/lower_array_len.rs:+6:9: +6:11
-          goto -> bb5;                     // scope 0 at $DIR/lower_array_len.rs:+1:5: +7:6
-      }
-  
-      bb5: {
-          StorageDead(_3);                 // scope 0 at $DIR/lower_array_len.rs:+7:5: +7:6
-          return;                          // scope 0 at $DIR/lower_array_len.rs:+8:2: +8:2
-      }
-  }
-  
diff --git a/src/test/mir-opt/lower_array_len.array_len.InstCombine.diff b/src/test/mir-opt/lower_array_len.array_len.InstCombine.diff
deleted file mode 100644 (file)
index 26f45be..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-- // MIR for `array_len` before InstCombine
-+ // MIR for `array_len` after InstCombine
-  
-  fn array_len(_1: &[u8; N]) -> usize {
-      debug arr => _1;                     // in scope 0 at $DIR/lower_array_len.rs:+0:34: +0:37
-      let mut _0: usize;                   // return place in scope 0 at $DIR/lower_array_len.rs:+0:52: +0:57
-      let mut _2: &[u8];                   // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-      let mut _3: &[u8; N];                // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-      let mut _4: &[u8; N];                // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-  
-      bb0: {
-          StorageLive(_2);                 // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-          StorageLive(_3);                 // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
--         _3 = &(*_1);                     // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+         _3 = _1;                         // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-          StorageLive(_4);                 // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-          _4 = _3;                         // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-          _2 = move _3 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-          StorageDead(_3);                 // scope 0 at $DIR/lower_array_len.rs:+1:7: +1:8
--         _0 = Len((*_4));                 // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+         _0 = const N;                    // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-          StorageDead(_4);                 // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-          StorageDead(_2);                 // scope 0 at $DIR/lower_array_len.rs:+1:13: +1:14
-          return;                          // scope 0 at $DIR/lower_array_len.rs:+2:2: +2:2
-      }
-  }
-  
diff --git a/src/test/mir-opt/lower_array_len.array_len.SimplifyLocals.diff b/src/test/mir-opt/lower_array_len.array_len.SimplifyLocals.diff
deleted file mode 100644 (file)
index 09d571d..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-- // MIR for `array_len` before SimplifyLocals
-+ // MIR for `array_len` after SimplifyLocals
-  
-  fn array_len(_1: &[u8; N]) -> usize {
-      debug arr => _1;                     // in scope 0 at $DIR/lower_array_len.rs:+0:34: +0:37
-      let mut _0: usize;                   // return place in scope 0 at $DIR/lower_array_len.rs:+0:52: +0:57
--     let mut _2: &[u8];                   // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
--     let mut _3: &[u8; N];                // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
--     let mut _4: &[u8; N];                // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-  
-      bb0: {
--         StorageLive(_2);                 // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
--         StorageLive(_3);                 // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
--         StorageLive(_4);                 // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
--         StorageDead(_3);                 // scope 0 at $DIR/lower_array_len.rs:+1:7: +1:8
-          _0 = const N;                    // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
--         StorageDead(_4);                 // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
--         StorageDead(_2);                 // scope 0 at $DIR/lower_array_len.rs:+1:13: +1:14
-          return;                          // scope 0 at $DIR/lower_array_len.rs:+2:2: +2:2
-      }
-  }
-  
diff --git a/src/test/mir-opt/lower_array_len.array_len_by_value.InstCombine.diff b/src/test/mir-opt/lower_array_len.array_len_by_value.InstCombine.diff
deleted file mode 100644 (file)
index 843da75..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-- // MIR for `array_len_by_value` before InstCombine
-+ // MIR for `array_len_by_value` after InstCombine
-  
-  fn array_len_by_value(_1: [u8; N]) -> usize {
-      debug arr => _1;                     // in scope 0 at $DIR/lower_array_len.rs:+0:43: +0:46
-      let mut _0: usize;                   // return place in scope 0 at $DIR/lower_array_len.rs:+0:60: +0:65
-      let mut _2: &[u8];                   // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-      let mut _3: &[u8; N];                // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-      let mut _4: &[u8; N];                // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-  
-      bb0: {
-          StorageLive(_2);                 // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-          StorageLive(_3);                 // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-          _3 = &_1;                        // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-          StorageLive(_4);                 // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-          _4 = _3;                         // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-          _2 = move _3 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-          StorageDead(_3);                 // scope 0 at $DIR/lower_array_len.rs:+1:7: +1:8
--         _0 = Len((*_4));                 // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+         _0 = const N;                    // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-          StorageDead(_4);                 // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-          StorageDead(_2);                 // scope 0 at $DIR/lower_array_len.rs:+1:13: +1:14
-          return;                          // scope 0 at $DIR/lower_array_len.rs:+2:2: +2:2
-      }
-  }
-  
diff --git a/src/test/mir-opt/lower_array_len.array_len_by_value.SimplifyLocals.diff b/src/test/mir-opt/lower_array_len.array_len_by_value.SimplifyLocals.diff
deleted file mode 100644 (file)
index dc1c00b..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-- // MIR for `array_len_by_value` before SimplifyLocals
-+ // MIR for `array_len_by_value` after SimplifyLocals
-  
-  fn array_len_by_value(_1: [u8; N]) -> usize {
-      debug arr => _1;                     // in scope 0 at $DIR/lower_array_len.rs:+0:43: +0:46
-      let mut _0: usize;                   // return place in scope 0 at $DIR/lower_array_len.rs:+0:60: +0:65
--     let mut _2: &[u8];                   // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
--     let mut _3: &[u8; N];                // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
--     let mut _4: &[u8; N];                // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-  
-      bb0: {
--         StorageLive(_2);                 // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
--         StorageLive(_3);                 // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
--         StorageLive(_4);                 // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
--         StorageDead(_3);                 // scope 0 at $DIR/lower_array_len.rs:+1:7: +1:8
-          _0 = const N;                    // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
--         StorageDead(_4);                 // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
--         StorageDead(_2);                 // scope 0 at $DIR/lower_array_len.rs:+1:13: +1:14
-          return;                          // scope 0 at $DIR/lower_array_len.rs:+2:2: +2:2
-      }
-  }
-  
index fc12ee75fcfcd233bccd82626f2e907bfa06ca5d..ea0224b21d72d769972aef5f75c3c0876ae8b495 100644 (file)
@@ -1,8 +1,7 @@
-// compile-flags: -Z mir-opt-level=4
+// unit-test: NormalizeArrayLen
+// compile-flags: -Zmir-enable-passes=+LowerSliceLenCalls
 
 // EMIT_MIR lower_array_len.array_bound.NormalizeArrayLen.diff
-// EMIT_MIR lower_array_len.array_bound.SimplifyLocals.diff
-// EMIT_MIR lower_array_len.array_bound.InstCombine.diff
 pub fn array_bound<const N: usize>(index: usize, slice: &[u8; N]) -> u8 {
     if index < slice.len() {
         slice[index]
@@ -12,8 +11,6 @@
 }
 
 // EMIT_MIR lower_array_len.array_bound_mut.NormalizeArrayLen.diff
-// EMIT_MIR lower_array_len.array_bound_mut.SimplifyLocals.diff
-// EMIT_MIR lower_array_len.array_bound_mut.InstCombine.diff
 pub fn array_bound_mut<const N: usize>(index: usize, slice: &mut [u8; N]) -> u8 {
     if index < slice.len() {
         slice[index]
 }
 
 // EMIT_MIR lower_array_len.array_len.NormalizeArrayLen.diff
-// EMIT_MIR lower_array_len.array_len.SimplifyLocals.diff
-// EMIT_MIR lower_array_len.array_len.InstCombine.diff
 pub fn array_len<const N: usize>(arr: &[u8; N]) -> usize {
     arr.len()
 }
 
 // EMIT_MIR lower_array_len.array_len_by_value.NormalizeArrayLen.diff
-// EMIT_MIR lower_array_len.array_len_by_value.SimplifyLocals.diff
-// EMIT_MIR lower_array_len.array_len_by_value.InstCombine.diff
 pub fn array_len_by_value<const N: usize>(arr: [u8; N]) -> usize {
     arr.len()
 }
diff --git a/src/test/mir-opt/lower_array_len_e2e.array_bound.PreCodegen.after.mir b/src/test/mir-opt/lower_array_len_e2e.array_bound.PreCodegen.after.mir
new file mode 100644 (file)
index 0000000..2c6c93c
--- /dev/null
@@ -0,0 +1,49 @@
+// MIR for `array_bound` after PreCodegen
+
+fn array_bound(_1: usize, _2: &[u8; N]) -> u8 {
+    debug index => _1;                   // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:36: +0:41
+    debug slice => _2;                   // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:50: +0:55
+    let mut _0: u8;                      // return place in scope 0 at $DIR/lower_array_len_e2e.rs:+0:70: +0:72
+    let mut _3: bool;                    // in scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
+    let mut _4: usize;                   // in scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:13
+    let mut _5: usize;                   // in scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27
+    let _6: usize;                       // in scope 0 at $DIR/lower_array_len_e2e.rs:+2:15: +2:20
+    let mut _7: usize;                   // in scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
+    let mut _8: bool;                    // in scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
+
+    bb0: {
+        StorageLive(_3);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
+        StorageLive(_4);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:13
+        _4 = _1;                         // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:13
+        StorageLive(_5);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27
+        _5 = const N;                    // scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27
+        _3 = Lt(move _4, move _5);       // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
+        StorageDead(_5);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+1:26: +1:27
+        StorageDead(_4);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+1:26: +1:27
+        switchInt(move _3) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
+    }
+
+    bb1: {
+        StorageLive(_6);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+2:15: +2:20
+        _6 = _1;                         // scope 0 at $DIR/lower_array_len_e2e.rs:+2:15: +2:20
+        _7 = const N;                    // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
+        _8 = Lt(_6, _7);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
+        assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb2; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
+    }
+
+    bb2: {
+        _0 = (*_2)[_6];                  // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
+        StorageDead(_6);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+3:5: +3:6
+        goto -> bb4;                     // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +5:6
+    }
+
+    bb3: {
+        _0 = const 42_u8;                // scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:11
+        goto -> bb4;                     // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +5:6
+    }
+
+    bb4: {
+        StorageDead(_3);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+5:5: +5:6
+        return;                          // scope 0 at $DIR/lower_array_len_e2e.rs:+6:2: +6:2
+    }
+}
diff --git a/src/test/mir-opt/lower_array_len_e2e.array_bound_mut.PreCodegen.after.mir b/src/test/mir-opt/lower_array_len_e2e.array_bound_mut.PreCodegen.after.mir
new file mode 100644 (file)
index 0000000..aee3a82
--- /dev/null
@@ -0,0 +1,62 @@
+// MIR for `array_bound_mut` after PreCodegen
+
+fn array_bound_mut(_1: usize, _2: &mut [u8; N]) -> u8 {
+    debug index => _1;                   // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:40: +0:45
+    debug slice => _2;                   // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:54: +0:59
+    let mut _0: u8;                      // return place in scope 0 at $DIR/lower_array_len_e2e.rs:+0:78: +0:80
+    let mut _3: bool;                    // in scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
+    let mut _4: usize;                   // in scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:13
+    let mut _5: usize;                   // in scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27
+    let _6: usize;                       // in scope 0 at $DIR/lower_array_len_e2e.rs:+2:15: +2:20
+    let mut _7: usize;                   // in scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
+    let mut _8: bool;                    // in scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
+    let _9: usize;                       // in scope 0 at $DIR/lower_array_len_e2e.rs:+4:15: +4:16
+    let mut _10: usize;                  // in scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:17
+    let mut _11: bool;                   // in scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:17
+
+    bb0: {
+        StorageLive(_3);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
+        StorageLive(_4);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:13
+        _4 = _1;                         // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:13
+        StorageLive(_5);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27
+        _5 = const N;                    // scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27
+        _3 = Lt(move _4, move _5);       // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
+        StorageDead(_5);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+1:26: +1:27
+        StorageDead(_4);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+1:26: +1:27
+        switchInt(move _3) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
+    }
+
+    bb1: {
+        StorageLive(_6);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+2:15: +2:20
+        _6 = _1;                         // scope 0 at $DIR/lower_array_len_e2e.rs:+2:15: +2:20
+        _7 = const N;                    // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
+        _8 = Lt(_6, _7);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
+        assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb2; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
+    }
+
+    bb2: {
+        _0 = (*_2)[_6];                  // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
+        StorageDead(_6);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+3:5: +3:6
+        goto -> bb5;                     // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +7:6
+    }
+
+    bb3: {
+        StorageLive(_9);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+4:15: +4:16
+        _9 = const 0_usize;              // scope 0 at $DIR/lower_array_len_e2e.rs:+4:15: +4:16
+        _10 = const N;                   // scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:17
+        _11 = Lt(const 0_usize, _10);    // scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:17
+        assert(move _11, "index out of bounds: the length is {} but the index is {}", move _10, const 0_usize) -> bb4; // scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:17
+    }
+
+    bb4: {
+        (*_2)[_9] = const 42_u8;         // scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:22
+        StorageDead(_9);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+4:22: +4:23
+        _0 = const 42_u8;                // scope 0 at $DIR/lower_array_len_e2e.rs:+6:9: +6:11
+        goto -> bb5;                     // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +7:6
+    }
+
+    bb5: {
+        StorageDead(_3);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+7:5: +7:6
+        return;                          // scope 0 at $DIR/lower_array_len_e2e.rs:+8:2: +8:2
+    }
+}
diff --git a/src/test/mir-opt/lower_array_len_e2e.array_len.PreCodegen.after.mir b/src/test/mir-opt/lower_array_len_e2e.array_len.PreCodegen.after.mir
new file mode 100644 (file)
index 0000000..4b19f67
--- /dev/null
@@ -0,0 +1,11 @@
+// MIR for `array_len` after PreCodegen
+
+fn array_len(_1: &[u8; N]) -> usize {
+    debug arr => _1;                     // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:34: +0:37
+    let mut _0: usize;                   // return place in scope 0 at $DIR/lower_array_len_e2e.rs:+0:52: +0:57
+
+    bb0: {
+        _0 = const N;                    // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +1:14
+        return;                          // scope 0 at $DIR/lower_array_len_e2e.rs:+2:2: +2:2
+    }
+}
diff --git a/src/test/mir-opt/lower_array_len_e2e.array_len_by_value.PreCodegen.after.mir b/src/test/mir-opt/lower_array_len_e2e.array_len_by_value.PreCodegen.after.mir
new file mode 100644 (file)
index 0000000..4dc0ba9
--- /dev/null
@@ -0,0 +1,11 @@
+// MIR for `array_len_by_value` after PreCodegen
+
+fn array_len_by_value(_1: [u8; N]) -> usize {
+    debug arr => _1;                     // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:43: +0:46
+    let mut _0: usize;                   // return place in scope 0 at $DIR/lower_array_len_e2e.rs:+0:60: +0:65
+
+    bb0: {
+        _0 = const N;                    // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +1:14
+        return;                          // scope 0 at $DIR/lower_array_len_e2e.rs:+2:2: +2:2
+    }
+}
diff --git a/src/test/mir-opt/lower_array_len_e2e.rs b/src/test/mir-opt/lower_array_len_e2e.rs
new file mode 100644 (file)
index 0000000..49b35d5
--- /dev/null
@@ -0,0 +1,39 @@
+// compile-flags: -Z mir-opt-level=4
+
+// EMIT_MIR lower_array_len_e2e.array_bound.PreCodegen.after.mir
+pub fn array_bound<const N: usize>(index: usize, slice: &[u8; N]) -> u8 {
+    if index < slice.len() {
+        slice[index]
+    } else {
+        42
+    }
+}
+
+// EMIT_MIR lower_array_len_e2e.array_bound_mut.PreCodegen.after.mir
+pub fn array_bound_mut<const N: usize>(index: usize, slice: &mut [u8; N]) -> u8 {
+    if index < slice.len() {
+        slice[index]
+    } else {
+        slice[0] = 42;
+
+        42
+    }
+}
+
+// EMIT_MIR lower_array_len_e2e.array_len.PreCodegen.after.mir
+pub fn array_len<const N: usize>(arr: &[u8; N]) -> usize {
+    arr.len()
+}
+
+// EMIT_MIR lower_array_len_e2e.array_len_by_value.PreCodegen.after.mir
+pub fn array_len_by_value<const N: usize>(arr: [u8; N]) -> usize {
+    arr.len()
+}
+
+fn main() {
+    let _ = array_bound(3, &[0, 1, 2, 3]);
+    let mut tmp = [0, 1, 2, 3, 4];
+    let _ = array_bound_mut(3, &mut [0, 1, 2, 3]);
+    let _ = array_len(&[0]);
+    let _ = array_len_by_value([0, 2]);
+}
index 5c635e2220ed707ce1de3fa180afae64e08f1413..3389db733b992a3a0576e83bae9c2d04a0490348 100644 (file)
@@ -7,7 +7,7 @@
       bb0: {
 -         _0 = std::intrinsics::min_align_of::<T>() -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:42
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:19:5: 19:40
+-                                          // + span: $DIR/lower_intrinsics.rs:21:5: 21:40
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn() -> usize {std::intrinsics::min_align_of::<T>}, val: Value(<ZST>) }
 +         _0 = AlignOf(T);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:42
 +         goto -> bb1;                     // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:42
index 8a80de32f3ae36d4c7916cc1849c93b4abed061a..f92ff9faf979686efb80d8edd3b0ba4def816b80 100644 (file)
@@ -31,7 +31,7 @@
           _3 = &(*_4);                     // scope 0 at $DIR/lower_intrinsics.rs:+1:42: +1:44
 -         _2 = discriminant_value::<T>(move _3) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:45
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:74:5: 74:41
+-                                          // + span: $DIR/lower_intrinsics.rs:49:5: 49:41
 -                                          // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r T) -> <T as DiscriminantKind>::Discriminant {discriminant_value::<T>}, val: Value(<ZST>) }
 +         _2 = discriminant((*_3));        // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:45
 +         goto -> bb1;                     // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:45
           StorageLive(_7);                 // scope 0 at $DIR/lower_intrinsics.rs:+2:42: +2:44
           _19 = const discriminant::<T>::promoted[2]; // scope 0 at $DIR/lower_intrinsics.rs:+2:42: +2:44
                                            // mir::Constant
-                                           // + span: $DIR/lower_intrinsics.rs:75:42: 75:44
+                                           // + span: $DIR/lower_intrinsics.rs:50:42: 50:44
                                            // + literal: Const { ty: &i32, val: Unevaluated(discriminant, [T], Some(promoted[2])) }
           _7 = &(*_19);                    // scope 0 at $DIR/lower_intrinsics.rs:+2:42: +2:44
           _6 = &(*_7);                     // scope 0 at $DIR/lower_intrinsics.rs:+2:42: +2:44
 -         _5 = discriminant_value::<i32>(move _6) -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:45
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:75:5: 75:41
+-                                          // + span: $DIR/lower_intrinsics.rs:50:5: 50:41
 -                                          // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r i32) -> <i32 as DiscriminantKind>::Discriminant {discriminant_value::<i32>}, val: Value(<ZST>) }
 +         _5 = discriminant((*_6));        // scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:45
 +         goto -> bb2;                     // scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:45
           StorageLive(_11);                // scope 0 at $DIR/lower_intrinsics.rs:+3:42: +3:45
           _18 = const discriminant::<T>::promoted[1]; // scope 0 at $DIR/lower_intrinsics.rs:+3:42: +3:45
                                            // mir::Constant
-                                           // + span: $DIR/lower_intrinsics.rs:76:42: 76:45
+                                           // + span: $DIR/lower_intrinsics.rs:51:42: 51:45
                                            // + literal: Const { ty: &(), val: Unevaluated(discriminant, [T], Some(promoted[1])) }
           _11 = &(*_18);                   // scope 0 at $DIR/lower_intrinsics.rs:+3:42: +3:45
           _10 = &(*_11);                   // scope 0 at $DIR/lower_intrinsics.rs:+3:42: +3:45
 -         _9 = discriminant_value::<()>(move _10) -> bb3; // scope 0 at $DIR/lower_intrinsics.rs:+3:5: +3:46
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:76:5: 76:41
+-                                          // + span: $DIR/lower_intrinsics.rs:51:5: 51:41
 -                                          // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r ()) -> <() as DiscriminantKind>::Discriminant {discriminant_value::<()>}, val: Value(<ZST>) }
 +         _9 = discriminant((*_10));       // scope 0 at $DIR/lower_intrinsics.rs:+3:5: +3:46
 +         goto -> bb3;                     // scope 0 at $DIR/lower_intrinsics.rs:+3:5: +3:46
           StorageLive(_15);                // scope 0 at $DIR/lower_intrinsics.rs:+4:42: +4:47
           _17 = const discriminant::<T>::promoted[0]; // scope 0 at $DIR/lower_intrinsics.rs:+4:42: +4:47
                                            // mir::Constant
-                                           // + span: $DIR/lower_intrinsics.rs:77:42: 77:47
+                                           // + span: $DIR/lower_intrinsics.rs:52:42: 52:47
                                            // + literal: Const { ty: &E, val: Unevaluated(discriminant, [T], Some(promoted[0])) }
           _15 = &(*_17);                   // scope 0 at $DIR/lower_intrinsics.rs:+4:42: +4:47
           _14 = &(*_15);                   // scope 0 at $DIR/lower_intrinsics.rs:+4:42: +4:47
 -         _13 = discriminant_value::<E>(move _14) -> bb4; // scope 0 at $DIR/lower_intrinsics.rs:+4:5: +4:48
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:77:5: 77:41
+-                                          // + span: $DIR/lower_intrinsics.rs:52:5: 52:41
 -                                          // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r E) -> <E as DiscriminantKind>::Discriminant {discriminant_value::<E>}, val: Value(<ZST>) }
 +         _13 = discriminant((*_14));      // scope 0 at $DIR/lower_intrinsics.rs:+4:5: +4:48
 +         goto -> bb4;                     // scope 0 at $DIR/lower_intrinsics.rs:+4:5: +4:48
           StorageDead(_15);                // scope 0 at $DIR/lower_intrinsics.rs:+4:48: +4:49
           StorageDead(_13);                // scope 0 at $DIR/lower_intrinsics.rs:+4:48: +4:49
           _0 = const ();                   // scope 0 at $DIR/lower_intrinsics.rs:+0:30: +5:2
-          drop(_1) -> bb5;                 // scope 0 at $DIR/lower_intrinsics.rs:+5:1: +5:2
+          drop(_1) -> [return: bb5, unwind: bb6]; // scope 0 at $DIR/lower_intrinsics.rs:+5:1: +5:2
       }
   
       bb5: {
           return;                          // scope 0 at $DIR/lower_intrinsics.rs:+5:2: +5:2
       }
+  
+      bb6 (cleanup): {
+          resume;                          // scope 0 at $DIR/lower_intrinsics.rs:+0:1: +5:2
+      }
   }
   
diff --git a/src/test/mir-opt/lower_intrinsics.f_u64.PreCodegen.before.mir b/src/test/mir-opt/lower_intrinsics.f_u64.PreCodegen.before.mir
deleted file mode 100644 (file)
index 2a9a099..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-// MIR for `f_u64` before PreCodegen
-
-fn f_u64() -> () {
-    let mut _0: ();                      // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:16: +0:16
-    let mut _1: u64;                     // in scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:21
-    scope 1 (inlined f_dispatch::<u64>) { // at $DIR/lower_intrinsics.rs:40:5: 40:21
-        debug t => _1;                   // in scope 1 at $DIR/lower_intrinsics.rs:44:22: 44:23
-        let _2: ();                      // in scope 1 at $DIR/lower_intrinsics.rs:48:9: 48:21
-        let mut _3: u64;                 // in scope 1 at $DIR/lower_intrinsics.rs:48:19: 48:20
-        scope 2 (inlined std::mem::size_of::<u64>) { // at $DIR/lower_intrinsics.rs:45:8: 45:32
-        }
-    }
-
-    bb0: {
-        StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:21
-        _1 = const 0_u64;                // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:21
-        StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:48:9: 48:21
-        StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:48:19: 48:20
-        _3 = move _1;                    // scope 1 at $DIR/lower_intrinsics.rs:48:19: 48:20
-        _2 = f_non_zst::<u64>(move _3) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:48:9: 48:21
-                                         // mir::Constant
-                                         // + span: $DIR/lower_intrinsics.rs:48:9: 48:18
-                                         // + literal: Const { ty: fn(u64) {f_non_zst::<u64>}, val: Value(<ZST>) }
-    }
-
-    bb1: {
-        StorageDead(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:48:20: 48:21
-        StorageDead(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:48:21: 48:22
-        StorageDead(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:21
-        return;                          // scope 0 at $DIR/lower_intrinsics.rs:+2:2: +2:2
-    }
-}
diff --git a/src/test/mir-opt/lower_intrinsics.f_unit.PreCodegen.before.mir b/src/test/mir-opt/lower_intrinsics.f_unit.PreCodegen.before.mir
deleted file mode 100644 (file)
index 5783822..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-// MIR for `f_unit` before PreCodegen
-
-fn f_unit() -> () {
-    let mut _0: ();                      // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:17: +0:17
-    let mut _1: ();                      // in scope 0 at $DIR/lower_intrinsics.rs:+1:16: +1:18
-    scope 1 (inlined f_dispatch::<()>) { // at $DIR/lower_intrinsics.rs:34:5: 34:19
-        debug t => _1;                   // in scope 1 at $DIR/lower_intrinsics.rs:44:22: 44:23
-        let _2: ();                      // in scope 1 at $DIR/lower_intrinsics.rs:46:9: 46:17
-        let mut _3: ();                  // in scope 1 at $DIR/lower_intrinsics.rs:46:15: 46:16
-        scope 2 (inlined std::mem::size_of::<()>) { // at $DIR/lower_intrinsics.rs:45:8: 45:32
-        }
-    }
-
-    bb0: {
-        StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:16: +1:18
-        StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:46:9: 46:17
-        StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:46:15: 46:16
-        _2 = f_zst::<()>(move _3) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:46:9: 46:17
-                                         // mir::Constant
-                                         // + span: $DIR/lower_intrinsics.rs:46:9: 46:14
-                                         // + literal: Const { ty: fn(()) {f_zst::<()>}, val: Value(<ZST>) }
-    }
-
-    bb1: {
-        StorageDead(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:46:16: 46:17
-        StorageDead(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:46:17: 46:18
-        StorageDead(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:18: +1:19
-        return;                          // scope 0 at $DIR/lower_intrinsics.rs:+2:2: +2:2
-    }
-}
index e6a2f6512f55af51df45fa5cc4b7a7ae8ece4190..4cbbc02c94333514a9091517956216b63945092f 100644 (file)
@@ -11,7 +11,7 @@
           _2 = move _1;                    // scope 0 at $DIR/lower_intrinsics.rs:+1:30: +1:31
 -         _0 = std::intrinsics::forget::<T>(move _2) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:32
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:24:5: 24:29
+-                                          // + span: $DIR/lower_intrinsics.rs:26:5: 26:29
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn(T) {std::intrinsics::forget::<T>}, val: Value(<ZST>) }
 +         _0 = const ();                   // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:32
 +         goto -> bb1;                     // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:32
index 1ab2f2a0a046828c32577c7ce3721661dfa879bd..d8cd5f59a3532fa0bcf496c6502ecae349ddbaa6 100644 (file)
@@ -13,7 +13,7 @@
           StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+2:9: +2:18
           _1 = std::intrinsics::size_of::<T>; // scope 0 at $DIR/lower_intrinsics.rs:+2:21: +2:51
                                            // mir::Constant
-                                           // + span: $DIR/lower_intrinsics.rs:62:21: 62:51
+                                           // + span: $DIR/lower_intrinsics.rs:37:21: 37:51
                                            // + literal: Const { ty: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::<T>}, val: Value(<ZST>) }
           StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:+3:5: +3:14
           _2 = _1;                         // scope 1 at $DIR/lower_intrinsics.rs:+3:5: +3:14
index eab51b65f1a19a6e868dbe6b4c24221a5d7b917e..195543d42bb5ba157b8a46c5d2b5fed5c1a96a13 100644 (file)
@@ -1,4 +1,6 @@
-// compile-flags: -Cpanic=abort
+// unit-test: LowerIntrinsics
+// ignore-wasm32 compiled with panic=abort by default
+
 #![feature(core_intrinsics)]
 #![crate_type = "lib"]
 
@@ -29,33 +31,6 @@ pub fn unreachable() -> ! {
     unsafe { core::intrinsics::unreachable() };
 }
 
-// EMIT_MIR lower_intrinsics.f_unit.PreCodegen.before.mir
-pub fn f_unit() {
-    f_dispatch(());
-}
-
-
-// EMIT_MIR lower_intrinsics.f_u64.PreCodegen.before.mir
-pub fn f_u64() {
-    f_dispatch(0u64);
-}
-
-#[inline(always)]
-pub fn f_dispatch<T>(t: T) {
-    if std::mem::size_of::<T>() == 0 {
-        f_zst(t);
-    } else {
-        f_non_zst(t);
-    }
-}
-
-#[inline(never)]
-pub fn f_zst<T>(_t: T) {
-}
-
-#[inline(never)]
-pub fn f_non_zst<T>(_t: T) {}
-
 // EMIT_MIR lower_intrinsics.non_const.LowerIntrinsics.diff
 pub fn non_const<T>() -> usize {
     // Check that lowering works with non-const operand as a func.
index 11b27976b551c9f171e11cbe7f9b0a0edb3ce07f..cf0ab73a5d4b1786b0eceb29f70859da81eef00d 100644 (file)
@@ -7,7 +7,7 @@
       bb0: {
 -         _0 = std::intrinsics::size_of::<T>() -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:37
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:14:5: 14:35
+-                                          // + span: $DIR/lower_intrinsics.rs:16:5: 16:35
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::<T>}, val: Value(<ZST>) }
 +         _0 = SizeOf(T);                  // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:37
 +         goto -> bb1;                     // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:37
index ac077e85b04f357a3ed5eab40a6182c2ec3e63b9..6f17d44516de194475d6f93250ee6b42443a22d5 100644 (file)
@@ -14,7 +14,7 @@
           StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:45
 -         _3 = std::intrinsics::unreachable(); // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:45
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:29:14: 29:43
+-                                          // + span: $DIR/lower_intrinsics.rs:31:14: 31:43
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn() -> ! {std::intrinsics::unreachable}, val: Value(<ZST>) }
 +         unreachable;                     // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:45
       }
index e0a5416b22b5fbe431578dadf506d8c7fab940c9..22ef75fd8046089c57c566a5705ac77d91166ac9 100644 (file)
@@ -32,7 +32,7 @@
           _5 = _2;                         // scope 0 at $DIR/lower_intrinsics.rs:+1:48: +1:49
 -         _3 = wrapping_add::<i32>(move _4, move _5) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:50
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:7:14: 7:44
+-                                          // + span: $DIR/lower_intrinsics.rs:9:14: 9:44
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> i32 {wrapping_add::<i32>}, val: Value(<ZST>) }
 +         _3 = Add(move _4, move _5);      // scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:50
 +         goto -> bb1;                     // scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:50
@@ -48,7 +48,7 @@
           _8 = _2;                         // scope 1 at $DIR/lower_intrinsics.rs:+2:48: +2:49
 -         _6 = wrapping_sub::<i32>(move _7, move _8) -> bb2; // scope 1 at $DIR/lower_intrinsics.rs:+2:14: +2:50
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:8:14: 8:44
+-                                          // + span: $DIR/lower_intrinsics.rs:10:14: 10:44
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> i32 {wrapping_sub::<i32>}, val: Value(<ZST>) }
 +         _6 = Sub(move _7, move _8);      // scope 1 at $DIR/lower_intrinsics.rs:+2:14: +2:50
 +         goto -> bb2;                     // scope 1 at $DIR/lower_intrinsics.rs:+2:14: +2:50
@@ -64,7 +64,7 @@
           _11 = _2;                        // scope 2 at $DIR/lower_intrinsics.rs:+3:48: +3:49
 -         _9 = wrapping_mul::<i32>(move _10, move _11) -> bb3; // scope 2 at $DIR/lower_intrinsics.rs:+3:14: +3:50
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:9:14: 9:44
+-                                          // + span: $DIR/lower_intrinsics.rs:11:14: 11:44
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> i32 {wrapping_mul::<i32>}, val: Value(<ZST>) }
 +         _9 = Mul(move _10, move _11);    // scope 2 at $DIR/lower_intrinsics.rs:+3:14: +3:50
 +         goto -> bb3;                     // scope 2 at $DIR/lower_intrinsics.rs:+3:14: +3:50
diff --git a/src/test/mir-opt/lower_intrinsics_e2e.f_u64.PreCodegen.after.mir b/src/test/mir-opt/lower_intrinsics_e2e.f_u64.PreCodegen.after.mir
new file mode 100644 (file)
index 0000000..8e18532
--- /dev/null
@@ -0,0 +1,32 @@
+// MIR for `f_u64` after PreCodegen
+
+fn f_u64() -> () {
+    let mut _0: ();                      // return place in scope 0 at $DIR/lower_intrinsics_e2e.rs:+0:16: +0:16
+    let mut _1: u64;                     // in scope 0 at $DIR/lower_intrinsics_e2e.rs:+1:5: +1:21
+    scope 1 (inlined f_dispatch::<u64>) { // at $DIR/lower_intrinsics_e2e.rs:15:5: 15:21
+        debug t => _1;                   // in scope 1 at $DIR/lower_intrinsics_e2e.rs:19:22: 19:23
+        let _2: ();                      // in scope 1 at $DIR/lower_intrinsics_e2e.rs:23:9: 23:21
+        let mut _3: u64;                 // in scope 1 at $DIR/lower_intrinsics_e2e.rs:23:19: 23:20
+        scope 2 (inlined std::mem::size_of::<u64>) { // at $DIR/lower_intrinsics_e2e.rs:20:8: 20:32
+        }
+    }
+
+    bb0: {
+        StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics_e2e.rs:+1:5: +1:21
+        _1 = const 0_u64;                // scope 0 at $DIR/lower_intrinsics_e2e.rs:+1:5: +1:21
+        StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics_e2e.rs:23:9: 23:21
+        StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics_e2e.rs:23:19: 23:20
+        _3 = move _1;                    // scope 1 at $DIR/lower_intrinsics_e2e.rs:23:19: 23:20
+        _2 = f_non_zst::<u64>(move _3) -> bb1; // scope 1 at $DIR/lower_intrinsics_e2e.rs:23:9: 23:21
+                                         // mir::Constant
+                                         // + span: $DIR/lower_intrinsics_e2e.rs:23:9: 23:18
+                                         // + literal: Const { ty: fn(u64) {f_non_zst::<u64>}, val: Value(<ZST>) }
+    }
+
+    bb1: {
+        StorageDead(_3);                 // scope 1 at $DIR/lower_intrinsics_e2e.rs:23:20: 23:21
+        StorageDead(_2);                 // scope 1 at $DIR/lower_intrinsics_e2e.rs:23:21: 23:22
+        StorageDead(_1);                 // scope 0 at $DIR/lower_intrinsics_e2e.rs:+1:5: +1:21
+        return;                          // scope 0 at $DIR/lower_intrinsics_e2e.rs:+2:2: +2:2
+    }
+}
diff --git a/src/test/mir-opt/lower_intrinsics_e2e.f_unit.PreCodegen.after.mir b/src/test/mir-opt/lower_intrinsics_e2e.f_unit.PreCodegen.after.mir
new file mode 100644 (file)
index 0000000..a5b396c
--- /dev/null
@@ -0,0 +1,30 @@
+// MIR for `f_unit` after PreCodegen
+
+fn f_unit() -> () {
+    let mut _0: ();                      // return place in scope 0 at $DIR/lower_intrinsics_e2e.rs:+0:17: +0:17
+    let mut _1: ();                      // in scope 0 at $DIR/lower_intrinsics_e2e.rs:+1:16: +1:18
+    scope 1 (inlined f_dispatch::<()>) { // at $DIR/lower_intrinsics_e2e.rs:9:5: 9:19
+        debug t => _1;                   // in scope 1 at $DIR/lower_intrinsics_e2e.rs:19:22: 19:23
+        let _2: ();                      // in scope 1 at $DIR/lower_intrinsics_e2e.rs:21:9: 21:17
+        let mut _3: ();                  // in scope 1 at $DIR/lower_intrinsics_e2e.rs:21:15: 21:16
+        scope 2 (inlined std::mem::size_of::<()>) { // at $DIR/lower_intrinsics_e2e.rs:20:8: 20:32
+        }
+    }
+
+    bb0: {
+        StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics_e2e.rs:+1:16: +1:18
+        StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics_e2e.rs:21:9: 21:17
+        StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics_e2e.rs:21:15: 21:16
+        _2 = f_zst::<()>(move _3) -> bb1; // scope 1 at $DIR/lower_intrinsics_e2e.rs:21:9: 21:17
+                                         // mir::Constant
+                                         // + span: $DIR/lower_intrinsics_e2e.rs:21:9: 21:14
+                                         // + literal: Const { ty: fn(()) {f_zst::<()>}, val: Value(<ZST>) }
+    }
+
+    bb1: {
+        StorageDead(_3);                 // scope 1 at $DIR/lower_intrinsics_e2e.rs:21:16: 21:17
+        StorageDead(_2);                 // scope 1 at $DIR/lower_intrinsics_e2e.rs:21:17: 21:18
+        StorageDead(_1);                 // scope 0 at $DIR/lower_intrinsics_e2e.rs:+1:18: +1:19
+        return;                          // scope 0 at $DIR/lower_intrinsics_e2e.rs:+2:2: +2:2
+    }
+}
diff --git a/src/test/mir-opt/lower_intrinsics_e2e.rs b/src/test/mir-opt/lower_intrinsics_e2e.rs
new file mode 100644 (file)
index 0000000..872ef59
--- /dev/null
@@ -0,0 +1,32 @@
+// Checks that we do not have any branches in the MIR for the two tested functions.
+
+// compile-flags: -Cpanic=abort
+#![feature(core_intrinsics)]
+#![crate_type = "lib"]
+
+// EMIT_MIR lower_intrinsics_e2e.f_unit.PreCodegen.after.mir
+pub fn f_unit() {
+    f_dispatch(());
+}
+
+
+// EMIT_MIR lower_intrinsics_e2e.f_u64.PreCodegen.after.mir
+pub fn f_u64() {
+    f_dispatch(0u64);
+}
+
+#[inline(always)]
+pub fn f_dispatch<T>(t: T) {
+    if std::mem::size_of::<T>() == 0 {
+        f_zst(t);
+    } else {
+        f_non_zst(t);
+    }
+}
+
+#[inline(never)]
+pub fn f_zst<T>(_t: T) {
+}
+
+#[inline(never)]
+pub fn f_non_zst<T>(_t: T) {}
index 2005c10efa93bf6700cae844553ddd21159e9fef..f9eeb1ea5b96095be840b3afd1c193409cdb55ba 100644 (file)
@@ -41,7 +41,7 @@
 -         _3 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:+16:13: +16:22
 -         _4 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:+17:13: +17:22
 -         _5 = const true;                 // scope 4 at $DIR/matches_reduce_branches.rs:+18:13: +18:21
--         nop;                             // scope 4 at $DIR/matches_reduce_branches.rs:+19:13: +19:15
+-         Deinit(_6);                      // scope 4 at $DIR/matches_reduce_branches.rs:+19:13: +19:15
 -         goto -> bb3;                     // scope 4 at $DIR/matches_reduce_branches.rs:+19:13: +19:15
 -     }
 - 
@@ -54,7 +54,7 @@
 +         _3 = Eq(_11, const 7_i32);       // scope 4 at $DIR/matches_reduce_branches.rs:+9:13: +9:21
           _4 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:+10:13: +10:22
           _5 = const true;                 // scope 4 at $DIR/matches_reduce_branches.rs:+11:13: +11:21
--         nop;                             // scope 4 at $DIR/matches_reduce_branches.rs:+12:13: +12:15
+          Deinit(_6);                      // scope 4 at $DIR/matches_reduce_branches.rs:+12:13: +12:15
 -         goto -> bb3;                     // scope 4 at $DIR/matches_reduce_branches.rs:+12:13: +12:15
 -     }
 - 
index 2005c10efa93bf6700cae844553ddd21159e9fef..f9eeb1ea5b96095be840b3afd1c193409cdb55ba 100644 (file)
@@ -41,7 +41,7 @@
 -         _3 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:+16:13: +16:22
 -         _4 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:+17:13: +17:22
 -         _5 = const true;                 // scope 4 at $DIR/matches_reduce_branches.rs:+18:13: +18:21
--         nop;                             // scope 4 at $DIR/matches_reduce_branches.rs:+19:13: +19:15
+-         Deinit(_6);                      // scope 4 at $DIR/matches_reduce_branches.rs:+19:13: +19:15
 -         goto -> bb3;                     // scope 4 at $DIR/matches_reduce_branches.rs:+19:13: +19:15
 -     }
 - 
@@ -54,7 +54,7 @@
 +         _3 = Eq(_11, const 7_i32);       // scope 4 at $DIR/matches_reduce_branches.rs:+9:13: +9:21
           _4 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:+10:13: +10:22
           _5 = const true;                 // scope 4 at $DIR/matches_reduce_branches.rs:+11:13: +11:21
--         nop;                             // scope 4 at $DIR/matches_reduce_branches.rs:+12:13: +12:15
+          Deinit(_6);                      // scope 4 at $DIR/matches_reduce_branches.rs:+12:13: +12:15
 -         goto -> bb3;                     // scope 4 at $DIR/matches_reduce_branches.rs:+12:13: +12:15
 -     }
 - 
index b7862e5678f23598d3ba2afb8b144d73309b0cdb..0b40b3be8bdd41efd5e773ab32228a05b64f394c 100644 (file)
@@ -4,26 +4,51 @@
   fn foo(_1: Option<()>) -> () {
       debug bar => _1;                     // in scope 0 at $DIR/matches_reduce_branches.rs:+0:8: +0:11
       let mut _0: ();                      // return place in scope 0 at $DIR/matches_reduce_branches.rs:+0:25: +0:25
-      let mut _2: isize;                   // in scope 0 at $DIR/matches_reduce_branches.rs:+1:22: +1:26
-+     let mut _3: isize;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _2: bool;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _3: isize;                   // in scope 0 at $DIR/matches_reduce_branches.rs:+1:22: +1:26
++     let mut _4: isize;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
   
       bb0: {
-          _2 = discriminant(_1);           // scope 0 at $DIR/matches_reduce_branches.rs:+1:17: +1:20
--         switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
--     }
-- 
--     bb1: {
+          StorageLive(_2);                 // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _3 = discriminant(_1);           // scope 0 at $DIR/matches_reduce_branches.rs:+1:17: +1:20
+-         switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++         StorageLive(_4);                 // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++         _4 = move _3;                    // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++         _2 = Eq(_4, const 0_isize);      // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++         StorageDead(_4);                 // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++         switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      }
+  
+      bb1: {
+-         _2 = const false;                // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
 -         goto -> bb3;                     // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
 -     }
 - 
 -     bb2: {
+-         _2 = const true;                 // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
 -         goto -> bb3;                     // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
 -     }
 - 
 -     bb3: {
-+         StorageLive(_3);                 // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-+         _3 = move _2;                    // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-+         StorageDead(_3);                 // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+-         switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+-     }
+- 
+-     bb4: {
+          Deinit(_0);                      // scope 0 at $DIR/matches_reduce_branches.rs:+2:9: +2:11
+-         goto -> bb6;                     // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6
++         goto -> bb3;                     // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6
+      }
+  
+-     bb5: {
++     bb2: {
+          _0 = const ();                   // scope 0 at $DIR/matches_reduce_branches.rs:+3:6: +3:6
+-         goto -> bb6;                     // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6
++         goto -> bb3;                     // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6
+      }
+  
+-     bb6: {
++     bb3: {
+          StorageDead(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:+3:5: +3:6
           return;                          // scope 0 at $DIR/matches_reduce_branches.rs:+4:2: +4:2
       }
   }
index b7862e5678f23598d3ba2afb8b144d73309b0cdb..0b40b3be8bdd41efd5e773ab32228a05b64f394c 100644 (file)
@@ -4,26 +4,51 @@
   fn foo(_1: Option<()>) -> () {
       debug bar => _1;                     // in scope 0 at $DIR/matches_reduce_branches.rs:+0:8: +0:11
       let mut _0: ();                      // return place in scope 0 at $DIR/matches_reduce_branches.rs:+0:25: +0:25
-      let mut _2: isize;                   // in scope 0 at $DIR/matches_reduce_branches.rs:+1:22: +1:26
-+     let mut _3: isize;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _2: bool;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _3: isize;                   // in scope 0 at $DIR/matches_reduce_branches.rs:+1:22: +1:26
++     let mut _4: isize;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
   
       bb0: {
-          _2 = discriminant(_1);           // scope 0 at $DIR/matches_reduce_branches.rs:+1:17: +1:20
--         switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
--     }
-- 
--     bb1: {
+          StorageLive(_2);                 // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _3 = discriminant(_1);           // scope 0 at $DIR/matches_reduce_branches.rs:+1:17: +1:20
+-         switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++         StorageLive(_4);                 // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++         _4 = move _3;                    // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++         _2 = Eq(_4, const 0_isize);      // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++         StorageDead(_4);                 // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++         switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      }
+  
+      bb1: {
+-         _2 = const false;                // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
 -         goto -> bb3;                     // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
 -     }
 - 
 -     bb2: {
+-         _2 = const true;                 // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
 -         goto -> bb3;                     // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
 -     }
 - 
 -     bb3: {
-+         StorageLive(_3);                 // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-+         _3 = move _2;                    // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-+         StorageDead(_3);                 // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+-         switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+-     }
+- 
+-     bb4: {
+          Deinit(_0);                      // scope 0 at $DIR/matches_reduce_branches.rs:+2:9: +2:11
+-         goto -> bb6;                     // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6
++         goto -> bb3;                     // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6
+      }
+  
+-     bb5: {
++     bb2: {
+          _0 = const ();                   // scope 0 at $DIR/matches_reduce_branches.rs:+3:6: +3:6
+-         goto -> bb6;                     // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6
++         goto -> bb3;                     // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6
+      }
+  
+-     bb6: {
++     bb3: {
+          StorageDead(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:+3:5: +3:6
           return;                          // scope 0 at $DIR/matches_reduce_branches.rs:+4:2: +4:2
       }
   }
diff --git a/src/test/mir-opt/matches_reduce_branches.foo.PreCodegen.before.32bit.mir b/src/test/mir-opt/matches_reduce_branches.foo.PreCodegen.before.32bit.mir
deleted file mode 100644 (file)
index a36ec8d..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// MIR for `foo` before PreCodegen
-
-fn foo(_1: Option<()>) -> () {
-    debug bar => _1;                     // in scope 0 at $DIR/matches_reduce_branches.rs:+0:8: +0:11
-    let mut _0: ();                      // return place in scope 0 at $DIR/matches_reduce_branches.rs:+0:25: +0:25
-
-    bb0: {
-        return;                          // scope 0 at $DIR/matches_reduce_branches.rs:+4:2: +4:2
-    }
-}
diff --git a/src/test/mir-opt/matches_reduce_branches.foo.PreCodegen.before.64bit.mir b/src/test/mir-opt/matches_reduce_branches.foo.PreCodegen.before.64bit.mir
deleted file mode 100644 (file)
index a36ec8d..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// MIR for `foo` before PreCodegen
-
-fn foo(_1: Option<()>) -> () {
-    debug bar => _1;                     // in scope 0 at $DIR/matches_reduce_branches.rs:+0:8: +0:11
-    let mut _0: ();                      // return place in scope 0 at $DIR/matches_reduce_branches.rs:+0:25: +0:25
-
-    bb0: {
-        return;                          // scope 0 at $DIR/matches_reduce_branches.rs:+4:2: +4:2
-    }
-}
index 672c6b34e94b612b6c2c5d9f1d933aa56855df17..b8c7722cd3713c905b31331b98b0cc2623594660 100644 (file)
   fn match_nested_if() -> bool {
       let mut _0: bool;                    // return place in scope 0 at $DIR/matches_reduce_branches.rs:+0:25: +0:29
       let _1: bool;                        // in scope 0 at $DIR/matches_reduce_branches.rs:+1:9: +1:12
-      let mut _2: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
-+     let mut _3: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
+      let mut _2: ();                      // in scope 0 at $DIR/matches_reduce_branches.rs:+1:21: +1:23
+      let mut _3: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
+      let mut _4: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
+      let mut _5: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
+      let mut _6: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
++     let mut _7: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
++     let mut _8: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
++     let mut _9: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
++     let mut _10: bool;                   // in scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
       scope 1 {
           debug val => _1;                 // in scope 1 at $DIR/matches_reduce_branches.rs:+1:9: +1:12
       }
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/matches_reduce_branches.rs:+1:9: +1:12
-          StorageLive(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
-          _2 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
--         switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
+          StorageLive(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:+1:21: +1:23
+          Deinit(_2);                      // scope 0 at $DIR/matches_reduce_branches.rs:+1:21: +1:23
+          StorageLive(_3);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
+          StorageLive(_4);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
+          StorageLive(_5);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
+          StorageLive(_6);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
+          _6 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
+-         switchInt(move _6) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
 -     }
 - 
 -     bb1: {
-+         StorageLive(_3);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
-+         _3 = move _2;                    // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
-          StorageDead(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:51: +2:52
--         _1 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:+8:13: +8:17
--         goto -> bb3;                     // scope 0 at $DIR/matches_reduce_branches.rs:+8:13: +8:17
+-         _5 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:31: +2:35
+-         goto -> bb3;                     // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
 -     }
 - 
 -     bb2: {
--         StorageDead(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:51: +2:52
--         _1 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19
--         goto -> bb3;                     // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19
+-         _5 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:+2:45: +2:50
+-         goto -> bb3;                     // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
 -     }
 - 
 -     bb3: {
-+         _1 = Ne(_3, const false);        // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19
-+         StorageDead(_3);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
++         StorageLive(_7);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
++         _7 = move _6;                    // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
++         _5 = Ne(_7, const false);        // scope 0 at $DIR/matches_reduce_branches.rs:+2:45: +2:50
++         StorageDead(_7);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
+          StorageDead(_6);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:51: +2:52
+-         switchInt(move _5) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
+-     }
+- 
+-     bb4: {
+-         _4 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:55: +2:59
+-         goto -> bb6;                     // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
+-     }
+- 
+-     bb5: {
+-         _4 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:+2:69: +2:74
+-         goto -> bb6;                     // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
+-     }
+- 
+-     bb6: {
++         StorageLive(_8);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
++         _8 = move _5;                    // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
++         _4 = Ne(_8, const false);        // scope 0 at $DIR/matches_reduce_branches.rs:+2:69: +2:74
++         StorageDead(_8);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
+          StorageDead(_5);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:75: +2:76
+-         switchInt(move _4) -> [false: bb8, otherwise: bb7]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
+-     }
+- 
+-     bb7: {
+-         _3 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:+3:13: +3:17
+-         goto -> bb9;                     // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
+-     }
+- 
+-     bb8: {
+-         _3 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:+5:13: +5:18
+-         goto -> bb9;                     // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
+-     }
+- 
+-     bb9: {
+-         switchInt(move _3) -> [false: bb11, otherwise: bb10]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
+-     }
+- 
+-     bb10: {
++         StorageLive(_9);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
++         _9 = move _4;                    // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
++         _3 = Ne(_9, const false);        // scope 0 at $DIR/matches_reduce_branches.rs:+5:13: +5:18
++         StorageDead(_9);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
++         StorageLive(_10);                // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
++         _10 = move _3;                   // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
+          StorageDead(_4);                 // scope 0 at $DIR/matches_reduce_branches.rs:+6:9: +6:10
+          StorageDead(_3);                 // scope 0 at $DIR/matches_reduce_branches.rs:+6:9: +6:10
+-         _1 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:+8:13: +8:17
+-         goto -> bb12;                    // scope 0 at $DIR/matches_reduce_branches.rs:+8:13: +8:17
+-     }
+- 
+-     bb11: {
+-         StorageDead(_4);                 // scope 0 at $DIR/matches_reduce_branches.rs:+6:9: +6:10
+-         StorageDead(_3);                 // scope 0 at $DIR/matches_reduce_branches.rs:+6:9: +6:10
+-         _1 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19
+-         goto -> bb12;                    // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19
+-     }
+- 
+-     bb12: {
++         _1 = Ne(_10, const false);       // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19
++         StorageDead(_10);                // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
+          StorageDead(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:+11:6: +11:7
           _0 = _1;                         // scope 1 at $DIR/matches_reduce_branches.rs:+12:5: +12:8
           StorageDead(_1);                 // scope 0 at $DIR/matches_reduce_branches.rs:+13:1: +13:2
           return;                          // scope 0 at $DIR/matches_reduce_branches.rs:+13:2: +13:2
index 672c6b34e94b612b6c2c5d9f1d933aa56855df17..b8c7722cd3713c905b31331b98b0cc2623594660 100644 (file)
   fn match_nested_if() -> bool {
       let mut _0: bool;                    // return place in scope 0 at $DIR/matches_reduce_branches.rs:+0:25: +0:29
       let _1: bool;                        // in scope 0 at $DIR/matches_reduce_branches.rs:+1:9: +1:12
-      let mut _2: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
-+     let mut _3: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
+      let mut _2: ();                      // in scope 0 at $DIR/matches_reduce_branches.rs:+1:21: +1:23
+      let mut _3: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
+      let mut _4: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
+      let mut _5: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
+      let mut _6: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
++     let mut _7: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
++     let mut _8: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
++     let mut _9: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
++     let mut _10: bool;                   // in scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
       scope 1 {
           debug val => _1;                 // in scope 1 at $DIR/matches_reduce_branches.rs:+1:9: +1:12
       }
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/matches_reduce_branches.rs:+1:9: +1:12
-          StorageLive(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
-          _2 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
--         switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
+          StorageLive(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:+1:21: +1:23
+          Deinit(_2);                      // scope 0 at $DIR/matches_reduce_branches.rs:+1:21: +1:23
+          StorageLive(_3);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
+          StorageLive(_4);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
+          StorageLive(_5);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
+          StorageLive(_6);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
+          _6 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
+-         switchInt(move _6) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
 -     }
 - 
 -     bb1: {
-+         StorageLive(_3);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
-+         _3 = move _2;                    // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
-          StorageDead(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:51: +2:52
--         _1 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:+8:13: +8:17
--         goto -> bb3;                     // scope 0 at $DIR/matches_reduce_branches.rs:+8:13: +8:17
+-         _5 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:31: +2:35
+-         goto -> bb3;                     // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
 -     }
 - 
 -     bb2: {
--         StorageDead(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:51: +2:52
--         _1 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19
--         goto -> bb3;                     // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19
+-         _5 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:+2:45: +2:50
+-         goto -> bb3;                     // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
 -     }
 - 
 -     bb3: {
-+         _1 = Ne(_3, const false);        // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19
-+         StorageDead(_3);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
++         StorageLive(_7);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
++         _7 = move _6;                    // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
++         _5 = Ne(_7, const false);        // scope 0 at $DIR/matches_reduce_branches.rs:+2:45: +2:50
++         StorageDead(_7);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
+          StorageDead(_6);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:51: +2:52
+-         switchInt(move _5) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
+-     }
+- 
+-     bb4: {
+-         _4 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:55: +2:59
+-         goto -> bb6;                     // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
+-     }
+- 
+-     bb5: {
+-         _4 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:+2:69: +2:74
+-         goto -> bb6;                     // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
+-     }
+- 
+-     bb6: {
++         StorageLive(_8);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
++         _8 = move _5;                    // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
++         _4 = Ne(_8, const false);        // scope 0 at $DIR/matches_reduce_branches.rs:+2:69: +2:74
++         StorageDead(_8);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
+          StorageDead(_5);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:75: +2:76
+-         switchInt(move _4) -> [false: bb8, otherwise: bb7]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
+-     }
+- 
+-     bb7: {
+-         _3 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:+3:13: +3:17
+-         goto -> bb9;                     // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
+-     }
+- 
+-     bb8: {
+-         _3 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:+5:13: +5:18
+-         goto -> bb9;                     // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
+-     }
+- 
+-     bb9: {
+-         switchInt(move _3) -> [false: bb11, otherwise: bb10]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
+-     }
+- 
+-     bb10: {
++         StorageLive(_9);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
++         _9 = move _4;                    // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
++         _3 = Ne(_9, const false);        // scope 0 at $DIR/matches_reduce_branches.rs:+5:13: +5:18
++         StorageDead(_9);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
++         StorageLive(_10);                // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
++         _10 = move _3;                   // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
+          StorageDead(_4);                 // scope 0 at $DIR/matches_reduce_branches.rs:+6:9: +6:10
+          StorageDead(_3);                 // scope 0 at $DIR/matches_reduce_branches.rs:+6:9: +6:10
+-         _1 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:+8:13: +8:17
+-         goto -> bb12;                    // scope 0 at $DIR/matches_reduce_branches.rs:+8:13: +8:17
+-     }
+- 
+-     bb11: {
+-         StorageDead(_4);                 // scope 0 at $DIR/matches_reduce_branches.rs:+6:9: +6:10
+-         StorageDead(_3);                 // scope 0 at $DIR/matches_reduce_branches.rs:+6:9: +6:10
+-         _1 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19
+-         goto -> bb12;                    // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19
+-     }
+- 
+-     bb12: {
++         _1 = Ne(_10, const false);       // scope 0 at $DIR/matches_reduce_branches.rs:+10:14: +10:19
++         StorageDead(_10);                // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
+          StorageDead(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:+11:6: +11:7
           _0 = _1;                         // scope 1 at $DIR/matches_reduce_branches.rs:+12:5: +12:8
           StorageDead(_1);                 // scope 0 at $DIR/matches_reduce_branches.rs:+13:1: +13:2
           return;                          // scope 0 at $DIR/matches_reduce_branches.rs:+13:2: +13:2
index 51be3884d48dd27b7a8f86d586a10bba0de5209b..c122b4c69d15a1a8f17411371eec649a526e8e05 100644 (file)
@@ -1,6 +1,7 @@
+// unit-test: MatchBranchSimplification
+
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
 // EMIT_MIR matches_reduce_branches.foo.MatchBranchSimplification.diff
-// EMIT_MIR matches_reduce_branches.foo.PreCodegen.before.mir
 // EMIT_MIR matches_reduce_branches.bar.MatchBranchSimplification.diff
 // EMIT_MIR matches_reduce_branches.match_nested_if.MatchBranchSimplification.diff
 
index 78373be48b6854d5efdbb6cf5ef0c85881eb677d..2c748b02a8b76711fc937d7447016410a440644d 100644 (file)
@@ -1,3 +1,5 @@
+// unit-test: MatchBranchSimplification
+
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
 // EMIT_MIR matches_u8.exhaustive_match.MatchBranchSimplification.diff
 // EMIT_MIR matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff
index b8c554d3ea6b02818cb2b26c179b21531e089f07..f25b3ce724be2db89b3f95fff98746d059aaaa80 100644 (file)
@@ -15,7 +15,7 @@
       scope 1 {
           debug residual => _6;            // in scope 1 at $DIR/separate_const_switch.rs:+1:9: +1:10
           scope 2 {
-              scope 8 (inlined #[track_caller] <Result<i32, i32> as FromResidual<Result<Infallible, i32>>>::from_residual) { // at $DIR/separate_const_switch.rs:29:8: 29:10
+              scope 8 (inlined #[track_caller] <Result<i32, i32> as FromResidual<Result<Infallible, i32>>>::from_residual) { // at $DIR/separate_const_switch.rs:25:8: 25:10
                   debug residual => _8;    // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
                   let _16: i32;            // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
                   let mut _17: i32;        // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
@@ -34,7 +34,7 @@
           scope 4 {
           }
       }
-      scope 5 (inlined <Result<i32, i32> as Try>::branch) { // at $DIR/separate_const_switch.rs:29:8: 29:10
+      scope 5 (inlined <Result<i32, i32> as Try>::branch) { // at $DIR/separate_const_switch.rs:25:8: 25:10
           debug self => _4;                // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
           let mut _10: isize;              // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
           let _11: i32;                    // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
index 5d82acf4d60905259414f168367a26ac7b818044..c809e5629cc152b4c02cd0b92efb6d138bc5c127 100644 (file)
@@ -4,8 +4,6 @@
 use std::ops::ControlFlow;
 
 // EMIT_MIR separate_const_switch.too_complex.SeparateConstSwitch.diff
-// EMIT_MIR separate_const_switch.too_complex.ConstProp.diff
-// EMIT_MIR separate_const_switch.too_complex.PreCodegen.after.mir
 fn too_complex(x: Result<i32, usize>) -> Option<i32> {
     // The pass should break the outer match into
     // two blocks that only have one parent each.
@@ -23,8 +21,6 @@ fn too_complex(x: Result<i32, usize>) -> Option<i32> {
 }
 
 // EMIT_MIR separate_const_switch.identity.SeparateConstSwitch.diff
-// EMIT_MIR separate_const_switch.identity.ConstProp.diff
-// EMIT_MIR separate_const_switch.identity.PreCodegen.after.mir
 fn identity(x: Result<i32, i32>) -> Result<i32, i32> {
     Ok(x?)
 }
index bedc86bbacb8c67fbe2d3b965e0e20a7fcad2ed5..cf6ff57aa96deef66017ce5bbde5f94fe420f23e 100644 (file)
@@ -4,6 +4,9 @@
 // compile-flags: -Zmir-opt-level=3
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
 
+// This pass is broken since deaggregation changed
+// ignore-test
+
 enum Src {
     Foo(u8),
     Bar,
index f7dcaa13449eac88c17898376922e5975859a142..c247872e2af46fb4bad904d0185a647a5559ea57 100644 (file)
@@ -6,6 +6,9 @@
 // EMIT_MIR simplify_arm.id_try.SimplifyArmIdentity.diff
 // EMIT_MIR simplify_arm.id_try.SimplifyBranchSame.diff
 
+// This pass is broken since deaggregation changed
+// ignore-test
+
 fn id(o: Option<u8>) -> Option<u8> {
     match o {
         Some(v) => Some(v),
index 84f57deccf7e0fa810dbe1039d5e2da91b1b9cc7..62a15df04b14429940d05a89f1711268caa43dc2 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -Zunsound-mir-opts
+// unit-test: SimplifyLocals
 
 fn map(x: Option<Box<()>>) -> Option<Box<()>> {
     match x {
diff --git a/src/test/mir-opt/simplify_arm.id.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify_arm.id.SimplifyArmIdentity.diff
deleted file mode 100644 (file)
index 9c3ad4b..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-- // MIR for `id` before SimplifyArmIdentity
-+ // MIR for `id` after SimplifyArmIdentity
-  
-  fn id(_1: Option<u8>) -> Option<u8> {
-      debug o => _1;                       // in scope 0 at $DIR/simplify-arm.rs:+0:7: +0:8
-      let mut _0: std::option::Option<u8>; // return place in scope 0 at $DIR/simplify-arm.rs:+0:25: +0:35
-      let mut _2: isize;                   // in scope 0 at $DIR/simplify-arm.rs:+2:9: +2:16
-      let _3: u8;                          // in scope 0 at $DIR/simplify-arm.rs:+2:14: +2:15
-      let mut _4: u8;                      // in scope 0 at $DIR/simplify-arm.rs:+2:25: +2:26
-      scope 1 {
-          debug v => _3;                   // in scope 1 at $DIR/simplify-arm.rs:+2:14: +2:15
-      }
-  
-      bb0: {
-          _2 = discriminant(_1);           // scope 0 at $DIR/simplify-arm.rs:+1:11: +1:12
-          switchInt(move _2) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:+1:5: +1:12
-      }
-  
-      bb1: {
-          Deinit(_0);                      // scope 0 at $DIR/simplify-arm.rs:+3:17: +3:21
-          discriminant(_0) = 0;            // scope 0 at $DIR/simplify-arm.rs:+3:17: +3:21
-          goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:+3:17: +3:21
-      }
-  
-      bb2: {
-          unreachable;                     // scope 0 at $DIR/simplify-arm.rs:+1:11: +1:12
-      }
-  
-      bb3: {
-          StorageLive(_3);                 // scope 0 at $DIR/simplify-arm.rs:+2:14: +2:15
-          _3 = ((_1 as Some).0: u8);       // scope 0 at $DIR/simplify-arm.rs:+2:14: +2:15
-          StorageLive(_4);                 // scope 1 at $DIR/simplify-arm.rs:+2:25: +2:26
-          _4 = _3;                         // scope 1 at $DIR/simplify-arm.rs:+2:25: +2:26
-          Deinit(_0);                      // scope 1 at $DIR/simplify-arm.rs:+2:20: +2:27
-          ((_0 as Some).0: u8) = move _4;  // scope 1 at $DIR/simplify-arm.rs:+2:20: +2:27
-          discriminant(_0) = 1;            // scope 1 at $DIR/simplify-arm.rs:+2:20: +2:27
-          StorageDead(_4);                 // scope 1 at $DIR/simplify-arm.rs:+2:26: +2:27
-          StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:+2:26: +2:27
-          goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:+2:26: +2:27
-      }
-  
-      bb4: {
-          return;                          // scope 0 at $DIR/simplify-arm.rs:+5:2: +5:2
-      }
-  }
-  
diff --git a/src/test/mir-opt/simplify_arm.id.SimplifyBranchSame.diff b/src/test/mir-opt/simplify_arm.id.SimplifyBranchSame.diff
deleted file mode 100644 (file)
index 7b3a699..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-- // MIR for `id` before SimplifyBranchSame
-+ // MIR for `id` after SimplifyBranchSame
-  
-  fn id(_1: Option<u8>) -> Option<u8> {
-      debug o => _1;                       // in scope 0 at $DIR/simplify-arm.rs:+0:7: +0:8
-      let mut _0: std::option::Option<u8>; // return place in scope 0 at $DIR/simplify-arm.rs:+0:25: +0:35
-      let mut _2: isize;                   // in scope 0 at $DIR/simplify-arm.rs:+2:9: +2:16
-      let _3: u8;                          // in scope 0 at $DIR/simplify-arm.rs:+2:14: +2:15
-      let mut _4: u8;                      // in scope 0 at $DIR/simplify-arm.rs:+2:25: +2:26
-      scope 1 {
-          debug v => _3;                   // in scope 1 at $DIR/simplify-arm.rs:+2:14: +2:15
-      }
-  
-      bb0: {
-          _2 = discriminant(_1);           // scope 0 at $DIR/simplify-arm.rs:+1:11: +1:12
-          switchInt(move _2) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:+1:5: +1:12
-      }
-  
-      bb1: {
-          Deinit(_0);                      // scope 0 at $DIR/simplify-arm.rs:+3:17: +3:21
-          discriminant(_0) = 0;            // scope 0 at $DIR/simplify-arm.rs:+3:17: +3:21
-          goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:+3:17: +3:21
-      }
-  
-      bb2: {
-          unreachable;                     // scope 0 at $DIR/simplify-arm.rs:+1:11: +1:12
-      }
-  
-      bb3: {
-          StorageLive(_3);                 // scope 0 at $DIR/simplify-arm.rs:+2:14: +2:15
-          _3 = ((_1 as Some).0: u8);       // scope 0 at $DIR/simplify-arm.rs:+2:14: +2:15
-          StorageLive(_4);                 // scope 1 at $DIR/simplify-arm.rs:+2:25: +2:26
-          _4 = _3;                         // scope 1 at $DIR/simplify-arm.rs:+2:25: +2:26
-          Deinit(_0);                      // scope 1 at $DIR/simplify-arm.rs:+2:20: +2:27
-          ((_0 as Some).0: u8) = move _4;  // scope 1 at $DIR/simplify-arm.rs:+2:20: +2:27
-          discriminant(_0) = 1;            // scope 1 at $DIR/simplify-arm.rs:+2:20: +2:27
-          StorageDead(_4);                 // scope 1 at $DIR/simplify-arm.rs:+2:26: +2:27
-          StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:+2:26: +2:27
-          goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:+2:26: +2:27
-      }
-  
-      bb4: {
-          return;                          // scope 0 at $DIR/simplify-arm.rs:+5:2: +5:2
-      }
-  }
-  
diff --git a/src/test/mir-opt/simplify_arm.id_result.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify_arm.id_result.SimplifyArmIdentity.diff
deleted file mode 100644 (file)
index 31d8453..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-- // MIR for `id_result` before SimplifyArmIdentity
-+ // MIR for `id_result` after SimplifyArmIdentity
-  
-  fn id_result(_1: Result<u8, i32>) -> Result<u8, i32> {
-      debug r => _1;                       // in scope 0 at $DIR/simplify-arm.rs:+0:14: +0:15
-      let mut _0: std::result::Result<u8, i32>; // return place in scope 0 at $DIR/simplify-arm.rs:+0:37: +0:52
-      let mut _2: isize;                   // in scope 0 at $DIR/simplify-arm.rs:+2:9: +2:14
-      let _3: u8;                          // in scope 0 at $DIR/simplify-arm.rs:+2:12: +2:13
-      let mut _4: u8;                      // in scope 0 at $DIR/simplify-arm.rs:+2:21: +2:22
-      let _5: i32;                         // in scope 0 at $DIR/simplify-arm.rs:+3:13: +3:14
-      let mut _6: i32;                     // in scope 0 at $DIR/simplify-arm.rs:+3:23: +3:24
-      scope 1 {
-          debug x => _3;                   // in scope 1 at $DIR/simplify-arm.rs:+2:12: +2:13
-      }
-      scope 2 {
-          debug y => _5;                   // in scope 2 at $DIR/simplify-arm.rs:+3:13: +3:14
-      }
-  
-      bb0: {
-          _2 = discriminant(_1);           // scope 0 at $DIR/simplify-arm.rs:+1:11: +1:12
-          switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:+1:5: +1:12
-      }
-  
-      bb1: {
-          StorageLive(_5);                 // scope 0 at $DIR/simplify-arm.rs:+3:13: +3:14
-          _5 = ((_1 as Err).0: i32);       // scope 0 at $DIR/simplify-arm.rs:+3:13: +3:14
-          StorageLive(_6);                 // scope 2 at $DIR/simplify-arm.rs:+3:23: +3:24
-          _6 = _5;                         // scope 2 at $DIR/simplify-arm.rs:+3:23: +3:24
-          Deinit(_0);                      // scope 2 at $DIR/simplify-arm.rs:+3:19: +3:25
-          ((_0 as Err).0: i32) = move _6;  // scope 2 at $DIR/simplify-arm.rs:+3:19: +3:25
-          discriminant(_0) = 1;            // scope 2 at $DIR/simplify-arm.rs:+3:19: +3:25
-          StorageDead(_6);                 // scope 2 at $DIR/simplify-arm.rs:+3:24: +3:25
-          StorageDead(_5);                 // scope 0 at $DIR/simplify-arm.rs:+3:24: +3:25
-          goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:+3:24: +3:25
-      }
-  
-      bb2: {
-          unreachable;                     // scope 0 at $DIR/simplify-arm.rs:+1:11: +1:12
-      }
-  
-      bb3: {
-          StorageLive(_3);                 // scope 0 at $DIR/simplify-arm.rs:+2:12: +2:13
-          _3 = ((_1 as Ok).0: u8);         // scope 0 at $DIR/simplify-arm.rs:+2:12: +2:13
-          StorageLive(_4);                 // scope 1 at $DIR/simplify-arm.rs:+2:21: +2:22
-          _4 = _3;                         // scope 1 at $DIR/simplify-arm.rs:+2:21: +2:22
-          Deinit(_0);                      // scope 1 at $DIR/simplify-arm.rs:+2:18: +2:23
-          ((_0 as Ok).0: u8) = move _4;    // scope 1 at $DIR/simplify-arm.rs:+2:18: +2:23
-          discriminant(_0) = 0;            // scope 1 at $DIR/simplify-arm.rs:+2:18: +2:23
-          StorageDead(_4);                 // scope 1 at $DIR/simplify-arm.rs:+2:22: +2:23
-          StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:+2:22: +2:23
-          goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:+2:22: +2:23
-      }
-  
-      bb4: {
-          return;                          // scope 0 at $DIR/simplify-arm.rs:+5:2: +5:2
-      }
-  }
-  
diff --git a/src/test/mir-opt/simplify_arm.id_result.SimplifyBranchSame.diff b/src/test/mir-opt/simplify_arm.id_result.SimplifyBranchSame.diff
deleted file mode 100644 (file)
index 3692ebf..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-- // MIR for `id_result` before SimplifyBranchSame
-+ // MIR for `id_result` after SimplifyBranchSame
-  
-  fn id_result(_1: Result<u8, i32>) -> Result<u8, i32> {
-      debug r => _1;                       // in scope 0 at $DIR/simplify-arm.rs:+0:14: +0:15
-      let mut _0: std::result::Result<u8, i32>; // return place in scope 0 at $DIR/simplify-arm.rs:+0:37: +0:52
-      let mut _2: isize;                   // in scope 0 at $DIR/simplify-arm.rs:+2:9: +2:14
-      let _3: u8;                          // in scope 0 at $DIR/simplify-arm.rs:+2:12: +2:13
-      let mut _4: u8;                      // in scope 0 at $DIR/simplify-arm.rs:+2:21: +2:22
-      let _5: i32;                         // in scope 0 at $DIR/simplify-arm.rs:+3:13: +3:14
-      let mut _6: i32;                     // in scope 0 at $DIR/simplify-arm.rs:+3:23: +3:24
-      scope 1 {
-          debug x => _3;                   // in scope 1 at $DIR/simplify-arm.rs:+2:12: +2:13
-      }
-      scope 2 {
-          debug y => _5;                   // in scope 2 at $DIR/simplify-arm.rs:+3:13: +3:14
-      }
-  
-      bb0: {
-          _2 = discriminant(_1);           // scope 0 at $DIR/simplify-arm.rs:+1:11: +1:12
-          switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:+1:5: +1:12
-      }
-  
-      bb1: {
-          StorageLive(_5);                 // scope 0 at $DIR/simplify-arm.rs:+3:13: +3:14
-          _5 = ((_1 as Err).0: i32);       // scope 0 at $DIR/simplify-arm.rs:+3:13: +3:14
-          StorageLive(_6);                 // scope 2 at $DIR/simplify-arm.rs:+3:23: +3:24
-          _6 = _5;                         // scope 2 at $DIR/simplify-arm.rs:+3:23: +3:24
-          Deinit(_0);                      // scope 2 at $DIR/simplify-arm.rs:+3:19: +3:25
-          ((_0 as Err).0: i32) = move _6;  // scope 2 at $DIR/simplify-arm.rs:+3:19: +3:25
-          discriminant(_0) = 1;            // scope 2 at $DIR/simplify-arm.rs:+3:19: +3:25
-          StorageDead(_6);                 // scope 2 at $DIR/simplify-arm.rs:+3:24: +3:25
-          StorageDead(_5);                 // scope 0 at $DIR/simplify-arm.rs:+3:24: +3:25
-          goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:+3:24: +3:25
-      }
-  
-      bb2: {
-          unreachable;                     // scope 0 at $DIR/simplify-arm.rs:+1:11: +1:12
-      }
-  
-      bb3: {
-          StorageLive(_3);                 // scope 0 at $DIR/simplify-arm.rs:+2:12: +2:13
-          _3 = ((_1 as Ok).0: u8);         // scope 0 at $DIR/simplify-arm.rs:+2:12: +2:13
-          StorageLive(_4);                 // scope 1 at $DIR/simplify-arm.rs:+2:21: +2:22
-          _4 = _3;                         // scope 1 at $DIR/simplify-arm.rs:+2:21: +2:22
-          Deinit(_0);                      // scope 1 at $DIR/simplify-arm.rs:+2:18: +2:23
-          ((_0 as Ok).0: u8) = move _4;    // scope 1 at $DIR/simplify-arm.rs:+2:18: +2:23
-          discriminant(_0) = 0;            // scope 1 at $DIR/simplify-arm.rs:+2:18: +2:23
-          StorageDead(_4);                 // scope 1 at $DIR/simplify-arm.rs:+2:22: +2:23
-          StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:+2:22: +2:23
-          goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:+2:22: +2:23
-      }
-  
-      bb4: {
-          return;                          // scope 0 at $DIR/simplify-arm.rs:+5:2: +5:2
-      }
-  }
-  
diff --git a/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.32bit.diff b/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.32bit.diff
deleted file mode 100644 (file)
index 118f5dd..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-- // MIR for `main` before SimplifyArmIdentity
-+ // MIR for `main` after SimplifyArmIdentity
-  
-  fn main() -> () {
-      let mut _0: ();                      // return place in scope 0 at $DIR/simplify-arm-identity.rs:+0:11: +0:11
-      let _1: Src;                         // in scope 0 at $DIR/simplify-arm-identity.rs:+1:9: +1:10
-      let mut _2: Dst;                     // in scope 0 at $DIR/simplify-arm-identity.rs:+2:18: +5:6
-      let mut _3: isize;                   // in scope 0 at $DIR/simplify-arm-identity.rs:+3:9: +3:20
-      let mut _5: u8;                      // in scope 0 at $DIR/simplify-arm-identity.rs:+3:33: +3:34
-      scope 1 {
-          debug e => _1;                   // in scope 1 at $DIR/simplify-arm-identity.rs:+1:9: +1:10
-          let _4: u8;                      // in scope 1 at $DIR/simplify-arm-identity.rs:+3:18: +3:19
-          scope 2 {
-          }
-          scope 3 {
-              debug x => _4;               // in scope 3 at $DIR/simplify-arm-identity.rs:+3:18: +3:19
-          }
-      }
-  
-      bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/simplify-arm-identity.rs:+1:9: +1:10
-          Deinit(_1);                      // scope 0 at $DIR/simplify-arm-identity.rs:+1:18: +1:29
-          ((_1 as Foo).0: u8) = const 0_u8; // scope 0 at $DIR/simplify-arm-identity.rs:+1:18: +1:29
-          discriminant(_1) = 0;            // scope 0 at $DIR/simplify-arm-identity.rs:+1:18: +1:29
-          StorageLive(_2);                 // scope 1 at $DIR/simplify-arm-identity.rs:+2:18: +5:6
-          _3 = const 0_isize;              // scope 1 at $DIR/simplify-arm-identity.rs:+2:24: +2:25
-          goto -> bb3;                     // scope 1 at $DIR/simplify-arm-identity.rs:+2:18: +2:25
-      }
-  
-      bb1: {
-          Deinit(_2);                      // scope 1 at $DIR/simplify-arm-identity.rs:+4:21: +4:32
-          ((_2 as Foo).0: u8) = const 0_u8; // scope 1 at $DIR/simplify-arm-identity.rs:+4:21: +4:32
-          discriminant(_2) = 0;            // scope 1 at $DIR/simplify-arm-identity.rs:+4:21: +4:32
-          goto -> bb4;                     // scope 1 at $DIR/simplify-arm-identity.rs:+4:21: +4:32
-      }
-  
-      bb2: {
-          unreachable;                     // scope 1 at $DIR/simplify-arm-identity.rs:+2:24: +2:25
-      }
-  
-      bb3: {
-          StorageLive(_4);                 // scope 1 at $DIR/simplify-arm-identity.rs:+3:18: +3:19
-          _4 = ((_1 as Foo).0: u8);        // scope 1 at $DIR/simplify-arm-identity.rs:+3:18: +3:19
-          StorageLive(_5);                 // scope 3 at $DIR/simplify-arm-identity.rs:+3:33: +3:34
-          _5 = _4;                         // scope 3 at $DIR/simplify-arm-identity.rs:+3:33: +3:34
-          Deinit(_2);                      // scope 3 at $DIR/simplify-arm-identity.rs:+3:24: +3:35
-          ((_2 as Foo).0: u8) = move _5;   // scope 3 at $DIR/simplify-arm-identity.rs:+3:24: +3:35
-          discriminant(_2) = 0;            // scope 3 at $DIR/simplify-arm-identity.rs:+3:24: +3:35
-          StorageDead(_5);                 // scope 3 at $DIR/simplify-arm-identity.rs:+3:34: +3:35
-          StorageDead(_4);                 // scope 1 at $DIR/simplify-arm-identity.rs:+3:34: +3:35
-          goto -> bb4;                     // scope 1 at $DIR/simplify-arm-identity.rs:+3:34: +3:35
-      }
-  
-      bb4: {
-          StorageDead(_2);                 // scope 1 at $DIR/simplify-arm-identity.rs:+5:6: +5:7
-          nop;                             // scope 0 at $DIR/simplify-arm-identity.rs:+0:11: +6:2
-          StorageDead(_1);                 // scope 0 at $DIR/simplify-arm-identity.rs:+6:1: +6:2
-          return;                          // scope 0 at $DIR/simplify-arm-identity.rs:+6:2: +6:2
-      }
-  }
-  
diff --git a/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.64bit.diff b/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.64bit.diff
deleted file mode 100644 (file)
index 118f5dd..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-- // MIR for `main` before SimplifyArmIdentity
-+ // MIR for `main` after SimplifyArmIdentity
-  
-  fn main() -> () {
-      let mut _0: ();                      // return place in scope 0 at $DIR/simplify-arm-identity.rs:+0:11: +0:11
-      let _1: Src;                         // in scope 0 at $DIR/simplify-arm-identity.rs:+1:9: +1:10
-      let mut _2: Dst;                     // in scope 0 at $DIR/simplify-arm-identity.rs:+2:18: +5:6
-      let mut _3: isize;                   // in scope 0 at $DIR/simplify-arm-identity.rs:+3:9: +3:20
-      let mut _5: u8;                      // in scope 0 at $DIR/simplify-arm-identity.rs:+3:33: +3:34
-      scope 1 {
-          debug e => _1;                   // in scope 1 at $DIR/simplify-arm-identity.rs:+1:9: +1:10
-          let _4: u8;                      // in scope 1 at $DIR/simplify-arm-identity.rs:+3:18: +3:19
-          scope 2 {
-          }
-          scope 3 {
-              debug x => _4;               // in scope 3 at $DIR/simplify-arm-identity.rs:+3:18: +3:19
-          }
-      }
-  
-      bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/simplify-arm-identity.rs:+1:9: +1:10
-          Deinit(_1);                      // scope 0 at $DIR/simplify-arm-identity.rs:+1:18: +1:29
-          ((_1 as Foo).0: u8) = const 0_u8; // scope 0 at $DIR/simplify-arm-identity.rs:+1:18: +1:29
-          discriminant(_1) = 0;            // scope 0 at $DIR/simplify-arm-identity.rs:+1:18: +1:29
-          StorageLive(_2);                 // scope 1 at $DIR/simplify-arm-identity.rs:+2:18: +5:6
-          _3 = const 0_isize;              // scope 1 at $DIR/simplify-arm-identity.rs:+2:24: +2:25
-          goto -> bb3;                     // scope 1 at $DIR/simplify-arm-identity.rs:+2:18: +2:25
-      }
-  
-      bb1: {
-          Deinit(_2);                      // scope 1 at $DIR/simplify-arm-identity.rs:+4:21: +4:32
-          ((_2 as Foo).0: u8) = const 0_u8; // scope 1 at $DIR/simplify-arm-identity.rs:+4:21: +4:32
-          discriminant(_2) = 0;            // scope 1 at $DIR/simplify-arm-identity.rs:+4:21: +4:32
-          goto -> bb4;                     // scope 1 at $DIR/simplify-arm-identity.rs:+4:21: +4:32
-      }
-  
-      bb2: {
-          unreachable;                     // scope 1 at $DIR/simplify-arm-identity.rs:+2:24: +2:25
-      }
-  
-      bb3: {
-          StorageLive(_4);                 // scope 1 at $DIR/simplify-arm-identity.rs:+3:18: +3:19
-          _4 = ((_1 as Foo).0: u8);        // scope 1 at $DIR/simplify-arm-identity.rs:+3:18: +3:19
-          StorageLive(_5);                 // scope 3 at $DIR/simplify-arm-identity.rs:+3:33: +3:34
-          _5 = _4;                         // scope 3 at $DIR/simplify-arm-identity.rs:+3:33: +3:34
-          Deinit(_2);                      // scope 3 at $DIR/simplify-arm-identity.rs:+3:24: +3:35
-          ((_2 as Foo).0: u8) = move _5;   // scope 3 at $DIR/simplify-arm-identity.rs:+3:24: +3:35
-          discriminant(_2) = 0;            // scope 3 at $DIR/simplify-arm-identity.rs:+3:24: +3:35
-          StorageDead(_5);                 // scope 3 at $DIR/simplify-arm-identity.rs:+3:34: +3:35
-          StorageDead(_4);                 // scope 1 at $DIR/simplify-arm-identity.rs:+3:34: +3:35
-          goto -> bb4;                     // scope 1 at $DIR/simplify-arm-identity.rs:+3:34: +3:35
-      }
-  
-      bb4: {
-          StorageDead(_2);                 // scope 1 at $DIR/simplify-arm-identity.rs:+5:6: +5:7
-          nop;                             // scope 0 at $DIR/simplify-arm-identity.rs:+0:11: +6:2
-          StorageDead(_1);                 // scope 0 at $DIR/simplify-arm-identity.rs:+6:1: +6:2
-          return;                          // scope 0 at $DIR/simplify-arm-identity.rs:+6:2: +6:2
-      }
-  }
-  
index d8e0657c6ebc66908583970518b57cdbb9328851..51d26b08b2a1c69217fbf247a24d4bf5f43efa4d 100644 (file)
@@ -5,24 +5,32 @@
       debug x => _1;                       // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+0:8: +0:9
       let mut _0: std::option::Option<std::boxed::Box<()>>; // return place in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+0:31: +0:46
       let mut _2: isize;                   // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+2:9: +2:13
--     let _3: std::boxed::Box<()>;         // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15
--     let mut _4: std::boxed::Box<()>;     // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:25: +3:26
+      let _3: std::boxed::Box<()>;         // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15
+      let mut _4: std::boxed::Box<()>;     // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:25: +3:26
 -     let mut _5: bool;                    // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:1: +5:2
 -     let mut _6: isize;                   // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:1: +5:2
 -     let mut _7: isize;                   // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:1: +5:2
       scope 1 {
-          debug x => ((_0 as Some).0: std::boxed::Box<()>); // in scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15
+          debug x => _3;                   // in scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15
       }
   
       bb0: {
+-         _5 = const false;                // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:11: +1:12
+-         _5 = const true;                 // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:11: +1:12
           _2 = discriminant(_1);           // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:11: +1:12
           switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:5: +1:12
       }
   
       bb1: {
-          ((_0 as Some).0: std::boxed::Box<()>) = move ((_1 as Some).0: std::boxed::Box<()>); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15
+          StorageLive(_3);                 // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15
+          _3 = move ((_1 as Some).0: std::boxed::Box<()>); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15
+          StorageLive(_4);                 // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:25: +3:26
+          _4 = move _3;                    // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:25: +3:26
           Deinit(_0);                      // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:20: +3:27
+          ((_0 as Some).0: std::boxed::Box<()>) = move _4; // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:20: +3:27
           discriminant(_0) = 1;            // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:20: +3:27
+          StorageDead(_4);                 // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:26: +3:27
+          StorageDead(_3);                 // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:26: +3:27
           goto -> bb4;                     // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:26: +3:27
       }
   
@@ -37,6 +45,7 @@
       }
   
       bb4: {
+-         _6 = discriminant(_1);           // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:1: +5:2
           return;                          // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:2: +5:2
       }
   }
index d8e0657c6ebc66908583970518b57cdbb9328851..51d26b08b2a1c69217fbf247a24d4bf5f43efa4d 100644 (file)
@@ -5,24 +5,32 @@
       debug x => _1;                       // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+0:8: +0:9
       let mut _0: std::option::Option<std::boxed::Box<()>>; // return place in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+0:31: +0:46
       let mut _2: isize;                   // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+2:9: +2:13
--     let _3: std::boxed::Box<()>;         // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15
--     let mut _4: std::boxed::Box<()>;     // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:25: +3:26
+      let _3: std::boxed::Box<()>;         // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15
+      let mut _4: std::boxed::Box<()>;     // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:25: +3:26
 -     let mut _5: bool;                    // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:1: +5:2
 -     let mut _6: isize;                   // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:1: +5:2
 -     let mut _7: isize;                   // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:1: +5:2
       scope 1 {
-          debug x => ((_0 as Some).0: std::boxed::Box<()>); // in scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15
+          debug x => _3;                   // in scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15
       }
   
       bb0: {
+-         _5 = const false;                // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:11: +1:12
+-         _5 = const true;                 // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:11: +1:12
           _2 = discriminant(_1);           // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:11: +1:12
           switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:5: +1:12
       }
   
       bb1: {
-          ((_0 as Some).0: std::boxed::Box<()>) = move ((_1 as Some).0: std::boxed::Box<()>); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15
+          StorageLive(_3);                 // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15
+          _3 = move ((_1 as Some).0: std::boxed::Box<()>); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15
+          StorageLive(_4);                 // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:25: +3:26
+          _4 = move _3;                    // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:25: +3:26
           Deinit(_0);                      // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:20: +3:27
+          ((_0 as Some).0: std::boxed::Box<()>) = move _4; // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:20: +3:27
           discriminant(_0) = 1;            // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:20: +3:27
+          StorageDead(_4);                 // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:26: +3:27
+          StorageDead(_3);                 // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:26: +3:27
           goto -> bb4;                     // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:26: +3:27
       }
   
@@ -37,6 +45,7 @@
       }
   
       bb4: {
+-         _6 = discriminant(_1);           // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:1: +5:2
           return;                          // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:2: +5:2
       }
   }
diff --git a/src/test/mir-opt/simplify_try.rs b/src/test/mir-opt/simplify_try.rs
deleted file mode 100644 (file)
index 15e351e..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-// compile-flags: -Zunsound-mir-opts
-// EMIT_MIR simplify_try.try_identity.SimplifyArmIdentity.diff
-// EMIT_MIR simplify_try.try_identity.SimplifyBranchSame.after.mir
-// EMIT_MIR simplify_try.try_identity.SimplifyLocals.after.mir
-// EMIT_MIR simplify_try.try_identity.DestinationPropagation.diff
-
-
-fn into_result<T, E>(r: Result<T, E>) -> Result<T, E> {
-    r
-}
-
-fn from_error<T, E>(e: E) -> Result<T, E> {
-    Err(e)
-}
-
-// This was written to the `?` from `try_trait`, but `try_trait_v2` uses a different structure,
-// so the relevant desugar is copied inline in order to keep the test testing the same thing.
-// FIXME(#85133): while this might be useful for `r#try!`, it would be nice to have a MIR
-// optimization that picks up the `?` desugaring, as `SimplifyArmIdentity` does not.
-fn try_identity(x: Result<u32, i32>) -> Result<u32, i32> {
-    let y = match into_result(x) {
-        Err(e) => return from_error(From::from(e)),
-        Ok(v) => v,
-    };
-    Ok(y)
-}
-
-fn main() {
-    let _ = try_identity(Ok(0));
-}
diff --git a/src/test/mir-opt/try_identity_e2e.new.PreCodegen.after.mir b/src/test/mir-opt/try_identity_e2e.new.PreCodegen.after.mir
new file mode 100644 (file)
index 0000000..330929c
--- /dev/null
@@ -0,0 +1,96 @@
+// MIR for `new` after PreCodegen
+
+fn new(_1: Result<T, E>) -> Result<T, E> {
+    debug x => _1;                       // in scope 0 at $DIR/try_identity_e2e.rs:+0:14: +0:15
+    let mut _0: std::result::Result<T, E>; // return place in scope 0 at $DIR/try_identity_e2e.rs:+0:34: +0:46
+    let mut _2: T;                       // in scope 0 at $DIR/try_identity_e2e.rs:+2:9: +10:10
+    let mut _3: std::ops::ControlFlow<E, T>; // in scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
+    let mut _4: isize;                   // in scope 0 at $DIR/try_identity_e2e.rs:+4:17: +4:22
+    let _5: T;                           // in scope 0 at $DIR/try_identity_e2e.rs:+4:20: +4:21
+    let mut _6: T;                       // in scope 0 at $DIR/try_identity_e2e.rs:+4:48: +4:49
+    let _7: E;                           // in scope 0 at $DIR/try_identity_e2e.rs:+5:21: +5:22
+    let mut _8: E;                       // in scope 0 at $DIR/try_identity_e2e.rs:+5:46: +5:47
+    let mut _9: isize;                   // in scope 0 at $DIR/try_identity_e2e.rs:+8:13: +8:37
+    let _10: T;                          // in scope 0 at $DIR/try_identity_e2e.rs:+8:35: +8:36
+    let _11: E;                          // in scope 0 at $DIR/try_identity_e2e.rs:+9:32: +9:33
+    let mut _12: E;                      // in scope 0 at $DIR/try_identity_e2e.rs:+9:49: +9:50
+    scope 1 {
+        debug v => _5;                   // in scope 1 at $DIR/try_identity_e2e.rs:+4:20: +4:21
+    }
+    scope 2 {
+        debug e => _7;                   // in scope 2 at $DIR/try_identity_e2e.rs:+5:21: +5:22
+    }
+    scope 3 {
+        debug v => _10;                  // in scope 3 at $DIR/try_identity_e2e.rs:+8:35: +8:36
+    }
+    scope 4 {
+        debug e => _11;                  // in scope 4 at $DIR/try_identity_e2e.rs:+9:32: +9:33
+    }
+
+    bb0: {
+        StorageLive(_2);                 // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +10:10
+        StorageLive(_3);                 // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
+        _4 = discriminant(_1);           // scope 0 at $DIR/try_identity_e2e.rs:+3:19: +3:20
+        switchInt(move _4) -> [0_isize: bb2, 1_isize: bb1, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+3:13: +3:20
+    }
+
+    bb1: {
+        StorageLive(_7);                 // scope 0 at $DIR/try_identity_e2e.rs:+5:21: +5:22
+        _7 = move ((_1 as Err).0: E);    // scope 0 at $DIR/try_identity_e2e.rs:+5:21: +5:22
+        StorageLive(_8);                 // scope 2 at $DIR/try_identity_e2e.rs:+5:46: +5:47
+        _8 = move _7;                    // scope 2 at $DIR/try_identity_e2e.rs:+5:46: +5:47
+        Deinit(_3);                      // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48
+        ((_3 as Break).0: E) = move _8;  // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48
+        discriminant(_3) = 1;            // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48
+        StorageDead(_8);                 // scope 2 at $DIR/try_identity_e2e.rs:+5:47: +5:48
+        StorageDead(_7);                 // scope 0 at $DIR/try_identity_e2e.rs:+5:47: +5:48
+        _9 = discriminant(_3);           // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
+        switchInt(move _9) -> [0_isize: bb5, 1_isize: bb3, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +7:10
+    }
+
+    bb2: {
+        StorageLive(_5);                 // scope 0 at $DIR/try_identity_e2e.rs:+4:20: +4:21
+        _5 = move ((_1 as Ok).0: T);     // scope 0 at $DIR/try_identity_e2e.rs:+4:20: +4:21
+        StorageLive(_6);                 // scope 1 at $DIR/try_identity_e2e.rs:+4:48: +4:49
+        _6 = move _5;                    // scope 1 at $DIR/try_identity_e2e.rs:+4:48: +4:49
+        Deinit(_3);                      // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50
+        ((_3 as Continue).0: T) = move _6; // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50
+        discriminant(_3) = 0;            // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50
+        StorageDead(_6);                 // scope 1 at $DIR/try_identity_e2e.rs:+4:49: +4:50
+        StorageDead(_5);                 // scope 0 at $DIR/try_identity_e2e.rs:+4:49: +4:50
+        _9 = discriminant(_3);           // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
+        switchInt(move _9) -> [0_isize: bb5, 1_isize: bb3, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +7:10
+    }
+
+    bb3: {
+        StorageLive(_11);                // scope 0 at $DIR/try_identity_e2e.rs:+9:32: +9:33
+        _11 = move ((_3 as Break).0: E); // scope 0 at $DIR/try_identity_e2e.rs:+9:32: +9:33
+        StorageLive(_12);                // scope 4 at $DIR/try_identity_e2e.rs:+9:49: +9:50
+        _12 = move _11;                  // scope 4 at $DIR/try_identity_e2e.rs:+9:49: +9:50
+        Deinit(_0);                      // scope 4 at $DIR/try_identity_e2e.rs:+9:45: +9:51
+        ((_0 as Err).0: E) = move _12;   // scope 4 at $DIR/try_identity_e2e.rs:+9:45: +9:51
+        discriminant(_0) = 1;            // scope 4 at $DIR/try_identity_e2e.rs:+9:45: +9:51
+        StorageDead(_12);                // scope 4 at $DIR/try_identity_e2e.rs:+9:50: +9:51
+        StorageDead(_11);                // scope 0 at $DIR/try_identity_e2e.rs:+9:50: +9:51
+        StorageDead(_2);                 // scope 0 at $DIR/try_identity_e2e.rs:+11:5: +11:6
+        StorageDead(_3);                 // scope 0 at $DIR/try_identity_e2e.rs:+12:1: +12:2
+        return;                          // scope 0 at $DIR/try_identity_e2e.rs:+12:1: +12:2
+    }
+
+    bb4: {
+        unreachable;                     // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
+    }
+
+    bb5: {
+        StorageLive(_10);                // scope 0 at $DIR/try_identity_e2e.rs:+8:35: +8:36
+        _10 = move ((_3 as Continue).0: T); // scope 0 at $DIR/try_identity_e2e.rs:+8:35: +8:36
+        _2 = move _10;                   // scope 3 at $DIR/try_identity_e2e.rs:+8:41: +8:42
+        StorageDead(_10);                // scope 0 at $DIR/try_identity_e2e.rs:+8:41: +8:42
+        Deinit(_0);                      // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +11:6
+        ((_0 as Ok).0: T) = move _2;     // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +11:6
+        discriminant(_0) = 0;            // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +11:6
+        StorageDead(_2);                 // scope 0 at $DIR/try_identity_e2e.rs:+11:5: +11:6
+        StorageDead(_3);                 // scope 0 at $DIR/try_identity_e2e.rs:+12:1: +12:2
+        return;                          // scope 0 at $DIR/try_identity_e2e.rs:+12:1: +12:2
+    }
+}
diff --git a/src/test/mir-opt/try_identity_e2e.old.PreCodegen.after.mir b/src/test/mir-opt/try_identity_e2e.old.PreCodegen.after.mir
new file mode 100644 (file)
index 0000000..18d3e0f
--- /dev/null
@@ -0,0 +1,53 @@
+// MIR for `old` after PreCodegen
+
+fn old(_1: Result<T, E>) -> Result<T, E> {
+    debug x => _1;                       // in scope 0 at $DIR/try_identity_e2e.rs:+0:14: +0:15
+    let mut _0: std::result::Result<T, E>; // return place in scope 0 at $DIR/try_identity_e2e.rs:+0:34: +0:46
+    let mut _2: T;                       // in scope 0 at $DIR/try_identity_e2e.rs:+2:9: +5:10
+    let mut _3: isize;                   // in scope 0 at $DIR/try_identity_e2e.rs:+3:13: +3:18
+    let _4: T;                           // in scope 0 at $DIR/try_identity_e2e.rs:+3:16: +3:17
+    let _5: E;                           // in scope 0 at $DIR/try_identity_e2e.rs:+4:17: +4:18
+    let mut _6: E;                       // in scope 0 at $DIR/try_identity_e2e.rs:+4:34: +4:35
+    scope 1 {
+        debug v => _4;                   // in scope 1 at $DIR/try_identity_e2e.rs:+3:16: +3:17
+    }
+    scope 2 {
+        debug e => _5;                   // in scope 2 at $DIR/try_identity_e2e.rs:+4:17: +4:18
+    }
+
+    bb0: {
+        StorageLive(_2);                 // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +5:10
+        _3 = discriminant(_1);           // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +2:16
+        switchInt(move _3) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +2:16
+    }
+
+    bb1: {
+        StorageLive(_5);                 // scope 0 at $DIR/try_identity_e2e.rs:+4:17: +4:18
+        _5 = move ((_1 as Err).0: E);    // scope 0 at $DIR/try_identity_e2e.rs:+4:17: +4:18
+        StorageLive(_6);                 // scope 2 at $DIR/try_identity_e2e.rs:+4:34: +4:35
+        _6 = move _5;                    // scope 2 at $DIR/try_identity_e2e.rs:+4:34: +4:35
+        Deinit(_0);                      // scope 2 at $DIR/try_identity_e2e.rs:+4:30: +4:36
+        ((_0 as Err).0: E) = move _6;    // scope 2 at $DIR/try_identity_e2e.rs:+4:30: +4:36
+        discriminant(_0) = 1;            // scope 2 at $DIR/try_identity_e2e.rs:+4:30: +4:36
+        StorageDead(_6);                 // scope 2 at $DIR/try_identity_e2e.rs:+4:35: +4:36
+        StorageDead(_5);                 // scope 0 at $DIR/try_identity_e2e.rs:+4:35: +4:36
+        StorageDead(_2);                 // scope 0 at $DIR/try_identity_e2e.rs:+6:5: +6:6
+        return;                          // scope 0 at $DIR/try_identity_e2e.rs:+7:1: +7:2
+    }
+
+    bb2: {
+        unreachable;                     // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +2:16
+    }
+
+    bb3: {
+        StorageLive(_4);                 // scope 0 at $DIR/try_identity_e2e.rs:+3:16: +3:17
+        _4 = move ((_1 as Ok).0: T);     // scope 0 at $DIR/try_identity_e2e.rs:+3:16: +3:17
+        _2 = move _4;                    // scope 1 at $DIR/try_identity_e2e.rs:+3:22: +3:23
+        StorageDead(_4);                 // scope 0 at $DIR/try_identity_e2e.rs:+3:22: +3:23
+        Deinit(_0);                      // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +6:6
+        ((_0 as Ok).0: T) = move _2;     // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +6:6
+        discriminant(_0) = 0;            // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +6:6
+        StorageDead(_2);                 // scope 0 at $DIR/try_identity_e2e.rs:+6:5: +6:6
+        return;                          // scope 0 at $DIR/try_identity_e2e.rs:+7:1: +7:2
+    }
+}
diff --git a/src/test/mir-opt/try_identity_e2e.rs b/src/test/mir-opt/try_identity_e2e.rs
new file mode 100644 (file)
index 0000000..00cb80f
--- /dev/null
@@ -0,0 +1,34 @@
+// Track the status of MIR optimizations simplifying `Ok(res?)` for both the old and new desugarings
+// of that syntax.
+
+use std::ops::ControlFlow;
+
+// EMIT_MIR try_identity_e2e.new.PreCodegen.after.mir
+fn new<T, E>(x: Result<T, E>) -> Result<T, E> {
+    Ok(
+        match {
+            match x {
+                Ok(v) => ControlFlow::Continue(v),
+                Err(e) => ControlFlow::Break(e),
+            }
+        } {
+            ControlFlow::Continue(v) => v,
+            ControlFlow::Break(e) => return Err(e),
+        }
+    )
+}
+
+// EMIT_MIR try_identity_e2e.old.PreCodegen.after.mir
+fn old<T, E>(x: Result<T, E>) -> Result<T, E> {
+    Ok(
+        match x {
+            Ok(v) => v,
+            Err(e) => return Err(e),
+        }
+    )
+}
+
+fn main() {
+    let _ = new::<(), ()>(Ok(()));
+    let _ = old::<(), ()>(Ok(()));
+}
diff --git a/src/test/rustdoc-gui/item-info-alignment.goml b/src/test/rustdoc-gui/item-info-alignment.goml
new file mode 100644 (file)
index 0000000..4d7b504
--- /dev/null
@@ -0,0 +1,10 @@
+// This test ensures that the "item-info" looks about the same
+// whether or not it's inside a toggle.
+goto: file://|DOC_PATH|/lib2/struct.ItemInfoAlignmentTest.html
+
+// First, we try it in "desktop" mode.
+size: (1200, 870)
+compare-elements-position: (".impl-items > .item-info", "summary > .item-info", ("x"))
+// Next, we try it in "mobile" mode (max-width: 700px).
+size: (650, 650)
+compare-elements-position: (".impl-items > .item-info", "summary > .item-info", ("x"))
index c35a86ccd1cab0cf0cc5b989542681d3c189b1a4..1c64974e9162710a3aad4b4790c89a01aa680f6c 100644 (file)
@@ -92,7 +92,7 @@ reload:
 assert-css: (
     ".search-input",
     {
-        "border-color": "rgb(240, 240, 240)",
+        "border-color": "rgb(224, 224, 224)",
         "background-color": "rgb(240, 240, 240)",
         "color": "rgb(17, 17, 17)",
     },
diff --git a/src/test/rustdoc-gui/search-input.goml b/src/test/rustdoc-gui/search-input.goml
deleted file mode 100644 (file)
index 6903e1a..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// Ensures that the search input border color changes on focus.
-goto: file://|DOC_PATH|/test_docs/index.html
-local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": "dark"}
-reload:
-
-assert-css: (".search-input", {"border-color": "rgb(240, 240, 240)"})
-click: ".search-input"
-assert-css: (".search-input", {"border-color": "rgb(0, 141, 253)"})
-
-local-storage: {"rustdoc-theme": "light"}
-reload:
-
-assert-css: (".search-input", {"border-color": "rgb(224, 224, 224)"})
-click: ".search-input"
-assert-css: (".search-input", {"border-color": "rgb(102, 175, 233)"})
-
-local-storage: {"rustdoc-theme": "ayu"}
-reload:
-
-assert-css: (".search-input", {"border-color": "rgb(92, 103, 115)"})
-click: ".search-input"
-assert-css: (".search-input", {"border-color": "rgb(92, 103, 115)"})
index 87f91be3ac82cec26d87785a1afe2debd038aed8..5a151ed7b687a2ba8042dd1b9ffaa07617f6d8df 100644 (file)
@@ -143,3 +143,40 @@ pub trait SimpleTrait {}
 /// Some docs.
 #[doc(cfg(any(target_os = "android", target_os = "linux", target_os = "emscripten", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd")))]
 impl SimpleTrait for LongItemInfo2 {}
+
+pub struct WhereWhitespace<T>;
+
+impl<T> WhereWhitespace<T> {
+    pub fn new<F>(f: F) -> Self
+    where
+        F: FnMut() -> i32,
+    {}
+}
+
+impl<K, T> Whitespace<&K> for WhereWhitespace<T>
+where
+    K: std::fmt::Debug,
+{
+    type Output = WhereWhitespace<T>;
+    fn index(&self, _key: &K) -> &Self::Output {
+        self
+    }
+}
+
+pub trait Whitespace<Idx>
+where
+    Idx: ?Sized,
+{
+    type Output;
+    fn index(&self, index: Idx) -> &Self::Output;
+}
+
+pub struct ItemInfoAlignmentTest;
+
+impl ItemInfoAlignmentTest {
+    /// This method has docs
+    #[deprecated]
+    pub fn foo() {}
+    #[deprecated]
+    pub fn bar() {}
+}
index 22212a31728dca6dc06524be2c9cc60e216a10fc..85e03c45e700e985bebd41ecd88898398fc70a30 100644 (file)
@@ -32,6 +32,6 @@ assert-property: (".item-decl pre", {"scrollWidth": "950"})
 size: (600, 600)
 goto: file://|DOC_PATH|/lib2/too_long/struct.SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName.html
 // It shouldn't have an overflow in the topbar either.
-assert-property: (".mobile-topbar .location", {"scrollWidth": "492"})
-assert-property: (".mobile-topbar .location", {"clientWidth": "492"})
+assert-property: (".mobile-topbar .location", {"scrollWidth": "502"})
+assert-property: (".mobile-topbar .location", {"clientWidth": "502"})
 assert-css: (".mobile-topbar .location", {"overflow-x": "hidden"})
diff --git a/src/test/rustdoc-gui/where-whitespace.goml b/src/test/rustdoc-gui/where-whitespace.goml
new file mode 100644 (file)
index 0000000..1a3ff1f
--- /dev/null
@@ -0,0 +1,27 @@
+// This test ensures that the where conditions are correctly displayed.
+goto: file://|DOC_PATH|/lib2/trait.Whitespace.html
+show-text: true
+// First, we check in the trait definition if the where clause is "on its own" (not on the same
+// line than "pub trait Whitespace<Idx>").
+compare-elements-position-false: (".item-decl code", ".where.fmt-newline", ("y"))
+// And that the code following it isn't on the same line either.
+compare-elements-position-false: (".item-decl .fnname", ".where.fmt-newline", ("y"))
+
+goto: file://|DOC_PATH|/lib2/struct.WhereWhitespace.html
+// We make the screen a bit wider to ensure that the trait impl is on one line.
+size: (915, 915)
+
+compare-elements-position-false: ("#method\.new .fnname", "#method\.new .where.fmt-newline", ("y"))
+// We ensure that both the trait name and the struct name are on the same line in
+// "impl<K, T> Whitespace<&K> for WhereWhitespace<T>".
+compare-elements-position: (
+    "#trait-implementations-list .impl h3 .trait",
+    "#trait-implementations-list .impl h3 .struct",
+    ("y"),
+)
+// And we now check that the where condition isn't on the same line.
+compare-elements-position-false: (
+    "#trait-implementations-list .impl h3 .trait",
+    "#trait-implementations-list .impl h3 .where.fmt-newline",
+    ("y"),
+)
diff --git a/src/test/rustdoc-json/enums/discriminant/basic.rs b/src/test/rustdoc-json/enums/discriminant/basic.rs
new file mode 100644 (file)
index 0000000..8c22161
--- /dev/null
@@ -0,0 +1,12 @@
+#[repr(i8)]
+pub enum Ordering {
+    // @is "$.index[*][?(@.name=='Less')].inner.variant_inner.expr" '"-1"'
+    // @is "$.index[*][?(@.name=='Less')].inner.variant_inner.value" '"-1"'
+    Less = -1,
+    // @is "$.index[*][?(@.name=='Equal')].inner.variant_inner.expr" '"0"'
+    // @is "$.index[*][?(@.name=='Equal')].inner.variant_inner.value" '"0"'
+    Equal = 0,
+    // @is "$.index[*][?(@.name=='Greater')].inner.variant_inner.expr" '"1"'
+    // @is "$.index[*][?(@.name=='Greater')].inner.variant_inner.value" '"1"'
+    Greater = 1,
+}
diff --git a/src/test/rustdoc-json/enums/discriminant/expr.rs b/src/test/rustdoc-json/enums/discriminant/expr.rs
new file mode 100644 (file)
index 0000000..235b0b4
--- /dev/null
@@ -0,0 +1,39 @@
+pub enum Foo {
+    // @is "$.index[*][?(@.name=='Addition')].inner.variant_inner.value" '"0"'
+    // @is "$.index[*][?(@.name=='Addition')].inner.variant_inner.expr" '"{ _ }"'
+    Addition = 0 + 0,
+    // @is "$.index[*][?(@.name=='Bin')].inner.variant_inner.value" '"1"'
+    // @is "$.index[*][?(@.name=='Bin')].inner.variant_inner.expr" '"0b1"'
+    Bin = 0b1,
+    // @is "$.index[*][?(@.name=='Oct')].inner.variant_inner.value" '"2"'
+    // @is "$.index[*][?(@.name=='Oct')].inner.variant_inner.expr" '"0o2"'
+    Oct = 0o2,
+    // @is "$.index[*][?(@.name=='PubConst')].inner.variant_inner.value" '"3"'
+    // @is "$.index[*][?(@.name=='PubConst')].inner.variant_inner.expr" '"THREE"'
+    PubConst = THREE,
+    // @is "$.index[*][?(@.name=='Hex')].inner.variant_inner.value" '"4"'
+    // @is "$.index[*][?(@.name=='Hex')].inner.variant_inner.expr" '"0x4"'
+    Hex = 0x4,
+    // @is "$.index[*][?(@.name=='Cast')].inner.variant_inner.value" '"5"'
+    // @is "$.index[*][?(@.name=='Cast')].inner.variant_inner.expr" '"{ _ }"'
+    Cast = 5 as isize,
+    // @is "$.index[*][?(@.name=='PubCall')].inner.variant_inner.value" '"6"'
+    // @is "$.index[*][?(@.name=='PubCall')].inner.variant_inner.expr" '"{ _ }"'
+    PubCall = six(),
+    // @is "$.index[*][?(@.name=='PrivCall')].inner.variant_inner.value" '"7"'
+    // @is "$.index[*][?(@.name=='PrivCall')].inner.variant_inner.expr" '"{ _ }"'
+    PrivCall = seven(),
+    // @is "$.index[*][?(@.name=='PrivConst')].inner.variant_inner.value" '"8"'
+    // @is "$.index[*][?(@.name=='PrivConst')].inner.variant_inner.expr" '"EIGHT"'
+    PrivConst = EIGHT,
+}
+
+pub const THREE: isize = 3;
+const EIGHT: isize = 8;
+
+pub const fn six() -> isize {
+    6
+}
+const fn seven() -> isize {
+    7
+}
diff --git a/src/test/rustdoc-json/enums/discriminant/limits.rs b/src/test/rustdoc-json/enums/discriminant/limits.rs
new file mode 100644 (file)
index 0000000..8df73d7
--- /dev/null
@@ -0,0 +1,43 @@
+// ignore-tidy-linelength
+#![feature(repr128)]
+#![allow(incomplete_features)]
+
+#[repr(u64)]
+pub enum U64 {
+    // @is "$.index[*][?(@.name=='U64Min')].inner.variant_inner.value" '"0"'
+    // @is "$.index[*][?(@.name=='U64Min')].inner.variant_inner.expr" '"u64::MIN"'
+    U64Min = u64::MIN,
+    // @is "$.index[*][?(@.name=='U64Max')].inner.variant_inner.value" '"18446744073709551615"'
+    // @is "$.index[*][?(@.name=='U64Max')].inner.variant_inner.expr" '"u64::MAX"'
+    U64Max = u64::MAX,
+}
+
+#[repr(i64)]
+pub enum I64 {
+    // @is "$.index[*][?(@.name=='I64Min')].inner.variant_inner.value" '"-9223372036854775808"'
+    // @is "$.index[*][?(@.name=='I64Min')].inner.variant_inner.expr" '"i64::MIN"'
+    I64Min = i64::MIN,
+    // @is "$.index[*][?(@.name=='I64Max')].inner.variant_inner.value" '"9223372036854775807"'
+    // @is "$.index[*][?(@.name=='I64Max')].inner.variant_inner.expr" '"i64::MAX"'
+    I64Max = i64::MAX,
+}
+
+#[repr(u128)]
+pub enum U128 {
+    // @is "$.index[*][?(@.name=='U128Min')].inner.variant_inner.value" '"0"'
+    // @is "$.index[*][?(@.name=='U128Min')].inner.variant_inner.expr" '"u128::MIN"'
+    U128Min = u128::MIN,
+    // @is "$.index[*][?(@.name=='U128Max')].inner.variant_inner.value" '"340282366920938463463374607431768211455"'
+    // @is "$.index[*][?(@.name=='U128Max')].inner.variant_inner.expr" '"u128::MAX"'
+    U128Max = u128::MAX,
+}
+
+#[repr(i128)]
+pub enum I128 {
+    // @is "$.index[*][?(@.name=='I128Min')].inner.variant_inner.value" '"-170141183460469231731687303715884105728"'
+    // @is "$.index[*][?(@.name=='I128Min')].inner.variant_inner.expr" '"i128::MIN"'
+    I128Min = i128::MIN,
+    // @is "$.index[*][?(@.name=='I128Max')].inner.variant_inner.value" '"170141183460469231731687303715884105727"'
+    // @is "$.index[*][?(@.name=='I128Max')].inner.variant_inner.expr" '"i128::MAX"'
+    I128Max = i128::MAX,
+}
diff --git a/src/test/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs b/src/test/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs
new file mode 100644 (file)
index 0000000..3417baa
--- /dev/null
@@ -0,0 +1,15 @@
+#[repr(u32)]
+pub enum Foo {
+    // @is "$.index[*][?(@.name=='Basic')].inner.variant_inner.value" '"0"'
+    // @is "$.index[*][?(@.name=='Basic')].inner.variant_inner.expr" '"0"'
+    Basic = 0,
+    // @is "$.index[*][?(@.name=='Suffix')].inner.variant_inner.value" '"10"'
+    // @is "$.index[*][?(@.name=='Suffix')].inner.variant_inner.expr" '"10u32"'
+    Suffix = 10u32,
+    // @is "$.index[*][?(@.name=='Underscore')].inner.variant_inner.value" '"100"'
+    // @is "$.index[*][?(@.name=='Underscore')].inner.variant_inner.expr" '"1_0_0"'
+    Underscore = 1_0_0,
+    // @is "$.index[*][?(@.name=='SuffixUnderscore')].inner.variant_inner.value" '"1000"'
+    // @is "$.index[*][?(@.name=='SuffixUnderscore')].inner.variant_inner.expr" '"1_0_0_0u32"'
+    SuffixUnderscore = 1_0_0_0u32,
+}
diff --git a/src/test/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs b/src/test/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs
new file mode 100644 (file)
index 0000000..6af944a
--- /dev/null
@@ -0,0 +1,10 @@
+pub enum Foo {
+    // @is "$.index[*][?(@.name=='Has')].inner.variant_inner" '{"expr":"0", "value":"0"}'
+    Has = 0,
+    // @is "$.index[*][?(@.name=='Doesnt')].inner.variant_inner" null
+    Doesnt,
+    // @is "$.index[*][?(@.name=='AlsoDoesnt')].inner.variant_inner" null
+    AlsoDoesnt,
+    // @is "$.index[*][?(@.name=='AlsoHas')].inner.variant_inner" '{"expr":"44", "value":"44"}'
+    AlsoHas = 44,
+}
index 352a8e646bb49fe76e9fc548a87be15378b2dd20..87d2f29e26055461a284f5b581469cc2e421e399 100644 (file)
@@ -31,12 +31,12 @@ impl Trait<{1 + 2}> for u8 {}
 impl<const N: usize> Trait<N> for [u8; N] {}
 
 // @has foo/struct.Foo.html '//pre[@class="rust struct"]' \
-//      'pub struct Foo<const N: usize> where u8: Trait<N>'
+//      'pub struct Foo<const N: usize>where u8: Trait<N>'
 pub struct Foo<const N: usize> where u8: Trait<N>;
 // @has foo/struct.Bar.html '//pre[@class="rust struct"]' 'pub struct Bar<T, const N: usize>(_)'
 pub struct Bar<T, const N: usize>([T; N]);
 
-// @has foo/struct.Foo.html '//*[@id="impl-Foo%3CM%3E"]/h3[@class="code-header in-band"]' 'impl<const M: usize> Foo<M> where u8: Trait<M>'
+// @has foo/struct.Foo.html '//*[@id="impl-Foo%3CM%3E"]/h3[@class="code-header in-band"]' 'impl<const M: usize> Foo<M>where u8: Trait<M>'
 impl<const M: usize> Foo<M> where u8: Trait<M> {
     // @has - '//*[@id="associatedconstant.FOO_ASSOC"]' 'pub const FOO_ASSOC: usize'
     pub const FOO_ASSOC: usize = M + 13;
@@ -50,14 +50,14 @@ pub fn hey<const N: usize>(&self) -> Bar<u8, N> {
 // @has foo/struct.Bar.html '//*[@id="impl-Bar%3Cu8%2C%20M%3E"]/h3[@class="code-header in-band"]' 'impl<const M: usize> Bar<u8, M>'
 impl<const M: usize> Bar<u8, M> {
     // @has - '//*[@id="method.hey"]' \
-    //      'pub fn hey<const N: usize>(&self) -> Foo<N> where u8: Trait<N>'
+    //      'pub fn hey<const N: usize>(&self) -> Foo<N>where u8: Trait<N>'
     pub fn hey<const N: usize>(&self) -> Foo<N> where u8: Trait<N> {
         Foo
     }
 }
 
 // @has foo/fn.test.html '//pre[@class="rust fn"]' \
-//      'pub fn test<const N: usize>() -> impl Trait<N> where u8: Trait<N>'
+//      'pub fn test<const N: usize>() -> impl Trait<N>where u8: Trait<N>'
 pub fn test<const N: usize>() -> impl Trait<N> where u8: Trait<N> {
     2u8
 }
diff --git a/src/test/rustdoc/doc_auto_cfg_nested_impl.rs b/src/test/rustdoc/doc_auto_cfg_nested_impl.rs
new file mode 100644 (file)
index 0000000..4d73e0d
--- /dev/null
@@ -0,0 +1,24 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/101129>.
+
+#![feature(doc_auto_cfg)]
+#![crate_type = "lib"]
+#![crate_name = "foo"]
+
+pub struct S;
+pub trait MyTrait1 {}
+pub trait MyTrait2 {}
+
+// @has foo/struct.S.html
+// @has - '//*[@id="impl-MyTrait1-for-S"]//*[@class="stab portability"]' \
+//        'Available on non-crate feature coolstuff only.'
+#[cfg(not(feature = "coolstuff"))]
+impl MyTrait1 for S {}
+
+#[cfg(not(feature = "coolstuff"))]
+mod submod {
+    use crate::{S, MyTrait2};
+    // This impl should also have the `not(feature = "coolstuff")`.
+    // @has - '//*[@id="impl-MyTrait2-for-S"]//*[@class="stab portability"]' \
+    //        'Available on non-crate feature coolstuff only.'
+    impl MyTrait2 for S {}
+}
index ae981b9499a67cb20d131528639b836c2196ae34..2b9d4952d04eecd6c670d920b4f530b62dfc009d 100644 (file)
@@ -3,7 +3,7 @@
 
 // @has foo/trait.LendingIterator.html
 pub trait LendingIterator {
-    // @has - '//*[@id="associatedtype.Item"]//h4[@class="code-header"]' "type Item<'a> where Self: 'a"
+    // @has - '//*[@id="associatedtype.Item"]//h4[@class="code-header"]' "type Item<'a>where Self: 'a"
     type Item<'a> where Self: 'a;
 
     // @has - '//*[@id="tymethod.next"]//h4[@class="code-header"]' \
@@ -24,7 +24,7 @@ fn next<'a>(&self) -> () {}
 pub struct Infinite<T>(T);
 
 // @has foo/trait.LendingIterator.html
-// @has - '//*[@id="associatedtype.Item-2"]//h4[@class="code-header"]' "type Item<'a> where Self: 'a = &'a T"
+// @has - '//*[@id="associatedtype.Item-2"]//h4[@class="code-header"]' "type Item<'a>where Self: 'a = &'a T"
 impl<T> LendingIterator for Infinite<T> {
     type Item<'a> where Self: 'a = &'a T;
 
index b75b8de52f9cb6c3fab04e3a1dbf86caa7d4e019..59b5b6e5797cc47e3037fdd914df2f6476a24187 100644 (file)
@@ -4,7 +4,7 @@
 pub trait Trait<'x> {}
 
 // @has foo/fn.test1.html
-// @has - '//pre' "pub fn test1<T>() where for<'a> &'a T: Iterator,"
+// @has - '//pre' "pub fn test1<T>()where for<'a> &'a T: Iterator,"
 pub fn test1<T>()
 where
     for<'a> &'a T: Iterator,
@@ -12,7 +12,7 @@ pub fn test1<T>()
 }
 
 // @has foo/fn.test2.html
-// @has - '//pre' "pub fn test2<T>() where for<'a, 'b> &'a T: Trait<'b>,"
+// @has - '//pre' "pub fn test2<T>()where for<'a, 'b> &'a T: Trait<'b>,"
 pub fn test2<T>()
 where
     for<'a, 'b> &'a T: Trait<'b>,
@@ -20,7 +20,7 @@ pub fn test2<T>()
 }
 
 // @has foo/fn.test3.html
-// @has - '//pre' "pub fn test3<F>() where F: for<'a, 'b> Fn(&'a u8, &'b u8),"
+// @has - '//pre' "pub fn test3<F>()where F: for<'a, 'b> Fn(&'a u8, &'b u8),"
 pub fn test3<F>()
 where
     F: for<'a, 'b> Fn(&'a u8, &'b u8),
@@ -38,7 +38,7 @@ pub struct Foo<'a> {
 // @has - '//span[@id="structfield.some_trait"]' "some_trait: &'a dyn for<'b> Trait<'b>"
 
 impl<'a> Foo<'a> {
-    // @has - '//h4[@class="code-header"]' "pub fn bar<T>() where T: Trait<'a>,"
+    // @has - '//h4[@class="code-header"]' "pub fn bar<T>()where T: Trait<'a>,"
     pub fn bar<T>()
     where
         T: Trait<'a>,
index 249158c1a1f89bca9a9f1b63f1da16c76785e388..b1481e1f27978045e6864c92d42841fdf5d0755a 100644 (file)
@@ -6,7 +6,7 @@
 pub struct Foo<T> { field: T }
 
 // @has impl_parts/struct.Foo.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
-//     "impl<T: Clone> !AnAutoTrait for Foo<T> where T: Sync,"
+//     "impl<T: Clone> !AnAutoTrait for Foo<T>where T: Sync,"
 // @has impl_parts/trait.AnAutoTrait.html '//*[@class="item-list"]//h3[@class="code-header in-band"]' \
-//     "impl<T: Clone> !AnAutoTrait for Foo<T> where T: Sync,"
+//     "impl<T: Clone> !AnAutoTrait for Foo<T>where T: Sync,"
 impl<T: Clone> !AnAutoTrait for Foo<T> where T: Sync {}
index 84fc6f94a265a62a5d5d1becf5daf1f7efaf389d..643f93875909390b0b8bf410c325ecfd9393a309 100644 (file)
@@ -25,7 +25,7 @@ pub trait IndexMut<Idx: ?Sized>: Index<Idx> {
 
 pub mod reexport {
     // @has issue_20727_4/reexport/trait.Index.html
-    // @has - '//*[@class="rust trait"]' 'trait Index<Idx> where Idx: ?Sized, {'
+    // @has - '//*[@class="rust trait"]' 'trait Index<Idx>where Idx: ?Sized,{'
     // @has - '//*[@class="rust trait"]' 'type Output: ?Sized'
     // @has - '//*[@class="rust trait"]' \
     //        'fn index(&self, index: Idx) -> &Self::Output'
@@ -33,7 +33,7 @@ pub mod reexport {
 
     // @has issue_20727_4/reexport/trait.IndexMut.html
     // @has - '//*[@class="rust trait"]' \
-    //        'trait IndexMut<Idx>: Index<Idx> where Idx: ?Sized, {'
+    //        'trait IndexMut<Idx>: Index<Idx>where Idx: ?Sized,{'
     // @has - '//*[@class="rust trait"]' \
     //        'fn index_mut(&mut self, index: Idx) -> &mut Self::Output;'
     pub use issue_20727::IndexMut;
index 2a586b6ff6cdcfe3f427800bfe57cdeabb89c50f..29d2ec64c206d007d1d1a395fc0c38a3feb10615 100644 (file)
@@ -5,5 +5,5 @@
 
 // @has issue_21801/struct.Foo.html
 // @has - '//*[@id="method.new"]' \
-//        'fn new<F>(f: F) -> Foo where F: FnMut() -> i32'
+//        'fn new<F>(f: F) -> Foowhere F: FnMut() -> i32'
 pub use issue_21801::Foo;
index 635c3175f8138a39e40bc83d04f2bc1a6c0386be..134821e1ef3ea9bc724bb81e119a664724597461 100644 (file)
@@ -5,7 +5,7 @@ pub trait MyTrait {
     fn my_string(&self) -> String;
 }
 
-// @has - "//div[@id='implementors-list']//*[@id='impl-MyTrait-for-T']//h3[@class='code-header in-band']" "impl<T> MyTrait for T where T: Debug"
+// @has - "//div[@id='implementors-list']//*[@id='impl-MyTrait-for-T']//h3[@class='code-header in-band']" "impl<T> MyTrait for Twhere T: Debug"
 impl<T> MyTrait for T
 where
     T: fmt::Debug,
index 4184086f622abaff7f57fb211360c358ccfe15c8..91b67757453d2e788343eb82a15fa1d26313d309 100644 (file)
@@ -2,5 +2,5 @@
 
 pub trait Bar {}
 
-// @has foo/struct.Foo.html '//pre' 'pub struct Foo<T>(pub T) where T: Bar;'
+// @has foo/struct.Foo.html '//pre' 'pub struct Foo<T>(pub T)where T: Bar;'
 pub struct Foo<T>(pub T) where T: Bar;
index d88c29217023a9f9b5da233a3766297a872eeb0b..43fb705f58994717d9868b4942bdf5801c7fb847 100644 (file)
@@ -11,8 +11,8 @@ impl<B, C> Signal2 for B where B: Signal<Item = C> {
 }
 
 // @has issue_50159/struct.Switch.html
-// @has - '//h3[@class="code-header in-band"]' 'impl<B> Send for Switch<B> where <B as Signal>::Item: Send'
-// @has - '//h3[@class="code-header in-band"]' 'impl<B> Sync for Switch<B> where <B as Signal>::Item: Sync'
+// @has - '//h3[@class="code-header in-band"]' 'impl<B> Send for Switch<B>where <B as Signal>::Item: Send'
+// @has - '//h3[@class="code-header in-band"]' 'impl<B> Sync for Switch<B>where <B as Signal>::Item: Sync'
 // @count - '//*[@id="implementations-list"]//*[@class="impl"]' 0
 // @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]' 5
 pub struct Switch<B: Signal> {
index ee11ccc6811633fac9cd3f6b09abfc35b7e0a62f..aa5890a84514fc56364e8724fbcaf5891fdbf6d0 100644 (file)
@@ -8,7 +8,7 @@ pub trait Owned<'a> {
 
 // @has issue_51236/struct.Owned.html
 // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
-// "impl<T> Send for Owned<T> where <T as Owned<'static>>::Reader: Send"
+// "impl<T> Send for Owned<T>where <T as Owned<'static>>::Reader: Send"
 pub struct Owned<T> where T: for<'a> ::traits::Owned<'a> {
     marker: PhantomData<<T as ::traits::Owned<'static>>::Reader>,
 }
index bedaf5c4ddc360a311c83fc415943cab0b1e08f2..ce0f85d25da56d70009b7fee9911db47c06bd05e 100644 (file)
@@ -1,13 +1,11 @@
 pub trait ScopeHandle<'scope> {}
 
-
-
 // @has issue_54705/struct.ScopeFutureContents.html
 // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
-// "impl<'scope, S> Send for ScopeFutureContents<'scope, S> where S: Sync"
+// "impl<'scope, S> Send for ScopeFutureContents<'scope, S>where S: Sync"
 //
 // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
-// "impl<'scope, S> Sync for ScopeFutureContents<'scope, S> where S: Sync"
+// "impl<'scope, S> Sync for ScopeFutureContents<'scope, S>where S: Sync"
 pub struct ScopeFutureContents<'scope, S>
     where S: ScopeHandle<'scope>,
 {
index 83e08094c09534abf9da016c5c95fd7c42c8e9e9..a8841f137fecff11bb32a8a7fa028e850e30d40d 100644 (file)
@@ -8,7 +8,7 @@
 
 extern crate issue_98697_reexport_with_anonymous_lifetime;
 
-// @has issue_98697/fn.repro.html '//pre[@class="rust fn"]/code' 'fn repro<F>() where F: Fn(&str)'
+// @has issue_98697/fn.repro.html '//pre[@class="rust fn"]/code' 'fn repro<F>()where F: Fn(&str)'
 // @!has issue_98697/fn.repro.html '//pre[@class="rust fn"]/code' 'for<'
 pub use issue_98697_reexport_with_anonymous_lifetime::repro;
 
index b3f511bc1f153fc423b713ea2866bccc7cc4d65f..7f8f74ff457a5ab906ec670ea3d930d4e049adaa 100644 (file)
@@ -7,8 +7,8 @@
 // @has - '//span[@class="in-band"]' 'Primitive Type slice'
 // @has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!'
 // @has - '//h2[@id="synthetic-implementations"]' 'Auto Trait Implementations'
-// @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl<T> Send for [T] where T: Send'
-// @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl<T> Sync for [T] where T: Sync'
+// @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl<T> Send for [T]where T: Send'
+// @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl<T> Sync for [T]where T: Sync'
 #[doc(primitive = "slice")]
 /// this is a test!
 mod slice_prim {}
index 54c54fdbf68a8acafc9e50e48d0af6f9f7d3bc7b..19138fd1aceb20d1c1c8edb5699b83befb86cac9 100644 (file)
@@ -1,6 +1,6 @@
 // @has basic/struct.Foo.html
-// @has - '//h3[@class="code-header in-band"]' 'impl<T> Send for Foo<T> where T: Send'
-// @has - '//h3[@class="code-header in-band"]' 'impl<T> Sync for Foo<T> where T: Sync'
+// @has - '//h3[@class="code-header in-band"]' 'impl<T> Send for Foo<T>where T: Send'
+// @has - '//h3[@class="code-header in-band"]' 'impl<T> Sync for Foo<T>where T: Sync'
 // @count - '//*[@id="implementations-list"]//*[@class="impl has-srclink"]' 0
 // @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]' 5
 pub struct Foo<T> {
index f9017b90caee774d2022797e0321002bb77b630f..39f78983da2b031766ab2c8968a2d26d73e4f320 100644 (file)
@@ -21,7 +21,7 @@ pub struct Foo<T> {
 
 // @has complex/struct.NotOuter.html
 // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
-// "impl<'a, T, K: ?Sized> Send for Outer<'a, T, K> where K: for<'b> Fn((&'b bool, &'a u8)) \
+// "impl<'a, T, K: ?Sized> Send for Outer<'a, T, K>where K: for<'b> Fn((&'b bool, &'a u8)) \
 // -> &'b i8, T: MyTrait<'a>, <T as MyTrait<'a>>::MyItem: Copy, 'a: 'static"
 
 pub use foo::{Foo, Inner as NotInner, MyTrait as NotMyTrait, Outer as NotOuter};
index ee1393f9729c176ccff505f02e489c9e2116a2dc..0c94850e78608c2cb12b5f90bf4cf80d6fd18e77 100644 (file)
@@ -10,10 +10,10 @@ unsafe impl<'a, T> Send for Inner<'a, T>
 
 // @has lifetimes/struct.Foo.html
 // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
-// "impl<'c, K> Send for Foo<'c, K> where K: for<'b> Fn(&'b bool) -> &'c u8, 'c: 'static"
+// "impl<'c, K> Send for Foo<'c, K>where K: for<'b> Fn(&'b bool) -> &'c u8, 'c: 'static"
 //
 // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
-// "impl<'c, K> Sync for Foo<'c, K> where K: Sync"
+// "impl<'c, K> Sync for Foo<'c, K>where K: Sync"
 pub struct Foo<'c, K: 'c> {
     inner_field: Inner<'c, K>,
 }
index 49bad162211b7041be4ba179022091d2d11f3b9f..35047e3e8c0717349eca64a02043ac1b06c4bc97 100644 (file)
@@ -1,6 +1,6 @@
 // @has manual/struct.Foo.html
 // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
-// 'impl<T> Sync for Foo<T> where T: Sync'
+// 'impl<T> Sync for Foo<T>where T: Sync'
 //
 // @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
 // 'impl<T> Send for Foo<T>'
index 69edbee619e31e8316c1796bcc7916cfd9cd9c28..09587bcc30f13954f3c742080c7ec24be6453d9e 100644 (file)
@@ -10,10 +10,10 @@ unsafe impl<T> Send for Inner<T>
 
 // @has nested/struct.Foo.html
 // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
-// 'impl<T> Send for Foo<T> where T: Copy'
+// 'impl<T> Send for Foo<T>where T: Copy'
 //
 // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
-// 'impl<T> Sync for Foo<T> where T: Sync'
+// 'impl<T> Sync for Foo<T>where T: Sync'
 pub struct Foo<T> {
     inner_field: Inner<T>,
 }
index 16ab876e829ef8f25f4d82d79529e4c89c84f3ca..41375decc8a4aa6c9971764ab82fab822973f17c 100644 (file)
@@ -10,7 +10,7 @@ unsafe impl<T> Send for Inner<T>
 
 // @has no_redundancy/struct.Outer.html
 // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
-// "impl<T> Send for Outer<T> where T: Send + Copy"
+// "impl<T> Send for Outer<T>where T: Send + Copy"
 pub struct Outer<T> {
     inner_field: Inner<T>,
 }
index 8b020582563f3d3ac9fe6cd6be4975c2c66641bf..e80b1b1dc9bcf99c96fc535bcc8d9ca7f9ed470a 100644 (file)
@@ -24,10 +24,10 @@ unsafe impl<'a, T> Sync for Inner<'a, T>
 
 // @has project/struct.Foo.html
 // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
-// "impl<'c, K> Send for Foo<'c, K> where K: MyTrait<MyItem = bool>, 'c: 'static"
+// "impl<'c, K> Send for Foo<'c, K>where K: MyTrait<MyItem = bool>, 'c: 'static"
 //
 // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
-// "impl<'c, K> Sync for Foo<'c, K> where K: MyTrait, <K as MyTrait>::MyItem: OtherTrait, \
+// "impl<'c, K> Sync for Foo<'c, K>where K: MyTrait, <K as MyTrait>::MyItem: OtherTrait, \
 // 'c: 'static,"
 pub struct Foo<'c, K: 'c> {
     inner_field: Inner<'c, K>,
index ccef901b18da3e57b359973eb52e04cb3f5f19ad..d15a8de7d2fe14fdb20381086bc6dc7a6762e58c 100644 (file)
@@ -24,6 +24,6 @@ impl<T> Pattern for Wrapper<T> {
 
 // @has self_referential/struct.WriteAndThen.html
 // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
-// "impl<P1> Send for WriteAndThen<P1>  where  <P1 as Pattern>::Value: Send"
+// "impl<P1> Send for WriteAndThen<P1>where    <P1 as Pattern>::Value: Send"
 pub struct WriteAndThen<P1>(pub P1::Value,pub <Constrain<P1, Wrapper<P1::Value>> as Pattern>::Value)
     where P1: Pattern;
index 36e985144b0e09026e60796a8908419b766eb363..08e9567313e22bb78f0faf6f5701537b6c9e3ecf 100644 (file)
@@ -4,7 +4,7 @@ pub trait OwnedTrait<'a> {
 
 // @has static_region/struct.Owned.html
 // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
-// "impl<T> Send for Owned<T> where <T as OwnedTrait<'static>>::Reader: Send"
+// "impl<T> Send for Owned<T>where <T as OwnedTrait<'static>>::Reader: Send"
 pub struct Owned<T> where T: OwnedTrait<'static> {
     marker: <T as OwnedTrait<'static>>::Reader,
 }
index 3150a8ea05f41f321dde58bbe2dded183deead48..b8502e10a48c4dcb5ad05e763930a673bae55046 100644 (file)
@@ -7,7 +7,7 @@ pub trait SomeTrait<Rhs = Self>
 }
 
 // @has 'foo/trait.SomeTrait.html'
-// @has - "//*[@id='impl-SomeTrait%3C(A%2C%20B%2C%20C%2C%20D%2C%20E)%3E-for-(A%2C%20B%2C%20C%2C%20D%2C%20E)']/h3" "impl<A, B, C, D, E> SomeTrait<(A, B, C, D, E)> for (A, B, C, D, E) where A: PartialOrd<A> + PartialEq<A>, B: PartialOrd<B> + PartialEq<B>, C: PartialOrd<C> + PartialEq<C>, D: PartialOrd<D> + PartialEq<D>, E: PartialOrd<E> + PartialEq<E> + ?Sized, "
+// @has - "//*[@id='impl-SomeTrait%3C(A%2C%20B%2C%20C%2C%20D%2C%20E)%3E-for-(A%2C%20B%2C%20C%2C%20D%2C%20E)']/h3" "impl<A, B, C, D, E> SomeTrait<(A, B, C, D, E)> for (A, B, C, D, E)where A: PartialOrd<A> + PartialEq<A>, B: PartialOrd<B> + PartialEq<B>, C: PartialOrd<C> + PartialEq<C>, D: PartialOrd<D> + PartialEq<D>, E: PartialOrd<E> + PartialEq<E> + ?Sized, "
 impl<A, B, C, D, E> SomeTrait<(A, B, C, D, E)> for (A, B, C, D, E)
 where
     A: PartialOrd<A> + PartialEq<A>,
index 50a5722fbaff6926e5feec51c6ffd18d531bac5a..c1a630e25ba0ef00881c4682afd10ed922f97351 100644 (file)
@@ -3,17 +3,17 @@
 
 pub trait MyTrait { fn dummy(&self) { } }
 
-// @has foo/struct.Alpha.html '//pre' "pub struct Alpha<A>(_) where A: MyTrait"
+// @has foo/struct.Alpha.html '//pre' "pub struct Alpha<A>(_)where A: MyTrait"
 pub struct Alpha<A>(A) where A: MyTrait;
-// @has foo/trait.Bravo.html '//pre' "pub trait Bravo<B> where B: MyTrait"
+// @has foo/trait.Bravo.html '//pre' "pub trait Bravo<B>where B: MyTrait"
 pub trait Bravo<B> where B: MyTrait { fn get(&self, B: B); }
-// @has foo/fn.charlie.html '//pre' "pub fn charlie<C>() where C: MyTrait"
+// @has foo/fn.charlie.html '//pre' "pub fn charlie<C>()where C: MyTrait"
 pub fn charlie<C>() where C: MyTrait {}
 
 pub struct Delta<D>(D);
 
 // @has foo/struct.Delta.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
-//          "impl<D> Delta<D> where D: MyTrait"
+//          "impl<D> Delta<D>where D: MyTrait"
 impl<D> Delta<D> where D: MyTrait {
     pub fn delta() {}
 }
@@ -33,19 +33,19 @@ pub trait TraitWhere {
 }
 
 // @has foo/struct.Echo.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
-//          "impl<E> MyTrait for Echo<E> where E: MyTrait"
+//          "impl<E> MyTrait for Echo<E>where E: MyTrait"
 // @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//h3[@class="code-header in-band"]' \
-//          "impl<E> MyTrait for Echo<E> where E: MyTrait"
-impl<E> MyTrait for Echo<E> where E: MyTrait {}
+//          "impl<E> MyTrait for Echo<E>where E: MyTrait"
+impl<E> MyTrait for Echo<E>where E: MyTrait {}
 
 pub enum Foxtrot<F> { Foxtrot1(F) }
 
 // @has foo/enum.Foxtrot.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
-//          "impl<F> MyTrait for Foxtrot<F> where F: MyTrait"
+//          "impl<F> MyTrait for Foxtrot<F>where F: MyTrait"
 // @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//h3[@class="code-header in-band"]' \
-//          "impl<F> MyTrait for Foxtrot<F> where F: MyTrait"
-impl<F> MyTrait for Foxtrot<F> where F: MyTrait {}
+//          "impl<F> MyTrait for Foxtrot<F>where F: MyTrait"
+impl<F> MyTrait for Foxtrot<F>where F: MyTrait {}
 
 // @has foo/type.Golf.html '//pre[@class="rust typedef"]' \
-//          "type Golf<T> where T: Clone, = (T, T)"
+//          "type Golf<T>where T: Clone, = (T, T)"
 pub type Golf<T> where T: Clone = (T, T);
index b1f557cb94de8538e58ef71051a7628f05fbf842..c1c109ac1eade556f168b1c2000ef8ff04d624e2 100644 (file)
@@ -2,7 +2,7 @@
 // Tests error conditions for specifying diagnostics using #[derive(SessionDiagnostic)]
 
 // normalize-stderr-test "the following other types implement trait `IntoDiagnosticArg`:(?:.*\n){0,9}\s+and \d+ others" -> "normalized in stderr"
-
+// normalize-stderr-test "diagnostic_builder\.rs:[0-9]+:[0-9]+" -> "diagnostic_builder.rs:LL:CC"
 // The proc_macro2 crate handles spans differently when on beta/stable release rather than nightly,
 // changing the output of this test. Since SessionDiagnostic is strictly internal to the compiler
 // the test is just ignored on stable and beta:
index 621c59f448951ed0d972684a86272be7438063bf..ab5c28fe473326aa02b4a5a42cd62e32a4dc57e5 100644 (file)
@@ -453,7 +453,7 @@ LL | #[derive(SessionDiagnostic)]
    |
    = help: normalized in stderr
 note: required by a bound in `DiagnosticBuilder::<'a, G>::set_arg`
-  --> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:569:19
+  --> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:LL:CC
    |
 LL |         arg: impl IntoDiagnosticArg,
    |                   ^^^^^^^^^^^^^^^^^ required by this bound in `DiagnosticBuilder::<'a, G>::set_arg`
index f0843c60543df4203c9a15cb6a8560196567aa82..812ca0c72bd058178d518b539eb4c709db737759 100644 (file)
@@ -167,8 +167,8 @@ enum P {
 #[derive(SessionSubdiagnostic)]
 enum Q {
     #[bar]
-//~^ ERROR `#[bar]` is not a valid attribute
-//~^^ ERROR cannot find attribute `bar` in this scope
+    //~^ ERROR `#[bar]` is not a valid attribute
+    //~^^ ERROR cannot find attribute `bar` in this scope
     A {
         #[primary_span]
         span: Span,
@@ -179,8 +179,8 @@ enum Q {
 #[derive(SessionSubdiagnostic)]
 enum R {
     #[bar = "..."]
-//~^ ERROR `#[bar = ...]` is not a valid attribute
-//~^^ ERROR cannot find attribute `bar` in this scope
+    //~^ ERROR `#[bar = ...]` is not a valid attribute
+    //~^^ ERROR cannot find attribute `bar` in this scope
     A {
         #[primary_span]
         span: Span,
@@ -191,8 +191,8 @@ enum R {
 #[derive(SessionSubdiagnostic)]
 enum S {
     #[bar = 4]
-//~^ ERROR `#[bar = ...]` is not a valid attribute
-//~^^ ERROR cannot find attribute `bar` in this scope
+    //~^ ERROR `#[bar = ...]` is not a valid attribute
+    //~^^ ERROR cannot find attribute `bar` in this scope
     A {
         #[primary_span]
         span: Span,
@@ -203,8 +203,8 @@ enum S {
 #[derive(SessionSubdiagnostic)]
 enum T {
     #[bar("...")]
-//~^ ERROR `#[bar("...")]` is not a valid attribute
-//~^^ ERROR cannot find attribute `bar` in this scope
+    //~^ ERROR `#[bar(...)]` is not a valid attribute
+    //~^^ ERROR cannot find attribute `bar` in this scope
     A {
         #[primary_span]
         span: Span,
@@ -215,7 +215,7 @@ enum T {
 #[derive(SessionSubdiagnostic)]
 enum U {
     #[label(code = "...")]
-//~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute
+    //~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute
     A {
         #[primary_span]
         span: Span,
@@ -232,7 +232,7 @@ enum V {
         var: String,
     },
     B {
-//~^ ERROR subdiagnostic kind not specified
+    //~^ ERROR subdiagnostic kind not specified
         #[primary_span]
         span: Span,
         var: String,
@@ -307,6 +307,14 @@ union AC {
     b: u64
 }
 
+#[derive(SessionSubdiagnostic)]
+#[label(parser::add_paren)]
+#[label(parser::add_paren)]
+struct AD {
+    #[primary_span]
+    span: Span,
+}
+
 #[derive(SessionSubdiagnostic)]
 #[label(parser::add_paren, parser::add_paren)]
 //~^ ERROR `#[label(parser::add_paren)]` is not a valid attribute
@@ -319,16 +327,16 @@ struct AE {
 #[label(parser::add_paren)]
 struct AF {
     #[primary_span]
-//~^ NOTE previously specified here
+    //~^ NOTE previously specified here
     span_a: Span,
     #[primary_span]
-//~^ ERROR specified multiple times
+    //~^ ERROR specified multiple times
     span_b: Span,
 }
 
 #[derive(SessionSubdiagnostic)]
 struct AG {
-//~^ ERROR subdiagnostic kind not specified
+    //~^ ERROR subdiagnostic kind not specified
     #[primary_span]
     span: Span,
 }
@@ -380,27 +388,25 @@ struct AK {
     #[primary_span]
     span: Span,
     #[applicability]
-//~^ NOTE previously specified here
+    //~^ NOTE previously specified here
     applicability_a: Applicability,
     #[applicability]
-//~^ ERROR specified multiple times
+    //~^ ERROR specified multiple times
     applicability_b: Applicability,
 }
 
 #[derive(SessionSubdiagnostic)]
 #[suggestion(parser::add_paren, code = "...")]
-//~^ ERROR suggestion without `applicability`
 struct AL {
     #[primary_span]
     span: Span,
     #[applicability]
-//~^ ERROR the `#[applicability]` attribute can only be applied to fields of type `Applicability`
+    //~^ ERROR the `#[applicability]` attribute can only be applied to fields of type `Applicability`
     applicability: Span,
 }
 
 #[derive(SessionSubdiagnostic)]
 #[suggestion(parser::add_paren, code = "...")]
-//~^ ERROR suggestion without `applicability`
 struct AM {
     #[primary_span]
     span: Span,
@@ -436,8 +442,7 @@ struct AP {
 
 #[derive(SessionSubdiagnostic)]
 #[suggestion(parser::add_paren, code = "...")]
-//~^ ERROR suggestion without `applicability`
-//~^^ ERROR suggestion without `#[primary_span]` field
+//~^ ERROR suggestion without `#[primary_span]` field
 struct AR {
     var: String,
 }
@@ -507,3 +512,120 @@ struct AZ {
     #[primary_span]
     span: Span,
 }
+
+#[derive(SessionSubdiagnostic)]
+#[suggestion(parser::add_paren, code = "...")]
+//~^ ERROR suggestion without `#[primary_span]` field
+struct BA {
+    #[suggestion_part]
+    //~^ ERROR `#[suggestion_part]` is not a valid attribute
+    span: Span,
+    #[suggestion_part(code = "...")]
+    //~^ ERROR `#[suggestion_part(...)]` is not a valid attribute
+    span2: Span,
+    #[applicability]
+    applicability: Applicability,
+    var: String,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")]
+//~^ ERROR multipart suggestion without any `#[suggestion_part(...)]` fields
+//~| ERROR `code` is not a valid nested attribute of a `multipart_suggestion` attribute
+struct BBa {
+    var: String,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")]
+struct BBb {
+    #[suggestion_part]
+    //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."`
+    span1: Span,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")]
+struct BBc {
+    #[suggestion_part()]
+    //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."`
+    span1: Span,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[multipart_suggestion(parser::add_paren)]
+//~^ ERROR multipart suggestion without any `#[suggestion_part(...)]` fields
+struct BC {
+    #[primary_span]
+    //~^ ERROR `#[primary_span]` is not a valid attribute
+    span: Span,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[multipart_suggestion(parser::add_paren)]
+struct BD {
+    #[suggestion_part]
+    //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."`
+    span1: Span,
+    #[suggestion_part()]
+    //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."`
+    span2: Span,
+    #[suggestion_part(foo = "bar")]
+    //~^ ERROR `#[suggestion_part(foo = ...)]` is not a valid attribute
+    span4: Span,
+    #[suggestion_part(code = "...")]
+    //~^ ERROR the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
+    s1: String,
+    #[suggestion_part()]
+    //~^ ERROR the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
+    s2: String,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")]
+struct BE {
+    #[suggestion_part(code = "...", code = ",,,")]
+    //~^ ERROR specified multiple times
+    //~| NOTE previously specified here
+    span: Span,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")]
+struct BF {
+    #[suggestion_part(code = "(")]
+    first: Span,
+    #[suggestion_part(code = ")")]
+    second: Span,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[multipart_suggestion(parser::add_paren)]
+struct BG {
+    #[applicability]
+    appl: Applicability,
+    #[suggestion_part(code = "(")]
+    first: Span,
+    #[suggestion_part(code = ")")]
+    second: Span,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")]
+//~^ NOTE previously specified here
+struct BH {
+    #[applicability]
+    //~^ ERROR specified multiple times
+    appl: Applicability,
+    #[suggestion_part(code = "(")]
+    first: Span,
+    #[suggestion_part(code = ")")]
+    second: Span,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")]
+struct BI {
+    #[suggestion_part(code = "")]
+    spans: Vec<Span>,
+}
index 6bd9144dbf6f0b8e8be1ca2dfb273f4cb1b17cb8..0a0247e898088b41bcb6592e1a53afb59cc76ec8 100644 (file)
@@ -65,16 +65,16 @@ LL | #[label()]
    | ^^^^^^^^^^
 
 error: `code` is not a valid nested attribute of a `label` attribute
-  --> $DIR/subdiagnostic-derive.rs:137:1
+  --> $DIR/subdiagnostic-derive.rs:137:28
    |
 LL | #[label(parser::add_paren, code = "...")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                            ^^^^^^^^^^^^
 
 error: `applicability` is not a valid nested attribute of a `label` attribute
-  --> $DIR/subdiagnostic-derive.rs:146:1
+  --> $DIR/subdiagnostic-derive.rs:146:28
    |
 LL | #[label(parser::add_paren, applicability = "machine-applicable")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: unsupported type attribute for subdiagnostic enum
   --> $DIR/subdiagnostic-derive.rs:155:1
@@ -100,13 +100,11 @@ error: `#[bar = ...]` is not a valid attribute
 LL |     #[bar = 4]
    |     ^^^^^^^^^^
 
-error: `#[bar("...")]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:205:11
+error: `#[bar(...)]` is not a valid attribute
+  --> $DIR/subdiagnostic-derive.rs:205:5
    |
 LL |     #[bar("...")]
-   |           ^^^^^
-   |
-   = help: first argument of the attribute should be the diagnostic slug
+   |     ^^^^^^^^^^^^^
 
 error: diagnostic slug must be first argument of a `#[label(...)]` attribute
   --> $DIR/subdiagnostic-derive.rs:217:5
@@ -163,6 +161,8 @@ error: `#[bar(...)]` is not a valid attribute
    |
 LL |     #[bar("...")]
    |     ^^^^^^^^^^^^^
+   |
+   = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes
 
 error: unexpected unsupported untagged union
   --> $DIR/subdiagnostic-derive.rs:304:1
@@ -175,7 +175,7 @@ LL | | }
    | |_^
 
 error: `#[label(parser::add_paren)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:311:28
+  --> $DIR/subdiagnostic-derive.rs:319:28
    |
 LL | #[label(parser::add_paren, parser::add_paren)]
    |                            ^^^^^^^^^^^^^^^^^
@@ -183,133 +183,225 @@ LL | #[label(parser::add_paren, parser::add_paren)]
    = help: a diagnostic slug must be the first argument to the attribute
 
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:324:5
+  --> $DIR/subdiagnostic-derive.rs:332:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:321:5
+  --> $DIR/subdiagnostic-derive.rs:329:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
 
 error: subdiagnostic kind not specified
-  --> $DIR/subdiagnostic-derive.rs:330:8
+  --> $DIR/subdiagnostic-derive.rs:338:8
    |
 LL | struct AG {
    |        ^^
 
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:367:47
+  --> $DIR/subdiagnostic-derive.rs:375:47
    |
 LL | #[suggestion(parser::add_paren, code = "...", code = "...")]
    |                                               ^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:367:33
+  --> $DIR/subdiagnostic-derive.rs:375:33
    |
 LL | #[suggestion(parser::add_paren, code = "...", code = "...")]
    |                                 ^^^^^^^^^^^^
 
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:385:5
+  --> $DIR/subdiagnostic-derive.rs:393:5
    |
 LL |     #[applicability]
    |     ^^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:382:5
+  --> $DIR/subdiagnostic-derive.rs:390:5
    |
 LL |     #[applicability]
    |     ^^^^^^^^^^^^^^^^
 
 error: the `#[applicability]` attribute can only be applied to fields of type `Applicability`
-  --> $DIR/subdiagnostic-derive.rs:396:5
+  --> $DIR/subdiagnostic-derive.rs:403:5
    |
 LL |     #[applicability]
    |     ^^^^^^^^^^^^^^^^
 
-error: suggestion without `applicability`
-  --> $DIR/subdiagnostic-derive.rs:391:1
+error: suggestion without `code = "..."`
+  --> $DIR/subdiagnostic-derive.rs:416:1
    |
-LL | / #[suggestion(parser::add_paren, code = "...")]
-LL | |
-LL | | struct AL {
-LL | |     #[primary_span]
-...  |
-LL | |     applicability: Span,
-LL | | }
-   | |_^
+LL | #[suggestion(parser::add_paren)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: suggestion without `applicability`
-  --> $DIR/subdiagnostic-derive.rs:402:1
+error: invalid applicability
+  --> $DIR/subdiagnostic-derive.rs:426:46
+   |
+LL | #[suggestion(parser::add_paren, code ="...", applicability = "foo")]
+   |                                              ^^^^^^^^^^^^^^^^^^^^^
+
+error: suggestion without `#[primary_span]` field
+  --> $DIR/subdiagnostic-derive.rs:444:1
    |
 LL | / #[suggestion(parser::add_paren, code = "...")]
 LL | |
-LL | | struct AM {
-LL | |     #[primary_span]
-LL | |     span: Span,
+LL | | struct AR {
+LL | |     var: String,
 LL | | }
    | |_^
 
-error: suggestion without `code = "..."`
-  --> $DIR/subdiagnostic-derive.rs:410:1
+error: unsupported type attribute for subdiagnostic enum
+  --> $DIR/subdiagnostic-derive.rs:458:1
    |
-LL | / #[suggestion(parser::add_paren)]
+LL | #[label]
+   | ^^^^^^^^
+
+error: `var` doesn't refer to a field on this type
+  --> $DIR/subdiagnostic-derive.rs:478:39
+   |
+LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
+   |                                       ^^^^^^^
+
+error: `var` doesn't refer to a field on this type
+  --> $DIR/subdiagnostic-derive.rs:497:43
+   |
+LL |     #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
+   |                                           ^^^^^^^
+
+error: `#[suggestion_part]` is not a valid attribute
+  --> $DIR/subdiagnostic-derive.rs:520:5
+   |
+LL |     #[suggestion_part]
+   |     ^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[suggestion_part(...)]` is only valid in multipart suggestions, use `#[primary_span]` instead
+
+error: `#[suggestion_part(...)]` is not a valid attribute
+  --> $DIR/subdiagnostic-derive.rs:523:5
+   |
+LL |     #[suggestion_part(code = "...")]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[suggestion_part(...)]` is only valid in multipart suggestions
+
+error: suggestion without `#[primary_span]` field
+  --> $DIR/subdiagnostic-derive.rs:517:1
+   |
+LL | / #[suggestion(parser::add_paren, code = "...")]
 LL | |
-LL | | struct AN {
-LL | |     #[primary_span]
+LL | | struct BA {
+LL | |     #[suggestion_part]
 ...  |
-LL | |     applicability: Applicability,
+LL | |     var: String,
 LL | | }
    | |_^
 
-error: invalid applicability
-  --> $DIR/subdiagnostic-derive.rs:420:46
+error: `code` is not a valid nested attribute of a `multipart_suggestion` attribute
+  --> $DIR/subdiagnostic-derive.rs:532:43
    |
-LL | #[suggestion(parser::add_paren, code ="...", applicability = "foo")]
-   |                                              ^^^^^^^^^^^^^^^^^^^^^
+LL | #[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")]
+   |                                           ^^^^^^^^^^^^
 
-error: suggestion without `applicability`
-  --> $DIR/subdiagnostic-derive.rs:438:1
+error: multipart suggestion without any `#[suggestion_part(...)]` fields
+  --> $DIR/subdiagnostic-derive.rs:532:1
    |
-LL | / #[suggestion(parser::add_paren, code = "...")]
+LL | / #[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")]
 LL | |
 LL | |
-LL | | struct AR {
+LL | | struct BBa {
 LL | |     var: String,
 LL | | }
    | |_^
 
-error: suggestion without `#[primary_span]` field
-  --> $DIR/subdiagnostic-derive.rs:438:1
+error: `#[suggestion_part(...)]` attribute without `code = "..."`
+  --> $DIR/subdiagnostic-derive.rs:542:5
    |
-LL | / #[suggestion(parser::add_paren, code = "...")]
+LL |     #[suggestion_part]
+   |     ^^^^^^^^^^^^^^^^^^
+
+error: `#[suggestion_part(...)]` attribute without `code = "..."`
+  --> $DIR/subdiagnostic-derive.rs:550:5
+   |
+LL |     #[suggestion_part()]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: `#[primary_span]` is not a valid attribute
+  --> $DIR/subdiagnostic-derive.rs:559:5
+   |
+LL |     #[primary_span]
+   |     ^^^^^^^^^^^^^^^
+   |
+   = help: multipart suggestions use one or more `#[suggestion_part]`s rather than one `#[primary_span]`
+
+error: multipart suggestion without any `#[suggestion_part(...)]` fields
+  --> $DIR/subdiagnostic-derive.rs:556:1
+   |
+LL | / #[multipart_suggestion(parser::add_paren)]
 LL | |
+LL | | struct BC {
+LL | |     #[primary_span]
 LL | |
-LL | | struct AR {
-LL | |     var: String,
+LL | |     span: Span,
 LL | | }
    | |_^
 
-error: unsupported type attribute for subdiagnostic enum
-  --> $DIR/subdiagnostic-derive.rs:453:1
+error: `#[suggestion_part(...)]` attribute without `code = "..."`
+  --> $DIR/subdiagnostic-derive.rs:567:5
    |
-LL | #[label]
-   | ^^^^^^^^
+LL |     #[suggestion_part]
+   |     ^^^^^^^^^^^^^^^^^^
 
-error: `var` doesn't refer to a field on this type
-  --> $DIR/subdiagnostic-derive.rs:473:39
+error: `#[suggestion_part(...)]` attribute without `code = "..."`
+  --> $DIR/subdiagnostic-derive.rs:570:5
    |
-LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
-   |                                       ^^^^^^^
+LL |     #[suggestion_part()]
+   |     ^^^^^^^^^^^^^^^^^^^^
 
-error: `var` doesn't refer to a field on this type
-  --> $DIR/subdiagnostic-derive.rs:492:43
+error: `#[suggestion_part(foo = ...)]` is not a valid attribute
+  --> $DIR/subdiagnostic-derive.rs:573:23
    |
-LL |     #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
-   |                                           ^^^^^^^
+LL |     #[suggestion_part(foo = "bar")]
+   |                       ^^^^^^^^^^^
+   |
+   = help: `code` is the only valid nested attribute
+
+error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
+  --> $DIR/subdiagnostic-derive.rs:576:5
+   |
+LL |     #[suggestion_part(code = "...")]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
+  --> $DIR/subdiagnostic-derive.rs:579:5
+   |
+LL |     #[suggestion_part()]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: specified multiple times
+  --> $DIR/subdiagnostic-derive.rs:587:37
+   |
+LL |     #[suggestion_part(code = "...", code = ",,,")]
+   |                                     ^^^^^^^^^^^^
+   |
+note: previously specified here
+  --> $DIR/subdiagnostic-derive.rs:587:23
+   |
+LL |     #[suggestion_part(code = "...", code = ",,,")]
+   |                       ^^^^^^^^^^^^
+
+error: specified multiple times
+  --> $DIR/subdiagnostic-derive.rs:617:5
+   |
+LL |     #[applicability]
+   |     ^^^^^^^^^^^^^^^^
+   |
+note: previously specified here
+  --> $DIR/subdiagnostic-derive.rs:614:43
+   |
+LL | #[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")]
+   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: cannot find attribute `foo` in this scope
   --> $DIR/subdiagnostic-derive.rs:63:3
@@ -371,6 +463,6 @@ error[E0425]: cannot find value `slug` in module `rustc_errors::fluent`
 LL | #[label(slug)]
    |         ^^^^ not found in `rustc_errors::fluent`
 
-error: aborting due to 50 previous errors
+error: aborting due to 63 previous errors
 
 For more information about this error, try `rustc --explain E0425`.
index c495ad6b842f8bb8056b819e23b3e0869e0ff7c1..b118ce1bd0ea95e433aa1a4e7824b87d0a632bb5 100644 (file)
@@ -26,7 +26,7 @@ LL | fn extra() {}
 help: remove the extra argument
    |
 LL |     extra();
-   |     ~~~~~~~
+   |          ~~
 
 error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/basic.rs:22:5
@@ -42,7 +42,7 @@ LL | fn missing(_i: u32) {}
 help: provide the argument
    |
 LL |     missing(/* u32 */);
-   |     ~~~~~~~~~~~~~~~~~~
+   |            ~~~~~~~~~~~
 
 error[E0308]: arguments to this function are incorrect
   --> $DIR/basic.rs:23:5
@@ -60,7 +60,7 @@ LL | fn swapped(_i: u32, _s: &str) {}
 help: swap these arguments
    |
 LL |     swapped(1, "");
-   |     ~~~~~~~~~~~~~~
+   |            ~~~~~~~
 
 error[E0308]: arguments to this function are incorrect
   --> $DIR/basic.rs:24:5
@@ -79,7 +79,7 @@ LL | fn permuted(_x: X, _y: Y, _z: Z) {}
 help: reorder these arguments
    |
 LL |     permuted(X {}, Y {}, Z {});
-   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |             ~~~~~~~~~~~~~~~~~~
 
 error[E0057]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/basic.rs:27:5
@@ -95,7 +95,7 @@ LL |     let closure = |x| x;
 help: provide the argument
    |
 LL |     closure(/* value */);
-   |     ~~~~~~~~~~~~~~~~~~~~
+   |            ~~~~~~~~~~~~~
 
 error: aborting due to 6 previous errors
 
index bf49e7444583b55eecb43ecd31e8dc544f657aaa..205a852983a3b0379213d9bcb084cea03231b696 100644 (file)
@@ -12,7 +12,7 @@ LL | fn complex(_i: u32, _s: &str, _e: E, _f: F, _g: G, _x: X, _y: Y, _z: Z ) {}
 help: did you mean
    |
 LL |   complex(/* u32 */, &"", /* E */, F::X2, G{}, X {}, Y {}, Z {});
-   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to previous error
 
index ca93ecc4e381a9407d27f2b5d2c923e51025cc89..0580e53c510af5ed3f8d4b0af8d0ba22a7c9d0be 100644 (file)
@@ -12,7 +12,7 @@ LL | fn foo<T: Fn()>(t: T) {
 help: remove the extra argument
    |
 LL |     t();
-   |     ~~~
+   |      ~~
 
 error[E0057]: this function takes 0 arguments but 1 argument was supplied
   --> $DIR/exotic-calls.rs:7:5
@@ -28,7 +28,7 @@ LL | fn bar(t: impl Fn()) {
 help: remove the extra argument
    |
 LL |     t();
-   |     ~~~
+   |      ~~
 
 error[E0057]: this function takes 0 arguments but 1 argument was supplied
   --> $DIR/exotic-calls.rs:16:5
@@ -44,7 +44,7 @@ LL | fn baz() -> impl Fn() {
 help: remove the extra argument
    |
 LL |     baz()()
-   |
+   |          ~~
 
 error[E0057]: this function takes 0 arguments but 1 argument was supplied
   --> $DIR/exotic-calls.rs:22:5
@@ -60,7 +60,7 @@ LL |     let x = || {};
 help: remove the extra argument
    |
 LL |     x();
-   |     ~~~
+   |      ~~
 
 error: aborting due to 4 previous errors
 
index 32b1e15737ab9370bc007fd78b5fe2ffa9e61efd..48787b0c352cee8e3ccb2f42a2120bbfb475f994 100644 (file)
@@ -12,7 +12,7 @@ LL | fn empty() {}
 help: remove the extra argument
    |
 LL |   empty();
-   |   ~~~~~~~
+   |        ~~
 
 error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/extra_arguments.rs:9:3
@@ -28,7 +28,7 @@ LL | fn one_arg(_a: i32) {}
 help: remove the extra argument
    |
 LL |   one_arg(1);
-   |   ~~~~~~~~~~
+   |          ~~~
 
 error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/extra_arguments.rs:10:3
@@ -44,7 +44,7 @@ LL | fn one_arg(_a: i32) {}
 help: remove the extra argument
    |
 LL |   one_arg(1);
-   |   ~~~~~~~~~~
+   |          ~~~
 
 error[E0061]: this function takes 1 argument but 3 arguments were supplied
   --> $DIR/extra_arguments.rs:11:3
@@ -62,7 +62,7 @@ LL | fn one_arg(_a: i32) {}
 help: remove the extra arguments
    |
 LL |   one_arg(1);
-   |   ~~~~~~~~~~
+   |          ~~~
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/extra_arguments.rs:13:3
@@ -78,7 +78,7 @@ LL | fn two_arg_same(_a: i32, _b: i32) {}
 help: remove the extra argument
    |
 LL |   two_arg_same(1, 1);
-   |   ~~~~~~~~~~~~~~~~~~
+   |               ~~~~~~
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/extra_arguments.rs:14:3
@@ -94,7 +94,7 @@ LL | fn two_arg_same(_a: i32, _b: i32) {}
 help: remove the extra argument
    |
 LL |   two_arg_same(1, 1);
-   |   ~~~~~~~~~~~~~~~~~~
+   |               ~~~~~~
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/extra_arguments.rs:16:3
@@ -110,7 +110,7 @@ LL | fn two_arg_diff(_a: i32, _b: &str) {}
 help: remove the extra argument
    |
 LL |   two_arg_diff(1, "");
-   |   ~~~~~~~~~~~~~~~~~~~
+   |               ~~~~~~~
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/extra_arguments.rs:17:3
@@ -126,7 +126,7 @@ LL | fn two_arg_diff(_a: i32, _b: &str) {}
 help: remove the extra argument
    |
 LL |   two_arg_diff(1, "");
-   |   ~~~~~~~~~~~~~~~~~~~
+   |               ~~~~~~~
 
 error[E0061]: this function takes 2 arguments but 4 arguments were supplied
   --> $DIR/extra_arguments.rs:18:3
@@ -144,7 +144,7 @@ LL | fn two_arg_diff(_a: i32, _b: &str) {}
 help: remove the extra arguments
    |
 LL |   two_arg_diff(1, "");
-   |   ~~~~~~~~~~~~~~~~~~~
+   |               ~~~~~~~
 
 error[E0061]: this function takes 2 arguments but 4 arguments were supplied
   --> $DIR/extra_arguments.rs:19:3
@@ -162,7 +162,7 @@ LL | fn two_arg_diff(_a: i32, _b: &str) {}
 help: remove the extra arguments
    |
 LL |   two_arg_diff(1, "");
-   |   ~~~~~~~~~~~~~~~~~~~
+   |               ~~~~~~~
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/extra_arguments.rs:22:3
@@ -178,7 +178,7 @@ LL | fn two_arg_same(_a: i32, _b: i32) {}
 help: remove the extra argument
    |
 LL |   two_arg_same(1, 1);
-   |   ~~~~~~~~~~~~~~~~~~
+   |               ~~~~~~
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/extra_arguments.rs:23:3
@@ -194,7 +194,7 @@ LL | fn two_arg_diff(_a: i32, _b: &str) {}
 help: remove the extra argument
    |
 LL |   two_arg_diff(1, "");
-   |   ~~~~~~~~~~~~~~~~~~~
+   |               ~~~~~~~
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/extra_arguments.rs:24:3
@@ -213,7 +213,7 @@ LL | fn two_arg_same(_a: i32, _b: i32) {}
 help: remove the extra argument
    |
 LL |   two_arg_same(1, 1);
-   |   ~~~~~~~~~~~~~~~~~~
+   |               ~~~~~~
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/extra_arguments.rs:30:3
@@ -232,7 +232,7 @@ LL | fn two_arg_diff(_a: i32, _b: &str) {}
 help: remove the extra argument
    |
 LL |   two_arg_diff(1, "");
-   |   ~~~~~~~~~~~~~~~~~~~
+   |               ~~~~~~~
 
 error: aborting due to 14 previous errors
 
index 804cb1aa322190344eecfd1d60c619cfce52f32a..4d18b97c98be1ade8db2c463fad3fc38bd5a9bf2 100644 (file)
@@ -14,7 +14,7 @@ LL | fn f(_: usize, _: &usize, _: usize) {}
 help: provide the argument
    |
 LL |     f(/* usize */, &x, /* usize */);
-   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to previous error
 
index ac54adc5eeb92997f9f3ce007d0c40b4ebc7f90c..de221ba1fe18078b8b99b979944a8acab579f2fc 100644 (file)
@@ -12,7 +12,7 @@ LL | pub fn g(a1: (), a2: bool, a3: bool, a4: bool, a5: bool, a6: ()) -> () {}
 help: provide the arguments
    |
 LL |     g((), /* bool */, /* bool */, /* bool */, /* bool */, ());
-   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to previous error
 
index b5dedf0f4fa05494a8b9dea6823f83639cda07ef..caa50f14b43e1e56da9df7e49a7f3016558532ad 100644 (file)
@@ -20,7 +20,7 @@ LL |     foo(&&A, B, C, D, &E, F, G);
 help: remove the extra arguments
    |
 LL |     foo(&&A, D, /* &E */, G);
-   |     ~~~~~~~~~~~~~~~~~~~~~~~~
+   |        ~~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to previous error
 
index 0c8b94901e16f4967b790c04ef2310dff26694a4..f64a83ab710674baad01999f437823940b1ff90a 100644 (file)
@@ -12,7 +12,7 @@ LL |     (|_, ()| ())(if true {} else {return;});
 help: provide the argument
    |
 LL |     (|_, ()| ())(if true {} else {return;}, ());
-   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to previous error
 
index 8f0d98d09e89e1e68b96401d3d2a99358e39a5e4..f2c47d353efad2b3636eef5462866affae985254 100644 (file)
@@ -12,7 +12,7 @@ LL |     (|_, ()| ())([return, ()]);
 help: provide the argument
    |
 LL |     (|_, ()| ())([return, ()], ());
-   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                 ~~~~~~~~~~~~~~~~~~
 
 error: aborting due to previous error
 
index bc005e82a2c46146ac359a93806df0aaedca9950..bcf36e37cdccfdbf372713a39f535cf5a814e46a 100644 (file)
@@ -12,7 +12,7 @@ LL |     let f = |_: (), f: fn()| f;
 help: provide the argument
    |
 LL |     let _f = f((), main);
-   |              ~~~~~~~~~~~
+   |               ~~~~~~~~~~
 
 error: aborting due to previous error
 
index 2509d22d7ff82e1f736a81466f4c9b63709cefc5..ba9ece040bec7a8a4e5494ef1f5fd0e8f19e9832 100644 (file)
@@ -12,7 +12,7 @@ LL | fn one_arg(_a: i32) {}
 help: provide the argument
    |
 LL |   one_arg(/* i32 */);
-   |   ~~~~~~~~~~~~~~~~~~
+   |          ~~~~~~~~~~~
 
 error[E0061]: this function takes 2 arguments but 0 arguments were supplied
   --> $DIR/missing_arguments.rs:14:3
@@ -28,7 +28,7 @@ LL | fn two_same(_a: i32, _b: i32) {}
 help: provide the arguments
    |
 LL |   two_same(/* i32 */, /* i32 */);
-   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |           ~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0061]: this function takes 2 arguments but 1 argument was supplied
   --> $DIR/missing_arguments.rs:15:3
@@ -44,7 +44,7 @@ LL | fn two_same(_a: i32, _b: i32) {}
 help: provide the argument
    |
 LL |   two_same(1, /* i32 */);
-   |   ~~~~~~~~~~~~~~~~~~~~~~
+   |           ~~~~~~~~~~~~~~
 
 error[E0061]: this function takes 2 arguments but 0 arguments were supplied
   --> $DIR/missing_arguments.rs:16:3
@@ -60,7 +60,7 @@ LL | fn two_diff(_a: i32, _b: f32) {}
 help: provide the arguments
    |
 LL |   two_diff(/* i32 */, /* f32 */);
-   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |           ~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0061]: this function takes 2 arguments but 1 argument was supplied
   --> $DIR/missing_arguments.rs:17:3
@@ -76,7 +76,7 @@ LL | fn two_diff(_a: i32, _b: f32) {}
 help: provide the argument
    |
 LL |   two_diff(1, /* f32 */);
-   |   ~~~~~~~~~~~~~~~~~~~~~~
+   |           ~~~~~~~~~~~~~~
 
 error[E0061]: this function takes 2 arguments but 1 argument was supplied
   --> $DIR/missing_arguments.rs:18:3
@@ -92,7 +92,7 @@ LL | fn two_diff(_a: i32, _b: f32) {}
 help: provide the argument
    |
 LL |   two_diff(/* i32 */, 1.0);
-   |   ~~~~~~~~~~~~~~~~~~~~~~~~
+   |           ~~~~~~~~~~~~~~~~
 
 error[E0061]: this function takes 3 arguments but 0 arguments were supplied
   --> $DIR/missing_arguments.rs:21:3
@@ -108,7 +108,7 @@ LL | fn three_same(_a: i32, _b: i32, _c: i32) {}
 help: provide the arguments
    |
 LL |   three_same(/* i32 */, /* i32 */, /* i32 */);
-   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0061]: this function takes 3 arguments but 1 argument was supplied
   --> $DIR/missing_arguments.rs:22:3
@@ -124,7 +124,7 @@ LL | fn three_same(_a: i32, _b: i32, _c: i32) {}
 help: provide the arguments
    |
 LL |   three_same(1, /* i32 */, /* i32 */);
-   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |             ~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0061]: this function takes 3 arguments but 2 arguments were supplied
   --> $DIR/missing_arguments.rs:23:3
@@ -140,7 +140,7 @@ LL | fn three_same(_a: i32, _b: i32, _c: i32) {}
 help: provide the argument
    |
 LL |   three_same(1, 1, /* i32 */);
-   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |             ~~~~~~~~~~~~~~~~~
 
 error[E0061]: this function takes 3 arguments but 2 arguments were supplied
   --> $DIR/missing_arguments.rs:26:3
@@ -156,7 +156,7 @@ LL | fn three_diff(_a: i32, _b: f32, _c: &str) {}
 help: provide the argument
    |
 LL |   three_diff(/* i32 */, 1.0, "");
-   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |             ~~~~~~~~~~~~~~~~~~~~
 
 error[E0061]: this function takes 3 arguments but 2 arguments were supplied
   --> $DIR/missing_arguments.rs:27:3
@@ -172,7 +172,7 @@ LL | fn three_diff(_a: i32, _b: f32, _c: &str) {}
 help: provide the argument
    |
 LL |   three_diff(1, /* f32 */, "");
-   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |             ~~~~~~~~~~~~~~~~~~
 
 error[E0061]: this function takes 3 arguments but 2 arguments were supplied
   --> $DIR/missing_arguments.rs:28:3
@@ -188,7 +188,7 @@ LL | fn three_diff(_a: i32, _b: f32, _c: &str) {}
 help: provide the argument
    |
 LL |   three_diff(1, 1.0, /* &str */);
-   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |             ~~~~~~~~~~~~~~~~~~~~
 
 error[E0061]: this function takes 3 arguments but 1 argument was supplied
   --> $DIR/missing_arguments.rs:29:3
@@ -204,7 +204,7 @@ LL | fn three_diff(_a: i32, _b: f32, _c: &str) {}
 help: provide the arguments
    |
 LL |   three_diff(/* i32 */, /* f32 */, "");
-   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |             ~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0061]: this function takes 3 arguments but 1 argument was supplied
   --> $DIR/missing_arguments.rs:30:3
@@ -223,7 +223,7 @@ LL | fn three_diff(_a: i32, _b: f32, _c: &str) {}
 help: provide the arguments
    |
 LL |   three_diff(/* i32 */, 1.0, /* &str */);
-   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0061]: this function takes 3 arguments but 1 argument was supplied
   --> $DIR/missing_arguments.rs:31:3
@@ -239,7 +239,7 @@ LL | fn three_diff(_a: i32, _b: f32, _c: &str) {}
 help: provide the arguments
    |
 LL |   three_diff(1, /* f32 */, /* &str */);
-   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |             ~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0061]: this function takes 4 arguments but 0 arguments were supplied
   --> $DIR/missing_arguments.rs:34:3
@@ -255,7 +255,7 @@ LL | fn four_repeated(_a: i32, _b: f32, _c: f32, _d: &str) {}
 help: provide the arguments
    |
 LL |   four_repeated(/* i32 */, /* f32 */, /* f32 */, /* &str */);
-   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0061]: this function takes 4 arguments but 2 arguments were supplied
   --> $DIR/missing_arguments.rs:35:3
@@ -271,7 +271,7 @@ LL | fn four_repeated(_a: i32, _b: f32, _c: f32, _d: &str) {}
 help: provide the arguments
    |
 LL |   four_repeated(1, /* f32 */, /* f32 */, "");
-   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0061]: this function takes 5 arguments but 0 arguments were supplied
   --> $DIR/missing_arguments.rs:38:3
@@ -287,7 +287,7 @@ LL | fn complex(_a: i32, _b: f32, _c: i32, _d: f32, _e: &str) {}
 help: provide the arguments
    |
 LL |   complex(/* i32 */, /* f32 */, /* i32 */, /* f32 */, /* &str */);
-   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0061]: this function takes 5 arguments but 2 arguments were supplied
   --> $DIR/missing_arguments.rs:39:3
@@ -303,7 +303,7 @@ LL | fn complex(_a: i32, _b: f32, _c: i32, _d: f32, _e: &str) {}
 help: provide the arguments
    |
 LL |   complex(1, /* f32 */, /* i32 */, /* f32 */, "");
-   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to 19 previous errors
 
index a52a30d7884f899f2ea3c8be9aa17444fd9962ab..8c525db1ac66ca03528993dad5a055d464a3520d 100644 (file)
@@ -14,7 +14,7 @@ LL | fn two_args(_a: i32, _b: f32) {}
 help: remove the extra argument
    |
 LL |   two_args(1, /* f32 */);
-   |   ~~~~~~~~~~~~~~~~~~~~~~
+   |           ~~~~~~~~~~~~~~
 
 error[E0061]: this function takes 3 arguments but 4 arguments were supplied
   --> $DIR/mixed_cases.rs:11:3
@@ -33,7 +33,7 @@ LL | fn three_args(_a: i32, _b: f32, _c: &str) {}
 help: did you mean
    |
 LL |   three_args(1, /* f32 */, "");
-   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |             ~~~~~~~~~~~~~~~~~~
 
 error[E0061]: this function takes 3 arguments but 2 arguments were supplied
   --> $DIR/mixed_cases.rs:14:3
@@ -52,7 +52,7 @@ LL | fn three_args(_a: i32, _b: f32, _c: &str) {}
 help: provide the argument
    |
 LL |   three_args(1, /* f32 */, /* &str */);
-   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |             ~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0308]: arguments to this function are incorrect
   --> $DIR/mixed_cases.rs:17:3
@@ -70,7 +70,7 @@ LL | fn three_args(_a: i32, _b: f32, _c: &str) {}
 help: did you mean
    |
 LL |   three_args(1, /* f32 */, "");
-   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |             ~~~~~~~~~~~~~~~~~~
 
 error[E0308]: arguments to this function are incorrect
   --> $DIR/mixed_cases.rs:20:3
@@ -89,7 +89,7 @@ LL | fn three_args(_a: i32, _b: f32, _c: &str) {}
 help: swap these arguments
    |
 LL |   three_args(1, /* f32 */, "");
-   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |             ~~~~~~~~~~~~~~~~~~
 
 error[E0061]: this function takes 3 arguments but 2 arguments were supplied
   --> $DIR/mixed_cases.rs:23:3
@@ -109,7 +109,7 @@ LL | fn three_args(_a: i32, _b: f32, _c: &str) {}
 help: did you mean
    |
 LL |   three_args(1, /* f32 */, "");
-   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |             ~~~~~~~~~~~~~~~~~~
 
 error: aborting due to 6 previous errors
 
index f16d22860d807c4aebc8c0a43fc86a630c2a015c..655807a7f382f41f2b471537e074963233a4733e 100644 (file)
@@ -15,7 +15,7 @@ LL | fn three_args(_a: i32, _b: f32, _c: &str) {}
 help: reorder these arguments
    |
 LL |   three_args(1, 1.0, "");
-   |   ~~~~~~~~~~~~~~~~~~~~~~
+   |             ~~~~~~~~~~~~
 
 error[E0308]: arguments to this function are incorrect
   --> $DIR/permuted_arguments.rs:12:3
@@ -36,7 +36,7 @@ LL | fn many_args(_a: i32, _b: f32, _c: &str, _d: X, _e: Y) {}
 help: reorder these arguments
    |
 LL |   many_args(1, 1.0, "", X {}, Y {});
-   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |            ~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to 2 previous errors
 
index a90792d0c5340296c316d01b03782567bdab9a02..dabf5e952b26bd754bf94b374c719701d71afb1a 100644 (file)
@@ -14,7 +14,7 @@ LL | fn two_args(_a: i32, _b: f32) {}
 help: swap these arguments
    |
 LL |   two_args(1, 1.0);
-   |   ~~~~~~~~~~~~~~~~
+   |           ~~~~~~~~
 
 error[E0308]: arguments to this function are incorrect
   --> $DIR/swapped_arguments.rs:9:3
@@ -32,7 +32,7 @@ LL | fn three_args(_a: i32, _b: f32, _c: &str) {}
 help: swap these arguments
    |
 LL |   three_args(1, 1.0, "");
-   |   ~~~~~~~~~~~~~~~~~~~~~~
+   |             ~~~~~~~~~~~~
 
 error[E0308]: arguments to this function are incorrect
   --> $DIR/swapped_arguments.rs:10:3
@@ -50,7 +50,7 @@ LL | fn three_args(_a: i32, _b: f32, _c: &str) {}
 help: swap these arguments
    |
 LL |   three_args(1, 1.0, "");
-   |   ~~~~~~~~~~~~~~~~~~~~~~
+   |             ~~~~~~~~~~~~
 
 error[E0308]: arguments to this function are incorrect
   --> $DIR/swapped_arguments.rs:11:3
@@ -68,7 +68,7 @@ LL | fn three_args(_a: i32, _b: f32, _c: &str) {}
 help: swap these arguments
    |
 LL |   three_args(1, 1.0, "");
-   |   ~~~~~~~~~~~~~~~~~~~~~~
+   |             ~~~~~~~~~~~~
 
 error[E0308]: arguments to this function are incorrect
   --> $DIR/swapped_arguments.rs:13:3
@@ -88,7 +88,7 @@ LL | fn four_args(_a: i32, _b: f32, _c: &str, _d: X) {}
 help: did you mean
    |
 LL |   four_args(1, 1.0, "", X {});
-   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |            ~~~~~~~~~~~~~~~~~~
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/asm/unpretty-expanded.rs b/src/test/ui/asm/unpretty-expanded.rs
new file mode 100644 (file)
index 0000000..6128f49
--- /dev/null
@@ -0,0 +1,3 @@
+// check-pass
+// compile-flags: -Zunpretty=expanded
+core::arch::global_asm!("x: .byte 42");
diff --git a/src/test/ui/asm/unpretty-expanded.stdout b/src/test/ui/asm/unpretty-expanded.stdout
new file mode 100644 (file)
index 0000000..15b60d1
--- /dev/null
@@ -0,0 +1,9 @@
+#![feature(prelude_import)]
+#![no_std]
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+#[macro_use]
+extern crate std;
+// check-pass
+// compile-flags: -Zunpretty=expanded
+global_asm! ("x: .byte 42");
index c993e1d27202d5a53ac33f843623d48b8bd24852..00066efccb8dd2229766a28170703ca18a8388ea 100644 (file)
@@ -29,12 +29,14 @@ pub fn f1_uint_uint() {
     f1(2u32, 4u32);
     //~^ ERROR `u32: Foo` is not satisfied
     //~| ERROR `u32: Foo` is not satisfied
+    //~| ERROR `u32: Foo` is not satisfied
 }
 
 pub fn f1_uint_int() {
     f1(2u32, 4i32);
     //~^ ERROR `u32: Foo` is not satisfied
     //~| ERROR `u32: Foo` is not satisfied
+    //~| ERROR `u32: Foo` is not satisfied
 }
 
 pub fn f2_int() {
index 5edd5c864e1357b44b0c6407bef4d309bc3139ec..206f4902410269912d13d6986d1c12add2cb313e 100644 (file)
@@ -31,6 +31,14 @@ note: required by a bound in `f1`
 LL | pub fn f1<T: Foo>(a: T, x: T::A) {}
    |              ^^^ required by this bound in `f1`
 
+error[E0277]: the trait bound `u32: Foo` is not satisfied
+  --> $DIR/associated-types-path-2.rs:29:5
+   |
+LL |     f1(2u32, 4u32);
+   |     ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `u32`
+   |
+   = help: the trait `Foo` is implemented for `i32`
+
 error[E0277]: the trait bound `u32: Foo` is not satisfied
   --> $DIR/associated-types-path-2.rs:29:14
    |
@@ -40,7 +48,7 @@ LL |     f1(2u32, 4u32);
    = help: the trait `Foo` is implemented for `i32`
 
 error[E0277]: the trait bound `u32: Foo` is not satisfied
-  --> $DIR/associated-types-path-2.rs:35:8
+  --> $DIR/associated-types-path-2.rs:36:8
    |
 LL |     f1(2u32, 4i32);
    |     -- ^^^^ the trait `Foo` is not implemented for `u32`
@@ -55,7 +63,15 @@ LL | pub fn f1<T: Foo>(a: T, x: T::A) {}
    |              ^^^ required by this bound in `f1`
 
 error[E0277]: the trait bound `u32: Foo` is not satisfied
-  --> $DIR/associated-types-path-2.rs:35:14
+  --> $DIR/associated-types-path-2.rs:36:5
+   |
+LL |     f1(2u32, 4i32);
+   |     ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `u32`
+   |
+   = help: the trait `Foo` is implemented for `i32`
+
+error[E0277]: the trait bound `u32: Foo` is not satisfied
+  --> $DIR/associated-types-path-2.rs:36:14
    |
 LL |     f1(2u32, 4i32);
    |              ^^^^ the trait `Foo` is not implemented for `u32`
@@ -63,7 +79,7 @@ LL |     f1(2u32, 4i32);
    = help: the trait `Foo` is implemented for `i32`
 
 error[E0308]: mismatched types
-  --> $DIR/associated-types-path-2.rs:41:18
+  --> $DIR/associated-types-path-2.rs:43:18
    |
 LL |     let _: i32 = f2(2i32);
    |            ---   ^^^^^^^^ expected `i32`, found `u32`
@@ -75,7 +91,7 @@ help: you can convert a `u32` to an `i32` and panic if the converted value doesn
 LL |     let _: i32 = f2(2i32).try_into().unwrap();
    |                          ++++++++++++++++++++
 
-error: aborting due to 6 previous errors
+error: aborting due to 8 previous errors
 
 Some errors have detailed explanations: E0277, E0308.
 For more information about an error, try `rustc --explain E0277`.
index c43ce2cadba046672c01a7e664572adae43c80a0..dcbe7765a9e1c4fd3d13f34a8e9b2f982f0a719c 100644 (file)
@@ -2,6 +2,9 @@
 
 // run-pass
 // edition:2018
+// revisions: normal drop-tracking
+// [normal]compile-flags: -Zdrop-tracking=no
+// [drop-tracking]compile-flags: -Zdrop-tracking
 
 #![allow(dead_code)]
 use std::future::Future;
index fb9dee11f2a0770e8e8b0957f0bf93270cf966f2..0e323443ae8b3f0870b7e4be6e7cfaa75be7f9ef 100644 (file)
@@ -30,7 +30,7 @@ error[E0277]: `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` is not a future
 LL |     (|_| 2333).await;
    |               ^^^^^^ `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` is not a future
    |
-   = help: the trait `Future` is not implemented for `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]`
+   = help: the trait `Future` is not implemented for closure `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]`
    = note: [closure@$DIR/issue-62009-1.rs:12:6: 12:9] must be a future or must implement `IntoFuture` to be awaited
    = note: required for `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` to implement `IntoFuture`
 help: remove the `.await`
diff --git a/src/test/ui/attributes/issue-100631.rs b/src/test/ui/attributes/issue-100631.rs
new file mode 100644 (file)
index 0000000..0fefcf8
--- /dev/null
@@ -0,0 +1,8 @@
+// issue #100631, make sure `TyCtxt::get_attr` only called by case that compiler
+// can reasonably deal with multiple attributes.
+// `repr` will use `TyCtxt::get_attrs` since it's `DuplicatesOk`.
+#[repr(C)] //~ ERROR: unsupported representation for zero-variant enum [E0084]
+#[repr(C)]
+enum Foo {}
+
+fn main() {}
diff --git a/src/test/ui/attributes/issue-100631.stderr b/src/test/ui/attributes/issue-100631.stderr
new file mode 100644 (file)
index 0000000..caa5351
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0084]: unsupported representation for zero-variant enum
+  --> $DIR/issue-100631.rs:4:1
+   |
+LL | #[repr(C)]
+   | ^^^^^^^^^^
+LL | #[repr(C)]
+LL | enum Foo {}
+   | -------- zero-variant enum
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0084`.
diff --git a/src/test/ui/attributes/unix_sigpipe/auxiliary/sigpipe-utils.rs b/src/test/ui/attributes/unix_sigpipe/auxiliary/sigpipe-utils.rs
new file mode 100644 (file)
index 0000000..e8b4fe7
--- /dev/null
@@ -0,0 +1,31 @@
+#![feature(rustc_private)]
+extern crate libc;
+
+/// So tests don't have to bring libc in scope themselves
+pub enum SignalHandler {
+    Ignore,
+    Default,
+}
+
+/// Helper to assert that [`libc::SIGPIPE`] has the expected signal handler.
+pub fn assert_sigpipe_handler(expected_handler: SignalHandler) {
+    #[cfg(unix)]
+    #[cfg(not(any(
+        target_os = "emscripten",
+        target_os = "fuchsia",
+        target_os = "horizon",
+        target_os = "android",
+    )))]
+    {
+        let prev = unsafe { libc::signal(libc::SIGPIPE, libc::SIG_IGN) };
+
+        let expected = match expected_handler {
+            SignalHandler::Ignore => libc::SIG_IGN,
+            SignalHandler::Default => libc::SIG_DFL,
+        };
+        assert_eq!(prev, expected);
+
+        // Unlikely to matter, but restore the old value anyway
+        unsafe { libc::signal(libc::SIGPIPE, prev); };
+    }
+}
diff --git a/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-crate.rs b/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-crate.rs
new file mode 100644 (file)
index 0000000..d6d020c
--- /dev/null
@@ -0,0 +1,4 @@
+#![feature(unix_sigpipe)]
+#![unix_sigpipe = "inherit"] //~ error: `unix_sigpipe` attribute cannot be used at crate level
+
+fn main() {}
diff --git a/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-crate.stderr b/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-crate.stderr
new file mode 100644 (file)
index 0000000..a1fb4d6
--- /dev/null
@@ -0,0 +1,13 @@
+error: `unix_sigpipe` attribute cannot be used at crate level
+  --> $DIR/unix_sigpipe-crate.rs:2:1
+   |
+LL | #![unix_sigpipe = "inherit"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: perhaps you meant to use an outer attribute
+   |
+LL | #[unix_sigpipe = "inherit"]
+   | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-duplicates.rs b/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-duplicates.rs
new file mode 100644 (file)
index 0000000..294cb38
--- /dev/null
@@ -0,0 +1,5 @@
+#![feature(unix_sigpipe)]
+
+#[unix_sigpipe = "sig_ign"]
+#[unix_sigpipe = "inherit"] //~ error: multiple `unix_sigpipe` attributes
+fn main() {}
diff --git a/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-duplicates.stderr b/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-duplicates.stderr
new file mode 100644 (file)
index 0000000..2362c17
--- /dev/null
@@ -0,0 +1,14 @@
+error: multiple `unix_sigpipe` attributes
+  --> $DIR/unix_sigpipe-duplicates.rs:4:1
+   |
+LL | #[unix_sigpipe = "inherit"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+   |
+note: attribute also specified here
+  --> $DIR/unix_sigpipe-duplicates.rs:3:1
+   |
+LL | #[unix_sigpipe = "sig_ign"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-error.rs b/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-error.rs
new file mode 100644 (file)
index 0000000..0a42a5b
--- /dev/null
@@ -0,0 +1,13 @@
+// run-pass
+// aux-build:sigpipe-utils.rs
+
+#![feature(unix_sigpipe)]
+
+#[unix_sigpipe = "sig_ign"]
+fn main() {
+    extern crate sigpipe_utils;
+
+    // #[unix_sigpipe = "sig_ign"] is active, so the legacy behavior of ignoring
+    // SIGPIPE shall be in effect
+    sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Ignore);
+}
diff --git a/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-inherit.rs b/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-inherit.rs
new file mode 100644 (file)
index 0000000..4f86480
--- /dev/null
@@ -0,0 +1,14 @@
+// run-pass
+// aux-build:sigpipe-utils.rs
+
+#![feature(unix_sigpipe)]
+
+#[unix_sigpipe = "inherit"]
+fn main() {
+    extern crate sigpipe_utils;
+
+    // #[unix_sigpipe = "inherit"] is active, so SIGPIPE shall NOT be ignored,
+    // instead the default handler shall be installed. (We assume that the
+    // process that runs these tests have the default handler.)
+    sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Default);
+}
diff --git a/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-list.rs b/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-list.rs
new file mode 100644 (file)
index 0000000..b5ebc07
--- /dev/null
@@ -0,0 +1,4 @@
+#![feature(unix_sigpipe)]
+
+#[unix_sigpipe(inherit)] //~ error: malformed `unix_sigpipe` attribute input
+fn main() {}
diff --git a/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-list.stderr b/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-list.stderr
new file mode 100644 (file)
index 0000000..59a87e1
--- /dev/null
@@ -0,0 +1,15 @@
+error: malformed `unix_sigpipe` attribute input
+  --> $DIR/unix_sigpipe-list.rs:3:1
+   |
+LL | #[unix_sigpipe(inherit)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: the following are the possible correct uses
+   |
+LL | #[unix_sigpipe = "inherit|sig_ign|sig_dfl"]
+   | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL | #[unix_sigpipe]
+   | ~~~~~~~~~~~~~~~
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.rs b/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.rs
new file mode 100644 (file)
index 0000000..cde6719
--- /dev/null
@@ -0,0 +1,6 @@
+#![feature(unix_sigpipe)]
+
+#[unix_sigpipe = "inherit"] //~ error: `unix_sigpipe` attribute can only be used on `fn main()`
+fn f() {}
+
+fn main() {}
diff --git a/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.stderr b/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.stderr
new file mode 100644 (file)
index 0000000..c4b8111
--- /dev/null
@@ -0,0 +1,8 @@
+error: `unix_sigpipe` attribute can only be used on `fn main()`
+  --> $DIR/unix_sigpipe-non-main-fn.rs:3:1
+   |
+LL | #[unix_sigpipe = "inherit"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.rs b/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.rs
new file mode 100644 (file)
index 0000000..16f7276
--- /dev/null
@@ -0,0 +1,8 @@
+#![feature(unix_sigpipe)]
+
+mod m {
+    #[unix_sigpipe = "inherit"] //~ error: `unix_sigpipe` attribute can only be used on root `fn main()`
+    fn main() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.stderr b/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.stderr
new file mode 100644 (file)
index 0000000..a04f605
--- /dev/null
@@ -0,0 +1,8 @@
+error: `unix_sigpipe` attribute can only be used on root `fn main()`
+  --> $DIR/unix_sigpipe-non-root-main.rs:4:5
+   |
+LL |     #[unix_sigpipe = "inherit"]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-not-used.rs b/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-not-used.rs
new file mode 100644 (file)
index 0000000..100b4ce
--- /dev/null
@@ -0,0 +1,9 @@
+// run-pass
+// aux-build:sigpipe-utils.rs
+
+fn main() {
+    extern crate sigpipe_utils;
+
+    // SIGPIPE shall be ignored since #[unix_sigpipe = "..."] is not used
+    sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Ignore);
+}
diff --git a/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-only-feature.rs b/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-only-feature.rs
new file mode 100644 (file)
index 0000000..b5adc2e
--- /dev/null
@@ -0,0 +1,13 @@
+// run-pass
+// aux-build:sigpipe-utils.rs
+
+#![feature(unix_sigpipe)]
+
+fn main() {
+    extern crate sigpipe_utils;
+
+    // Only #![feature(unix_sigpipe)] is enabled, not #[unix_sigpipe = "..."].
+    // This shall not change any behavior, so we still expect SIGPIPE to be
+    // ignored
+    sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Ignore);
+}
diff --git a/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-rustc_main.rs b/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-rustc_main.rs
new file mode 100644 (file)
index 0000000..6befb9e
--- /dev/null
@@ -0,0 +1,15 @@
+// run-pass
+// aux-build:sigpipe-utils.rs
+
+#![feature(unix_sigpipe)]
+#![feature(rustc_attrs)]
+
+#[unix_sigpipe = "sig_dfl"]
+#[rustc_main]
+fn rustc_main() {
+    extern crate sigpipe_utils;
+
+    // #[unix_sigpipe = "sig_dfl"] is active, so SIGPIPE handler shall be
+    // SIG_DFL. Note that we have a #[rustc_main], but it should still work.
+    sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Default);
+}
diff --git a/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-sig_dfl.rs b/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-sig_dfl.rs
new file mode 100644 (file)
index 0000000..238c0d5
--- /dev/null
@@ -0,0 +1,13 @@
+// run-pass
+// aux-build:sigpipe-utils.rs
+
+#![feature(unix_sigpipe)]
+
+#[unix_sigpipe = "sig_dfl"]
+fn main() {
+    extern crate sigpipe_utils;
+
+    // #[unix_sigpipe = "sig_dfl"] is active, so SIGPIPE shall NOT be ignored, instead
+    // the default handler shall be installed
+    sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Default);
+}
diff --git a/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-start.rs b/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-start.rs
new file mode 100644 (file)
index 0000000..64fd5ec
--- /dev/null
@@ -0,0 +1,6 @@
+#![feature(start)]
+#![feature(unix_sigpipe)]
+
+#[start]
+#[unix_sigpipe = "inherit"] //~ error: `unix_sigpipe` attribute can only be used on `fn main()`
+fn custom_start(argc: isize, argv: *const *const u8) -> isize { 0 }
diff --git a/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-start.stderr b/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-start.stderr
new file mode 100644 (file)
index 0000000..2c9ce47
--- /dev/null
@@ -0,0 +1,8 @@
+error: `unix_sigpipe` attribute can only be used on `fn main()`
+  --> $DIR/unix_sigpipe-start.rs:5:1
+   |
+LL | #[unix_sigpipe = "inherit"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-struct.rs b/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-struct.rs
new file mode 100644 (file)
index 0000000..a5e47cf
--- /dev/null
@@ -0,0 +1,6 @@
+#![feature(unix_sigpipe)]
+
+#[unix_sigpipe = "inherit"] //~ error: `unix_sigpipe` attribute can only be used on `fn main()`
+struct S;
+
+fn main() {}
diff --git a/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-struct.stderr b/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-struct.stderr
new file mode 100644 (file)
index 0000000..c56ee60
--- /dev/null
@@ -0,0 +1,8 @@
+error: `unix_sigpipe` attribute can only be used on `fn main()`
+  --> $DIR/unix_sigpipe-struct.rs:3:1
+   |
+LL | #[unix_sigpipe = "inherit"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-wrong.rs b/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-wrong.rs
new file mode 100644 (file)
index 0000000..4ec25de
--- /dev/null
@@ -0,0 +1,4 @@
+#![feature(unix_sigpipe)]
+
+#[unix_sigpipe = "wrong"] //~ error: valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl`
+fn main() {}
diff --git a/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-wrong.stderr b/src/test/ui/attributes/unix_sigpipe/unix_sigpipe-wrong.stderr
new file mode 100644 (file)
index 0000000..a66e45a
--- /dev/null
@@ -0,0 +1,8 @@
+error: valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl`
+  --> $DIR/unix_sigpipe-wrong.rs:3:1
+   |
+LL | #[unix_sigpipe = "wrong"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/attributes/unix_sigpipe/unix_sigpipe.rs b/src/test/ui/attributes/unix_sigpipe/unix_sigpipe.rs
new file mode 100644 (file)
index 0000000..7bf1c73
--- /dev/null
@@ -0,0 +1,4 @@
+#![feature(unix_sigpipe)]
+
+#[unix_sigpipe] //~ error: valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl`
+fn main() {}
diff --git a/src/test/ui/attributes/unix_sigpipe/unix_sigpipe.stderr b/src/test/ui/attributes/unix_sigpipe/unix_sigpipe.stderr
new file mode 100644 (file)
index 0000000..1b1eda8
--- /dev/null
@@ -0,0 +1,8 @@
+error: valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl`
+  --> $DIR/unix_sigpipe.rs:3:1
+   |
+LL | #[unix_sigpipe]
+   | ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
index 68303b842088ecadca31671af29cf1e884c719e6..097a14f26f868eb35538ca95c72e3c356a505988 100644 (file)
@@ -18,7 +18,7 @@ LL | fn foo(s: &i32) -> &i32 {
 LL |     assert_eq!(foo, y);
    |     ^^^^^^^^^^^^^^^^^^ `for<'r> fn(&'r i32) -> &'r i32 {foo}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
-   = help: the trait `Debug` is not implemented for `for<'r> fn(&'r i32) -> &'r i32 {foo}`
+   = help: the trait `Debug` is not implemented for fn item `for<'r> fn(&'r i32) -> &'r i32 {foo}`
    = help: use parentheses to call the function: `foo(s)`
    = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/borrowck/do-not-suggest-adding-move-when-closure-is-already-marked-as-move.rs b/src/test/ui/borrowck/do-not-suggest-adding-move-when-closure-is-already-marked-as-move.rs
new file mode 100644 (file)
index 0000000..5244592
--- /dev/null
@@ -0,0 +1,8 @@
+fn main() {
+    let mut vec: Vec<i32> = Vec::new();
+    let closure = move || {
+        vec.clear();
+        let mut iter = vec.iter();
+        move || { iter.next() } //~ ERROR captured variable cannot escape `FnMut` closure bod
+    };
+}
diff --git a/src/test/ui/borrowck/do-not-suggest-adding-move-when-closure-is-already-marked-as-move.stderr b/src/test/ui/borrowck/do-not-suggest-adding-move-when-closure-is-already-marked-as-move.stderr
new file mode 100644 (file)
index 0000000..78ca090
--- /dev/null
@@ -0,0 +1,18 @@
+error: captured variable cannot escape `FnMut` closure body
+  --> $DIR/do-not-suggest-adding-move-when-closure-is-already-marked-as-move.rs:6:9
+   |
+LL |     let mut vec: Vec<i32> = Vec::new();
+   |         ------- variable defined here
+LL |     let closure = move || {
+   |                         - inferred to be a `FnMut` closure
+LL |         vec.clear();
+   |         --- variable captured here
+LL |         let mut iter = vec.iter();
+LL |         move || { iter.next() }
+   |         ^^^^^^^^^^^^^^^^^^^^^^^ returns a closure that contains a reference to a captured variable, which then escapes the closure body
+   |
+   = note: `FnMut` closures only have access to their captured variables while they are executing...
+   = note: ...therefore, they cannot allow references to captured variables to escape
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/borrowck/issue-101119.rs b/src/test/ui/borrowck/issue-101119.rs
new file mode 100644 (file)
index 0000000..64e52ea
--- /dev/null
@@ -0,0 +1,16 @@
+struct State;
+
+fn once(_: impl FnOnce()) {}
+
+fn fill_memory_blocks_mt(state: &mut State) {
+    loop {
+        once(move || {
+            //~^ ERROR use of moved value: `state`
+            fill_segment(state);
+        });
+    }
+}
+
+fn fill_segment(_: &mut State) {}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/issue-101119.stderr b/src/test/ui/borrowck/issue-101119.stderr
new file mode 100644 (file)
index 0000000..a22afdc
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0382]: use of moved value: `state`
+  --> $DIR/issue-101119.rs:7:14
+   |
+LL | fn fill_memory_blocks_mt(state: &mut State) {
+   |                          ----- move occurs because `state` has type `&mut State`, which does not implement the `Copy` trait
+LL |     loop {
+LL |         once(move || {
+   |              ^^^^^^^ value moved into closure here, in previous iteration of loop
+LL |
+LL |             fill_segment(state);
+   |                          ----- use occurs due to use in closure
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
index 176bec819d67a115861ed61b1719d9f956b8225b..2ffb80f7ef6149c34dd547484318f72eaccbd3d1 100644 (file)
@@ -18,7 +18,7 @@ LL |     fn foo(f: isize, x: u8, ...);
 help: provide the arguments
    |
 LL |         foo(/* isize */, /* u8 */);
-   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |            ~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0060]: this function takes at least 2 arguments but 1 argument was supplied
   --> $DIR/variadic-ffi-1.rs:21:9
@@ -34,7 +34,7 @@ LL |     fn foo(f: isize, x: u8, ...);
 help: provide the argument
    |
 LL |         foo(1, /* u8 */);
-   |         ~~~~~~~~~~~~~~~~
+   |            ~~~~~~~~~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/variadic-ffi-1.rs:23:56
diff --git a/src/test/ui/check-cfg/allow-at-crate-level.rs b/src/test/ui/check-cfg/allow-at-crate-level.rs
new file mode 100644 (file)
index 0000000..ce3383a
--- /dev/null
@@ -0,0 +1,8 @@
+// This test check that #![allow(unexpected_cfgs)] works with --cfg
+//
+// check-pass
+// compile-flags: --cfg=unexpected --check-cfg=names() -Z unstable-options
+
+#![allow(unexpected_cfgs)]
+
+fn main() {}
index 6cce31d339286babadec43ef7dddd93094fb31cb..7db2aadec177b218c6b960bae1661a9e807bec57 100644 (file)
@@ -15,5 +15,9 @@ LL | #[cfg(feature = "rand")]
    |
    = note: expected values for `feature` are: full, serde
 
-warning: 2 warnings emitted
+warning: unexpected condition value `rand` for condition name `feature`
+   |
+   = help: was set with `--cfg` but isn't in the `--check-cfg` expected values
+
+warning: 3 warnings emitted
 
index 8e3d20d50458fb4a39ed6b305b190d0d65ba12ca..4e488fc03ec4bb09abc8a367208ea08a6b2ed05e 100644 (file)
@@ -3,7 +3,7 @@
 // we correctly lint on the `cfg!` macro and `cfg_attr` attribute.
 //
 // check-pass
-// compile-flags: --check-cfg=names() --check-cfg=values(feature,"foo") --cfg feature="bar" -Z unstable-options
+// compile-flags: --check-cfg=names() --check-cfg=values(feature,"foo") --cfg feature="bar" --cfg unknown_name -Z unstable-options
 
 #[cfg(windows)]
 fn do_windows_stuff() {}
index e51b75b3d4358a1f8c0059d2885a15c27e8cc5fb..9cf887ec7885cce93ac25c9dfc633ec497ee9678 100644 (file)
@@ -28,6 +28,14 @@ warning: unexpected `cfg` condition name
 LL | #[cfg_attr(uu, test)]
    |            ^^
 
+warning: unexpected condition value `bar` for condition name `feature`
+   |
+   = help: was set with `--cfg` but isn't in the `--check-cfg` expected values
+
+warning: unexpected `unknown_name` as condition name
+   |
+   = help: was set with `--cfg` but isn't in the `--check-cfg` expected names
+
 warning: unexpected `cfg` condition name
   --> $DIR/mix.rs:35:10
    |
@@ -170,5 +178,5 @@ LL |     cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra"));
    |
    = note: expected values for `feature` are: foo
 
-warning: 25 warnings emitted
+warning: 27 warnings emitted
 
index bd095c2d83d8a186cb49ed9e2a36514e251883df..6ce63e829b314f5faa831247a4021492c5b04ef6 100644 (file)
@@ -6,7 +6,7 @@ LL |     let x: Option<&[u8]> = Some("foo").map(std::mem::transmute);
    |                                        |
    |                                        required by a bound introduced by this call
    |
-   = help: the trait `FnOnce<(&str,)>` is not implemented for `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}`
+   = help: the trait `FnOnce<(&str,)>` is not implemented for fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {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
diff --git a/src/test/ui/coercion/issue-101066.rs b/src/test/ui/coercion/issue-101066.rs
new file mode 100644 (file)
index 0000000..b658ed1
--- /dev/null
@@ -0,0 +1,16 @@
+// check-pass
+
+use std::convert::TryFrom;
+
+pub trait FieldElement {
+    type Integer: TryFrom<usize, Error = std::num::TryFromIntError>;
+
+    fn valid_integer_try_from<N>(i: N) -> Result<Self::Integer, ()>
+    where
+        Self::Integer: TryFrom<N>,
+    {
+        Self::Integer::try_from(i).map_err(|_| ())
+    }
+}
+
+fn main() {}
index d6e993a10101d711d6815c50bebf2dc391885255..01f2f48956458cf35e3eeea2386c6c2c0b5955c8 100644 (file)
@@ -10,16 +10,6 @@ LL |                     panic!("const-eval error: cannot use f32::to_bits on a
 LL |         unsafe { intrinsics::const_eval_select((self,), ct_f32_to_u32, rt_f32_to_u32) }
    |                  -------------------------------------------------------------------- inside `core::f32::<impl f32>::to_bits` at $SRC_DIR/core/src/num/f32.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL |     extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
-   |     ------------------------------------------------------------------ inside `<fn(f32) -> u32 {core::f32::<impl f32>::to_bits::ct_f32_to_u32} as FnOnce<(f32,)>>::call_once - shim(fn(f32) -> u32 {core::f32::<impl f32>::to_bits::ct_f32_to_u32})` at $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-  ::: $SRC_DIR/core/src/intrinsics.rs:LL:COL
-   |
-LL |     called_in_const.call_once(arg)
-   |     ------------------------------ inside `const_eval_select::<(f32,), fn(f32) -> u32 {core::f32::<impl f32>::to_bits::ct_f32_to_u32}, [closure@core::f32::<impl f32>::to_bits::{closure#0}], u32>` at $SRC_DIR/core/src/intrinsics.rs:LL:COL
-   |
   ::: $DIR/const-float-bits-reject-conv.rs:27:30
    |
 LL |     const MASKED_NAN1: u32 = f32::NAN.to_bits() ^ 0x002A_AAAA;
@@ -39,16 +29,6 @@ LL |                     panic!("const-eval error: cannot use f32::to_bits on a
 LL |         unsafe { intrinsics::const_eval_select((self,), ct_f32_to_u32, rt_f32_to_u32) }
    |                  -------------------------------------------------------------------- inside `core::f32::<impl f32>::to_bits` at $SRC_DIR/core/src/num/f32.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL |     extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
-   |     ------------------------------------------------------------------ inside `<fn(f32) -> u32 {core::f32::<impl f32>::to_bits::ct_f32_to_u32} as FnOnce<(f32,)>>::call_once - shim(fn(f32) -> u32 {core::f32::<impl f32>::to_bits::ct_f32_to_u32})` at $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-  ::: $SRC_DIR/core/src/intrinsics.rs:LL:COL
-   |
-LL |     called_in_const.call_once(arg)
-   |     ------------------------------ inside `const_eval_select::<(f32,), fn(f32) -> u32 {core::f32::<impl f32>::to_bits::ct_f32_to_u32}, [closure@core::f32::<impl f32>::to_bits::{closure#0}], u32>` at $SRC_DIR/core/src/intrinsics.rs:LL:COL
-   |
   ::: $DIR/const-float-bits-reject-conv.rs:28:30
    |
 LL |     const MASKED_NAN2: u32 = f32::NAN.to_bits() ^ 0x0055_5555;
@@ -117,16 +97,6 @@ LL |                     panic!("const-eval error: cannot use f64::to_bits on a
 LL |         unsafe { intrinsics::const_eval_select((self,), ct_f64_to_u64, rt_f64_to_u64) }
    |                  -------------------------------------------------------------------- inside `core::f64::<impl f64>::to_bits` at $SRC_DIR/core/src/num/f64.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL |     extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
-   |     ------------------------------------------------------------------ inside `<fn(f64) -> u64 {core::f64::<impl f64>::to_bits::ct_f64_to_u64} as FnOnce<(f64,)>>::call_once - shim(fn(f64) -> u64 {core::f64::<impl f64>::to_bits::ct_f64_to_u64})` at $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-  ::: $SRC_DIR/core/src/intrinsics.rs:LL:COL
-   |
-LL |     called_in_const.call_once(arg)
-   |     ------------------------------ inside `const_eval_select::<(f64,), fn(f64) -> u64 {core::f64::<impl f64>::to_bits::ct_f64_to_u64}, [closure@core::f64::<impl f64>::to_bits::{closure#0}], u64>` at $SRC_DIR/core/src/intrinsics.rs:LL:COL
-   |
   ::: $DIR/const-float-bits-reject-conv.rs:54:30
    |
 LL |     const MASKED_NAN1: u64 = f64::NAN.to_bits() ^ 0x000A_AAAA_AAAA_AAAA;
@@ -146,16 +116,6 @@ LL |                     panic!("const-eval error: cannot use f64::to_bits on a
 LL |         unsafe { intrinsics::const_eval_select((self,), ct_f64_to_u64, rt_f64_to_u64) }
    |                  -------------------------------------------------------------------- inside `core::f64::<impl f64>::to_bits` at $SRC_DIR/core/src/num/f64.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL |     extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
-   |     ------------------------------------------------------------------ inside `<fn(f64) -> u64 {core::f64::<impl f64>::to_bits::ct_f64_to_u64} as FnOnce<(f64,)>>::call_once - shim(fn(f64) -> u64 {core::f64::<impl f64>::to_bits::ct_f64_to_u64})` at $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-  ::: $SRC_DIR/core/src/intrinsics.rs:LL:COL
-   |
-LL |     called_in_const.call_once(arg)
-   |     ------------------------------ inside `const_eval_select::<(f64,), fn(f64) -> u64 {core::f64::<impl f64>::to_bits::ct_f64_to_u64}, [closure@core::f64::<impl f64>::to_bits::{closure#0}], u64>` at $SRC_DIR/core/src/intrinsics.rs:LL:COL
-   |
   ::: $DIR/const-float-bits-reject-conv.rs:55:30
    |
 LL |     const MASKED_NAN2: u64 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555;
index 2307f52c93bceb8aa8f0fffab4c8806998ed0092..bea226f09dcb9186bba62843099c1aac454b889e 100644 (file)
@@ -12,7 +12,7 @@ LL |     let f = |x| x * 3;
 help: provide the argument
    |
 LL |     let a = f(/* value */);
-   |             ~~~~~~~~~~~~~~
+   |              ~~~~~~~~~~~~~
 
 error[E0057]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/E0057.rs:5:13
@@ -28,7 +28,7 @@ LL |     let f = |x| x * 3;
 help: remove the extra argument
    |
 LL |     let c = f(2);
-   |             ~~~~
+   |              ~~~
 
 error: aborting due to 2 previous errors
 
index 644fd59833878e31c8405010dbac3c1f9ee8b8dc..934a18d896dc6a0ab7a8517c831a0d63fbe25de1 100644 (file)
@@ -12,7 +12,7 @@ LL |     fn printf(_: *const u8, ...) -> u32;
 help: provide the argument
    |
 LL |     unsafe { printf(/* *const u8 */); }
-   |              ~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ~~~~~~~~~~~~~~~~~
 
 error: aborting due to previous error
 
index fa55db0924d2953112b837eb2ece28edf43ce461..fa4ccbe6677c033c63957e41c6086965f3d85b08 100644 (file)
@@ -12,7 +12,7 @@ LL | fn f(a: u16, b: &str) {}
 help: provide the argument
    |
 LL |     f(0, /* &str */);
-   |     ~~~~~~~~~~~~~~~~
+   |      ~~~~~~~~~~~~~~~
 
 error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/E0061.rs:9:5
@@ -28,7 +28,7 @@ LL | fn f2(a: u16) {}
 help: provide the argument
    |
 LL |     f2(/* u16 */);
-   |     ~~~~~~~~~~~~~
+   |       ~~~~~~~~~~~
 
 error: aborting due to 2 previous errors
 
index c6f0d5df9b53b3ba44a5f93e32ed5e5232a9da74..ff2934a2ba88301bc512e415641606bcb205f5ea 100644 (file)
@@ -6,7 +6,7 @@ LL |     is_fn(f);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `Fn<()>` is not implemented for `extern "C" fn() {f}`
+   = help: the trait `Fn<()>` is not implemented for fn item `extern "C" fn() {f}`
    = note: wrap the `extern "C" fn() {f}` in a closure with no arguments: `|| { /* code */ }`
 note: required by a bound in `is_fn`
   --> $DIR/extern-wrong-value-type.rs:4:28
diff --git a/src/test/ui/feature-gates/feature-gate-unix_sigpipe.rs b/src/test/ui/feature-gates/feature-gate-unix_sigpipe.rs
new file mode 100644 (file)
index 0000000..46dc3f6
--- /dev/null
@@ -0,0 +1,4 @@
+#![crate_type = "bin"]
+
+#[unix_sigpipe = "inherit"] //~ the `#[unix_sigpipe]` attribute is an experimental feature
+fn main () {}
diff --git a/src/test/ui/feature-gates/feature-gate-unix_sigpipe.stderr b/src/test/ui/feature-gates/feature-gate-unix_sigpipe.stderr
new file mode 100644 (file)
index 0000000..cf32844
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0658]: the `#[unix_sigpipe]` attribute is an experimental feature
+  --> $DIR/feature-gate-unix_sigpipe.rs:3:1
+   |
+LL | #[unix_sigpipe = "inherit"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #97889 <https://github.com/rust-lang/rust/issues/97889> for more information
+   = help: add `#![feature(unix_sigpipe)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
index b7757740d9e34de53ca83755350cb841b114ea17..0f7520ef7f8a95a80644466eedf36a0a5902a143 100644 (file)
@@ -18,11 +18,8 @@ LL |     foo(*x);
    |         ^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `(dyn Foo + 'static)`
+   = note: all function arguments must have a statically known size
    = help: unsized fn params are gated as an unstable feature
-help: function arguments must have a statically known size, borrowed types always have a known size
-   |
-LL |     foo(&*x);
-   |         +
 
 error: aborting due to 2 previous errors
 
index 22ba63c3e86f0ef812ddbee47080f403af17b524..09e25f4dc9668eb226a675d56e09e3c637c945a2 100644 (file)
@@ -12,7 +12,7 @@ LL | fn f<I>(i: I)
 help: provide the argument
    |
 LL |     f(&[f(/* value */)]);
-   |         ~~~~~~~~~~~~~~
+   |          ~~~~~~~~~~~~~
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/intrinsics/const-eval-select-backtrace-std.rs b/src/test/ui/intrinsics/const-eval-select-backtrace-std.rs
new file mode 100644 (file)
index 0000000..29aefe0
--- /dev/null
@@ -0,0 +1,6 @@
+// See issue #100696.
+// run-fail
+// check-run-results
+fn main() {
+    &""[1..];
+}
diff --git a/src/test/ui/intrinsics/const-eval-select-backtrace-std.run.stderr b/src/test/ui/intrinsics/const-eval-select-backtrace-std.run.stderr
new file mode 100644 (file)
index 0000000..e53e603
--- /dev/null
@@ -0,0 +1,2 @@
+thread 'main' panicked at 'byte index 1 is out of bounds of ``', $DIR/const-eval-select-backtrace-std.rs:5:6
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
diff --git a/src/test/ui/intrinsics/const-eval-select-backtrace.rs b/src/test/ui/intrinsics/const-eval-select-backtrace.rs
new file mode 100644 (file)
index 0000000..99f0725
--- /dev/null
@@ -0,0 +1,18 @@
+#![feature(core_intrinsics)]
+// See issue #100696.
+// run-fail
+// check-run-results
+
+#[track_caller]
+fn uhoh() {
+    panic!("Aaah!")
+}
+
+const fn c() {}
+
+fn main() {
+    // safety: this is unsound and just used to test
+    unsafe {
+        std::intrinsics::const_eval_select((), c, uhoh);
+    }
+}
diff --git a/src/test/ui/intrinsics/const-eval-select-backtrace.run.stderr b/src/test/ui/intrinsics/const-eval-select-backtrace.run.stderr
new file mode 100644 (file)
index 0000000..2fd730a
--- /dev/null
@@ -0,0 +1,2 @@
+thread 'main' panicked at 'Aaah!', $DIR/const-eval-select-backtrace.rs:16:9
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
index e5640f5ab53b192ab352109e039dc3b4616a59fe..fa14efad7b4a473ebd2f8744a2d9b7b154f2a7ce 100644 (file)
@@ -5,10 +5,13 @@
 
 const fn not_fn_items() {
     const_eval_select((), || {}, || {});
-    //~^ ERROR the trait bound
+    //~^ ERROR this argument must be a function item
+    //~| ERROR this argument must be a function item
     const_eval_select((), 42, 0xDEADBEEF);
-    //~^ ERROR the trait bound
+    //~^ ERROR expected a `FnOnce<()>` closure
     //~| ERROR expected a `FnOnce<()>` closure
+    //~| ERROR this argument must be a function item
+    //~| ERROR this argument must be a function item
 }
 
 const fn foo(n: i32) -> i32 {
@@ -35,4 +38,9 @@ const fn args_ty_mismatch() {
     //~^ ERROR type mismatch
 }
 
+const fn non_const_fn() {
+    const_eval_select((1,), bar, bar);
+    //~^ ERROR this argument must be a `const fn`
+}
+
 fn main() {}
index 1a761ad5441cea3887270de031594c2bb21cc138..3720528ad4e402b0e4feb3131b1213ee50812ead 100644 (file)
@@ -1,42 +1,57 @@
-error[E0277]: the trait bound `[closure@$DIR/const-eval-select-bad.rs:7:27: 7:29]: FnOnce<()>` is not satisfied
+error: this argument must be a function item
   --> $DIR/const-eval-select-bad.rs:7:27
    |
 LL |     const_eval_select((), || {}, || {});
-   |     -----------------     ^^^^^ expected an `FnOnce<()>` closure, found `[closure@$DIR/const-eval-select-bad.rs:7:27: 7:29]`
-   |     |
-   |     required by a bound introduced by this call
+   |                           ^^^^^
    |
-   = help: the trait `~const FnOnce<()>` is not implemented for `[closure@$DIR/const-eval-select-bad.rs:7:27: 7:29]`
-note: the trait `FnOnce<()>` is implemented for `[closure@$DIR/const-eval-select-bad.rs:7:27: 7:29]`, but that implementation is not `const`
-  --> $DIR/const-eval-select-bad.rs:7:27
+   = note: expected a function item, found [closure@$DIR/const-eval-select-bad.rs:7:27: 7:29]
+   = help: consult the documentation on `const_eval_select` for more information
+
+error: this argument must be a function item
+  --> $DIR/const-eval-select-bad.rs:7:34
    |
 LL |     const_eval_select((), || {}, || {});
-   |                           ^^^^^
-   = note: wrap the `[closure@$DIR/const-eval-select-bad.rs:7:27: 7:29]` 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: ~const FnOnce<ARG, Output = RET>,
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
+   = note: expected a function item, found [closure@$DIR/const-eval-select-bad.rs:7:34: 7:36]
+   = help: consult the documentation on `const_eval_select` for more information
 
-error[E0277]: the trait bound `{integer}: FnOnce<()>` is not satisfied
-  --> $DIR/const-eval-select-bad.rs:9:27
+error: this argument must be a function item
+  --> $DIR/const-eval-select-bad.rs:10:27
+   |
+LL |     const_eval_select((), 42, 0xDEADBEEF);
+   |                           ^^
+   |
+   = note: expected a function item, found {integer}
+   = help: consult the documentation on `const_eval_select` for more information
+
+error[E0277]: expected a `FnOnce<()>` closure, found `{integer}`
+  --> $DIR/const-eval-select-bad.rs:10:27
    |
 LL |     const_eval_select((), 42, 0xDEADBEEF);
    |     -----------------     ^^ expected an `FnOnce<()>` closure, found `{integer}`
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `~const FnOnce<()>` is not implemented for `{integer}`
+   = help: the trait `FnOnce<()>` is not implemented for `{integer}`
    = 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: ~const FnOnce<ARG, Output = RET>,
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
+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
+   |
+LL |     const_eval_select((), 42, 0xDEADBEEF);
+   |                               ^^^^^^^^^^
+   |
+   = note: expected a function item, found {integer}
+   = help: consult the documentation on `const_eval_select` for more information
 
 error[E0277]: expected a `FnOnce<()>` closure, found `{integer}`
-  --> $DIR/const-eval-select-bad.rs:9:31
+  --> $DIR/const-eval-select-bad.rs:10:31
    |
 LL |     const_eval_select((), 42, 0xDEADBEEF);
    |     -----------------         ^^^^^^^^^^ expected an `FnOnce<()>` closure, found `{integer}`
@@ -48,11 +63,11 @@ LL |     const_eval_select((), 42, 0xDEADBEEF);
 note: required by a bound in `const_eval_select`
   --> $SRC_DIR/core/src/intrinsics.rs:LL:COL
    |
-LL |     G: FnOnce<ARG, Output = RET> + ~const Destruct,
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
+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:29:34
+  --> $DIR/const-eval-select-bad.rs:32:34
    |
 LL |     const_eval_select((1,), foo, bar);
    |     -----------------            ^^^ expected `i32`, found `bool`
@@ -62,11 +77,11 @@ 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> + ~const Destruct,
-   |                    ^^^^^^^^^^^^ required by this bound in `const_eval_select`
+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:34:32
+  --> $DIR/const-eval-select-bad.rs:37:32
    |
 LL | const fn foo(n: i32) -> i32 {
    | --------------------------- found signature defined here
@@ -81,10 +96,18 @@ LL |     const_eval_select((true,), foo, baz);
 note: required by a bound in `const_eval_select`
   --> $SRC_DIR/core/src/intrinsics.rs:LL:COL
    |
-LL |     F: ~const FnOnce<ARG, Output = RET>,
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
+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
+   |
+LL |     const_eval_select((1,), bar, bar);
+   |                             ^^^
+   |
+   = help: consult the documentation on `const_eval_select` for more information
 
-error: aborting due to 5 previous errors
+error: aborting due to 9 previous errors
 
 Some errors have detailed explanations: E0271, E0277, E0631.
 For more information about an error, try `rustc --explain E0271`.
index aaa3c49b3d83ea468b98434656856502c29b824d..76645645464ed37eb3999091a2d55dc01fcca994 100644 (file)
@@ -12,7 +12,7 @@ LL | fn _foo<F: Fn()> (f: F) {
 help: remove the extra argument
    |
 LL |     |t| f();
-   |         ~~~
+   |          ~~
 
 error: aborting due to previous error
 
index e499d0572f607c278f7f6ad8334de0d29e3e34fb..767fdd5caf06a2136b4dbe907d8044d3285e0cde 100644 (file)
@@ -23,7 +23,7 @@ LL |     print_x(&X);
 help: provide the argument
    |
 LL |     print_x(/* &dyn Foo<Item = bool> */, /* &str */);
-   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to previous error
 
index 48b22bca20f067444040cd73b4c487343e31e8ee..97492e6e0fa2e008986115b28c250893a5dfa23e 100644 (file)
@@ -5,9 +5,7 @@ LL | fn get_function<'a>() -> &'a dyn Fn() -> dyn Trait {
    | -------------------------------------------------- `get_function` defined here returns `&dyn Fn() -> (dyn Trait + 'static)`
 ...
 LL |     let t: &dyn Trait = &get_function()();
-   |                          ^^^^^^^^^^^^^^--
-   |                          |
-   |                          call expression requires function
+   |                          ^^^^^^^^^^^^^^ this trait object returns an unsized value `(dyn Trait + 'static)`, so it cannot be called
 
 error: aborting due to previous error
 
index aab19a699ace08770c7e3b89e40cf6fa2d1a80a0..bb45fa083381bf75ba6fafe0daf2fbd5d11187cf 100644 (file)
@@ -12,7 +12,7 @@ LL | fn foo(a: usize) {}
 help: remove the extra argument
    |
 LL | fn main() { foo(5) }
-   |             ~~~~~~
+   |                ~~~
 
 error: aborting due to previous error
 
index e5368ddf1e5760b88b1b071a3319af0939110b6d..08fe0b35eb7d86db51ba4c8c269019d789a77c8b 100644 (file)
@@ -89,7 +89,7 @@ error[E0277]: `fn(usize) -> Foo {Foo::Bar}` doesn't implement `Debug`
 LL |     assert_eq!(Foo::Bar, i);
    |     ^^^^^^^^^^^^^^^^^^^^^^^ `fn(usize) -> Foo {Foo::Bar}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
-   = help: the trait `Debug` is not implemented for `fn(usize) -> Foo {Foo::Bar}`
+   = help: the trait `Debug` is not implemented for fn item `fn(usize) -> Foo {Foo::Bar}`
    = help: the following other types implement trait `Debug`:
              extern "C" fn() -> Ret
              extern "C" fn(A, B) -> Ret
@@ -108,7 +108,7 @@ error[E0277]: `fn(usize) -> Foo {Foo::Bar}` doesn't implement `Debug`
 LL |     assert_eq!(Foo::Bar, i);
    |     ^^^^^^^^^^^^^^^^^^^^^^^ `fn(usize) -> Foo {Foo::Bar}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
-   = help: the trait `Debug` is not implemented for `fn(usize) -> Foo {Foo::Bar}`
+   = help: the trait `Debug` is not implemented for fn item `fn(usize) -> Foo {Foo::Bar}`
    = help: the following other types implement trait `Debug`:
              extern "C" fn() -> Ret
              extern "C" fn(A, B) -> Ret
index 9239385e6436904b5235e8bc657dfa283c9b4077..7f29709ce50958bf9d72f716b73e8c3c6d8e4fa7 100644 (file)
@@ -28,7 +28,7 @@ LL | fn a() -> i32 {
 LL |     assert_eq!(a, 0);
    |     ^^^^^^^^^^^^^^^^ `fn() -> i32 {a}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
-   = help: the trait `Debug` is not implemented for `fn() -> i32 {a}`
+   = help: the trait `Debug` is not implemented for fn item `fn() -> i32 {a}`
    = help: use parentheses to call the function: `a()`
    = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/issues/issue-99875.rs b/src/test/ui/issues/issue-99875.rs
new file mode 100644 (file)
index 0000000..cf73fd8
--- /dev/null
@@ -0,0 +1,16 @@
+struct Argument;
+struct Return;
+
+fn function(_: Argument) -> Return { todo!() }
+
+trait Trait {}
+impl Trait for fn(Argument) -> Return {}
+
+fn takes(_: impl Trait) {}
+
+fn main() {
+    takes(function);
+    //~^ ERROR the trait bound
+    takes(|_: Argument| -> Return { todo!() });
+    //~^ ERROR the trait bound
+}
diff --git a/src/test/ui/issues/issue-99875.stderr b/src/test/ui/issues/issue-99875.stderr
new file mode 100644 (file)
index 0000000..3ff8f12
--- /dev/null
@@ -0,0 +1,33 @@
+error[E0277]: the trait bound `fn(Argument) -> Return {function}: Trait` is not satisfied
+  --> $DIR/issue-99875.rs:12:11
+   |
+LL |     takes(function);
+   |     ----- ^^^^^^^^ the trait `Trait` is not implemented for fn item `fn(Argument) -> Return {function}`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `Trait` is implemented for fn pointer `fn(Argument) -> Return`
+note: required by a bound in `takes`
+  --> $DIR/issue-99875.rs:9:18
+   |
+LL | fn takes(_: impl Trait) {}
+   |                  ^^^^^ required by this bound in `takes`
+
+error[E0277]: the trait bound `[closure@$DIR/issue-99875.rs:14:11: 14:34]: Trait` is not satisfied
+  --> $DIR/issue-99875.rs:14:11
+   |
+LL |     takes(|_: Argument| -> Return { todo!() });
+   |     ----- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for closure `[closure@$DIR/issue-99875.rs:14:11: 14:34]`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `Trait` is implemented for fn pointer `fn(Argument) -> Return`
+note: required by a bound in `takes`
+  --> $DIR/issue-99875.rs:9:18
+   |
+LL | fn takes(_: impl Trait) {}
+   |                  ^^^^^ required by this bound in `takes`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
index c4addaccefc1045ec2045563331e1dd0e7fc5326..80c77edae9eb1fb0c6f3dfa69ebca00780b27857 100644 (file)
@@ -1,12 +1,15 @@
 fn main() {
     let _ = Iterator::next(&mut ());
     //~^ ERROR `()` is not an iterator
+    //~| ERROR `()` is not an iterator
+    //~| ERROR `()` is not an iterator
 
     for _ in false {}
     //~^ ERROR `bool` is not an iterator
 
     let _ = Iterator::next(&mut ());
     //~^ ERROR `()` is not an iterator
+    //~| ERROR `()` is not an iterator
 
     other()
 }
@@ -16,9 +19,12 @@ pub fn other() {
 
     let _ = Iterator::next(&mut ());
     //~^ ERROR `()` is not an iterator
+    //~| ERROR `()` is not an iterator
+    //~| ERROR `()` is not an iterator
 
     let _ = Iterator::next(&mut ());
     //~^ ERROR `()` is not an iterator
+    //~| ERROR `()` is not an iterator
 
     for _ in false {}
     //~^ ERROR `bool` is not an iterator
index 53b610c172392f2bed4cb7831c47c1ac15023012..3256e57d4361b2a2856486dd40ed29db8177ba01 100644 (file)
@@ -8,8 +8,16 @@ LL |     let _ = Iterator::next(&mut ());
    |
    = help: the trait `Iterator` is not implemented for `()`
 
+error[E0277]: `()` is not an iterator
+  --> $DIR/issue-28098.rs:2:13
+   |
+LL |     let _ = Iterator::next(&mut ());
+   |             ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator
+   |
+   = help: the trait `Iterator` is not implemented for `()`
+
 error[E0277]: `bool` is not an iterator
-  --> $DIR/issue-28098.rs:5:14
+  --> $DIR/issue-28098.rs:7:14
    |
 LL |     for _ in false {}
    |              ^^^^^ `bool` is not an iterator
@@ -18,7 +26,7 @@ LL |     for _ in false {}
    = note: required for `bool` to implement `IntoIterator`
 
 error[E0277]: `()` is not an iterator
-  --> $DIR/issue-28098.rs:8:28
+  --> $DIR/issue-28098.rs:10:28
    |
 LL |     let _ = Iterator::next(&mut ());
    |             -------------- ^^^^^^^ `()` is not an iterator
@@ -28,7 +36,23 @@ LL |     let _ = Iterator::next(&mut ());
    = help: the trait `Iterator` is not implemented for `()`
 
 error[E0277]: `()` is not an iterator
-  --> $DIR/issue-28098.rs:17:28
+  --> $DIR/issue-28098.rs:10:13
+   |
+LL |     let _ = Iterator::next(&mut ());
+   |             ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator
+   |
+   = help: the trait `Iterator` is not implemented for `()`
+
+error[E0277]: `()` is not an iterator
+  --> $DIR/issue-28098.rs:2:13
+   |
+LL |     let _ = Iterator::next(&mut ());
+   |             ^^^^^^^^^^^^^^ `()` is not an iterator
+   |
+   = help: the trait `Iterator` is not implemented for `()`
+
+error[E0277]: `()` is not an iterator
+  --> $DIR/issue-28098.rs:20:28
    |
 LL |     let _ = Iterator::next(&mut ());
    |             -------------- ^^^^^^^ `()` is not an iterator
@@ -38,7 +62,15 @@ LL |     let _ = Iterator::next(&mut ());
    = help: the trait `Iterator` is not implemented for `()`
 
 error[E0277]: `()` is not an iterator
-  --> $DIR/issue-28098.rs:20:28
+  --> $DIR/issue-28098.rs:20:13
+   |
+LL |     let _ = Iterator::next(&mut ());
+   |             ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator
+   |
+   = help: the trait `Iterator` is not implemented for `()`
+
+error[E0277]: `()` is not an iterator
+  --> $DIR/issue-28098.rs:25:28
    |
 LL |     let _ = Iterator::next(&mut ());
    |             -------------- ^^^^^^^ `()` is not an iterator
@@ -47,8 +79,16 @@ LL |     let _ = Iterator::next(&mut ());
    |
    = help: the trait `Iterator` is not implemented for `()`
 
+error[E0277]: `()` is not an iterator
+  --> $DIR/issue-28098.rs:25:13
+   |
+LL |     let _ = Iterator::next(&mut ());
+   |             ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator
+   |
+   = help: the trait `Iterator` is not implemented for `()`
+
 error[E0277]: `bool` is not an iterator
-  --> $DIR/issue-28098.rs:23:14
+  --> $DIR/issue-28098.rs:29:14
    |
 LL |     for _ in false {}
    |              ^^^^^ `bool` is not an iterator
@@ -56,6 +96,14 @@ LL |     for _ in false {}
    = help: the trait `Iterator` is not implemented for `bool`
    = note: required for `bool` to implement `IntoIterator`
 
-error: aborting due to 6 previous errors
+error[E0277]: `()` is not an iterator
+  --> $DIR/issue-28098.rs:20:13
+   |
+LL |     let _ = Iterator::next(&mut ());
+   |             ^^^^^^^^^^^^^^ `()` is not an iterator
+   |
+   = help: the trait `Iterator` is not implemented for `()`
+
+error: aborting due to 12 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/let-else/let-else-drop-order.rs b/src/test/ui/let-else/let-else-drop-order.rs
new file mode 100644 (file)
index 0000000..0054f3d
--- /dev/null
@@ -0,0 +1,270 @@
+// run-pass
+// edition:2021
+// check-run-results
+//
+// Drop order tests for let else
+//
+// Mostly this ensures two things:
+// 1. That let and let else temporary drop order is the same.
+//    This is a specific design request: https://github.com/rust-lang/rust/pull/93628#issuecomment-1047140316
+// 2. That the else block truly only runs after the
+//    temporaries have dropped.
+//
+// We also print some nice tables for an overview by humans.
+// Changes in those tables are considered breakages, but the
+// important properties 1 and 2 are also enforced by the code.
+// This is important as it's easy to update the stdout file
+// with a --bless and miss the impact of that change.
+
+#![feature(let_else)]
+#![allow(irrefutable_let_patterns)]
+
+use std::cell::RefCell;
+use std::rc::Rc;
+
+#[derive(Clone)]
+struct DropAccountant(Rc<RefCell<Vec<Vec<String>>>>);
+
+impl DropAccountant {
+    fn new() -> Self {
+        Self(Default::default())
+    }
+    fn build_droppy(&self, v: u32) -> Droppy<u32> {
+        Droppy(self.clone(), v)
+    }
+    fn build_droppy_enum_none(&self, _v: u32) -> ((), DroppyEnum<u32>) {
+        ((), DroppyEnum::None(self.clone()))
+    }
+    fn new_list(&self, s: impl ToString) {
+        self.0.borrow_mut().push(vec![s.to_string()]);
+    }
+    fn push(&self, s: impl ToString) {
+        let s = s.to_string();
+        let mut accounts = self.0.borrow_mut();
+        accounts.last_mut().unwrap().push(s);
+    }
+    fn print_table(&self) {
+        println!();
+
+        let accounts = self.0.borrow();
+        let before_last = &accounts[accounts.len() - 2];
+        let last = &accounts[accounts.len() - 1];
+        let before_last = get_comma_list(before_last);
+        let last = get_comma_list(last);
+        const LINES: &[&str] = &[
+            "vanilla",
+            "&",
+            "&mut",
+            "move",
+            "fn(this)",
+            "tuple",
+            "array",
+            "ref &",
+            "ref mut &mut",
+        ];
+        let max_len = LINES.iter().map(|v| v.len()).max().unwrap();
+        let max_len_before = before_last.iter().map(|v| v.len()).max().unwrap();
+        let max_len_last = last.iter().map(|v| v.len()).max().unwrap();
+
+        println!(
+            "| {: <max_len$} | {: <max_len_before$} | {: <max_len_last$} |",
+            "construct", before_last[0], last[0]
+        );
+        println!("| {:-<max_len$} | {:-<max_len_before$} | {:-<max_len_last$} |", "", "", "");
+
+        for ((l, l_before), l_last) in
+            LINES.iter().zip(before_last[1..].iter()).zip(last[1..].iter())
+        {
+            println!(
+                "| {: <max_len$} | {: <max_len_before$} | {: <max_len_last$} |",
+                l, l_before, l_last,
+            );
+        }
+    }
+    #[track_caller]
+    fn assert_all_equal_to(&self, st: &str) {
+        let accounts = self.0.borrow();
+        let last = &accounts[accounts.len() - 1];
+        let last = get_comma_list(last);
+        for line in last[1..].iter() {
+            assert_eq!(line.trim(), st.trim());
+        }
+    }
+    #[track_caller]
+    fn assert_equality_last_two_lists(&self) {
+        let accounts = self.0.borrow();
+        let last = &accounts[accounts.len() - 1];
+        let before_last = &accounts[accounts.len() - 2];
+        for (l, b) in last[1..].iter().zip(before_last[1..].iter()) {
+            if !(l == b || l == "n/a" || b == "n/a") {
+                panic!("not equal: '{last:?}' != '{before_last:?}'");
+            }
+        }
+    }
+}
+
+fn get_comma_list(sl: &[String]) -> Vec<String> {
+    std::iter::once(sl[0].clone())
+        .chain(sl[1..].chunks(2).map(|c| c.join(",")))
+        .collect::<Vec<String>>()
+}
+
+struct Droppy<T>(DropAccountant, T);
+
+impl<T> Drop for Droppy<T> {
+    fn drop(&mut self) {
+        self.0.push("drop");
+    }
+}
+
+#[allow(dead_code)]
+enum DroppyEnum<T> {
+    Some(DropAccountant, T),
+    None(DropAccountant),
+}
+
+impl<T> Drop for DroppyEnum<T> {
+    fn drop(&mut self) {
+        match self {
+            DroppyEnum::Some(acc, _inner) => acc,
+            DroppyEnum::None(acc) => acc,
+        }
+        .push("drop");
+    }
+}
+
+macro_rules! nestings_with {
+    ($construct:ident, $binding:pat, $exp:expr) => {
+        // vanilla:
+        $construct!($binding, $exp.1);
+
+        // &:
+        $construct!(&$binding, &$exp.1);
+
+        // &mut:
+        $construct!(&mut $binding, &mut ($exp.1));
+
+        {
+            // move:
+            let w = $exp;
+            $construct!(
+                $binding,
+                {
+                    let w = w;
+                    w
+                }
+                .1
+            );
+        }
+
+        // fn(this):
+        $construct!($binding, std::convert::identity($exp).1);
+    };
+}
+
+macro_rules! nestings {
+    ($construct:ident, $binding:pat, $exp:expr) => {
+        nestings_with!($construct, $binding, $exp);
+
+        // tuple:
+        $construct!(($binding, 77), ($exp.1, 77));
+
+        // array:
+        $construct!([$binding], [$exp.1]);
+    };
+}
+
+macro_rules! let_else {
+    ($acc:expr, $v:expr, $binding:pat, $build:ident) => {
+        let acc = $acc;
+        let v = $v;
+
+        macro_rules! let_else_construct {
+            ($arg:pat, $exp:expr) => {
+                loop {
+                    let $arg = $exp else {
+                        acc.push("else");
+                        break;
+                    };
+                    acc.push("body");
+                    break;
+                }
+            };
+        }
+        nestings!(let_else_construct, $binding, acc.$build(v));
+        // ref &:
+        let_else_construct!($binding, &acc.$build(v).1);
+
+        // ref mut &mut:
+        let_else_construct!($binding, &mut acc.$build(v).1);
+    };
+}
+
+macro_rules! let_ {
+    ($acc:expr, $binding:tt) => {
+        let acc = $acc;
+
+        macro_rules! let_construct {
+            ($arg:pat, $exp:expr) => {{
+                let $arg = $exp;
+                acc.push("body");
+            }};
+        }
+        let v = 0;
+        {
+            nestings_with!(let_construct, $binding, acc.build_droppy(v));
+        }
+        acc.push("n/a");
+        acc.push("n/a");
+        acc.push("n/a");
+        acc.push("n/a");
+
+        // ref &:
+        let_construct!($binding, &acc.build_droppy(v).1);
+
+        // ref mut &mut:
+        let_construct!($binding, &mut acc.build_droppy(v).1);
+    };
+}
+
+fn main() {
+    let acc = DropAccountant::new();
+
+    println!(" --- matching cases ---");
+
+    // Ensure that let and let else have the same behaviour
+    acc.new_list("let _");
+    let_!(&acc, _);
+    acc.new_list("let else _");
+    let_else!(&acc, 0, _, build_droppy);
+    acc.assert_equality_last_two_lists();
+    acc.print_table();
+
+    // Ensure that let and let else have the same behaviour
+    acc.new_list("let _v");
+    let_!(&acc, _v);
+    acc.new_list("let else _v");
+    let_else!(&acc, 0, _v, build_droppy);
+    acc.assert_equality_last_two_lists();
+    acc.print_table();
+
+    println!();
+
+    println!(" --- mismatching cases ---");
+
+    acc.new_list("let else _ mismatch");
+    let_else!(&acc, 1, DroppyEnum::Some(_, _), build_droppy_enum_none);
+    acc.new_list("let else _v mismatch");
+    let_else!(&acc, 1, DroppyEnum::Some(_, _v), build_droppy_enum_none);
+    acc.print_table();
+    // This ensures that we always drop before visiting the else case
+    acc.assert_all_equal_to("drop,else");
+
+    acc.new_list("let else 0 mismatch");
+    let_else!(&acc, 1, 0, build_droppy);
+    acc.new_list("let else 0 mismatch");
+    let_else!(&acc, 1, 0, build_droppy);
+    acc.print_table();
+    // This ensures that we always drop before visiting the else case
+    acc.assert_all_equal_to("drop,else");
+}
diff --git a/src/test/ui/let-else/let-else-drop-order.run.stdout b/src/test/ui/let-else/let-else-drop-order.run.stdout
new file mode 100644 (file)
index 0000000..01cf2f7
--- /dev/null
@@ -0,0 +1,51 @@
+ --- matching cases ---
+
+| construct    | let _     | let else _ |
+| ------------ | --------- | ---------- |
+| vanilla      | drop,body | drop,body  |
+| &            | body,drop | body,drop  |
+| &mut         | body,drop | body,drop  |
+| move         | drop,body | drop,body  |
+| fn(this)     | drop,body | drop,body  |
+| tuple        | n/a,n/a   | drop,body  |
+| array        | n/a,n/a   | drop,body  |
+| ref &        | body,drop | body,drop  |
+| ref mut &mut | body,drop | body,drop  |
+
+| construct    | let _v    | let else _v |
+| ------------ | --------- | ----------- |
+| vanilla      | drop,body | drop,body   |
+| &            | body,drop | body,drop   |
+| &mut         | body,drop | body,drop   |
+| move         | drop,body | drop,body   |
+| fn(this)     | drop,body | drop,body   |
+| tuple        | n/a,n/a   | drop,body   |
+| array        | n/a,n/a   | drop,body   |
+| ref &        | body,drop | body,drop   |
+| ref mut &mut | body,drop | body,drop   |
+
+ --- mismatching cases ---
+
+| construct    | let else _ mismatch | let else _v mismatch |
+| ------------ | ------------------- | -------------------- |
+| vanilla      | drop,else           | drop,else            |
+| &            | drop,else           | drop,else            |
+| &mut         | drop,else           | drop,else            |
+| move         | drop,else           | drop,else            |
+| fn(this)     | drop,else           | drop,else            |
+| tuple        | drop,else           | drop,else            |
+| array        | drop,else           | drop,else            |
+| ref &        | drop,else           | drop,else            |
+| ref mut &mut | drop,else           | drop,else            |
+
+| construct    | let else 0 mismatch | let else 0 mismatch |
+| ------------ | ------------------- | ------------------- |
+| vanilla      | drop,else           | drop,else           |
+| &            | drop,else           | drop,else           |
+| &mut         | drop,else           | drop,else           |
+| move         | drop,else           | drop,else           |
+| fn(this)     | drop,else           | drop,else           |
+| tuple        | drop,else           | drop,else           |
+| array        | drop,else           | drop,else           |
+| ref &        | drop,else           | drop,else           |
+| ref mut &mut | drop,else           | drop,else           |
index f3af5cf5a35764f96c9d054889b64916afa3ccc6..98d39d614d0e9647e98036a3e0e357f13dd0e691 100644 (file)
@@ -54,7 +54,7 @@ LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() }
 help: provide the argument
    |
 LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter(/* &u8 */) }
-   |                                               ~~~~~~~~~~~~~~~
+   |                                                   ~~~~~~~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/issue-26638.rs:5:47
diff --git a/src/test/ui/lint/issue-101284.rs b/src/test/ui/lint/issue-101284.rs
new file mode 100644 (file)
index 0000000..1381d4f
--- /dev/null
@@ -0,0 +1,15 @@
+// check-pass
+// edition:2021
+#![deny(rust_2021_compatibility)]
+
+pub struct Warns {
+    // `Arc` has significant drop
+    _significant_drop: std::sync::Arc<()>,
+    field: String,
+}
+
+pub fn test(w: Warns) {
+    _ = || drop(w.field);
+}
+
+fn main() {}
diff --git a/src/test/ui/lint/let_underscore/let_underscore_drop.rs b/src/test/ui/lint/let_underscore/let_underscore_drop.rs
new file mode 100644 (file)
index 0000000..f298871
--- /dev/null
@@ -0,0 +1,14 @@
+// check-pass
+#![warn(let_underscore_drop)]
+
+struct NontrivialDrop;
+
+impl Drop for NontrivialDrop {
+    fn drop(&mut self) {
+        println!("Dropping!");
+    }
+}
+
+fn main() {
+    let _ = NontrivialDrop; //~WARNING non-binding let on a type that implements `Drop`
+}
diff --git a/src/test/ui/lint/let_underscore/let_underscore_drop.stderr b/src/test/ui/lint/let_underscore/let_underscore_drop.stderr
new file mode 100644 (file)
index 0000000..7b7de20
--- /dev/null
@@ -0,0 +1,22 @@
+warning: non-binding let on a type that implements `Drop`
+  --> $DIR/let_underscore_drop.rs:13:5
+   |
+LL |     let _ = NontrivialDrop;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/let_underscore_drop.rs:2:9
+   |
+LL | #![warn(let_underscore_drop)]
+   |         ^^^^^^^^^^^^^^^^^^^
+help: consider binding to an unused variable to avoid immediately dropping the value
+   |
+LL |     let _unused = NontrivialDrop;
+   |         ~~~~~~~
+help: consider immediately dropping the value
+   |
+LL |     drop(NontrivialDrop);
+   |     ~~~~~              +
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/lint/let_underscore/let_underscore_lock.rs b/src/test/ui/lint/let_underscore/let_underscore_lock.rs
new file mode 100644 (file)
index 0000000..7423862
--- /dev/null
@@ -0,0 +1,7 @@
+// check-fail
+use std::sync::{Arc, Mutex};
+
+fn main() {
+    let data = Arc::new(Mutex::new(0));
+    let _ = data.lock().unwrap(); //~ERROR non-binding let on a synchronization lock
+}
diff --git a/src/test/ui/lint/let_underscore/let_underscore_lock.stderr b/src/test/ui/lint/let_underscore/let_underscore_lock.stderr
new file mode 100644 (file)
index 0000000..fb58af0
--- /dev/null
@@ -0,0 +1,20 @@
+error: non-binding let on a synchronization lock
+  --> $DIR/let_underscore_lock.rs:6:9
+   |
+LL |     let _ = data.lock().unwrap();
+   |         ^   ^^^^^^^^^^^^^^^^^^^^ this binding will immediately drop the value assigned to it
+   |         |
+   |         this lock is not assigned to a binding and is immediately dropped
+   |
+   = note: `#[deny(let_underscore_lock)]` on by default
+help: consider binding to an unused variable to avoid immediately dropping the value
+   |
+LL |     let _unused = data.lock().unwrap();
+   |         ~~~~~~~
+help: consider immediately dropping the value
+   |
+LL |     drop(data.lock().unwrap());
+   |     ~~~~~                    +
+
+error: aborting due to previous error
+
index e9b49c89bf162d519745cd1bbeadc824ac449e8d..a4ffb864dad9cb3848684ef77fa542e1ef4a386d 100644 (file)
@@ -12,7 +12,7 @@ LL |     fn zero(self) -> Foo { self }
 help: remove the extra argument
    |
 LL |     x.zero()
-   |       ~~~~~~
+   |           ~~
 
 error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/method-call-err-msg.rs:14:7
@@ -28,7 +28,7 @@ LL |     fn one(self, _: isize) -> Foo { self }
 help: provide the argument
    |
 LL |      .one(/* isize */)
-   |       ~~~~~~~~~~~~~~~~
+   |          ~~~~~~~~~~~~~
 
 error[E0061]: this function takes 2 arguments but 1 argument was supplied
   --> $DIR/method-call-err-msg.rs:15:7
@@ -44,7 +44,7 @@ LL |     fn two(self, _: isize, _: isize) -> Foo { self }
 help: provide the argument
    |
 LL |      .two(0, /* isize */);
-   |       ~~~~~~~~~~~~~~~~~~~
+   |          ~~~~~~~~~~~~~~~~
 
 error[E0599]: `Foo` is not an iterator
   --> $DIR/method-call-err-msg.rs:19:7
@@ -84,7 +84,7 @@ LL |     fn three<T>(self, _: T, _: T, _: T) -> Foo { self }
 help: provide the arguments
    |
 LL |     y.three::<usize>(/* usize */, /* usize */, /* usize */);
-   |       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/mir/issue-99866.rs b/src/test/ui/mir/issue-99866.rs
new file mode 100644 (file)
index 0000000..d39ae6e
--- /dev/null
@@ -0,0 +1,25 @@
+// check-pass
+pub trait Backend {
+    type DescriptorSetLayout;
+}
+
+pub struct Back;
+
+impl Backend for Back {
+    type DescriptorSetLayout = u32;
+}
+
+pub struct HalSetLayouts {
+    vertex_layout: <Back as Backend>::DescriptorSetLayout,
+}
+
+impl HalSetLayouts {
+    pub fn iter<DSL>(self) -> DSL
+    where
+        Back: Backend<DescriptorSetLayout = DSL>,
+    {
+        self.vertex_layout
+    }
+}
+
+fn main() {}
index 475ea9dfaf1b44d842c3d4dfbe2a11d73df2eea7..fb3597aa853008dad5a56443e7ba40c6c43f187a 100644 (file)
@@ -26,7 +26,7 @@ LL | impl FnMut<(isize,)> for S {
 help: provide the argument
    |
 LL |     let ans = s(/* isize */);
-   |               ~~~~~~~~~~~~~~
+   |                ~~~~~~~~~~~~~
 
 error[E0057]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/overloaded-calls-bad.rs:31:15
@@ -44,7 +44,7 @@ LL | impl FnMut<(isize,)> for S {
 help: remove the extra argument
    |
 LL |     let ans = s(/* isize */);
-   |               ~~~~~~~~~~~~~~
+   |                ~~~~~~~~~~~~~
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/modules/auxiliary/dummy_lib.rs b/src/test/ui/modules/auxiliary/dummy_lib.rs
new file mode 100644 (file)
index 0000000..ef805c1
--- /dev/null
@@ -0,0 +1,2 @@
+#[allow(dead_code)]
+pub struct Dummy;
diff --git a/src/test/ui/modules/special_module_name.rs b/src/test/ui/modules/special_module_name.rs
new file mode 100644 (file)
index 0000000..15c59b2
--- /dev/null
@@ -0,0 +1,8 @@
+mod lib;
+//~^ WARN found module declaration for lib.rs
+//~| ERROR file not found for module `lib`
+mod main;
+//~^ WARN found module declaration for main.rs
+//~| ERROR file not found for module `main`
+
+fn main() {}
diff --git a/src/test/ui/modules/special_module_name.stderr b/src/test/ui/modules/special_module_name.stderr
new file mode 100644 (file)
index 0000000..8b3da29
--- /dev/null
@@ -0,0 +1,37 @@
+error[E0583]: file not found for module `lib`
+  --> $DIR/special_module_name.rs:1:1
+   |
+LL | mod lib;
+   | ^^^^^^^^
+   |
+   = help: to create the module `lib`, create file "$DIR/lib.rs" or "$DIR/lib/mod.rs"
+
+error[E0583]: file not found for module `main`
+  --> $DIR/special_module_name.rs:4:1
+   |
+LL | mod main;
+   | ^^^^^^^^^
+   |
+   = help: to create the module `main`, create file "$DIR/main.rs" or "$DIR/main/mod.rs"
+
+warning: found module declaration for lib.rs
+  --> $DIR/special_module_name.rs:1:1
+   |
+LL | mod lib;
+   | ^^^^^^^^
+   |
+   = note: `#[warn(special_module_name)]` on by default
+   = note: lib.rs is the root of this crate's library target
+   = help: to refer to it from other targets, use the library's name as the path
+
+warning: found module declaration for main.rs
+  --> $DIR/special_module_name.rs:4:1
+   |
+LL | mod main;
+   | ^^^^^^^^^
+   |
+   = note: a binary crate cannot be used as library
+
+error: aborting due to 2 previous errors; 2 warnings emitted
+
+For more information about this error, try `rustc --explain E0583`.
diff --git a/src/test/ui/modules/special_module_name_ignore.rs b/src/test/ui/modules/special_module_name_ignore.rs
new file mode 100644 (file)
index 0000000..07cea9b
--- /dev/null
@@ -0,0 +1,9 @@
+// run-pass
+
+#[path = "auxiliary/dummy_lib.rs"]
+mod lib;
+
+#[path = "auxiliary/dummy_lib.rs"]
+mod main;
+
+fn main() {}
index b04ea14d1a58095238293d750d6b9d93936ccaa7..c07914df7273a0dc06e3e36d57e8fae34f43309d 100644 (file)
@@ -218,7 +218,7 @@ error[E0277]: the trait bound `fn() -> c::TS {c::TS}: Impossible` is not satisfi
   --> $DIR/namespace-mix.rs:56:11
    |
 LL |     check(m3::TS);
-   |     ----- ^^^^^^ the trait `Impossible` is not implemented for `fn() -> c::TS {c::TS}`
+   |     ----- ^^^^^^ the trait `Impossible` is not implemented for fn item `fn() -> c::TS {c::TS}`
    |     |
    |     required by a bound introduced by this call
    |
@@ -274,7 +274,7 @@ error[E0277]: the trait bound `fn() -> namespace_mix::c::TS {namespace_mix::c::T
   --> $DIR/namespace-mix.rs:62:11
    |
 LL |     check(xm3::TS);
-   |     ----- ^^^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::TS {namespace_mix::c::TS}`
+   |     ----- ^^^^^^^ the trait `Impossible` is not implemented for fn item `fn() -> namespace_mix::c::TS {namespace_mix::c::TS}`
    |     |
    |     required by a bound introduced by this call
    |
@@ -526,7 +526,7 @@ error[E0277]: the trait bound `fn() -> c::E {c::E::TV}: Impossible` is not satis
   --> $DIR/namespace-mix.rs:122:11
    |
 LL |     check(m9::TV);
-   |     ----- ^^^^^^ the trait `Impossible` is not implemented for `fn() -> c::E {c::E::TV}`
+   |     ----- ^^^^^^ the trait `Impossible` is not implemented for fn item `fn() -> c::E {c::E::TV}`
    |     |
    |     required by a bound introduced by this call
    |
@@ -582,7 +582,7 @@ error[E0277]: the trait bound `fn() -> namespace_mix::c::E {namespace_mix::xm7::
   --> $DIR/namespace-mix.rs:128:11
    |
 LL |     check(xm9::TV);
-   |     ----- ^^^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::E {namespace_mix::xm7::TV}`
+   |     ----- ^^^^^^^ the trait `Impossible` is not implemented for fn item `fn() -> namespace_mix::c::E {namespace_mix::xm7::TV}`
    |     |
    |     required by a bound introduced by this call
    |
index b1df578ea80a98e48644618b3e218c7937493193..8b2dafb4e1d034443dfcdef861cb4047240fc25b 100644 (file)
@@ -12,7 +12,7 @@ LL | fn foo(a: isize, b: isize, c: isize, d:isize) {
 help: provide the argument
    |
 LL |   foo(1, 2, 3, /* isize */);
-   |   ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |      ~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0061]: this function takes 6 arguments but 3 arguments were supplied
   --> $DIR/not-enough-arguments.rs:29:3
@@ -40,7 +40,7 @@ LL |     f: i32,
 help: provide the arguments
    |
 LL |   bar(1, 2, 3, /* i32 */, /* i32 */, /* i32 */);
-   |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to 2 previous errors
 
index 60b6629e694dbc1d53ff43b277f55dd975014ddd..74f5bb7ddb0ec068f966899458467ec7af4984ab 100644 (file)
@@ -1,24 +1,50 @@
 #![feature(rustc_attrs)]
 
 #[rustc_object_lifetime_default]
-struct A<T>(T); //~ ERROR BaseDefault
+struct A<
+    T, //~ ERROR BaseDefault
+>(T);
 
 #[rustc_object_lifetime_default]
-struct B<'a,T>(&'a (), T); //~ ERROR BaseDefault
+struct B<
+    'a,
+    T, //~ ERROR BaseDefault
+>(&'a (), T);
 
 #[rustc_object_lifetime_default]
-struct C<'a,T:'a>(&'a T); //~ ERROR 'a
+struct C<
+    'a,
+    T: 'a, //~ ERROR 'a
+>(&'a T);
 
 #[rustc_object_lifetime_default]
-struct D<'a,'b,T:'a+'b>(&'a T, &'b T); //~ ERROR Ambiguous
+struct D<
+    'a,
+    'b,
+    T: 'a + 'b, //~ ERROR Ambiguous
+>(&'a T, &'b T);
 
 #[rustc_object_lifetime_default]
-struct E<'a,'b:'a,T:'b>(&'a T, &'b T); //~ ERROR 'b
+struct E<
+    'a,
+    'b: 'a,
+    T: 'b, //~ ERROR 'b
+>(&'a T, &'b T);
 
 #[rustc_object_lifetime_default]
-struct F<'a,'b,T:'a,U:'b>(&'a T, &'b U); //~ ERROR 'a,'b
+struct F<
+    'a,
+    'b,
+    T: 'a, //~ ERROR 'a
+    U: 'b, //~ ERROR 'b
+>(&'a T, &'b U);
 
 #[rustc_object_lifetime_default]
-struct G<'a,'b,T:'a,U:'a+'b>(&'a T, &'b U); //~ ERROR 'a,Ambiguous
-
-fn main() { }
+struct G<
+    'a,
+    'b,
+    T: 'a,      //~ ERROR 'a
+    U: 'a + 'b, //~ ERROR Ambiguous
+>(&'a T, &'b U);
+
+fn main() {}
index 60cb98c8fd37210c0e2c3ea5f7f7629bd468c2d4..a58afad3ef2beab986f63ef3ff0b41901ea7ccf1 100644 (file)
@@ -1,44 +1,56 @@
 error: BaseDefault
-  --> $DIR/object-lifetime-default.rs:4:1
+  --> $DIR/object-lifetime-default.rs:5:5
    |
-LL | struct A<T>(T);
-   | ^^^^^^^^^^^^^^^
+LL |     T,
+   |     ^
 
 error: BaseDefault
-  --> $DIR/object-lifetime-default.rs:7:1
+  --> $DIR/object-lifetime-default.rs:11:5
    |
-LL | struct B<'a,T>(&'a (), T);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     T,
+   |     ^
 
 error: 'a
-  --> $DIR/object-lifetime-default.rs:10:1
+  --> $DIR/object-lifetime-default.rs:17:5
    |
-LL | struct C<'a,T:'a>(&'a T);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     T: 'a,
+   |     ^
 
 error: Ambiguous
-  --> $DIR/object-lifetime-default.rs:13:1
+  --> $DIR/object-lifetime-default.rs:24:5
    |
-LL | struct D<'a,'b,T:'a+'b>(&'a T, &'b T);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     T: 'a + 'b,
+   |     ^
 
 error: 'b
-  --> $DIR/object-lifetime-default.rs:16:1
+  --> $DIR/object-lifetime-default.rs:31:5
    |
-LL | struct E<'a,'b:'a,T:'b>(&'a T, &'b T);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     T: 'b,
+   |     ^
 
-error: 'a,'b
-  --> $DIR/object-lifetime-default.rs:19:1
+error: 'a
+  --> $DIR/object-lifetime-default.rs:38:5
+   |
+LL |     T: 'a,
+   |     ^
+
+error: 'b
+  --> $DIR/object-lifetime-default.rs:39:5
    |
-LL | struct F<'a,'b,T:'a,U:'b>(&'a T, &'b U);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     U: 'b,
+   |     ^
 
-error: 'a,Ambiguous
-  --> $DIR/object-lifetime-default.rs:22:1
+error: 'a
+  --> $DIR/object-lifetime-default.rs:46:5
+   |
+LL |     T: 'a,
+   |     ^
+
+error: Ambiguous
+  --> $DIR/object-lifetime-default.rs:47:5
    |
-LL | struct G<'a,'b,T:'a,U:'a+'b>(&'a T, &'b U);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     U: 'a + 'b,
+   |     ^
 
-error: aborting due to 7 previous errors
+error: aborting due to 9 previous errors
 
diff --git a/src/test/ui/on-unimplemented/enclosing-scope.rs b/src/test/ui/on-unimplemented/enclosing-scope.rs
deleted file mode 100644 (file)
index 881bff6..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-// Test scope annotations from `enclosing_scope` parameter
-
-#![feature(rustc_attrs)]
-
-#[rustc_on_unimplemented(enclosing_scope="in this scope")]
-trait Trait{}
-
-struct Foo;
-
-fn f<T: Trait>(x: T) {}
-
-fn main() {
-    let x = || {
-        f(Foo{}); //~ ERROR the trait bound `Foo: Trait` is not satisfied
-        let y = || {
-            f(Foo{}); //~ ERROR the trait bound `Foo: Trait` is not satisfied
-        };
-    };
-
-    {
-        {
-            f(Foo{}); //~ ERROR the trait bound `Foo: Trait` is not satisfied
-        }
-    }
-
-    f(Foo{}); //~ ERROR the trait bound `Foo: Trait` is not satisfied
-}
diff --git a/src/test/ui/on-unimplemented/enclosing-scope.stderr b/src/test/ui/on-unimplemented/enclosing-scope.stderr
deleted file mode 100644 (file)
index 67759d0..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-error[E0277]: the trait bound `Foo: Trait` is not satisfied
-  --> $DIR/enclosing-scope.rs:14:11
-   |
-LL |       let x = || {
-   |  _____________-
-LL | |         f(Foo{});
-   | |         - ^^^^^ the trait `Trait` is not implemented for `Foo`
-   | |         |
-   | |         required by a bound introduced by this call
-LL | |         let y = || {
-LL | |             f(Foo{});
-LL | |         };
-LL | |     };
-   | |_____- in this scope
-   |
-note: required by a bound in `f`
-  --> $DIR/enclosing-scope.rs:10:9
-   |
-LL | fn f<T: Trait>(x: T) {}
-   |         ^^^^^ required by this bound in `f`
-
-error[E0277]: the trait bound `Foo: Trait` is not satisfied
-  --> $DIR/enclosing-scope.rs:16:15
-   |
-LL |           let y = || {
-   |  _________________-
-LL | |             f(Foo{});
-   | |             - ^^^^^ the trait `Trait` is not implemented for `Foo`
-   | |             |
-   | |             required by a bound introduced by this call
-LL | |         };
-   | |_________- in this scope
-   |
-note: required by a bound in `f`
-  --> $DIR/enclosing-scope.rs:10:9
-   |
-LL | fn f<T: Trait>(x: T) {}
-   |         ^^^^^ required by this bound in `f`
-
-error[E0277]: the trait bound `Foo: Trait` is not satisfied
-  --> $DIR/enclosing-scope.rs:22:15
-   |
-LL | / fn main() {
-LL | |     let x = || {
-LL | |         f(Foo{});
-LL | |         let y = || {
-...  |
-LL | |             f(Foo{});
-   | |             - ^^^^^ the trait `Trait` is not implemented for `Foo`
-   | |             |
-   | |             required by a bound introduced by this call
-...  |
-LL | |     f(Foo{});
-LL | | }
-   | |_- in this scope
-   |
-note: required by a bound in `f`
-  --> $DIR/enclosing-scope.rs:10:9
-   |
-LL | fn f<T: Trait>(x: T) {}
-   |         ^^^^^ required by this bound in `f`
-
-error[E0277]: the trait bound `Foo: Trait` is not satisfied
-  --> $DIR/enclosing-scope.rs:26:7
-   |
-LL | / fn main() {
-LL | |     let x = || {
-LL | |         f(Foo{});
-LL | |         let y = || {
-...  |
-LL | |     f(Foo{});
-   | |     - ^^^^^ the trait `Trait` is not implemented for `Foo`
-   | |     |
-   | |     required by a bound introduced by this call
-LL | | }
-   | |_- in this scope
-   |
-note: required by a bound in `f`
-  --> $DIR/enclosing-scope.rs:10:9
-   |
-LL | fn f<T: Trait>(x: T) {}
-   |         ^^^^^ required by this bound in `f`
-
-error: aborting due to 4 previous errors
-
-For more information about this error, try `rustc --explain E0277`.
index 79c40f650db810daf1f9197fdcd46d4a2f05311e..a32fd4566231db60224c29803608766b650b5ac8 100644 (file)
@@ -32,8 +32,14 @@ fn index(&self, _index: Bar<usize>) -> &i32 {
 fn main() {
     Index::index(&[] as &[i32], 2u32);
     //~^ ERROR E0277
+    //~| ERROR E0277
+    //~| ERROR E0277
     Index::index(&[] as &[i32], Foo(2u32));
     //~^ ERROR E0277
+    //~| ERROR E0277
+    //~| ERROR E0277
     Index::index(&[] as &[i32], Bar(2u32));
     //~^ ERROR E0277
+    //~| ERROR E0277
+    //~| ERROR E0277
 }
index d47a398412fe4e7b37ffe5db36e74818506f83ea..d628b159a66d2067c1808cd20a7f4cbddfed58f8 100644 (file)
@@ -11,8 +11,19 @@ LL |     Index::index(&[] as &[i32], 2u32);
              <[i32] as Index<Bar<usize>>>
              <[i32] as Index<Foo<usize>>>
 
+error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
+  --> $DIR/multiple-impls.rs:33:5
+   |
+LL |     Index::index(&[] as &[i32], 2u32);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait message
+   |
+   = help: the trait `Index<u32>` is not implemented for `[i32]`
+   = help: the following other types implement trait `Index<Idx>`:
+             <[i32] as Index<Bar<usize>>>
+             <[i32] as Index<Foo<usize>>>
+
 error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied
-  --> $DIR/multiple-impls.rs:35:33
+  --> $DIR/multiple-impls.rs:37:33
    |
 LL |     Index::index(&[] as &[i32], Foo(2u32));
    |     ------------                ^^^^^^^^^ on impl for Foo
@@ -24,8 +35,19 @@ LL |     Index::index(&[] as &[i32], Foo(2u32));
              <[i32] as Index<Bar<usize>>>
              <[i32] as Index<Foo<usize>>>
 
+error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied
+  --> $DIR/multiple-impls.rs:37:5
+   |
+LL |     Index::index(&[] as &[i32], Foo(2u32));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ on impl for Foo
+   |
+   = help: the trait `Index<Foo<u32>>` is not implemented for `[i32]`
+   = help: the following other types implement trait `Index<Idx>`:
+             <[i32] as Index<Bar<usize>>>
+             <[i32] as Index<Foo<usize>>>
+
 error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied
-  --> $DIR/multiple-impls.rs:37:33
+  --> $DIR/multiple-impls.rs:41:33
    |
 LL |     Index::index(&[] as &[i32], Bar(2u32));
    |     ------------                ^^^^^^^^^ on impl for Bar
@@ -37,6 +59,50 @@ LL |     Index::index(&[] as &[i32], Bar(2u32));
              <[i32] as Index<Bar<usize>>>
              <[i32] as Index<Foo<usize>>>
 
-error: aborting due to 3 previous errors
+error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied
+  --> $DIR/multiple-impls.rs:41:5
+   |
+LL |     Index::index(&[] as &[i32], Bar(2u32));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ on impl for Bar
+   |
+   = help: the trait `Index<Bar<u32>>` is not implemented for `[i32]`
+   = help: the following other types implement trait `Index<Idx>`:
+             <[i32] as Index<Bar<usize>>>
+             <[i32] as Index<Foo<usize>>>
+
+error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
+  --> $DIR/multiple-impls.rs:33:5
+   |
+LL |     Index::index(&[] as &[i32], 2u32);
+   |     ^^^^^^^^^^^^ trait message
+   |
+   = help: the trait `Index<u32>` is not implemented for `[i32]`
+   = help: the following other types implement trait `Index<Idx>`:
+             <[i32] as Index<Bar<usize>>>
+             <[i32] as Index<Foo<usize>>>
+
+error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied
+  --> $DIR/multiple-impls.rs:37:5
+   |
+LL |     Index::index(&[] as &[i32], Foo(2u32));
+   |     ^^^^^^^^^^^^ on impl for Foo
+   |
+   = help: the trait `Index<Foo<u32>>` is not implemented for `[i32]`
+   = help: the following other types implement trait `Index<Idx>`:
+             <[i32] as Index<Bar<usize>>>
+             <[i32] as Index<Foo<usize>>>
+
+error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied
+  --> $DIR/multiple-impls.rs:41:5
+   |
+LL |     Index::index(&[] as &[i32], Bar(2u32));
+   |     ^^^^^^^^^^^^ on impl for Bar
+   |
+   = help: the trait `Index<Bar<u32>>` is not implemented for `[i32]`
+   = help: the following other types implement trait `Index<Idx>`:
+             <[i32] as Index<Bar<usize>>>
+             <[i32] as Index<Foo<usize>>>
+
+error: aborting due to 9 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
index b03e1f7c6a8dfbb8d76b0865b245e48301d5cb18..d0537810ce11e4a099509e5f74fec4b999f7061f 100644 (file)
@@ -21,4 +21,6 @@ fn index(&self, index: usize) -> &i32 {
 fn main() {
     Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
     //~^ ERROR E0277
+    //~| ERROR E0277
+    //~| ERROR E0277
 }
index 01315b854098ee4dee9d1c06703ce4cc3477dfac..2253c5992a64a346cf88b15d91cbb3954ae9c2aa 100644 (file)
@@ -9,6 +9,24 @@ LL |     Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
    = help: the trait `Index<u32>` is not implemented for `[i32]`
    = help: the trait `Index<usize>` is implemented for `[i32]`
 
-error: aborting due to previous error
+error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
+  --> $DIR/on-impl.rs:22:5
+   |
+LL |     Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice
+   |
+   = help: the trait `Index<u32>` is not implemented for `[i32]`
+   = help: the trait `Index<usize>` is implemented for `[i32]`
+
+error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
+  --> $DIR/on-impl.rs:22:5
+   |
+LL |     Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
+   |     ^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice
+   |
+   = help: the trait `Index<u32>` is not implemented for `[i32]`
+   = help: the trait `Index<usize>` is implemented for `[i32]`
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/on-unimplemented/parent-label.rs b/src/test/ui/on-unimplemented/parent-label.rs
new file mode 100644 (file)
index 0000000..b65f649
--- /dev/null
@@ -0,0 +1,27 @@
+// Test scope annotations from `parent_label` parameter
+
+#![feature(rustc_attrs)]
+
+#[rustc_on_unimplemented(parent_label = "in this scope")]
+trait Trait {}
+
+struct Foo;
+
+fn f<T: Trait>(x: T) {}
+
+fn main() {
+    let x = || {
+        f(Foo {}); //~ ERROR the trait bound `Foo: Trait` is not satisfied
+        let y = || {
+            f(Foo {}); //~ ERROR the trait bound `Foo: Trait` is not satisfied
+        };
+    };
+
+    {
+        {
+            f(Foo {}); //~ ERROR the trait bound `Foo: Trait` is not satisfied
+        }
+    }
+
+    f(Foo {}); //~ ERROR the trait bound `Foo: Trait` is not satisfied
+}
diff --git a/src/test/ui/on-unimplemented/parent-label.stderr b/src/test/ui/on-unimplemented/parent-label.stderr
new file mode 100644 (file)
index 0000000..8cd7412
--- /dev/null
@@ -0,0 +1,69 @@
+error[E0277]: the trait bound `Foo: Trait` is not satisfied
+  --> $DIR/parent-label.rs:14:11
+   |
+LL |     let x = || {
+   |             -- in this scope
+LL |         f(Foo {});
+   |         - ^^^^^^ the trait `Trait` is not implemented for `Foo`
+   |         |
+   |         required by a bound introduced by this call
+   |
+note: required by a bound in `f`
+  --> $DIR/parent-label.rs:10:9
+   |
+LL | fn f<T: Trait>(x: T) {}
+   |         ^^^^^ required by this bound in `f`
+
+error[E0277]: the trait bound `Foo: Trait` is not satisfied
+  --> $DIR/parent-label.rs:16:15
+   |
+LL |         let y = || {
+   |                 -- in this scope
+LL |             f(Foo {});
+   |             - ^^^^^^ the trait `Trait` is not implemented for `Foo`
+   |             |
+   |             required by a bound introduced by this call
+   |
+note: required by a bound in `f`
+  --> $DIR/parent-label.rs:10:9
+   |
+LL | fn f<T: Trait>(x: T) {}
+   |         ^^^^^ required by this bound in `f`
+
+error[E0277]: the trait bound `Foo: Trait` is not satisfied
+  --> $DIR/parent-label.rs:22:15
+   |
+LL | fn main() {
+   | --------- in this scope
+...
+LL |             f(Foo {});
+   |             - ^^^^^^ the trait `Trait` is not implemented for `Foo`
+   |             |
+   |             required by a bound introduced by this call
+   |
+note: required by a bound in `f`
+  --> $DIR/parent-label.rs:10:9
+   |
+LL | fn f<T: Trait>(x: T) {}
+   |         ^^^^^ required by this bound in `f`
+
+error[E0277]: the trait bound `Foo: Trait` is not satisfied
+  --> $DIR/parent-label.rs:26:7
+   |
+LL | fn main() {
+   | --------- in this scope
+...
+LL |     f(Foo {});
+   |     - ^^^^^^ the trait `Trait` is not implemented for `Foo`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `f`
+  --> $DIR/parent-label.rs:10:9
+   |
+LL | fn f<T: Trait>(x: T) {}
+   |         ^^^^^ required by this bound in `f`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/privacy/access_levels.rs b/src/test/ui/privacy/access_levels.rs
new file mode 100644 (file)
index 0000000..d51d2b5
--- /dev/null
@@ -0,0 +1,49 @@
+#![feature(rustc_attrs)]
+
+#[rustc_access_level] mod outer { //~ ERROR None
+    #[rustc_access_level] pub mod inner { //~ ERROR Some(Exported)
+        #[rustc_access_level]
+        extern "C" { //~ ERROR Some(Exported)
+            #[rustc_access_level] static a: u8; //~ ERROR None
+            #[rustc_access_level] pub fn b(); //~ ERROR Some(Exported)
+        }
+        #[rustc_access_level]
+        pub trait Trait { //~ ERROR Some(Exported)
+            #[rustc_access_level] const A: i32; //~ ERROR Some(Exported)
+            #[rustc_access_level] type B; //~ ERROR Some(Exported)
+        }
+
+        #[rustc_access_level]
+        pub struct Struct { //~ ERROR Some(Exported)
+            #[rustc_access_level] a: u8, //~ ERROR None
+            #[rustc_access_level] pub b: u8, //~ ERROR Some(Exported)
+        }
+
+        #[rustc_access_level]
+        pub union Union { //~ ERROR Some(Exported)
+            #[rustc_access_level] a: u8, //~ ERROR None
+            #[rustc_access_level] pub b: u8, //~ ERROR Some(Exported)
+        }
+
+        #[rustc_access_level]
+        pub enum Enum { //~ ERROR Some(Exported)
+            #[rustc_access_level] A( //~ ERROR Some(Exported)
+                #[rustc_access_level] Struct, //~ ERROR Some(Exported)
+                #[rustc_access_level] Union,  //~ ERROR Some(Exported)
+            ),
+        }
+    }
+
+    #[rustc_access_level] macro_rules! none_macro { //~ ERROR None
+        () => {};
+    }
+
+    #[macro_export]
+    #[rustc_access_level] macro_rules! public_macro { //~ ERROR Some(Public)
+        () => {};
+    }
+}
+
+pub use outer::inner;
+
+fn main() {}
diff --git a/src/test/ui/privacy/access_levels.stderr b/src/test/ui/privacy/access_levels.stderr
new file mode 100644 (file)
index 0000000..f326293
--- /dev/null
@@ -0,0 +1,125 @@
+error: None
+  --> $DIR/access_levels.rs:3:23
+   |
+LL | #[rustc_access_level] mod outer {
+   |                       ^^^^^^^^^
+
+error: Some(Exported)
+  --> $DIR/access_levels.rs:4:27
+   |
+LL |     #[rustc_access_level] pub mod inner {
+   |                           ^^^^^^^^^^^^^
+
+error: Some(Exported)
+  --> $DIR/access_levels.rs:6:9
+   |
+LL | /         extern "C" {
+LL | |             #[rustc_access_level] static a: u8;
+LL | |             #[rustc_access_level] pub fn b();
+LL | |         }
+   | |_________^
+
+error: Some(Exported)
+  --> $DIR/access_levels.rs:11:9
+   |
+LL |         pub trait Trait {
+   |         ^^^^^^^^^^^^^^^
+
+error: Some(Exported)
+  --> $DIR/access_levels.rs:17:9
+   |
+LL |         pub struct Struct {
+   |         ^^^^^^^^^^^^^^^^^
+
+error: None
+  --> $DIR/access_levels.rs:18:35
+   |
+LL |             #[rustc_access_level] a: u8,
+   |                                   ^^^^^
+
+error: Some(Exported)
+  --> $DIR/access_levels.rs:19:35
+   |
+LL |             #[rustc_access_level] pub b: u8,
+   |                                   ^^^^^^^^^
+
+error: Some(Exported)
+  --> $DIR/access_levels.rs:23:9
+   |
+LL |         pub union Union {
+   |         ^^^^^^^^^^^^^^^
+
+error: None
+  --> $DIR/access_levels.rs:24:35
+   |
+LL |             #[rustc_access_level] a: u8,
+   |                                   ^^^^^
+
+error: Some(Exported)
+  --> $DIR/access_levels.rs:25:35
+   |
+LL |             #[rustc_access_level] pub b: u8,
+   |                                   ^^^^^^^^^
+
+error: Some(Exported)
+  --> $DIR/access_levels.rs:29:9
+   |
+LL |         pub enum Enum {
+   |         ^^^^^^^^^^^^^
+
+error: Some(Exported)
+  --> $DIR/access_levels.rs:30:35
+   |
+LL |             #[rustc_access_level] A(
+   |                                   ^
+
+error: Some(Exported)
+  --> $DIR/access_levels.rs:31:39
+   |
+LL |                 #[rustc_access_level] Struct,
+   |                                       ^^^^^^
+
+error: Some(Exported)
+  --> $DIR/access_levels.rs:32:39
+   |
+LL |                 #[rustc_access_level] Union,
+   |                                       ^^^^^
+
+error: None
+  --> $DIR/access_levels.rs:37:27
+   |
+LL |     #[rustc_access_level] macro_rules! none_macro {
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: Some(Public)
+  --> $DIR/access_levels.rs:42:27
+   |
+LL |     #[rustc_access_level] macro_rules! public_macro {
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: Some(Exported)
+  --> $DIR/access_levels.rs:12:35
+   |
+LL |             #[rustc_access_level] const A: i32;
+   |                                   ^^^^^^^^^^^^
+
+error: Some(Exported)
+  --> $DIR/access_levels.rs:13:35
+   |
+LL |             #[rustc_access_level] type B;
+   |                                   ^^^^^^
+
+error: None
+  --> $DIR/access_levels.rs:7:35
+   |
+LL |             #[rustc_access_level] static a: u8;
+   |                                   ^^^^^^^^^^^^
+
+error: Some(Exported)
+  --> $DIR/access_levels.rs:8:35
+   |
+LL |             #[rustc_access_level] pub fn b();
+   |                                   ^^^^^^^^^^
+
+error: aborting due to 20 previous errors
+
index 5463e79d74e0a262eefcbcc5bfca58d53f702f4f..1d6ef8a13610a1be1294e9af0943f5da4f7e94e3 100644 (file)
@@ -80,13 +80,21 @@ fn assert_ts_eq(lhs: &TokenStream, rhs: &TokenStream) {
 pub fn expand_expr_is(input: TokenStream) -> TokenStream {
     let mut iter = input.into_iter();
     let mut expected_tts = Vec::new();
-    loop {
+    let comma = loop {
         match iter.next() {
-            Some(TokenTree::Punct(ref p)) if p.as_char() == ',' => break,
+            Some(TokenTree::Punct(p)) if p.as_char() == ',' => break p,
             Some(tt) => expected_tts.push(tt),
             None => panic!("expected comma"),
         }
-    }
+    };
+
+    // Make sure that `Ident` and `Literal` objects from this proc-macro's
+    // environment are not invalidated when `expand_expr` recursively invokes
+    // another macro by taking a local copy, and checking it after the fact.
+    let pre_expand_span = comma.span();
+    let pre_expand_ident = Ident::new("ident", comma.span());
+    let pre_expand_literal = Literal::string("literal");
+    let pre_expand_call_site = Span::call_site();
 
     let expected = expected_tts.into_iter().collect::<TokenStream>();
     let expanded = iter.collect::<TokenStream>().expand_expr().expect("expand_expr failed");
@@ -100,6 +108,15 @@ pub fn expand_expr_is(input: TokenStream) -> TokenStream {
     // Also compare the raw tts to make sure they line up.
     assert_ts_eq(&expected, &expanded);
 
+    assert!(comma.span().eq(&pre_expand_span), "pre-expansion span is still equal");
+    assert_eq!(pre_expand_ident.to_string(), "ident", "pre-expansion identifier is still valid");
+    assert_eq!(
+        pre_expand_literal.to_string(),
+        "\"literal\"",
+        "pre-expansion literal is still valid"
+    );
+    assert!(Span::call_site().eq(&pre_expand_call_site), "pre-expansion call-site is still equal");
+
     TokenStream::new()
 }
 
index 78b0beff0da39d6aae0af07deafac0e05ce2b58f..59b3e44c74a52270e2e87b2d9f205072e2fd4b59 100644 (file)
@@ -10,7 +10,7 @@ LL | | }
    | |_call the function in a closure: `|| unsafe { /* code */ }`
    |   required by a bound introduced by this call
    |
-   = help: the trait `Fn<(proc_macro::TokenStream,)>` is not implemented for `unsafe extern "C" fn(i32, u32) -> u32 {foo}`
+   = help: the trait `Fn<(proc_macro::TokenStream,)>` is not implemented for fn item `unsafe extern "C" fn(i32, u32) -> u32 {foo}`
    = 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
index f0eb1a4f487375576da404128fb56b1cd57b153a..6d5d5bad9fe1a342f67b5b581035203fccda800d 100644 (file)
@@ -34,7 +34,7 @@ LL | pub const fn size_of<T>() -> usize {
 help: remove the extra argument
    |
 LL |     std::mem::size_of();
-   |     ~~~~~~~~~~~~~~~~~~~
+   |                      ~~
 
 error: aborting due to 3 previous errors
 
index fce0cdfe0d569bb9f0208bd837836537a9102139..bc06fde49e993c3305934510f91e48268a907558 100644 (file)
@@ -1493,17 +1493,11 @@ LL |     if (let 0 = 0)? {}
 error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> $DIR/disallowed-positions.rs:132:19
    |
-LL | / fn nested_within_if_expr() {
-LL | |     if &let 0 = 0 {}
-LL | |
-LL | |
-...  |
-LL | |     if (let 0 = 0)? {}
-   | |                   ^ cannot use the `?` operator in a function that returns `()`
-...  |
-LL | |
-LL | | }
-   | |_- this function should return `Result` or `Option` to accept `?`
+LL | fn nested_within_if_expr() {
+   | -------------------------- this function should return `Result` or `Option` to accept `?`
+...
+LL |     if (let 0 = 0)? {}
+   |                   ^ cannot use the `?` operator in a function that returns `()`
    |
    = help: the trait `FromResidual<_>` is not implemented for `()`
 
@@ -1693,17 +1687,11 @@ LL |     while (let 0 = 0)? {}
 error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> $DIR/disallowed-positions.rs:224:22
    |
-LL | / fn nested_within_while_expr() {
-LL | |     while &let 0 = 0 {}
-LL | |
-LL | |
-...  |
-LL | |     while (let 0 = 0)? {}
-   | |                      ^ cannot use the `?` operator in a function that returns `()`
-...  |
-LL | |
-LL | | }
-   | |_- this function should return `Result` or `Option` to accept `?`
+LL | fn nested_within_while_expr() {
+   | ----------------------------- this function should return `Result` or `Option` to accept `?`
+...
+LL |     while (let 0 = 0)? {}
+   |                      ^ cannot use the `?` operator in a function that returns `()`
    |
    = help: the trait `FromResidual<_>` is not implemented for `()`
 
@@ -1881,17 +1869,11 @@ LL |     (let 0 = 0)?;
 error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> $DIR/disallowed-positions.rs:325:16
    |
-LL | / fn outside_if_and_while_expr() {
-LL | |     &let 0 = 0;
-LL | |
-LL | |
-...  |
-LL | |     (let 0 = 0)?;
-   | |                ^ cannot use the `?` operator in a function that returns `()`
-...  |
-LL | |
-LL | | }
-   | |_- this function should return `Result` or `Option` to accept `?`
+LL | fn outside_if_and_while_expr() {
+   | ------------------------------ this function should return `Result` or `Option` to accept `?`
+...
+LL |     (let 0 = 0)?;
+   |                ^ cannot use the `?` operator in a function that returns `()`
    |
    = help: the trait `FromResidual<_>` is not implemented for `()`
 
index 94a90a568548988a4754644f771c8838c928d9a6..fc7bf22775dd715188c1f287f14c96737a96b791 100644 (file)
@@ -6,7 +6,7 @@ LL |     call(foo);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `Fn<()>` is not implemented for `fn() {foo}`
+   = help: the trait `Fn<()>` is not implemented for fn item `fn() {foo}`
    = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
    = note: `#[target_feature]` functions do not implement the `Fn` traits
 note: required by a bound in `call`
@@ -23,7 +23,7 @@ LL |     call_mut(foo);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `FnMut<()>` is not implemented for `fn() {foo}`
+   = help: the trait `FnMut<()>` is not implemented for fn item `fn() {foo}`
    = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
    = note: `#[target_feature]` functions do not implement the `Fn` traits
 note: required by a bound in `call_mut`
@@ -40,7 +40,7 @@ LL |     call_once(foo);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `FnOnce<()>` is not implemented for `fn() {foo}`
+   = help: the trait `FnOnce<()>` is not implemented for fn item `fn() {foo}`
    = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
    = note: `#[target_feature]` functions do not implement the `Fn` traits
 note: required by a bound in `call_once`
@@ -57,7 +57,7 @@ LL |     call(foo_unsafe);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `Fn<()>` is not implemented for `unsafe fn() {foo_unsafe}`
+   = help: the trait `Fn<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}`
    = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
    = note: `#[target_feature]` functions do not implement the `Fn` traits
 note: required by a bound in `call`
@@ -74,7 +74,7 @@ LL |     call_mut(foo_unsafe);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `FnMut<()>` is not implemented for `unsafe fn() {foo_unsafe}`
+   = help: the trait `FnMut<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}`
    = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
    = note: `#[target_feature]` functions do not implement the `Fn` traits
 note: required by a bound in `call_mut`
@@ -91,7 +91,7 @@ LL |     call_once(foo_unsafe);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `FnOnce<()>` is not implemented for `unsafe fn() {foo_unsafe}`
+   = help: the trait `FnOnce<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}`
    = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
    = note: `#[target_feature]` functions do not implement the `Fn` traits
 note: required by a bound in `call_once`
index 28a911d0c5bfa2f45264f36f69c77948843a4485..15179954adcd927da4b352383e350edafca24ca1 100644 (file)
@@ -64,7 +64,7 @@ LL | fn foo(Option<i32>, String) {}
 help: remove the extra argument
    |
 LL |     foo(Some(42), 2);
-   |     ~~~~~~~~~~~~~~~~
+   |        ~~~~~~~~~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/issue-34264.rs:8:13
@@ -94,7 +94,7 @@ LL | fn bar(x, y: usize) {}
 help: remove the extra argument
    |
 LL |     bar(1, 2);
-   |     ~~~~~~~~~
+   |        ~~~~~~
 
 error: aborting due to 6 previous errors
 
index d2afd277ecf79edd74633d9f74da968c2e2e4816..b76a3ab307ae458bc091ec8a5b0f22099e82a962 100644 (file)
@@ -12,7 +12,7 @@ LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
 help: provide the argument
    |
 LL |     let _: Result<(), String> = Ok(());
-   |                                 ~~~~~~
+   |                                   ~~~~
 
 error[E0061]: this function takes 2 arguments but 0 arguments were supplied
   --> $DIR/missing-unit-argument.rs:12:5
@@ -28,7 +28,7 @@ LL | fn foo(():(), ():()) {}
 help: provide the arguments
    |
 LL |     foo((), ());
-   |     ~~~~~~~~~~~
+   |        ~~~~~~~~
 
 error[E0061]: this function takes 2 arguments but 1 argument was supplied
   --> $DIR/missing-unit-argument.rs:13:5
@@ -44,7 +44,7 @@ LL | fn foo(():(), ():()) {}
 help: provide the argument
    |
 LL |     foo((), ());
-   |     ~~~~~~~~~~~
+   |        ~~~~~~~~
 
 error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/missing-unit-argument.rs:14:5
@@ -60,7 +60,7 @@ LL | fn bar(():()) {}
 help: provide the argument
    |
 LL |     bar(());
-   |     ~~~~~~~
+   |        ~~~~
 
 error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/missing-unit-argument.rs:15:7
@@ -76,7 +76,7 @@ LL |     fn baz(self, (): ()) { }
 help: provide the argument
    |
 LL |     S.baz(());
-   |       ~~~~~~~
+   |          ~~~~
 
 error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/missing-unit-argument.rs:16:7
@@ -92,7 +92,7 @@ LL |     fn generic<T>(self, _: T) { }
 help: provide the argument
    |
 LL |     S.generic::<()>(());
-   |       ~~~~~~~~~~~~~~~~~
+   |                    ~~~~
 
 error: aborting due to 6 previous errors
 
index eb828bb9a2c179352d4e46b65dc26df8ef57fd68..0a736f7be834e6da66083c655a68db6dd3999ac2 100644 (file)
-
-PRE EXPANSION AST STATS
-
-Name                Accumulated Size         Count     Item Size
-----------------------------------------------------------------
-ExprField                 48 ( 0.6%)             1            48
-Crate                     56 ( 0.7%)             1            56
-Attribute                 64 ( 0.8%)             2            32
-- Normal                    32 ( 0.4%)             1
-- DocComment                32 ( 0.4%)             1
-GenericArgs               64 ( 0.8%)             1            64
-- AngleBracketed            64 ( 0.8%)             1
-Local                     72 ( 0.9%)             1            72
-WherePredicate            72 ( 0.9%)             1            72
-- BoundPredicate            72 ( 0.9%)             1
-Arm                       96 ( 1.1%)             2            48
-ForeignItem               96 ( 1.1%)             1            96
-- Fn                        96 ( 1.1%)             1
-FieldDef                 160 ( 1.9%)             2            80
-Stmt                     160 ( 1.9%)             5            32
-- Local                     32 ( 0.4%)             1
-- MacCall                   32 ( 0.4%)             1
-- Expr                      96 ( 1.1%)             3
-Param                    160 ( 1.9%)             4            40
-FnDecl                   200 ( 2.4%)             5            40
-Variant                  240 ( 2.8%)             2           120
-Block                    288 ( 3.4%)             6            48
-GenericBound             352 ( 4.2%)             4            88
-- Trait                    352 ( 4.2%)             4
-AssocItem                416 ( 4.9%)             4           104
-- TyAlias                  208 ( 2.5%)             2
-- Fn                       208 ( 2.5%)             2
-GenericParam             520 ( 6.1%)             5           104
-PathSegment              720 ( 8.5%)            30            24
-Expr                     832 ( 9.8%)             8           104
-- Path                     104 ( 1.2%)             1
-- Match                    104 ( 1.2%)             1
-- Struct                   104 ( 1.2%)             1
-- Lit                      208 ( 2.5%)             2
-- Block                    312 ( 3.7%)             3
-Pat                      840 ( 9.9%)             7           120
-- Struct                   120 ( 1.4%)             1
-- Wild                     120 ( 1.4%)             1
-- Ident                    600 ( 7.1%)             5
-Ty                     1_344 (15.9%)            14            96
-- Rptr                      96 ( 1.1%)             1
-- Ptr                       96 ( 1.1%)             1
-- ImplicitSelf             192 ( 2.3%)             2
-- Path                     960 (11.4%)            10
-Item                   1_656 (19.6%)             9           184
-- Trait                    184 ( 2.2%)             1
-- Enum                     184 ( 2.2%)             1
-- ForeignMod               184 ( 2.2%)             1
-- Impl                     184 ( 2.2%)             1
-- Fn                       368 ( 4.4%)             2
-- Use                      552 ( 6.5%)             3
-----------------------------------------------------------------
-Total                  8_456
-
-
-POST EXPANSION AST STATS
-
-Name                Accumulated Size         Count     Item Size
-----------------------------------------------------------------
-ExprField                 48 ( 0.5%)             1            48
-Crate                     56 ( 0.6%)             1            56
-GenericArgs               64 ( 0.7%)             1            64
-- AngleBracketed            64 ( 0.7%)             1
-Local                     72 ( 0.8%)             1            72
-WherePredicate            72 ( 0.8%)             1            72
-- BoundPredicate            72 ( 0.8%)             1
-Arm                       96 ( 1.0%)             2            48
-ForeignItem               96 ( 1.0%)             1            96
-- Fn                        96 ( 1.0%)             1
-InlineAsm                120 ( 1.3%)             1           120
-Attribute                128 ( 1.4%)             4            32
-- DocComment                32 ( 0.3%)             1
-- Normal                    96 ( 1.0%)             3
-FieldDef                 160 ( 1.7%)             2            80
-Stmt                     160 ( 1.7%)             5            32
-- Local                     32 ( 0.3%)             1
-- Semi                      32 ( 0.3%)             1
-- Expr                      96 ( 1.0%)             3
-Param                    160 ( 1.7%)             4            40
-FnDecl                   200 ( 2.2%)             5            40
-Variant                  240 ( 2.6%)             2           120
-Block                    288 ( 3.1%)             6            48
-GenericBound             352 ( 3.8%)             4            88
-- Trait                    352 ( 3.8%)             4
-AssocItem                416 ( 4.5%)             4           104
-- TyAlias                  208 ( 2.3%)             2
-- Fn                       208 ( 2.3%)             2
-GenericParam             520 ( 5.7%)             5           104
-PathSegment              792 ( 8.6%)            33            24
-Pat                      840 ( 9.1%)             7           120
-- Struct                   120 ( 1.3%)             1
-- Wild                     120 ( 1.3%)             1
-- Ident                    600 ( 6.5%)             5
-Expr                     936 (10.2%)             9           104
-- Path                     104 ( 1.1%)             1
-- Match                    104 ( 1.1%)             1
-- Struct                   104 ( 1.1%)             1
-- InlineAsm                104 ( 1.1%)             1
-- Lit                      208 ( 2.3%)             2
-- Block                    312 ( 3.4%)             3
-Ty                     1_344 (14.6%)            14            96
-- Rptr                      96 ( 1.0%)             1
-- Ptr                       96 ( 1.0%)             1
-- ImplicitSelf             192 ( 2.1%)             2
-- Path                     960 (10.5%)            10
-Item                   2_024 (22.0%)            11           184
-- Trait                    184 ( 2.0%)             1
-- Enum                     184 ( 2.0%)             1
-- ExternCrate              184 ( 2.0%)             1
-- ForeignMod               184 ( 2.0%)             1
-- Impl                     184 ( 2.0%)             1
-- Fn                       368 ( 4.0%)             2
-- Use                      736 ( 8.0%)             4
-----------------------------------------------------------------
-Total                  9_184
-
-
-HIR STATS
-
-Name                Accumulated Size         Count     Item Size
-----------------------------------------------------------------
-Param                     64 ( 0.7%)             2            32
-Local                     64 ( 0.7%)             1            64
-ForeignItem               72 ( 0.8%)             1            72
-FieldDef                  96 ( 1.0%)             2            48
-Arm                       96 ( 1.0%)             2            48
-Stmt                      96 ( 1.0%)             3            32
-FnDecl                   120 ( 1.3%)             3            40
-Attribute                128 ( 1.4%)             4            32
-Lifetime                 128 ( 1.4%)             4            32
-Variant                  160 ( 1.7%)             2            80
-ImplItem                 176 ( 1.9%)             2            88
-GenericBound             192 ( 2.1%)             4            48
-TraitItem                192 ( 2.1%)             2            96
-WherePredicate           216 ( 2.3%)             3            72
-Block                    288 ( 3.1%)             6            48
-QPath                    408 ( 4.4%)            17            24
-Pat                      440 ( 4.8%)             5            88
-Expr                     672 ( 7.3%)            12            56
-Item                     960 (10.4%)            12            80
-Ty                     1_152 (12.4%)            16            72
-Path                   1_296 (14.0%)            27            48
-PathSegment            2_240 (24.2%)            40            56
-----------------------------------------------------------------
-Total                  9_256
-
+ast-stats-1 PRE EXPANSION AST STATS
+ast-stats-1 Name                Accumulated Size         Count     Item Size
+ast-stats-1 ----------------------------------------------------------------
+ast-stats-1 ExprField                 48 ( 0.6%)             1            48
+ast-stats-1 Crate                     56 ( 0.7%)             1            56
+ast-stats-1 Attribute                 64 ( 0.8%)             2            32
+ast-stats-1 - Normal                    32 ( 0.4%)             1
+ast-stats-1 - DocComment                32 ( 0.4%)             1
+ast-stats-1 GenericArgs               64 ( 0.8%)             1            64
+ast-stats-1 - AngleBracketed            64 ( 0.8%)             1
+ast-stats-1 Local                     72 ( 0.9%)             1            72
+ast-stats-1 WherePredicate            72 ( 0.9%)             1            72
+ast-stats-1 - BoundPredicate            72 ( 0.9%)             1
+ast-stats-1 Arm                       96 ( 1.1%)             2            48
+ast-stats-1 ForeignItem               96 ( 1.1%)             1            96
+ast-stats-1 - Fn                        96 ( 1.1%)             1
+ast-stats-1 FieldDef                 160 ( 1.9%)             2            80
+ast-stats-1 Stmt                     160 ( 1.9%)             5            32
+ast-stats-1 - Local                     32 ( 0.4%)             1
+ast-stats-1 - MacCall                   32 ( 0.4%)             1
+ast-stats-1 - Expr                      96 ( 1.1%)             3
+ast-stats-1 Param                    160 ( 1.9%)             4            40
+ast-stats-1 FnDecl                   200 ( 2.4%)             5            40
+ast-stats-1 Variant                  240 ( 2.8%)             2           120
+ast-stats-1 Block                    288 ( 3.4%)             6            48
+ast-stats-1 GenericBound             352 ( 4.2%)             4            88
+ast-stats-1 - Trait                    352 ( 4.2%)             4
+ast-stats-1 AssocItem                416 ( 4.9%)             4           104
+ast-stats-1 - TyAlias                  208 ( 2.5%)             2
+ast-stats-1 - Fn                       208 ( 2.5%)             2
+ast-stats-1 GenericParam             520 ( 6.1%)             5           104
+ast-stats-1 PathSegment              720 ( 8.5%)            30            24
+ast-stats-1 Expr                     832 ( 9.8%)             8           104
+ast-stats-1 - Path                     104 ( 1.2%)             1
+ast-stats-1 - Match                    104 ( 1.2%)             1
+ast-stats-1 - Struct                   104 ( 1.2%)             1
+ast-stats-1 - Lit                      208 ( 2.5%)             2
+ast-stats-1 - Block                    312 ( 3.7%)             3
+ast-stats-1 Pat                      840 ( 9.9%)             7           120
+ast-stats-1 - Struct                   120 ( 1.4%)             1
+ast-stats-1 - Wild                     120 ( 1.4%)             1
+ast-stats-1 - Ident                    600 ( 7.1%)             5
+ast-stats-1 Ty                     1_344 (15.9%)            14            96
+ast-stats-1 - Rptr                      96 ( 1.1%)             1
+ast-stats-1 - Ptr                       96 ( 1.1%)             1
+ast-stats-1 - ImplicitSelf             192 ( 2.3%)             2
+ast-stats-1 - Path                     960 (11.4%)            10
+ast-stats-1 Item                   1_656 (19.6%)             9           184
+ast-stats-1 - Trait                    184 ( 2.2%)             1
+ast-stats-1 - Enum                     184 ( 2.2%)             1
+ast-stats-1 - ForeignMod               184 ( 2.2%)             1
+ast-stats-1 - Impl                     184 ( 2.2%)             1
+ast-stats-1 - Fn                       368 ( 4.4%)             2
+ast-stats-1 - Use                      552 ( 6.5%)             3
+ast-stats-1 ----------------------------------------------------------------
+ast-stats-1 Total                  8_456
+ast-stats-1
+ast-stats-2 POST EXPANSION AST STATS
+ast-stats-2 Name                Accumulated Size         Count     Item Size
+ast-stats-2 ----------------------------------------------------------------
+ast-stats-2 ExprField                 48 ( 0.5%)             1            48
+ast-stats-2 Crate                     56 ( 0.6%)             1            56
+ast-stats-2 GenericArgs               64 ( 0.7%)             1            64
+ast-stats-2 - AngleBracketed            64 ( 0.7%)             1
+ast-stats-2 Local                     72 ( 0.8%)             1            72
+ast-stats-2 WherePredicate            72 ( 0.8%)             1            72
+ast-stats-2 - BoundPredicate            72 ( 0.8%)             1
+ast-stats-2 Arm                       96 ( 1.0%)             2            48
+ast-stats-2 ForeignItem               96 ( 1.0%)             1            96
+ast-stats-2 - Fn                        96 ( 1.0%)             1
+ast-stats-2 InlineAsm                120 ( 1.3%)             1           120
+ast-stats-2 Attribute                128 ( 1.4%)             4            32
+ast-stats-2 - DocComment                32 ( 0.3%)             1
+ast-stats-2 - Normal                    96 ( 1.0%)             3
+ast-stats-2 FieldDef                 160 ( 1.7%)             2            80
+ast-stats-2 Stmt                     160 ( 1.7%)             5            32
+ast-stats-2 - Local                     32 ( 0.3%)             1
+ast-stats-2 - Semi                      32 ( 0.3%)             1
+ast-stats-2 - Expr                      96 ( 1.0%)             3
+ast-stats-2 Param                    160 ( 1.7%)             4            40
+ast-stats-2 FnDecl                   200 ( 2.2%)             5            40
+ast-stats-2 Variant                  240 ( 2.6%)             2           120
+ast-stats-2 Block                    288 ( 3.1%)             6            48
+ast-stats-2 GenericBound             352 ( 3.8%)             4            88
+ast-stats-2 - Trait                    352 ( 3.8%)             4
+ast-stats-2 AssocItem                416 ( 4.5%)             4           104
+ast-stats-2 - TyAlias                  208 ( 2.3%)             2
+ast-stats-2 - Fn                       208 ( 2.3%)             2
+ast-stats-2 GenericParam             520 ( 5.7%)             5           104
+ast-stats-2 PathSegment              792 ( 8.6%)            33            24
+ast-stats-2 Pat                      840 ( 9.1%)             7           120
+ast-stats-2 - Struct                   120 ( 1.3%)             1
+ast-stats-2 - Wild                     120 ( 1.3%)             1
+ast-stats-2 - Ident                    600 ( 6.5%)             5
+ast-stats-2 Expr                     936 (10.2%)             9           104
+ast-stats-2 - Path                     104 ( 1.1%)             1
+ast-stats-2 - Match                    104 ( 1.1%)             1
+ast-stats-2 - Struct                   104 ( 1.1%)             1
+ast-stats-2 - InlineAsm                104 ( 1.1%)             1
+ast-stats-2 - Lit                      208 ( 2.3%)             2
+ast-stats-2 - Block                    312 ( 3.4%)             3
+ast-stats-2 Ty                     1_344 (14.6%)            14            96
+ast-stats-2 - Rptr                      96 ( 1.0%)             1
+ast-stats-2 - Ptr                       96 ( 1.0%)             1
+ast-stats-2 - ImplicitSelf             192 ( 2.1%)             2
+ast-stats-2 - Path                     960 (10.5%)            10
+ast-stats-2 Item                   2_024 (22.0%)            11           184
+ast-stats-2 - Trait                    184 ( 2.0%)             1
+ast-stats-2 - Enum                     184 ( 2.0%)             1
+ast-stats-2 - ExternCrate              184 ( 2.0%)             1
+ast-stats-2 - ForeignMod               184 ( 2.0%)             1
+ast-stats-2 - Impl                     184 ( 2.0%)             1
+ast-stats-2 - Fn                       368 ( 4.0%)             2
+ast-stats-2 - Use                      736 ( 8.0%)             4
+ast-stats-2 ----------------------------------------------------------------
+ast-stats-2 Total                  9_184
+ast-stats-2
+hir-stats HIR STATS
+hir-stats Name                Accumulated Size         Count     Item Size
+hir-stats ----------------------------------------------------------------
+hir-stats ForeignItemRef            24 ( 0.2%)             1            24
+hir-stats Mod                       32 ( 0.3%)             1            32
+hir-stats ExprField                 40 ( 0.4%)             1            40
+hir-stats TraitItemRef              56 ( 0.5%)             2            28
+hir-stats Param                     64 ( 0.6%)             2            32
+hir-stats Local                     64 ( 0.6%)             1            64
+hir-stats InlineAsm                 72 ( 0.7%)             1            72
+hir-stats ImplItemRef               72 ( 0.7%)             2            36
+hir-stats FieldDef                  96 ( 0.9%)             2            48
+hir-stats Arm                       96 ( 0.9%)             2            48
+hir-stats Body                      96 ( 0.9%)             3            32
+hir-stats Stmt                      96 ( 0.9%)             3            32
+hir-stats - Local                     32 ( 0.3%)             1
+hir-stats - Semi                      32 ( 0.3%)             1
+hir-stats - Expr                      32 ( 0.3%)             1
+hir-stats FnDecl                   120 ( 1.2%)             3            40
+hir-stats Attribute                128 ( 1.3%)             4            32
+hir-stats GenericArgs              144 ( 1.4%)             3            48
+hir-stats Variant                  160 ( 1.6%)             2            80
+hir-stats GenericArg               160 ( 1.6%)             4            40
+hir-stats - Type                      40 ( 0.4%)             1
+hir-stats - Lifetime                 120 ( 1.2%)             3
+hir-stats GenericBound             192 ( 1.9%)             4            48
+hir-stats - Trait                    192 ( 1.9%)             4
+hir-stats WherePredicate           216 ( 2.1%)             3            72
+hir-stats - BoundPredicate           216 ( 2.1%)             3
+hir-stats Block                    288 ( 2.8%)             6            48
+hir-stats GenericParam             400 ( 3.9%)             5            80
+hir-stats Pat                      440 ( 4.3%)             5            88
+hir-stats - Wild                      88 ( 0.9%)             1
+hir-stats - Struct                    88 ( 0.9%)             1
+hir-stats - Binding                  264 ( 2.6%)             3
+hir-stats Generics                 560 ( 5.5%)            10            56
+hir-stats Expr                     768 ( 7.5%)            12            64
+hir-stats - Path                      64 ( 0.6%)             1
+hir-stats - Struct                    64 ( 0.6%)             1
+hir-stats - Match                     64 ( 0.6%)             1
+hir-stats - InlineAsm                 64 ( 0.6%)             1
+hir-stats - Lit                      128 ( 1.3%)             2
+hir-stats - Block                    384 ( 3.8%)             6
+hir-stats Item                     960 ( 9.4%)            12            80
+hir-stats - Trait                     80 ( 0.8%)             1
+hir-stats - Enum                      80 ( 0.8%)             1
+hir-stats - ExternCrate               80 ( 0.8%)             1
+hir-stats - ForeignMod                80 ( 0.8%)             1
+hir-stats - Impl                      80 ( 0.8%)             1
+hir-stats - Fn                       160 ( 1.6%)             2
+hir-stats - Use                      400 ( 3.9%)             5
+hir-stats Ty                     1_080 (10.6%)            15            72
+hir-stats - Ptr                       72 ( 0.7%)             1
+hir-stats - Rptr                      72 ( 0.7%)             1
+hir-stats - Path                     936 ( 9.2%)            13
+hir-stats Path                   1_536 (15.1%)            32            48
+hir-stats PathSegment            2_240 (22.0%)            40            56
+hir-stats ----------------------------------------------------------------
+hir-stats Total                 10_200
+hir-stats
index 4c952669cfafda9f0aae592cf2350f1178f3af00..0a91c442d2c6f0e45dd21bc6d8212c9dc8b7265e 100644 (file)
@@ -19,7 +19,7 @@ LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
 help: remove the extra argument
    |
 LL |     let _: Option<(i32, bool)> = Some(/* (i32, bool) */);
-   |                                  ~~~~~~~~~~~~~~~~~~~~~~~
+   |                                      ~~~~~~~~~~~~~~~~~~~
 
 error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/args-instead-of-tuple-errors.rs:8:5
@@ -42,7 +42,7 @@ LL | fn int_bool(_: (i32, bool)) {
 help: remove the extra argument
    |
 LL |     int_bool(/* (i32, bool) */);
-   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |             ~~~~~~~~~~~~~~~~~~~
 
 error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied
   --> $DIR/args-instead-of-tuple-errors.rs:11:28
@@ -58,7 +58,7 @@ LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
 help: provide the argument
    |
 LL |     let _: Option<(i8,)> = Some(/* (i8,) */);
-   |                            ~~~~~~~~~~~~~~~~~
+   |                                ~~~~~~~~~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/args-instead-of-tuple-errors.rs:14:34
index 2448a5149654d318ef4067e2177a5e08815e4608..20f9e5259a4e2c050427970dec7b033a07d699ba 100644 (file)
@@ -44,7 +44,7 @@ LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
 help: provide the argument
    |
 LL |     let _: Option<()> = Some(());
-   |                         ~~~~~~~~
+   |                             ~~~~
 
 error[E0308]: mismatched types
   --> $DIR/args-instead-of-tuple.rs:14:34
index c7d420e0aae83efaa353285f4e8c38b6ec81800f..bfd506c9f6e0cc06370b9d3f3da2f35af10ea927 100644 (file)
@@ -9,7 +9,7 @@ LL |     bar(foo);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `Future` is not implemented for `fn() -> impl Future<Output = ()> {foo}`
+   = help: the trait `Future` is not implemented for fn item `fn() -> impl Future<Output = ()> {foo}`
    = note: fn() -> impl Future<Output = ()> {foo} must be a future or must implement `IntoFuture` to be awaited
 note: required by a bound in `bar`
   --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16
@@ -31,7 +31,7 @@ LL |     bar(async_closure);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `Future` is not implemented for `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33]`
+   = help: the trait `Future` is not implemented for closure `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33]`
    = note: [closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33] must be a future or must implement `IntoFuture` to be awaited
 note: required by a bound in `bar`
   --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16
diff --git a/src/test/ui/suggestions/copied-and-cloned.fixed b/src/test/ui/suggestions/copied-and-cloned.fixed
new file mode 100644 (file)
index 0000000..f801403
--- /dev/null
@@ -0,0 +1,23 @@
+// run-rustfix
+
+fn expect<T>(_: T) {}
+
+fn main() {
+    let x = Some(&());
+    expect::<Option<()>>(x.copied());
+    //~^ ERROR mismatched types
+    //~| HELP use `Option::copied` to copy the value inside the `Option`
+    let x = Ok(&());
+    expect::<Result<(), ()>>(x.copied());
+    //~^ ERROR mismatched types
+    //~| HELP use `Result::copied` to copy the value inside the `Result`
+    let s = String::new();
+    let x = Some(&s);
+    expect::<Option<String>>(x.cloned());
+    //~^ ERROR mismatched types
+    //~| HELP use `Option::cloned` to clone the value inside the `Option`
+    let x = Ok(&s);
+    expect::<Result<String, ()>>(x.cloned());
+    //~^ ERROR mismatched types
+    //~| HELP use `Result::cloned` to clone the value inside the `Result`
+}
diff --git a/src/test/ui/suggestions/copied-and-cloned.rs b/src/test/ui/suggestions/copied-and-cloned.rs
new file mode 100644 (file)
index 0000000..640450b
--- /dev/null
@@ -0,0 +1,23 @@
+// run-rustfix
+
+fn expect<T>(_: T) {}
+
+fn main() {
+    let x = Some(&());
+    expect::<Option<()>>(x);
+    //~^ ERROR mismatched types
+    //~| HELP use `Option::copied` to copy the value inside the `Option`
+    let x = Ok(&());
+    expect::<Result<(), ()>>(x);
+    //~^ ERROR mismatched types
+    //~| HELP use `Result::copied` to copy the value inside the `Result`
+    let s = String::new();
+    let x = Some(&s);
+    expect::<Option<String>>(x);
+    //~^ ERROR mismatched types
+    //~| HELP use `Option::cloned` to clone the value inside the `Option`
+    let x = Ok(&s);
+    expect::<Result<String, ()>>(x);
+    //~^ ERROR mismatched types
+    //~| HELP use `Result::cloned` to clone the value inside the `Result`
+}
diff --git a/src/test/ui/suggestions/copied-and-cloned.stderr b/src/test/ui/suggestions/copied-and-cloned.stderr
new file mode 100644 (file)
index 0000000..a633628
--- /dev/null
@@ -0,0 +1,83 @@
+error[E0308]: mismatched types
+  --> $DIR/copied-and-cloned.rs:7:26
+   |
+LL |     expect::<Option<()>>(x);
+   |     -------------------- ^ expected `()`, found `&()`
+   |     |
+   |     arguments to this function are incorrect
+   |
+   = note: expected enum `Option<()>`
+              found enum `Option<&()>`
+note: function defined here
+  --> $DIR/copied-and-cloned.rs:3:4
+   |
+LL | fn expect<T>(_: T) {}
+   |    ^^^^^^    ----
+help: use `Option::copied` to copy the value inside the `Option`
+   |
+LL |     expect::<Option<()>>(x.copied());
+   |                           +++++++++
+
+error[E0308]: mismatched types
+  --> $DIR/copied-and-cloned.rs:11:30
+   |
+LL |     expect::<Result<(), ()>>(x);
+   |     ------------------------ ^ expected `()`, found `&()`
+   |     |
+   |     arguments to this function are incorrect
+   |
+   = note: expected enum `Result<(), ()>`
+              found enum `Result<&(), _>`
+note: function defined here
+  --> $DIR/copied-and-cloned.rs:3:4
+   |
+LL | fn expect<T>(_: T) {}
+   |    ^^^^^^    ----
+help: use `Result::copied` to copy the value inside the `Result`
+   |
+LL |     expect::<Result<(), ()>>(x.copied());
+   |                               +++++++++
+
+error[E0308]: mismatched types
+  --> $DIR/copied-and-cloned.rs:16:30
+   |
+LL |     expect::<Option<String>>(x);
+   |     ------------------------ ^ expected struct `String`, found `&String`
+   |     |
+   |     arguments to this function are incorrect
+   |
+   = note: expected enum `Option<String>`
+              found enum `Option<&String>`
+note: function defined here
+  --> $DIR/copied-and-cloned.rs:3:4
+   |
+LL | fn expect<T>(_: T) {}
+   |    ^^^^^^    ----
+help: use `Option::cloned` to clone the value inside the `Option`
+   |
+LL |     expect::<Option<String>>(x.cloned());
+   |                               +++++++++
+
+error[E0308]: mismatched types
+  --> $DIR/copied-and-cloned.rs:20:34
+   |
+LL |     expect::<Result<String, ()>>(x);
+   |     ---------------------------- ^ expected struct `String`, found `&String`
+   |     |
+   |     arguments to this function are incorrect
+   |
+   = note: expected enum `Result<String, ()>`
+              found enum `Result<&String, _>`
+note: function defined here
+  --> $DIR/copied-and-cloned.rs:3:4
+   |
+LL | fn expect<T>(_: T) {}
+   |    ^^^^^^    ----
+help: use `Result::cloned` to clone the value inside the `Result`
+   |
+LL |     expect::<Result<String, ()>>(x.cloned());
+   |                                   +++++++++
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/deref-path-method.rs b/src/test/ui/suggestions/deref-path-method.rs
new file mode 100644 (file)
index 0000000..0281cdb
--- /dev/null
@@ -0,0 +1,6 @@
+fn main() {
+    let vec = Vec::new();
+    Vec::contains(&vec, &0);
+    //~^ ERROR no function or associated item named `contains` found for struct `Vec<_, _>` in the current scope
+    //~| HELP the function `contains` is implemented on `[_]`
+}
diff --git a/src/test/ui/suggestions/deref-path-method.stderr b/src/test/ui/suggestions/deref-path-method.stderr
new file mode 100644 (file)
index 0000000..1cc37d6
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0599]: no function or associated item named `contains` found for struct `Vec<_, _>` in the current scope
+  --> $DIR/deref-path-method.rs:3:10
+   |
+LL |     Vec::contains(&vec, &0);
+   |          ^^^^^^^^ function or associated item not found in `Vec<_, _>`
+   |
+help: the function `contains` is implemented on `[_]`
+   |
+LL |     <[_]>::contains(&vec, &0);
+   |     ~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
index fb0a6f70bfb46e051f9681541c81c257073af4fd..fe603b67575d33c7f6242b45e294bf7e22d1d936 100644 (file)
@@ -5,7 +5,7 @@ LL | fn foo() -> impl T<O=()> { S }
    |    --- consider calling this function
 ...
 LL |     bar(foo);
-   |     --- ^^^ the trait `T` is not implemented for `fn() -> impl T<O = ()> {foo}`
+   |     --- ^^^ the trait `T` is not implemented for fn item `fn() -> impl T<O = ()> {foo}`
    |     |
    |     required by a bound introduced by this call
    |
@@ -25,7 +25,7 @@ error[E0277]: the trait bound `[closure@$DIR/fn-ctor-passed-as-arg-where-it-shou
 LL |     let closure = || S;
    |                   -- consider calling this closure
 LL |     bar(closure);
-   |     --- ^^^^^^^ the trait `T` is not implemented for `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:21]`
+   |     --- ^^^^^^^ the trait `T` is not implemented for closure `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:21]`
    |     |
    |     required by a bound introduced by this call
    |
index 2abbbf3c158d6067aa29f0c337a40e687485635b..0225c4230dc4de91cd58e13cc200174f5046133a 100644 (file)
@@ -3,6 +3,7 @@
 //! provided indirectly through an abstraction.
 
 #![crate_type = "lib"]
+#![feature(adt_const_params)]
 #![feature(transmutability)]
 #![allow(dead_code, incomplete_features, non_camel_case_types)]
 
@@ -13,19 +14,13 @@ pub fn is_transmutable<
         Src,
         Dst,
         Context,
-        const ASSUME_ALIGNMENT: bool,
-        const ASSUME_LIFETIMES: bool,
-        const ASSUME_VALIDITY: bool,
-        const ASSUME_VISIBILITY: bool,
+        const ASSUME: std::mem::Assume,
     >()
     where
         Dst: BikeshedIntrinsicFrom<
             Src,
             Context,
-            ASSUME_ALIGNMENT,
-            ASSUME_LIFETIMES,
-            ASSUME_VALIDITY,
-            ASSUME_VISIBILITY,
+            ASSUME,
         >,
     {}
 }
@@ -35,7 +30,7 @@ fn direct() {
     #[repr(C)] struct Src;
     #[repr(C)] struct Dst;
 
-    assert::is_transmutable::<Src, Dst, Context, false, false, false, false>();
+    assert::is_transmutable::<Src, Dst, Context, { std::mem::Assume::NOTHING }>();
 }
 
 fn via_const() {
@@ -45,7 +40,7 @@ fn via_const() {
 
     const FALSE: bool = false;
 
-    assert::is_transmutable::<Src, Dst, Context, FALSE, FALSE, FALSE, FALSE>();
+    assert::is_transmutable::<Src, Dst, Context, { std::mem::Assume::NOTHING }>();
 }
 
 fn via_associated_const() {
@@ -65,9 +60,13 @@ impl Trait for Ty {}
         Src,
         Dst,
         Context,
-        {Ty::FALSE},
-        {Ty::FALSE},
-        {Ty::FALSE},
-        {Ty::FALSE}
+        {
+            std::mem::Assume {
+                alignment: {Ty::FALSE},
+                lifetimes: {Ty::FALSE},
+                safety: {Ty::FALSE},
+                validity: {Ty::FALSE},
+            }
+        }
     >();
 }
index 94c38bb28f7e20cadce116eda3014ddf33d0f66e..e693a09570f3adb7be5be9243234b992cf9a4715 100644 (file)
@@ -6,13 +6,13 @@
 #![allow(dead_code, incomplete_features, non_camel_case_types)]
 
 mod assert {
-    use std::mem::BikeshedIntrinsicFrom;
+    use std::mem::{Assume, BikeshedIntrinsicFrom};
     pub struct Context;
 
     pub fn array_like<T, E, const N: usize>()
     where
-        T: BikeshedIntrinsicFrom<[E; N], Context, false, false, false, true>,
-        [E; N]: BikeshedIntrinsicFrom<T, Context, false, false, false, true>
+        T: BikeshedIntrinsicFrom<[E; N], Context, { Assume::SAFETY }>,
+        [E; N]: BikeshedIntrinsicFrom<T, Context, { Assume::SAFETY }>
     {}
 }
 
index bfe6d830a1be77864dca587ccb86213fdc7ad7c3..353797d0c4bb0062124410e180f727b09fd92b0c 100644 (file)
@@ -6,12 +6,12 @@
 #![allow(dead_code, incomplete_features, non_camel_case_types)]
 
 mod assert {
-    use std::mem::BikeshedIntrinsicFrom;
+    use std::mem::{Assume, BikeshedIntrinsicFrom};
     pub struct Context;
 
     pub fn is_maybe_transmutable<Src, Dst>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+        Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY.and(Assume::VALIDITY) }>
     {}
 }
 
index fcb1765ea6bb46206c2b35d650748027d1275243..b00e5c7e4008caae923f013ff808af552fc56ec0 100644 (file)
@@ -6,12 +6,17 @@
 #![allow(dead_code, incomplete_features, non_camel_case_types)]
 
 mod assert {
-    use std::mem::BikeshedIntrinsicFrom;
+    use std::mem::{Assume, BikeshedIntrinsicFrom};
     pub struct Context;
 
     pub fn is_maybe_transmutable<Src, Dst>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+        Dst: BikeshedIntrinsicFrom<Src, Context, {
+            Assume::ALIGNMENT
+                .and(Assume::LIFETIMES)
+                .and(Assume::SAFETY)
+                .and(Assume::VALIDITY)
+        }>
     {}
 }
 
index 8e69527c1862c2e4a4130d5608914579a0cabc8a..853bd9cbc0fb3c4cd8c0b65322a8660ec135fafe 100644 (file)
@@ -5,12 +5,17 @@
 #![allow(dead_code, incomplete_features, non_camel_case_types)]
 
 mod assert {
-    use std::mem::BikeshedIntrinsicFrom;
+    use std::mem::{Assume, BikeshedIntrinsicFrom};
     pub struct Context;
 
     pub fn is_maybe_transmutable<Src, Dst>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+        Dst: BikeshedIntrinsicFrom<Src, Context, {
+            Assume::ALIGNMENT
+                .and(Assume::LIFETIMES)
+                .and(Assume::SAFETY)
+                .and(Assume::VALIDITY)
+        }>
     {}
 }
 
index eae0c947d4253fc339ee2350ee96b87799f08e27..96a2fdc54dbb42e86a62ffbfa4fced74fcb1df83 100644 (file)
 error[E0277]: `[String; 0]` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
-  --> $DIR/should_require_well_defined_layout.rs:21:52
+  --> $DIR/should_require_well_defined_layout.rs:26:52
    |
 LL |         assert::is_maybe_transmutable::<repr_rust, ()>();
    |                                                    ^^ `[String; 0]` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<[String; 0], assert::Context, true, true, true, true>` is not implemented for `()`
+   = help: the trait `BikeshedIntrinsicFrom<[String; 0], assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()`
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/should_require_well_defined_layout.rs:13:14
    |
-LL |     pub fn is_maybe_transmutable<Src, Dst>()
-   |            --------------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL |       pub fn is_maybe_transmutable<Src, Dst>()
+   |              --------------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume::ALIGNMENT
+LL | |                 .and(Assume::LIFETIMES)
+LL | |                 .and(Assume::SAFETY)
+LL | |                 .and(Assume::VALIDITY)
+LL | |         }>
+   | |__________^ required by this bound in `is_maybe_transmutable`
 
 error[E0277]: `u128` cannot be safely transmuted into `[String; 0]` in the defining scope of `assert::Context`.
-  --> $DIR/should_require_well_defined_layout.rs:22:47
+  --> $DIR/should_require_well_defined_layout.rs:27:47
    |
 LL |         assert::is_maybe_transmutable::<u128, repr_rust>();
    |                                               ^^^^^^^^^ `u128` cannot be safely transmuted into `[String; 0]` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, true, true, true, true>` is not implemented for `[String; 0]`
+   = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `[String; 0]`
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/should_require_well_defined_layout.rs:13:14
    |
-LL |     pub fn is_maybe_transmutable<Src, Dst>()
-   |            --------------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL |       pub fn is_maybe_transmutable<Src, Dst>()
+   |              --------------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume::ALIGNMENT
+LL | |                 .and(Assume::LIFETIMES)
+LL | |                 .and(Assume::SAFETY)
+LL | |                 .and(Assume::VALIDITY)
+LL | |         }>
+   | |__________^ required by this bound in `is_maybe_transmutable`
 
 error[E0277]: `[String; 1]` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
-  --> $DIR/should_require_well_defined_layout.rs:27:52
+  --> $DIR/should_require_well_defined_layout.rs:32:52
    |
 LL |         assert::is_maybe_transmutable::<repr_rust, ()>();
    |                                                    ^^ `[String; 1]` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<[String; 1], assert::Context, true, true, true, true>` is not implemented for `()`
+   = help: the trait `BikeshedIntrinsicFrom<[String; 1], assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()`
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/should_require_well_defined_layout.rs:13:14
    |
-LL |     pub fn is_maybe_transmutable<Src, Dst>()
-   |            --------------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL |       pub fn is_maybe_transmutable<Src, Dst>()
+   |              --------------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume::ALIGNMENT
+LL | |                 .and(Assume::LIFETIMES)
+LL | |                 .and(Assume::SAFETY)
+LL | |                 .and(Assume::VALIDITY)
+LL | |         }>
+   | |__________^ required by this bound in `is_maybe_transmutable`
 
 error[E0277]: `u128` cannot be safely transmuted into `[String; 1]` in the defining scope of `assert::Context`.
-  --> $DIR/should_require_well_defined_layout.rs:28:47
+  --> $DIR/should_require_well_defined_layout.rs:33:47
    |
 LL |         assert::is_maybe_transmutable::<u128, repr_rust>();
    |                                               ^^^^^^^^^ `u128` cannot be safely transmuted into `[String; 1]` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, true, true, true, true>` is not implemented for `[String; 1]`
+   = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `[String; 1]`
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/should_require_well_defined_layout.rs:13:14
    |
-LL |     pub fn is_maybe_transmutable<Src, Dst>()
-   |            --------------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL |       pub fn is_maybe_transmutable<Src, Dst>()
+   |              --------------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume::ALIGNMENT
+LL | |                 .and(Assume::LIFETIMES)
+LL | |                 .and(Assume::SAFETY)
+LL | |                 .and(Assume::VALIDITY)
+LL | |         }>
+   | |__________^ required by this bound in `is_maybe_transmutable`
 
 error[E0277]: `[String; 2]` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
-  --> $DIR/should_require_well_defined_layout.rs:33:52
+  --> $DIR/should_require_well_defined_layout.rs:38:52
    |
 LL |         assert::is_maybe_transmutable::<repr_rust, ()>();
    |                                                    ^^ `[String; 2]` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<[String; 2], assert::Context, true, true, true, true>` is not implemented for `()`
+   = help: the trait `BikeshedIntrinsicFrom<[String; 2], assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()`
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/should_require_well_defined_layout.rs:13:14
    |
-LL |     pub fn is_maybe_transmutable<Src, Dst>()
-   |            --------------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL |       pub fn is_maybe_transmutable<Src, Dst>()
+   |              --------------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume::ALIGNMENT
+LL | |                 .and(Assume::LIFETIMES)
+LL | |                 .and(Assume::SAFETY)
+LL | |                 .and(Assume::VALIDITY)
+LL | |         }>
+   | |__________^ required by this bound in `is_maybe_transmutable`
 
 error[E0277]: `u128` cannot be safely transmuted into `[String; 2]` in the defining scope of `assert::Context`.
-  --> $DIR/should_require_well_defined_layout.rs:34:47
+  --> $DIR/should_require_well_defined_layout.rs:39:47
    |
 LL |         assert::is_maybe_transmutable::<u128, repr_rust>();
    |                                               ^^^^^^^^^ `u128` cannot be safely transmuted into `[String; 2]` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, true, true, true, true>` is not implemented for `[String; 2]`
+   = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `[String; 2]`
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/should_require_well_defined_layout.rs:13:14
    |
-LL |     pub fn is_maybe_transmutable<Src, Dst>()
-   |            --------------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL |       pub fn is_maybe_transmutable<Src, Dst>()
+   |              --------------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume::ALIGNMENT
+LL | |                 .and(Assume::LIFETIMES)
+LL | |                 .and(Assume::SAFETY)
+LL | |                 .and(Assume::VALIDITY)
+LL | |         }>
+   | |__________^ required by this bound in `is_maybe_transmutable`
 
 error: aborting due to 6 previous errors
 
index 18e02b0d2b90851566ae395cca6a4e4cea5c1b84..940f070e7e3605b840a9285d6f261df864982cbb 100644 (file)
@@ -5,11 +5,18 @@
 #![allow(dead_code)]
 
 mod assert {
-    use std::mem::BikeshedIntrinsicFrom;
+    use std::mem::{Assume, BikeshedIntrinsicFrom};
 
     pub fn is_transmutable<Src, Dst, Context>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+        Dst: BikeshedIntrinsicFrom<Src, Context, {
+            Assume {
+                alignment: true,
+                lifetimes: true,
+                safety: true,
+                validity: true,
+            }
+        }>
     {}
 }
 
index fa2e3b89b079a1f4cab04fa42b6ec38700b7d6b8..4da5fcea3374c1c4cbeab386c65c944384a7b963 100644 (file)
 error[E0277]: `Zst` cannot be safely transmuted into `V0i8` in the defining scope of `n8::Context`.
-  --> $DIR/primitive_reprs_should_have_correct_length.rs:41:44
+  --> $DIR/primitive_reprs_should_have_correct_length.rs:48:44
    |
 LL |         assert::is_transmutable::<Smaller, Current, Context>();
    |                                            ^^^^^^^ `Zst` cannot be safely transmuted into `V0i8` in the defining scope of `n8::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<Zst, n8::Context, true, true, true, true>` is not implemented for `V0i8`
+   = help: the trait `BikeshedIntrinsicFrom<Zst, n8::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `V0i8`
 note: required by a bound in `is_transmutable`
   --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
    |
-LL |     pub fn is_transmutable<Src, Dst, Context>()
-   |            --------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |       pub fn is_transmutable<Src, Dst, Context>()
+   |              --------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_transmutable`
 
 error[E0277]: `V0i8` cannot be safely transmuted into `u16` in the defining scope of `n8::Context`.
-  --> $DIR/primitive_reprs_should_have_correct_length.rs:43:44
+  --> $DIR/primitive_reprs_should_have_correct_length.rs:50:44
    |
 LL |         assert::is_transmutable::<Current, Larger, Context>();
    |                                            ^^^^^^ `V0i8` cannot be safely transmuted into `u16` in the defining scope of `n8::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<V0i8, n8::Context, true, true, true, true>` is not implemented for `u16`
+   = help: the trait `BikeshedIntrinsicFrom<V0i8, n8::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `u16`
 note: required by a bound in `is_transmutable`
   --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
    |
-LL |     pub fn is_transmutable<Src, Dst, Context>()
-   |            --------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |       pub fn is_transmutable<Src, Dst, Context>()
+   |              --------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_transmutable`
 
 error[E0277]: `Zst` cannot be safely transmuted into `V0u8` in the defining scope of `n8::Context`.
-  --> $DIR/primitive_reprs_should_have_correct_length.rs:49:44
+  --> $DIR/primitive_reprs_should_have_correct_length.rs:56:44
    |
 LL |         assert::is_transmutable::<Smaller, Current, Context>();
    |                                            ^^^^^^^ `Zst` cannot be safely transmuted into `V0u8` in the defining scope of `n8::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<Zst, n8::Context, true, true, true, true>` is not implemented for `V0u8`
+   = help: the trait `BikeshedIntrinsicFrom<Zst, n8::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `V0u8`
 note: required by a bound in `is_transmutable`
   --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
    |
-LL |     pub fn is_transmutable<Src, Dst, Context>()
-   |            --------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |       pub fn is_transmutable<Src, Dst, Context>()
+   |              --------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_transmutable`
 
 error[E0277]: `V0u8` cannot be safely transmuted into `u16` in the defining scope of `n8::Context`.
-  --> $DIR/primitive_reprs_should_have_correct_length.rs:51:44
+  --> $DIR/primitive_reprs_should_have_correct_length.rs:58:44
    |
 LL |         assert::is_transmutable::<Current, Larger, Context>();
    |                                            ^^^^^^ `V0u8` cannot be safely transmuted into `u16` in the defining scope of `n8::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<V0u8, n8::Context, true, true, true, true>` is not implemented for `u16`
+   = help: the trait `BikeshedIntrinsicFrom<V0u8, n8::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `u16`
 note: required by a bound in `is_transmutable`
   --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
    |
-LL |     pub fn is_transmutable<Src, Dst, Context>()
-   |            --------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |       pub fn is_transmutable<Src, Dst, Context>()
+   |              --------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `V0i16` in the defining scope of `n16::Context`.
-  --> $DIR/primitive_reprs_should_have_correct_length.rs:65:44
+  --> $DIR/primitive_reprs_should_have_correct_length.rs:72:44
    |
 LL |         assert::is_transmutable::<Smaller, Current, Context>();
    |                                            ^^^^^^^ `u8` cannot be safely transmuted into `V0i16` in the defining scope of `n16::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u8, n16::Context, true, true, true, true>` is not implemented for `V0i16`
+   = help: the trait `BikeshedIntrinsicFrom<u8, n16::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `V0i16`
 note: required by a bound in `is_transmutable`
   --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
    |
-LL |     pub fn is_transmutable<Src, Dst, Context>()
-   |            --------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |       pub fn is_transmutable<Src, Dst, Context>()
+   |              --------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_transmutable`
 
 error[E0277]: `V0i16` cannot be safely transmuted into `u32` in the defining scope of `n16::Context`.
-  --> $DIR/primitive_reprs_should_have_correct_length.rs:67:44
+  --> $DIR/primitive_reprs_should_have_correct_length.rs:74:44
    |
 LL |         assert::is_transmutable::<Current, Larger, Context>();
    |                                            ^^^^^^ `V0i16` cannot be safely transmuted into `u32` in the defining scope of `n16::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<V0i16, n16::Context, true, true, true, true>` is not implemented for `u32`
+   = help: the trait `BikeshedIntrinsicFrom<V0i16, n16::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `u32`
 note: required by a bound in `is_transmutable`
   --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
    |
-LL |     pub fn is_transmutable<Src, Dst, Context>()
-   |            --------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |       pub fn is_transmutable<Src, Dst, Context>()
+   |              --------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `V0u16` in the defining scope of `n16::Context`.
-  --> $DIR/primitive_reprs_should_have_correct_length.rs:73:44
+  --> $DIR/primitive_reprs_should_have_correct_length.rs:80:44
    |
 LL |         assert::is_transmutable::<Smaller, Current, Context>();
    |                                            ^^^^^^^ `u8` cannot be safely transmuted into `V0u16` in the defining scope of `n16::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u8, n16::Context, true, true, true, true>` is not implemented for `V0u16`
+   = help: the trait `BikeshedIntrinsicFrom<u8, n16::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `V0u16`
 note: required by a bound in `is_transmutable`
   --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
    |
-LL |     pub fn is_transmutable<Src, Dst, Context>()
-   |            --------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |       pub fn is_transmutable<Src, Dst, Context>()
+   |              --------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_transmutable`
 
 error[E0277]: `V0u16` cannot be safely transmuted into `u32` in the defining scope of `n16::Context`.
-  --> $DIR/primitive_reprs_should_have_correct_length.rs:75:44
+  --> $DIR/primitive_reprs_should_have_correct_length.rs:82:44
    |
 LL |         assert::is_transmutable::<Current, Larger, Context>();
    |                                            ^^^^^^ `V0u16` cannot be safely transmuted into `u32` in the defining scope of `n16::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<V0u16, n16::Context, true, true, true, true>` is not implemented for `u32`
+   = help: the trait `BikeshedIntrinsicFrom<V0u16, n16::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `u32`
 note: required by a bound in `is_transmutable`
   --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
    |
-LL |     pub fn is_transmutable<Src, Dst, Context>()
-   |            --------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |       pub fn is_transmutable<Src, Dst, Context>()
+   |              --------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_transmutable`
 
 error[E0277]: `u16` cannot be safely transmuted into `V0i32` in the defining scope of `n32::Context`.
-  --> $DIR/primitive_reprs_should_have_correct_length.rs:89:44
+  --> $DIR/primitive_reprs_should_have_correct_length.rs:96:44
    |
 LL |         assert::is_transmutable::<Smaller, Current, Context>();
    |                                            ^^^^^^^ `u16` cannot be safely transmuted into `V0i32` in the defining scope of `n32::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u16, n32::Context, true, true, true, true>` is not implemented for `V0i32`
+   = help: the trait `BikeshedIntrinsicFrom<u16, n32::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `V0i32`
 note: required by a bound in `is_transmutable`
   --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
    |
-LL |     pub fn is_transmutable<Src, Dst, Context>()
-   |            --------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |       pub fn is_transmutable<Src, Dst, Context>()
+   |              --------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_transmutable`
 
 error[E0277]: `V0i32` cannot be safely transmuted into `u64` in the defining scope of `n32::Context`.
-  --> $DIR/primitive_reprs_should_have_correct_length.rs:91:44
+  --> $DIR/primitive_reprs_should_have_correct_length.rs:98:44
    |
 LL |         assert::is_transmutable::<Current, Larger, Context>();
    |                                            ^^^^^^ `V0i32` cannot be safely transmuted into `u64` in the defining scope of `n32::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<V0i32, n32::Context, true, true, true, true>` is not implemented for `u64`
+   = help: the trait `BikeshedIntrinsicFrom<V0i32, n32::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `u64`
 note: required by a bound in `is_transmutable`
   --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
    |
-LL |     pub fn is_transmutable<Src, Dst, Context>()
-   |            --------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |       pub fn is_transmutable<Src, Dst, Context>()
+   |              --------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_transmutable`
 
 error[E0277]: `u16` cannot be safely transmuted into `V0u32` in the defining scope of `n32::Context`.
-  --> $DIR/primitive_reprs_should_have_correct_length.rs:97:44
+  --> $DIR/primitive_reprs_should_have_correct_length.rs:104:44
    |
 LL |         assert::is_transmutable::<Smaller, Current, Context>();
    |                                            ^^^^^^^ `u16` cannot be safely transmuted into `V0u32` in the defining scope of `n32::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u16, n32::Context, true, true, true, true>` is not implemented for `V0u32`
+   = help: the trait `BikeshedIntrinsicFrom<u16, n32::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `V0u32`
 note: required by a bound in `is_transmutable`
   --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
    |
-LL |     pub fn is_transmutable<Src, Dst, Context>()
-   |            --------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |       pub fn is_transmutable<Src, Dst, Context>()
+   |              --------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_transmutable`
 
 error[E0277]: `V0u32` cannot be safely transmuted into `u64` in the defining scope of `n32::Context`.
-  --> $DIR/primitive_reprs_should_have_correct_length.rs:99:44
+  --> $DIR/primitive_reprs_should_have_correct_length.rs:106:44
    |
 LL |         assert::is_transmutable::<Current, Larger, Context>();
    |                                            ^^^^^^ `V0u32` cannot be safely transmuted into `u64` in the defining scope of `n32::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<V0u32, n32::Context, true, true, true, true>` is not implemented for `u64`
+   = help: the trait `BikeshedIntrinsicFrom<V0u32, n32::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `u64`
 note: required by a bound in `is_transmutable`
   --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
    |
-LL |     pub fn is_transmutable<Src, Dst, Context>()
-   |            --------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |       pub fn is_transmutable<Src, Dst, Context>()
+   |              --------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_transmutable`
 
 error[E0277]: `u32` cannot be safely transmuted into `V0i64` in the defining scope of `n64::Context`.
-  --> $DIR/primitive_reprs_should_have_correct_length.rs:113:44
+  --> $DIR/primitive_reprs_should_have_correct_length.rs:120:44
    |
 LL |         assert::is_transmutable::<Smaller, Current, Context>();
    |                                            ^^^^^^^ `u32` cannot be safely transmuted into `V0i64` in the defining scope of `n64::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u32, n64::Context, true, true, true, true>` is not implemented for `V0i64`
+   = help: the trait `BikeshedIntrinsicFrom<u32, n64::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `V0i64`
 note: required by a bound in `is_transmutable`
   --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
    |
-LL |     pub fn is_transmutable<Src, Dst, Context>()
-   |            --------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |       pub fn is_transmutable<Src, Dst, Context>()
+   |              --------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_transmutable`
 
 error[E0277]: `V0i64` cannot be safely transmuted into `u128` in the defining scope of `n64::Context`.
-  --> $DIR/primitive_reprs_should_have_correct_length.rs:115:44
+  --> $DIR/primitive_reprs_should_have_correct_length.rs:122:44
    |
 LL |         assert::is_transmutable::<Current, Larger, Context>();
    |                                            ^^^^^^ `V0i64` cannot be safely transmuted into `u128` in the defining scope of `n64::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<V0i64, n64::Context, true, true, true, true>` is not implemented for `u128`
+   = help: the trait `BikeshedIntrinsicFrom<V0i64, n64::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `u128`
 note: required by a bound in `is_transmutable`
   --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
    |
-LL |     pub fn is_transmutable<Src, Dst, Context>()
-   |            --------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |       pub fn is_transmutable<Src, Dst, Context>()
+   |              --------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_transmutable`
 
 error[E0277]: `u32` cannot be safely transmuted into `V0u64` in the defining scope of `n64::Context`.
-  --> $DIR/primitive_reprs_should_have_correct_length.rs:121:44
+  --> $DIR/primitive_reprs_should_have_correct_length.rs:128:44
    |
 LL |         assert::is_transmutable::<Smaller, Current, Context>();
    |                                            ^^^^^^^ `u32` cannot be safely transmuted into `V0u64` in the defining scope of `n64::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u32, n64::Context, true, true, true, true>` is not implemented for `V0u64`
+   = help: the trait `BikeshedIntrinsicFrom<u32, n64::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `V0u64`
 note: required by a bound in `is_transmutable`
   --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
    |
-LL |     pub fn is_transmutable<Src, Dst, Context>()
-   |            --------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |       pub fn is_transmutable<Src, Dst, Context>()
+   |              --------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_transmutable`
 
 error[E0277]: `V0u64` cannot be safely transmuted into `u128` in the defining scope of `n64::Context`.
-  --> $DIR/primitive_reprs_should_have_correct_length.rs:123:44
+  --> $DIR/primitive_reprs_should_have_correct_length.rs:130:44
    |
 LL |         assert::is_transmutable::<Current, Larger, Context>();
    |                                            ^^^^^^ `V0u64` cannot be safely transmuted into `u128` in the defining scope of `n64::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<V0u64, n64::Context, true, true, true, true>` is not implemented for `u128`
+   = help: the trait `BikeshedIntrinsicFrom<V0u64, n64::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `u128`
 note: required by a bound in `is_transmutable`
   --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
    |
-LL |     pub fn is_transmutable<Src, Dst, Context>()
-   |            --------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |       pub fn is_transmutable<Src, Dst, Context>()
+   |              --------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `V0isize` in the defining scope of `nsize::Context`.
-  --> $DIR/primitive_reprs_should_have_correct_length.rs:137:44
+  --> $DIR/primitive_reprs_should_have_correct_length.rs:144:44
    |
 LL |         assert::is_transmutable::<Smaller, Current, Context>();
    |                                            ^^^^^^^ `u8` cannot be safely transmuted into `V0isize` in the defining scope of `nsize::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u8, nsize::Context, true, true, true, true>` is not implemented for `V0isize`
+   = help: the trait `BikeshedIntrinsicFrom<u8, nsize::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `V0isize`
 note: required by a bound in `is_transmutable`
   --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
    |
-LL |     pub fn is_transmutable<Src, Dst, Context>()
-   |            --------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |       pub fn is_transmutable<Src, Dst, Context>()
+   |              --------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_transmutable`
 
 error[E0277]: `V0isize` cannot be safely transmuted into `[usize; 2]` in the defining scope of `nsize::Context`.
-  --> $DIR/primitive_reprs_should_have_correct_length.rs:139:44
+  --> $DIR/primitive_reprs_should_have_correct_length.rs:146:44
    |
 LL |         assert::is_transmutable::<Current, Larger, Context>();
    |                                            ^^^^^^ `V0isize` cannot be safely transmuted into `[usize; 2]` in the defining scope of `nsize::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<V0isize, nsize::Context, true, true, true, true>` is not implemented for `[usize; 2]`
+   = help: the trait `BikeshedIntrinsicFrom<V0isize, nsize::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `[usize; 2]`
 note: required by a bound in `is_transmutable`
   --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
    |
-LL |     pub fn is_transmutable<Src, Dst, Context>()
-   |            --------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |       pub fn is_transmutable<Src, Dst, Context>()
+   |              --------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `V0usize` in the defining scope of `nsize::Context`.
-  --> $DIR/primitive_reprs_should_have_correct_length.rs:145:44
+  --> $DIR/primitive_reprs_should_have_correct_length.rs:152:44
    |
 LL |         assert::is_transmutable::<Smaller, Current, Context>();
    |                                            ^^^^^^^ `u8` cannot be safely transmuted into `V0usize` in the defining scope of `nsize::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u8, nsize::Context, true, true, true, true>` is not implemented for `V0usize`
+   = help: the trait `BikeshedIntrinsicFrom<u8, nsize::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `V0usize`
 note: required by a bound in `is_transmutable`
   --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
    |
-LL |     pub fn is_transmutable<Src, Dst, Context>()
-   |            --------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |       pub fn is_transmutable<Src, Dst, Context>()
+   |              --------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_transmutable`
 
 error[E0277]: `V0usize` cannot be safely transmuted into `[usize; 2]` in the defining scope of `nsize::Context`.
-  --> $DIR/primitive_reprs_should_have_correct_length.rs:147:44
+  --> $DIR/primitive_reprs_should_have_correct_length.rs:154:44
    |
 LL |         assert::is_transmutable::<Current, Larger, Context>();
    |                                            ^^^^^^ `V0usize` cannot be safely transmuted into `[usize; 2]` in the defining scope of `nsize::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<V0usize, nsize::Context, true, true, true, true>` is not implemented for `[usize; 2]`
+   = help: the trait `BikeshedIntrinsicFrom<V0usize, nsize::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `[usize; 2]`
 note: required by a bound in `is_transmutable`
   --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
    |
-LL |     pub fn is_transmutable<Src, Dst, Context>()
-   |            --------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |       pub fn is_transmutable<Src, Dst, Context>()
+   |              --------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_transmutable`
 
 error: aborting due to 20 previous errors
 
index 978a12648f03a9c11e585d74a9eff3c5a1057733..102111ae291c6200d6a57103e7b2a130e4d68b4d 100644 (file)
@@ -6,12 +6,19 @@
 #![allow(dead_code, incomplete_features, non_camel_case_types)]
 
 mod assert {
-    use std::mem::BikeshedIntrinsicFrom;
+    use std::mem::{Assume, BikeshedIntrinsicFrom};
     pub struct Context;
 
     pub fn is_maybe_transmutable<Src, Dst>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+        Dst: BikeshedIntrinsicFrom<Src, Context, {
+            Assume {
+                alignment: true,
+                lifetimes: true,
+                safety: true,
+                validity: true,
+            }
+        }>
     {}
 }
 
index 3273e87c89ff4f3c97663eb060ee3f210bd7ba29..510b8c56e5ab8712ff456d0d0d2c7c1f37918789 100644 (file)
 error[E0277]: `void::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
-  --> $DIR/should_require_well_defined_layout.rs:21:52
+  --> $DIR/should_require_well_defined_layout.rs:28:52
    |
 LL |         assert::is_maybe_transmutable::<repr_rust, ()>();
    |                                                    ^^ `void::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<void::repr_rust, assert::Context, true, true, true, true>` is not implemented for `()`
+   = help: the trait `BikeshedIntrinsicFrom<void::repr_rust, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()`
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/should_require_well_defined_layout.rs:14:14
    |
-LL |     pub fn is_maybe_transmutable<Src, Dst>()
-   |            --------------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL |       pub fn is_maybe_transmutable<Src, Dst>()
+   |              --------------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_maybe_transmutable`
 
 error[E0277]: `u128` cannot be safely transmuted into `void::repr_rust` in the defining scope of `assert::Context`.
-  --> $DIR/should_require_well_defined_layout.rs:22:47
+  --> $DIR/should_require_well_defined_layout.rs:29:47
    |
 LL |         assert::is_maybe_transmutable::<u128, repr_rust>();
    |                                               ^^^^^^^^^ `u128` cannot be safely transmuted into `void::repr_rust` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, true, true, true, true>` is not implemented for `void::repr_rust`
+   = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `void::repr_rust`
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/should_require_well_defined_layout.rs:14:14
    |
-LL |     pub fn is_maybe_transmutable<Src, Dst>()
-   |            --------------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL |       pub fn is_maybe_transmutable<Src, Dst>()
+   |              --------------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_maybe_transmutable`
 
 error[E0277]: `singleton::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
-  --> $DIR/should_require_well_defined_layout.rs:27:52
+  --> $DIR/should_require_well_defined_layout.rs:34:52
    |
 LL |         assert::is_maybe_transmutable::<repr_rust, ()>();
    |                                                    ^^ `singleton::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<singleton::repr_rust, assert::Context, true, true, true, true>` is not implemented for `()`
+   = help: the trait `BikeshedIntrinsicFrom<singleton::repr_rust, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()`
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/should_require_well_defined_layout.rs:14:14
    |
-LL |     pub fn is_maybe_transmutable<Src, Dst>()
-   |            --------------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL |       pub fn is_maybe_transmutable<Src, Dst>()
+   |              --------------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_maybe_transmutable`
 
 error[E0277]: `u128` cannot be safely transmuted into `singleton::repr_rust` in the defining scope of `assert::Context`.
-  --> $DIR/should_require_well_defined_layout.rs:28:47
+  --> $DIR/should_require_well_defined_layout.rs:35:47
    |
 LL |         assert::is_maybe_transmutable::<u128, repr_rust>();
    |                                               ^^^^^^^^^ `u128` cannot be safely transmuted into `singleton::repr_rust` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, true, true, true, true>` is not implemented for `singleton::repr_rust`
+   = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `singleton::repr_rust`
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/should_require_well_defined_layout.rs:14:14
    |
-LL |     pub fn is_maybe_transmutable<Src, Dst>()
-   |            --------------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL |       pub fn is_maybe_transmutable<Src, Dst>()
+   |              --------------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_maybe_transmutable`
 
 error[E0277]: `duplex::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
-  --> $DIR/should_require_well_defined_layout.rs:33:52
+  --> $DIR/should_require_well_defined_layout.rs:40:52
    |
 LL |         assert::is_maybe_transmutable::<repr_rust, ()>();
    |                                                    ^^ `duplex::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<duplex::repr_rust, assert::Context, true, true, true, true>` is not implemented for `()`
+   = help: the trait `BikeshedIntrinsicFrom<duplex::repr_rust, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()`
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/should_require_well_defined_layout.rs:14:14
    |
-LL |     pub fn is_maybe_transmutable<Src, Dst>()
-   |            --------------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL |       pub fn is_maybe_transmutable<Src, Dst>()
+   |              --------------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_maybe_transmutable`
 
 error[E0277]: `u128` cannot be safely transmuted into `duplex::repr_rust` in the defining scope of `assert::Context`.
-  --> $DIR/should_require_well_defined_layout.rs:34:47
+  --> $DIR/should_require_well_defined_layout.rs:41:47
    |
 LL |         assert::is_maybe_transmutable::<u128, repr_rust>();
    |                                               ^^^^^^^^^ `u128` cannot be safely transmuted into `duplex::repr_rust` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, true, true, true, true>` is not implemented for `duplex::repr_rust`
+   = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `duplex::repr_rust`
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/should_require_well_defined_layout.rs:14:14
    |
-LL |     pub fn is_maybe_transmutable<Src, Dst>()
-   |            --------------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL |       pub fn is_maybe_transmutable<Src, Dst>()
+   |              --------------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_maybe_transmutable`
 
 error: aborting due to 6 previous errors
 
index 6558d2658ee455fc2ff7ce5e8838543116273db7..b753cf0e62d5943dbe40b2b84551ab1d38cf14bf 100644 (file)
@@ -7,12 +7,17 @@
 #![allow(dead_code)]
 
 mod assert {
-    use std::mem::BikeshedIntrinsicFrom;
+    use std::mem::{Assume, BikeshedIntrinsicFrom};
     pub struct Context;
 
     pub fn is_transmutable<Src, Dst>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+        Dst: BikeshedIntrinsicFrom<Src, Context, {
+            Assume::ALIGNMENT
+                .and(Assume::LIFETIMES)
+                .and(Assume::SAFETY)
+                .and(Assume::VALIDITY)
+        }>
     {}
 }
 
index 466b6c8a15b52ede797b96fb26b09cf48cc93ba5..c077c52a36ac7913cf4309cbb867345bdf8c49be 100644 (file)
@@ -6,11 +6,16 @@
 #![allow(dead_code)]
 
 mod assert {
-    use std::mem::BikeshedIntrinsicFrom;
+    use std::mem::{Assume, BikeshedIntrinsicFrom};
 
     pub fn is_transmutable<Src, Dst, Context>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+        Dst: BikeshedIntrinsicFrom<Src, Context, {
+            Assume::ALIGNMENT
+                .and(Assume::LIFETIMES)
+                .and(Assume::SAFETY)
+                .and(Assume::VALIDITY)
+        }>
     {}
 }
 
index 429f7211d17a86cfaa87434afd180be295246cb9..a823503d594e9715847ec46d38ecf76a78dd6b1a 100644 (file)
@@ -1,18 +1,24 @@
 error[E0277]: `Src` cannot be safely transmuted into `Dst` in the defining scope of `should_pad_variants::Context`.
-  --> $DIR/should_pad_variants.rs:39:36
+  --> $DIR/should_pad_variants.rs:44:36
    |
 LL |     assert::is_transmutable::<Src, Dst, Context>();
    |                                    ^^^ `Src` cannot be safely transmuted into `Dst` in the defining scope of `should_pad_variants::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<Src, should_pad_variants::Context, true, true, true, true>` is not implemented for `Dst`
+   = help: the trait `BikeshedIntrinsicFrom<Src, should_pad_variants::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `Dst`
 note: required by a bound in `is_transmutable`
   --> $DIR/should_pad_variants.rs:13:14
    |
-LL |     pub fn is_transmutable<Src, Dst, Context>()
-   |            --------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |       pub fn is_transmutable<Src, Dst, Context>()
+   |              --------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume::ALIGNMENT
+LL | |                 .and(Assume::LIFETIMES)
+LL | |                 .and(Assume::SAFETY)
+LL | |                 .and(Assume::VALIDITY)
+LL | |         }>
+   | |__________^ required by this bound in `is_transmutable`
 
 error: aborting due to previous error
 
index 67a3c4e94ba8fb17e971908237c777044b62ccee..19ff690050031e16698eeeffdb952f971b6175eb 100644 (file)
@@ -7,12 +7,17 @@
 #![allow(dead_code)]
 
 mod assert {
-    use std::mem::BikeshedIntrinsicFrom;
+    use std::mem::{Assume, BikeshedIntrinsicFrom};
     pub struct Context;
 
     pub fn is_transmutable<Src, Dst>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+        Dst: BikeshedIntrinsicFrom<Src, Context, {
+            Assume::ALIGNMENT
+                .and(Assume::LIFETIMES)
+                .and(Assume::SAFETY)
+                .and(Assume::VALIDITY)
+        }>
     {}
 }
 
index 78023cb378acacced03668822eba2a023e26158f..fcb70813bd961f76bbffa57ea04dc6dedbcfbd42 100644 (file)
@@ -1,18 +1,24 @@
 error[E0277]: `Src` cannot be safely transmuted into `Unexpected` in the defining scope of `assert::Context`.
-  --> $DIR/should_respect_endianness.rs:32:36
+  --> $DIR/should_respect_endianness.rs:37:36
    |
 LL |     assert::is_transmutable::<Src, Unexpected>();
    |                                    ^^^^^^^^^^ `Src` cannot be safely transmuted into `Unexpected` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<Src, assert::Context, true, true, true, true>` is not implemented for `Unexpected`
+   = help: the trait `BikeshedIntrinsicFrom<Src, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `Unexpected`
 note: required by a bound in `is_transmutable`
   --> $DIR/should_respect_endianness.rs:15:14
    |
-LL |     pub fn is_transmutable<Src, Dst>()
-   |            --------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |       pub fn is_transmutable<Src, Dst>()
+   |              --------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume::ALIGNMENT
+LL | |                 .and(Assume::LIFETIMES)
+LL | |                 .and(Assume::SAFETY)
+LL | |                 .and(Assume::VALIDITY)
+LL | |         }>
+   | |__________^ required by this bound in `is_transmutable`
 
 error: aborting due to previous error
 
index e13462d390b0302b4da240b27623ab79ab672dc4..b3a1e13b85bed0595c5bfa4d43e2c1e86de9c070 100644 (file)
@@ -10,7 +10,7 @@ mod assert {
 
     pub fn is_transmutable<Src, Dst, Context>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
+        Dst: BikeshedIntrinsicFrom<Src, Context>
     {}
 }
 
index dc51e2a8f4d2b65c58106c7ce90a970d3378958f..092b205b770270e8983d920239201cb8175897ef 100644 (file)
@@ -10,7 +10,7 @@ mod assert {
 
     pub fn is_transmutable<Src, Dst, Context>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
+        Dst: BikeshedIntrinsicFrom<Src, Context>
     {}
 }
 
index 86fc8bd6b28568230b434e28f8dc890bc15c04fa..ebe34e13432b55614d454538ca275dca63789319 100644 (file)
@@ -10,7 +10,7 @@ mod assert {
 
     pub fn is_transmutable<Src, Dst, Context>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
+        Dst: BikeshedIntrinsicFrom<Src, Context>
     {}
 }
 
index bd36748e7901bb167c3077c6d3113a1c8f75d22c..354abf99d4d07ae29bae4d46e27d0c1550936188 100644 (file)
@@ -2,11 +2,13 @@
 //! provided.
 
 #![crate_type = "lib"]
+#![feature(adt_const_params)]
+#![feature(generic_const_exprs)]
 #![feature(transmutability)]
 #![allow(dead_code, incomplete_features, non_camel_case_types)]
 
 mod assert {
-    use std::mem::BikeshedIntrinsicFrom;
+    use std::mem::{Assume, BikeshedIntrinsicFrom};
 
     pub fn is_transmutable<
         Src,
@@ -14,19 +16,34 @@ pub fn is_transmutable<
         Context,
         const ASSUME_ALIGNMENT: bool,
         const ASSUME_LIFETIMES: bool,
+        const ASSUME_SAFETY: bool,
         const ASSUME_VALIDITY: bool,
-        const ASSUME_VISIBILITY: bool,
     >()
     where
         Dst: BikeshedIntrinsicFrom<
             Src,
             Context,
-            ASSUME_ALIGNMENT,
-            ASSUME_LIFETIMES,
-            ASSUME_VALIDITY,
-            ASSUME_VISIBILITY,
+            { from_options(ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_SAFETY, ASSUME_VALIDITY) }
+            //~^ ERROR E0080
+            //~| ERROR E0080
+            //~| ERROR E0080
+            //~| ERROR E0080
         >,
     {}
+
+    const fn from_options(
+        alignment: bool,
+        lifetimes: bool,
+        safety: bool,
+        validity: bool,
+    ) -> Assume {
+        Assume {
+            alignment,
+            lifetimes,
+            safety,
+            validity,
+        }
+    }
 }
 
 fn test() {
index e1464e02352c6231e1248c261a03948aba7eb4b9..a258f2ecea6d9a0c34b6312996d1f3a9f26c9a38 100644 (file)
@@ -1,27 +1,52 @@
 error[E0308]: mismatched types
-  --> $DIR/wrong-type-assume.rs:36:51
+  --> $DIR/wrong-type-assume.rs:53:51
    |
 LL |     assert::is_transmutable::<Src, Dst, Context, {0u8}, false, false, false>();
    |                                                   ^^^ expected `bool`, found `u8`
 
+error[E0080]: evaluation of `assert::is_transmutable::<test::Src, test::Dst, test::Context, {0u8}, false, false, false>::{constant#0}` failed
+  --> $DIR/wrong-type-assume.rs:26:15
+   |
+LL |             { from_options(ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_SAFETY, ASSUME_VALIDITY) }
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
+
 error[E0308]: mismatched types
-  --> $DIR/wrong-type-assume.rs:37:58
+  --> $DIR/wrong-type-assume.rs:54:58
    |
 LL |     assert::is_transmutable::<Src, Dst, Context, false, {0u8}, false, false>();
    |                                                          ^^^ expected `bool`, found `u8`
 
+error[E0080]: evaluation of `assert::is_transmutable::<test::Src, test::Dst, test::Context, false, {0u8}, false, false>::{constant#0}` failed
+  --> $DIR/wrong-type-assume.rs:26:15
+   |
+LL |             { from_options(ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_SAFETY, ASSUME_VALIDITY) }
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
+
 error[E0308]: mismatched types
-  --> $DIR/wrong-type-assume.rs:38:65
+  --> $DIR/wrong-type-assume.rs:55:65
    |
 LL |     assert::is_transmutable::<Src, Dst, Context, false, false, {0u8}, false>();
    |                                                                 ^^^ expected `bool`, found `u8`
 
+error[E0080]: evaluation of `assert::is_transmutable::<test::Src, test::Dst, test::Context, false, false, {0u8}, false>::{constant#0}` failed
+  --> $DIR/wrong-type-assume.rs:26:15
+   |
+LL |             { from_options(ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_SAFETY, ASSUME_VALIDITY) }
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
+
 error[E0308]: mismatched types
-  --> $DIR/wrong-type-assume.rs:39:72
+  --> $DIR/wrong-type-assume.rs:56:72
    |
 LL |     assert::is_transmutable::<Src, Dst, Context, false, false, false, {0u8}>();
    |                                                                        ^^^ expected `bool`, found `u8`
 
-error: aborting due to 4 previous errors
+error[E0080]: evaluation of `assert::is_transmutable::<test::Src, test::Dst, test::Context, false, false, false, {0u8}>::{constant#0}` failed
+  --> $DIR/wrong-type-assume.rs:26:15
+   |
+LL |             { from_options(ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_SAFETY, ASSUME_VALIDITY) }
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
+
+error: aborting due to 8 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
+Some errors have detailed explanations: E0080, E0308.
+For more information about an error, try `rustc --explain E0080`.
index 4f79bc2533708ef41774b6e60a8619d607c10016..eebb74fff471ce9ec240c27a876dd2a79f026776 100644 (file)
@@ -4,17 +4,17 @@
 #![allow(incomplete_features)]
 
 mod assert {
-    use std::mem::BikeshedIntrinsicFrom;
+    use std::mem::{Assume, BikeshedIntrinsicFrom};
     pub struct Context;
 
     pub fn is_transmutable<Src, Dst>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, true>
+        Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }>
     {}
 
     pub fn is_maybe_transmutable<Src, Dst>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, false, false, true, true>
+        Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY.and(Assume::VALIDITY) }>
     {}
 }
 
index dc740251c871e1e3d30de7afa57fa2e82454635c..214b5e150edd23de17a4d3a3f0d3feebda09a07f 100644 (file)
@@ -4,15 +4,15 @@ error[E0277]: `u8` cannot be safely transmuted into `bool` in the defining scope
 LL |     assert::is_transmutable::<u8, bool>();
    |                                   ^^^^ `u8` cannot be safely transmuted into `bool` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, false, false, false, true>` is not implemented for `bool`
+   = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: true, validity: false }>` is not implemented for `bool`
 note: required by a bound in `is_transmutable`
   --> $DIR/bool.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error: aborting due to previous error
 
index a5f79065d8aad514be41b8c6e29eb23871f7367d..0df43d2045f72aeca46bf958ff981118c849daa3 100644 (file)
@@ -9,7 +9,7 @@ mod assert {
 
     pub fn is_transmutable<Src, Dst>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
+        Dst: BikeshedIntrinsicFrom<Src, Context>
     {}
 }
 
index 9b802a444e86a1f01c8adcf4cafc1efffdf32ef3..7cb7ca8e6db524a7255ea08a0c6e1ba7b6165589 100644 (file)
@@ -4,15 +4,15 @@ error[E0277]: `i8` cannot be safely transmuted into `i16` in the defining scope
 LL |     assert::is_transmutable::<   i8,   i16>();
    |                                        ^^^ `i8` cannot be safely transmuted into `i16` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, false, false, false, false>` is not implemented for `i16`
+   = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i16`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `u16` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:63:40
@@ -20,15 +20,15 @@ error[E0277]: `i8` cannot be safely transmuted into `u16` in the defining scope
 LL |     assert::is_transmutable::<   i8,   u16>();
    |                                        ^^^ `i8` cannot be safely transmuted into `u16` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, false, false, false, false>` is not implemented for `u16`
+   = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u16`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:64:40
@@ -36,15 +36,15 @@ error[E0277]: `i8` cannot be safely transmuted into `i32` in the defining scope
 LL |     assert::is_transmutable::<   i8,   i32>();
    |                                        ^^^ `i8` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, false, false, false, false>` is not implemented for `i32`
+   = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i32`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:65:40
@@ -52,15 +52,15 @@ error[E0277]: `i8` cannot be safely transmuted into `f32` in the defining scope
 LL |     assert::is_transmutable::<   i8,   f32>();
    |                                        ^^^ `i8` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, false, false, false, false>` is not implemented for `f32`
+   = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f32`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:66:40
@@ -68,15 +68,15 @@ error[E0277]: `i8` cannot be safely transmuted into `u32` in the defining scope
 LL |     assert::is_transmutable::<   i8,   u32>();
    |                                        ^^^ `i8` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, false, false, false, false>` is not implemented for `u32`
+   = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u32`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:67:40
@@ -84,15 +84,15 @@ error[E0277]: `i8` cannot be safely transmuted into `u64` in the defining scope
 LL |     assert::is_transmutable::<   i8,   u64>();
    |                                        ^^^ `i8` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, false, false, false, false>` is not implemented for `u64`
+   = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:68:40
@@ -100,15 +100,15 @@ error[E0277]: `i8` cannot be safely transmuted into `i64` in the defining scope
 LL |     assert::is_transmutable::<   i8,   i64>();
    |                                        ^^^ `i8` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, false, false, false, false>` is not implemented for `i64`
+   = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:69:40
@@ -116,15 +116,15 @@ error[E0277]: `i8` cannot be safely transmuted into `f64` in the defining scope
 LL |     assert::is_transmutable::<   i8,   f64>();
    |                                        ^^^ `i8` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, false, false, false, false>` is not implemented for `f64`
+   = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:70:39
@@ -132,15 +132,15 @@ error[E0277]: `i8` cannot be safely transmuted into `u128` in the defining scope
 LL |     assert::is_transmutable::<   i8,  u128>();
    |                                       ^^^^ `i8` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, false, false, false, false>` is not implemented for `u128`
+   = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:71:39
@@ -148,15 +148,15 @@ error[E0277]: `i8` cannot be safely transmuted into `i128` in the defining scope
 LL |     assert::is_transmutable::<   i8,  i128>();
    |                                       ^^^^ `i8` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, false, false, false, false>` is not implemented for `i128`
+   = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `i16` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:73:40
@@ -164,15 +164,15 @@ error[E0277]: `u8` cannot be safely transmuted into `i16` in the defining scope
 LL |     assert::is_transmutable::<   u8,   i16>();
    |                                        ^^^ `u8` cannot be safely transmuted into `i16` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, false, false, false, false>` is not implemented for `i16`
+   = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i16`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `u16` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:74:40
@@ -180,15 +180,15 @@ error[E0277]: `u8` cannot be safely transmuted into `u16` in the defining scope
 LL |     assert::is_transmutable::<   u8,   u16>();
    |                                        ^^^ `u8` cannot be safely transmuted into `u16` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, false, false, false, false>` is not implemented for `u16`
+   = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u16`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:75:40
@@ -196,15 +196,15 @@ error[E0277]: `u8` cannot be safely transmuted into `i32` in the defining scope
 LL |     assert::is_transmutable::<   u8,   i32>();
    |                                        ^^^ `u8` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, false, false, false, false>` is not implemented for `i32`
+   = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i32`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:76:40
@@ -212,15 +212,15 @@ error[E0277]: `u8` cannot be safely transmuted into `f32` in the defining scope
 LL |     assert::is_transmutable::<   u8,   f32>();
    |                                        ^^^ `u8` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, false, false, false, false>` is not implemented for `f32`
+   = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f32`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:77:40
@@ -228,15 +228,15 @@ error[E0277]: `u8` cannot be safely transmuted into `u32` in the defining scope
 LL |     assert::is_transmutable::<   u8,   u32>();
    |                                        ^^^ `u8` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, false, false, false, false>` is not implemented for `u32`
+   = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u32`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:78:40
@@ -244,15 +244,15 @@ error[E0277]: `u8` cannot be safely transmuted into `u64` in the defining scope
 LL |     assert::is_transmutable::<   u8,   u64>();
    |                                        ^^^ `u8` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, false, false, false, false>` is not implemented for `u64`
+   = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:79:40
@@ -260,15 +260,15 @@ error[E0277]: `u8` cannot be safely transmuted into `i64` in the defining scope
 LL |     assert::is_transmutable::<   u8,   i64>();
    |                                        ^^^ `u8` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, false, false, false, false>` is not implemented for `i64`
+   = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:80:40
@@ -276,15 +276,15 @@ error[E0277]: `u8` cannot be safely transmuted into `f64` in the defining scope
 LL |     assert::is_transmutable::<   u8,   f64>();
    |                                        ^^^ `u8` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, false, false, false, false>` is not implemented for `f64`
+   = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:81:39
@@ -292,15 +292,15 @@ error[E0277]: `u8` cannot be safely transmuted into `u128` in the defining scope
 LL |     assert::is_transmutable::<   u8,  u128>();
    |                                       ^^^^ `u8` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, false, false, false, false>` is not implemented for `u128`
+   = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:82:39
@@ -308,15 +308,15 @@ error[E0277]: `u8` cannot be safely transmuted into `i128` in the defining scope
 LL |     assert::is_transmutable::<   u8,  i128>();
    |                                       ^^^^ `u8` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, false, false, false, false>` is not implemented for `i128`
+   = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i16` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:84:40
@@ -324,15 +324,15 @@ error[E0277]: `i16` cannot be safely transmuted into `i32` in the defining scope
 LL |     assert::is_transmutable::<  i16,   i32>();
    |                                        ^^^ `i16` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, false, false, false, false>` is not implemented for `i32`
+   = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i32`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i16` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:85:40
@@ -340,15 +340,15 @@ error[E0277]: `i16` cannot be safely transmuted into `f32` in the defining scope
 LL |     assert::is_transmutable::<  i16,   f32>();
    |                                        ^^^ `i16` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, false, false, false, false>` is not implemented for `f32`
+   = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f32`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i16` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:86:40
@@ -356,15 +356,15 @@ error[E0277]: `i16` cannot be safely transmuted into `u32` in the defining scope
 LL |     assert::is_transmutable::<  i16,   u32>();
    |                                        ^^^ `i16` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, false, false, false, false>` is not implemented for `u32`
+   = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u32`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i16` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:87:40
@@ -372,15 +372,15 @@ error[E0277]: `i16` cannot be safely transmuted into `u64` in the defining scope
 LL |     assert::is_transmutable::<  i16,   u64>();
    |                                        ^^^ `i16` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, false, false, false, false>` is not implemented for `u64`
+   = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i16` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:88:40
@@ -388,15 +388,15 @@ error[E0277]: `i16` cannot be safely transmuted into `i64` in the defining scope
 LL |     assert::is_transmutable::<  i16,   i64>();
    |                                        ^^^ `i16` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, false, false, false, false>` is not implemented for `i64`
+   = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i16` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:89:40
@@ -404,15 +404,15 @@ error[E0277]: `i16` cannot be safely transmuted into `f64` in the defining scope
 LL |     assert::is_transmutable::<  i16,   f64>();
    |                                        ^^^ `i16` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, false, false, false, false>` is not implemented for `f64`
+   = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i16` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:90:39
@@ -420,15 +420,15 @@ error[E0277]: `i16` cannot be safely transmuted into `u128` in the defining scop
 LL |     assert::is_transmutable::<  i16,  u128>();
    |                                       ^^^^ `i16` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, false, false, false, false>` is not implemented for `u128`
+   = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i16` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:91:39
@@ -436,15 +436,15 @@ error[E0277]: `i16` cannot be safely transmuted into `i128` in the defining scop
 LL |     assert::is_transmutable::<  i16,  i128>();
    |                                       ^^^^ `i16` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, false, false, false, false>` is not implemented for `i128`
+   = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u16` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:93:40
@@ -452,15 +452,15 @@ error[E0277]: `u16` cannot be safely transmuted into `i32` in the defining scope
 LL |     assert::is_transmutable::<  u16,   i32>();
    |                                        ^^^ `u16` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, false, false, false, false>` is not implemented for `i32`
+   = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i32`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u16` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:94:40
@@ -468,15 +468,15 @@ error[E0277]: `u16` cannot be safely transmuted into `f32` in the defining scope
 LL |     assert::is_transmutable::<  u16,   f32>();
    |                                        ^^^ `u16` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, false, false, false, false>` is not implemented for `f32`
+   = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f32`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u16` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:95:40
@@ -484,15 +484,15 @@ error[E0277]: `u16` cannot be safely transmuted into `u32` in the defining scope
 LL |     assert::is_transmutable::<  u16,   u32>();
    |                                        ^^^ `u16` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, false, false, false, false>` is not implemented for `u32`
+   = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u32`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u16` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:96:40
@@ -500,15 +500,15 @@ error[E0277]: `u16` cannot be safely transmuted into `u64` in the defining scope
 LL |     assert::is_transmutable::<  u16,   u64>();
    |                                        ^^^ `u16` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, false, false, false, false>` is not implemented for `u64`
+   = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u16` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:97:40
@@ -516,15 +516,15 @@ error[E0277]: `u16` cannot be safely transmuted into `i64` in the defining scope
 LL |     assert::is_transmutable::<  u16,   i64>();
    |                                        ^^^ `u16` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, false, false, false, false>` is not implemented for `i64`
+   = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u16` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:98:40
@@ -532,15 +532,15 @@ error[E0277]: `u16` cannot be safely transmuted into `f64` in the defining scope
 LL |     assert::is_transmutable::<  u16,   f64>();
    |                                        ^^^ `u16` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, false, false, false, false>` is not implemented for `f64`
+   = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u16` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:99:39
@@ -548,15 +548,15 @@ error[E0277]: `u16` cannot be safely transmuted into `u128` in the defining scop
 LL |     assert::is_transmutable::<  u16,  u128>();
    |                                       ^^^^ `u16` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, false, false, false, false>` is not implemented for `u128`
+   = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u16` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:100:39
@@ -564,15 +564,15 @@ error[E0277]: `u16` cannot be safely transmuted into `i128` in the defining scop
 LL |     assert::is_transmutable::<  u16,  i128>();
    |                                       ^^^^ `u16` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, false, false, false, false>` is not implemented for `i128`
+   = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:102:40
@@ -580,15 +580,15 @@ error[E0277]: `i32` cannot be safely transmuted into `u64` in the defining scope
 LL |     assert::is_transmutable::<  i32,   u64>();
    |                                        ^^^ `i32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, false, false, false, false>` is not implemented for `u64`
+   = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:103:40
@@ -596,15 +596,15 @@ error[E0277]: `i32` cannot be safely transmuted into `i64` in the defining scope
 LL |     assert::is_transmutable::<  i32,   i64>();
    |                                        ^^^ `i32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, false, false, false, false>` is not implemented for `i64`
+   = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:104:40
@@ -612,15 +612,15 @@ error[E0277]: `i32` cannot be safely transmuted into `f64` in the defining scope
 LL |     assert::is_transmutable::<  i32,   f64>();
    |                                        ^^^ `i32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, false, false, false, false>` is not implemented for `f64`
+   = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:105:39
@@ -628,15 +628,15 @@ error[E0277]: `i32` cannot be safely transmuted into `u128` in the defining scop
 LL |     assert::is_transmutable::<  i32,  u128>();
    |                                       ^^^^ `i32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, false, false, false, false>` is not implemented for `u128`
+   = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:106:39
@@ -644,15 +644,15 @@ error[E0277]: `i32` cannot be safely transmuted into `i128` in the defining scop
 LL |     assert::is_transmutable::<  i32,  i128>();
    |                                       ^^^^ `i32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, false, false, false, false>` is not implemented for `i128`
+   = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `f32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:108:40
@@ -660,15 +660,15 @@ error[E0277]: `f32` cannot be safely transmuted into `u64` in the defining scope
 LL |     assert::is_transmutable::<  f32,   u64>();
    |                                        ^^^ `f32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, false, false, false, false>` is not implemented for `u64`
+   = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `f32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:109:40
@@ -676,15 +676,15 @@ error[E0277]: `f32` cannot be safely transmuted into `i64` in the defining scope
 LL |     assert::is_transmutable::<  f32,   i64>();
    |                                        ^^^ `f32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, false, false, false, false>` is not implemented for `i64`
+   = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `f32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:110:40
@@ -692,15 +692,15 @@ error[E0277]: `f32` cannot be safely transmuted into `f64` in the defining scope
 LL |     assert::is_transmutable::<  f32,   f64>();
    |                                        ^^^ `f32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, false, false, false, false>` is not implemented for `f64`
+   = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `f32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:111:39
@@ -708,15 +708,15 @@ error[E0277]: `f32` cannot be safely transmuted into `u128` in the defining scop
 LL |     assert::is_transmutable::<  f32,  u128>();
    |                                       ^^^^ `f32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, false, false, false, false>` is not implemented for `u128`
+   = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `f32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:112:39
@@ -724,15 +724,15 @@ error[E0277]: `f32` cannot be safely transmuted into `i128` in the defining scop
 LL |     assert::is_transmutable::<  f32,  i128>();
    |                                       ^^^^ `f32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, false, false, false, false>` is not implemented for `i128`
+   = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:114:40
@@ -740,15 +740,15 @@ error[E0277]: `u32` cannot be safely transmuted into `u64` in the defining scope
 LL |     assert::is_transmutable::<  u32,   u64>();
    |                                        ^^^ `u32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, false, false, false, false>` is not implemented for `u64`
+   = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:115:40
@@ -756,15 +756,15 @@ error[E0277]: `u32` cannot be safely transmuted into `i64` in the defining scope
 LL |     assert::is_transmutable::<  u32,   i64>();
    |                                        ^^^ `u32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, false, false, false, false>` is not implemented for `i64`
+   = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:116:40
@@ -772,15 +772,15 @@ error[E0277]: `u32` cannot be safely transmuted into `f64` in the defining scope
 LL |     assert::is_transmutable::<  u32,   f64>();
    |                                        ^^^ `u32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, false, false, false, false>` is not implemented for `f64`
+   = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:117:39
@@ -788,15 +788,15 @@ error[E0277]: `u32` cannot be safely transmuted into `u128` in the defining scop
 LL |     assert::is_transmutable::<  u32,  u128>();
    |                                       ^^^^ `u32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, false, false, false, false>` is not implemented for `u128`
+   = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:118:39
@@ -804,15 +804,15 @@ error[E0277]: `u32` cannot be safely transmuted into `i128` in the defining scop
 LL |     assert::is_transmutable::<  u32,  i128>();
    |                                       ^^^^ `u32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, false, false, false, false>` is not implemented for `i128`
+   = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:120:39
@@ -820,15 +820,15 @@ error[E0277]: `u64` cannot be safely transmuted into `u128` in the defining scop
 LL |     assert::is_transmutable::<  u64,  u128>();
    |                                       ^^^^ `u64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u64, assert::Context, false, false, false, false>` is not implemented for `u128`
+   = help: the trait `BikeshedIntrinsicFrom<u64, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:121:39
@@ -836,15 +836,15 @@ error[E0277]: `u64` cannot be safely transmuted into `i128` in the defining scop
 LL |     assert::is_transmutable::<  u64,  i128>();
    |                                       ^^^^ `u64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u64, assert::Context, false, false, false, false>` is not implemented for `i128`
+   = help: the trait `BikeshedIntrinsicFrom<u64, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:123:39
@@ -852,15 +852,15 @@ error[E0277]: `i64` cannot be safely transmuted into `u128` in the defining scop
 LL |     assert::is_transmutable::<  i64,  u128>();
    |                                       ^^^^ `i64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<i64, assert::Context, false, false, false, false>` is not implemented for `u128`
+   = help: the trait `BikeshedIntrinsicFrom<i64, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:124:39
@@ -868,15 +868,15 @@ error[E0277]: `i64` cannot be safely transmuted into `i128` in the defining scop
 LL |     assert::is_transmutable::<  i64,  i128>();
    |                                       ^^^^ `i64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<i64, assert::Context, false, false, false, false>` is not implemented for `i128`
+   = help: the trait `BikeshedIntrinsicFrom<i64, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `f64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:126:39
@@ -884,15 +884,15 @@ error[E0277]: `f64` cannot be safely transmuted into `u128` in the defining scop
 LL |     assert::is_transmutable::<  f64,  u128>();
    |                                       ^^^^ `f64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<f64, assert::Context, false, false, false, false>` is not implemented for `u128`
+   = help: the trait `BikeshedIntrinsicFrom<f64, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `f64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
   --> $DIR/numbers.rs:127:39
@@ -900,15 +900,15 @@ error[E0277]: `f64` cannot be safely transmuted into `i128` in the defining scop
 LL |     assert::is_transmutable::<  f64,  i128>();
    |                                       ^^^^ `f64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<f64, assert::Context, false, false, false, false>` is not implemented for `i128`
+   = help: the trait `BikeshedIntrinsicFrom<f64, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
 note: required by a bound in `is_transmutable`
   --> $DIR/numbers.rs:12:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error: aborting due to 57 previous errors
 
index 86d4740300dff7ff3df4eb93161fe1e5d1b8c4c1..1975a61de988215663bf94801d225a7f8504584a 100644 (file)
@@ -5,11 +5,16 @@
 #![allow(dead_code)]
 
 mod assert {
-    use std::mem::BikeshedIntrinsicFrom;
+    use std::mem::{Assume, BikeshedIntrinsicFrom};
 
     pub fn is_transmutable<Src, Dst, Context>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+        Dst: BikeshedIntrinsicFrom<Src, Context, {
+            Assume::ALIGNMENT
+                .and(Assume::LIFETIMES)
+                .and(Assume::SAFETY)
+                .and(Assume::VALIDITY)
+        }>
     {}
 }
 
index cf27c0d17b3378600faccc12d45e03bb93100693..8cabe44a0538c817219df58c0a20e801ce6701ca 100644 (file)
@@ -1,18 +1,24 @@
 error[E0277]: `()` cannot be safely transmuted into `u8` in the defining scope of `should_have_correct_size::Context`.
-  --> $DIR/unit.rs:23:35
+  --> $DIR/unit.rs:28:35
    |
 LL |     assert::is_transmutable::<(), u8, Context>();
    |                                   ^^ `()` cannot be safely transmuted into `u8` in the defining scope of `should_have_correct_size::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<(), should_have_correct_size::Context, true, true, true, true>` is not implemented for `u8`
+   = help: the trait `BikeshedIntrinsicFrom<(), should_have_correct_size::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `u8`
 note: required by a bound in `is_transmutable`
   --> $DIR/unit.rs:12:14
    |
-LL |     pub fn is_transmutable<Src, Dst, Context>()
-   |            --------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |       pub fn is_transmutable<Src, Dst, Context>()
+   |              --------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume::ALIGNMENT
+LL | |                 .and(Assume::LIFETIMES)
+LL | |                 .and(Assume::SAFETY)
+LL | |                 .and(Assume::VALIDITY)
+LL | |         }>
+   | |__________^ required by this bound in `is_transmutable`
 
 error: aborting due to previous error
 
index c6fd4c43e95c00440e4e33fc4d306754eecce5ba..af3ff0ec1d20567c52647b53fd1271fca50d7527 100644 (file)
@@ -5,12 +5,19 @@
 #![allow(dead_code, incomplete_features, non_camel_case_types)]
 
 mod assert {
-    use std::mem::BikeshedIntrinsicFrom;
+    use std::mem::{Assume, BikeshedIntrinsicFrom};
     pub struct Context;
 
     pub fn is_maybe_transmutable<Src, Dst>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+        Dst: BikeshedIntrinsicFrom<Src, Context, {
+            Assume {
+                alignment: true,
+                lifetimes: true,
+                safety: true,
+                validity: true,
+            }
+        }>
     {}
 }
 
index 17ffcf64177e3fa13e7311aeb08058a5d47a2c2d..e9c7b144a826cfca705b0860cfcd3ff98745d7e6 100644 (file)
@@ -1,18 +1,25 @@
 error[E0277]: `&'static Unit` cannot be safely transmuted into `&'static Unit` in the defining scope of `assert::Context`.
-  --> $DIR/references.rs:19:52
+  --> $DIR/references.rs:26:52
    |
 LL |     assert::is_maybe_transmutable::<&'static Unit, &'static Unit>();
    |                                                    ^^^^^^^^^^^^^ `&'static Unit` cannot be safely transmuted into `&'static Unit` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<&'static Unit, assert::Context, true, true, true, true>` is not implemented for `&'static Unit`
+   = help: the trait `BikeshedIntrinsicFrom<&'static Unit, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `&'static Unit`
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/references.rs:13:14
    |
-LL |     pub fn is_maybe_transmutable<Src, Dst>()
-   |            --------------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL |       pub fn is_maybe_transmutable<Src, Dst>()
+   |              --------------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_maybe_transmutable`
 
 error: aborting due to previous error
 
index 71720165ab06327fdfcf1fa3b41db44716f1082c..ea9bf2a237ed38ef124fda5a178cd5d36b484a9d 100644 (file)
@@ -6,12 +6,19 @@
 #![allow(dead_code, incomplete_features, non_camel_case_types)]
 
 mod assert {
-    use std::mem::BikeshedIntrinsicFrom;
+    use std::mem::{Assume, BikeshedIntrinsicFrom};
     pub struct Context;
 
     pub fn is_maybe_transmutable<Src, Dst>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+        Dst: BikeshedIntrinsicFrom<Src, Context, {
+            Assume {
+                alignment: true,
+                lifetimes: true,
+                safety: true,
+                validity: true,
+            }
+        }>
     {}
 }
 
index ae8acf50418976cb2705ddd8a6f5683d90e1b5a7..17dc995fcd961b975c2e51a1b3008803f38dd715 100644 (file)
@@ -6,12 +6,19 @@
 #![allow(dead_code, incomplete_features, non_camel_case_types)]
 
 mod assert {
-    use std::mem::BikeshedIntrinsicFrom;
+    use std::mem::{Assume, BikeshedIntrinsicFrom};
     pub struct Context;
 
     pub fn is_maybe_transmutable<Src, Dst>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+        Dst: BikeshedIntrinsicFrom<Src, Context, {
+            Assume {
+                alignment: true,
+                lifetimes: true,
+                safety: true,
+                validity: true,
+            }
+        }>
     {}
 }
 
index 556be989dbc252a141b9d3ee918ca2573a05be31..9a65b4d702da68ab92de277d0b5ac8ae1a3f81ea 100644 (file)
@@ -5,12 +5,19 @@
 #![allow(dead_code, incomplete_features, non_camel_case_types)]
 
 mod assert {
-    use std::mem::BikeshedIntrinsicFrom;
+    use std::mem::{Assume, BikeshedIntrinsicFrom};
     pub struct Context;
 
     pub fn is_maybe_transmutable<Src, Dst>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+        Dst: BikeshedIntrinsicFrom<Src, Context, {
+            Assume {
+                alignment: true,
+                lifetimes: true,
+                safety: true,
+                validity: true,
+            }
+        }>
     {}
 }
 
index 07355f7c2ad265e79c8b083dea8a9650592369b1..621dbee849f0c21157cb1f6194622b233fa5935d 100644 (file)
 error[E0277]: `should_reject_repr_rust::unit::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
-  --> $DIR/should_require_well_defined_layout.rs:21:52
+  --> $DIR/should_require_well_defined_layout.rs:28:52
    |
 LL |         assert::is_maybe_transmutable::<repr_rust, ()>();
    |                                                    ^^ `should_reject_repr_rust::unit::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<should_reject_repr_rust::unit::repr_rust, assert::Context, true, true, true, true>` is not implemented for `()`
+   = help: the trait `BikeshedIntrinsicFrom<should_reject_repr_rust::unit::repr_rust, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()`
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/should_require_well_defined_layout.rs:13:14
    |
-LL |     pub fn is_maybe_transmutable<Src, Dst>()
-   |            --------------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL |       pub fn is_maybe_transmutable<Src, Dst>()
+   |              --------------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_maybe_transmutable`
 
 error[E0277]: `u128` cannot be safely transmuted into `should_reject_repr_rust::unit::repr_rust` in the defining scope of `assert::Context`.
-  --> $DIR/should_require_well_defined_layout.rs:22:47
+  --> $DIR/should_require_well_defined_layout.rs:29:47
    |
 LL |         assert::is_maybe_transmutable::<u128, repr_rust>();
    |                                               ^^^^^^^^^ `u128` cannot be safely transmuted into `should_reject_repr_rust::unit::repr_rust` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, true, true, true, true>` is not implemented for `should_reject_repr_rust::unit::repr_rust`
+   = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `should_reject_repr_rust::unit::repr_rust`
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/should_require_well_defined_layout.rs:13:14
    |
-LL |     pub fn is_maybe_transmutable<Src, Dst>()
-   |            --------------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL |       pub fn is_maybe_transmutable<Src, Dst>()
+   |              --------------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_maybe_transmutable`
 
 error[E0277]: `should_reject_repr_rust::tuple::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
-  --> $DIR/should_require_well_defined_layout.rs:27:52
+  --> $DIR/should_require_well_defined_layout.rs:34:52
    |
 LL |         assert::is_maybe_transmutable::<repr_rust, ()>();
    |                                                    ^^ `should_reject_repr_rust::tuple::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<should_reject_repr_rust::tuple::repr_rust, assert::Context, true, true, true, true>` is not implemented for `()`
+   = help: the trait `BikeshedIntrinsicFrom<should_reject_repr_rust::tuple::repr_rust, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()`
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/should_require_well_defined_layout.rs:13:14
    |
-LL |     pub fn is_maybe_transmutable<Src, Dst>()
-   |            --------------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL |       pub fn is_maybe_transmutable<Src, Dst>()
+   |              --------------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_maybe_transmutable`
 
 error[E0277]: `u128` cannot be safely transmuted into `should_reject_repr_rust::tuple::repr_rust` in the defining scope of `assert::Context`.
-  --> $DIR/should_require_well_defined_layout.rs:28:47
+  --> $DIR/should_require_well_defined_layout.rs:35:47
    |
 LL |         assert::is_maybe_transmutable::<u128, repr_rust>();
    |                                               ^^^^^^^^^ `u128` cannot be safely transmuted into `should_reject_repr_rust::tuple::repr_rust` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, true, true, true, true>` is not implemented for `should_reject_repr_rust::tuple::repr_rust`
+   = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `should_reject_repr_rust::tuple::repr_rust`
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/should_require_well_defined_layout.rs:13:14
    |
-LL |     pub fn is_maybe_transmutable<Src, Dst>()
-   |            --------------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL |       pub fn is_maybe_transmutable<Src, Dst>()
+   |              --------------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_maybe_transmutable`
 
 error[E0277]: `should_reject_repr_rust::braces::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
-  --> $DIR/should_require_well_defined_layout.rs:33:52
+  --> $DIR/should_require_well_defined_layout.rs:40:52
    |
 LL |         assert::is_maybe_transmutable::<repr_rust, ()>();
    |                                                    ^^ `should_reject_repr_rust::braces::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<should_reject_repr_rust::braces::repr_rust, assert::Context, true, true, true, true>` is not implemented for `()`
+   = help: the trait `BikeshedIntrinsicFrom<should_reject_repr_rust::braces::repr_rust, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()`
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/should_require_well_defined_layout.rs:13:14
    |
-LL |     pub fn is_maybe_transmutable<Src, Dst>()
-   |            --------------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL |       pub fn is_maybe_transmutable<Src, Dst>()
+   |              --------------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_maybe_transmutable`
 
 error[E0277]: `u128` cannot be safely transmuted into `should_reject_repr_rust::braces::repr_rust` in the defining scope of `assert::Context`.
-  --> $DIR/should_require_well_defined_layout.rs:34:47
+  --> $DIR/should_require_well_defined_layout.rs:41:47
    |
 LL |         assert::is_maybe_transmutable::<u128, repr_rust>();
    |                                               ^^^^^^^^^ `u128` cannot be safely transmuted into `should_reject_repr_rust::braces::repr_rust` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, true, true, true, true>` is not implemented for `should_reject_repr_rust::braces::repr_rust`
+   = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `should_reject_repr_rust::braces::repr_rust`
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/should_require_well_defined_layout.rs:13:14
    |
-LL |     pub fn is_maybe_transmutable<Src, Dst>()
-   |            --------------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL |       pub fn is_maybe_transmutable<Src, Dst>()
+   |              --------------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_maybe_transmutable`
 
 error[E0277]: `aligned::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
-  --> $DIR/should_require_well_defined_layout.rs:39:52
+  --> $DIR/should_require_well_defined_layout.rs:46:52
    |
 LL |         assert::is_maybe_transmutable::<repr_rust, ()>();
    |                                                    ^^ `aligned::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<aligned::repr_rust, assert::Context, true, true, true, true>` is not implemented for `()`
+   = help: the trait `BikeshedIntrinsicFrom<aligned::repr_rust, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()`
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/should_require_well_defined_layout.rs:13:14
    |
-LL |     pub fn is_maybe_transmutable<Src, Dst>()
-   |            --------------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL |       pub fn is_maybe_transmutable<Src, Dst>()
+   |              --------------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_maybe_transmutable`
 
 error[E0277]: `u128` cannot be safely transmuted into `aligned::repr_rust` in the defining scope of `assert::Context`.
-  --> $DIR/should_require_well_defined_layout.rs:40:47
+  --> $DIR/should_require_well_defined_layout.rs:47:47
    |
 LL |         assert::is_maybe_transmutable::<u128, repr_rust>();
    |                                               ^^^^^^^^^ `u128` cannot be safely transmuted into `aligned::repr_rust` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, true, true, true, true>` is not implemented for `aligned::repr_rust`
+   = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `aligned::repr_rust`
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/should_require_well_defined_layout.rs:13:14
    |
-LL |     pub fn is_maybe_transmutable<Src, Dst>()
-   |            --------------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL |       pub fn is_maybe_transmutable<Src, Dst>()
+   |              --------------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_maybe_transmutable`
 
 error[E0277]: `packed::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
-  --> $DIR/should_require_well_defined_layout.rs:45:52
+  --> $DIR/should_require_well_defined_layout.rs:52:52
    |
 LL |         assert::is_maybe_transmutable::<repr_rust, ()>();
    |                                                    ^^ `packed::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<packed::repr_rust, assert::Context, true, true, true, true>` is not implemented for `()`
+   = help: the trait `BikeshedIntrinsicFrom<packed::repr_rust, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()`
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/should_require_well_defined_layout.rs:13:14
    |
-LL |     pub fn is_maybe_transmutable<Src, Dst>()
-   |            --------------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL |       pub fn is_maybe_transmutable<Src, Dst>()
+   |              --------------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_maybe_transmutable`
 
 error[E0277]: `u128` cannot be safely transmuted into `packed::repr_rust` in the defining scope of `assert::Context`.
-  --> $DIR/should_require_well_defined_layout.rs:46:47
+  --> $DIR/should_require_well_defined_layout.rs:53:47
    |
 LL |         assert::is_maybe_transmutable::<u128, repr_rust>();
    |                                               ^^^^^^^^^ `u128` cannot be safely transmuted into `packed::repr_rust` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, true, true, true, true>` is not implemented for `packed::repr_rust`
+   = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `packed::repr_rust`
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/should_require_well_defined_layout.rs:13:14
    |
-LL |     pub fn is_maybe_transmutable<Src, Dst>()
-   |            --------------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL |       pub fn is_maybe_transmutable<Src, Dst>()
+   |              --------------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_maybe_transmutable`
 
 error[E0277]: `nested::repr_c` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
-  --> $DIR/should_require_well_defined_layout.rs:52:49
+  --> $DIR/should_require_well_defined_layout.rs:59:49
    |
 LL |         assert::is_maybe_transmutable::<repr_c, ()>();
    |                                                 ^^ `nested::repr_c` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<nested::repr_c, assert::Context, true, true, true, true>` is not implemented for `()`
+   = help: the trait `BikeshedIntrinsicFrom<nested::repr_c, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()`
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/should_require_well_defined_layout.rs:13:14
    |
-LL |     pub fn is_maybe_transmutable<Src, Dst>()
-   |            --------------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL |       pub fn is_maybe_transmutable<Src, Dst>()
+   |              --------------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_maybe_transmutable`
 
 error[E0277]: `u128` cannot be safely transmuted into `nested::repr_c` in the defining scope of `assert::Context`.
-  --> $DIR/should_require_well_defined_layout.rs:53:47
+  --> $DIR/should_require_well_defined_layout.rs:60:47
    |
 LL |         assert::is_maybe_transmutable::<u128, repr_c>();
    |                                               ^^^^^^ `u128` cannot be safely transmuted into `nested::repr_c` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, true, true, true, true>` is not implemented for `nested::repr_c`
+   = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `nested::repr_c`
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/should_require_well_defined_layout.rs:13:14
    |
-LL |     pub fn is_maybe_transmutable<Src, Dst>()
-   |            --------------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL |       pub fn is_maybe_transmutable<Src, Dst>()
+   |              --------------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_maybe_transmutable`
 
 error: aborting due to 12 previous errors
 
index db49b914fe06535cf76941a142dcbead611fc4b8..28724562bad2c6433bcb222d4240b4795c53a14c 100644 (file)
@@ -6,12 +6,17 @@
 #![allow(dead_code)]
 
 mod assert {
-    use std::mem::BikeshedIntrinsicFrom;
+    use std::mem::{Assume, BikeshedIntrinsicFrom};
     pub struct Context;
 
     pub fn is_transmutable<Src, Dst>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+        Dst: BikeshedIntrinsicFrom<Src, Context, {
+            Assume::ALIGNMENT
+                .and(Assume::LIFETIMES)
+                .and(Assume::SAFETY)
+                .and(Assume::VALIDITY)
+        }>
     {}
 }
 
index 975118b99b7baf9edcda44b7cf367f76a6364764..e469c497353bb82bd13025044fbbdcd008c4bafb 100644 (file)
@@ -7,12 +7,12 @@
 #![allow(incomplete_features)]
 
 mod assert {
-    use std::mem::BikeshedIntrinsicFrom;
+    use std::mem::{Assume, BikeshedIntrinsicFrom};
     pub struct Context;
 
     pub fn is_transmutable<Src, Dst>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, true>
+        Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }>
     {}
 }
 
index e215799a232407d0c6c94972e97b40fc531b5c24..09c13cc4dc75985aebcca20b5bc7a8952b898855 100644 (file)
@@ -6,12 +6,19 @@
 #![allow(dead_code, incomplete_features, non_camel_case_types)]
 
 mod assert {
-    use std::mem::BikeshedIntrinsicFrom;
+    use std::mem::{Assume, BikeshedIntrinsicFrom};
     pub struct Context;
 
     pub fn is_maybe_transmutable<Src, Dst>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+        Dst: BikeshedIntrinsicFrom<Src, Context, {
+            Assume {
+                alignment: true,
+                lifetimes: true,
+                safety: true,
+                validity: true,
+            }
+        }>
     {}
 }
 
index 34a53c7a80c42a5101196fe179fd285b4e69aa3d..24c2abd698e704d95a9558a254c7569834b7ea2d 100644 (file)
@@ -6,12 +6,19 @@
 #![allow(dead_code, incomplete_features, non_camel_case_types)]
 
 mod assert {
-    use std::mem::BikeshedIntrinsicFrom;
+    use std::mem::{Assume, BikeshedIntrinsicFrom};
     pub struct Context;
 
     pub fn is_maybe_transmutable<Src, Dst>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+        Dst: BikeshedIntrinsicFrom<Src, Context, {
+            Assume {
+                alignment: true,
+                lifetimes: true,
+                safety: true,
+                validity: true,
+            }
+        }>
     {}
 }
 
index cec8e389f444e1437f78fa404ad857b8e164a28a..b1d5f71dcc585e97cd396c2f2bd30ee162e6f67f 100644 (file)
@@ -5,12 +5,19 @@
 #![allow(dead_code, incomplete_features, non_camel_case_types)]
 
 mod assert {
-    use std::mem::BikeshedIntrinsicFrom;
+    use std::mem::{Assume, BikeshedIntrinsicFrom};
     pub struct Context;
 
     pub fn is_maybe_transmutable<Src, Dst>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+        Dst: BikeshedIntrinsicFrom<Src, Context, {
+            Assume {
+                alignment: true,
+                lifetimes: true,
+                safety: true,
+                validity: true,
+            }
+        }>
     {}
 }
 
index 2ed01b159ab0bef5a70edf9bbd5677afc62cfd45..523bde85adfa9f524246f80cc6a9646e0d8e5b17 100644 (file)
@@ -1,34 +1,48 @@
 error[E0277]: `should_reject_repr_rust::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
-  --> $DIR/should_require_well_defined_layout.rs:23:48
+  --> $DIR/should_require_well_defined_layout.rs:30:48
    |
 LL |     assert::is_maybe_transmutable::<repr_rust, ()>();
    |                                                ^^ `should_reject_repr_rust::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<should_reject_repr_rust::repr_rust, assert::Context, true, true, true, true>` is not implemented for `()`
+   = help: the trait `BikeshedIntrinsicFrom<should_reject_repr_rust::repr_rust, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()`
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/should_require_well_defined_layout.rs:13:14
    |
-LL |     pub fn is_maybe_transmutable<Src, Dst>()
-   |            --------------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL |       pub fn is_maybe_transmutable<Src, Dst>()
+   |              --------------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_maybe_transmutable`
 
 error[E0277]: `u128` cannot be safely transmuted into `should_reject_repr_rust::repr_rust` in the defining scope of `assert::Context`.
-  --> $DIR/should_require_well_defined_layout.rs:24:43
+  --> $DIR/should_require_well_defined_layout.rs:31:43
    |
 LL |     assert::is_maybe_transmutable::<u128, repr_rust>();
    |                                           ^^^^^^^^^ `u128` cannot be safely transmuted into `should_reject_repr_rust::repr_rust` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, true, true, true, true>` is not implemented for `should_reject_repr_rust::repr_rust`
+   = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `should_reject_repr_rust::repr_rust`
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/should_require_well_defined_layout.rs:13:14
    |
-LL |     pub fn is_maybe_transmutable<Src, Dst>()
-   |            --------------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL |       pub fn is_maybe_transmutable<Src, Dst>()
+   |              --------------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_maybe_transmutable`
 
 error: aborting due to 2 previous errors
 
index c4757900f9c3e884e9309cda637e8392f1b10b0d..cabe544677e0fb195f5ea05be699d2e234ae7f93 100644 (file)
@@ -6,11 +6,16 @@
 #![allow(dead_code)]
 
 mod assert {
-    use std::mem::BikeshedIntrinsicFrom;
+    use std::mem::{Assume, BikeshedIntrinsicFrom};
 
     pub fn is_transmutable<Src, Dst, Context>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
+        Dst: BikeshedIntrinsicFrom<Src, Context, {
+            Assume::ALIGNMENT
+                .and(Assume::LIFETIMES)
+                .and(Assume::SAFETY)
+                .and(Assume::VALIDITY)
+        }>
     {}
 }
 
index 429f7211d17a86cfaa87434afd180be295246cb9..a823503d594e9715847ec46d38ecf76a78dd6b1a 100644 (file)
@@ -1,18 +1,24 @@
 error[E0277]: `Src` cannot be safely transmuted into `Dst` in the defining scope of `should_pad_variants::Context`.
-  --> $DIR/should_pad_variants.rs:39:36
+  --> $DIR/should_pad_variants.rs:44:36
    |
 LL |     assert::is_transmutable::<Src, Dst, Context>();
    |                                    ^^^ `Src` cannot be safely transmuted into `Dst` in the defining scope of `should_pad_variants::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<Src, should_pad_variants::Context, true, true, true, true>` is not implemented for `Dst`
+   = help: the trait `BikeshedIntrinsicFrom<Src, should_pad_variants::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `Dst`
 note: required by a bound in `is_transmutable`
   --> $DIR/should_pad_variants.rs:13:14
    |
-LL |     pub fn is_transmutable<Src, Dst, Context>()
-   |            --------------- required by a bound in this
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |       pub fn is_transmutable<Src, Dst, Context>()
+   |              --------------- required by a bound in this
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume::ALIGNMENT
+LL | |                 .and(Assume::LIFETIMES)
+LL | |                 .and(Assume::SAFETY)
+LL | |                 .and(Assume::VALIDITY)
+LL | |         }>
+   | |__________^ required by this bound in `is_transmutable`
 
 error: aborting due to previous error
 
index 2493d71554ad3d4dc03bc139da910d36eb37ad10..1007fdd795422f04ec863e5d7a825fa4df3ba304 100644 (file)
@@ -7,13 +7,12 @@
 #![allow(dead_code, incomplete_features, non_camel_case_types)]
 
 mod assert {
-    use std::mem::BikeshedIntrinsicFrom;
+    use std::mem::{Assume, BikeshedIntrinsicFrom};
     pub struct Context;
 
     pub fn is_maybe_transmutable<Src, Dst>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, false, false, true, true>
-        // validity IS assumed --------------------------------^^^^
+        Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY.and(Assume::VALIDITY) }>
     {}
 }
 
index e8138d0e046c55d2172188cf8b296749ad1419ff..a24dfccd3187d585b84f73e1c6239c01a2f7fec8 100644 (file)
@@ -5,12 +5,12 @@
 #![allow(dead_code, incomplete_features, non_camel_case_types)]
 
 mod assert {
-    use std::mem::BikeshedIntrinsicFrom;
+    use std::mem::{Assume, BikeshedIntrinsicFrom};
     pub struct Context;
 
     pub fn is_transmutable<Src, Dst>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, true>
+        Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }>
     {}
 }
 
index 99f58900817282f5ec0e7bf9c9227ae0a2c558ce..41f0cedc3a31197d10379976fe3a83afa169b1ee 100644 (file)
@@ -4,15 +4,15 @@ error[E0277]: `Superset` cannot be safely transmuted into `Subset` in the defini
 LL |     assert::is_transmutable::<Superset, Subset>();
    |                                         ^^^^^^ `Superset` cannot be safely transmuted into `Subset` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<Superset, assert::Context, false, false, false, true>` is not implemented for `Subset`
+   = help: the trait `BikeshedIntrinsicFrom<Superset, assert::Context, Assume { alignment: false, lifetimes: false, safety: true, validity: false }>` is not implemented for `Subset`
 note: required by a bound in `is_transmutable`
   --> $DIR/should_reject_contraction.rs:13:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error: aborting due to previous error
 
index 16160e29a5469ff863fee6c88705116908ce2cb6..43aaa6905fd4ff72e8d2c75f12621661da0aca5b 100644 (file)
@@ -5,13 +5,12 @@
 #![allow(dead_code, incomplete_features, non_camel_case_types)]
 
 mod assert {
-    use std::mem::BikeshedIntrinsicFrom;
+    use std::mem::{Assume, BikeshedIntrinsicFrom};
     pub struct Context;
 
     pub fn is_maybe_transmutable<Src, Dst>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, false, false, true, true>
-        // validity IS assumed --------------------------------^^^^
+        Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY.and(Assume::VALIDITY) }>
     {}
 }
 
index 5714e2bf320c5a44a8654016ec3d9f2c69beb044..4323f9740665fcfd818bc6b0fb1334b8016caef0 100644 (file)
@@ -1,34 +1,34 @@
 error[E0277]: `A` cannot be safely transmuted into `B` in the defining scope of `assert::Context`.
-  --> $DIR/should_reject_disjoint.rs:34:40
+  --> $DIR/should_reject_disjoint.rs:33:40
    |
 LL |     assert::is_maybe_transmutable::<A, B>();
    |                                        ^ `A` cannot be safely transmuted into `B` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<A, assert::Context, false, false, true, true>` is not implemented for `B`
+   = help: the trait `BikeshedIntrinsicFrom<A, assert::Context, Assume { alignment: false, lifetimes: false, safety: true, validity: true }>` is not implemented for `B`
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/should_reject_disjoint.rs:13:14
    |
 LL |     pub fn is_maybe_transmutable<Src, Dst>()
    |            --------------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY.and(Assume::VALIDITY) }>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
 
 error[E0277]: `B` cannot be safely transmuted into `A` in the defining scope of `assert::Context`.
-  --> $DIR/should_reject_disjoint.rs:35:40
+  --> $DIR/should_reject_disjoint.rs:34:40
    |
 LL |     assert::is_maybe_transmutable::<B, A>();
    |                                        ^ `B` cannot be safely transmuted into `A` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<B, assert::Context, false, false, true, true>` is not implemented for `A`
+   = help: the trait `BikeshedIntrinsicFrom<B, assert::Context, Assume { alignment: false, lifetimes: false, safety: true, validity: true }>` is not implemented for `A`
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/should_reject_disjoint.rs:13:14
    |
 LL |     pub fn is_maybe_transmutable<Src, Dst>()
    |            --------------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, true, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY.and(Assume::VALIDITY) }>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
 
 error: aborting due to 2 previous errors
 
index 58e399fb962259a166981e4e3adefb517eea0840..9cd4233ee74551aa742905c0875af9aedc90de87 100644 (file)
@@ -6,13 +6,13 @@
 #![allow(dead_code, incomplete_features, non_camel_case_types)]
 
 mod assert {
-    use std::mem::BikeshedIntrinsicFrom;
+    use std::mem::{Assume, BikeshedIntrinsicFrom};
     pub struct Context;
 
     pub fn is_transmutable<Src, Dst>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, true>
-        // validity is NOT assumed ----------------------------^^^^^
+        Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }>
+        // validity is NOT assumed --------------^^^^^^^^^^^^^^^^^^
     {}
 }
 
index 92689a5f828b475fee72a52c888da56f9b2a5373..e009888ae8d31d7f289921c6e9aa1e02c38ad4c1 100644 (file)
@@ -4,15 +4,15 @@ error[E0277]: `A` cannot be safely transmuted into `B` in the defining scope of
 LL |     assert::is_transmutable::<A, B>();
    |                                  ^ `A` cannot be safely transmuted into `B` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<A, assert::Context, false, false, false, true>` is not implemented for `B`
+   = help: the trait `BikeshedIntrinsicFrom<A, assert::Context, Assume { alignment: false, lifetimes: false, safety: true, validity: false }>` is not implemented for `B`
 note: required by a bound in `is_transmutable`
   --> $DIR/should_reject_intersecting.rs:14:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `B` cannot be safely transmuted into `A` in the defining scope of `assert::Context`.
   --> $DIR/should_reject_intersecting.rs:37:34
@@ -20,15 +20,15 @@ error[E0277]: `B` cannot be safely transmuted into `A` in the defining scope of
 LL |     assert::is_transmutable::<B, A>();
    |                                  ^ `B` cannot be safely transmuted into `A` in the defining scope of `assert::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<B, assert::Context, false, false, false, true>` is not implemented for `A`
+   = help: the trait `BikeshedIntrinsicFrom<B, assert::Context, Assume { alignment: false, lifetimes: false, safety: true, validity: false }>` is not implemented for `A`
 note: required by a bound in `is_transmutable`
   --> $DIR/should_reject_intersecting.rs:14:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, true>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error: aborting due to 2 previous errors
 
index 5a8c810494c58b77a16468d8544f1600beebb77e..8a41669c65e74ca88609fb61d99720d49cef8e9f 100644 (file)
@@ -7,12 +7,12 @@
 #![allow(dead_code)]
 
 mod assert {
-    use std::mem::BikeshedIntrinsicFrom;
+    use std::mem::{Assume, BikeshedIntrinsicFrom};
 
     pub fn is_transmutable<Src, Dst, Context>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, true>
-        // visibility IS assumed -------------------------------------^^^^
+        Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }>
+        // safety IS assumed --------------------^^^^^^^^^^^^^^^^^^
     {}
 }
 
index 77ab4fa6bff4b8ab8a595f46e4873db9cbf7a951..dd57b877d78c0a8d1234e49a0fc19f2a7710263f 100644 (file)
@@ -7,12 +7,12 @@
 #![allow(dead_code)]
 
 mod assert {
-    use std::mem::BikeshedIntrinsicFrom;
+    use std::mem::{Assume, BikeshedIntrinsicFrom};
 
     pub fn is_transmutable<Src, Dst, Context>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, true>
-        // visibility IS assumed -------------------------------------^^^^
+        Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }>
+        // safety IS assumed --------------------^^^^^^^^^^^^^^^^^^
     {}
 }
 
index 2421b24cbf07f472593fefd8cf148c5199ce2ab0..ebce8ce87dfda697a800d8f38728f4f5b767c5ae 100644 (file)
 #![allow(dead_code)]
 
 mod assert {
-    use std::mem::BikeshedIntrinsicFrom;
+    use std::mem::{Assume, BikeshedIntrinsicFrom};
 
     pub fn is_transmutable<Src, Dst, Context>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, true>
-        // visibility IS assumed -------------------------------------^^^^
+        Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }>
+        // safety IS assumed --------------------^^^^^^^^^^^^^^^^^^
     {}
 }
 
index 80b454fda560ff61bf1484de993f4314e0345282..546fcbaa3de2375d7b80c2e0ce2162ce5f6aa6e0 100644 (file)
@@ -8,12 +8,12 @@
 #![allow(dead_code)]
 
 mod assert {
-    use std::mem::BikeshedIntrinsicFrom;
+    use std::mem::{Assume, BikeshedIntrinsicFrom};
 
     pub fn is_transmutable<Src, Dst, Context>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, true>
-        // visibility IS assumed -------------------------------------^^^^
+        Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }>
+        // safety IS assumed --------------------^^^^^^^^^^^^^^^^^^
     {}
 }
 
index 7c53c91e4eda7b0457a215884f7b6ca1ab72bc11..b9b74d18338af0c1fbbcada00b77d90287757987 100644 (file)
@@ -8,12 +8,12 @@
 #![allow(dead_code)]
 
 mod assert {
-    use std::mem::BikeshedIntrinsicFrom;
+    use std::mem::{Assume, BikeshedIntrinsicFrom};
 
     pub fn is_transmutable<Src, Dst, Context>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, true>
-        // visibility IS assumed -------------------------------------^^^^
+        Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }>
+        // safety IS assumed --------------------^^^^^^^^^^^^^^^^^^
     {}
 }
 
index c3f298f01632568d95f5180cf9ab5d45a23445e5..5a0df09d492621a2845adfcb36524fb6ad169955 100644 (file)
@@ -11,8 +11,7 @@ mod assert {
 
     pub fn is_transmutable<Src, Dst, Context>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-        // visibility is NOT assumed ---------------------------------^^^^^
+        Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed
     {}
 }
 
index 73f6aece51eb539698eecf09d28ac515f35573ea..0f69630cc64fa589cc1f603586f957576f529c7b 100644 (file)
@@ -11,8 +11,7 @@ mod assert {
 
     pub fn is_transmutable<Src, Dst, Context>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-        // visibility is NOT assumed ---------------------------------^^^^^
+        Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed
     {}
 }
 
index 6d602601e96abc2e5e2ecaf73dd65fea80f8883e..9c8345a8e91a99df811df3e820b2fcf99828c183 100644 (file)
@@ -11,8 +11,7 @@ mod assert {
 
     pub fn is_transmutable<Src, Dst, Context>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-        // visibility is NOT assumed ---------------------------------^^^^^
+        Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed
     {}
 }
 
index 3f7d08d0ae24857138a7b3ba8dda9121f5057c3a..39b73302e364d22145f4b1a188efb5e1f86504ef 100644 (file)
@@ -1,5 +1,5 @@
 error[E0446]: private type `src::Zst` in public interface
-  --> $DIR/should_accept_if_src_has_unreachable_field.rs:23:9
+  --> $DIR/should_accept_if_src_has_unreachable_field.rs:22:9
    |
 LL |     #[repr(C)] pub(self) struct Zst; // <- unreachable type
    |                -------------------- `src::Zst` declared as private
index 1943fb8716a111596039cedf638cc834282a66ac..acf9f2302500a25216951a85b3955eb73621f551 100644 (file)
@@ -11,8 +11,7 @@ mod assert {
 
     pub fn is_transmutable<Src, Dst, Context>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-        // visibility is NOT assumed ---------------------------------^^^^^
+        Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed
     {}
 }
 
index e961984e189322ec4026609ed46276507682695c..76dc7f3407555c0a0513200ca6c371120fe30ef2 100644 (file)
@@ -1,11 +1,11 @@
 error[E0603]: struct `Src` is private
-  --> $DIR/should_accept_if_src_has_unreachable_ty.rs:38:36
+  --> $DIR/should_accept_if_src_has_unreachable_ty.rs:37:36
    |
 LL |     assert::is_transmutable::<src::Src, dst::Dst, Context>();
    |                                    ^^^ private struct
    |
 note: the struct `Src` is defined here
-  --> $DIR/should_accept_if_src_has_unreachable_ty.rs:23:16
+  --> $DIR/should_accept_if_src_has_unreachable_ty.rs:22:16
    |
 LL |     #[repr(C)] pub(self) struct Src {
    |                ^^^^^^^^^^^^^^^^^^^^
index fcf3f3a52780578a7fc5e986a351def78032d504..e8c3fbc9a0469d0baf76950f6d29a38a4cb11719 100644 (file)
@@ -10,8 +10,7 @@ mod assert {
 
     pub fn is_transmutable<Src, Dst, Context>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-        // visibility is NOT assumed ---------------------------------^^^^^
+        Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed
     {}
 }
 
index 85124019e7f0358dd9f38c82bf2b30165c92ba7c..d5d6d431b6f62454234d1fb751c51b95fa2e7e99 100644 (file)
@@ -1,18 +1,18 @@
 error[E0277]: `Src` cannot be safely transmuted into `Dst` in the defining scope of `test::Context`.
-  --> $DIR/should_reject_if_dst_has_private_field.rs:36:41
+  --> $DIR/should_reject_if_dst_has_private_field.rs:35:41
    |
 LL |     assert::is_transmutable::<src::Src, dst::Dst, Context>();
    |                                         ^^^^^^^^ `Src` cannot be safely transmuted into `Dst` in the defining scope of `test::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<Src, test::Context, false, false, false, false>` is not implemented for `Dst`
+   = help: the trait `BikeshedIntrinsicFrom<Src, test::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `Dst`
 note: required by a bound in `is_transmutable`
   --> $DIR/should_reject_if_dst_has_private_field.rs:13:14
    |
 LL |     pub fn is_transmutable<Src, Dst, Context>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error: aborting due to previous error
 
index 566b56467124f87624ce3a581d6d33f80c71cf19..47bca27abaa887711a5053ac78761fe88876261f 100644 (file)
@@ -10,8 +10,7 @@ mod assert {
 
     pub fn is_transmutable<Src, Dst, Context>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-        // visibility is NOT assumed ---------------------------------^^^^^
+        Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed
     {}
 }
 
index 0be564d93e2d8cb98d52b21ead007319f1c23e88..a1ca2ced53f291ec40e02bcfca4ad777e32bd1ab 100644 (file)
@@ -1,18 +1,18 @@
 error[E0277]: `Src` cannot be safely transmuted into `Dst` in the defining scope of `test::Context`.
-  --> $DIR/should_reject_if_dst_has_private_variant.rs:37:41
+  --> $DIR/should_reject_if_dst_has_private_variant.rs:36:41
    |
 LL |     assert::is_transmutable::<src::Src, dst::Dst, Context>();
    |                                         ^^^^^^^^ `Src` cannot be safely transmuted into `Dst` in the defining scope of `test::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<Src, test::Context, false, false, false, false>` is not implemented for `Dst`
+   = help: the trait `BikeshedIntrinsicFrom<Src, test::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `Dst`
 note: required by a bound in `is_transmutable`
   --> $DIR/should_reject_if_dst_has_private_variant.rs:13:14
    |
 LL |     pub fn is_transmutable<Src, Dst, Context>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error: aborting due to previous error
 
index 35fff5966c85b07bcbe9990e69532264291a7895..662c32af17aa888bcfd9feaa0985928a84f5f54d 100644 (file)
@@ -23,8 +23,7 @@ mod assert {
 
     pub fn is_transmutable<Src, Dst, Context>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-        // visibility is NOT assumed ---------------------------------^^^^^
+        Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed
     {}
 }
 
index 42799d803b0289958692e1f6c763b2ad3f4bc582..d7e21676fd385731ec3fb41d8d7228e8cf2a4072 100644 (file)
@@ -12,8 +12,7 @@ mod assert {
 
     pub fn is_transmutable<Src, Dst, Context>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-        // visibility is NOT assumed ---------------------------------^^^^^
+        Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed
     {}
 }
 
index 95c68d452010b9cb902bfcc6f3fe8b08af1dc742..4e648664d5abb6bf4bedf183cbba6f2b4ec8a13f 100644 (file)
@@ -1,18 +1,18 @@
 error[E0277]: `Src` cannot be safely transmuted into `Dst` in the defining scope of `test::Context`.
-  --> $DIR/should_reject_if_dst_has_unreachable_field.rs:38:41
+  --> $DIR/should_reject_if_dst_has_unreachable_field.rs:37:41
    |
 LL |     assert::is_transmutable::<src::Src, dst::Dst, Context>();
    |                                         ^^^^^^^^ `Src` cannot be safely transmuted into `Dst` in the defining scope of `test::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<Src, test::Context, false, false, false, false>` is not implemented for `Dst`
+   = help: the trait `BikeshedIntrinsicFrom<Src, test::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `Dst`
 note: required by a bound in `is_transmutable`
   --> $DIR/should_reject_if_dst_has_unreachable_field.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst, Context>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error: aborting due to previous error
 
index e13b32b30d9643134ed25951e542451c509f4baa..c7b59f15b99cc273546c9f9872d89bf62e52afa9 100644 (file)
@@ -12,8 +12,7 @@ mod assert {
 
     pub fn is_transmutable<Src, Dst, Context>()
     where
-        Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-        // visibility is NOT assumed ---------------------------------^^^^^
+        Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed
     {}
 }
 
index 3391839e39e023e86a6c3830ef46082d33ec606c..bd72d64ccd75f9e4e449724fca2bd3bfc959917a 100644 (file)
@@ -1,30 +1,30 @@
 error[E0603]: struct `Dst` is private
-  --> $DIR/should_reject_if_dst_has_unreachable_ty.rs:39:46
+  --> $DIR/should_reject_if_dst_has_unreachable_ty.rs:38:46
    |
 LL |     assert::is_transmutable::<src::Src, dst::Dst, Context>();
    |                                              ^^^ private struct
    |
 note: the struct `Dst` is defined here
-  --> $DIR/should_reject_if_dst_has_unreachable_ty.rs:32:16
+  --> $DIR/should_reject_if_dst_has_unreachable_ty.rs:31:16
    |
 LL |     #[repr(C)] pub(self) struct Dst {
    |                ^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `Src` cannot be safely transmuted into `Dst` in the defining scope of `test::Context`.
-  --> $DIR/should_reject_if_dst_has_unreachable_ty.rs:39:41
+  --> $DIR/should_reject_if_dst_has_unreachable_ty.rs:38:41
    |
 LL |     assert::is_transmutable::<src::Src, dst::Dst, Context>();
    |                                         ^^^^^^^^ `Src` cannot be safely transmuted into `Dst` in the defining scope of `test::Context`.
    |
-   = help: the trait `BikeshedIntrinsicFrom<Src, test::Context, false, false, false, false>` is not implemented for `Dst`
+   = help: the trait `BikeshedIntrinsicFrom<Src, test::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `Dst`
 note: required by a bound in `is_transmutable`
   --> $DIR/should_reject_if_dst_has_unreachable_ty.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst, Context>()
    |            --------------- required by a bound in this
 LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, false>
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error: aborting due to 2 previous errors
 
index 529f5f16c8fcddd89395c138b3cf829226999efc..27e6a603acd91689accbfe1fbe4b6e19139170e3 100644 (file)
@@ -22,13 +22,10 @@ LL |     Ok(Err(123_i32)?)
 error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
   --> $DIR/bad-interconversion.rs:11:12
    |
-LL | / fn option_to_result() -> Result<u64, String> {
-LL | |     Some(3)?;
-   | |            ^ use `.ok_or(...)?` to provide an error compatible with `Result<u64, String>`
-LL | |
-LL | |     Ok(10)
-LL | | }
-   | |_- this function returns a `Result`
+LL | fn option_to_result() -> Result<u64, String> {
+   | -------------------------------------------- this function returns a `Result`
+LL |     Some(3)?;
+   |            ^ use `.ok_or(...)?` to provide an error compatible with `Result<u64, String>`
    |
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<u64, String>`
    = help: the following other types implement trait `FromResidual<R>`:
@@ -38,12 +35,10 @@ LL | | }
 error[E0277]: the `?` operator can only be used on `Result`s in a function that returns `Result`
   --> $DIR/bad-interconversion.rs:17:31
    |
-LL | / fn control_flow_to_result() -> Result<u64, String> {
-LL | |     Ok(ControlFlow::Break(123)?)
-   | |                               ^ this `?` produces `ControlFlow<{integer}, Infallible>`, which is incompatible with `Result<u64, String>`
-LL | |
-LL | | }
-   | |_- this function returns a `Result`
+LL | fn control_flow_to_result() -> Result<u64, String> {
+   | -------------------------------------------------- this function returns a `Result`
+LL |     Ok(ControlFlow::Break(123)?)
+   |                               ^ this `?` produces `ControlFlow<{integer}, Infallible>`, which is incompatible with `Result<u64, String>`
    |
    = help: the trait `FromResidual<ControlFlow<{integer}, Infallible>>` is not implemented for `Result<u64, String>`
    = help: the following other types implement trait `FromResidual<R>`:
@@ -53,12 +48,10 @@ LL | | }
 error[E0277]: the `?` operator can only be used on `Option`s, not `Result`s, in a function that returns `Option`
   --> $DIR/bad-interconversion.rs:22:22
    |
-LL | / fn result_to_option() -> Option<u16> {
-LL | |     Some(Err("hello")?)
-   | |                      ^ use `.ok()?` if you want to discard the `Result<Infallible, &str>` error information
-LL | |
-LL | | }
-   | |_- this function returns an `Option`
+LL | fn result_to_option() -> Option<u16> {
+   | ------------------------------------ this function returns an `Option`
+LL |     Some(Err("hello")?)
+   |                      ^ use `.ok()?` if you want to discard the `Result<Infallible, &str>` error information
    |
    = help: the trait `FromResidual<Result<Infallible, &str>>` is not implemented for `Option<u16>`
    = help: the following other types implement trait `FromResidual<R>`:
@@ -68,12 +61,10 @@ LL | | }
 error[E0277]: the `?` operator can only be used on `Option`s in a function that returns `Option`
   --> $DIR/bad-interconversion.rs:27:33
    |
-LL | / fn control_flow_to_option() -> Option<u64> {
-LL | |     Some(ControlFlow::Break(123)?)
-   | |                                 ^ this `?` produces `ControlFlow<{integer}, Infallible>`, which is incompatible with `Option<u64>`
-LL | |
-LL | | }
-   | |_- this function returns an `Option`
+LL | fn control_flow_to_option() -> Option<u64> {
+   | ------------------------------------------ this function returns an `Option`
+LL |     Some(ControlFlow::Break(123)?)
+   |                                 ^ this `?` produces `ControlFlow<{integer}, Infallible>`, which is incompatible with `Option<u64>`
    |
    = help: the trait `FromResidual<ControlFlow<{integer}, Infallible>>` is not implemented for `Option<u64>`
    = help: the following other types implement trait `FromResidual<R>`:
@@ -83,12 +74,10 @@ LL | | }
 error[E0277]: the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow`
   --> $DIR/bad-interconversion.rs:32:39
    |
-LL | / fn result_to_control_flow() -> ControlFlow<String> {
-LL | |     ControlFlow::Continue(Err("hello")?)
-   | |                                       ^ this `?` produces `Result<Infallible, &str>`, which is incompatible with `ControlFlow<String>`
-LL | |
-LL | | }
-   | |_- this function returns a `ControlFlow`
+LL | fn result_to_control_flow() -> ControlFlow<String> {
+   | -------------------------------------------------- this function returns a `ControlFlow`
+LL |     ControlFlow::Continue(Err("hello")?)
+   |                                       ^ this `?` produces `Result<Infallible, &str>`, which is incompatible with `ControlFlow<String>`
    |
    = help: the trait `FromResidual<Result<Infallible, &str>>` is not implemented for `ControlFlow<String>`
    = help: the trait `FromResidual` is implemented for `ControlFlow<B, C>`
@@ -96,13 +85,10 @@ LL | | }
 error[E0277]: the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow`
   --> $DIR/bad-interconversion.rs:37:12
    |
-LL | / fn option_to_control_flow() -> ControlFlow<u64> {
-LL | |     Some(3)?;
-   | |            ^ this `?` produces `Option<Infallible>`, which is incompatible with `ControlFlow<u64>`
-LL | |
-LL | |     ControlFlow::Break(10)
-LL | | }
-   | |_- this function returns a `ControlFlow`
+LL | fn option_to_control_flow() -> ControlFlow<u64> {
+   | ----------------------------------------------- this function returns a `ControlFlow`
+LL |     Some(3)?;
+   |            ^ this `?` produces `Option<Infallible>`, which is incompatible with `ControlFlow<u64>`
    |
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `ControlFlow<u64>`
    = help: the trait `FromResidual` is implemented for `ControlFlow<B, C>`
@@ -110,13 +96,10 @@ LL | | }
 error[E0277]: the `?` operator in a function that returns `ControlFlow<B, _>` can only be used on other `ControlFlow<B, _>`s (with the same Break type)
   --> $DIR/bad-interconversion.rs:43:29
    |
-LL | / fn control_flow_to_control_flow() -> ControlFlow<i64> {
-LL | |     ControlFlow::Break(4_u8)?;
-   | |                             ^ this `?` produces `ControlFlow<u8, Infallible>`, which is incompatible with `ControlFlow<i64>`
-LL | |
-LL | |     ControlFlow::Continue(())
-LL | | }
-   | |_- this function returns a `ControlFlow`
+LL | fn control_flow_to_control_flow() -> ControlFlow<i64> {
+   | ----------------------------------------------------- this function returns a `ControlFlow`
+LL |     ControlFlow::Break(4_u8)?;
+   |                             ^ this `?` produces `ControlFlow<u8, Infallible>`, which is incompatible with `ControlFlow<i64>`
    |
    = help: the trait `FromResidual<ControlFlow<u8, Infallible>>` is not implemented for `ControlFlow<i64>`
    = note: unlike `Result`, there's no `From`-conversion performed for `ControlFlow`
index ae5c3ad628281c3968e19bcbf79b15b1a32f23f0..fabc1ff2c762ec34a85441720de9a79fa4c19a97 100644 (file)
@@ -1,13 +1,11 @@
 error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
   --> $DIR/option-to-result.rs:5:6
    |
-LL | / fn test_result() -> Result<(),()> {
-LL | |     let a:Option<()> = Some(());
-LL | |     a?;
-   | |      ^ use `.ok_or(...)?` to provide an error compatible with `Result<(), ()>`
-LL | |     Ok(())
-LL | | }
-   | |_- this function returns a `Result`
+LL | fn test_result() -> Result<(),()> {
+   | --------------------------------- this function returns a `Result`
+LL |     let a:Option<()> = Some(());
+LL |     a?;
+   |      ^ use `.ok_or(...)?` to provide an error compatible with `Result<(), ()>`
    |
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<(), ()>`
    = help: the following other types implement trait `FromResidual<R>`:
@@ -17,13 +15,11 @@ LL | | }
 error[E0277]: the `?` operator can only be used on `Option`s, not `Result`s, in a function that returns `Option`
   --> $DIR/option-to-result.rs:11:6
    |
-LL | / fn test_option() -> Option<i32>{
-LL | |     let a:Result<i32, i32> = Ok(5);
-LL | |     a?;
-   | |      ^ use `.ok()?` if you want to discard the `Result<Infallible, i32>` error information
-LL | |     Some(5)
-LL | | }
-   | |_- this function returns an `Option`
+LL | fn test_option() -> Option<i32>{
+   | ------------------------------- this function returns an `Option`
+LL |     let a:Result<i32, i32> = Ok(5);
+LL |     a?;
+   |      ^ use `.ok()?` if you want to discard the `Result<Infallible, i32>` error information
    |
    = help: the trait `FromResidual<Result<Infallible, i32>>` is not implemented for `Option<i32>`
    = help: the following other types implement trait `FromResidual<R>`:
index a6badd1903885cfaf9fb503a22de18eb415c9095..9ee540c79fdda6ace10d8ec0b64a889ba486cacf 100644 (file)
@@ -1,51 +1,44 @@
 error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> $DIR/try-on-option-diagnostics.rs:7:6
    |
-LL | / fn a_function() -> u32 {
-LL | |     let x: Option<u32> = None;
-LL | |     x?;
-   | |      ^ cannot use the `?` operator in a function that returns `u32`
-LL | |     22
-LL | | }
-   | |_- this function should return `Result` or `Option` to accept `?`
+LL | fn a_function() -> u32 {
+   | ---------------------- this function should return `Result` or `Option` to accept `?`
+LL |     let x: Option<u32> = None;
+LL |     x?;
+   |      ^ cannot use the `?` operator in a function that returns `u32`
    |
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `u32`
 
 error[E0277]: the `?` operator can only be used in a closure that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> $DIR/try-on-option-diagnostics.rs:14:10
    |
-LL |       let a_closure = || {
-   |  _____________________-
-LL | |         let x: Option<u32> = None;
-LL | |         x?;
-   | |          ^ cannot use the `?` operator in a closure that returns `{integer}`
-LL | |         22
-LL | |     };
-   | |_____- this function should return `Result` or `Option` to accept `?`
+LL |     let a_closure = || {
+   |                     -- this function should return `Result` or `Option` to accept `?`
+LL |         let x: Option<u32> = None;
+LL |         x?;
+   |          ^ cannot use the `?` operator in a closure that returns `{integer}`
    |
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `{integer}`
 
 error[E0277]: the `?` operator can only be used in a method that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> $DIR/try-on-option-diagnostics.rs:26:14
    |
-LL | /         fn a_method() {
-LL | |             let x: Option<u32> = None;
-LL | |             x?;
-   | |              ^ cannot use the `?` operator in a method that returns `()`
-LL | |         }
-   | |_________- this function should return `Result` or `Option` to accept `?`
+LL |         fn a_method() {
+   |         ------------- this function should return `Result` or `Option` to accept `?`
+LL |             let x: Option<u32> = None;
+LL |             x?;
+   |              ^ cannot use the `?` operator in a method that returns `()`
    |
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `()`
 
 error[E0277]: the `?` operator can only be used in a trait method that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> $DIR/try-on-option-diagnostics.rs:39:14
    |
-LL | /         fn a_trait_method() {
-LL | |             let x: Option<u32> = None;
-LL | |             x?;
-   | |              ^ cannot use the `?` operator in a trait method that returns `()`
-LL | |         }
-   | |_________- this function should return `Result` or `Option` to accept `?`
+LL |         fn a_trait_method() {
+   |         ------------------- this function should return `Result` or `Option` to accept `?`
+LL |             let x: Option<u32> = None;
+LL |             x?;
+   |              ^ cannot use the `?` operator in a trait method that returns `()`
    |
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `()`
 
index ba85a7cada2329668ec3bebd3a3f3bb3a4fb05ba..fad6a1fe8237b925ddd144ac937760a4f2eab81a 100644 (file)
@@ -1,13 +1,11 @@
 error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
   --> $DIR/try-on-option.rs:5:6
    |
-LL | / fn foo() -> Result<u32, ()> {
-LL | |     let x: Option<u32> = None;
-LL | |     x?;
-   | |      ^ use `.ok_or(...)?` to provide an error compatible with `Result<u32, ()>`
-LL | |     Ok(22)
-LL | | }
-   | |_- this function returns a `Result`
+LL | fn foo() -> Result<u32, ()> {
+   | --------------------------- this function returns a `Result`
+LL |     let x: Option<u32> = None;
+LL |     x?;
+   |      ^ use `.ok_or(...)?` to provide an error compatible with `Result<u32, ()>`
    |
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<u32, ()>`
    = help: the following other types implement trait `FromResidual<R>`:
@@ -17,13 +15,11 @@ LL | | }
 error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> $DIR/try-on-option.rs:11:6
    |
-LL | / fn bar() -> u32 {
-LL | |     let x: Option<u32> = None;
-LL | |     x?;
-   | |      ^ cannot use the `?` operator in a function that returns `u32`
-LL | |     22
-LL | | }
-   | |_- this function should return `Result` or `Option` to accept `?`
+LL | fn bar() -> u32 {
+   | --------------- this function should return `Result` or `Option` to accept `?`
+LL |     let x: Option<u32> = None;
+LL |     x?;
+   |      ^ cannot use the `?` operator in a function that returns `u32`
    |
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `u32`
 
index ad55f40b5b6382703bffae17bf321c29d55439c7..7cd38e0cf95eaf339f0dcafb31d7de20b160ebb4 100644 (file)
@@ -1,15 +1,11 @@
 error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> $DIR/try-operator-on-main.rs:7:31
    |
-LL | / fn main() {
-LL | |     // error for a `Try` type on a non-`Try` fn
-LL | |     std::fs::File::open("foo")?;
-   | |                               ^ cannot use the `?` operator in a function that returns `()`
-LL | |
-...  |
-LL | |     try_trait_generic::<()>();
-LL | | }
-   | |_- this function should return `Result` or `Option` to accept `?`
+LL | fn main() {
+   | --------- this function should return `Result` or `Option` to accept `?`
+LL |     // error for a `Try` type on a non-`Try` fn
+LL |     std::fs::File::open("foo")?;
+   |                               ^ cannot use the `?` operator in a function that returns `()`
    |
    = help: the trait `FromResidual<Result<Infallible, std::io::Error>>` is not implemented for `()`
 
@@ -24,17 +20,11 @@ LL |     ()?;
 error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> $DIR/try-operator-on-main.rs:10:7
    |
-LL | / fn main() {
-LL | |     // error for a `Try` type on a non-`Try` fn
-LL | |     std::fs::File::open("foo")?;
-LL | |
-LL | |     // a non-`Try` type on a non-`Try` fn
-LL | |     ()?;
-   | |       ^ cannot use the `?` operator in a function that returns `()`
-...  |
-LL | |     try_trait_generic::<()>();
-LL | | }
-   | |_- this function should return `Result` or `Option` to accept `?`
+LL | fn main() {
+   | --------- this function should return `Result` or `Option` to accept `?`
+...
+LL |     ()?;
+   |       ^ cannot use the `?` operator in a function that returns `()`
    |
    = help: the trait `FromResidual<_>` is not implemented for `()`
 
index 968cb75db7633582680eee04cd997990409bbc1e..f3a547fa238273c4cdd26ec2a6f21bba0c75b673 100644 (file)
@@ -19,7 +19,7 @@ LL |     pub fn push(&mut self, value: T) {
 help: remove the extra argument
    |
 LL |         groups.push(/* (Vec<String>, Vec<Process>) */);
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to previous error
 
index 828ae21b4808d5299c169d637da9669834e3637d..a2686ab9440e8b5e2587c335979e639ebc1da2ac 100644 (file)
@@ -16,7 +16,7 @@ LL |     (|| {})(|| {
 help: remove the extra argument
    |
 LL |     (|| {})();
-   |     ~~~~~~~~~
+   |            ~~
 
 error: aborting due to previous error
 
index 006253f84320802f6582a962b9c2ca5c6fe78509..eb58ee73ca21b4f3eb8f9d9ce83c2a6b71fff389 100644 (file)
@@ -12,7 +12,7 @@ LL |     V(u8)
 help: provide the argument
    |
 LL |     <E>::V(/* u8 */);
-   |     ~~~~~~~~~~~~~~~~
+   |           ~~~~~~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/enum-variant-priority-higher-than-other-inherent.rs:22:17
index fcac6c495c4b2705eeb71a01775c56bcc789eca3..de578ca93ed59b827d3ab48bb0086eb619d77c03 100644 (file)
@@ -21,7 +21,7 @@ LL |     pub fn with_capacity(capacity: usize) -> Self {
 help: remove the extra argument
    |
 LL |     let x: Vec::with_capacity(10);
-   |            ~~~~~~~~~~~~~~~~~~~~~~
+   |                              ~~~~
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/typeck/assign-non-lval-needs-deref.rs b/src/test/ui/typeck/assign-non-lval-needs-deref.rs
new file mode 100644 (file)
index 0000000..c979d76
--- /dev/null
@@ -0,0 +1,19 @@
+// issue #101376
+
+use std::ops::AddAssign;
+struct Foo;
+
+impl AddAssign<()> for Foo {
+    fn add_assign(&mut self, _: ()) {}
+}
+
+impl AddAssign<()> for &mut Foo {
+    fn add_assign(&mut self, _: ()) {}
+}
+
+fn main() {
+    (&mut Foo) += ();
+    //~^ ERROR invalid left-hand side of assignment
+    //~| NOTE cannot assign to this expression
+    //~| HELP consider dereferencing the left-hand side of this operation
+}
diff --git a/src/test/ui/typeck/assign-non-lval-needs-deref.stderr b/src/test/ui/typeck/assign-non-lval-needs-deref.stderr
new file mode 100644 (file)
index 0000000..ee83b14
--- /dev/null
@@ -0,0 +1,16 @@
+error[E0067]: invalid left-hand side of assignment
+  --> $DIR/assign-non-lval-needs-deref.rs:15:16
+   |
+LL |     (&mut Foo) += ();
+   |     ---------- ^^
+   |     |
+   |     cannot assign to this expression
+   |
+help: consider dereferencing the left-hand side of this operation
+   |
+LL |     *(&mut Foo) += ();
+   |     +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0067`.
diff --git a/src/test/ui/typeck/point-at-type-param-in-path-expr.rs b/src/test/ui/typeck/point-at-type-param-in-path-expr.rs
new file mode 100644 (file)
index 0000000..9a21536
--- /dev/null
@@ -0,0 +1,6 @@
+fn foo<T: std::fmt::Display>() {}
+
+fn main() {
+    let x = foo::<()>;
+    //~^ ERROR `()` doesn't implement `std::fmt::Display`
+}
diff --git a/src/test/ui/typeck/point-at-type-param-in-path-expr.stderr b/src/test/ui/typeck/point-at-type-param-in-path-expr.stderr
new file mode 100644 (file)
index 0000000..1feaa05
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0277]: `()` doesn't implement `std::fmt::Display`
+  --> $DIR/point-at-type-param-in-path-expr.rs:4:19
+   |
+LL |     let x = foo::<()>;
+   |                   ^^ `()` cannot be formatted with the default formatter
+   |
+   = help: the trait `std::fmt::Display` is not implemented for `()`
+   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+note: required by a bound in `foo`
+  --> $DIR/point-at-type-param-in-path-expr.rs:1:11
+   |
+LL | fn foo<T: std::fmt::Display>() {}
+   |           ^^^^^^^^^^^^^^^^^ required by this bound in `foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
index 703032a83223154ff916a6292876b5497bae7819..b734bcd4eb0485cda5c519c6bd479fd1b2cad936 100644 (file)
@@ -12,7 +12,7 @@ LL | fn l(_a: Vec<u8>) {}
 help: remove the extra argument
    |
 LL |     l(vec![])
-   |
+   |      ~~~~~~~~
 
 error: aborting due to previous error
 
index f72082d53016729e3b45b3f68205382ac45b016e..ea94bcbc2903058476c441be1bab37ab14807f52 100644 (file)
@@ -12,7 +12,7 @@ LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
 help: remove the extra argument
    |
 LL |     let _ = Some(3);
-   |             ~~~~~~~
+   |                 ~~~
 
 error[E0061]: this enum variant takes 1 argument but 3 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:7:13
@@ -30,7 +30,7 @@ LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
 help: remove the extra arguments
    |
 LL |     let _ = Ok(3);
-   |             ~~~~~
+   |               ~~~
 
 error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:8:13
@@ -46,7 +46,7 @@ LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
 help: provide the argument
    |
 LL |     let _ = Ok(/* value */);
-   |             ~~~~~~~~~~~~~~~
+   |               ~~~~~~~~~~~~~
 
 error[E0061]: this struct takes 1 argument but 0 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:9:13
@@ -62,7 +62,7 @@ LL | struct Wrapper(i32);
 help: provide the argument
    |
 LL |     let _ = Wrapper(/* i32 */);
-   |             ~~~~~~~~~~~~~~~~~~
+   |                    ~~~~~~~~~~~
 
 error[E0061]: this struct takes 1 argument but 2 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:10:13
@@ -78,7 +78,7 @@ LL | struct Wrapper(i32);
 help: remove the extra argument
    |
 LL |     let _ = Wrapper(5);
-   |             ~~~~~~~~~~
+   |                    ~~~
 
 error[E0061]: this struct takes 2 arguments but 0 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:11:13
@@ -94,7 +94,7 @@ LL | struct DoubleWrapper(i32, i32);
 help: provide the arguments
    |
 LL |     let _ = DoubleWrapper(/* i32 */, /* i32 */);
-   |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                          ~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0061]: this struct takes 2 arguments but 1 argument was supplied
   --> $DIR/struct-enum-wrong-args.rs:12:13
@@ -110,7 +110,7 @@ LL | struct DoubleWrapper(i32, i32);
 help: provide the argument
    |
 LL |     let _ = DoubleWrapper(5, /* i32 */);
-   |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                          ~~~~~~~~~~~~~~
 
 error[E0061]: this struct takes 2 arguments but 3 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:13:13
@@ -126,7 +126,7 @@ LL | struct DoubleWrapper(i32, i32);
 help: remove the extra argument
    |
 LL |     let _ = DoubleWrapper(5, 2);
-   |             ~~~~~~~~~~~~~~~~~~~
+   |                          ~~~~~~
 
 error: aborting due to 8 previous errors
 
index 939b3c5223c484c1209ae9bac1c22415f4965493..ec86213f8629df02bc4efa51d6d4bbdb0469eacc 100644 (file)
@@ -3,6 +3,7 @@
 fn main() {
     <i32 as Add<u32>>::add(1, 2);
     //~^ ERROR cannot add `u32` to `i32`
+    //~| ERROR cannot add `u32` to `i32`
     <i32 as Add<i32>>::add(1u32, 2);
     //~^ ERROR mismatched types
     <i32 as Add<i32>>::add(1, 2u32);
index f08c81bc1e937f7bada03d02c80886a7d277c649..eaab6ff3d9a0419227d6ad01307049dbebcc021a 100644 (file)
@@ -19,7 +19,7 @@ LL |     <i32 as Add<u32>>::add(1, 2);
            and 48 others
 
 error[E0308]: mismatched types
-  --> $DIR/ufcs-qpath-self-mismatch.rs:6:28
+  --> $DIR/ufcs-qpath-self-mismatch.rs:7:28
    |
 LL |     <i32 as Add<i32>>::add(1u32, 2);
    |     ---------------------- ^^^^ expected `i32`, found `u32`
@@ -37,7 +37,7 @@ LL |     <i32 as Add<i32>>::add(1i32, 2);
    |                             ~~~
 
 error[E0308]: mismatched types
-  --> $DIR/ufcs-qpath-self-mismatch.rs:8:31
+  --> $DIR/ufcs-qpath-self-mismatch.rs:9:31
    |
 LL |     <i32 as Add<i32>>::add(1, 2u32);
    |     ----------------------    ^^^^ expected `i32`, found `u32`
@@ -54,7 +54,25 @@ help: change the type of the numeric literal from `u32` to `i32`
 LL |     <i32 as Add<i32>>::add(1, 2i32);
    |                                ~~~
 
-error: aborting due to 3 previous errors
+error[E0277]: cannot add `u32` to `i32`
+  --> $DIR/ufcs-qpath-self-mismatch.rs:4:5
+   |
+LL |     <i32 as Add<u32>>::add(1, 2);
+   |     ^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u32`
+   |
+   = help: the trait `Add<u32>` is not implemented for `i32`
+   = help: the following other types implement trait `Add<Rhs>`:
+             <&'a f32 as Add<f32>>
+             <&'a f64 as Add<f64>>
+             <&'a i128 as Add<i128>>
+             <&'a i16 as Add<i16>>
+             <&'a i32 as Add<i32>>
+             <&'a i64 as Add<i64>>
+             <&'a i8 as Add<i8>>
+             <&'a isize as Add<isize>>
+           and 48 others
+
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0277, E0308.
 For more information about an error, try `rustc --explain E0277`.
index 18e133957ba37fa5aebb201743715c2eb3b91caf..9833304c636b1b0b36c9642915d1b78ddf6c274f 100644 (file)
@@ -6,7 +6,7 @@ LL |     let x = call_it(&square, 22);
    |             |
    |             required by a bound introduced by this call
    |
-   = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
+   = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for fn item `for<'r> unsafe fn(&'r isize) -> isize {square}`
    = note: unsafe function cannot be called generically without an unsafe block
 note: required by a bound in `call_it`
   --> $DIR/unboxed-closures-unsafe-extern-fn.rs:9:15
@@ -22,7 +22,7 @@ LL |     let y = call_it_mut(&mut square, 22);
    |             |
    |             required by a bound introduced by this call
    |
-   = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
+   = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for fn item `for<'r> unsafe fn(&'r isize) -> isize {square}`
    = note: unsafe function cannot be called generically without an unsafe block
 note: required by a bound in `call_it_mut`
   --> $DIR/unboxed-closures-unsafe-extern-fn.rs:12:19
@@ -38,7 +38,7 @@ LL |     let z = call_it_once(square, 22);
    |             |
    |             required by a bound introduced by this call
    |
-   = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
+   = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for fn item `for<'r> unsafe fn(&'r isize) -> isize {square}`
    = note: unsafe function cannot be called generically without an unsafe block
 note: required by a bound in `call_it_once`
   --> $DIR/unboxed-closures-unsafe-extern-fn.rs:15:20
index 77c176de625ca95e456b7d3af0dd3a7b3e631b7e..54c92e0cd040cad8f592f9b442cf3bdb8c13e1f8 100644 (file)
@@ -6,7 +6,7 @@ LL |     let x = call_it(&square, 22);
    |             |
    |             required by a bound introduced by this call
    |
-   = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+   = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for fn item `for<'r> extern "C" fn(&'r isize) -> isize {square}`
 note: required by a bound in `call_it`
   --> $DIR/unboxed-closures-wrong-abi.rs:9:15
    |
@@ -21,7 +21,7 @@ LL |     let y = call_it_mut(&mut square, 22);
    |             |
    |             required by a bound introduced by this call
    |
-   = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+   = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for fn item `for<'r> extern "C" fn(&'r isize) -> isize {square}`
 note: required by a bound in `call_it_mut`
   --> $DIR/unboxed-closures-wrong-abi.rs:12:19
    |
@@ -36,7 +36,7 @@ LL |     let z = call_it_once(square, 22);
    |             |
    |             required by a bound introduced by this call
    |
-   = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+   = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for fn item `for<'r> extern "C" fn(&'r isize) -> isize {square}`
 note: required by a bound in `call_it_once`
   --> $DIR/unboxed-closures-wrong-abi.rs:15:20
    |
index c826af3c4c38f0f263f775f1840ceadc377d81c0..2fedb5b92c2896a4afc2a364bb8e53ccc2b5678c 100644 (file)
@@ -6,7 +6,7 @@ LL |     let x = call_it(&square, 22);
    |             |
    |             required by a bound introduced by this call
    |
-   = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
+   = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}`
    = note: unsafe function cannot be called generically without an unsafe block
 note: required by a bound in `call_it`
   --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:10:15
@@ -22,7 +22,7 @@ LL |     let y = call_it_mut(&mut square, 22);
    |             |
    |             required by a bound introduced by this call
    |
-   = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
+   = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}`
    = note: unsafe function cannot be called generically without an unsafe block
 note: required by a bound in `call_it_mut`
   --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:13:19
@@ -38,7 +38,7 @@ LL |     let z = call_it_once(square, 22);
    |             |
    |             required by a bound introduced by this call
    |
-   = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
+   = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}`
    = note: unsafe function cannot be called generically without an unsafe block
 note: required by a bound in `call_it_once`
   --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:16:20
index f5491552a45d2ed89134cab0d3b53c6adbde58f7..71bbdf5dec7696600f3a02ee2544624d0c097244 100644 (file)
@@ -5,11 +5,8 @@ LL |     &X(*Y)
    |        ^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `[u8]`
+   = note: all function arguments must have a statically known size
    = help: unsized fn params are gated as an unstable feature
-help: function arguments must have a statically known size, borrowed types always have a known size
-   |
-LL |     &X(&*Y)
-   |        +
 
 error: aborting due to previous error
 
index 4ed54cecce3ce9ab6ff058781f4c8a500ee6b8b5..646e9a0b9ea8354cc409d05f10e8dc752c5de78e 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 4ed54cecce3ce9ab6ff058781f4c8a500ee6b8b5
+Subproject commit 646e9a0b9ea8354cc409d05f10e8dc752c5de78e
index 15e00c7d7ce4c3e56faea6be845039c50dc6f034..2bc275ceff0be50cad4cabffd08cbe40e1751958 100644 (file)
@@ -66,7 +66,7 @@ Starting with an `expr`, you can check whether it is calling a specific method
 impl<'tcx> LateLintPass<'tcx> for MyStructLint {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
         // Check our expr is calling a method
-        if let hir::ExprKind::MethodCall(path, _, [_self_arg, ..]) = &expr.kind
+        if let hir::ExprKind::MethodCall(path, _, _self_arg, ..) = &expr.kind
             // Check the name of this method is `some_method`
             && path.ident.name == sym!(some_method)
             // Optionally, check the type of the self argument.
index 6a6554f968b334e5ca3ce1802ff475440df66090..7cd198ace86c0e3ff3f3edf4c9b44dc862b68429 100644 (file)
@@ -43,7 +43,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
             && matches!(cx.tcx.get_diagnostic_name(macro_call.def_id), Some(sym::assert_macro))
             && let Some((condition, panic_expn)) = find_assert_args(cx, e, macro_call.expn)
             && matches!(panic_expn, PanicExpn::Empty)
-            && let ExprKind::MethodCall(method_segment, [recv], _) = condition.kind
+            && let ExprKind::MethodCall(method_segment, recv, [], _) = condition.kind
             && let result_type_with_refs = cx.typeck_results().expr_ty(recv)
             && let result_type = result_type_with_refs.peel_refs()
             && is_type_diagnostic_item(cx, result_type, sym::Result)
index ad206b5fb304f04e3e79a465eff631cadae1da64..d9e2c9c8578f711f2a4f3c2a6185edbfafecefb8 100644 (file)
@@ -55,7 +55,7 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
             // do not lint if the closure is called using an iterator (see #1141)
             if_chain! {
                 if let Some(parent) = get_parent_expr(self.cx, expr);
-                if let ExprKind::MethodCall(_, [self_arg, ..], _) = &parent.kind;
+                if let ExprKind::MethodCall(_, self_arg, ..) = &parent.kind;
                 let caller = self.cx.typeck_results().expr_ty(self_arg);
                 if let Some(iter_id) = self.cx.tcx.get_diagnostic_item(sym::Iterator);
                 if implements_trait(self.cx, caller, iter_id, &[]);
@@ -117,7 +117,8 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
                             );
                         }
                     } else {
-                        let span = block.expr.as_ref().map_or_else(|| block.stmts[0].span, |e| e.span);
+                        let span =
+                            block.expr.as_ref().map_or_else(|| block.stmts[0].span, |e| e.span);
                         if span.from_expansion() || expr.span.from_expansion() {
                             return;
                         }
index 6eb78d21e826629e7c928153ffe4c007e4c1fc32..656d639f0efd9838c272c92d6aa0e5d2e3fa7179 100644 (file)
@@ -270,8 +270,8 @@ fn simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<String> {
                 ))
             })
         },
-        ExprKind::MethodCall(path, args, _) if args.len() == 1 => {
-            let type_of_receiver = cx.typeck_results().expr_ty(&args[0]);
+        ExprKind::MethodCall(path, receiver, [], _) => {
+            let type_of_receiver = cx.typeck_results().expr_ty(receiver);
             if !is_type_diagnostic_item(cx, type_of_receiver, sym::Option)
                 && !is_type_diagnostic_item(cx, type_of_receiver, sym::Result)
             {
@@ -285,7 +285,7 @@ fn simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<String> {
                     let path: &str = path.ident.name.as_str();
                     a == path
                 })
-                .and_then(|(_, neg_method)| Some(format!("{}.{}()", snippet_opt(cx, args[0].span)?, neg_method)))
+                .and_then(|(_, neg_method)| Some(format!("{}.{}()", snippet_opt(cx, receiver.span)?, neg_method)))
         },
         _ => None,
     }
index 6426e8c25ac1c728de493d03ad475bdbc4256651..3f1edabe6c5040621bb2903b0df2e2ea07843270 100644 (file)
@@ -20,7 +20,7 @@ pub(super) fn check(
     if meets_msrv(msrv, msrvs::UNSIGNED_ABS)
         && let ty::Int(from) = cast_from.kind()
         && let ty::Uint(to) = cast_to.kind()
-        && let ExprKind::MethodCall(method_path, args, _) = cast_expr.kind
+        && let ExprKind::MethodCall(method_path, receiver, ..) = cast_expr.kind
         && method_path.ident.name.as_str() == "abs"
     {
         let span = if from.bit_width() == to.bit_width() {
@@ -37,7 +37,7 @@ pub(super) fn check(
             span,
             &format!("casting the result of `{cast_from}::abs()` to {cast_to}"),
             "replace with",
-            format!("{}.unsigned_abs()", Sugg::hir(cx, &args[0], "..").maybe_par()),
+            format!("{}.unsigned_abs()", Sugg::hir(cx, receiver, "..").maybe_par()),
             Applicability::MachineApplicable,
         );
     }
index 64f87c80f8d147a5e3e21aed776582434d465fee..406547a4454e6a1abeb91b894a599f36c9109191 100644 (file)
@@ -44,7 +44,7 @@ fn apply_reductions(cx: &LateContext<'_>, nbits: u64, expr: &Expr<'_>, signed: b
                 .saturating_sub(constant_int(cx, right).map_or(0, |s| u64::try_from(s).expect("shift too high"))),
             _ => nbits,
         },
-        ExprKind::MethodCall(method, [left, right], _) => {
+        ExprKind::MethodCall(method, left, [right], _) => {
             if signed {
                 return nbits;
             }
@@ -55,7 +55,7 @@ fn apply_reductions(cx: &LateContext<'_>, nbits: u64, expr: &Expr<'_>, signed: b
             };
             apply_reductions(cx, nbits, left, signed).min(max_bits.unwrap_or(u64::max_value()))
         },
-        ExprKind::MethodCall(method, [_, lo, hi], _) => {
+        ExprKind::MethodCall(method, _, [lo, hi], _) => {
             if method.ident.as_str() == "clamp" {
                 //FIXME: make this a diagnostic item
                 if let (Some(lo_bits), Some(hi_bits)) = (get_constant_bits(cx, lo), get_constant_bits(cx, hi)) {
@@ -64,7 +64,7 @@ fn apply_reductions(cx: &LateContext<'_>, nbits: u64, expr: &Expr<'_>, signed: b
             }
             nbits
         },
-        ExprKind::MethodCall(method, [_value], _) => {
+        ExprKind::MethodCall(method, _value, [], _) => {
             if method.ident.name.as_str() == "signum" {
                 0 // do not lint if cast comes from a `signum` function
             } else {
index d476a1a7646c01e24bd8ea9b3df3297ec980fdba..da7b12f67266a31898f5fcec7484eb11f6e8f865 100644 (file)
@@ -18,7 +18,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
             cx.typeck_results().expr_ty(expr),
         );
         lint_cast_ptr_alignment(cx, expr, cast_from, cast_to);
-    } else if let ExprKind::MethodCall(method_path, [self_arg, ..], _) = &expr.kind {
+    } else if let ExprKind::MethodCall(method_path, self_arg, ..) = &expr.kind {
         if method_path.ident.name == sym!(cast)
             && let Some(generic_args) = method_path.args
             && let [GenericArg::Type(cast_to)] = generic_args.args
@@ -64,7 +64,7 @@ fn is_used_as_unaligned(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
         return false;
     };
     match parent.kind {
-        ExprKind::MethodCall(name, [self_arg, ..], _) if self_arg.hir_id == e.hir_id => {
+        ExprKind::MethodCall(name, self_arg, ..) if self_arg.hir_id == e.hir_id => {
             if matches!(name.ident.as_str(), "read_unaligned" | "write_unaligned")
                 && let Some(def_id) = cx.typeck_results().type_dependent_def_id(parent.hir_id)
                 && let Some(def_id) = cx.tcx.impl_of_method(def_id)
index 75f70b77ed4e7d34a07a52467ab4c7f61e563053..5b59350be042c9ee173a398e36c403a81c86e01a 100644 (file)
@@ -41,14 +41,14 @@ fn should_lint(cx: &LateContext<'_>, cast_op: &Expr<'_>, cast_from: Ty<'_>, cast
             }
 
             // Don't lint for the result of methods that always return non-negative values.
-            if let ExprKind::MethodCall(path, _, _) = cast_op.kind {
+            if let ExprKind::MethodCall(path, ..) = cast_op.kind {
                 let mut method_name = path.ident.name.as_str();
                 let allowed_methods = ["abs", "checked_abs", "rem_euclid", "checked_rem_euclid"];
 
                 if_chain! {
                     if method_name == "unwrap";
                     if let Some(arglist) = method_chain_args(cast_op, &["unwrap"]);
-                    if let ExprKind::MethodCall(inner_path, _, _) = &arglist[0][0].kind;
+                    if let ExprKind::MethodCall(inner_path, ..) = &arglist[0].0.kind;
                     then {
                         method_name = inner_path.ident.name.as_str();
                     }
index fb418a3251f588c4cc58dbb5d8da10c88ffc96bf..64c5de5104206c73ee9eecb29dced83d11cbf658 100644 (file)
@@ -69,10 +69,7 @@ struct NumericFallbackVisitor<'a, 'tcx> {
 
 impl<'a, 'tcx> NumericFallbackVisitor<'a, 'tcx> {
     fn new(cx: &'a LateContext<'tcx>) -> Self {
-        Self {
-            ty_bounds: vec![TyBound::Nothing],
-            cx,
-        }
+        Self { ty_bounds: vec![TyBound::Nothing], cx }
     }
 
     /// Check whether a passed literal has potential to cause fallback or not.
@@ -129,19 +126,21 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
                     }
                     return;
                 }
-            },
+            }
 
-            ExprKind::MethodCall(_, args, _) => {
+            ExprKind::MethodCall(_, receiver, args, _) => {
                 if let Some(def_id) = self.cx.typeck_results().type_dependent_def_id(expr.hir_id) {
                     let fn_sig = self.cx.tcx.fn_sig(def_id).skip_binder();
-                    for (expr, bound) in iter::zip(*args, fn_sig.inputs()) {
+                    for (expr, bound) in
+                        iter::zip(std::iter::once(*receiver).chain(args.iter()), fn_sig.inputs())
+                    {
                         self.ty_bounds.push(TyBound::Ty(*bound));
                         self.visit_expr(expr);
                         self.ty_bounds.pop();
                     }
                     return;
                 }
-            },
+            }
 
             ExprKind::Struct(_, fields, base) => {
                 let ty = self.cx.typeck_results().expr_ty(expr);
@@ -176,15 +175,15 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
                         return;
                     }
                 }
-            },
+            }
 
             ExprKind::Lit(lit) => {
                 let ty = self.cx.typeck_results().expr_ty(expr);
                 self.check_lit(lit, ty, expr.hir_id);
                 return;
-            },
+            }
 
-            _ => {},
+            _ => {}
         }
 
         walk_expr(self, expr);
@@ -198,7 +197,7 @@ fn visit_stmt(&mut self, stmt: &'tcx Stmt<'_>) {
                 } else {
                     self.ty_bounds.push(TyBound::Nothing);
                 }
-            },
+            }
 
             _ => self.ty_bounds.push(TyBound::Nothing),
         }
index 1506ea604f0dd21ab827db4062d57bd9a2939532..ae509aab1525f68d2598e5d903ec3f085789166f 100644 (file)
@@ -503,7 +503,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
     }
 
     fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) {
-        if let PatKind::Binding(BindingAnnotation::Ref, id, name, _) = pat.kind {
+        if let PatKind::Binding(BindingAnnotation::REF, id, name, _) = pat.kind {
             if let Some(opt_prev_pat) = self.ref_locals.get_mut(&id) {
                 // This binding id has been seen before. Add this pattern to the list of changes.
                 if let Some(prev_pat) = opt_prev_pat {
@@ -581,7 +581,7 @@ fn try_parse_ref_op<'tcx>(
     expr: &'tcx Expr<'_>,
 ) -> Option<(RefOp, &'tcx Expr<'tcx>)> {
     let (def_id, arg) = match expr.kind {
-        ExprKind::MethodCall(_, [arg], _) => (typeck.type_dependent_def_id(expr.hir_id)?, arg),
+        ExprKind::MethodCall(_, arg, [], _) => (typeck.type_dependent_def_id(expr.hir_id)?, arg),
         ExprKind::Call(
             Expr {
                 kind: ExprKind::Path(path),
@@ -796,58 +796,59 @@ fn walk_parents<'tcx>(
                             },
                         })
                     }),
-                ExprKind::MethodCall(_, args, _) => {
+                ExprKind::MethodCall(_, receiver, args, _) => {
                     let id = cx.typeck_results().type_dependent_def_id(parent.hir_id).unwrap();
-                    args.iter().position(|arg| arg.hir_id == child_id).map(|i| {
-                        if i == 0 {
-                            // Check for calls to trait methods where the trait is implemented on a reference.
-                            // Two cases need to be handled:
-                            // * `self` methods on `&T` will never have auto-borrow
-                            // * `&self` methods on `&T` can have auto-borrow, but `&self` methods on `T` will take
-                            //   priority.
-                            if e.hir_id != child_id {
-                                Position::ReborrowStable(precedence)
-                            } else if let Some(trait_id) = cx.tcx.trait_of_item(id)
-                                && let arg_ty = cx.tcx.erase_regions(cx.typeck_results().expr_ty_adjusted(e))
-                                && let ty::Ref(_, sub_ty, _) = *arg_ty.kind()
-                                && let subs = match cx
-                                    .typeck_results()
-                                    .node_substs_opt(parent.hir_id)
-                                    .and_then(|subs| subs.get(1..))
-                                {
-                                    Some(subs) => cx.tcx.mk_substs(subs.iter().copied()),
-                                    None => cx.tcx.mk_substs(std::iter::empty::<ty::subst::GenericArg<'_>>()),
-                                } && let impl_ty = if cx.tcx.fn_sig(id).skip_binder().inputs()[0].is_ref() {
-                                    // Trait methods taking `&self`
-                                    sub_ty
-                                } else {
-                                    // Trait methods taking `self`
-                                    arg_ty
-                                } && impl_ty.is_ref()
-                                && cx.tcx.infer_ctxt().enter(|infcx|
-                                    infcx
-                                        .type_implements_trait(trait_id, impl_ty, subs, cx.param_env)
-                                        .must_apply_modulo_regions()
-                                )
+                    if receiver.hir_id == child_id {
+                        // Check for calls to trait methods where the trait is implemented on a reference.
+                        // Two cases need to be handled:
+                        // * `self` methods on `&T` will never have auto-borrow
+                        // * `&self` methods on `&T` can have auto-borrow, but `&self` methods on `T` will take
+                        //   priority.
+                        if e.hir_id != child_id {
+                            return Some(Position::ReborrowStable(precedence))
+                        } else if let Some(trait_id) = cx.tcx.trait_of_item(id)
+                            && let arg_ty = cx.tcx.erase_regions(cx.typeck_results().expr_ty_adjusted(e))
+                            && let ty::Ref(_, sub_ty, _) = *arg_ty.kind()
+                            && let subs = match cx
+                                .typeck_results()
+                                .node_substs_opt(parent.hir_id)
+                                .and_then(|subs| subs.get(1..))
                             {
-                                Position::MethodReceiverRefImpl
+                                Some(subs) => cx.tcx.mk_substs(subs.iter().copied()),
+                                None => cx.tcx.mk_substs(std::iter::empty::<ty::subst::GenericArg<'_>>()),
+                            } && let impl_ty = if cx.tcx.fn_sig(id).skip_binder().inputs()[0].is_ref() {
+                                // Trait methods taking `&self`
+                                sub_ty
                             } else {
-                                Position::MethodReceiver
-                            }
+                                // Trait methods taking `self`
+                                arg_ty
+                            } && impl_ty.is_ref()
+                            && cx.tcx.infer_ctxt().enter(|infcx|
+                                infcx
+                                    .type_implements_trait(trait_id, impl_ty, subs, cx.param_env)
+                                    .must_apply_modulo_regions()
+                            )
+                        {
+                            return Some(Position::MethodReceiverRefImpl)
                         } else {
-                            let ty = cx.tcx.fn_sig(id).skip_binder().inputs()[i];
+                            return Some(Position::MethodReceiver)
+                        }
+                    }
+                    args.iter()
+                        .position(|arg| arg.hir_id == child_id)
+                        .map(|i| {
+                            let ty = cx.tcx.fn_sig(id).skip_binder().inputs()[i + 1];
                             if let ty::Param(param_ty) = ty.kind() {
-                                needless_borrow_impl_arg_position(cx, parent, i, *param_ty, e, precedence, msrv)
+                                needless_borrow_impl_arg_position(cx, parent, i + 1, *param_ty, e, precedence, msrv)
                             } else {
                                 ty_auto_deref_stability(
                                     cx,
-                                    cx.tcx.erase_late_bound_regions(cx.tcx.fn_sig(id).input(i)),
+                                    cx.tcx.erase_late_bound_regions(cx.tcx.fn_sig(id).input(i + 1)),
                                     precedence,
                                 )
                                 .position_for_arg()
                             }
-                        }
-                    })
+                        })
                 },
                 ExprKind::Field(child, name) if child.hir_id == e.hir_id => Some(Position::FieldAccess(name.name)),
                 ExprKind::Unary(UnOp::Deref, child) if child.hir_id == e.hir_id => Some(Position::Deref),
index da111e7378eaf8be147c455c80ce779e642be12f..512872cedc1ea04d6f45be24bb378f77fa7372cf 100644 (file)
@@ -828,7 +828,7 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
 
         // check for `unwrap`
         if let Some(arglists) = method_chain_args(expr, &["unwrap"]) {
-            let receiver_ty = self.typeck_results.expr_ty(&arglists[0][0]).peel_refs();
+            let receiver_ty = self.typeck_results.expr_ty(&arglists[0].0).peel_refs();
             if is_type_diagnostic_item(self.cx, receiver_ty, sym::Option)
                 || is_type_diagnostic_item(self.cx, receiver_ty, sym::Result)
             {
index 4e3ae4c9614113f3a1132462d8b70600c8a7f8c9..e70df3f53c75de24d99388251cc906c4b444987c 100644 (file)
@@ -245,8 +245,8 @@ fn try_parse_contains<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Optio
     match expr.kind {
         ExprKind::MethodCall(
             _,
+            map,
             [
-                map,
                 Expr {
                     kind: ExprKind::AddrOf(_, _, key),
                     span: key_span,
@@ -280,7 +280,7 @@ struct InsertExpr<'tcx> {
     value: &'tcx Expr<'tcx>,
 }
 fn try_parse_insert<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<InsertExpr<'tcx>> {
-    if let ExprKind::MethodCall(_, [map, key, value], _) = expr.kind {
+    if let ExprKind::MethodCall(_, map, [key, value], _) = expr.kind {
         let id = cx.typeck_results().type_dependent_def_id(expr.hir_id)?;
         if match_def_path(cx, id, &paths::BTREEMAP_INSERT) || match_def_path(cx, id, &paths::HASHMAP_INSERT) {
             Some(InsertExpr { map, key, value })
index 4f9ff97f1fd1a1ace7344eb47c6aa6259fbaa29d..1342a4697b991664122c18fe8071fda8054fa81c 100644 (file)
@@ -106,7 +106,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
             if !is_adjusted(cx, &body.value);
             if let ExprKind::Call(callee, args) = body.value.kind;
             if let ExprKind::Path(_) = callee.kind;
-            if check_inputs(cx, body.params, args);
+            if check_inputs(cx, body.params, None, args);
             let callee_ty = cx.typeck_results().expr_ty_adjusted(callee);
             let call_ty = cx.typeck_results().type_dependent_def_id(body.value.hir_id)
                 .map_or(callee_ty, |id| cx.tcx.type_of(id));
@@ -146,8 +146,8 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
 
         if_chain!(
             if !is_adjusted(cx, &body.value);
-            if let ExprKind::MethodCall(path, args, _) = body.value.kind;
-            if check_inputs(cx, body.params, args);
+            if let ExprKind::MethodCall(path, receiver, args, _) = body.value.kind;
+            if check_inputs(cx, body.params, Some(receiver), args);
             let method_def_id = cx.typeck_results().type_dependent_def_id(body.value.hir_id).unwrap();
             let substs = cx.typeck_results().node_substs(body.value.hir_id);
             let call_ty = cx.tcx.bound_type_of(method_def_id).subst(cx.tcx, substs);
@@ -167,12 +167,17 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
     }
 }
 
-fn check_inputs(cx: &LateContext<'_>, params: &[Param<'_>], call_args: &[Expr<'_>]) -> bool {
-    if params.len() != call_args.len() {
+fn check_inputs(
+    cx: &LateContext<'_>,
+    params: &[Param<'_>],
+    receiver: Option<&Expr<'_>>,
+    call_args: &[Expr<'_>],
+) -> bool {
+    if receiver.map_or(params.len() != call_args.len(), |_| params.len() != call_args.len() + 1) {
         return false;
     }
     let binding_modes = cx.typeck_results().pat_binding_modes();
-    std::iter::zip(params, call_args).all(|(param, arg)| {
+    let check_inputs = |param: &Param<'_>, arg| {
         match param.pat.kind {
             PatKind::Binding(_, id, ..) if path_to_local_id(arg, id) => {},
             _ => return false,
@@ -200,7 +205,9 @@ fn check_inputs(cx: &LateContext<'_>, params: &[Param<'_>], call_args: &[Expr<'_
             },
             _ => false,
         }
-    })
+    };
+    std::iter::zip(params, receiver.into_iter().chain(call_args.iter()))
+        .all(|(param, arg)| check_inputs(param, arg))
 }
 
 fn check_sig<'tcx>(cx: &LateContext<'tcx>, closure_ty: Ty<'tcx>, call_ty: Ty<'tcx>) -> bool {
index 5bf4313b41a49ae062fa7e8faf6f55ef83f52b9b..b9ed4af02190b07c4eb7c5a409ab890be52e907b 100644 (file)
@@ -45,10 +45,10 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         if_chain! {
             // match call to unwrap
-            if let ExprKind::MethodCall(unwrap_fun, [write_call], _) = expr.kind;
+            if let ExprKind::MethodCall(unwrap_fun, write_call, [], _) = expr.kind;
             if unwrap_fun.ident.name == sym::unwrap;
             // match call to write_fmt
-            if let ExprKind::MethodCall(write_fun, [write_recv, write_arg], _) = look_in_block(cx, &write_call.kind);
+            if let ExprKind::MethodCall(write_fun, write_recv, [write_arg], _) = look_in_block(cx, &write_call.kind);
             if write_fun.ident.name == sym!(write_fmt);
             // match calls to std::io::stdout() / std::io::stderr ()
             if let Some(dest_name) = if match_function_call(cx, write_recv, &paths::STDOUT).is_some() {
@@ -128,7 +128,7 @@ fn look_in_block<'tcx, 'hir>(cx: &LateContext<'tcx>, kind: &'tcx ExprKind<'hir>)
         if let Some(Node::Pat(res_pat)) = cx.tcx.hir().find(expr_res);
 
         // Find id of the local we found in the block
-        if let PatKind::Binding(BindingAnnotation::Unannotated, local_hir_id, _ident, None) = local.pat.kind;
+        if let PatKind::Binding(BindingAnnotation::NONE, local_hir_id, _ident, None) = local.pat.kind;
 
         // If those two are the same hir id
         if res_pat.hir_id == local_hir_id;
index b88e53aeca693d42f40d3d69f82a6ef17ac4b276..790eea63f58c49e048e58caf039c5e4360765a61 100644 (file)
@@ -84,7 +84,7 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
 
             // check for `unwrap`
             if let Some(arglists) = method_chain_args(expr, &["unwrap"]) {
-                let receiver_ty = self.typeck_results.expr_ty(&arglists[0][0]).peel_refs();
+                let receiver_ty = self.typeck_results.expr_ty(&arglists[0].0).peel_refs();
                 if is_type_diagnostic_item(self.lcx, receiver_ty, sym::Option)
                     || is_type_diagnostic_item(self.lcx, receiver_ty, sym::Result)
                 {
index bb50e8fcabbb712c15c4dd0cdae52368fbb8ae23..728db41d600438e39803cc21dee554a1e0879820 100644 (file)
@@ -164,15 +164,15 @@ fn prepare_receiver_sugg<'a>(cx: &LateContext<'_>, mut expr: &'a Expr<'a>) -> Su
     suggestion.maybe_par()
 }
 
-fn check_log_base(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
-    if let Some(method) = get_specialized_log_method(cx, &args[1]) {
+fn check_log_base(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) {
+    if let Some(method) = get_specialized_log_method(cx, &args[0]) {
         span_lint_and_sugg(
             cx,
             SUBOPTIMAL_FLOPS,
             expr.span,
             "logarithm for bases 2, 10 and e can be computed more accurately",
             "consider using",
-            format!("{}.{}()", Sugg::hir(cx, &args[0], "..").maybe_par(), method),
+            format!("{}.{}()", Sugg::hir(cx, receiver, "..").maybe_par(), method),
             Applicability::MachineApplicable,
         );
     }
@@ -180,14 +180,14 @@ fn check_log_base(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
 
 // TODO: Lint expressions of the form `(x + y).ln()` where y > 1 and
 // suggest usage of `(x + (y - 1)).ln_1p()` instead
-fn check_ln1p(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
+fn check_ln1p(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>) {
     if let ExprKind::Binary(
         Spanned {
             node: BinOpKind::Add, ..
         },
         lhs,
         rhs,
-    ) = &args[0].kind
+    ) = receiver.kind
     {
         let recv = match (
             constant(cx, cx.typeck_results(), lhs),
@@ -235,9 +235,9 @@ fn get_integer_from_float_constant(value: &Constant) -> Option<i32> {
     }
 }
 
-fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
+fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) {
     // Check receiver
-    if let Some((value, _)) = constant(cx, cx.typeck_results(), &args[0]) {
+    if let Some((value, _)) = constant(cx, cx.typeck_results(), receiver) {
         let method = if F32(f32_consts::E) == value || F64(f64_consts::E) == value {
             "exp"
         } else if F32(2.0) == value || F64(2.0) == value {
@@ -252,24 +252,24 @@ fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
             expr.span,
             "exponent for bases 2 and e can be computed more accurately",
             "consider using",
-            format!("{}.{}()", prepare_receiver_sugg(cx, &args[1]), method),
+            format!("{}.{}()", prepare_receiver_sugg(cx, &args[0]), method),
             Applicability::MachineApplicable,
         );
     }
 
     // Check argument
-    if let Some((value, _)) = constant(cx, cx.typeck_results(), &args[1]) {
+    if let Some((value, _)) = constant(cx, cx.typeck_results(), &args[0]) {
         let (lint, help, suggestion) = if F32(1.0 / 2.0) == value || F64(1.0 / 2.0) == value {
             (
                 SUBOPTIMAL_FLOPS,
                 "square-root of a number can be computed more efficiently and accurately",
-                format!("{}.sqrt()", Sugg::hir(cx, &args[0], "..").maybe_par()),
+                format!("{}.sqrt()", Sugg::hir(cx, receiver, "..").maybe_par()),
             )
         } else if F32(1.0 / 3.0) == value || F64(1.0 / 3.0) == value {
             (
                 IMPRECISE_FLOPS,
                 "cube-root of a number can be computed more accurately",
-                format!("{}.cbrt()", Sugg::hir(cx, &args[0], "..").maybe_par()),
+                format!("{}.cbrt()", Sugg::hir(cx, receiver, "..").maybe_par()),
             )
         } else if let Some(exponent) = get_integer_from_float_constant(&value) {
             (
@@ -277,7 +277,7 @@ fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
                 "exponentiation with integer powers can be computed more efficiently",
                 format!(
                     "{}.powi({})",
-                    Sugg::hir(cx, &args[0], "..").maybe_par(),
+                    Sugg::hir(cx, receiver, "..").maybe_par(),
                     numeric_literal::format(&exponent.to_string(), None, false)
                 ),
             )
@@ -297,13 +297,14 @@ fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
     }
 }
 
-fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
-    if let Some((value, _)) = constant(cx, cx.typeck_results(), &args[1]) {
+fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) {
+    if let Some((value, _)) = constant(cx, cx.typeck_results(), &args[0]) {
         if value == Int(2) {
             if let Some(parent) = get_parent_expr(cx, expr) {
                 if let Some(grandparent) = get_parent_expr(cx, parent) {
-                    if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, args, _) = grandparent.kind {
-                        if method_name.as_str() == "sqrt" && detect_hypot(cx, args).is_some() {
+                    if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, receiver, ..) = grandparent.kind
+                    {
+                        if method_name.as_str() == "sqrt" && detect_hypot(cx, receiver).is_some() {
                             return;
                         }
                     }
@@ -327,8 +328,8 @@ fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
                         "consider using",
                         format!(
                             "{}.mul_add({}, {})",
-                            Sugg::hir(cx, &args[0], "..").maybe_par(),
-                            Sugg::hir(cx, &args[0], ".."),
+                            Sugg::hir(cx, receiver, "..").maybe_par(),
+                            Sugg::hir(cx, receiver, ".."),
                             Sugg::hir(cx, other_addend, ".."),
                         ),
                         Applicability::MachineApplicable,
@@ -339,14 +340,14 @@ fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
     }
 }
 
-fn detect_hypot(cx: &LateContext<'_>, args: &[Expr<'_>]) -> Option<String> {
+fn detect_hypot(cx: &LateContext<'_>, receiver: &Expr<'_>) -> Option<String> {
     if let ExprKind::Binary(
         Spanned {
             node: BinOpKind::Add, ..
         },
         add_lhs,
         add_rhs,
-    ) = args[0].kind
+    ) = receiver.kind
     {
         // check if expression of the form x * x + y * y
         if_chain! {
@@ -363,12 +364,12 @@ fn detect_hypot(cx: &LateContext<'_>, args: &[Expr<'_>]) -> Option<String> {
         if_chain! {
             if let ExprKind::MethodCall(
                 PathSegment { ident: lmethod_name, .. },
-                [largs_0, largs_1, ..],
+                largs_0, [largs_1, ..],
                 _
             ) = &add_lhs.kind;
             if let ExprKind::MethodCall(
                 PathSegment { ident: rmethod_name, .. },
-                [rargs_0, rargs_1, ..],
+                rargs_0, [rargs_1, ..],
                 _
             ) = &add_rhs.kind;
             if lmethod_name.as_str() == "powi" && rmethod_name.as_str() == "powi";
@@ -384,8 +385,8 @@ fn detect_hypot(cx: &LateContext<'_>, args: &[Expr<'_>]) -> Option<String> {
     None
 }
 
-fn check_hypot(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
-    if let Some(message) = detect_hypot(cx, args) {
+fn check_hypot(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>) {
+    if let Some(message) = detect_hypot(cx, receiver) {
         span_lint_and_sugg(
             cx,
             IMPRECISE_FLOPS,
@@ -406,7 +407,7 @@ fn check_expm1(cx: &LateContext<'_>, expr: &Expr<'_>) {
         if cx.typeck_results().expr_ty(lhs).is_floating_point();
         if let Some((value, _)) = constant(cx, cx.typeck_results(), rhs);
         if F32(1.0) == value || F64(1.0) == value;
-        if let ExprKind::MethodCall(path, [self_arg, ..], _) = &lhs.kind;
+        if let ExprKind::MethodCall(path, self_arg, ..) = &lhs.kind;
         if cx.typeck_results().expr_ty(self_arg).is_floating_point();
         if path.ident.name.as_str() == "exp";
         then {
@@ -450,8 +451,8 @@ fn check_mul_add(cx: &LateContext<'_>, expr: &Expr<'_>) {
     ) = &expr.kind
     {
         if let Some(parent) = get_parent_expr(cx, expr) {
-            if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, args, _) = parent.kind {
-                if method_name.as_str() == "sqrt" && detect_hypot(cx, args).is_some() {
+            if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, receiver, ..) = parent.kind {
+                if method_name.as_str() == "sqrt" && detect_hypot(cx, receiver).is_some() {
                     return;
                 }
             }
@@ -586,14 +587,14 @@ fn check_custom_abs(cx: &LateContext<'_>, expr: &Expr<'_>) {
 
 fn are_same_base_logs(cx: &LateContext<'_>, expr_a: &Expr<'_>, expr_b: &Expr<'_>) -> bool {
     if_chain! {
-        if let ExprKind::MethodCall(PathSegment { ident: method_name_a, .. }, args_a, _) = expr_a.kind;
-        if let ExprKind::MethodCall(PathSegment { ident: method_name_b, .. }, args_b, _) = expr_b.kind;
+        if let ExprKind::MethodCall(PathSegment { ident: method_name_a, .. }, _, args_a, _) = expr_a.kind;
+        if let ExprKind::MethodCall(PathSegment { ident: method_name_b, .. }, _, args_b, _) = expr_b.kind;
         then {
             return method_name_a.as_str() == method_name_b.as_str() &&
                 args_a.len() == args_b.len() &&
                 (
                     ["ln", "log2", "log10"].contains(&method_name_a.as_str()) ||
-                    method_name_a.as_str() == "log" && args_a.len() == 2 && eq_expr_value(cx, &args_a[1], &args_b[1])
+                    method_name_a.as_str() == "log" && args_a.len() == 1 && eq_expr_value(cx, &args_a[0], &args_b[0])
                 );
         }
     }
@@ -612,8 +613,8 @@ fn check_log_division(cx: &LateContext<'_>, expr: &Expr<'_>) {
             rhs,
         ) = &expr.kind;
         if are_same_base_logs(cx, lhs, rhs);
-        if let ExprKind::MethodCall(_, [largs_self, ..], _) = &lhs.kind;
-        if let ExprKind::MethodCall(_, [rargs_self, ..], _) = &rhs.kind;
+        if let ExprKind::MethodCall(_, largs_self, ..) = &lhs.kind;
+        if let ExprKind::MethodCall(_, rargs_self, ..) = &rhs.kind;
         then {
             span_lint_and_sugg(
                 cx,
@@ -711,16 +712,16 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
             return;
         }
 
-        if let ExprKind::MethodCall(path, args, _) = &expr.kind {
-            let recv_ty = cx.typeck_results().expr_ty(&args[0]);
+        if let ExprKind::MethodCall(path, receiver, args, _) = &expr.kind {
+            let recv_ty = cx.typeck_results().expr_ty(receiver);
 
             if recv_ty.is_floating_point() {
                 match path.ident.name.as_str() {
-                    "ln" => check_ln1p(cx, expr, args),
-                    "log" => check_log_base(cx, expr, args),
-                    "powf" => check_powf(cx, expr, args),
-                    "powi" => check_powi(cx, expr, args),
-                    "sqrt" => check_hypot(cx, expr, args),
+                    "ln" => check_ln1p(cx, expr, receiver),
+                    "log" => check_log_base(cx, expr, receiver, args),
+                    "powf" => check_powf(cx, expr, receiver, args),
+                    "powi" => check_powi(cx, expr, receiver, args),
+                    "sqrt" => check_hypot(cx, expr, receiver),
                     _ => {},
                 }
             }
index 9fb9fd99748b4b63eabb571073dcba3306d938fb..2a55c48cf7731abb590b4d392d4512d90453e4fc 100644 (file)
@@ -99,7 +99,12 @@ fn outermost_expn_data(expn_data: ExpnData) -> ExpnData {
     }
 }
 
-fn check_format_in_format_args(cx: &LateContext<'_>, call_site: Span, name: Symbol, arg: &Expr<'_>) {
+fn check_format_in_format_args(
+    cx: &LateContext<'_>,
+    call_site: Span,
+    name: Symbol,
+    arg: &Expr<'_>,
+) {
     let expn_data = arg.span.ctxt().outer_expn_data();
     if expn_data.call_site.from_expansion() {
         return;
@@ -126,7 +131,7 @@ fn check_format_in_format_args(cx: &LateContext<'_>, call_site: Span, name: Symb
 fn check_to_string_in_format_args(cx: &LateContext<'_>, name: Symbol, value: &Expr<'_>) {
     if_chain! {
         if !value.span.from_expansion();
-        if let ExprKind::MethodCall(_, [receiver], _) = value.kind;
+        if let ExprKind::MethodCall(_, receiver, [], _) = value.kind;
         if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(value.hir_id);
         if is_diag_trait_item(cx, method_def_id, sym::ToString);
         let receiver_ty = cx.typeck_results().expr_ty(receiver);
@@ -177,10 +182,7 @@ fn check_to_string_in_format_args(cx: &LateContext<'_>, name: Symbol, value: &Ex
 
 // Returns true if `hir_id` is referred to by multiple format params
 fn is_aliased(args: &FormatArgsExpn<'_>, hir_id: HirId) -> bool {
-    args.params()
-        .filter(|param| param.value.hir_id == hir_id)
-        .at_most_one()
-        .is_err()
+    args.params().filter(|param| param.value.hir_id == hir_id).at_most_one().is_err()
 }
 
 fn count_needed_derefs<'tcx, I>(mut ty: Ty<'tcx>, mut iter: I) -> (usize, Ty<'tcx>)
@@ -190,11 +192,7 @@ fn count_needed_derefs<'tcx, I>(mut ty: Ty<'tcx>, mut iter: I) -> (usize, Ty<'tc
     let mut n_total = 0;
     let mut n_needed = 0;
     loop {
-        if let Some(Adjustment {
-            kind: Adjust::Deref(overloaded_deref),
-            target,
-        }) = iter.next()
-        {
+        if let Some(Adjustment { kind: Adjust::Deref(overloaded_deref), target }) = iter.next() {
             n_total += 1;
             if overloaded_deref.is_some() {
                 n_needed = n_total;
index d8bc0bf08f2b314b8513902d14f6da434e229d74..b628fd9f758143fa537dae4112d95a032696d5fb 100644 (file)
@@ -139,7 +139,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
 fn check_to_string_in_display(cx: &LateContext<'_>, expr: &Expr<'_>) {
     if_chain! {
         // Get the hir_id of the object we are calling the method on
-        if let ExprKind::MethodCall(path, [ref self_arg, ..], _) = expr.kind;
+        if let ExprKind::MethodCall(path, self_arg, ..) = expr.kind;
         // Is the method to_string() ?
         if path.ident.name == sym::to_string;
         // Is the method a part of the ToString trait? (i.e. not to_string() implemented
index ebf5ab086dcea7ae6966984ad8810a47c39fcf3a..9b9f1872bfc1d2cf5b42a86253b05ccb2db63927 100644 (file)
@@ -54,7 +54,7 @@ fn is_format(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
 impl<'tcx> LateLintPass<'tcx> for FormatPushString {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         let arg = match expr.kind {
-            ExprKind::MethodCall(_, [_, arg], _) => {
+            ExprKind::MethodCall(_, _, [arg], _) => {
                 if let Some(fn_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) &&
                 match_def_path(cx, fn_def_id, &paths::PUSH_STR) {
                     arg
index 6672a6cb0b58fb7be926b3d0f074021645f602e2..a17b23f5edc8609074d202d7f85d974be80d84dc 100644 (file)
@@ -212,7 +212,7 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
             return;
         }
         match expr.kind {
-            Call(_, args) | MethodCall(_, args, _) => {
+            Call(_, args) => {
                 let mut tys = DefIdSet::default();
                 for arg in args {
                     if self.cx.tcx.has_typeck_results(arg.hir_id.owner.to_def_id())
@@ -230,6 +230,24 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
                     tys.clear();
                 }
             },
+            MethodCall(_, receiver, args, _) => {
+                let mut tys = DefIdSet::default();
+                for arg in std::iter::once(receiver).chain(args.iter()) {
+                    if self.cx.tcx.has_typeck_results(arg.hir_id.owner.to_def_id())
+                        && is_mutable_ty(
+                            self.cx,
+                            self.cx.tcx.typeck(arg.hir_id.owner).expr_ty(arg),
+                            arg.span,
+                            &mut tys,
+                        )
+                        && is_mutated_static(arg)
+                    {
+                        self.mutates_static = true;
+                        return;
+                    }
+                    tys.clear();
+                }
+            },
             Assign(target, ..) | AssignOp(_, target, _) | AddrOf(_, hir::Mutability::Mut, target) => {
                 self.mutates_static |= is_mutated_static(target);
             },
index 565a1c871d7580458b633285ea8a84aa913e0410..3bbfa52e810392c98cadd63e7cea7e32dd30ec3e 100644 (file)
@@ -88,11 +88,12 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
                     }
                 }
             },
-            hir::ExprKind::MethodCall(_, args, _) => {
+            hir::ExprKind::MethodCall(_, receiver, args, _) => {
                 let def_id = self.typeck_results.type_dependent_def_id(expr.hir_id).unwrap();
                 let base_type = self.cx.tcx.type_of(def_id);
 
                 if type_is_unsafe_function(self.cx, base_type) {
+                    self.check_arg(receiver);
                     for arg in args {
                         self.check_arg(arg);
                     }
index 4d703d691acc2f81e57296256027072221c27214..9ea8c494cfcdab4a0fd71e5dbe80433fd4e2f8b1 100644 (file)
@@ -129,7 +129,7 @@ fn found_mutex_if_same_as(&self, op_mutex: &Expr<'_>) -> Option<&Expr<'_>> {
 
 fn is_mutex_lock_call<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
     if_chain! {
-        if let ExprKind::MethodCall(path, [self_arg, ..], _) = &expr.kind;
+        if let ExprKind::MethodCall(path, self_arg, ..) = &expr.kind;
         if path.ident.as_str() == "lock";
         let ty = cx.typeck_results().expr_ty(self_arg).peel_refs();
         if is_type_diagnostic_item(cx, ty, sym::Mutex);
index d0c6495e35a72db0453952e4ae68aaf14b72c9e3..0dd7f5bf000d20d69192bf6dfb5251380366251d 100644 (file)
@@ -95,12 +95,14 @@ fn find_slice_values(cx: &LateContext<'_>, pat: &hir::Pat<'_>) -> FxIndexMap<hir
     let mut removed_pat: FxHashSet<hir::HirId> = FxHashSet::default();
     let mut slices: FxIndexMap<hir::HirId, SliceLintInformation> = FxIndexMap::default();
     pat.walk_always(|pat| {
-        if let hir::PatKind::Binding(binding, value_hir_id, ident, sub_pat) = pat.kind {
-            // We'll just ignore mut and ref mut for simplicity sake right now
-            if let hir::BindingAnnotation::Mutable | hir::BindingAnnotation::RefMut = binding {
-                return;
-            }
-
+        // We'll just ignore mut and ref mut for simplicity sake right now
+        if let hir::PatKind::Binding(
+            hir::BindingAnnotation(by_ref, hir::Mutability::Not),
+            value_hir_id,
+            ident,
+            sub_pat,
+        ) = pat.kind
+        {
             // This block catches bindings with sub patterns. It would be hard to build a correct suggestion
             // for them and it's likely that the user knows what they are doing in such a case.
             if removed_pat.contains(&value_hir_id) {
@@ -116,7 +118,7 @@ fn find_slice_values(cx: &LateContext<'_>, pat: &hir::Pat<'_>) -> FxIndexMap<hir
             if let ty::Slice(inner_ty) | ty::Array(inner_ty, _) = bound_ty.peel_refs().kind() {
                 // The values need to use the `ref` keyword if they can't be copied.
                 // This will need to be adjusted if the lint want to support mutable access in the future
-                let src_is_ref = bound_ty.is_ref() && binding != hir::BindingAnnotation::Ref;
+                let src_is_ref = bound_ty.is_ref() && by_ref != hir::ByRef::Yes;
                 let needs_ref = !(src_is_ref || is_copy(cx, *inner_ty));
 
                 let slice_info = slices
index 01c7eef4e04da87e91fbf45433b532b3911b3600..d55a8e1ead17d11eb02f135c361010dca7fb9a2c 100644 (file)
@@ -59,7 +59,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
             MaybeInfinite => (MAYBE_INFINITE_ITER, "possible infinite iteration detected"),
             Finite => {
                 return;
-            },
+            }
         };
         span_lint(cx, lint, expr.span, msg);
     }
@@ -123,43 +123,43 @@ enum Heuristic {
 /// is an upper bound, e.g., some methods can return a possibly
 /// infinite iterator at worst, e.g., `take_while`.
 const HEURISTICS: [(&str, usize, Heuristic, Finiteness); 19] = [
-    ("zip", 2, All, Infinite),
-    ("chain", 2, Any, Infinite),
-    ("cycle", 1, Always, Infinite),
-    ("map", 2, First, Infinite),
-    ("by_ref", 1, First, Infinite),
-    ("cloned", 1, First, Infinite),
-    ("rev", 1, First, Infinite),
-    ("inspect", 1, First, Infinite),
-    ("enumerate", 1, First, Infinite),
-    ("peekable", 2, First, Infinite),
-    ("fuse", 1, First, Infinite),
-    ("skip", 2, First, Infinite),
-    ("skip_while", 1, First, Infinite),
-    ("filter", 2, First, Infinite),
-    ("filter_map", 2, First, Infinite),
-    ("flat_map", 2, First, Infinite),
-    ("unzip", 1, First, Infinite),
-    ("take_while", 2, First, MaybeInfinite),
-    ("scan", 3, First, MaybeInfinite),
+    ("zip", 1, All, Infinite),
+    ("chain", 1, Any, Infinite),
+    ("cycle", 0, Always, Infinite),
+    ("map", 1, First, Infinite),
+    ("by_ref", 0, First, Infinite),
+    ("cloned", 0, First, Infinite),
+    ("rev", 0, First, Infinite),
+    ("inspect", 0, First, Infinite),
+    ("enumerate", 0, First, Infinite),
+    ("peekable", 1, First, Infinite),
+    ("fuse", 0, First, Infinite),
+    ("skip", 1, First, Infinite),
+    ("skip_while", 0, First, Infinite),
+    ("filter", 1, First, Infinite),
+    ("filter_map", 1, First, Infinite),
+    ("flat_map", 1, First, Infinite),
+    ("unzip", 0, First, Infinite),
+    ("take_while", 1, First, MaybeInfinite),
+    ("scan", 2, First, MaybeInfinite),
 ];
 
 fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
     match expr.kind {
-        ExprKind::MethodCall(method, args, _) => {
+        ExprKind::MethodCall(method, receiver, args, _) => {
             for &(name, len, heuristic, cap) in &HEURISTICS {
                 if method.ident.name.as_str() == name && args.len() == len {
                     return (match heuristic {
                         Always => Infinite,
-                        First => is_infinite(cx, &args[0]),
-                        Any => is_infinite(cx, &args[0]).or(is_infinite(cx, &args[1])),
-                        All => is_infinite(cx, &args[0]).and(is_infinite(cx, &args[1])),
+                        First => is_infinite(cx, receiver),
+                        Any => is_infinite(cx, receiver).or(is_infinite(cx, &args[0])),
+                        All => is_infinite(cx, receiver).and(is_infinite(cx, &args[0])),
                     })
                     .and(cap);
                 }
             }
-            if method.ident.name == sym!(flat_map) && args.len() == 2 {
-                if let ExprKind::Closure(&Closure { body, .. }) = args[1].kind {
+            if method.ident.name == sym!(flat_map) && args.len() == 1 {
+                if let ExprKind::Closure(&Closure { body, .. }) = args[0].kind {
                     let body = cx.tcx.hir().body(body);
                     return is_infinite(cx, &body.value);
                 }
@@ -179,29 +179,29 @@ fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
 /// the names and argument lengths of methods that *may* exhaust their
 /// iterators
 const POSSIBLY_COMPLETING_METHODS: [(&str, usize); 6] = [
-    ("find", 2),
-    ("rfind", 2),
-    ("position", 2),
-    ("rposition", 2),
-    ("any", 2),
-    ("all", 2),
+    ("find", 1),
+    ("rfind", 1),
+    ("position", 1),
+    ("rposition", 1),
+    ("any", 1),
+    ("all", 1),
 ];
 
 /// the names and argument lengths of methods that *always* exhaust
 /// their iterators
 const COMPLETING_METHODS: [(&str, usize); 12] = [
-    ("count", 1),
-    ("fold", 3),
-    ("for_each", 2),
-    ("partition", 2),
-    ("max", 1),
-    ("max_by", 2),
-    ("max_by_key", 2),
-    ("min", 1),
-    ("min_by", 2),
-    ("min_by_key", 2),
-    ("sum", 1),
-    ("product", 1),
+    ("count", 0),
+    ("fold", 2),
+    ("for_each", 1),
+    ("partition", 1),
+    ("max", 0),
+    ("max_by", 1),
+    ("max_by_key", 1),
+    ("min", 0),
+    ("min_by", 1),
+    ("min_by_key", 1),
+    ("sum", 0),
+    ("product", 0),
 ];
 
 /// the paths of types that are known to be infinitely allocating
@@ -218,26 +218,24 @@ fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
 
 fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
     match expr.kind {
-        ExprKind::MethodCall(method, args, _) => {
+        ExprKind::MethodCall(method, receiver, args, _) => {
             for &(name, len) in &COMPLETING_METHODS {
                 if method.ident.name.as_str() == name && args.len() == len {
-                    return is_infinite(cx, &args[0]);
+                    return is_infinite(cx, receiver);
                 }
             }
             for &(name, len) in &POSSIBLY_COMPLETING_METHODS {
                 if method.ident.name.as_str() == name && args.len() == len {
-                    return MaybeInfinite.and(is_infinite(cx, &args[0]));
+                    return MaybeInfinite.and(is_infinite(cx, receiver));
                 }
             }
-            if method.ident.name == sym!(last) && args.len() == 1 {
-                let not_double_ended = cx
-                    .tcx
-                    .get_diagnostic_item(sym::DoubleEndedIterator)
-                    .map_or(false, |id| {
-                        !implements_trait(cx, cx.typeck_results().expr_ty(&args[0]), id, &[])
+            if method.ident.name == sym!(last) && args.is_empty() {
+                let not_double_ended =
+                    cx.tcx.get_diagnostic_item(sym::DoubleEndedIterator).map_or(false, |id| {
+                        !implements_trait(cx, cx.typeck_results().expr_ty(receiver), id, &[])
                     });
                 if not_double_ended {
-                    return is_infinite(cx, &args[0]);
+                    return is_infinite(cx, receiver);
                 }
             } else if method.ident.name == sym!(collect) {
                 let ty = cx.typeck_results().expr_ty(expr);
@@ -245,7 +243,7 @@ fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
                     .iter()
                     .any(|diag_item| is_type_diagnostic_item(cx, ty, *diag_item))
                 {
-                    return is_infinite(cx, &args[0]);
+                    return is_infinite(cx, receiver);
                 }
             }
         },
index 246f5aad8fbadec7deba6693828df65932744188..3cbdaff407b04383f07bf24c84dfb71d52bed93d 100644 (file)
@@ -370,7 +370,7 @@ fn check_for_is_empty<'tcx>(
 }
 
 fn check_cmp(cx: &LateContext<'_>, span: Span, method: &Expr<'_>, lit: &Expr<'_>, op: &str, compare_to: u32) {
-    if let (&ExprKind::MethodCall(method_path, args, _), &ExprKind::Lit(ref lit)) = (&method.kind, &lit.kind) {
+    if let (&ExprKind::MethodCall(method_path, receiver, args, _), &ExprKind::Lit(ref lit)) = (&method.kind, &lit.kind) {
         // check if we are in an is_empty() method
         if let Some(name) = get_item_name(cx, method) {
             if name.as_str() == "is_empty" {
@@ -378,7 +378,7 @@ fn check_cmp(cx: &LateContext<'_>, span: Span, method: &Expr<'_>, lit: &Expr<'_>
             }
         }
 
-        check_len(cx, span, method_path.ident.name, args, &lit.node, op, compare_to);
+        check_len(cx, span, method_path.ident.name, receiver, args, &lit.node, op, compare_to);
     } else {
         check_empty_expr(cx, span, method, lit, op);
     }
@@ -388,6 +388,7 @@ fn check_len(
     cx: &LateContext<'_>,
     span: Span,
     method_name: Symbol,
+    receiver: &Expr<'_>,
     args: &[Expr<'_>],
     lit: &LitKind,
     op: &str,
@@ -399,7 +400,7 @@ fn check_len(
             return;
         }
 
-        if method_name == sym::len && args.len() == 1 && has_is_empty(cx, &args[0]) {
+        if method_name == sym::len && args.is_empty() && has_is_empty(cx, receiver) {
             let mut applicability = Applicability::MachineApplicable;
             span_lint_and_sugg(
                 cx,
@@ -410,7 +411,7 @@ fn check_len(
                 format!(
                     "{}{}.is_empty()",
                     op,
-                    snippet_with_applicability(cx, args[0].span, "_", &mut applicability)
+                    snippet_with_applicability(cx, receiver.span, "_", &mut applicability)
                 ),
                 applicability,
             );
index 56bbbbbc819e5aa58020185a6ddee98dc0be15d0..10fc0f4018efdd31c990809aa7a0fca44925fa40 100644 (file)
@@ -4,7 +4,7 @@
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
-use rustc_hir::BindingAnnotation;
+use rustc_hir::{BindingAnnotation, Mutability};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
@@ -98,7 +98,7 @@ fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) {
                     };
 
                     let mutability = match mode {
-                        BindingAnnotation::RefMut | BindingAnnotation::Mutable => "<mut> ",
+                        BindingAnnotation(_, Mutability::Mut) => "<mut> ",
                         _ => "",
                     };
 
index 215c83a7edf6e9f91d86ecc5ce962894ad71ffa6..09b2376d5c04a6d68ad26d1d3abaaa8002f7d4db 100644 (file)
@@ -106,7 +106,7 @@ fn get_binding(pat: &Pat<'_>) -> Option<HirId> {
             hir_id = None;
             return;
         }
-        if let BindingAnnotation::Unannotated = annotation {
+        if let BindingAnnotation::NONE = annotation {
             hir_id = Some(id);
         }
     });
index a65df48e413e842115fc8154ab7787944d4c2851..3fc569af89ecb4f386ba4a5b973494b4e31b9279 100644 (file)
@@ -119,7 +119,7 @@ fn print_offset(offset: MinifyingSugg<'static>) -> MinifyingSugg<'static> {
 
     let print_limit = |end: &Expr<'_>, end_str: &str, base: &Expr<'_>, sugg: MinifyingSugg<'static>| {
         if_chain! {
-            if let ExprKind::MethodCall(method, [recv], _) = end.kind;
+            if let ExprKind::MethodCall(method, recv, [], _) = end.kind;
             if method.ident.name == sym::len;
             if path_to_local(recv) == path_to_local(base);
             then {
@@ -341,7 +341,7 @@ fn get_slice_like_element_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Opti
 
 fn fetch_cloned_expr<'tcx>(expr: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> {
     if_chain! {
-        if let ExprKind::MethodCall(method, [arg], _) = expr.kind;
+        if let ExprKind::MethodCall(method, arg, [], _) = expr.kind;
         if method.ident.name == sym::clone;
         then { arg } else { expr }
     }
index 0696afa39225f52281ba9dc01463e212d70117de..8412875b11b7ecbfae00e57166f5712f5a61307c 100644 (file)
@@ -33,7 +33,7 @@ fn unpack_cond<'tcx>(cond: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> {
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, body: &'tcx Expr<'_>) {
     if_chain! {
         if let ExprKind::Block(Block { stmts: [], expr: None, ..}, _) = body.kind;
-        if let ExprKind::MethodCall(method, [callee, ..], _) = unpack_cond(cond).kind;
+        if let ExprKind::MethodCall(method, callee, ..) = unpack_cond(cond).kind;
         if [sym::load, sym::compare_exchange, sym::compare_exchange_weak].contains(&method.ident.name);
         if let ty::Adt(def, _substs) = cx.typeck_results().expr_ty(callee).kind();
         if cx.tcx.is_diagnostic_item(sym::AtomicBool, def.did());
index ed270bd490d781803f4fffdae7f32331b4a044e4..74f3bda9f43efb0fe0749d4e069640cc634bba4e 100644 (file)
@@ -742,7 +742,7 @@ fn check_for_loop<'tcx>(
 fn check_for_loop_arg(cx: &LateContext<'_>, pat: &Pat<'_>, arg: &Expr<'_>) {
     let mut next_loop_linted = false; // whether or not ITER_NEXT_LOOP lint was used
 
-    if let ExprKind::MethodCall(method, [self_arg], _) = arg.kind {
+    if let ExprKind::MethodCall(method, self_arg, [], _) = arg.kind {
         let method_name = method.ident.as_str();
         // check for looping over x.iter() or x.iter_mut(), could use &x or &mut x
         match method_name {
index aedf3810b23e95c88de5d867eea3c03d446d0e24..fce2d54639cbf22af7ae546a0153ec48793b7978 100644 (file)
@@ -44,7 +44,7 @@ fn check_for_mutability(cx: &LateContext<'_>, bound: &Expr<'_>) -> Option<HirId>
     if_chain! {
         if let Some(hir_id) = path_to_local(bound);
         if let Node::Pat(pat) = cx.tcx.hir().get(hir_id);
-        if let PatKind::Binding(BindingAnnotation::Mutable, ..) = pat.kind;
+        if let PatKind::Binding(BindingAnnotation::MUT, ..) = pat.kind;
         then {
             return Some(hir_id);
         }
index 6d987f393fa5ce353c2d38dae517e5cdf18f1a6d..6e6faa79adc9e7df8e2d43df4efc1fe3e086bbcd 100644 (file)
@@ -25,11 +25,11 @@ pub(super) fn check<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) {
 }
 fn check_needless_collect_direct_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) {
     if_chain! {
-        if let ExprKind::MethodCall(method, args, _) = expr.kind;
-        if let ExprKind::MethodCall(chain_method, _, _) = args[0].kind;
-        if chain_method.ident.name == sym!(collect) && is_trait_method(cx, &args[0], sym::Iterator);
+        if let ExprKind::MethodCall(method, receiver, args, _) = expr.kind;
+        if let ExprKind::MethodCall(chain_method, ..) = receiver.kind;
+        if chain_method.ident.name == sym!(collect) && is_trait_method(cx, receiver, sym::Iterator);
         then {
-            let ty = cx.typeck_results().expr_ty(&args[0]);
+            let ty = cx.typeck_results().expr_ty(receiver);
             let mut applicability = Applicability::MaybeIncorrect;
             let is_empty_sugg = "next().is_none()".to_string();
             let method_name = method.ident.name.as_str();
@@ -41,7 +41,7 @@ fn check_needless_collect_direct_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCont
                     "len" => "count()".to_string(),
                     "is_empty" => is_empty_sugg,
                     "contains" => {
-                        let contains_arg = snippet_with_applicability(cx, args[1].span, "??", &mut applicability);
+                        let contains_arg = snippet_with_applicability(cx, args[0].span, "??", &mut applicability);
                         let (arg, pred) = contains_arg
                             .strip_prefix('&')
                             .map_or(("&x", &*contains_arg), |s| ("x", s));
@@ -80,7 +80,7 @@ fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCo
                 if let StmtKind::Local(local) = stmt.kind;
                 if let PatKind::Binding(_, id, ..) = local.pat.kind;
                 if let Some(init_expr) = local.init;
-                if let ExprKind::MethodCall(method_name, &[ref iter_source], ..) = init_expr.kind;
+                if let ExprKind::MethodCall(method_name, iter_source, [], ..) = init_expr.kind;
                 if method_name.ident.name == sym!(collect) && is_trait_method(cx, init_expr, sym::Iterator);
                 let ty = cx.typeck_results().expr_ty(init_expr);
                 if is_type_diagnostic_item(cx, ty, sym::Vec) ||
@@ -203,7 +203,7 @@ fn visit_block(&mut self, block: &'tcx Block<'tcx>) {
 
     fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
         // Check function calls on our collection
-        if let ExprKind::MethodCall(method_name, [recv, args @ ..], _) = &expr.kind {
+        if let ExprKind::MethodCall(method_name, recv, [args @ ..], _) = &expr.kind {
             if method_name.ident.name == sym!(collect) && is_trait_method(self.cx, expr, sym::Iterator) {
                 self.current_mutably_captured_ids = get_captured_ids(self.cx, self.cx.typeck_results().expr_ty(recv));
                 self.visit_expr(recv);
index 7ca4a7c4ebfc276a60a692f1491056942a621810..ffcf83e4605e2d3cbb84986e80fadbbc7b21a5da 100644 (file)
@@ -188,7 +188,7 @@ pub(super) fn check<'tcx>(
 
 fn is_len_call(expr: &Expr<'_>, var: Symbol) -> bool {
     if_chain! {
-        if let ExprKind::MethodCall(method, [recv], _) = expr.kind;
+        if let ExprKind::MethodCall(method, recv, [], _) = expr.kind;
         if method.ident.name == sym::len;
         if let ExprKind::Path(QPath::Resolved(_, path)) = recv.kind;
         if path.segments.len() == 1;
@@ -301,7 +301,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
     fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
         if_chain! {
             // a range index op
-            if let ExprKind::MethodCall(meth, [args_0, args_1, ..], _) = &expr.kind;
+            if let ExprKind::MethodCall(meth, args_0, [args_1, ..], _) = &expr.kind;
             if (meth.ident.name == sym::index && match_trait_method(self.cx, expr, &paths::INDEX))
                 || (meth.ident.name == sym::index_mut && match_trait_method(self.cx, expr, &paths::INDEX_MUT));
             if !self.check(args_1, args_0, expr);
@@ -356,9 +356,12 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
                     self.visit_expr(expr);
                 }
             },
-            ExprKind::MethodCall(_, args, _) => {
+            ExprKind::MethodCall(_, receiver, args, _) => {
                 let def_id = self.cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap();
-                for (ty, expr) in iter::zip(self.cx.tcx.fn_sig(def_id).inputs().skip_binder(), args) {
+                for (ty, expr) in iter::zip(
+                    self.cx.tcx.fn_sig(def_id).inputs().skip_binder(),
+                    std::iter::once(receiver).chain(args.iter()),
+                ) {
                     self.prefer_mutable = false;
                     if let ty::Ref(_, _, mutbl) = *ty.kind() {
                         if mutbl == Mutability::Mut {
index 32de20f6531fec3a88f63c815972274447c3c503..116e589cad6f3495d87ccccbf1fdf9e238b9c1da 100644 (file)
@@ -120,8 +120,9 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult {
         | ExprKind::Repeat(e, _)
         | ExprKind::DropTemps(e) => never_loop_expr(e, main_loop_id),
         ExprKind::Let(let_expr) => never_loop_expr(let_expr.init, main_loop_id),
-        ExprKind::Array(es) | ExprKind::MethodCall(_, es, _) | ExprKind::Tup(es) => {
-            never_loop_expr_all(&mut es.iter(), main_loop_id)
+        ExprKind::Array(es) | ExprKind::Tup(es) => never_loop_expr_all(&mut es.iter(), main_loop_id),
+        ExprKind::MethodCall(_, receiver, es, _) => {
+            never_loop_expr_all(&mut std::iter::once(receiver).chain(es.iter()), main_loop_id)
         },
         ExprKind::Struct(_, fields, base) => {
             let fields = never_loop_expr_all(&mut fields.iter().map(|f| f.expr), main_loop_id);
@@ -178,9 +179,9 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult {
                 InlineAsmOperand::In { expr, .. } | InlineAsmOperand::InOut { expr, .. } => {
                     never_loop_expr(expr, main_loop_id)
                 },
-                InlineAsmOperand::Out { expr, .. } => never_loop_expr_all(&mut expr.iter(), main_loop_id),
+                InlineAsmOperand::Out { expr, .. } => never_loop_expr_all(&mut expr.iter().copied(), main_loop_id),
                 InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
-                    never_loop_expr_all(&mut once(in_expr).chain(out_expr.iter()), main_loop_id)
+                    never_loop_expr_all(&mut once(*in_expr).chain(out_expr.iter().copied()), main_loop_id)
                 },
                 InlineAsmOperand::Const { .. }
                 | InlineAsmOperand::SymFn { .. }
index 1439f1f4c75d5b03555c10edc1c2d67166c46d86..aeefe6e33fbe9a9405175f3dd1ba6a3af7ea3f53 100644 (file)
@@ -7,7 +7,7 @@
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit::{walk_expr, Visitor};
-use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, HirId, Node, Pat, PatKind, Stmt, StmtKind};
+use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, HirId, Mutability, Node, Pat, PatKind, Stmt, StmtKind};
 use rustc_lint::LateContext;
 use rustc_span::symbol::sym;
 use std::iter::Iterator;
@@ -65,7 +65,7 @@ fn emit_lint(cx: &LateContext<'_>, vec: &Expr<'_>, pushed_item: &Expr<'_>) {
                             if_chain! {
                                 if let Node::Pat(pat) = node;
                                 if let PatKind::Binding(bind_ann, ..) = pat.kind;
-                                if !matches!(bind_ann, BindingAnnotation::RefMut | BindingAnnotation::Mutable);
+                                if !matches!(bind_ann, BindingAnnotation(_, Mutability::Mut));
                                 let parent_node = cx.tcx.hir().get_parent_node(hir_id);
                                 if let Some(Node::Local(parent_let_expr)) = cx.tcx.hir().find(parent_node);
                                 if let Some(init) = parent_let_expr.init;
@@ -180,10 +180,9 @@ fn get_vec_push<'tcx>(cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) -> Option<(&
     if_chain! {
             // Extract method being called
             if let StmtKind::Semi(semi_stmt) = &stmt.kind;
-            if let ExprKind::MethodCall(path, args, _) = &semi_stmt.kind;
+            if let ExprKind::MethodCall(path, self_expr, args, _) = &semi_stmt.kind;
             // Figure out the parameters for the method call
-            if let Some(self_expr) = args.get(0);
-            if let Some(pushed_item) = args.get(1);
+            if let Some(pushed_item) = args.get(0);
             // Check that the method being called is push() on a Vec
             if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(self_expr), sym::Vec);
             if path.ident.name.as_str() == "push";
index a0bd7ad0ac647fb7d0f606e932b15a7e5a5031b3..f4b47808dfaa362b8b7f9ce3d6625d87d07d8a48 100644 (file)
@@ -35,32 +35,29 @@ pub(super) fn check<'tcx>(
         ) => (arg, "&mut "),
         ExprKind::MethodCall(
             method,
-            [
-                Expr {
-                    kind: ExprKind::Array([arg]),
-                    ..
-                },
-            ],
+            Expr {
+                kind: ExprKind::Array([arg]),
+                ..
+            },
+            [],
             _,
         ) if method.ident.name == rustc_span::sym::iter => (arg, "&"),
         ExprKind::MethodCall(
             method,
-            [
-                Expr {
-                    kind: ExprKind::Array([arg]),
-                    ..
-                },
-            ],
+            Expr {
+                kind: ExprKind::Array([arg]),
+                ..
+            },
+            [],
             _,
         ) if method.ident.name.as_str() == "iter_mut" => (arg, "&mut "),
         ExprKind::MethodCall(
             method,
-            [
-                Expr {
-                    kind: ExprKind::Array([arg]),
-                    ..
-                },
-            ],
+            Expr {
+                kind: ExprKind::Array([arg]),
+                ..
+            },
+            [],
             _,
         ) if method.ident.name == rustc_span::sym::into_iter => (arg, ""),
         // Only check for arrays edition 2021 or later, as this case will trigger a compiler error otherwise.
index ca617859db49d713ea5fe3ffa4fc0aaa52e0f771..735d704a43cee343dcdb0ea76dea3a02566e6815 100644 (file)
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, loop_block: &'tcx Block<'_>) {
     let (init, has_trailing_exprs) = match (loop_block.stmts, loop_block.expr) {
         ([stmt, stmts @ ..], expr) => {
-            if let StmtKind::Local(&Local { init: Some(e), els: None, .. }) | StmtKind::Semi(e) | StmtKind::Expr(e) = stmt.kind {
+            if let StmtKind::Local(&Local {
+                init: Some(e),
+                els: None,
+                ..
+            })
+            | StmtKind::Semi(e)
+            | StmtKind::Expr(e) = stmt.kind
+            {
                 (e, !stmts.is_empty() || expr.is_some())
             } else {
                 return;
index e9e215e662f1939c6d799d5e0cdd84aee65fdea5..2c54033f8597502c6fb8db8c276f6f91d450377c 100644 (file)
@@ -23,7 +23,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         if let Res::Def(_, pat_did) = pat_path.res;
         if match_def_path(cx, pat_did, &paths::OPTION_SOME);
         // check for call to `Iterator::next`
-        if let ExprKind::MethodCall(method_name, [iter_expr], _) = let_expr.kind;
+        if let ExprKind::MethodCall(method_name, iter_expr, [], _) = let_expr.kind;
         if method_name.ident.name == sym::next;
         if is_trait_method(cx, let_expr, sym::Iterator);
         if let Some(iter_expr_struct) = try_parse_iter_expr(cx, iter_expr);
index 60bbcde4f1de566b2ab100acc675130691ba61cd..6655c92b1da8da05a2f2f983bbe9fd8e28eaf439 100644 (file)
@@ -105,7 +105,7 @@ fn get_size_of_ty<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<
         if let Some(def_id) = cx.qpath_res(count_func_qpath, count_func.hir_id).opt_def_id();
         if cx.tcx.is_diagnostic_item(sym::mem_size_of, def_id);
         then {
-            cx.typeck_results().node_substs(count_func.hir_id).types().next().map(|resolved_ty| (real_ty, resolved_ty))
+            cx.typeck_results().node_substs(count_func.hir_id).types().next().map(|resolved_ty| (*real_ty, resolved_ty))
         } else {
             None
         }
@@ -134,7 +134,7 @@ fn create_sugg(cx: &LateContext<'_>, expr: &Expr<'_>, base_sugg: String) -> Stri
 fn is_ty_conversion(expr: &Expr<'_>) -> bool {
     if let ExprKind::Cast(..) = expr.kind {
         true
-    } else if let ExprKind::MethodCall(path, [_], _) = expr.kind
+    } else if let ExprKind::MethodCall(path, _, [], _) = expr.kind
         && path.ident.name == rustc_span::sym::try_into
     {
         // This is only called for `usize` which implements `TryInto`. Therefore,
index 42d2577cc3161f48cb1242d23d88b9633dc64fa4..f28c37d3dca7e0d9d49417fe4c832197d70229cb 100644 (file)
@@ -66,9 +66,9 @@ impl<'tcx> LateLintPass<'tcx> for ManualRetain {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
         if let Some(parent_expr) = get_parent_expr(cx, expr)
             && let Assign(left_expr, collect_expr, _) = &parent_expr.kind
-            && let hir::ExprKind::MethodCall(seg, _, _) = &collect_expr.kind
+            && let hir::ExprKind::MethodCall(seg, ..) = &collect_expr.kind
             && seg.args.is_none()
-            && let hir::ExprKind::MethodCall(_, [target_expr], _) = &collect_expr.kind
+            && let hir::ExprKind::MethodCall(_, target_expr, [], _) = &collect_expr.kind
             && let Some(collect_def_id) = cx.typeck_results().type_dependent_def_id(collect_expr.hir_id)
             && match_def_path(cx, collect_def_id, &paths::CORE_ITER_COLLECT) {
             check_into_iter(cx, parent_expr, left_expr, target_expr, self.msrv);
@@ -87,10 +87,10 @@ fn check_into_iter(
     target_expr: &hir::Expr<'_>,
     msrv: Option<RustcVersion>,
 ) {
-    if let hir::ExprKind::MethodCall(_, [into_iter_expr, _], _) = &target_expr.kind
+    if let hir::ExprKind::MethodCall(_, into_iter_expr, [_], _) = &target_expr.kind
         && let Some(filter_def_id) = cx.typeck_results().type_dependent_def_id(target_expr.hir_id)
         && match_def_path(cx, filter_def_id, &paths::CORE_ITER_FILTER)
-        && let hir::ExprKind::MethodCall(_, [struct_expr], _) = &into_iter_expr.kind
+        && let hir::ExprKind::MethodCall(_, struct_expr, [], _) = &into_iter_expr.kind
         && let Some(into_iter_def_id) = cx.typeck_results().type_dependent_def_id(into_iter_expr.hir_id)
         && match_def_path(cx, into_iter_def_id, &paths::CORE_ITER_INTO_ITER)
         && match_acceptable_type(cx, left_expr, msrv)
@@ -106,14 +106,14 @@ fn check_iter(
     target_expr: &hir::Expr<'_>,
     msrv: Option<RustcVersion>,
 ) {
-    if let hir::ExprKind::MethodCall(_, [filter_expr], _) = &target_expr.kind
+    if let hir::ExprKind::MethodCall(_, filter_expr, [], _) = &target_expr.kind
         && let Some(copied_def_id) = cx.typeck_results().type_dependent_def_id(target_expr.hir_id)
         && (match_def_path(cx, copied_def_id, &paths::CORE_ITER_COPIED)
             || match_def_path(cx, copied_def_id, &paths::CORE_ITER_CLONED))
-        && let hir::ExprKind::MethodCall(_, [iter_expr, _], _) = &filter_expr.kind
+        && let hir::ExprKind::MethodCall(_, iter_expr, [_], _) = &filter_expr.kind
         && let Some(filter_def_id) = cx.typeck_results().type_dependent_def_id(filter_expr.hir_id)
         && match_def_path(cx, filter_def_id, &paths::CORE_ITER_FILTER)
-        && let hir::ExprKind::MethodCall(_, [struct_expr], _) = &iter_expr.kind
+        && let hir::ExprKind::MethodCall(_, struct_expr, [], _) = &iter_expr.kind
         && let Some(iter_expr_def_id) = cx.typeck_results().type_dependent_def_id(iter_expr.hir_id)
         && match_acceptable_def_path(cx, iter_expr_def_id)
         && match_acceptable_type(cx, left_expr, msrv)
@@ -130,13 +130,13 @@ fn check_to_owned(
     msrv: Option<RustcVersion>,
 ) {
     if meets_msrv(msrv,  msrvs::STRING_RETAIN)
-        && let hir::ExprKind::MethodCall(_, [filter_expr], _) = &target_expr.kind
+        && let hir::ExprKind::MethodCall(_, filter_expr, [], _) = &target_expr.kind
         && let Some(to_owned_def_id) = cx.typeck_results().type_dependent_def_id(target_expr.hir_id)
         && match_def_path(cx, to_owned_def_id, &paths::TO_OWNED_METHOD)
-        && let hir::ExprKind::MethodCall(_, [chars_expr, _], _) = &filter_expr.kind
+        && let hir::ExprKind::MethodCall(_, chars_expr, [_], _) = &filter_expr.kind
         && let Some(filter_def_id) = cx.typeck_results().type_dependent_def_id(filter_expr.hir_id)
         && match_def_path(cx, filter_def_id, &paths::CORE_ITER_FILTER)
-        && let hir::ExprKind::MethodCall(_, [str_expr], _) = &chars_expr.kind
+        && let hir::ExprKind::MethodCall(_, str_expr, [], _) = &chars_expr.kind
         && let Some(chars_expr_def_id) = cx.typeck_results().type_dependent_def_id(chars_expr.hir_id)
         && match_def_path(cx, chars_expr_def_id, &paths::STR_CHARS)
         && let ty = cx.typeck_results().expr_ty(str_expr).peel_refs()
@@ -147,7 +147,7 @@ fn check_to_owned(
 }
 
 fn suggest(cx: &LateContext<'_>, parent_expr: &hir::Expr<'_>, left_expr: &hir::Expr<'_>, filter_expr: &hir::Expr<'_>) {
-    if let hir::ExprKind::MethodCall(_, [_, closure], _) = filter_expr.kind
+    if let hir::ExprKind::MethodCall(_, _, [closure], _) = filter_expr.kind
         && let hir::ExprKind::Closure(&hir::Closure { body, ..}) = closure.kind
         && let filter_body = cx.tcx.hir().body(body)
         && let [filter_params] = filter_body.params
index a90eaa8fdcbe35b200216f180c5675be3d5ff6d0..6acfb2ae3471c3b3a4f3840b609d490af95e0cfe 100644 (file)
@@ -55,8 +55,8 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
             ExprKind::Call(func, args) => {
                 parse_call(cx, expr.span, func, args);
             },
-            ExprKind::MethodCall(path_segment, args, _) => {
-                parse_method_call(cx, expr.span, path_segment, args);
+            ExprKind::MethodCall(path_segment, receiver, ..) => {
+                parse_method_call(cx, expr.span, path_segment, receiver);
             },
             _ => (),
         }
@@ -88,14 +88,9 @@ fn warn_then_suggest(cx: &LateContext<'_>, span: Span) {
 }
 
 /// Tries to parse an expression as a method call, emitting the warning if necessary.
-fn parse_method_call(cx: &LateContext<'_>, span: Span, path_segment: &PathSegment<'_>, args: &[Expr<'_>]) {
-    if args.is_empty() {
-        // When parsing TryFrom::try_from(...).expect(...), we will have more than 1 arg.
-        return;
-    }
-
+fn parse_method_call(cx: &LateContext<'_>, span: Span, path_segment: &PathSegment<'_>, receiver: &Expr<'_>) {
     let ident = path_segment.ident.as_str();
-    let method_arg_kind = &args[0].kind;
+    let method_arg_kind = &receiver.kind;
     if ["to_string", "to_owned", "into"].contains(&ident) && is_expr_kind_empty_str(method_arg_kind) {
         warn_then_suggest(cx, span);
     } else if let ExprKind::Call(func, args) = method_arg_kind {
index dfb3efc4e28b65c246e3fe67b3be4b74ac12c8e0..7941c8c9c7e39bc4c2f941d765f19904569c7bbd 100644 (file)
@@ -74,7 +74,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
 
         if_chain! {
             if let Some(higher::If { cond, then, .. }) = higher::If::hir(expr);
-            if let ExprKind::MethodCall(_, [target_arg, pattern], _) = cond.kind;
+            if let ExprKind::MethodCall(_, target_arg, [pattern], _) = cond.kind;
             if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(cond.hir_id);
             if let ExprKind::Path(target_path) = &target_arg.kind;
             then {
@@ -132,7 +132,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
 // Returns `Some(arg)` if `expr` matches `arg.len()` and `None` otherwise.
 fn len_arg<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
     if_chain! {
-        if let ExprKind::MethodCall(_, [arg], _) = expr.kind;
+        if let ExprKind::MethodCall(_, arg, [], _) = expr.kind;
         if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
         if match_def_path(cx, method_def_id, &paths::STR_LEN);
         then {
index 6db852c3ffe79a1c6f9234f7f3b3a35cd6af7848..33d744815299f040f56a967423b248e65eb6ea5c 100644 (file)
@@ -200,8 +200,13 @@ fn suggestion_msg(function_type: &str, map_type: &str) -> String {
     )
 }
 
-fn lint_map_unit_fn(cx: &LateContext<'_>, stmt: &hir::Stmt<'_>, expr: &hir::Expr<'_>, map_args: &[hir::Expr<'_>]) {
-    let var_arg = &map_args[0];
+fn lint_map_unit_fn(
+    cx: &LateContext<'_>,
+    stmt: &hir::Stmt<'_>,
+    expr: &hir::Expr<'_>,
+    map_args: (&hir::Expr<'_>, &[hir::Expr<'_>]),
+) {
+    let var_arg = &map_args.0;
 
     let (map_type, variant, lint) = if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(var_arg), sym::Option) {
         ("Option", "Some", OPTION_MAP_UNIT_FN)
@@ -210,7 +215,7 @@ fn lint_map_unit_fn(cx: &LateContext<'_>, stmt: &hir::Stmt<'_>, expr: &hir::Expr
     } else {
         return;
     };
-    let fn_arg = &map_args[1];
+    let fn_arg = &map_args.1[0];
 
     if is_unit_function(cx, fn_arg) {
         let mut applicability = Applicability::MachineApplicable;
index 3349b85f1347a396519aeb5cba96c59813c93cec..8588ab1ed8db781d159aa74363f4eddbf8642562 100644 (file)
@@ -58,7 +58,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
             };
 
         if_chain! {
-            if let ExprKind::MethodCall(ok_path, [ref result_types_0, ..], _) = let_expr.kind; //check is expr.ok() has type Result<T,E>.ok(, _)
+            if let ExprKind::MethodCall(ok_path, result_types_0, ..) = let_expr.kind; //check is expr.ok() has type Result<T,E>.ok(, _)
             if let PatKind::TupleStruct(QPath::Resolved(_, x), y, _)  = let_pat.kind; //get operation
             if method_chain_args(let_expr, &["ok"]).is_some(); //test to see if using ok() method use std::marker::Sized;
             if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(result_types_0), sym::Result);
index 8f98b43b9e5c8d240327b269a2961468d0e28275..b0198e856d5b6ad3b4e107fc792821cb6eb76ef4 100644 (file)
@@ -165,7 +165,7 @@ fn check<'tcx>(
                 }
 
                 // `ref` and `ref mut` annotations were handled earlier.
-                let annotation = if matches!(annotation, BindingAnnotation::Mutable) {
+                let annotation = if matches!(annotation, BindingAnnotation::MUT) {
                     "mut "
                 } else {
                     ""
index a0efdecec67f49aac5d6af449d4156c6059729e1..91d17f481e2df1cd7e369e1eb3dee2e9659dea0f 100644 (file)
@@ -2,7 +2,7 @@
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::{is_lang_ctor, peel_blocks};
 use rustc_errors::Applicability;
-use rustc_hir::{Arm, BindingAnnotation, Expr, ExprKind, LangItem, PatKind, QPath};
+use rustc_hir::{Arm, BindingAnnotation, ByRef, Expr, ExprKind, LangItem, Mutability, PatKind, QPath};
 use rustc_lint::LateContext;
 use rustc_middle::ty;
 
 
 pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) {
     if arms.len() == 2 && arms[0].guard.is_none() && arms[1].guard.is_none() {
-        let arm_ref: Option<BindingAnnotation> = if is_none_arm(cx, &arms[0]) {
+        let arm_ref_mut = if is_none_arm(cx, &arms[0]) {
             is_ref_some_arm(cx, &arms[1])
         } else if is_none_arm(cx, &arms[1]) {
             is_ref_some_arm(cx, &arms[0])
         } else {
             None
         };
-        if let Some(rb) = arm_ref {
-            let suggestion = if rb == BindingAnnotation::Ref {
-                "as_ref"
-            } else {
-                "as_mut"
+        if let Some(rb) = arm_ref_mut {
+            let suggestion = match rb {
+                Mutability::Not => "as_ref",
+                Mutability::Mut => "as_mut",
             };
 
             let output_ty = cx.typeck_results().expr_ty(expr);
@@ -66,19 +65,18 @@ fn is_none_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
 }
 
 // Checks if arm has the form `Some(ref v) => Some(v)` (checks for `ref` and `ref mut`)
-fn is_ref_some_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> Option<BindingAnnotation> {
+fn is_ref_some_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> Option<Mutability> {
     if_chain! {
         if let PatKind::TupleStruct(ref qpath, [first_pat, ..], _) = arm.pat.kind;
         if is_lang_ctor(cx, qpath, LangItem::OptionSome);
-        if let PatKind::Binding(rb, .., ident, _) = first_pat.kind;
-        if rb == BindingAnnotation::Ref || rb == BindingAnnotation::RefMut;
+        if let PatKind::Binding(BindingAnnotation(ByRef::Yes, mutabl), .., ident, _) = first_pat.kind;
         if let ExprKind::Call(e, [arg]) = peel_blocks(arm.body).kind;
         if let ExprKind::Path(ref some_path) = e.kind;
         if is_lang_ctor(cx, some_path, LangItem::OptionSome);
         if let ExprKind::Path(QPath::Resolved(_, path2)) = arg.kind;
         if path2.segments.len() == 1 && ident.name == path2.segments[0].ident.name;
         then {
-            return Some(rb)
+            return Some(mutabl)
         }
     }
     None
index fa3b8d1fceaaccb582e4c560ab4788d9828a26bc..1e80b6cf2d838ecf4d6c64d8fcb353ed214b0d0e 100644 (file)
@@ -48,7 +48,7 @@ struct MatchExprVisitor<'a, 'tcx> {
 impl<'a, 'tcx> Visitor<'tcx> for MatchExprVisitor<'a, 'tcx> {
     fn visit_expr(&mut self, ex: &'tcx Expr<'_>) {
         match ex.kind {
-            ExprKind::MethodCall(segment, [receiver], _) if self.case_altered(segment.ident.as_str(), receiver) => {},
+            ExprKind::MethodCall(segment, receiver, [], _) if self.case_altered(segment.ident.as_str(), receiver) => {},
             _ => walk_expr(self, ex),
         }
     }
index 6f037339ec75870552a3d2867f447a012364d143..634eef82e532ae50304b9f1dd76316ee0acc6748 100644 (file)
@@ -8,7 +8,7 @@
 };
 use rustc_errors::Applicability;
 use rustc_hir::LangItem::OptionNone;
-use rustc_hir::{Arm, BindingAnnotation, Expr, ExprKind, FnRetTy, Guard, Node, Pat, PatKind, Path, QPath};
+use rustc_hir::{Arm, BindingAnnotation, ByRef, Expr, ExprKind, FnRetTy, Guard, Node, Pat, PatKind, Path, QPath};
 use rustc_lint::LateContext;
 use rustc_span::sym;
 use rustc_typeck::hir_ty_to_ty;
@@ -189,8 +189,7 @@ fn pat_same_as_expr(pat: &Pat<'_>, expr: &Expr<'_>) -> bool {
                 },
             )),
         ) => {
-            return !matches!(annot, BindingAnnotation::Ref | BindingAnnotation::RefMut)
-                && pat_ident.name == first_seg.ident.name;
+            return !matches!(annot, BindingAnnotation(ByRef::Yes, _)) && pat_ident.name == first_seg.ident.name;
         },
         // Example: `Custom::TypeA => Custom::TypeB`, or `None => None`
         (PatKind::Path(QPath::Resolved(_, p_path)), ExprKind::Path(QPath::Resolved(_, e_path))) => {
index 8499e050af2426898ede4a71210d0a4ef8451785..f7443471e31dda274d656766223512c64de39ccb 100644 (file)
@@ -120,7 +120,7 @@ fn find_sugg_for_if_let<'tcx>(
     // check that `while_let_on_iterator` lint does not trigger
     if_chain! {
         if keyword == "while";
-        if let ExprKind::MethodCall(method_path, _, _) = let_expr.kind;
+        if let ExprKind::MethodCall(method_path, ..) = let_expr.kind;
         if method_path.ident.name == sym::next;
         if is_trait_method(cx, let_expr, sym::Iterator);
         then {
index b0b15b3f54cd8b35f253218596c49c61aebc27be..86a9df034979be06feb7484f112acf00b2f9529a 100644 (file)
@@ -291,7 +291,7 @@ fn visit_expr(&mut self, ex: &'tcx Expr<'_>) {
         self.is_chain_end = false;
 
         match ex.kind {
-            ExprKind::MethodCall(_, [ref expr, ..], _) => {
+            ExprKind::MethodCall(_, expr, ..) => {
                 self.visit_expr(expr);
             }
             ExprKind::Binary(_, left, right) => {
@@ -331,8 +331,7 @@ fn visit_expr(&mut self, ex: &'tcx Expr<'_>) {
             ExprKind::Index(..) |
             ExprKind::Ret(..) |
             ExprKind::Repeat(..) |
-            ExprKind::Yield(..) |
-            ExprKind::MethodCall(..) => walk_expr(self, ex),
+            ExprKind::Yield(..) => walk_expr(self, ex),
             ExprKind::AddrOf(_, _, _) |
             ExprKind::Block(_, _) |
             ExprKind::Break(_, _) |
index 92091a0c3395f7b4578bc9e26126b1c5daa72e7a..95478af45b4bf3fa687149fa8f76d5e5587306b4 100644 (file)
@@ -175,7 +175,7 @@ fn collect_pat_paths<'a>(acc: &mut Vec<Ty<'a>>, cx: &LateContext<'a>, pat: &Pat<
             let p_ty = cx.typeck_results().pat_ty(p);
             collect_pat_paths(acc, cx, p, p_ty);
         }),
-        PatKind::TupleStruct(..) | PatKind::Binding(BindingAnnotation::Unannotated, .., None) | PatKind::Path(_) => {
+        PatKind::TupleStruct(..) | PatKind::Binding(BindingAnnotation::NONE, .., None) | PatKind::Path(_) => {
             acc.push(ty);
         },
         _ => {},
index 6a7c63d76f72c8afee58a465bec5ba33a21e5436..fef90f6eba49525eb5c0f827aee1e823d97808df 100644 (file)
@@ -42,11 +42,11 @@ pub(super) fn check<'tcx>(
         if ty::Uint(UintTy::U8) == *cx.typeck_results().expr_ty(needle).peel_refs().kind();
         if !is_local_used(cx, needle, arg_id);
         then {
-            let haystack = if let ExprKind::MethodCall(path, args, _) =
+            let haystack = if let ExprKind::MethodCall(path, receiver, [], _) =
                     filter_recv.kind {
                 let p = path.ident.name;
-                if (p == sym::iter || p == sym!(iter_mut)) && args.len() == 1 {
-                    &args[0]
+                if p == sym::iter || p == sym!(iter_mut) {
+                    receiver
                 } else {
                     filter_recv
                 }
index f7b79f0839ba8c17ffbfd08172c16df143491df8..51aec21527a7116e8d253911e12611ba829af055 100644 (file)
@@ -23,7 +23,7 @@ pub(super) fn check(
         if Some(id) == cx.tcx.lang_items().option_some_variant();
         then {
             let mut applicability = Applicability::MachineApplicable;
-            let self_ty = cx.typeck_results().expr_ty_adjusted(&args[0][0]).peel_refs();
+            let self_ty = cx.typeck_results().expr_ty_adjusted(&args[0].0).peel_refs();
 
             if *self_ty.kind() != ty::Str {
                 return false;
@@ -37,7 +37,7 @@ pub(super) fn check(
                 "like this",
                 format!("{}{}.{}({})",
                         if info.eq { "" } else { "!" },
-                        snippet_with_applicability(cx, args[0][0].span, "..", &mut applicability),
+                        snippet_with_applicability(cx, args[0].0.span, "..", &mut applicability),
                         suggest,
                         snippet_with_applicability(cx, arg_char.span, "..", &mut applicability)),
                 applicability,
index a7c0e43923e139b3cc378b6f54aa19161d396f6e..b85bfec2b12ba33de410c2902678864a1fdc0f50 100644 (file)
@@ -30,7 +30,7 @@ pub(super) fn check<'tcx>(
                 "like this",
                 format!("{}{}.{}('{}')",
                         if info.eq { "" } else { "!" },
-                        snippet_with_applicability(cx, args[0][0].span, "..", &mut applicability),
+                        snippet_with_applicability(cx, args[0].0.span, "..", &mut applicability),
                         suggest,
                         c.escape_default()),
                 applicability,
index 60e1355f9b92d889036ae7b2c67e4d510e4305c0..f5bead387d7bd170b17aec80361b8bb04ffc8560 100644 (file)
@@ -4,7 +4,7 @@
 use clippy_utils::sugg;
 use clippy_utils::ty::is_copy;
 use rustc_errors::Applicability;
-use rustc_hir::{BindingAnnotation, Expr, ExprKind, MatchSource, Node, PatKind, QPath};
+use rustc_hir::{BindingAnnotation, ByRef, Expr, ExprKind, MatchSource, Node, PatKind, QPath};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, adjustment::Adjust};
 use rustc_span::symbol::{sym, Symbol};
 
 /// Checks for the `CLONE_ON_COPY` lint.
 #[allow(clippy::too_many_lines)]
-pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symbol, args: &[Expr<'_>]) {
-    let arg = match args {
-        [arg] if method_name == sym::clone => arg,
-        _ => return,
-    };
+pub(super) fn check(
+    cx: &LateContext<'_>,
+    expr: &Expr<'_>,
+    method_name: Symbol,
+    receiver: &Expr<'_>,
+    args: &[Expr<'_>],
+) {
+    let arg = if method_name == sym::clone && args.is_empty() { receiver } else { return };
     if cx
         .typeck_results()
         .type_dependent_def_id(expr.hir_id)
@@ -81,7 +84,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symbol,
                 // &*x is a nop, &x.clone() is not
                 ExprKind::AddrOf(..) => return,
                 // (*x).func() is useless, x.clone().func() can work in case func borrows self
-                ExprKind::MethodCall(_, [self_arg, ..], _)
+                ExprKind::MethodCall(_, self_arg, ..)
                     if expr.hir_id == self_arg.hir_id && ty != cx.typeck_results().expr_ty_adjusted(expr) =>
                 {
                     return;
@@ -91,19 +94,14 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symbol,
                     hir_callee.kind,
                     ExprKind::Path(QPath::LangItem(rustc_hir::LangItem::TryTraitBranch, _, _))
                 ),
-                ExprKind::MethodCall(_, [self_arg, ..], _) if expr.hir_id == self_arg.hir_id => true,
+                ExprKind::MethodCall(_, self_arg, ..) if expr.hir_id == self_arg.hir_id => true,
                 ExprKind::Match(_, _, MatchSource::TryDesugar | MatchSource::AwaitDesugar)
                 | ExprKind::Field(..)
                 | ExprKind::Index(..) => true,
                 _ => false,
             },
             // local binding capturing a reference
-            Some(Node::Local(l))
-                if matches!(
-                    l.pat.kind,
-                    PatKind::Binding(BindingAnnotation::Ref | BindingAnnotation::RefMut, ..)
-                ) =>
-            {
+            Some(Node::Local(l)) if matches!(l.pat.kind, PatKind::Binding(BindingAnnotation(ByRef::Yes, _), ..)) => {
                 return;
             },
             _ => false,
index 6417bc81304739e9c72ac75a9fb1c9d4045e097f..f82ca8912006180b5b853dd57f8af0538c423976 100644 (file)
 
 use super::CLONE_ON_REF_PTR;
 
-pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Symbol, args: &[hir::Expr<'_>]) {
-    if !(args.len() == 1 && method_name == sym::clone) {
+pub(super) fn check(
+    cx: &LateContext<'_>,
+    expr: &hir::Expr<'_>,
+    method_name: Symbol,
+    receiver: &hir::Expr<'_>,
+    args: &[hir::Expr<'_>],
+) {
+    if !(args.is_empty() && method_name == sym::clone) {
         return;
     }
-    let arg = &args[0];
-    let obj_ty = cx.typeck_results().expr_ty(arg).peel_refs();
+    let obj_ty = cx.typeck_results().expr_ty(receiver).peel_refs();
 
     if let ty::Adt(_, subst) = obj_ty.kind() {
         let caller_type = if is_type_diagnostic_item(cx, obj_ty, sym::Rc) {
@@ -28,7 +33,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Sym
             return;
         };
 
-        let snippet = snippet_with_macro_callsite(cx, arg.span, "..");
+        let snippet = snippet_with_macro_callsite(cx, receiver.span, "..");
 
         span_lint_and_sugg(
             cx,
index 561033be5b6af3945bfadf83c6903a56b7f486c9..501646863fe156c4fab56cc8452f2e23cf7e65f9 100644 (file)
@@ -23,7 +23,7 @@ pub(super) fn check<'tcx>(
         // If the parent node's `to` argument is the same as the `to` argument
         // of the last replace call in the current chain, don't lint as it was already linted
         if let Some(parent) = get_parent_expr(cx, expr)
-            && let Some(("replace", [_, current_from, current_to], _)) = method_call(parent)
+            && let Some(("replace", _, [current_from, current_to], _)) = method_call(parent)
             && eq_expr_value(cx, to, current_to)
             && from_kind == cx.typeck_results().expr_ty(current_from).peel_refs().kind()
         {
@@ -48,7 +48,7 @@ fn collect_replace_calls<'tcx>(
     let mut from_args = VecDeque::new();
 
     let _: Option<()> = for_each_expr(expr, |e| {
-        if let Some(("replace", [_, from, to], _)) = method_call(e) {
+        if let Some(("replace", _, [from, to], _)) = method_call(e) {
             if eq_expr_value(cx, to_arg, to) && cx.typeck_results().expr_ty(from).peel_refs().is_char() {
                 methods.push_front(e);
                 from_args.push_front(from);
@@ -78,7 +78,7 @@ fn check_consecutive_replace_calls<'tcx>(
         .collect();
     let app = Applicability::MachineApplicable;
     let earliest_replace_call = replace_methods.methods.front().unwrap();
-    if let Some((_, [..], span_lo)) = method_call(earliest_replace_call) {
+    if let Some((_, _, [..], span_lo)) = method_call(earliest_replace_call) {
         span_lint_and_sugg(
             cx,
             COLLAPSIBLE_STR_REPLACE,
index 6f2307d8f18ff1505acd84603ff2003c3f0e1feb..bd846d71d4668ed29288ea248849193432903462 100644 (file)
@@ -19,6 +19,7 @@ pub(super) fn check<'tcx>(
     expr: &hir::Expr<'_>,
     method_span: Span,
     name: &str,
+    receiver: &'tcx hir::Expr<'tcx>,
     args: &'tcx [hir::Expr<'tcx>],
 ) {
     // Strip `&`, `as_ref()` and `as_str()` off `arg` until we're left with either a `String` or
@@ -28,16 +29,13 @@ fn get_arg_root<'a>(cx: &LateContext<'_>, arg: &'a hir::Expr<'a>) -> &'a hir::Ex
         loop {
             arg_root = match &arg_root.kind {
                 hir::ExprKind::AddrOf(hir::BorrowKind::Ref, _, expr) => expr,
-                hir::ExprKind::MethodCall(method_name, call_args, _) => {
-                    if call_args.len() == 1
-                        && (method_name.ident.name == sym::as_str || method_name.ident.name == sym::as_ref)
-                        && {
-                            let arg_type = cx.typeck_results().expr_ty(&call_args[0]);
-                            let base_type = arg_type.peel_refs();
-                            *base_type.kind() == ty::Str || is_type_diagnostic_item(cx, base_type, sym::String)
-                        }
-                    {
-                        &call_args[0]
+                hir::ExprKind::MethodCall(method_name, receiver, [], ..) => {
+                    if (method_name.ident.name == sym::as_str || method_name.ident.name == sym::as_ref) && {
+                        let arg_type = cx.typeck_results().expr_ty(receiver);
+                        let base_type = arg_type.peel_refs();
+                        *base_type.kind() == ty::Str || is_type_diagnostic_item(cx, base_type, sym::String)
+                    } {
+                        receiver
                     } else {
                         break;
                     }
@@ -114,11 +112,11 @@ fn is_call(node: &hir::ExprKind<'_>) -> bool {
         }
     }
 
-    if args.len() != 2 || name != "expect" || !is_call(&args[1].kind) {
+    if args.len() != 1 || name != "expect" || !is_call(&args[0].kind) {
         return;
     }
 
-    let receiver_type = cx.typeck_results().expr_ty_adjusted(&args[0]);
+    let receiver_type = cx.typeck_results().expr_ty_adjusted(receiver);
     let closure_args = if is_type_diagnostic_item(cx, receiver_type, sym::Option) {
         "||"
     } else if is_type_diagnostic_item(cx, receiver_type, sym::Result) {
@@ -127,7 +125,7 @@ fn is_call(node: &hir::ExprKind<'_>) -> bool {
         return;
     };
 
-    let arg_root = get_arg_root(cx, &args[1]);
+    let arg_root = get_arg_root(cx, &args[0]);
 
     let span_replace_word = method_span.with_hi(expr.span.hi());
 
index a15fe609402251db53e17ba0ba32c8c3fee7d45b..37b28463527cc5c3bcfe01233a19770ed0f6fe76 100644 (file)
@@ -14,7 +14,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg:
     if_chain! {
         if is_type_diagnostic_item(cx, ty, sym::Vec);
         //check source object
-        if let ExprKind::MethodCall(src_method, [drain_vec, drain_arg], _) = &arg.kind;
+        if let ExprKind::MethodCall(src_method, drain_vec, [drain_arg], _) = &arg.kind;
         if src_method.ident.as_str() == "drain";
         let src_ty = cx.typeck_results().expr_ty(drain_vec);
         //check if actual src type is mutable for code suggestion
index 692e22a7c5cf7138dbbc0f7cf6df0f06228721b3..9dc839afc6256e8c9b89d8d51d3e8fd1c74f9543 100644 (file)
@@ -28,11 +28,11 @@ fn is_method<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, method_name: Sy
             let closure_expr = peel_blocks(&body.value);
             let arg_id = body.params[0].pat.hir_id;
             match closure_expr.kind {
-                hir::ExprKind::MethodCall(hir::PathSegment { ident, .. }, args, _) => {
+                hir::ExprKind::MethodCall(hir::PathSegment { ident, .. }, receiver, ..) => {
                     if_chain! {
                     if ident.name == method_name;
-                    if let hir::ExprKind::Path(path) = &args[0].kind;
-                    if let Res::Local(ref local) = cx.qpath_res(path, args[0].hir_id);
+                    if let hir::ExprKind::Path(path) = &receiver.kind;
+                    if let Res::Local(ref local) = cx.qpath_res(path, receiver.hir_id);
                     then {
                         return arg_id == *local
                     }
@@ -106,7 +106,7 @@ pub(super) fn check<'tcx>(
             };
             // closure ends with is_some() or is_ok()
             if let PatKind::Binding(_, filter_param_id, _, None) = filter_pat.kind;
-            if let ExprKind::MethodCall(path, [filter_arg], _) = filter_body.value.kind;
+            if let ExprKind::MethodCall(path, filter_arg, [], _) = filter_body.value.kind;
             if let Some(opt_ty) = cx.typeck_results().expr_ty(filter_arg).peel_refs().ty_adt_def();
             if let Some(is_result) = if cx.tcx.is_diagnostic_item(sym::Option, opt_ty.did()) {
                 Some(false)
@@ -123,13 +123,13 @@ pub(super) fn check<'tcx>(
             if let [map_param] = map_body.params;
             if let PatKind::Binding(_, map_param_id, map_param_ident, None) = map_param.pat.kind;
             // closure ends with expect() or unwrap()
-            if let ExprKind::MethodCall(seg, [map_arg, ..], _) = map_body.value.kind;
+            if let ExprKind::MethodCall(seg, map_arg, ..) = map_body.value.kind;
             if matches!(seg.ident.name, sym::expect | sym::unwrap | sym::unwrap_or);
 
             // .filter(..).map(|y| f(y).copied().unwrap())
             //                     ~~~~
             let map_arg_peeled = match map_arg.kind {
-                ExprKind::MethodCall(method, [original_arg], _) if acceptable_methods(method) => {
+                ExprKind::MethodCall(method, original_arg, [], _) if acceptable_methods(method) => {
                     original_arg
                 },
                 _ => map_arg,
index 23368238ef5cce6511ff799e008287b5b9fc4ccd..02aada87202c26cd2afb3d744e0f304850c7d1c1 100644 (file)
@@ -22,7 +22,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg:
     ) = arg.kind
 
         // LHS of subtraction is "x.len()"
-        && let ExprKind::MethodCall(lhs_path, [lhs_recv], _) = &lhs.kind
+        && let ExprKind::MethodCall(lhs_path, lhs_recv, [], _) = &lhs.kind
         && lhs_path.ident.name == sym::len
 
         // RHS of subtraction is 1
index f52170df662ca666bbaf7eee1bcbadb2d4f2f05b..e1c9b5248a8a4f912c434a6f1a8886d9e59b7dcd 100644 (file)
 use super::INEFFICIENT_TO_STRING;
 
 /// Checks for the `INEFFICIENT_TO_STRING` lint
-pub fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, method_name: Symbol, args: &[hir::Expr<'_>]) {
+pub fn check<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &hir::Expr<'_>,
+    method_name: Symbol,
+    receiver: &hir::Expr<'_>,
+    args: &[hir::Expr<'_>],
+) {
     if_chain! {
-        if args.len() == 1 && method_name == sym::to_string;
+        if args.is_empty() && method_name == sym::to_string;
         if let Some(to_string_meth_did) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
         if match_def_path(cx, to_string_meth_did, &paths::TO_STRING_METHOD);
         if let Some(substs) = cx.typeck_results().node_substs_opt(expr.hir_id);
-        let arg_ty = cx.typeck_results().expr_ty_adjusted(&args[0]);
+        let arg_ty = cx.typeck_results().expr_ty_adjusted(receiver);
         let self_ty = substs.type_at(0);
         let (deref_self_ty, deref_count) = walk_ptrs_ty_depth(self_ty);
         if deref_count >= 1;
@@ -35,7 +41,7 @@ pub fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, method_name: Sy
                         self_ty, deref_self_ty
                     ));
                     let mut applicability = Applicability::MachineApplicable;
-                    let arg_snippet = snippet_with_applicability(cx, args[0].span, "..", &mut applicability);
+                    let arg_snippet = snippet_with_applicability(cx, receiver.span, "..", &mut applicability);
                     diag.span_suggestion(
                         expr.span,
                         "try dereferencing the receiver",
index da13b4ba37a562f6c06d2e39714cb3a90a8e0278..11e76841e9f054425257442a1e2f7e825d7f21d1 100644 (file)
@@ -16,9 +16,9 @@ pub(super) fn check(
     expr: &hir::Expr<'_>,
     method_span: Span,
     method_name: Symbol,
-    args: &[hir::Expr<'_>],
+    receiver: &hir::Expr<'_>,
 ) {
-    let self_ty = cx.typeck_results().expr_ty_adjusted(&args[0]);
+    let self_ty = cx.typeck_results().expr_ty_adjusted(receiver);
     if_chain! {
         if let ty::Ref(..) = self_ty.kind();
         if method_name == sym::into_iter;
index 43e9451f7d37eb4f42b24e2b1bb39d2c5b8c74e8..beb772100affcb1e5f1351c413c0a656b0baeae7 100644 (file)
@@ -24,7 +24,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr
                     if let Some(id) = path_to_local(recv);
                     if let Node::Pat(pat) = cx.tcx.hir().get(id);
                     if let PatKind::Binding(ann, _, _, _)  = pat.kind;
-                    if ann != BindingAnnotation::Mutable;
+                    if ann != BindingAnnotation::MUT;
                     then {
                         application = Applicability::Unspecified;
                         diag.span_help(
index 152072e09c77275795922332495b9622baea5335..a669cbbbcc602c77c4fc59c6bad177892751111f 100644 (file)
@@ -35,7 +35,7 @@ fn is_full_range(cx: &LateContext<'_>, container: &Expr<'_>, range: Range<'_>) -
         && range.end.map_or(true, |e| {
             if range.limits == RangeLimits::HalfOpen
                 && let ExprKind::Path(QPath::Resolved(None, container_path)) = container.kind
-                && let ExprKind::MethodCall(name, [self_arg], _) = e.kind
+                && let ExprKind::MethodCall(name, self_arg, [], _) = e.kind
                 && name.ident.name == sym::len
                 && let ExprKind::Path(QPath::Resolved(None, path)) = self_arg.kind
             {
index ffedda95ff8e57870170c940bebf4933f107e3e4..e8442091fd3067fd3717c397856770c6055d17de 100644 (file)
@@ -33,13 +33,13 @@ pub(super) fn check<'tcx>(
             let closure_expr = peel_blocks(&closure_body.value);
             match closure_body.params[0].pat.kind {
                 hir::PatKind::Ref(inner, hir::Mutability::Not) => if let hir::PatKind::Binding(
-                    hir::BindingAnnotation::Unannotated, .., name, None
+                    hir::BindingAnnotation::NONE, .., name, None
                 ) = inner.kind {
                     if ident_eq(name, closure_expr) {
                         lint_explicit_closure(cx, e.span, recv.span, true, msrv);
                     }
                 },
-                hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, .., name, None) => {
+                hir::PatKind::Binding(hir::BindingAnnotation::NONE, .., name, None) => {
                     match closure_expr.kind {
                         hir::ExprKind::Unary(hir::UnOp::Deref, inner) => {
                             if ident_eq(name, inner) {
@@ -48,7 +48,7 @@ pub(super) fn check<'tcx>(
                                 }
                             }
                         },
-                        hir::ExprKind::MethodCall(method, [obj], _) => if_chain! {
+                        hir::ExprKind::MethodCall(method, obj, [], _) => if_chain! {
                             if ident_eq(name, obj) && method.ident.name == sym::clone;
                             if let Some(fn_id) = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id);
                             if let Some(trait_id) = cx.tcx.trait_of_item(fn_id);
index a0d190a58aff9a7f10478600f0d8ddab1b3b2840..fc9ba15d82a40e4e00f59c35ef8c378c43e28847 100644 (file)
@@ -3161,11 +3161,13 @@ pub fn new(
 ]);
 
 /// Extracts a method call name, args, and `Span` of the method name.
-fn method_call<'tcx>(recv: &'tcx hir::Expr<'tcx>) -> Option<(&'tcx str, &'tcx [hir::Expr<'tcx>], Span)> {
-    if let ExprKind::MethodCall(path, args, _) = recv.kind {
-        if !args.iter().any(|e| e.span.from_expansion()) {
+fn method_call<'tcx>(
+    recv: &'tcx hir::Expr<'tcx>,
+) -> Option<(&'tcx str, &'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>], Span)> {
+    if let ExprKind::MethodCall(path, receiver, args, _) = recv.kind {
+        if !args.iter().any(|e| e.span.from_expansion()) && !receiver.span.from_expansion() {
             let name = path.ident.name.as_str();
-            return Some((name, args, path.ident.span));
+            return Some((name, receiver, args, path.ident.span));
         }
     }
     None
@@ -3183,17 +3185,17 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
             hir::ExprKind::Call(func, args) => {
                 from_iter_instead_of_collect::check(cx, expr, args, func);
             },
-            hir::ExprKind::MethodCall(method_call, args, _) => {
+            hir::ExprKind::MethodCall(method_call, receiver, args, _) => {
                 let method_span = method_call.ident.span;
-                or_fun_call::check(cx, expr, method_span, method_call.ident.as_str(), args);
-                expect_fun_call::check(cx, expr, method_span, method_call.ident.as_str(), args);
-                clone_on_copy::check(cx, expr, method_call.ident.name, args);
-                clone_on_ref_ptr::check(cx, expr, method_call.ident.name, args);
-                inefficient_to_string::check(cx, expr, method_call.ident.name, args);
-                single_char_add_str::check(cx, expr, args);
-                into_iter_on_ref::check(cx, expr, method_span, method_call.ident.name, args);
-                single_char_pattern::check(cx, expr, method_call.ident.name, args);
-                unnecessary_to_owned::check(cx, expr, method_call.ident.name, args, self.msrv);
+                or_fun_call::check(cx, expr, method_span, method_call.ident.as_str(), receiver, args);
+                expect_fun_call::check(cx, expr, method_span, method_call.ident.as_str(), receiver, args);
+                clone_on_copy::check(cx, expr, method_call.ident.name, receiver, args);
+                clone_on_ref_ptr::check(cx, expr, method_call.ident.name, receiver, args);
+                inefficient_to_string::check(cx, expr, method_call.ident.name, receiver, args);
+                single_char_add_str::check(cx, expr, receiver, args);
+                into_iter_on_ref::check(cx, expr, method_span, method_call.ident.name, receiver);
+                single_char_pattern::check(cx, expr, method_call.ident.name, receiver, args);
+                unnecessary_to_owned::check(cx, expr, method_call.ident.name, receiver, args, self.msrv);
             },
             hir::ExprKind::Binary(op, lhs, rhs) if op.node == hir::BinOpKind::Eq || op.node == hir::BinOpKind::Ne => {
                 let mut info = BinaryExprInfo {
@@ -3379,7 +3381,7 @@ fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>
 impl Methods {
     #[allow(clippy::too_many_lines)]
     fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if let Some((name, [recv, args @ ..], span)) = method_call(expr) {
+        if let Some((name, recv, args, span)) = method_call(expr) {
             match (name, args) {
                 ("add" | "offset" | "sub" | "wrapping_offset" | "wrapping_add" | "wrapping_sub", [_arg]) => {
                     zst_offset::check(cx, expr, recv);
@@ -3399,13 +3401,13 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
                 ("assume_init", []) => uninit_assumed_init::check(cx, expr, recv),
                 ("cloned", []) => cloned_instead_of_copied::check(cx, expr, recv, span, self.msrv),
                 ("collect", []) => match method_call(recv) {
-                    Some((name @ ("cloned" | "copied"), [recv2], _)) => {
+                    Some((name @ ("cloned" | "copied"), recv2, [], _)) => {
                         iter_cloned_collect::check(cx, name, expr, recv2);
                     },
-                    Some(("map", [m_recv, m_arg], _)) => {
+                    Some(("map", m_recv, [m_arg], _)) => {
                         map_collect_result_unit::check(cx, expr, m_recv, m_arg, recv);
                     },
-                    Some(("take", [take_self_arg, take_arg], _)) => {
+                    Some(("take", take_self_arg, [take_arg], _)) => {
                         if meets_msrv(self.msrv, msrvs::STR_REPEAT) {
                             manual_str_repeat::check(cx, expr, recv, take_self_arg, take_arg);
                         }
@@ -3413,26 +3415,26 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
                     _ => {},
                 },
                 ("count", []) if is_trait_method(cx, expr, sym::Iterator) => match method_call(recv) {
-                    Some(("cloned", [recv2], _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, true, false),
-                    Some((name2 @ ("into_iter" | "iter" | "iter_mut"), [recv2], _)) => {
+                    Some(("cloned", recv2, [], _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, true, false),
+                    Some((name2 @ ("into_iter" | "iter" | "iter_mut"), recv2, [], _)) => {
                         iter_count::check(cx, expr, recv2, name2);
                     },
-                    Some(("map", [_, arg], _)) => suspicious_map::check(cx, expr, recv, arg),
-                    Some(("filter", [recv2, arg], _)) => bytecount::check(cx, expr, recv2, arg),
-                    Some(("bytes", [recv2], _)) => bytes_count_to_len::check(cx, expr, recv, recv2),
+                    Some(("map", _, [arg], _)) => suspicious_map::check(cx, expr, recv, arg),
+                    Some(("filter", recv2, [arg], _)) => bytecount::check(cx, expr, recv2, arg),
+                    Some(("bytes", recv2, [], _)) => bytes_count_to_len::check(cx, expr, recv, recv2),
                     _ => {},
                 },
                 ("drain", [arg]) => {
                     iter_with_drain::check(cx, expr, recv, span, arg);
                 },
                 ("ends_with", [arg]) => {
-                    if let ExprKind::MethodCall(_, _, span) = expr.kind {
+                    if let ExprKind::MethodCall(.., span) = expr.kind {
                         case_sensitive_file_extension_comparisons::check(cx, expr, span, recv, arg);
                     }
                 },
                 ("expect", [_]) => match method_call(recv) {
-                    Some(("ok", [recv], _)) => ok_expect::check(cx, expr, recv),
-                    Some(("err", [recv], err_span)) => err_expect::check(cx, expr, recv, self.msrv, span, err_span),
+                    Some(("ok", recv, [], _)) => ok_expect::check(cx, expr, recv),
+                    Some(("err", recv, [], err_span)) => err_expect::check(cx, expr, recv, self.msrv, span, err_span),
                     _ => expect_used::check(cx, expr, recv, false, self.allow_expect_in_tests),
                 },
                 ("expect_err", [_]) => expect_used::check(cx, expr, recv, true, self.allow_expect_in_tests),
@@ -3452,13 +3454,13 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
                     flat_map_option::check(cx, expr, arg, span);
                 },
                 ("flatten", []) => match method_call(recv) {
-                    Some(("map", [recv, map_arg], map_span)) => map_flatten::check(cx, expr, recv, map_arg, map_span),
-                    Some(("cloned", [recv2], _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, false, true),
+                    Some(("map", recv, [map_arg], map_span)) => map_flatten::check(cx, expr, recv, map_arg, map_span),
+                    Some(("cloned", recv2, [], _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, false, true),
                     _ => {},
                 },
                 ("fold", [init, acc]) => unnecessary_fold::check(cx, expr, init, acc, span),
                 ("for_each", [_]) => {
-                    if let Some(("inspect", [_, _], span2)) = method_call(recv) {
+                    if let Some(("inspect", _, [_], span2)) = method_call(recv) {
                         inspect_for_each::check(cx, expr, span2);
                     }
                 },
@@ -3478,12 +3480,12 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
                     iter_on_single_or_empty_collections::check(cx, expr, name, recv);
                 },
                 ("join", [join_arg]) => {
-                    if let Some(("collect", _, span)) = method_call(recv) {
+                    if let Some(("collect", _, _, span)) = method_call(recv) {
                         unnecessary_join::check(cx, expr, recv, join_arg, span);
                     }
                 },
                 ("last", []) | ("skip", [_]) => {
-                    if let Some((name2, [recv2, args2 @ ..], _span2)) = method_call(recv) {
+                    if let Some((name2, recv2, args2, _span2)) = method_call(recv) {
                         if let ("cloned", []) = (name2, args2) {
                             iter_overeager_cloned::check(cx, expr, recv, recv2, false, false);
                         }
@@ -3498,7 +3500,7 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
                     } else {
                         map_err_ignore::check(cx, expr, m_arg);
                     }
-                    if let Some((name, [recv2, args @ ..], span2)) = method_call(recv) {
+                    if let Some((name, recv2, args, span2)) = method_call(recv) {
                         match (name, args) {
                             ("as_mut", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, true, self.msrv),
                             ("as_ref", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, false, self.msrv),
@@ -3518,7 +3520,7 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
                     manual_ok_or::check(cx, expr, recv, def, map);
                 },
                 ("next", []) => {
-                    if let Some((name2, [recv2, args2 @ ..], _)) = method_call(recv) {
+                    if let Some((name2, recv2, args2, _)) = method_call(recv) {
                         match (name2, args2) {
                             ("cloned", []) => iter_overeager_cloned::check(cx, expr, recv, recv2, false, false),
                             ("filter", [arg]) => filter_next::check(cx, expr, recv2, arg),
@@ -3531,10 +3533,10 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
                     }
                 },
                 ("nth", [n_arg]) => match method_call(recv) {
-                    Some(("bytes", [recv2], _)) => bytes_nth::check(cx, expr, recv2, n_arg),
-                    Some(("cloned", [recv2], _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, false, false),
-                    Some(("iter", [recv2], _)) => iter_nth::check(cx, expr, recv2, recv, n_arg, false),
-                    Some(("iter_mut", [recv2], _)) => iter_nth::check(cx, expr, recv2, recv, n_arg, true),
+                    Some(("bytes", recv2, [], _)) => bytes_nth::check(cx, expr, recv2, n_arg),
+                    Some(("cloned", recv2, [], _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, false, false),
+                    Some(("iter", recv2, [], _)) => iter_nth::check(cx, expr, recv2, recv, n_arg, false),
+                    Some(("iter_mut", recv2, [], _)) => iter_nth::check(cx, expr, recv2, recv, n_arg, true),
                     _ => iter_nth_zero::check(cx, expr, recv, n_arg),
                 },
                 ("ok_or_else", [arg]) => unnecessary_lazy_eval::check(cx, expr, recv, arg, "ok_or"),
@@ -3591,7 +3593,7 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
                 },
                 ("step_by", [arg]) => iterator_step_by_zero::check(cx, expr, arg),
                 ("take", [_arg]) => {
-                    if let Some((name2, [recv2, args2 @ ..], _span2)) = method_call(recv) {
+                    if let Some((name2, recv2, args2, _span2)) = method_call(recv) {
                         if let ("cloned", []) = (name2, args2) {
                             iter_overeager_cloned::check(cx, expr, recv, recv2, false, false);
                         }
@@ -3614,13 +3616,13 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
                 },
                 ("unwrap", []) => {
                     match method_call(recv) {
-                        Some(("get", [recv, get_arg], _)) => {
+                        Some(("get", recv, [get_arg], _)) => {
                             get_unwrap::check(cx, expr, recv, get_arg, false);
                         },
-                        Some(("get_mut", [recv, get_arg], _)) => {
+                        Some(("get_mut", recv, [get_arg], _)) => {
                             get_unwrap::check(cx, expr, recv, get_arg, true);
                         },
-                        Some(("or", [recv, or_arg], or_span)) => {
+                        Some(("or", recv, [or_arg], or_span)) => {
                             or_then_unwrap::check(cx, expr, recv, or_arg, or_span);
                         },
                         _ => {},
@@ -3629,19 +3631,19 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
                 },
                 ("unwrap_err", []) => unwrap_used::check(cx, expr, recv, true, self.allow_unwrap_in_tests),
                 ("unwrap_or", [u_arg]) => match method_call(recv) {
-                    Some((arith @ ("checked_add" | "checked_sub" | "checked_mul"), [lhs, rhs], _)) => {
+                    Some((arith @ ("checked_add" | "checked_sub" | "checked_mul"), lhs, [rhs], _)) => {
                         manual_saturating_arithmetic::check(cx, expr, lhs, rhs, u_arg, &arith["checked_".len()..]);
                     },
-                    Some(("map", [m_recv, m_arg], span)) => {
+                    Some(("map", m_recv, [m_arg], span)) => {
                         option_map_unwrap_or::check(cx, expr, m_recv, m_arg, recv, u_arg, span);
                     },
-                    Some(("then_some", [t_recv, t_arg], _)) => {
+                    Some(("then_some", t_recv, [t_arg], _)) => {
                         obfuscated_if_else::check(cx, expr, t_recv, t_arg, u_arg);
                     },
                     _ => {},
                 },
                 ("unwrap_or_else", [u_arg]) => match method_call(recv) {
-                    Some(("map", [recv, map_arg], _))
+                    Some(("map", recv, [map_arg], _))
                         if map_unwrap_or::check(cx, expr, recv, map_arg, u_arg, self.msrv) => {},
                     _ => {
                         unwrap_or_else_default::check(cx, expr, recv, u_arg);
@@ -3649,7 +3651,7 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
                     },
                 },
                 ("zip", [arg]) => {
-                    if let ExprKind::MethodCall(name, [iter_recv], _) = recv.kind
+                    if let ExprKind::MethodCall(name, iter_recv, [], _) = recv.kind
                         && name.ident.name == sym::iter
                     {
                         range_zip_with_len::check(cx, expr, iter_recv, arg);
@@ -3662,7 +3664,7 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
 }
 
 fn check_is_some_is_none(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, is_some: bool) {
-    if let Some((name @ ("find" | "position" | "rposition"), [f_recv, arg], span)) = method_call(recv) {
+    if let Some((name @ ("find" | "position" | "rposition"), f_recv, [arg], span)) = method_call(recv) {
         search_is_some::check(cx, expr, name, is_some, f_recv, arg, recv, span);
     }
 }
index c3112823e3469eeb576f601f8ed71f31a19b5dd9..903fa306f935a8e6b005c7c67e6323b6ad706a27 100644 (file)
@@ -36,12 +36,12 @@ enum OpenOption {
 }
 
 fn get_open_options(cx: &LateContext<'_>, argument: &Expr<'_>, options: &mut Vec<(OpenOption, Argument)>) {
-    if let ExprKind::MethodCall(path, arguments, _) = argument.kind {
-        let obj_ty = cx.typeck_results().expr_ty(&arguments[0]).peel_refs();
+    if let ExprKind::MethodCall(path, receiver, arguments, _) = argument.kind {
+        let obj_ty = cx.typeck_results().expr_ty(receiver).peel_refs();
 
         // Only proceed if this is a call on some object of type std::fs::OpenOptions
-        if match_type(cx, obj_ty, &paths::OPEN_OPTIONS) && arguments.len() >= 2 {
-            let argument_option = match arguments[1].kind {
+        if match_type(cx, obj_ty, &paths::OPEN_OPTIONS) && arguments.len() >= 1 {
+            let argument_option = match arguments[0].kind {
                 ExprKind::Lit(ref span) => {
                     if let Spanned {
                         node: LitKind::Bool(lit),
@@ -77,7 +77,7 @@ fn get_open_options(cx: &LateContext<'_>, argument: &Expr<'_>, options: &mut Vec
                 _ => (),
             }
 
-            get_open_options(cx, &arguments[0], options);
+            get_open_options(cx, receiver, options);
         }
     }
 }
index 20cad0f181e951dcb22d5b69cc7a90c717eef42e..81c67b4ca6a59d0816908e88e600eeff66e13e38 100644 (file)
@@ -56,13 +56,12 @@ pub(super) fn check<'tcx>(
             let closure_expr = peel_blocks(&closure_body.value);
 
             match &closure_expr.kind {
-                hir::ExprKind::MethodCall(_, args, _) => {
+                hir::ExprKind::MethodCall(_, receiver, [], _) => {
                     if_chain! {
-                        if args.len() == 1;
-                        if path_to_local_id(&args[0], closure_body.params[0].pat.hir_id);
+                        if path_to_local_id(receiver, closure_body.params[0].pat.hir_id);
                         let adj = cx
                             .typeck_results()
-                            .expr_adjustments(&args[0])
+                            .expr_adjustments(receiver)
                             .iter()
                             .map(|x| &x.kind)
                             .collect::<Box<[_]>>();
index 6af134019a472956958a698163b7837c6a5b9ea3..76876d8662936846bb7766db36547df3903900a5 100644 (file)
@@ -20,6 +20,7 @@ pub(super) fn check<'tcx>(
     expr: &hir::Expr<'_>,
     method_span: Span,
     name: &str,
+    receiver: &'tcx hir::Expr<'_>,
     args: &'tcx [hir::Expr<'_>],
 ) {
     /// Checks for `unwrap_or(T::new())` or `unwrap_or(T::default())`.
@@ -144,7 +145,7 @@ fn check_general_case<'tcx>(
         }
     }
 
-    if let [self_arg, arg] = args {
+    if let [arg] = args {
         let inner_arg = if let hir::ExprKind::Block(
             hir::Block {
                 stmts: [],
@@ -163,11 +164,11 @@ fn check_general_case<'tcx>(
                 let or_has_args = !or_args.is_empty();
                 if !check_unwrap_or_default(cx, name, fun, arg, or_has_args, expr.span, method_span) {
                     let fun_span = if or_has_args { None } else { Some(fun.span) };
-                    check_general_case(cx, name, method_span, self_arg, arg, expr.span, fun_span);
+                    check_general_case(cx, name, method_span, receiver, arg, expr.span, fun_span);
                 }
             },
             hir::ExprKind::Index(..) | hir::ExprKind::MethodCall(..) => {
-                check_general_case(cx, name, method_span, self_arg, arg, expr.span, None);
+                check_general_case(cx, name, method_span, receiver, arg, expr.span, None);
             },
             _ => (),
         }
index 00a2a0d14d1132946ef80749581d3e0e12644ea8..867a3b4023770e6e162bc2227960022866d10cc5 100644 (file)
@@ -16,7 +16,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &'
         if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::Range::hir(zip_arg);
         if is_integer_const(cx, start, 0);
         // `.len()` call
-        if let ExprKind::MethodCall(len_path, [len_recv], _) = end.kind;
+        if let ExprKind::MethodCall(len_path, len_recv, [], _) = end.kind;
         if len_path.ident.name == sym::len;
         // `.iter()` and `.len()` called on same `Path`
         if let ExprKind::Path(QPath::Resolved(_, iter_path)) = recv.kind;
index 9a5fabcf7cd5064e9ef86af014f83882ae6e5d09..81450fd8c6c3c565faa9350ef60f2b868e181e03 100644 (file)
@@ -3,12 +3,12 @@
 use rustc_hir as hir;
 use rustc_lint::LateContext;
 
-pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
+pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, receiver: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
     if let Some(fn_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) {
         if match_def_path(cx, fn_def_id, &paths::PUSH_STR) {
-            single_char_push_string::check(cx, expr, args);
+            single_char_push_string::check(cx, expr, receiver, args);
         } else if match_def_path(cx, fn_def_id, &paths::INSERT_STR) {
-            single_char_insert_string::check(cx, expr, args);
+            single_char_insert_string::check(cx, expr, receiver, args);
         }
     }
 }
index 6cdc954c03be15ea38f0f15e587104e09ea61a78..18b6b5be175d14f34ecb22093fc49d354482ce53 100644 (file)
@@ -8,12 +8,12 @@
 use super::SINGLE_CHAR_ADD_STR;
 
 /// lint for length-1 `str`s as argument for `insert_str`
-pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
+pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, receiver: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
     let mut applicability = Applicability::MachineApplicable;
-    if let Some(extension_string) = get_hint_if_single_char_arg(cx, &args[2], &mut applicability) {
+    if let Some(extension_string) = get_hint_if_single_char_arg(cx, &args[1], &mut applicability) {
         let base_string_snippet =
-            snippet_with_applicability(cx, args[0].span.source_callsite(), "_", &mut applicability);
-        let pos_arg = snippet_with_applicability(cx, args[1].span, "..", &mut applicability);
+            snippet_with_applicability(cx, receiver.span.source_callsite(), "_", &mut applicability);
+        let pos_arg = snippet_with_applicability(cx, args[0].span, "..", &mut applicability);
         let sugg = format!("{}.insert({}, {})", base_string_snippet, pos_arg, extension_string);
         span_lint_and_sugg(
             cx,
index bf9006c690621031f1056c6ee0ac8efb45577d39..4221c52d5cd79a57924fa2b8af6ed4caaf3b8c4a 100644 (file)
 use super::SINGLE_CHAR_PATTERN;
 
 const PATTERN_METHODS: [(&str, usize); 24] = [
-    ("contains", 1),
-    ("starts_with", 1),
-    ("ends_with", 1),
-    ("find", 1),
-    ("rfind", 1),
-    ("split", 1),
-    ("split_inclusive", 1),
-    ("rsplit", 1),
-    ("split_terminator", 1),
-    ("rsplit_terminator", 1),
-    ("splitn", 2),
-    ("rsplitn", 2),
-    ("split_once", 1),
-    ("rsplit_once", 1),
-    ("matches", 1),
-    ("rmatches", 1),
-    ("match_indices", 1),
-    ("rmatch_indices", 1),
-    ("strip_prefix", 1),
-    ("strip_suffix", 1),
-    ("trim_start_matches", 1),
-    ("trim_end_matches", 1),
-    ("replace", 1),
-    ("replacen", 1),
+    ("contains", 0),
+    ("starts_with", 0),
+    ("ends_with", 0),
+    ("find", 0),
+    ("rfind", 0),
+    ("split", 0),
+    ("split_inclusive", 0),
+    ("rsplit", 0),
+    ("split_terminator", 0),
+    ("rsplit_terminator", 0),
+    ("splitn", 1),
+    ("rsplitn", 1),
+    ("split_once", 0),
+    ("rsplit_once", 0),
+    ("matches", 0),
+    ("rmatches", 0),
+    ("match_indices", 0),
+    ("rmatch_indices", 0),
+    ("strip_prefix", 0),
+    ("strip_suffix", 0),
+    ("trim_start_matches", 0),
+    ("trim_end_matches", 0),
+    ("replace", 0),
+    ("replacen", 0),
 ];
 
 /// lint for length-1 `str`s for methods in `PATTERN_METHODS`
-pub(super) fn check(cx: &LateContext<'_>, _expr: &hir::Expr<'_>, method_name: Symbol, args: &[hir::Expr<'_>]) {
+pub(super) fn check(
+    cx: &LateContext<'_>,
+    _expr: &hir::Expr<'_>,
+    method_name: Symbol,
+    receiver: &hir::Expr<'_>,
+    args: &[hir::Expr<'_>],
+) {
     for &(method, pos) in &PATTERN_METHODS {
         if_chain! {
-            if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty_adjusted(&args[0]).kind();
+            if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty_adjusted(receiver).kind();
             if *ty.kind() == ty::Str;
             if method_name.as_str() == method && args.len() > pos;
             let arg = &args[pos];
index 0237d39cbdb4e767eecba43e99d478dfffd021bb..9ea6751956abb2c42b1492e917c64eaa36a8617c 100644 (file)
@@ -8,11 +8,11 @@
 use super::SINGLE_CHAR_ADD_STR;
 
 /// lint for length-1 `str`s as argument for `push_str`
-pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
+pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, receiver: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
     let mut applicability = Applicability::MachineApplicable;
-    if let Some(extension_string) = get_hint_if_single_char_arg(cx, &args[1], &mut applicability) {
+    if let Some(extension_string) = get_hint_if_single_char_arg(cx, &args[0], &mut applicability) {
         let base_string_snippet =
-            snippet_with_applicability(cx, args[0].span.source_callsite(), "..", &mut applicability);
+            snippet_with_applicability(cx, receiver.span.source_callsite(), "..", &mut applicability);
         let sugg = format!("{}.push({})", base_string_snippet, extension_string);
         span_lint_and_sugg(
             cx,
index 4ac738272d08523c53f925100eafe8143173701e..9ca4d65550d3e1d594726005ecf99fd3c84d9a26 100644 (file)
@@ -130,7 +130,7 @@ fn check_manual_split_once_indirect(
     let ctxt = expr.span.ctxt();
     let mut parents = cx.tcx.hir().parent_iter(expr.hir_id);
     if let (_, Node::Local(local)) = parents.next()?
-        && let PatKind::Binding(BindingAnnotation::Mutable, iter_binding_id, iter_ident, None) = local.pat.kind
+        && let PatKind::Binding(BindingAnnotation::MUT, iter_binding_id, iter_ident, None) = local.pat.kind
         && let (iter_stmt_id, Node::Stmt(_)) = parents.next()?
         && let (_, Node::Block(enclosing_block)) = parents.next()?
 
@@ -212,11 +212,10 @@ fn indirect_usage<'tcx>(
     ctxt: SyntaxContext,
 ) -> Option<IndirectUsage<'tcx>> {
     if let StmtKind::Local(Local {
-        pat:
-            Pat {
-                kind: PatKind::Binding(BindingAnnotation::Unannotated, _, ident, None),
-                ..
-            },
+        pat: Pat {
+            kind: PatKind::Binding(BindingAnnotation::NONE, _, ident, None),
+            ..
+        },
         init: Some(init_expr),
         hir_id: local_hir_id,
         ..
@@ -292,7 +291,7 @@ fn parse_iter_usage<'tcx>(
 ) -> Option<IterUsage> {
     let (kind, span) = match iter.next() {
         Some((_, Node::Expr(e))) if e.span.ctxt() == ctxt => {
-            let (name, args) = if let ExprKind::MethodCall(name, [_, args @ ..], _) = e.kind {
+            let (name, args) = if let ExprKind::MethodCall(name, _, [args @ ..], _) = e.kind {
                 (name, args)
             } else {
                 return None;
@@ -327,7 +326,7 @@ fn parse_iter_usage<'tcx>(
                         } else {
                             if_chain! {
                                 if let Some((_, Node::Expr(next_expr))) = iter.next();
-                                if let ExprKind::MethodCall(next_name, [_], _) = next_expr.kind;
+                                if let ExprKind::MethodCall(next_name, _, [], _) = next_expr.kind;
                                 if next_name.ident.name == sym::next;
                                 if next_expr.span.ctxt() == ctxt;
                                 if let Some(next_id) = cx.typeck_results().type_dependent_def_id(next_expr.hir_id);
@@ -367,7 +366,7 @@ fn parse_iter_usage<'tcx>(
                 }
             },
             _ if e.span.ctxt() != ctxt => (None, span),
-            ExprKind::MethodCall(name, [_], _)
+            ExprKind::MethodCall(name, _, [], _)
                 if name.ident.name == sym::unwrap
                     && cx
                         .typeck_results()
index d06658f2a5e6e8241e9878ea3684e8d0776760a5..143dcee350521075ee0acd3acd3459107fa02708 100644 (file)
@@ -16,7 +16,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr
         return;
     }
     if let Some(arglists) = method_chain_args(arg, &["chars"]) {
-        let target = &arglists[0][0];
+        let target = &arglists[0].0;
         let self_ty = cx.typeck_results().expr_ty(target).peel_refs();
         let ref_str = if *self_ty.kind() == ty::Str {
             ""
index 19037093e20a1be9da01d7fea78aabe139f13c6a..95138c0e25b034a088447c327bda976b0a15b3e4 100644 (file)
@@ -43,7 +43,7 @@ pub fn check_for_loop_iter(
         if let Some(receiver_snippet) = snippet_opt(cx, receiver.span);
         then {
             let snippet = if_chain! {
-                if let ExprKind::MethodCall(maybe_iter_method_name, [collection], _) = receiver.kind;
+                if let ExprKind::MethodCall(maybe_iter_method_name, collection, [], _) = receiver.kind;
                 if maybe_iter_method_name.ident.name == sym::iter;
 
                 if let Some(iterator_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator);
index 1876c7fb9d0510fd855b52232bdfa38b6e6e7a65..a187a8d6016f871325c2d58ca803d19add8ca842 100644 (file)
@@ -54,7 +54,7 @@ pub(super) fn check<'tcx>(
                 // This is a duplicate of what's happening in clippy_lints::methods::method_call,
                 // which isn't ideal, We want to get the method call span,
                 // but prefer to avoid changing the signature of the function itself.
-                if let hir::ExprKind::MethodCall(_, _, span) = expr.kind {
+                if let hir::ExprKind::MethodCall(.., span) = expr.kind {
                     span_lint_and_then(cx, UNNECESSARY_LAZY_EVALUATIONS, expr.span, msg, |diag| {
                         diag.span_suggestion(
                             span,
index 1966990bd774f929a37551329aff18832c326c17..6f25acca1de6123e1a08586d8edd57f17fe192d8 100644 (file)
@@ -50,9 +50,13 @@ fn mirrored_exprs(a_expr: &Expr<'_>, a_ident: &Ident, b_expr: &Expr<'_>, b_ident
         // The two exprs are method calls.
         // Check to see that the function is the same and the arguments are mirrored
         // This is enough because the receiver of the method is listed in the arguments
-        (ExprKind::MethodCall(left_segment, left_args, _), ExprKind::MethodCall(right_segment, right_args, _)) => {
+        (
+            ExprKind::MethodCall(left_segment, left_receiver, left_args, _),
+            ExprKind::MethodCall(right_segment, right_receiver, right_args, _),
+        ) => {
             left_segment.ident == right_segment.ident
                 && iter::zip(*left_args, *right_args).all(|(left, right)| mirrored_exprs(left, a_ident, right, b_ident))
+                && mirrored_exprs(left_receiver, a_ident, right_receiver, b_ident)
         },
         // Two tuples with mirrored contents
         (ExprKind::Tup(left_exprs), ExprKind::Tup(right_exprs)) => {
@@ -125,7 +129,7 @@ fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: &Exp
             Param { pat: Pat { kind: PatKind::Binding(_, _, left_ident, _), .. }, ..},
             Param { pat: Pat { kind: PatKind::Binding(_, _, right_ident, _), .. }, .. }
         ] = &closure_body.params;
-        if let ExprKind::MethodCall(method_path, [left_expr, right_expr], _) = closure_body.value.kind;
+        if let ExprKind::MethodCall(method_path, left_expr, [right_expr], _) = closure_body.value.kind;
         if method_path.ident.name == sym::cmp;
         if is_trait_method(cx, &closure_body.value, sym::Ord);
         then {
index 44bf84352943853bddfa26628e7515617a93e14f..9dceb9af2f2234b09673affa472dce6887b57bdf 100644 (file)
@@ -24,12 +24,13 @@ pub fn check<'tcx>(
     cx: &LateContext<'tcx>,
     expr: &'tcx Expr<'tcx>,
     method_name: Symbol,
-    args: &'tcx [Expr<'tcx>],
+    receiver: &'tcx Expr<'_>,
+    args: &'tcx [Expr<'_>],
     msrv: Option<RustcVersion>,
 ) {
     if_chain! {
         if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
-        if let [receiver] = args;
+        if args.is_empty();
         then {
             if is_cloned_or_copied(cx, method_name, method_def_id) {
                 unnecessary_iter_cloned::check(cx, expr, method_name, receiver);
@@ -245,9 +246,14 @@ fn check_other_call_arg<'tcx>(
 ) -> bool {
     if_chain! {
         if let Some((maybe_call, maybe_arg)) = skip_addr_of_ancestors(cx, expr);
-        if let Some((callee_def_id, call_substs, call_args)) = get_callee_substs_and_args(cx, maybe_call);
+        if let Some((callee_def_id, call_substs, call_receiver, call_args)) = get_callee_substs_and_args(cx, maybe_call);
         let fn_sig = cx.tcx.fn_sig(callee_def_id).skip_binder();
-        if let Some(i) = call_args.iter().position(|arg| arg.hir_id == maybe_arg.hir_id);
+        let index = if let Some(call_receiver) = call_receiver {
+            std::iter::once(call_receiver).chain(call_args.iter()).position(|arg| arg.hir_id == maybe_arg.hir_id)
+        } else {
+            call_args.iter().position(|arg| arg.hir_id == maybe_arg.hir_id)
+        };
+        if let Some(i) = index;
         if let Some(input) = fn_sig.inputs().get(i);
         let (input, n_refs) = peel_mid_ty_refs(*input);
         if let (trait_predicates, projection_predicates) = get_input_traits_and_projections(cx, callee_def_id, input);
@@ -342,22 +348,22 @@ fn skip_addr_of_ancestors<'tcx>(
 fn get_callee_substs_and_args<'tcx>(
     cx: &LateContext<'tcx>,
     expr: &'tcx Expr<'tcx>,
-) -> Option<(DefId, SubstsRef<'tcx>, &'tcx [Expr<'tcx>])> {
+) -> Option<(DefId, SubstsRef<'tcx>, Option<&'tcx Expr<'tcx>>, &'tcx [Expr<'tcx>])> {
     if_chain! {
         if let ExprKind::Call(callee, args) = expr.kind;
         let callee_ty = cx.typeck_results().expr_ty(callee);
         if let ty::FnDef(callee_def_id, _) = callee_ty.kind();
         then {
             let substs = cx.typeck_results().node_substs(callee.hir_id);
-            return Some((*callee_def_id, substs, args));
+            return Some((*callee_def_id, substs, None, args));
         }
     }
     if_chain! {
-        if let ExprKind::MethodCall(_, args, _) = expr.kind;
+        if let ExprKind::MethodCall(_, receiver, args, _) = expr.kind;
         if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
         then {
             let substs = cx.typeck_results().node_substs(expr.hir_id);
-            return Some((method_def_id, substs, args));
+            return Some((method_def_id, substs, Some(receiver), args));
         }
     }
     None
index 3015531e8439327c1337e21e89acb6367fb437fa..ae6b165fdc36650d8517e9d2b1f450a934ecc0b3 100644 (file)
@@ -28,7 +28,7 @@ fn may_slice<'a>(cx: &LateContext<'a>, ty: Ty<'a>) -> bool {
         }
     }
 
-    if let hir::ExprKind::MethodCall(path, [self_arg, ..], _) = &expr.kind {
+    if let hir::ExprKind::MethodCall(path, self_arg, ..) = &expr.kind {
         if path.ident.name == sym::iter && may_slice(cx, cx.typeck_results().expr_ty(self_arg)) {
             Some(self_arg)
         } else {
@@ -139,9 +139,9 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
                         self.addr_of_exprs.push(parent);
                         return;
                     },
-                    ExprKind::MethodCall(_, args, _) => {
+                    ExprKind::MethodCall(.., args, _) => {
                         if_chain! {
-                            if args.iter().skip(1).all(|arg| !self.is_binding(arg));
+                            if args.iter().all(|arg| !self.is_binding(arg));
                             if let Some(method_def_id) = self.cx.typeck_results().type_dependent_def_id(parent.hir_id);
                             let method_ty = self.cx.tcx.type_of(method_def_id);
                             let self_ty = method_ty.fn_sig(self.cx.tcx).input(0).skip_binder();
index a081cde85725b3518b6f3ae863b2eee3d14f1e44..44b21e7b080d22c6aa8c8654ceb76b226ccba6d2 100644 (file)
@@ -75,23 +75,22 @@ fn min_max<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(MinMax, Cons
                     .qpath_res(qpath, path.hir_id)
                     .opt_def_id()
                     .and_then(|def_id| match cx.tcx.get_diagnostic_name(def_id) {
-                        Some(sym::cmp_min) => fetch_const(cx, args, MinMax::Min),
-                        Some(sym::cmp_max) => fetch_const(cx, args, MinMax::Max),
+                        Some(sym::cmp_min) => fetch_const(cx, None, args, MinMax::Min),
+                        Some(sym::cmp_max) => fetch_const(cx, None, args, MinMax::Max),
                         _ => None,
                     })
             } else {
                 None
             }
         },
-        ExprKind::MethodCall(path, args, _) => {
+        ExprKind::MethodCall(path, receiver, args @ [_], _) => {
             if_chain! {
-                if let [obj, _] = args;
-                if cx.typeck_results().expr_ty(obj).is_floating_point() || match_trait_method(cx, expr, &paths::ORD);
+                if cx.typeck_results().expr_ty(receiver).is_floating_point() || match_trait_method(cx, expr, &paths::ORD);
                 then {
                     if path.ident.name == sym!(max) {
-                        fetch_const(cx, args, MinMax::Max)
+                        fetch_const(cx, Some(receiver), args, MinMax::Max)
                     } else if path.ident.name == sym!(min) {
-                        fetch_const(cx, args, MinMax::Min)
+                        fetch_const(cx, Some(receiver), args, MinMax::Min)
                     } else {
                         None
                     }
@@ -104,16 +103,24 @@ fn min_max<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(MinMax, Cons
     }
 }
 
-fn fetch_const<'a>(cx: &LateContext<'_>, args: &'a [Expr<'a>], m: MinMax) -> Option<(MinMax, Constant, &'a Expr<'a>)> {
-    if args.len() != 2 {
+fn fetch_const<'a>(
+    cx: &LateContext<'_>,
+    receiver: Option<&'a Expr<'a>>,
+    args: &'a [Expr<'a>],
+    m: MinMax,
+) -> Option<(MinMax, Constant, &'a Expr<'a>)> {
+    let mut args = receiver.into_iter().chain(args.into_iter());
+    let arg0 = args.next()?;
+    let arg1 = args.next()?;
+    if args.next().is_some() {
         return None;
     }
-    constant_simple(cx, cx.typeck_results(), &args[0]).map_or_else(
-        || constant_simple(cx, cx.typeck_results(), &args[1]).map(|c| (m, c, &args[0])),
+    constant_simple(cx, cx.typeck_results(), arg0).map_or_else(
+        || constant_simple(cx, cx.typeck_results(), arg1).map(|c| (m, c, arg0)),
         |c| {
-            if constant_simple(cx, cx.typeck_results(), &args[1]).is_none() {
+            if constant_simple(cx, cx.typeck_results(), arg1).is_none() {
                 // otherwise ignore
-                Some((m, c, &args[1]))
+                Some((m, c, arg1))
             } else {
                 None
             }
index 8224e80c9ccb36cb5f75ef2e025ddc7b9074e998..ea245edd77040688400d3810e3e10b668fcac282 100644 (file)
@@ -5,8 +5,8 @@
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{
-    self as hir, def, BinOpKind, BindingAnnotation, Body, Expr, ExprKind, FnDecl, HirId, Mutability, PatKind, Stmt,
-    StmtKind, TyKind,
+    self as hir, def, BinOpKind, BindingAnnotation, Body, ByRef, Expr, ExprKind, FnDecl, HirId, Mutability, PatKind,
+    Stmt, StmtKind, TyKind,
 };
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::lint::in_external_macro;
@@ -146,7 +146,7 @@ fn check_fn(
             return;
         }
         for arg in iter_input_pats(decl, body) {
-            if let PatKind::Binding(BindingAnnotation::Ref | BindingAnnotation::RefMut, ..) = arg.pat.kind {
+            if let PatKind::Binding(BindingAnnotation(ByRef::Yes, _), ..) = arg.pat.kind {
                 span_lint(
                     cx,
                     TOPLEVEL_REF_ARG,
@@ -162,9 +162,8 @@ fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
         if_chain! {
             if !in_external_macro(cx.tcx.sess, stmt.span);
             if let StmtKind::Local(local) = stmt.kind;
-            if let PatKind::Binding(an, .., name, None) = local.pat.kind;
+            if let PatKind::Binding(BindingAnnotation(ByRef::Yes, mutabl), .., name, None) = local.pat.kind;
             if let Some(init) = local.init;
-            if an == BindingAnnotation::Ref || an == BindingAnnotation::RefMut;
             then {
                 // use the macro callsite when the init span (but not the whole local span)
                 // comes from an expansion like `vec![1, 2, 3]` in `let ref _ = vec![1, 2, 3];`
@@ -173,7 +172,7 @@ fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
                 } else {
                     Sugg::hir(cx, init, "..")
                 };
-                let (mutopt, initref) = if an == BindingAnnotation::RefMut {
+                let (mutopt, initref) = if mutabl == Mutability::Mut {
                     ("mut ", sugg_init.mut_addr())
                 } else {
                     ("", sugg_init.addr())
index 525dbf7757c14c3c7e97cbffad764fca4d51a442..d7bb0616acb0ba4aba14a2af50eb13263eeb70a1 100644 (file)
@@ -1,18 +1,12 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use rustc_ast::ast::{BindingMode, Mutability, Pat, PatKind};
+use rustc_ast::ast::{Pat, PatKind};
 use rustc_errors::Applicability;
 use rustc_lint::EarlyContext;
 
 use super::REDUNDANT_PATTERN;
 
 pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) {
-    if let PatKind::Ident(left, ident, Some(ref right)) = pat.kind {
-        let left_binding = match left {
-            BindingMode::ByRef(Mutability::Mut) => "ref mut ",
-            BindingMode::ByRef(Mutability::Not) => "ref ",
-            BindingMode::ByValue(..) => "",
-        };
-
+    if let PatKind::Ident(ann, ident, Some(ref right)) = pat.kind {
         if let PatKind::Wild = right.kind {
             span_lint_and_sugg(
                 cx,
@@ -23,7 +17,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) {
                     ident.name, ident.name,
                 ),
                 "try",
-                format!("{}{}", left_binding, ident.name),
+                format!("{}{}", ann.prefix_str(), ident.name),
                 Applicability::MachineApplicable,
             );
         }
index f434a655f8aff5a9d9c0fd101158b0ef02b1fc72..82dc03ef5c5bce3c264c505ef9ff5b5075a115b4 100644 (file)
@@ -43,18 +43,24 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
                 if let ExprKind::Path(ref path) = fn_expr.kind {
                     check_arguments(
                         cx,
-                        arguments,
+                        arguments.iter().collect(),
                         cx.typeck_results().expr_ty(fn_expr),
                         &rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_qpath(path, false)),
                         "function",
                     );
                 }
             },
-            ExprKind::MethodCall(path, arguments, _) => {
+            ExprKind::MethodCall(path, receiver, arguments, _) => {
                 let def_id = cx.typeck_results().type_dependent_def_id(e.hir_id).unwrap();
                 let substs = cx.typeck_results().node_substs(e.hir_id);
                 let method_type = cx.tcx.bound_type_of(def_id).subst(cx.tcx, substs);
-                check_arguments(cx, arguments, method_type, path.ident.as_str(), "method");
+                check_arguments(
+                    cx,
+                    std::iter::once(receiver).chain(arguments.iter()).collect(),
+                    method_type,
+                    path.ident.as_str(),
+                    "method",
+                );
             },
             _ => (),
         }
@@ -63,7 +69,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
 
 fn check_arguments<'tcx>(
     cx: &LateContext<'tcx>,
-    arguments: &[Expr<'_>],
+    arguments: Vec<&Expr<'_>>,
     type_definition: Ty<'tcx>,
     name: &str,
     fn_kind: &str,
index 9838d3cad9f02d537732033a0435ffa73281ea1f..f2ffac85bf4023cc25368595e239b84c7383f7e9 100644 (file)
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use if_chain::if_chain;
-use rustc_ast::ast::{BindingMode, Lifetime, Mutability, Param, PatKind, Path, TyKind};
+use rustc_ast::ast::{BindingAnnotation, ByRef, Lifetime, Mutability, Param, PatKind, Path, TyKind};
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -120,14 +120,14 @@ fn check_param(&mut self, cx: &EarlyContext<'_>, p: &Param) {
 
         match &p.ty.kind {
             TyKind::Path(None, path) => {
-                if let PatKind::Ident(BindingMode::ByValue(mutbl), _, _) = p.pat.kind {
+                if let PatKind::Ident(BindingAnnotation(ByRef::No, mutbl), _, _) = p.pat.kind {
                     check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Value, mutbl);
                 }
             },
             TyKind::Rptr(lifetime, mut_ty) => {
                 if_chain! {
                 if let TyKind::Path(None, path) = &mut_ty.ty.kind;
-                if let PatKind::Ident(BindingMode::ByValue(Mutability::Not), _, _) = p.pat.kind;
+                if let PatKind::Ident(BindingAnnotation::NONE, _, _) = p.pat.kind;
                     then {
                         check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Ref(*lifetime), mut_ty.mutbl);
                     }
index 05c012b92e878e6327f2ba1839bd3327b455aaae..b8855e5adbff4c11c6b17a7176c0857372e4dfda 100644 (file)
@@ -59,7 +59,7 @@ fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) {
             if let PatKind::Ref(sub_pat, Mutability::Not) = pat.kind;
 
             // Check sub_pat got a `ref` keyword (excluding `ref mut`).
-            if let PatKind::Binding(BindingAnnotation::Ref, .., spanned_name, _) = sub_pat.kind;
+            if let PatKind::Binding(BindingAnnotation::REF, .., spanned_name, _) = sub_pat.kind;
             let parent_id = cx.tcx.hir().get_parent_node(pat.hir_id);
             if let Some(parent_node) = cx.tcx.hir().find(parent_id);
             then {
index 10e188ecb79a6af8365f832e17926fff68b50d0b..f8cc3fbb3cdfaeacdcc0332fb432c05586d767eb 100644 (file)
@@ -56,12 +56,12 @@ fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
 
         if_chain! {
             // Check the method name is `for_each`.
-            if let ExprKind::MethodCall(method_name, [for_each_recv, for_each_arg], _) = expr.kind;
+            if let ExprKind::MethodCall(method_name, for_each_recv, [for_each_arg], _) = expr.kind;
             if method_name.ident.name == Symbol::intern("for_each");
             // Check `for_each` is an associated function of `Iterator`.
             if is_trait_method(cx, expr, sym::Iterator);
             // Checks the receiver of `for_each` is also a method call.
-            if let ExprKind::MethodCall(_, [iter_recv], _) = for_each_recv.kind;
+            if let ExprKind::MethodCall(_, iter_recv, [], _) = for_each_recv.kind;
             // Skip the lint if the call chain is too long. e.g. `v.field.iter().for_each()` or
             // `v.foo().iter().for_each()` must be skipped.
             if matches!(
index ff2999b1f4a51da2137295baa6ad007c06348322..de99f1d7078e97eb40fd1030376f9c179c26bf75 100644 (file)
@@ -373,7 +373,7 @@ fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'tcx>) {
             if let Local {
                 init: None,
                 pat: &Pat {
-                    kind: PatKind::Binding(BindingAnnotation::Unannotated, binding_id, _, None),
+                    kind: PatKind::Binding(BindingAnnotation::NONE, binding_id, _, None),
                     ..
                 },
                 source: LocalSource::Normal,
index 0cbef1c95fe95ba4a15b565d2cbc147593cf6b50..6d17c7a7346f3994fc99e74cd8d6d002dc3f16bf 100644 (file)
@@ -8,7 +8,9 @@
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{Applicability, Diagnostic};
 use rustc_hir::intravisit::FnKind;
-use rustc_hir::{BindingAnnotation, Body, FnDecl, GenericArg, HirId, Impl, ItemKind, Node, PatKind, QPath, TyKind};
+use rustc_hir::{
+    BindingAnnotation, Body, FnDecl, GenericArg, HirId, Impl, ItemKind, Mutability, Node, PatKind, QPath, TyKind,
+};
 use rustc_hir::{HirIdMap, HirIdSet};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
@@ -188,13 +190,9 @@ fn check_fn(
                 if !implements_borrow_trait;
                 if !all_borrowable_trait;
 
-                if let PatKind::Binding(mode, canonical_id, ..) = arg.pat.kind;
+                if let PatKind::Binding(BindingAnnotation(_, Mutability::Not), canonical_id, ..) = arg.pat.kind;
                 if !moved_vars.contains(&canonical_id);
                 then {
-                    if mode == BindingAnnotation::Mutable || mode == BindingAnnotation::RefMut {
-                        continue;
-                    }
-
                     // Dereference suggestion
                     let sugg = |diag: &mut Diagnostic| {
                         if let ty::Adt(def, ..) = ty.kind() {
index ed022b9d5291cbf3ad6cdf3df582a6ced7b25440..25fb4f0f4cff199ed2aa961faad136b0e533e1d0 100644 (file)
@@ -43,7 +43,7 @@
 impl<'tcx> LateLintPass<'tcx> for NonOctalUnixPermissions {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
         match &expr.kind {
-            ExprKind::MethodCall(path, [func, param], _) => {
+            ExprKind::MethodCall(path, func, [param], _) => {
                 let obj_ty = cx.typeck_results().expr_ty(func).peel_refs();
 
                 if_chain! {
index 774a3540d1e0c41bef19b00f44b955664de5c743..17d5fa2152bbffe438f627e0d41103f9c063df95 100644 (file)
@@ -304,13 +304,13 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) {
                             }
                             return;
                         },
-                        ExprKind::MethodCall(_, args, _)
+                        ExprKind::MethodCall(_, receiver, args, _)
                             if typeck.type_dependent_def_id(parent.hir_id).map_or(false, |id| {
                                 id == param.fn_id
                                     && has_matching_substs(param.fn_kind, typeck.node_substs(parent.hir_id))
                             }) =>
                         {
-                            if let Some(idx) = args.iter().position(|arg| arg.hir_id == child_id) {
+                            if let Some(idx) = std::iter::once(receiver).chain(args.iter()).position(|arg| arg.hir_id == child_id) {
                                 param.uses.push(Usage::new(span, idx));
                             }
                             return;
index e1f9b5906f667cdb8e62ae670ecba722bb13773f..638a514ff9b361f7e33e3bc02d86f25e3214688f 100644 (file)
@@ -38,7 +38,7 @@ fn symmetric_partial_eq<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, other: Ty<'t
 fn check_op(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: bool) {
     let typeck = cx.typeck_results();
     let (arg, arg_span) = match expr.kind {
-        ExprKind::MethodCall(.., [arg], _)
+        ExprKind::MethodCall(_, arg, [], _)
             if typeck
                 .type_dependent_def_id(expr.hir_id)
                 .and_then(|id| cx.tcx.trait_of_item(id))
index 0d067d1e1968c4ec2d729e932c08f6cabf6e7577..827a2b26709350dc1ad9ceb3f678cca5ab26a82d 100644 (file)
@@ -17,7 +17,7 @@ pub(crate) fn check<'tcx>(
     right: &'tcx Expr<'_>,
 ) {
     if op == BinOpKind::Div
-        && let ExprKind::MethodCall(method_path, [self_arg], _) = left.kind
+        && let ExprKind::MethodCall(method_path, self_arg, [], _) = left.kind
         && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(self_arg).peel_refs(), sym::Duration)
         && let Some((Constant::Int(divisor), _)) = constant(cx, cx.typeck_results(), right)
     {
index 0ef793443ff45ce618c7bfc2d32ae2363674c6d1..97ddcdb24799d12ac2a73d9202a2b724b6249fb4 100644 (file)
@@ -113,7 +113,7 @@ fn is_signum(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     }
 
     if_chain! {
-        if let ExprKind::MethodCall(method_name, [ref self_arg, ..], _) = expr.kind;
+        if let ExprKind::MethodCall(method_name, self_arg, ..) = expr.kind;
         if sym!(signum) == method_name.ident.name;
         // Check that the receiver of the signum() is a float (expressions[0] is the receiver of
         // the method call)
index 1805672e372544d8b34e64548fd7118a67e3c8b9..1085e608944154beed10801798f9aa684a3fe643 100644 (file)
@@ -185,7 +185,7 @@ fn in_impl<'tcx>(
         if let ItemKind::Impl(item) = &item.kind;
         if let Some(of_trait) = &item.of_trait;
         if let Some(seg) = of_trait.path.segments.last();
-        if let Some(Res::Def(_, trait_id)) = seg.res;
+        if let Res::Def(_, trait_id) = seg.res;
         if trait_id == bin_op;
         if let Some(generic_args) = seg.args;
         if let Some(GenericArg::Type(other_ty)) = generic_args.args.last();
index 9602d0d1d2ea1a725963b38f8762a4744c2c4328..0315678bf97a96c1ef6fcd58e59df3c7b4b5342d 100644 (file)
@@ -130,7 +130,7 @@ fn try_get_option_occurence<'tcx>(
             .filter_map(|(id, &c)| none_captures.get(id).map(|&c2| (c, c2)))
             .all(|(x, y)| x.is_imm_ref() && y.is_imm_ref());
         then {
-            let capture_mut = if bind_annotation == BindingAnnotation::Mutable { "mut " } else { "" };
+            let capture_mut = if bind_annotation == BindingAnnotation::MUT { "mut " } else { "" };
             let some_body = peel_blocks(if_then);
             let none_body = peel_blocks(if_else);
             let method_sugg = if eager_or_lazy::switch_to_eager_eval(cx, none_body) { "map_or" } else { "map_or_else" };
@@ -138,7 +138,7 @@ fn try_get_option_occurence<'tcx>(
             let (as_ref, as_mut) = match &expr.kind {
                 ExprKind::AddrOf(_, Mutability::Not, _) => (true, false),
                 ExprKind::AddrOf(_, Mutability::Mut, _) => (false, true),
-                _ => (bind_annotation == BindingAnnotation::Ref, bind_annotation == BindingAnnotation::RefMut),
+                _ => (bind_annotation == BindingAnnotation::REF, bind_annotation == BindingAnnotation::REF_MUT),
             };
 
             // Check if captures the closure will need conflict with borrows made in the scrutinee.
index 5fa4fd74853f1d09ee164aa0846dbbe424190b6b..0960b050c240e37553be6b96824f26b2d09983fd 100644 (file)
@@ -221,7 +221,7 @@ fn check_poly_fn(&mut self, cx: &LateContext<'tcx>, def_id: LocalDefId, decl: &F
                     // if function has a body and parameter is annotated with mut, ignore
                     if let Some(param) = fn_body.and_then(|body| body.params.get(index)) {
                         match param.pat.kind {
-                            PatKind::Binding(BindingAnnotation::Unannotated, _, _, _) => {},
+                            PatKind::Binding(BindingAnnotation::NONE, _, _, _) => {},
                             _ => continue,
                         }
                     }
index 3c5ea2d94144faf0718772b5342befcc510c7b8e..0028e0bc6c517e79e13f3b57452972f013da44c0 100644 (file)
@@ -571,7 +571,7 @@ fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
                 Some((Node::Stmt(_), _)) => (),
                 Some((Node::Local(l), _)) => {
                     // Only trace simple bindings. e.g `let x = y;`
-                    if let PatKind::Binding(BindingAnnotation::Unannotated, id, _, None) = l.pat.kind {
+                    if let PatKind::Binding(BindingAnnotation::NONE, id, _, None) = l.pat.kind {
                         self.bindings.insert(id, args_idx);
                     } else {
                         set_skip_flag();
@@ -591,8 +591,11 @@ fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
                             set_skip_flag();
                         }
                     },
-                    ExprKind::MethodCall(name, expr_args @ [self_arg, ..], _) => {
-                        let i = expr_args.iter().position(|arg| arg.hir_id == child_id).unwrap_or(0);
+                    ExprKind::MethodCall(name, self_arg, expr_args, _) => {
+                        let i = std::iter::once(self_arg)
+                            .chain(expr_args.iter())
+                            .position(|arg| arg.hir_id == child_id)
+                            .unwrap_or(0);
                         if i == 0 {
                             // Check if the method can be renamed.
                             let name = name.ident.as_str();
@@ -644,7 +647,7 @@ fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
             .filter_map(|(i, arg)| {
                 let param = &body.params[arg.idx];
                 match param.pat.kind {
-                    PatKind::Binding(BindingAnnotation::Unannotated, id, _, None)
+                    PatKind::Binding(BindingAnnotation::NONE, id, _, None)
                         if !is_lint_allowed(cx, PTR_ARG, param.hir_id) =>
                     {
                         Some((id, i))
index b907f38afbb92f96dfb27efe3659872e239bac34..4dc65da3ea1fd9fd8227823a0ce416c6c573a466 100644 (file)
@@ -93,7 +93,7 @@ fn expr_as_ptr_offset_call<'tcx>(
     cx: &LateContext<'tcx>,
     expr: &'tcx Expr<'_>,
 ) -> Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>, Method)> {
-    if let ExprKind::MethodCall(path_segment, [arg_0, arg_1, ..], _) = &expr.kind {
+    if let ExprKind::MethodCall(path_segment, arg_0, [arg_1, ..], _) = &expr.kind {
         if is_expr_ty_raw_ptr(cx, arg_0) {
             if path_segment.ident.name == sym::offset {
                 return Some((arg_0, arg_1, Method::Offset));
index b432ccb1ee32dd675d054de109fd3ec690fe80f8..f4f1fd336df7cc81c4a60786da7e95ccb5ed85bb 100644 (file)
@@ -9,7 +9,7 @@
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
-use rustc_hir::{BindingAnnotation, Expr, ExprKind, Node, PatKind, PathSegment, QPath};
+use rustc_hir::{BindingAnnotation, ByRef, Expr, ExprKind, Node, PatKind, PathSegment, QPath};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::Ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -86,7 +86,7 @@ fn check_is_none_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Ex
     if_chain! {
         if let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr);
         if !is_else_clause(cx.tcx, expr);
-        if let ExprKind::MethodCall(segment, [caller, ..], _) = &cond.kind;
+        if let ExprKind::MethodCall(segment, caller, ..) = &cond.kind;
         let caller_ty = cx.typeck_results().expr_ty(caller);
         let if_block = IfBlockType::IfIs(caller, caller_ty, segment.ident.name, then, r#else);
         if is_early_return(sym::Option, cx, &if_block) || is_early_return(sym::Result, cx, &if_block);
@@ -123,7 +123,7 @@ fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr:
         if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else }) = higher::IfLet::hir(cx, expr);
         if !is_else_clause(cx.tcx, expr);
         if let PatKind::TupleStruct(ref path1, [field], None) = let_pat.kind;
-        if let PatKind::Binding(annot, bind_id, ident, None) = field.kind;
+        if let PatKind::Binding(BindingAnnotation(by_ref, _), bind_id, ident, None) = field.kind;
         let caller_ty = cx.typeck_results().expr_ty(let_expr);
         let if_block = IfBlockType::IfLet(path1, caller_ty, ident.name, let_expr, if_then, if_else);
         if (is_early_return(sym::Option, cx, &if_block) && path_to_local_id(peel_blocks(if_then), bind_id))
@@ -132,12 +132,11 @@ fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr:
         then {
             let mut applicability = Applicability::MachineApplicable;
             let receiver_str = snippet_with_applicability(cx, let_expr.span, "..", &mut applicability);
-            let by_ref = matches!(annot, BindingAnnotation::Ref | BindingAnnotation::RefMut);
             let requires_semi = matches!(get_parent_node(cx.tcx, expr.hir_id), Some(Node::Stmt(_)));
             let sugg = format!(
                 "{}{}?{}",
                 receiver_str,
-                if by_ref { ".as_ref()" } else { "" },
+                if by_ref == ByRef::Yes { ".as_ref()" } else { "" },
                 if requires_semi { ";" } else { "" }
             );
             span_lint_and_sugg(
index 9538a8104739ee544e516c3997f1f52884b5bfea..94dec191103c587d02a2bc8501cfc0ac02cc0bb1 100644 (file)
@@ -61,7 +61,7 @@ fn check_block(&mut self, cx: &LateContext<'tcx>, block: &hir::Block<'tcx>) {
                 // finds use of `_.read(&mut v)`
                 let mut read_found = false;
                 let mut visitor = expr_visitor_no_bodies(|expr| {
-                    if let ExprKind::MethodCall(path, [_self, arg], _) = expr.kind
+                    if let ExprKind::MethodCall(path, _self, [arg], _) = expr.kind
                         && let PathSegment { ident: read_or_read_exact, .. } = *path
                         && matches!(read_or_read_exact.as_str(), "read" | "read_exact")
                         && let ExprKind::AddrOf(_, hir::Mutability::Mut, inner) = arg.kind
index 909d6971a5497305a7937bd7b70984e7ffb729b6..42514f861be1c25f33bcca47ef88ac7a2cef5b47 100644 (file)
@@ -43,8 +43,7 @@ fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>) {
             if mut_ty.mutbl == Mutability::Not;
             if let TyKind::Path(ref qpath) = &mut_ty.ty.kind;
             let last = last_path_segment(qpath);
-            if let Some(res) = last.res;
-            if let Some(def_id) = res.opt_def_id();
+            if let Some(def_id) = last.res.opt_def_id();
 
             if cx.tcx.is_diagnostic_item(sym::Option, def_id);
             if let Some(params) = last_path_segment(qpath).args ;
index bfb9f0d01e1dc88a717b3b1317a2cae03f557228..ac4e29e9dfdfa0f5d5c95b93b2b6883284aeb757 100644 (file)
@@ -108,7 +108,7 @@ fn get_pointee_ty_and_count_expr<'tcx>(
     };
     if_chain! {
         // Find calls to copy_{from,to}{,_nonoverlapping} and write_bytes methods
-        if let ExprKind::MethodCall(method_path, [ptr_self, .., count], _) = expr.kind;
+        if let ExprKind::MethodCall(method_path, ptr_self, [.., count], _) = expr.kind;
         let method_ident = method_path.ident.as_str();
         if METHODS.iter().any(|m| *m == method_ident);
 
index b59a25e3a40047eb024a24547ba458488d910ce0..c07aa00a12789af66d57b26093c4839347c80d80 100644 (file)
@@ -99,7 +99,7 @@ fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
         // Matches statements which initializes vectors. For example: `let mut vec = Vec::with_capacity(10)`
         if_chain! {
             if let StmtKind::Local(local) = stmt.kind;
-            if let PatKind::Binding(BindingAnnotation::Mutable, local_id, _, None) = local.pat.kind;
+            if let PatKind::Binding(BindingAnnotation::MUT, local_id, _, None) = local.pat.kind;
             if let Some(init) = local.init;
             if let Some(len_arg) = Self::is_vec_with_capacity(cx, init);
 
@@ -201,7 +201,7 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> {
     fn search_slow_extend_filling(&mut self, expr: &'tcx Expr<'_>) {
         if_chain! {
             if self.initialization_found;
-            if let ExprKind::MethodCall(path, [self_arg, extend_arg], _) = expr.kind;
+            if let ExprKind::MethodCall(path, self_arg, [extend_arg], _) = expr.kind;
             if path_to_local_id(self_arg, self.vec_alloc.local_id);
             if path.ident.name == sym!(extend);
             if self.is_repeat_take(extend_arg);
@@ -215,7 +215,7 @@ fn search_slow_extend_filling(&mut self, expr: &'tcx Expr<'_>) {
     /// Checks if the given expression is resizing a vector with 0
     fn search_slow_resize_filling(&mut self, expr: &'tcx Expr<'_>) {
         if self.initialization_found
-            && let ExprKind::MethodCall(path, [self_arg, len_arg, fill_arg], _) = expr.kind
+            && let ExprKind::MethodCall(path, self_arg, [len_arg, fill_arg], _) = expr.kind
             && path_to_local_id(self_arg, self.vec_alloc.local_id)
             && path.ident.name == sym!(resize)
             // Check that is filled with 0
@@ -224,7 +224,7 @@ fn search_slow_resize_filling(&mut self, expr: &'tcx Expr<'_>) {
                 // Check that len expression is equals to `with_capacity` expression
                 if SpanlessEq::new(self.cx).eq_expr(len_arg, self.vec_alloc.len_expr) {
                     self.slow_expression = Some(InitializationType::Resize(expr));
-                } else if let ExprKind::MethodCall(path, _, _) = len_arg.kind && path.ident.as_str() == "capacity" {
+                } else if let ExprKind::MethodCall(path, ..) = len_arg.kind && path.ident.as_str() == "capacity" {
                     self.slow_expression = Some(InitializationType::Resize(expr));
                 }
             }
@@ -233,7 +233,7 @@ fn search_slow_resize_filling(&mut self, expr: &'tcx Expr<'_>) {
     /// Returns `true` if give expression is `repeat(0).take(...)`
     fn is_repeat_take(&self, expr: &Expr<'_>) -> bool {
         if_chain! {
-            if let ExprKind::MethodCall(take_path, [recv, len_arg, ..], _) = expr.kind;
+            if let ExprKind::MethodCall(take_path, recv, [len_arg, ..], _) = expr.kind;
             if take_path.ident.name == sym!(take);
             // Check that take is applied to `repeat(0)`
             if self.is_repeat_zero(recv);
@@ -241,7 +241,7 @@ fn is_repeat_take(&self, expr: &Expr<'_>) -> bool {
                 // Check that len expression is equals to `with_capacity` expression
                 if SpanlessEq::new(self.cx).eq_expr(len_arg, self.vec_alloc.len_expr) {
                     return true;
-                } else if let ExprKind::MethodCall(path, _, _) = len_arg.kind && path.ident.as_str() == "capacity" {
+                } else if let ExprKind::MethodCall(path, ..) = len_arg.kind && path.ident.as_str() == "capacity" {
                     return true;
                 }
             }
index 22eb06b364632f7a9f5a26b5ae95d4d053fb066c..662d399ca538a6918a07b3a69d14996ca1febc6d 100644 (file)
@@ -262,7 +262,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
             let (method_names, expressions, _) = method_calls(left, 1);
             if method_names.len() == 1;
             if expressions.len() == 1;
-            if expressions[0].len() == 1;
+            if expressions[0].1.is_empty();
             if method_names[0] == sym!(as_bytes);
 
             // Check for slicer
@@ -270,7 +270,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
 
             then {
                 let mut applicability = Applicability::MachineApplicable;
-                let string_expression = &expressions[0][0];
+                let string_expression = &expressions[0].0;
 
                 let snippet_app = snippet_with_applicability(
                     cx,
@@ -291,12 +291,12 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
         }
 
         if_chain! {
-            if let ExprKind::MethodCall(path, args, _) = &e.kind;
+            if let ExprKind::MethodCall(path, receiver, ..) = &e.kind;
             if path.ident.name == sym!(as_bytes);
-            if let ExprKind::Lit(lit) = &args[0].kind;
+            if let ExprKind::Lit(lit) = &receiver.kind;
             if let LitKind::Str(lit_content, _) = &lit.node;
             then {
-                let callsite = snippet(cx, args[0].span.source_callsite(), r#""foo""#);
+                let callsite = snippet(cx, receiver.span.source_callsite(), r#""foo""#);
                 let mut applicability = Applicability::MachineApplicable;
                 if callsite.starts_with("include_str!") {
                     span_lint_and_sugg(
@@ -305,7 +305,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
                         e.span,
                         "calling `as_bytes()` on `include_str!(..)`",
                         "consider using `include_bytes!(..)` instead",
-                        snippet_with_applicability(cx, args[0].span, r#""foo""#, &mut applicability).replacen(
+                        snippet_with_applicability(cx, receiver.span, r#""foo""#, &mut applicability).replacen(
                             "include_str",
                             "include_bytes",
                             1,
@@ -314,7 +314,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
                     );
                 } else if lit_content.as_str().is_ascii()
                     && lit_content.as_str().len() <= MAX_LENGTH_BYTE_STRING_LIT
-                    && !args[0].span.from_expansion()
+                    && !receiver.span.from_expansion()
                 {
                     span_lint_and_sugg(
                         cx,
@@ -324,7 +324,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
                         "consider using a byte string literal instead",
                         format!(
                             "b{}",
-                            snippet_with_applicability(cx, args[0].span, r#""foo""#, &mut applicability)
+                            snippet_with_applicability(cx, receiver.span, r#""foo""#, &mut applicability)
                         ),
                         applicability,
                     );
@@ -333,9 +333,9 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
         }
 
         if_chain! {
-            if let ExprKind::MethodCall(path, [recv], _) = &e.kind;
+            if let ExprKind::MethodCall(path, recv, [], _) = &e.kind;
             if path.ident.name == sym!(into_bytes);
-            if let ExprKind::MethodCall(path, [recv], _) = &recv.kind;
+            if let ExprKind::MethodCall(path, recv, [], _) = &recv.kind;
             if matches!(path.ident.name.as_str(), "to_owned" | "to_string");
             if let ExprKind::Lit(lit) = &recv.kind;
             if let LitKind::Str(lit_content, _) = &lit.node;
@@ -393,7 +393,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
 impl<'tcx> LateLintPass<'tcx> for StrToString {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
         if_chain! {
-            if let ExprKind::MethodCall(path, [self_arg, ..], _) = &expr.kind;
+            if let ExprKind::MethodCall(path, self_arg, ..) = &expr.kind;
             if path.ident.name == sym::to_string;
             let ty = cx.typeck_results().expr_ty(self_arg);
             if let ty::Ref(_, ty, ..) = ty.kind();
@@ -443,7 +443,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
 impl<'tcx> LateLintPass<'tcx> for StringToString {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
         if_chain! {
-            if let ExprKind::MethodCall(path, [self_arg, ..], _) = &expr.kind;
+            if let ExprKind::MethodCall(path, self_arg, ..) = &expr.kind;
             if path.ident.name == sym::to_string;
             let ty = cx.typeck_results().expr_ty(self_arg);
             if is_type_diagnostic_item(cx, ty, sym::String);
@@ -487,11 +487,11 @@ impl<'tcx> LateLintPass<'tcx> for TrimSplitWhitespace {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
         let tyckres = cx.typeck_results();
         if_chain! {
-            if let ExprKind::MethodCall(path, [split_recv], split_ws_span) = expr.kind;
+            if let ExprKind::MethodCall(path, split_recv, [], split_ws_span) = expr.kind;
             if path.ident.name == sym!(split_whitespace);
             if let Some(split_ws_def_id) = tyckres.type_dependent_def_id(expr.hir_id);
             if cx.tcx.is_diagnostic_item(sym::str_split_whitespace, split_ws_def_id);
-            if let ExprKind::MethodCall(path, [_trim_recv], trim_span) = split_recv.kind;
+            if let ExprKind::MethodCall(path, _trim_recv, [], trim_span) = split_recv.kind;
             if let trim_fn_name @ ("trim" | "trim_start" | "trim_end") = path.ident.name.as_str();
             if let Some(trim_def_id) = tyckres.type_dependent_def_id(split_recv.hir_id);
             if is_one_of_trim_diagnostic_items(cx, trim_def_id);
index 7bc9cf742e6549e7dbbcffa91b499da3766d61bb..78403d9fdb7e6f17a81b1f4069105878369d0e9b 100644 (file)
@@ -47,7 +47,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
             if let ExprKind::Path(path) = &func.kind;
             if let Some(did) = cx.qpath_res(path, func.hir_id).opt_def_id();
             if match_libc_symbol(cx, did, "strlen");
-            if let ExprKind::MethodCall(path, [self_arg], _) = recv.kind;
+            if let ExprKind::MethodCall(path, self_arg, [], _) = recv.kind;
             if !recv.span.from_expansion();
             if path.ident.name == sym::as_ptr;
             then {
index aa6c01b3a7cd935a3a9835ab79088a8c2cdaf6bc..651201f34ed28d46471e08ff6b2a9610679d2ad9 100644 (file)
 impl<'tcx> LateLintPass<'tcx> for ToDigitIsSome {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
         if_chain! {
-            if let hir::ExprKind::MethodCall(is_some_path, is_some_args, _) = &expr.kind;
+            if let hir::ExprKind::MethodCall(is_some_path, to_digit_expr, [], _) = &expr.kind;
             if is_some_path.ident.name.as_str() == "is_some";
-            if let [to_digit_expr] = &**is_some_args;
             then {
                 let match_result = match &to_digit_expr.kind {
-                    hir::ExprKind::MethodCall(to_digits_path, to_digit_args, _) => {
+                    hir::ExprKind::MethodCall(to_digits_path, char_arg, [radix_arg], _) => {
                         if_chain! {
-                            if let [char_arg, radix_arg] = &**to_digit_args;
                             if to_digits_path.ident.name.as_str() == "to_digit";
                             let char_arg_ty = cx.typeck_results().expr_ty_adjusted(char_arg);
                             if *char_arg_ty.kind() == ty::Char;
                             then {
-                                Some((true, char_arg, radix_arg))
+                                Some((true, *char_arg, radix_arg))
                             } else {
                                 None
                             }
@@ -59,7 +57,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
                     }
                     hir::ExprKind::Call(to_digits_call, to_digit_args) => {
                         if_chain! {
-                            if let [char_arg, radix_arg] = &**to_digit_args;
+                            if let [char_arg, radix_arg] = *to_digit_args;
                             if let hir::ExprKind::Path(to_digits_path) = &to_digits_call.kind;
                             if let to_digits_call_res = cx.qpath_res(to_digits_path, to_digits_call.hir_id);
                             if let Some(to_digits_def_id) = to_digits_call_res.opt_def_id();
index 2ffa022b04f7a4b870e32717c5cd45aa189d23cf..a25be93b8d61696f3f803e48ae294b5f02ef24fc 100644 (file)
@@ -128,7 +128,7 @@ fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'tc
                 if !bound_predicate.span.from_expansion();
                 if let TyKind::Path(QPath::Resolved(_, Path { segments, .. })) = bound_predicate.bounded_ty.kind;
                 if let Some(PathSegment {
-                    res: Some(Res::SelfTy{ trait_: Some(def_id), alias_to: _ }), ..
+                    res: Res::SelfTy{ trait_: Some(def_id), alias_to: _ }, ..
                 }) = segments.first();
                 if let Some(
                     Node::Item(
index 9a41603f2f4ce1068d6dccbc2e61de037b7d3653..3f99bd3f31567c43592b9e2301557857096f65e7 100644 (file)
@@ -177,7 +177,7 @@ fn extract_init_or_reserve_target<'tcx>(cx: &LateContext<'tcx>, stmt: &'tcx Stmt
                     });
                 }
             },
-            ExprKind::MethodCall(path, [self_expr, _], _) if is_reserve(cx, path, self_expr) => {
+            ExprKind::MethodCall(path, self_expr, [_], _) if is_reserve(cx, path, self_expr) => {
                 return Some(TargetVec {
                     location: VecLocation::Expr(self_expr),
                     init_kind: None,
@@ -211,7 +211,7 @@ fn extract_set_len_self<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Opt
         }
     });
     match expr.kind {
-        ExprKind::MethodCall(path, [self_expr, _], _) => {
+        ExprKind::MethodCall(path, self_expr, [_], _) => {
             let self_type = cx.typeck_results().expr_ty(self_expr).peel_refs();
             if is_type_diagnostic_item(cx, self_type, sym::Vec) && path.ident.name.as_str() == "set_len" {
                 Some((self_expr, expr.span))
index b0fce91abeb7d3fd44cd750321140aafa1d97454..851eef7b332417658b090489fa968aa0850923f4 100644 (file)
@@ -144,8 +144,9 @@ fn check_arg<'tcx>(cx: &LateContext<'tcx>, arg: &'tcx Expr<'tcx>) -> Option<(Spa
 
 impl<'tcx> LateLintPass<'tcx> for UnitReturnExpectingOrd {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
-        if let ExprKind::MethodCall(_, args, _) = expr.kind {
+        if let ExprKind::MethodCall(_, receiver, args, _) = expr.kind {
             let arg_indices = get_args_to_check(cx, expr);
+            let args = std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>();
             for (i, trait_name) in arg_indices {
                 if i < args.len() {
                     match check_arg(cx, &args[i]) {
index aec028d5c4824b63bfad47af38eca5846a18ab1a..35824b03170afb87e139373715ad3b1caca492e5 100644 (file)
@@ -128,7 +128,7 @@ fn needs_inferred_result_ty(
     locals_to_check: &mut Vec<HirId>,
     seen_locals: &mut HirIdSet,
 ) -> bool {
-    let (id, args) = match e.kind {
+    let (id, receiver, args) = match e.kind {
         ExprKind::Call(
             Expr {
                 kind: ExprKind::Path(ref path),
@@ -137,11 +137,11 @@ fn needs_inferred_result_ty(
             },
             args,
         ) => match cx.qpath_res(path, *hir_id) {
-            Res::Def(DefKind::AssocFn | DefKind::Fn, id) => (id, args),
+            Res::Def(DefKind::AssocFn | DefKind::Fn, id) => (id, None, args),
             _ => return false,
         },
-        ExprKind::MethodCall(_, args, _) => match cx.typeck_results().type_dependent_def_id(e.hir_id) {
-            Some(id) => (id, args),
+        ExprKind::MethodCall(_, receiver, args, _) => match cx.typeck_results().type_dependent_def_id(e.hir_id) {
+            Some(id) => (id, Some(receiver), args),
             None => return false,
         },
         ExprKind::Path(QPath::Resolved(None, path)) => {
@@ -156,6 +156,11 @@ fn needs_inferred_result_ty(
     };
     let sig = cx.tcx.fn_sig(id).skip_binder();
     if let ty::Param(output_ty) = *sig.output().kind() {
+        let args: Vec<&Expr<'_>> = if let Some(receiver) = receiver {
+            std::iter::once(receiver).chain(args.iter()).collect()
+        } else {
+            args.iter().collect()
+        };
         sig.inputs().iter().zip(args).all(|(&ty, arg)| {
             !ty.is_param(output_ty.index) || each_value_source_needs_inference(cx, arg, locals_to_check, seen_locals)
         })
index 16da2f11b81a6a6650b07d9dde5062461720c5b5..7ffb53dcf455f371e313cade841426bdeae0fd92 100644 (file)
@@ -30,26 +30,27 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
         }
     }
 
-    match expr.kind {
-        ExprKind::Call(_, args) | ExprKind::MethodCall(_, args, _) => {
-            let args_to_recover = args
-                .iter()
-                .filter(|arg| {
-                    if cx.typeck_results().expr_ty(arg).is_unit() && !utils::is_unit_literal(arg) {
-                        !matches!(
-                            &arg.kind,
-                            ExprKind::Match(.., MatchSource::TryDesugar) | ExprKind::Path(..)
-                        )
-                    } else {
-                        false
-                    }
-                })
-                .collect::<Vec<_>>();
-            if !args_to_recover.is_empty() && !is_from_proc_macro(cx, expr) {
-                lint_unit_args(cx, expr, &args_to_recover);
+    let args: Vec<_> = match expr.kind {
+        ExprKind::Call(_, args) => args.iter().collect(),
+        ExprKind::MethodCall(_, receiver, args, _) => std::iter::once(receiver).chain(args.iter()).collect(),
+        _ => return,
+    };
+
+    let args_to_recover = args
+        .into_iter()
+        .filter(|arg| {
+            if cx.typeck_results().expr_ty(arg).is_unit() && !utils::is_unit_literal(arg) {
+                !matches!(
+                    &arg.kind,
+                    ExprKind::Match(.., MatchSource::TryDesugar) | ExprKind::Path(..)
+                )
+            } else {
+                false
             }
-        },
-        _ => (),
+        })
+        .collect::<Vec<_>>();
+    if !args_to_recover.is_empty() && !is_from_proc_macro(cx, expr) {
+        lint_unit_args(cx, expr, &args_to_recover.as_slice());
     }
 }
 
index 04e2f301bfd888399efbae51888f2b8366c96e89..fb73c386640b49babd971298c21445d4286f9225 100644 (file)
@@ -137,12 +137,12 @@ fn insert_necessary_parens(pat: &mut P<Pat>) {
     struct Visitor;
     impl MutVisitor for Visitor {
         fn visit_pat(&mut self, pat: &mut P<Pat>) {
-            use ast::{BindingMode::*, Mutability::*};
+            use ast::BindingAnnotation;
             noop_visit_pat(pat, self);
             let target = match &mut pat.kind {
                 // `i @ a | b`, `box a | b`, and `& mut? a | b`.
                 Ident(.., Some(p)) | Box(p) | Ref(p, _) if matches!(&p.kind, Or(ps) if ps.len() > 1) => p,
-                Ref(p, Not) if matches!(p.kind, Ident(ByValue(Mut), ..)) => p, // `&(mut x)`
+                Ref(p, Mutability::Not) if matches!(p.kind, Ident(BindingAnnotation::MUT, ..)) => p, // `&(mut x)`
                 _ => return,
             };
             target.kind = Paren(P(take_pat(target)));
index 323cf83ffcffae0410f5ba0ec668055a70679ebe..b38d71784fcfc74475b7f07042267479929aabe8 100644 (file)
@@ -64,7 +64,7 @@ fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) {
                     check_map_error(cx, res, expr);
                 }
             },
-            hir::ExprKind::MethodCall(path, [ref arg_0, ..], _) => match path.ident.as_str() {
+            hir::ExprKind::MethodCall(path, arg_0, ..) => match path.ident.as_str() {
                 "expect" | "unwrap" | "unwrap_or" | "unwrap_or_else" => {
                     check_map_error(cx, arg_0, expr);
                 },
@@ -94,9 +94,9 @@ fn try_remove_await<'a>(expr: &'a hir::Expr<'a>) -> Option<&hir::Expr<'a>> {
 
 fn check_map_error(cx: &LateContext<'_>, call: &hir::Expr<'_>, expr: &hir::Expr<'_>) {
     let mut call = call;
-    while let hir::ExprKind::MethodCall(path, args, _) = call.kind {
+    while let hir::ExprKind::MethodCall(path, receiver, ..) = call.kind {
         if matches!(path.ident.as_str(), "or" | "or_else" | "ok") {
-            call = &args[0];
+            call = receiver;
         } else {
             break;
         }
@@ -110,7 +110,7 @@ fn check_map_error(cx: &LateContext<'_>, call: &hir::Expr<'_>, expr: &hir::Expr<
 }
 
 fn check_method_call(cx: &LateContext<'_>, call: &hir::Expr<'_>, expr: &hir::Expr<'_>, is_await: bool) {
-    if let hir::ExprKind::MethodCall(path, _, _) = call.kind {
+    if let hir::ExprKind::MethodCall(path, ..) = call.kind {
         let symbol = path.ident.as_str();
         let read_trait = if is_await {
             match_trait_method(cx, call, &paths::FUTURES_IO_ASYNCREADEXT)
index ac73173697e8596bcc5b013f1b7d57e38fc28ab2..cfc181e435b9c9da1068a6d642a16d4d9f789b71 100644 (file)
@@ -149,7 +149,8 @@ fn visit_expr(&mut self, ex: &'_ Expr<'_>) {
                                     ident: method_name_ident,
                                     ..
                                 },
-                                [self_arg, remaining_args @ ..],
+                                self_arg,
+                                remaining_args,
                                 _,
                             ) => {
                                 let method_name = method_name_ident.name.as_str();
index d3f9e5abfd739a2ba9e2b66cb132d49ca87ceb54..9092156be150a30634c382add42dd2fcc6a5e1e1 100644 (file)
@@ -154,13 +154,13 @@ fn is_relevant_result_call(cx: &LateContext<'_>, ty: Ty<'_>, method_name: &str)
         return collect_unwrap_info(cx, if_expr, expr, branch, !invert, false);
     } else {
         if_chain! {
-            if let ExprKind::MethodCall(method_name, args, _) = &expr.kind;
-            if let Some(local_id) = path_to_local(&args[0]);
-            let ty = cx.typeck_results().expr_ty(&args[0]);
+            if let ExprKind::MethodCall(method_name, receiver, args, _) = &expr.kind;
+            if let Some(local_id) = path_to_local(receiver);
+            let ty = cx.typeck_results().expr_ty(receiver);
             let name = method_name.ident.as_str();
             if is_relevant_option_call(cx, ty, name) || is_relevant_result_call(cx, ty, name);
             then {
-                assert!(args.len() == 1);
+                assert!(args.len() == 0);
                 let unwrappable = match name {
                     "is_some" | "is_ok" => true,
                     "is_err" | "is_none" => false,
@@ -231,7 +231,7 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
         } else {
             // find `unwrap[_err]()` calls:
             if_chain! {
-                if let ExprKind::MethodCall(method_name, [self_arg, ..], _) = expr.kind;
+                if let ExprKind::MethodCall(method_name, self_arg, ..) = expr.kind;
                 if let Some(id) = path_to_local(self_arg);
                 if [sym::unwrap, sym::expect, sym!(unwrap_err)].contains(&method_name.ident.name);
                 let call_to_unwrap = [sym::unwrap, sym::expect].contains(&method_name.ident.name);
index b32be238cd55a178129cd428ba5015059d3c0b60..b3ca15f7648bc082bdb8ea71694d65631c9c6200 100644 (file)
@@ -83,7 +83,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindExpectUnwrap<'a, 'tcx> {
     fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
         // check for `expect`
         if let Some(arglists) = method_chain_args(expr, &["expect"]) {
-            let receiver_ty = self.typeck_results.expr_ty(&arglists[0][0]).peel_refs();
+            let receiver_ty = self.typeck_results.expr_ty(&arglists[0].0).peel_refs();
             if is_type_diagnostic_item(self.lcx, receiver_ty, sym::Option)
                 || is_type_diagnostic_item(self.lcx, receiver_ty, sym::Result)
             {
@@ -93,7 +93,7 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
 
         // check for `unwrap`
         if let Some(arglists) = method_chain_args(expr, &["unwrap"]) {
-            let receiver_ty = self.typeck_results.expr_ty(&arglists[0][0]).peel_refs();
+            let receiver_ty = self.typeck_results.expr_ty(&arglists[0].0).peel_refs();
             if is_type_diagnostic_item(self.lcx, receiver_ty, sym::Option)
                 || is_type_diagnostic_item(self.lcx, receiver_ty, sym::Result)
             {
index b6738e2891d3e914b2a31f655b5d2402c6a49efb..f1b6463ad0f7c62a375aa8cfad9f7a086729cf19 100644 (file)
@@ -64,7 +64,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
                 }
             },
 
-            ExprKind::MethodCall(name, .., [recv, ..], _) => {
+            ExprKind::MethodCall(name, recv, ..) => {
                 if is_trait_method(cx, e, sym::Into) && name.ident.as_str() == "into" {
                     let a = cx.typeck_results().expr_ty(e);
                     let b = cx.typeck_results().expr_ty(recv);
index 429c64ac156418c1656161f2d840c8330235f96f..1489c96d9e9b03bcb61a8bb8cd84fb7a0977be97 100644 (file)
@@ -6,7 +6,9 @@
 use rustc_ast::LitIntType;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
-use rustc_hir::{ArrayLen, Closure, ExprKind, FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, TyKind};
+use rustc_hir::{
+    ArrayLen, BindingAnnotation, Closure, ExprKind, FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, TyKind,
+};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::symbol::{Ident, Symbol};
@@ -402,10 +404,11 @@ macro_rules! kind {
                 self.expr(func);
                 self.slice(args, |e| self.expr(e));
             },
-            ExprKind::MethodCall(method_name, args, _) => {
-                bind!(self, method_name, args);
-                kind!("MethodCall({method_name}, {args}, _)");
+            ExprKind::MethodCall(method_name, receiver, args, _) => {
+                bind!(self, method_name, receiver, args);
+                kind!("MethodCall({method_name}, {receiver}, {args}, _)");
                 self.ident(field!(method_name.ident));
+                self.expr(receiver);
                 self.slice(args, |e| self.expr(e));
             },
             ExprKind::Tup(elements) => {
@@ -595,7 +598,7 @@ fn block(&self, block: &Binding<&hir::Block<'_>>) {
     }
 
     fn body(&self, body_id: &Binding<hir::BodyId>) {
-        let expr = &self.cx.tcx.hir().body(body_id.value).value;
+        let expr = self.cx.tcx.hir().body(body_id.value).value;
         bind!(self, expr);
         out!("let {expr} = &cx.tcx.hir().body({body_id}).value;");
         self.expr(expr);
@@ -609,10 +612,16 @@ macro_rules! kind {
 
         match pat.value.kind {
             PatKind::Wild => kind!("Wild"),
-            PatKind::Binding(anno, .., name, sub) => {
+            PatKind::Binding(ann, _, name, sub) => {
                 bind!(self, name);
                 opt_bind!(self, sub);
-                kind!("Binding(BindingAnnotation::{anno:?}, _, {name}, {sub})");
+                let ann = match ann {
+                    BindingAnnotation::NONE => "NONE",
+                    BindingAnnotation::REF => "REF",
+                    BindingAnnotation::MUT => "MUT",
+                    BindingAnnotation::REF_MUT => "REF_MUT",
+                };
+                kind!("Binding(BindingAnnotation::{ann}, _, {name}, {sub})");
                 self.ident(name);
                 sub.if_some(|p| self.pat(p));
             },
index eb34085a2abf3a5e5631bf182173a33cb14abb9c..ae1c11ef83c31cab317d5702cdacd8082c4100d2 100644 (file)
@@ -687,7 +687,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
             if let ["expn_data", "outer_expn"] = method_names.as_slice();
             let args = arg_lists[1];
             if args.len() == 1;
-            let self_arg = &args[0];
+            let self_arg = &args.0;
             let self_ty = cx.typeck_results().expr_ty(self_arg).peel_refs();
             if match_type(cx, self_ty, &paths::SYNTAX_CONTEXT);
             then {
index 35db45e2b0c9921b97672f6322e48a870f658190..8425837fd73366277219447d83e196b11c71ffa3 100644 (file)
@@ -100,7 +100,7 @@ fn display_err(&self, cx: &LateContext<'_>) {
                         || get_parent_expr(cx, last_place)
                             .map_or(false, |e| matches!(e.kind, ExprKind::AddrOf(_, Mutability::Mut, _)));
                 },
-                ExprKind::MethodCall(_, [recv, ..], _)
+                ExprKind::MethodCall(_, recv, ..)
                     if recv.hir_id == e.hir_id
                         && adjusted_mut == Mutability::Mut
                         && !adjusted_ty.peel_refs().is_slice() =>
@@ -157,7 +157,7 @@ fn check_block(&mut self, _: &LateContext<'tcx>, _: &'tcx Block<'tcx>) {
 
     fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'tcx>) {
         if let Some(init_expr) = local.init
-            && let PatKind::Binding(BindingAnnotation::Mutable, id, name, None) = local.pat.kind
+            && let PatKind::Binding(BindingAnnotation::MUT, id, name, None) = local.pat.kind
             && !in_external_macro(cx.sess(), local.span)
             && let Some(init) = get_vec_init_kind(cx, init_expr)
             && !matches!(init, VecInitKind::WithExprCapacity(_))
@@ -201,7 +201,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
     fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
         if let Some(searcher) = self.searcher.take() {
             if let StmtKind::Expr(expr) | StmtKind::Semi(expr) = stmt.kind
-                && let ExprKind::MethodCall(name, [self_arg, _], _) = expr.kind
+                && let ExprKind::MethodCall(name, self_arg, [_], _) = expr.kind
                 && path_to_local_id(self_arg, searcher.local_id)
                 && name.ident.as_str() == "push"
             {
index 8335ffae81eb7ce64c97caba247b02847103ca86..e8d2d579f097e5451a870788145360c3e7510c40 100644 (file)
@@ -118,9 +118,9 @@ fn expr_search_pat(tcx: TyCtxt<'_>, e: &Expr<'_>) -> (Pat, Pat) {
         ExprKind::Unary(UnOp::Neg, e) => (Pat::Str("-"), expr_search_pat(tcx, e).1),
         ExprKind::Lit(ref lit) => lit_search_pat(&lit.node),
         ExprKind::Array(_) | ExprKind::Repeat(..) => (Pat::Str("["), Pat::Str("]")),
-        ExprKind::Call(e, []) | ExprKind::MethodCall(_, [e], _) => (expr_search_pat(tcx, e).0, Pat::Str("(")),
+        ExprKind::Call(e, []) | ExprKind::MethodCall(_, e, [], _) => (expr_search_pat(tcx, e).0, Pat::Str("(")),
         ExprKind::Call(first, [.., last])
-        | ExprKind::MethodCall(_, [first, .., last], _)
+        | ExprKind::MethodCall(_, first, [.., last], _)
         | ExprKind::Binary(_, first, last)
         | ExprKind::Tup([first, .., last])
         | ExprKind::Assign(first, last, _)
index 7f55db3b31f7070cdfd74801d2608ec4d6f00f6e..ad95369b9ef707091919fa59ea167a906c35e14e 100644 (file)
@@ -155,13 +155,7 @@ pub fn span_lint_and_then<C, S, F>(cx: &C, lint: &'static Lint, sp: S, msg: &str
     });
 }
 
-pub fn span_lint_hir(
-    cx: &LateContext<'_>,
-    lint: &'static Lint,
-    hir_id: HirId,
-    sp: Span,
-    msg: &str,
-) {
+pub fn span_lint_hir(cx: &LateContext<'_>, lint: &'static Lint, hir_id: HirId, sp: Span, msg: &str) {
     cx.tcx.struct_span_lint_hir(lint, hir_id, sp, |diag| {
         let mut diag = diag.build(msg);
         docs_link(&mut diag, lint);
index 730724b95b968277082b2f72c5fed88cc6645b1d..124a00d817847ae7a827a6c8694e0a9e1d888e83 100644 (file)
@@ -45,12 +45,7 @@ fn bitor_assign(&mut self, rhs: Self) {
 }
 
 /// Determine the eagerness of the given function call.
-fn fn_eagerness<'tcx>(
-    cx: &LateContext<'tcx>,
-    fn_id: DefId,
-    name: Symbol,
-    args: &'tcx [Expr<'_>],
-) -> EagernessSuggestion {
+fn fn_eagerness<'tcx>(cx: &LateContext<'tcx>, fn_id: DefId, name: Symbol, have_one_arg: bool) -> EagernessSuggestion {
     use EagernessSuggestion::{Eager, Lazy, NoChange};
     let name = name.as_str();
 
@@ -59,7 +54,7 @@ fn fn_eagerness<'tcx>(
         None => return Lazy,
     };
 
-    if (name.starts_with("as_") || name == "len" || name == "is_empty") && args.len() == 1 {
+    if (name.starts_with("as_") || name == "len" || name == "is_empty") && have_one_arg {
         if matches!(
             cx.tcx.crate_name(fn_id.krate),
             sym::std | sym::core | sym::alloc | sym::proc_macro
@@ -127,10 +122,11 @@ fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
                     },
                     Res::Def(_, id) => match path {
                         QPath::Resolved(_, p) => {
-                            self.eagerness |= fn_eagerness(self.cx, id, p.segments.last().unwrap().ident.name, args);
+                            self.eagerness |=
+                                fn_eagerness(self.cx, id, p.segments.last().unwrap().ident.name, !args.is_empty());
                         },
                         QPath::TypeRelative(_, name) => {
-                            self.eagerness |= fn_eagerness(self.cx, id, name.ident.name, args);
+                            self.eagerness |= fn_eagerness(self.cx, id, name.ident.name, !args.is_empty());
                         },
                         QPath::LangItem(..) => self.eagerness = Lazy,
                     },
@@ -141,12 +137,12 @@ fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
                     self.eagerness |= NoChange;
                     return;
                 },
-                ExprKind::MethodCall(name, args, _) => {
+                ExprKind::MethodCall(name, ..) => {
                     self.eagerness |= self
                         .cx
                         .typeck_results()
                         .type_dependent_def_id(e.hir_id)
-                        .map_or(Lazy, |id| fn_eagerness(self.cx, id, name.ident.name, args));
+                        .map_or(Lazy, |id| fn_eagerness(self.cx, id, name.ident.name, true));
                 },
                 ExprKind::Index(_, e) => {
                     let ty = self.cx.typeck_results().expr_ty_adjusted(e);
index 1834e2a2de8720b861a8690b57313f33c5297996..57448f716d4941e023d2a7112c7e6f919ebcac34 100644 (file)
@@ -6,9 +6,9 @@
 use rustc_hir::def::Res;
 use rustc_hir::HirIdMap;
 use rustc_hir::{
-    ArrayLen, BinOpKind, Block, BodyId, Closure, Expr, ExprField, ExprKind, FnRetTy, GenericArg, GenericArgs, Guard,
-    HirId, InlineAsmOperand, Let, Lifetime, LifetimeName, ParamName, Pat, PatField, PatKind, Path, PathSegment, QPath,
-    Stmt, StmtKind, Ty, TyKind, TypeBinding,
+    ArrayLen, BinOpKind, BindingAnnotation, Block, BodyId, Closure, Expr, ExprField, ExprKind, FnRetTy, GenericArg,
+    GenericArgs, Guard, HirId, InlineAsmOperand, Let, Lifetime, LifetimeName, ParamName, Pat, PatField, PatKind, Path,
+    PathSegment, QPath, Stmt, StmtKind, Ty, TyKind, TypeBinding,
 };
 use rustc_lexer::{tokenize, TokenKind};
 use rustc_lint::LateContext;
@@ -282,8 +282,14 @@ pub fn eq_expr(&mut self, left: &Expr<'_>, right: &Expr<'_>) -> bool {
                             && self.eq_expr(l.body, r.body)
                     })
             },
-            (&ExprKind::MethodCall(l_path, l_args, _), &ExprKind::MethodCall(r_path, r_args, _)) => {
-                self.inner.allow_side_effects && self.eq_path_segment(l_path, r_path) && self.eq_exprs(l_args, r_args)
+            (
+                &ExprKind::MethodCall(l_path, l_receiver, l_args, _),
+                &ExprKind::MethodCall(r_path, r_receiver, r_args, _),
+            ) => {
+                self.inner.allow_side_effects
+                    && self.eq_path_segment(l_path, r_path)
+                    && self.eq_expr(l_receiver, r_receiver)
+                    && self.eq_exprs(l_args, r_args)
             },
             (&ExprKind::Repeat(le, ll), &ExprKind::Repeat(re, rl)) => {
                 self.eq_expr(le, re) && self.eq_array_length(ll, rl)
@@ -743,8 +749,9 @@ pub fn hash_expr(&mut self, e: &Expr<'_>) {
 
                 s.hash(&mut self.s);
             },
-            ExprKind::MethodCall(path, args, ref _fn_span) => {
+            ExprKind::MethodCall(path, receiver, args, ref _fn_span) => {
                 self.hash_name(path.ident.name);
+                self.hash_expr(receiver);
                 self.hash_exprs(args);
             },
             ExprKind::ConstBlock(ref l_id) => {
@@ -815,8 +822,9 @@ pub fn hash_qpath(&mut self, p: &QPath<'_>) {
     pub fn hash_pat(&mut self, pat: &Pat<'_>) {
         std::mem::discriminant(&pat.kind).hash(&mut self.s);
         match pat.kind {
-            PatKind::Binding(ann, _, _, pat) => {
-                std::mem::discriminant(&ann).hash(&mut self.s);
+            PatKind::Binding(BindingAnnotation(by_ref, mutability), _, _, pat) => {
+                std::mem::discriminant(&by_ref).hash(&mut self.s);
+                std::mem::discriminant(&mutability).hash(&mut self.s);
                 if let Some(pat) = pat {
                     self.hash_pat(pat);
                 }
index 997e773b5da4eecc3cf2ea61ae2dc0a1f131c552..b27439cbec278bec5bafb3fd46e47b7d0deb0422 100644 (file)
@@ -192,7 +192,7 @@ pub fn find_binding_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<
     let hir = cx.tcx.hir();
     if_chain! {
         if let Some(Node::Pat(pat)) = hir.find(hir_id);
-        if matches!(pat.kind, PatKind::Binding(BindingAnnotation::Unannotated, ..));
+        if matches!(pat.kind, PatKind::Binding(BindingAnnotation::NONE, ..));
         let parent = hir.get_parent_node(hir_id);
         if let Some(Node::Local(local)) = hir.find(parent);
         then {
@@ -337,7 +337,7 @@ pub fn qpath_generic_tys<'tcx>(qpath: &QPath<'tcx>) -> impl Iterator<Item = &'tc
         .map_or(&[][..], |a| a.args)
         .iter()
         .filter_map(|a| match a {
-            hir::GenericArg::Type(ty) => Some(ty),
+            hir::GenericArg::Type(ty) => Some(*ty),
             _ => None,
         })
 }
@@ -1036,21 +1036,21 @@ fn visit_pat(&mut self, p: &'tcx Pat<'tcx>) {
 pub fn method_calls<'tcx>(
     expr: &'tcx Expr<'tcx>,
     max_depth: usize,
-) -> (Vec<Symbol>, Vec<&'tcx [Expr<'tcx>]>, Vec<Span>) {
+) -> (Vec<Symbol>, Vec<(&'tcx Expr<'tcx>, &'tcx [Expr<'tcx>])>, Vec<Span>) {
     let mut method_names = Vec::with_capacity(max_depth);
     let mut arg_lists = Vec::with_capacity(max_depth);
     let mut spans = Vec::with_capacity(max_depth);
 
     let mut current = expr;
     for _ in 0..max_depth {
-        if let ExprKind::MethodCall(path, args, _) = &current.kind {
-            if args.iter().any(|e| e.span.from_expansion()) {
+        if let ExprKind::MethodCall(path, receiver, args, _) = &current.kind {
+            if receiver.span.from_expansion() || args.iter().any(|e| e.span.from_expansion()) {
                 break;
             }
             method_names.push(path.ident.name);
-            arg_lists.push(&**args);
+            arg_lists.push((*receiver, &**args));
             spans.push(path.ident.span);
-            current = &args[0];
+            current = receiver;
         } else {
             break;
         }
@@ -1065,18 +1065,18 @@ pub fn method_calls<'tcx>(
 /// `method_chain_args(expr, &["bar", "baz"])` will return a `Vec`
 /// containing the `Expr`s for
 /// `.bar()` and `.baz()`
-pub fn method_chain_args<'a>(expr: &'a Expr<'_>, methods: &[&str]) -> Option<Vec<&'a [Expr<'a>]>> {
+pub fn method_chain_args<'a>(expr: &'a Expr<'_>, methods: &[&str]) -> Option<Vec<(&'a Expr<'a>, &'a [Expr<'a>])>> {
     let mut current = expr;
     let mut matched = Vec::with_capacity(methods.len());
     for method_name in methods.iter().rev() {
         // method chains are stored last -> first
-        if let ExprKind::MethodCall(path, args, _) = current.kind {
+        if let ExprKind::MethodCall(path, receiver, args, _) = current.kind {
             if path.ident.name.as_str() == *method_name {
-                if args.iter().any(|e| e.span.from_expansion()) {
+                if receiver.span.from_expansion() || args.iter().any(|e| e.span.from_expansion()) {
                     return None;
                 }
-                matched.push(args); // build up `matched` backwards
-                current = &args[0]; // go to parent expression
+                matched.push((receiver, args)); // build up `matched` backwards
+                current = receiver; // go to parent expression
             } else {
                 return None;
             }
@@ -1239,8 +1239,10 @@ pub fn get_enclosing_loop_or_multi_call_closure<'tcx>(
                                     ty_is_fn_once_param(cx.tcx, ty.skip_binder(), predicates).then_some(())
                                 })
                             },
-                            ExprKind::MethodCall(_, args, _) => {
-                                let i = args.iter().position(|arg| arg.hir_id == id)?;
+                            ExprKind::MethodCall(_, receiver, args, _) => {
+                                let i = std::iter::once(receiver)
+                                    .chain(args.iter())
+                                    .position(|arg| arg.hir_id == id)?;
                                 let id = cx.typeck_results().type_dependent_def_id(e.hir_id)?;
                                 let ty = cx.tcx.fn_sig(id).skip_binder().inputs()[i];
                                 ty_is_fn_once_param(cx.tcx, ty, cx.tcx.param_env(id).caller_bounds()).then_some(())
@@ -1812,7 +1814,7 @@ fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool {
             }
         };
 
-        let mut expr = &func.value;
+        let mut expr = func.value;
         loop {
             match expr.kind {
                 #[rustfmt::skip]
index 649b7b9940af3b067ab74f34a67a2cdb35cb762e..0226f74906b5152b66a678c960200fcd844564da 100644 (file)
@@ -36,7 +36,7 @@ fn extract_clone_suggestions<'tcx>(
         if abort {
             return false;
         }
-        if let ExprKind::MethodCall(seg, [recv], _) = expr.kind {
+        if let ExprKind::MethodCall(seg, recv, [], _) = expr.kind {
             if path_to_local_id(recv, id) {
                 if seg.ident.name.as_str() == "capacity" {
                     abort = true;
index 081c98e2f3ce726ccf9019a46fc4631eefde9a29..cca71bbf76e2877196898bec350b5435dbcbeaf5 100644 (file)
@@ -373,12 +373,14 @@ fn binop_to_string(op: AssocOp, lhs: &str, rhs: &str) -> String {
         | AssocOp::LessEqual
         | AssocOp::NotEqual
         | AssocOp::Greater
-        | AssocOp::GreaterEqual => format!(
-            "{} {} {}",
-            lhs,
-            op.to_ast_binop().expect("Those are AST ops").to_string(),
-            rhs
-        ),
+        | AssocOp::GreaterEqual => {
+            format!(
+                "{} {} {}",
+                lhs,
+                op.to_ast_binop().expect("Those are AST ops").to_string(),
+                rhs
+            )
+        },
         AssocOp::Assign => format!("{} = {}", lhs, rhs),
         AssocOp::AssignOp(op) => {
             format!("{} {}= {}", lhs, token_kind_to_string(&token::BinOp(op)), rhs)
@@ -868,15 +870,15 @@ pub fn finish(&mut self) -> String {
     /// indicates whether the function from `parent_expr` takes its args by double reference
     fn func_takes_arg_by_double_ref(&self, parent_expr: &'tcx hir::Expr<'_>, cmt_hir_id: HirId) -> bool {
         let ty = match parent_expr.kind {
-            ExprKind::MethodCall(_, call_args, _) => {
+            ExprKind::MethodCall(_, receiver, call_args, _) => {
                 if let Some(sig) = self
                     .cx
                     .typeck_results()
                     .type_dependent_def_id(parent_expr.hir_id)
                     .map(|did| self.cx.tcx.fn_sig(did).skip_binder())
                 {
-                    call_args
-                        .iter()
+                    std::iter::once(receiver)
+                        .chain(call_args.iter())
                         .position(|arg| arg.hir_id == cmt_hir_id)
                         .map(|i| sig.inputs()[i])
                 } else {
@@ -933,14 +935,14 @@ fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, _: ty::BorrowKind) {
                     match &parent_expr.kind {
                         // given expression is the self argument and will be handled completely by the compiler
                         // i.e.: `|x| x.is_something()`
-                        ExprKind::MethodCall(_, [self_expr, ..], _) if self_expr.hir_id == cmt.hir_id => {
+                        ExprKind::MethodCall(_, self_expr, ..) if self_expr.hir_id == cmt.hir_id => {
                             let _ = write!(self.suggestion_start, "{}{}", start_snip, ident_str_with_proj);
                             self.next_pos = span.hi();
                             return;
                         },
                         // item is used in a call
                         // i.e.: `Call`: `|x| please(x)` or `MethodCall`: `|x| [1, 2, 3].contains(x)`
-                        ExprKind::Call(_, [call_args @ ..]) | ExprKind::MethodCall(_, [_, call_args @ ..], _) => {
+                        ExprKind::Call(_, [call_args @ ..]) | ExprKind::MethodCall(_, _, [call_args @ ..], _) => {
                             let expr = self.cx.tcx.hir().expect_expr(cmt.hir_id);
                             let arg_ty_kind = self.cx.typeck_results().expr_ty(expr).kind();
 
index bae8ad9f5659067030d39315aa3276d68a4910a5..6a62002a4d12e3274f14773f79c9ac41b3524aec 100644 (file)
@@ -620,7 +620,13 @@ fn helper<'tcx, B>(
                     helper(typeck, true, arg, f)?;
                 }
             },
-            ExprKind::MethodCall(_, args, _) | ExprKind::Tup(args) | ExprKind::Array(args) => {
+            ExprKind::MethodCall(_, receiver, args, _) => {
+                helper(typeck, true, receiver, f)?;
+                for arg in args {
+                    helper(typeck, true, arg, f)?;
+                }
+            },
+            ExprKind::Tup(args) | ExprKind::Array(args) => {
                 for arg in args {
                     helper(typeck, true, arg, f)?;
                 }
index 3125863036bb798a820f58864850fbe3ca567aad..597318a556b850fc5b356214849b6c23ca734b13 100644 (file)
@@ -6,7 +6,7 @@ if_chain! {
     if match_qpath(qpath, &["char"]);
     if let ExprKind::Lit(ref lit) = expr.kind;
     if let LitKind::Int(69, LitIntType::Unsuffixed) = lit.node;
-    if let PatKind::Binding(BindingAnnotation::Unannotated, _, name, None) = local.pat.kind;
+    if let PatKind::Binding(BindingAnnotation::NONE, _, name, None) = local.pat.kind;
     if name.as_str() == "x";
     then {
         // report your lint here
index 2fc4a7d1f7fe87482ebe6edaef25c15f2f350107..a529981e2e68372c0cd034cdbc187cc0c2da900a 100644 (file)
@@ -5,13 +5,13 @@ if_chain! {
     if let Some(init) = local.init;
     if let ExprKind::Lit(ref lit) = init.kind;
     if let LitKind::Int(42, LitIntType::Signed(IntTy::I32)) = lit.node;
-    if let PatKind::Binding(BindingAnnotation::Unannotated, _, name, None) = local.pat.kind;
+    if let PatKind::Binding(BindingAnnotation::NONE, _, name, None) = local.pat.kind;
     if name.as_str() == "x";
     if let StmtKind::Local(local1) = block.stmts[1].kind;
     if let Some(init1) = local1.init;
     if let ExprKind::Lit(ref lit1) = init1.kind;
     if let LitKind::Float(_, LitFloatType::Suffixed(FloatTy::F32)) = lit1.node;
-    if let PatKind::Binding(BindingAnnotation::Unannotated, _, name1, None) = local1.pat.kind;
+    if let PatKind::Binding(BindingAnnotation::NONE, _, name1, None) = local1.pat.kind;
     if name1.as_str() == "_t";
     if let StmtKind::Semi(e) = block.stmts[2].kind;
     if let ExprKind::Unary(UnOp::Neg, inner) = e.kind;
@@ -31,7 +31,7 @@ if_chain! {
     if let ExprKind::Path(ref qpath) = func.kind;
     if match_qpath(qpath, &["String", "new"]);
     if args.is_empty();
-    if let PatKind::Binding(BindingAnnotation::Unannotated, _, name, None) = local.pat.kind;
+    if let PatKind::Binding(BindingAnnotation::NONE, _, name, None) = local.pat.kind;
     if name.as_str() == "expr";
     if let Some(trailing_expr) = block.expr;
     if let ExprKind::Call(func1, args1) = trailing_expr.kind;
index 3d9560f697a79ee7b3d5416960f9f2e27a4218d5..ceb53fcd496369c11e90ea971cc02091e8c33780 100644 (file)
@@ -1,6 +1,6 @@
 if_chain! {
     if let Some(higher::ForLoop { pat: pat, arg: arg, body: body, .. }) = higher::ForLoop::hir(expr);
-    if let PatKind::Binding(BindingAnnotation::Unannotated, _, name, None) = pat.kind;
+    if let PatKind::Binding(BindingAnnotation::NONE, _, name, None) = pat.kind;
     if name.as_str() == "y";
     if let ExprKind::Struct(qpath, fields, None) = arg.kind;
     if matches!(qpath, QPath::LangItem(LangItem::Range, _));
@@ -17,7 +17,7 @@ if_chain! {
     if let Some(init) = local.init;
     if let ExprKind::Path(ref qpath1) = init.kind;
     if match_qpath(qpath1, &["y"]);
-    if let PatKind::Binding(BindingAnnotation::Unannotated, _, name1, None) = local.pat.kind;
+    if let PatKind::Binding(BindingAnnotation::NONE, _, name1, None) = local.pat.kind;
     if name1.as_str() == "z";
     if block.expr.is_none();
     then {
index 38444a0094ca972eb1a0a732dea4ab1ac51e2ad3..2cf69a035b4c7364ff6ee3991c78f50101f067bf 100644 (file)
@@ -21,7 +21,7 @@ if_chain! {
     if let Some(init1) = local1.init;
     if let ExprKind::Lit(ref lit4) = init1.kind;
     if let LitKind::Int(3, LitIntType::Unsuffixed) = lit4.node;
-    if let PatKind::Binding(BindingAnnotation::Unannotated, _, name, None) = local1.pat.kind;
+    if let PatKind::Binding(BindingAnnotation::NONE, _, name, None) = local1.pat.kind;
     if name.as_str() == "x";
     if let Some(trailing_expr) = block.expr;
     if let ExprKind::Path(ref qpath) = trailing_expr.kind;
@@ -30,7 +30,7 @@ if_chain! {
     if arms[2].guard.is_none();
     if let ExprKind::Lit(ref lit5) = arms[2].body.kind;
     if let LitKind::Int(1, LitIntType::Unsuffixed) = lit5.node;
-    if let PatKind::Binding(BindingAnnotation::Unannotated, _, name1, None) = local.pat.kind;
+    if let PatKind::Binding(BindingAnnotation::NONE, _, name1, None) = local.pat.kind;
     if name1.as_str() == "a";
     then {
         // report your lint here
index 5e78b7c9de7e3990b3e415899ccb1ae096185cd4..b5bbc9e213c6e928330105b81cd6b0e7fb17fd45 100644 (file)
@@ -53,11 +53,11 @@ if_chain! {
     }
 }
 if_chain! {
-    if let ExprKind::MethodCall(method_name, args, _) = expr.kind;
+    if let ExprKind::MethodCall(method_name, receiver, args, _) = expr.kind;
     if method_name.ident.as_str() == "test";
-    if args.len() == 1;
-    if let ExprKind::Path(ref qpath) = args[0].kind;
+    if let ExprKind::Path(ref qpath) = receiver.kind;
     if match_qpath(qpath, &["test_method_call"]);
+    if args.is_empty();
     then {
         // report your lint here
     }
index b9fd852f742cf81360c0cb167683acde754b63eb..f4dac6e947e323e37c7c1996fb982061159d7c39 100644 (file)
@@ -4,7 +4,7 @@ version = "0.0.0"
 edition = "2021"
 
 [dependencies]
-rustdoc = { path = "../../librustdoc" }
+mdbook = { version = "0.4", default-features = false, features = ["search"] }
 
 [[bin]]
 name = "error_index_generator"
diff --git a/src/tools/error_index_generator/book_config.toml b/src/tools/error_index_generator/book_config.toml
new file mode 100644 (file)
index 0000000..885100a
--- /dev/null
@@ -0,0 +1,19 @@
+[book]
+title = "Error codes index"
+description = "Book listing all Rust error codes"
+src = ""
+
+[output.html]
+git-repository-url = "https://github.com/rust-lang/rust/"
+additional-css = ["error-index.css"]
+additional-js = ["error-index.js"]
+
+[output.html.search]
+enable = true
+limit-results = 20
+use-boolean-and = true
+boost-title = 2
+boost-hierarchy = 2
+boost-paragraph = 1
+expand = true
+heading-split-level = 0
diff --git a/src/tools/error_index_generator/error-index.css b/src/tools/error_index_generator/error-index.css
new file mode 100644 (file)
index 0000000..8975af8
--- /dev/null
@@ -0,0 +1,38 @@
+code.compile_fail {
+       border-left: 2px solid red;
+}
+
+pre .tooltip {
+       position: absolute;
+       left: -25px;
+       top: 0;
+       z-index: 1;
+       color: red;
+       cursor: pointer;
+}
+pre .tooltip::after {
+       display: none;
+       content: "This example deliberately fails to compile";
+       background-color: #000;
+       color: #fff;
+       border-color: #000;
+       text-align: center;
+       padding: 5px 3px 3px 3px;
+       border-radius: 6px;
+       margin-left: 5px;
+}
+pre .tooltip::before {
+       display: none;
+       border-color: transparent black transparent transparent;
+       content: " ";
+       position: absolute;
+       top: 50%;
+       left: 16px;
+       margin-top: -5px;
+       border-width: 5px;
+       border-style: solid;
+}
+
+pre .tooltip:hover::before, pre .tooltip:hover::after {
+       display: inline;
+}
diff --git a/src/tools/error_index_generator/error-index.js b/src/tools/error_index_generator/error-index.js
new file mode 100644 (file)
index 0000000..39b371b
--- /dev/null
@@ -0,0 +1,9 @@
+for (const elem of document.querySelectorAll("pre.playground")) {
+    if (elem.querySelector(".compile_fail") === null) {
+        continue;
+    }
+    const child = document.createElement("div");
+    child.className = "tooltip";
+    child.textContent = "ⓘ";
+    elem.appendChild(child);
+}
index 68c46700361a8da36dd766f53a69e5720760b6b9..1bde8e007826dffca053aa69474ecba3530ea68a 100644 (file)
@@ -1,20 +1,21 @@
 #![feature(rustc_private)]
 
 extern crate rustc_driver;
-extern crate rustc_span;
 
+// We use the function we generate from `register_diagnostics!`.
 use crate::error_codes::error_codes;
 
 use std::env;
 use std::error::Error;
-use std::fs::{create_dir_all, File};
+use std::fs::{self, File};
 use std::io::Write;
 use std::path::Path;
 use std::path::PathBuf;
 
-use rustc_span::edition::DEFAULT_EDITION;
+use std::str::FromStr;
 
-use rustdoc::html::markdown::{ErrorCodes, HeadingOffset, IdMap, Markdown, Playground};
+use mdbook::book::{parse_summary, BookItem, Chapter};
+use mdbook::{Config, MDBook};
 
 macro_rules! register_diagnostics {
     ($($error_code:ident: $message:expr,)+ ; $($undocumented:ident,)* ) => {
@@ -33,104 +34,21 @@ pub fn error_codes() -> Vec<(&'static str, Option<&'static str>)> {
 mod error_codes;
 
 enum OutputFormat {
-    HTML(HTMLFormatter),
+    HTML,
     Markdown,
     Unknown(String),
 }
 
 impl OutputFormat {
-    fn from(format: &str, resource_suffix: &str) -> OutputFormat {
+    fn from(format: &str) -> OutputFormat {
         match &*format.to_lowercase() {
-            "html" => OutputFormat::HTML(HTMLFormatter(resource_suffix.to_owned())),
+            "html" => OutputFormat::HTML,
             "markdown" => OutputFormat::Markdown,
             s => OutputFormat::Unknown(s.to_owned()),
         }
     }
 }
 
-struct HTMLFormatter(String);
-
-impl HTMLFormatter {
-    fn create_error_code_file(
-        &self,
-        err_code: &str,
-        explanation: &str,
-        parent_dir: &Path,
-    ) -> Result<(), Box<dyn Error>> {
-        let mut output_file = File::create(parent_dir.join(err_code).with_extension("html"))?;
-
-        self.header(&mut output_file, "../", "")?;
-        self.title(&mut output_file, &format!("Error code {}", err_code))?;
-
-        let mut id_map = IdMap::new();
-        let playground =
-            Playground { crate_name: None, url: String::from("https://play.rust-lang.org/") };
-        write!(
-            output_file,
-            "{}",
-            Markdown {
-                content: explanation,
-                links: &[],
-                ids: &mut id_map,
-                error_codes: ErrorCodes::Yes,
-                edition: DEFAULT_EDITION,
-                playground: &Some(playground),
-                heading_offset: HeadingOffset::H1,
-            }
-            .into_string()
-        )?;
-        write!(
-            output_file,
-            "<p>\
-                <a style='text-align: center;display: block;width: 100%;' \
-                   href='../error-index.html'>Back to list of error codes</a>\
-             </p>",
-        )?;
-
-        self.footer(&mut output_file)
-    }
-
-    fn header(
-        &self,
-        output: &mut dyn Write,
-        extra_path: &str,
-        extra: &str,
-    ) -> Result<(), Box<dyn Error>> {
-        write!(
-            output,
-            r##"<!DOCTYPE html>
-<html>
-<head>
-<title>Rust Compiler Error Index</title>
-<meta charset="utf-8">
-<!-- Include rust.css after light.css so its rules take priority. -->
-<link rel="stylesheet" type="text/css" href="{extra_path}rustdoc{suffix}.css"/>
-<link rel="stylesheet" type="text/css" href="{extra_path}light{suffix}.css"/>
-<link rel="stylesheet" type="text/css" href="{extra_path}rust.css"/>
-<style>
-.error-undescribed {{
-    display: none;
-}}
-</style>{extra}
-</head>
-<body>
-"##,
-            suffix = self.0,
-        )?;
-        Ok(())
-    }
-
-    fn title(&self, output: &mut dyn Write, title: &str) -> Result<(), Box<dyn Error>> {
-        write!(output, "<h1>{}</h1>\n", title)?;
-        Ok(())
-    }
-
-    fn footer(&self, output: &mut dyn Write) -> Result<(), Box<dyn Error>> {
-        write!(output, "</body></html>")?;
-        Ok(())
-    }
-}
-
 /// Output an HTML page for the errors in `err_map` to `output_path`.
 fn render_markdown(output_path: &Path) -> Result<(), Box<dyn Error>> {
     let mut output_file = File::create(output_path)?;
@@ -147,61 +65,119 @@ fn render_markdown(output_path: &Path) -> Result<(), Box<dyn Error>> {
     Ok(())
 }
 
-fn render_html(output_path: &Path, formatter: HTMLFormatter) -> Result<(), Box<dyn Error>> {
-    let mut output_file = File::create(output_path)?;
+// By default, mdbook doesn't consider code blocks as Rust ones contrary to rustdoc so we have
+// to manually add `rust` attribute whenever needed.
+fn add_rust_attribute_on_codeblock(explanation: &str) -> String {
+    // Very hacky way to add the rust attribute on all code blocks.
+    let mut skip = true;
+    explanation.split("\n```").fold(String::new(), |mut acc, part| {
+        if !acc.is_empty() {
+            acc.push_str("\n```");
+        }
+        if !skip {
+            if let Some(attrs) = part.split('\n').next() {
+                if !attrs.contains("rust")
+                    && (attrs.is_empty()
+                        || attrs.contains("compile_fail")
+                        || attrs.contains("ignore")
+                        || attrs.contains("edition"))
+                {
+                    if !attrs.is_empty() {
+                        acc.push_str("rust,");
+                    } else {
+                        acc.push_str("rust");
+                    }
+                }
+            }
+        }
+        skip = !skip;
+        acc.push_str(part);
+        acc
+    })
+}
 
-    let error_codes_dir = "error_codes";
+fn render_html(output_path: &Path) -> Result<(), Box<dyn Error>> {
+    let mut introduction = format!(
+        "<script src='redirect.js'></script>
+# Rust error codes index
 
-    let parent = output_path.parent().expect("There should have a parent").join(error_codes_dir);
+This page lists all the error codes emitted by the Rust compiler.
 
-    if !parent.exists() {
-        create_dir_all(&parent)?;
-    }
+"
+    );
 
-    formatter.header(
-        &mut output_file,
-        "",
-        &format!(
-            r#"<script>(function() {{
-    if (window.location.hash) {{
-        let code = window.location.hash.replace(/^#/, '');
-        // We have to make sure this pattern matches to avoid inadvertently creating an
-        // open redirect.
-        if (/^E[0-9]+$/.test(code)) {{
-            window.location = './{error_codes_dir}/' + code + '.html';
-        }}
-    }}
-}})()</script>"#
-        ),
-    )?;
-    formatter.title(&mut output_file, "Rust Compiler Error Index")?;
+    let err_codes = error_codes();
+    let mut chapters = Vec::with_capacity(err_codes.len());
 
-    write!(
-        output_file,
-        "<p>This page lists all the error codes emitted by the Rust compiler. If you want a full \
-            explanation on an error code, click on it.</p>\
-         <ul>",
-    )?;
-    for (err_code, explanation) in error_codes().iter() {
+    for (err_code, explanation) in err_codes.iter() {
         if let Some(explanation) = explanation {
-            write!(
-                output_file,
-                "<li><a href='./{0}/{1}.html'>{1}</a></li>",
-                error_codes_dir, err_code
-            )?;
-            formatter.create_error_code_file(err_code, explanation, &parent)?;
+            introduction.push_str(&format!(" * [{0}](./{0}.html)\n", err_code));
+
+            let content = add_rust_attribute_on_codeblock(explanation);
+            chapters.push(BookItem::Chapter(Chapter {
+                name: err_code.to_string(),
+                content: format!("# Error code {}\n\n{}\n", err_code, content),
+                number: None,
+                sub_items: Vec::new(),
+                // We generate it into the `error_codes` folder.
+                path: Some(PathBuf::from(&format!("{}.html", err_code))),
+                source_path: None,
+                parent_names: Vec::new(),
+            }));
         } else {
-            write!(output_file, "<li>{}</li>", err_code)?;
+            introduction.push_str(&format!(" * {}\n", err_code));
         }
     }
-    write!(output_file, "</ul>")?;
-    formatter.footer(&mut output_file)
+
+    let mut config = Config::from_str(include_str!("book_config.toml"))?;
+    config.build.build_dir = output_path.join("error_codes").to_path_buf();
+    let mut book = MDBook::load_with_config_and_summary(
+        env!("CARGO_MANIFEST_DIR"),
+        config,
+        parse_summary("")?,
+    )?;
+    let chapter = Chapter {
+        name: "Rust error codes index".to_owned(),
+        content: introduction,
+        number: None,
+        sub_items: chapters,
+        // Very important: this file is named as `error-index.html` and not `index.html`!
+        path: Some(PathBuf::from("error-index.html")),
+        source_path: None,
+        parent_names: Vec::new(),
+    };
+    book.book.sections.push(BookItem::Chapter(chapter));
+    book.build()?;
+
+    // We can't put this content into another file, otherwise `mbdbook` will also put it into the
+    // output directory, making a duplicate.
+    fs::write(
+        output_path.join("error-index.html"),
+        r#"<!DOCTYPE html>
+<html>
+    <head>
+        <title>Rust error codes index - Error codes index</title>
+        <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
+        <meta name="description" content="Book listing all Rust error codes">
+        <script src="error_codes/redirect.js"></script>
+    </head>
+    <body>
+        <div>If you are not automatically redirected to the error code index, please <a id="index-link" href="./error_codes/error-index.html">here</a>.
+        <script>document.getElementById("index-link").click()</script>
+    </body>
+</html>"#,
+    )?;
+
+    // No need for a 404 file, it's already handled by the server.
+    fs::remove_file(output_path.join("error_codes/404.html"))?;
+
+    Ok(())
 }
 
 fn main_with_result(format: OutputFormat, dst: &Path) -> Result<(), Box<dyn Error>> {
     match format {
         OutputFormat::Unknown(s) => panic!("Unknown output format: {}", s),
-        OutputFormat::HTML(h) => render_html(dst, h),
+        OutputFormat::HTML => render_html(dst),
         OutputFormat::Markdown => render_markdown(dst),
     }
 }
@@ -210,12 +186,9 @@ fn parse_args() -> (OutputFormat, PathBuf) {
     let mut args = env::args().skip(1);
     let format = args.next();
     let dst = args.next();
-    let resource_suffix = args.next().unwrap_or_else(String::new);
-    let format = format
-        .map(|a| OutputFormat::from(&a, &resource_suffix))
-        .unwrap_or(OutputFormat::from("html", &resource_suffix));
+    let format = format.map(|a| OutputFormat::from(&a)).unwrap_or(OutputFormat::from("html"));
     let dst = dst.map(PathBuf::from).unwrap_or_else(|| match format {
-        OutputFormat::HTML(..) => PathBuf::from("doc/error-index.html"),
+        OutputFormat::HTML => PathBuf::from("doc"),
         OutputFormat::Markdown => PathBuf::from("doc/error-index.md"),
         OutputFormat::Unknown(..) => PathBuf::from("<nul>"),
     });
@@ -225,9 +198,8 @@ fn parse_args() -> (OutputFormat, PathBuf) {
 fn main() {
     rustc_driver::init_env_logger("RUST_LOG");
     let (format, dst) = parse_args();
-    let result =
-        rustc_span::create_default_session_globals_then(move || main_with_result(format, &dst));
+    let result = main_with_result(format, &dst);
     if let Err(e) = result {
-        panic!("{}", e.to_string());
+        panic!("{:?}", e);
     }
 }
diff --git a/src/tools/error_index_generator/redirect.js b/src/tools/error_index_generator/redirect.js
new file mode 100644 (file)
index 0000000..8c907f5
--- /dev/null
@@ -0,0 +1,16 @@
+(function() {
+    if (window.location.hash) {
+        let code = window.location.hash.replace(/^#/, '');
+        // We have to make sure this pattern matches to avoid inadvertently creating an
+        // open redirect.
+        if (!/^E[0-9]+$/.test(code)) {
+            return;
+        }
+        if (window.location.pathname.indexOf("/error_codes/") !== -1) {
+            // We're not at the top level, so we don't prepend with "./error_codes/".
+            window.location = './' + code + '.html';
+        } else {
+            window.location = './error_codes/' + code + '.html';
+        }
+    }
+})()
index 9696e35b7963f8a42f880c78f11ecb015a168e76..2a923a61b0a70b74a78127746059ff568d470386 100644 (file)
@@ -8,6 +8,7 @@
 /// Descriptions of rustc lint groups.
 static GROUP_DESCRIPTIONS: &[(&str, &str)] = &[
     ("unused", "Lints that detect things being declared but not used, or excess syntax"),
+    ("let-underscore", "Lints that detect wildcard let bindings that are likely to be invalid"),
     ("rustdoc", "Rustdoc-specific lints"),
     ("rust-2018-idioms", "Lints to nudge you toward idiomatic features of Rust 2018"),
     ("nonstandard-style", "Violation of standard naming conventions"),
index 90bd24a75e0649d82863c41536a532267e96bac0..1795f3d7fe5bc5a3a0a9b908f333681274971dbb 100644 (file)
@@ -8,8 +8,8 @@
 //! make gcc/clang pass `-flavor <flavor>` as the first two arguments in the linker invocation
 //! and since Windows does not support symbolic links for files this wrapper is used in place of a
 //! symbolic link. It execs `../rust-lld -flavor <flavor>` by propagating the flavor argument
-//! passed to the wrapper as the first two arguments. On Windows it spawns a `..\rust-lld.exe`
-//! child process.
+//! obtained from the wrapper's name as the first two arguments.
+//! On Windows it spawns a `..\rust-lld.exe` child process.
 
 use std::fmt::Display;
 use std::path::{Path, PathBuf};
@@ -53,29 +53,32 @@ fn get_rust_lld_path(current_exe_path: &Path) -> PathBuf {
     rust_lld_path
 }
 
+/// Extract LLD flavor name from the lld-wrapper executable name.
+fn get_lld_flavor(current_exe_path: &Path) -> Result<&'static str, String> {
+    let stem = current_exe_path.file_stem();
+    Ok(match stem.and_then(|s| s.to_str()) {
+        Some("ld.lld") => "gnu",
+        Some("ld64.lld") => "darwin",
+        Some("lld-link") => "link",
+        Some("wasm-ld") => "wasm",
+        _ => return Err(format!("{:?}", stem)),
+    })
+}
+
 /// Returns the command for invoking rust-lld with the correct flavor.
-/// LLD only accepts the flavor argument at the first two arguments, so move it there.
+/// LLD only accepts the flavor argument at the first two arguments, so pass it there.
 ///
 /// Exits on error.
 fn get_rust_lld_command(current_exe_path: &Path) -> process::Command {
     let rust_lld_path = get_rust_lld_path(current_exe_path);
     let mut command = process::Command::new(rust_lld_path);
 
-    let mut flavor = None;
-    let args = env::args_os()
-        .skip(1)
-        .filter(|arg| match arg.to_str().and_then(|s| s.strip_prefix("-rustc-lld-flavor=")) {
-            Some(suffix) => {
-                flavor = Some(suffix.to_string());
-                false
-            }
-            None => true,
-        })
-        .collect::<Vec<_>>();
+    let flavor =
+        get_lld_flavor(current_exe_path).unwrap_or_exit_with("executable has unexpected name");
 
     command.arg("-flavor");
-    command.arg(flavor.unwrap_or_exit_with("-rustc-lld-flavor=<flavor> is not passed"));
-    command.args(args);
+    command.arg(flavor);
+    command.args(env::args_os().skip(1));
     command
 }
 
index ab88e64b152d3704c35db96dbbc6efaaed67773f..dba35d2be72f4b78343d1a0f0b4737306f310672 160000 (submodule)
@@ -1 +1 @@
-Subproject commit ab88e64b152d3704c35db96dbbc6efaaed67773f
+Subproject commit dba35d2be72f4b78343d1a0f0b4737306f310672
index 146e53f2e9a0f16a1bf1e07bfa3fd3e2fb6e23ce..33b35d05415763f06d8af2d9f484e7536cd64d9c 100644 (file)
@@ -14,7 +14,7 @@ fn main() {
             walk::filter_dirs(path)
                 // We exempt these as they require the placeholder
                 // for their operation
-                || path.ends_with("compiler/rustc_passes/src/lib_features.rs")
+                || path.ends_with("compiler/rustc_attr/src/builtin.rs")
                 || path.ends_with("src/tools/tidy/src/features/version.rs")
                 || path.ends_with("src/tools/replace-version-placeholder")
         },
index 3c982b261271d7e7d38fb62b44b85bb6e62b90bc..80bb3b5d6a8d47c7dffd97873e5b3825e4c96af2 100644 (file)
@@ -77,9 +77,6 @@ clap = { version = "3.1.1", features = ["derive", "clap_derive"]}
 curl-sys = { version = "0.4.13", features = ["http2", "libnghttp2-sys"], optional = true }
 # Ensure default features of libz-sys, which are disabled in some scenarios.
 libz-sys = { version = "1.1.2" }
-# The only user of memchr's deprecated `use_std` feature is `combine`, so this can be
-# removed if/when https://github.com/Marwes/combine/pull/348 is merged and released.
-memchr = { version = "2.5", features = ["std", "use_std"] }
 # Ensure default features of regex, which are disabled in some scenarios.
 regex = { version = "1.5.6" }
 serde_json = { version = "1.0.31", features = ["raw_value", "unbounded_depth"] }
index 9b74b35f31413cc20c8b0cdd3863fad51b1ae5b0..e2fe92b28f23e9fc53a256fe1538b188849bccf6 100644 (file)
@@ -1,4 +1,6 @@
-use rustc_ast::ast::{self, BindingMode, Pat, PatField, PatKind, RangeEnd, RangeSyntax};
+use rustc_ast::ast::{
+    self, BindingAnnotation, ByRef, Pat, PatField, PatKind, RangeEnd, RangeSyntax,
+};
 use rustc_ast::ptr;
 use rustc_span::{BytePos, Span};
 
@@ -99,10 +101,10 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
                 write_list(&items, &fmt)
             }
             PatKind::Box(ref pat) => rewrite_unary_prefix(context, "box ", &**pat, shape),
-            PatKind::Ident(binding_mode, ident, ref sub_pat) => {
-                let (prefix, mutability) = match binding_mode {
-                    BindingMode::ByRef(mutability) => ("ref", mutability),
-                    BindingMode::ByValue(mutability) => ("", mutability),
+            PatKind::Ident(BindingAnnotation(by_ref, mutability), ident, ref sub_pat) => {
+                let prefix = match by_ref {
+                    ByRef::Yes => "ref",
+                    ByRef::No => "",
                 };
                 let mut_infix = format_mutability(mutability).trim();
                 let id_str = rewrite_ident(context, ident);
index 05e1eb2bfb00695a6f981f917b20eeaa83880329..cbd8cfa01fccb7315b4a3c76d4bfa56bf3be1e00 100644 (file)
@@ -91,9 +91,6 @@
     "autocfg",
     "bitflags",
     "block-buffer",
-    "block-padding",
-    "byte-tools",
-    "byteorder",
     "cc",
     "cfg-if",
     "chalk-derive",
     "ena",
     "env_logger",
     "expect-test",
-    "fake-simd",
     "fallible-iterator", // dependency of `thorin`
     "filetime",
     "fixedbitset",
     "object",
     "odht",
     "once_cell",
-    "opaque-debug",
     "parking_lot",
     "parking_lot_core",
     "pathdiff",
index 39b47ce703f37b07f807eecd8f60dd3e8c4ac637..3a5b869f72f76d05beb08d12f96c29e2bce4e6b8 100644 (file)
@@ -1,5 +1,6 @@
+#[rustc_const_unstable(feature = "const_unicode_case_lookup", issue = "101400")]
 #[inline(always)]
-fn bitset_search<
+const fn bitset_search<
     const N: usize,
     const CHUNK_SIZE: usize,
     const N1: usize,
@@ -15,14 +16,18 @@ fn bitset_search<
     let bucket_idx = (needle / 64) as usize;
     let chunk_map_idx = bucket_idx / CHUNK_SIZE;
     let chunk_piece = bucket_idx % CHUNK_SIZE;
-    let chunk_idx = if let Some(&v) = chunk_idx_map.get(chunk_map_idx) {
-        v
+    // FIXME: const-hack: Revert to `slice::get` after `const_slice_index`
+    // feature stabilizes.
+    let chunk_idx = if chunk_map_idx < chunk_idx_map.len() {
+        chunk_idx_map[chunk_map_idx]
     } else {
         return false;
     };
     let idx = bitset_chunk_idx[chunk_idx as usize][chunk_piece] as usize;
-    let word = if let Some(word) = bitset_canonical.get(idx) {
-        *word
+    // FIXME: const-hack: Revert to `slice::get` after `const_slice_index`
+    // feature stabilizes.
+    let word = if idx < bitset_canonical.len() {
+        bitset_canonical[idx]
     } else {
         let (real_idx, mapping) = bitset_canonicalized[idx - bitset_canonical.len()];
         let mut word = bitset_canonical[real_idx as usize];
index 13eed7b10997e3d0d60f2571cac36a7a00724971..890ff986c2be05c6178b0c79fd637c88e17e1b28 100644 (file)
@@ -76,7 +76,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 
         writeln!(
             &mut self.file,
-            "static BITSET_CANONICAL: [u64; {}] = [{}];",
+            "const BITSET_CANONICAL: &'static [u64; {}] = &[{}];",
             canonicalized.canonical_words.len(),
             fmt_list(canonicalized.canonical_words.iter().map(|v| Bits(*v))),
         )
@@ -84,7 +84,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         self.bytes_used += 8 * canonicalized.canonical_words.len();
         writeln!(
             &mut self.file,
-            "static BITSET_MAPPING: [(u8, u8); {}] = [{}];",
+            "const BITSET_MAPPING: &'static [(u8, u8); {}] = &[{}];",
             canonicalized.canonicalized_words.len(),
             fmt_list(&canonicalized.canonicalized_words),
         )
@@ -96,7 +96,12 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 
         self.blank_line();
 
-        writeln!(&mut self.file, "pub fn lookup(c: char) -> bool {{").unwrap();
+        writeln!(
+            &mut self.file,
+            r#"#[rustc_const_unstable(feature = "const_unicode_case_lookup", issue = "101400")]"#
+        )
+        .unwrap();
+        writeln!(&mut self.file, "pub const fn lookup(c: char) -> bool {{").unwrap();
         writeln!(&mut self.file, "    super::bitset_search(",).unwrap();
         writeln!(&mut self.file, "        c as u32,").unwrap();
         writeln!(&mut self.file, "        &BITSET_CHUNKS_MAP,").unwrap();
@@ -130,7 +135,7 @@ fn emit_chunk_map(&mut self, zero_at: u8, compressed_words: &[u8], chunk_length:
 
         writeln!(
             &mut self.file,
-            "static BITSET_CHUNKS_MAP: [u8; {}] = [{}];",
+            "const BITSET_CHUNKS_MAP: &'static [u8; {}] = &[{}];",
             chunk_indices.len(),
             fmt_list(&chunk_indices),
         )
@@ -138,7 +143,7 @@ fn emit_chunk_map(&mut self, zero_at: u8, compressed_words: &[u8], chunk_length:
         self.bytes_used += chunk_indices.len();
         writeln!(
             &mut self.file,
-            "static BITSET_INDEX_CHUNKS: [[u8; {}]; {}] = [{}];",
+            "const BITSET_INDEX_CHUNKS: &'static [[u8; {}]; {}] = &[{}];",
             chunk_length,
             chunks.len(),
             fmt_list(chunks.iter()),
index 8a90bc0e3c143c91f8d9ca8c2cc87e396da1ef11..89edab91fcd701a29107e03d6886b273bcca7122 100644 (file)
@@ -195,6 +195,13 @@ trigger_files = [
     "compiler/rustc_macros/src/diagnostics"
 ]
 
+[autolabel."A-query-system"]
+trigger_files = [
+    "compiler/rustc_query_system",
+    "compiler/rustc_query_impl",
+    "compiler/rustc_macros/src/query.rs"
+]
+
 [notify-zulip."I-prioritize"]
 zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts
 topic = "#{number} {title}"
@@ -309,9 +316,6 @@ Examples of `T-libs-api` changes:
 * Changing observable runtime behavior of library APIs
 """
 
-[mentions."library/proc_macro/src/bridge"]
-cc = ["@rust-lang/wg-rls-2"]
-
 [mentions."src/librustdoc/clean/types.rs"]
 cc = ["@camelid"]