]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #105419 - YC:issue-41731, r=petrochenkov
authorMatthias Krüger <matthias.krueger@famsik.de>
Sun, 18 Dec 2022 22:03:04 +0000 (23:03 +0100)
committerGitHub <noreply@github.com>
Sun, 18 Dec 2022 22:03:04 +0000 (23:03 +0100)
Add tests for #41731

Closes #41731

1727 files changed:
.github/workflows/ci.yml
.gitmodules
Cargo.lock
RELEASES.md
compiler/rustc_abi/src/lib.rs
compiler/rustc_apfloat/src/ieee.rs
compiler/rustc_arena/src/lib.rs
compiler/rustc_ast/src/ast.rs
compiler/rustc_ast/src/attr/mod.rs
compiler/rustc_ast/src/ptr.rs
compiler/rustc_ast/src/token.rs
compiler/rustc_ast/src/tokenstream.rs
compiler/rustc_ast/src/util/literal.rs
compiler/rustc_ast_lowering/src/expr.rs
compiler/rustc_ast_lowering/src/item.rs
compiler/rustc_ast_lowering/src/lib.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_pretty/src/pprust/state.rs
compiler/rustc_ast_pretty/src/pprust/state/expr.rs
compiler/rustc_attr/src/builtin.rs
compiler/rustc_borrowck/src/borrow_set.rs
compiler/rustc_borrowck/src/dataflow.rs
compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
compiler/rustc_borrowck/src/diagnostics/mod.rs
compiler/rustc_borrowck/src/diagnostics/move_errors.rs
compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
compiler/rustc_borrowck/src/diagnostics/region_errors.rs
compiler/rustc_borrowck/src/diagnostics/region_name.rs
compiler/rustc_borrowck/src/invalidation.rs
compiler/rustc_borrowck/src/lib.rs
compiler/rustc_borrowck/src/region_infer/mod.rs
compiler/rustc_borrowck/src/type_check/mod.rs
compiler/rustc_borrowck/src/universal_regions.rs
compiler/rustc_builtin_macros/src/alloc_error_handler.rs
compiler/rustc_builtin_macros/src/assert/context.rs
compiler/rustc_builtin_macros/src/concat.rs
compiler/rustc_builtin_macros/src/concat_bytes.rs
compiler/rustc_builtin_macros/src/derive.rs
compiler/rustc_builtin_macros/src/deriving/clone.rs
compiler/rustc_builtin_macros/src/deriving/decodable.rs
compiler/rustc_builtin_macros/src/deriving/default.rs
compiler/rustc_builtin_macros/src/deriving/encodable.rs
compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
compiler/rustc_builtin_macros/src/deriving/generic/ty.rs
compiler/rustc_builtin_macros/src/deriving/mod.rs
compiler/rustc_builtin_macros/src/env.rs
compiler/rustc_builtin_macros/src/format.rs
compiler/rustc_builtin_macros/src/format_foreign.rs
compiler/rustc_builtin_macros/src/global_allocator.rs
compiler/rustc_builtin_macros/src/test.rs
compiler/rustc_builtin_macros/src/test_harness.rs
compiler/rustc_codegen_cranelift/.cirrus.yml
compiler/rustc_codegen_cranelift/.github/workflows/main.yml
compiler/rustc_codegen_cranelift/.github/workflows/nightly-cranelift.yml
compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml
compiler/rustc_codegen_cranelift/.gitignore
compiler/rustc_codegen_cranelift/.vscode/settings.json
compiler/rustc_codegen_cranelift/Cargo.lock
compiler/rustc_codegen_cranelift/Cargo.toml
compiler/rustc_codegen_cranelift/Readme.md
compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock
compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs
compiler/rustc_codegen_cranelift/build_system/build_backend.rs
compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs
compiler/rustc_codegen_cranelift/build_system/mod.rs
compiler/rustc_codegen_cranelift/build_system/path.rs [new file with mode: 0644]
compiler/rustc_codegen_cranelift/build_system/prepare.rs
compiler/rustc_codegen_cranelift/build_system/rustc_info.rs
compiler/rustc_codegen_cranelift/build_system/tests.rs
compiler/rustc_codegen_cranelift/build_system/utils.rs
compiler/rustc_codegen_cranelift/clean_all.sh
compiler/rustc_codegen_cranelift/config.txt
compiler/rustc_codegen_cranelift/docs/usage.md
compiler/rustc_codegen_cranelift/example/issue-72793.rs [new file with mode: 0644]
compiler/rustc_codegen_cranelift/example/mini_core.rs
compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs
compiler/rustc_codegen_cranelift/example/std_example.rs
compiler/rustc_codegen_cranelift/rust-toolchain
compiler/rustc_codegen_cranelift/rustfmt.toml
compiler/rustc_codegen_cranelift/scripts/filter_profile.rs
compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs [new file with mode: 0644]
compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh
compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
compiler/rustc_codegen_cranelift/src/abi/mod.rs
compiler/rustc_codegen_cranelift/src/allocator.rs
compiler/rustc_codegen_cranelift/src/base.rs
compiler/rustc_codegen_cranelift/src/cast.rs
compiler/rustc_codegen_cranelift/src/common.rs
compiler/rustc_codegen_cranelift/src/constant.rs
compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs
compiler/rustc_codegen_cranelift/src/discriminant.rs
compiler/rustc_codegen_cranelift/src/driver/jit.rs
compiler/rustc_codegen_cranelift/src/driver/mod.rs
compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs [new file with mode: 0644]
compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs [new file with mode: 0644]
compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
compiler/rustc_codegen_cranelift/src/main_shim.rs
compiler/rustc_codegen_cranelift/src/num.rs
compiler/rustc_codegen_cranelift/src/optimize/peephole.rs
compiler/rustc_codegen_cranelift/src/value_and_place.rs
compiler/rustc_codegen_cranelift/test.sh
compiler/rustc_codegen_cranelift/y.rs
compiler/rustc_codegen_gcc/src/builder.rs
compiler/rustc_codegen_gcc/src/consts.rs
compiler/rustc_codegen_gcc/src/errors.rs
compiler/rustc_codegen_gcc/src/type_.rs
compiler/rustc_codegen_llvm/src/allocator.rs
compiler/rustc_codegen_llvm/src/back/archive.rs
compiler/rustc_codegen_llvm/src/back/lto.rs
compiler/rustc_codegen_llvm/src/builder.rs
compiler/rustc_codegen_llvm/src/consts.rs
compiler/rustc_codegen_llvm/src/context.rs
compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
compiler/rustc_codegen_llvm/src/declare.rs
compiler/rustc_codegen_llvm/src/errors.rs
compiler/rustc_codegen_llvm/src/intrinsic.rs
compiler/rustc_codegen_llvm/src/llvm/ffi.rs
compiler/rustc_codegen_llvm/src/type_.rs
compiler/rustc_codegen_ssa/src/back/archive.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/codegen_attrs.rs [new file with mode: 0644]
compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
compiler/rustc_codegen_ssa/src/errors.rs
compiler/rustc_codegen_ssa/src/lib.rs
compiler/rustc_codegen_ssa/src/meth.rs
compiler/rustc_codegen_ssa/src/mir/block.rs
compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
compiler/rustc_codegen_ssa/src/mir/rvalue.rs
compiler/rustc_codegen_ssa/src/target_features.rs
compiler/rustc_codegen_ssa/src/traits/builder.rs
compiler/rustc_codegen_ssa/src/traits/type_.rs
compiler/rustc_const_eval/src/const_eval/error.rs
compiler/rustc_const_eval/src/const_eval/eval_queries.rs
compiler/rustc_const_eval/src/const_eval/machine.rs
compiler/rustc_const_eval/src/const_eval/valtrees.rs
compiler/rustc_const_eval/src/interpret/cast.rs
compiler/rustc_const_eval/src/interpret/eval_context.rs
compiler/rustc_const_eval/src/interpret/intrinsics.rs
compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs
compiler/rustc_const_eval/src/interpret/machine.rs
compiler/rustc_const_eval/src/interpret/memory.rs
compiler/rustc_const_eval/src/interpret/operand.rs
compiler/rustc_const_eval/src/interpret/operator.rs
compiler/rustc_const_eval/src/interpret/place.rs
compiler/rustc_const_eval/src/interpret/step.rs
compiler/rustc_const_eval/src/interpret/terminator.rs
compiler/rustc_const_eval/src/interpret/util.rs
compiler/rustc_const_eval/src/interpret/validity.rs
compiler/rustc_const_eval/src/transform/validate.rs
compiler/rustc_const_eval/src/util/aggregate.rs
compiler/rustc_const_eval/src/util/call_kind.rs
compiler/rustc_const_eval/src/util/might_permit_raw_init.rs
compiler/rustc_const_eval/src/util/type_name.rs
compiler/rustc_data_structures/src/base_n.rs
compiler/rustc_data_structures/src/fingerprint.rs
compiler/rustc_data_structures/src/graph/scc/mod.rs
compiler/rustc_data_structures/src/graph/vec_graph/mod.rs
compiler/rustc_data_structures/src/owning_ref/mod.rs
compiler/rustc_data_structures/src/owning_ref/tests.rs
compiler/rustc_data_structures/src/profiling.rs
compiler/rustc_data_structures/src/sorted_map.rs
compiler/rustc_data_structures/src/sorted_map/index_map.rs
compiler/rustc_data_structures/src/sso/either_iter.rs
compiler/rustc_data_structures/src/sso/map.rs
compiler/rustc_data_structures/src/sso/set.rs
compiler/rustc_data_structures/src/sync.rs
compiler/rustc_data_structures/src/tagged_ptr/drop.rs
compiler/rustc_data_structures/src/vec_map.rs
compiler/rustc_driver/src/lib.rs
compiler/rustc_error_codes/src/error_codes.rs
compiler/rustc_error_codes/src/error_codes/E0158.md
compiler/rustc_error_codes/src/error_codes/E0320.md [new file with mode: 0644]
compiler/rustc_error_codes/src/error_codes/E0492.md
compiler/rustc_error_codes/src/error_codes/E0791.md [new file with mode: 0644]
compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl
compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl
compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl
compiler/rustc_error_messages/locales/en-US/expand.ftl
compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl
compiler/rustc_error_messages/locales/en-US/metadata.ftl
compiler/rustc_error_messages/locales/en-US/mir_build.ftl [new file with mode: 0644]
compiler/rustc_error_messages/locales/en-US/monomorphize.ftl
compiler/rustc_error_messages/locales/en-US/parse.ftl
compiler/rustc_error_messages/locales/en-US/session.ftl
compiler/rustc_error_messages/src/lib.rs
compiler/rustc_errors/src/diagnostic.rs
compiler/rustc_errors/src/diagnostic_impls.rs
compiler/rustc_errors/src/emitter.rs
compiler/rustc_errors/src/lib.rs
compiler/rustc_expand/src/base.rs
compiler/rustc_expand/src/build.rs
compiler/rustc_expand/src/config.rs
compiler/rustc_expand/src/errors.rs
compiler/rustc_expand/src/expand.rs
compiler/rustc_expand/src/lib.rs
compiler/rustc_expand/src/mbe/macro_check.rs
compiler/rustc_expand/src/mbe/macro_rules.rs
compiler/rustc_expand/src/module.rs
compiler/rustc_expand/src/proc_macro_server.rs
compiler/rustc_expand/src/tests.rs
compiler/rustc_feature/src/accepted.rs
compiler/rustc_feature/src/active.rs
compiler/rustc_feature/src/builtin_attrs.rs
compiler/rustc_hir/src/hir.rs
compiler/rustc_hir/src/pat_util.rs
compiler/rustc_hir/src/tests.rs
compiler/rustc_hir_analysis/src/astconv/mod.rs
compiler/rustc_hir_analysis/src/check/check.rs
compiler/rustc_hir_analysis/src/check/compare_method.rs
compiler/rustc_hir_analysis/src/check/mod.rs
compiler/rustc_hir_analysis/src/check/wfcheck.rs
compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
compiler/rustc_hir_analysis/src/collect.rs
compiler/rustc_hir_analysis/src/collect/generics_of.rs
compiler/rustc_hir_analysis/src/collect/lifetimes.rs
compiler/rustc_hir_analysis/src/collect/predicates_of.rs
compiler/rustc_hir_analysis/src/collect/type_of.rs
compiler/rustc_hir_analysis/src/constrained_generic_params.rs
compiler/rustc_hir_analysis/src/errors.rs
compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
compiler/rustc_hir_analysis/src/outlives/utils.rs
compiler/rustc_hir_analysis/src/variance/constraints.rs
compiler/rustc_hir_analysis/src/variance/mod.rs
compiler/rustc_hir_pretty/src/lib.rs
compiler/rustc_hir_typeck/src/_match.rs
compiler/rustc_hir_typeck/src/callee.rs
compiler/rustc_hir_typeck/src/cast.rs
compiler/rustc_hir_typeck/src/check.rs
compiler/rustc_hir_typeck/src/closure.rs
compiler/rustc_hir_typeck/src/coercion.rs
compiler/rustc_hir_typeck/src/demand.rs
compiler/rustc_hir_typeck/src/expr.rs
compiler/rustc_hir_typeck/src/expr_use_visitor.rs
compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
compiler/rustc_hir_typeck/src/generator_interior/mod.rs
compiler/rustc_hir_typeck/src/lib.rs
compiler/rustc_hir_typeck/src/method/confirm.rs
compiler/rustc_hir_typeck/src/method/mod.rs
compiler/rustc_hir_typeck/src/method/probe.rs
compiler/rustc_hir_typeck/src/method/suggest.rs
compiler/rustc_hir_typeck/src/pat.rs
compiler/rustc_hir_typeck/src/writeback.rs
compiler/rustc_incremental/src/assert_dep_graph.rs
compiler/rustc_incremental/src/persist/dirty_clean.rs
compiler/rustc_incremental/src/persist/fs.rs
compiler/rustc_index/src/bit_set.rs
compiler/rustc_index/src/vec.rs
compiler/rustc_infer/src/errors/mod.rs
compiler/rustc_infer/src/infer/at.rs
compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
compiler/rustc_infer/src/infer/combine.rs
compiler/rustc_infer/src/infer/equate.rs
compiler/rustc_infer/src/infer/error_reporting/mod.rs
compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
compiler/rustc_infer/src/infer/error_reporting/note.rs
compiler/rustc_infer/src/infer/error_reporting/note_region.rs [new file with mode: 0644]
compiler/rustc_infer/src/infer/error_reporting/suggest.rs [new file with mode: 0644]
compiler/rustc_infer/src/infer/freshen.rs
compiler/rustc_infer/src/infer/glb.rs
compiler/rustc_infer/src/infer/lattice.rs
compiler/rustc_infer/src/infer/lub.rs
compiler/rustc_infer/src/infer/mod.rs
compiler/rustc_infer/src/infer/nll_relate/mod.rs
compiler/rustc_infer/src/infer/note.rs [new file with mode: 0644]
compiler/rustc_infer/src/infer/opaque_types.rs
compiler/rustc_infer/src/infer/outlives/components.rs
compiler/rustc_infer/src/infer/outlives/obligations.rs
compiler/rustc_infer/src/infer/outlives/verify.rs
compiler/rustc_infer/src/infer/projection.rs
compiler/rustc_infer/src/infer/region_constraints/mod.rs
compiler/rustc_infer/src/infer/sub.rs
compiler/rustc_infer/src/traits/project.rs
compiler/rustc_infer/src/traits/util.rs
compiler/rustc_interface/src/passes.rs
compiler/rustc_interface/src/queries.rs
compiler/rustc_interface/src/tests.rs
compiler/rustc_lexer/src/lib.rs
compiler/rustc_lexer/src/unescape.rs
compiler/rustc_lint/src/builtin.rs
compiler/rustc_lint/src/context.rs
compiler/rustc_lint/src/early.rs
compiler/rustc_lint/src/hidden_unicode_codepoints.rs
compiler/rustc_lint/src/late.rs
compiler/rustc_lint/src/lib.rs
compiler/rustc_lint/src/nonstandard_style.rs
compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
compiler/rustc_lint/src/passes.rs
compiler/rustc_lint/src/types.rs
compiler/rustc_lint/src/unused.rs
compiler/rustc_lint_defs/src/builtin.rs
compiler/rustc_llvm/build.rs
compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
compiler/rustc_macros/src/diagnostics/diagnostic.rs
compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
compiler/rustc_metadata/src/creader.rs
compiler/rustc_metadata/src/errors.rs
compiler/rustc_metadata/src/fs.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/table.rs
compiler/rustc_middle/src/arena.rs
compiler/rustc_middle/src/hir/map/mod.rs
compiler/rustc_middle/src/hir/mod.rs
compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
compiler/rustc_middle/src/mir/coverage.rs
compiler/rustc_middle/src/mir/interpret/mod.rs
compiler/rustc_middle/src/mir/interpret/pointer.rs
compiler/rustc_middle/src/mir/interpret/value.rs
compiler/rustc_middle/src/mir/mod.rs
compiler/rustc_middle/src/mir/mono.rs
compiler/rustc_middle/src/mir/syntax.rs
compiler/rustc_middle/src/mir/tcx.rs
compiler/rustc_middle/src/mir/terminator.rs
compiler/rustc_middle/src/mir/visit.rs
compiler/rustc_middle/src/query/keys.rs
compiler/rustc_middle/src/query/mod.rs
compiler/rustc_middle/src/traits/mod.rs
compiler/rustc_middle/src/traits/query.rs
compiler/rustc_middle/src/ty/adjustment.rs
compiler/rustc_middle/src/ty/codec.rs
compiler/rustc_middle/src/ty/consts.rs
compiler/rustc_middle/src/ty/consts/int.rs
compiler/rustc_middle/src/ty/consts/kind.rs
compiler/rustc_middle/src/ty/context.rs
compiler/rustc_middle/src/ty/diagnostics.rs
compiler/rustc_middle/src/ty/error.rs
compiler/rustc_middle/src/ty/fast_reject.rs
compiler/rustc_middle/src/ty/flags.rs
compiler/rustc_middle/src/ty/fold.rs
compiler/rustc_middle/src/ty/generics.rs
compiler/rustc_middle/src/ty/inhabitedness/mod.rs
compiler/rustc_middle/src/ty/instance.rs
compiler/rustc_middle/src/ty/layout.rs
compiler/rustc_middle/src/ty/mod.rs
compiler/rustc_middle/src/ty/parameterized.rs
compiler/rustc_middle/src/ty/print/mod.rs
compiler/rustc_middle/src/ty/print/pretty.rs
compiler/rustc_middle/src/ty/relate.rs
compiler/rustc_middle/src/ty/structural_impls.rs
compiler/rustc_middle/src/ty/sty.rs
compiler/rustc_middle/src/ty/subst.rs
compiler/rustc_middle/src/ty/typeck_results.rs [new file with mode: 0644]
compiler/rustc_middle/src/ty/util.rs
compiler/rustc_middle/src/ty/visit.rs
compiler/rustc_middle/src/ty/vtable.rs
compiler/rustc_middle/src/ty/walk.rs
compiler/rustc_mir_build/Cargo.toml
compiler/rustc_mir_build/src/build/block.rs
compiler/rustc_mir_build/src/build/custom/mod.rs
compiler/rustc_mir_build/src/build/custom/parse/instruction.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/as_rvalue.rs
compiler/rustc_mir_build/src/build/expr/into.rs
compiler/rustc_mir_build/src/build/expr/stmt.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/errors.rs [new file with mode: 0644]
compiler/rustc_mir_build/src/lib.rs
compiler/rustc_mir_build/src/lints.rs
compiler/rustc_mir_build/src/thir/constant.rs
compiler/rustc_mir_build/src/thir/cx/expr.rs
compiler/rustc_mir_build/src/thir/pattern/check_match.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_dataflow/src/drop_flag_effects.rs
compiler/rustc_mir_dataflow/src/elaborate_drops.rs
compiler/rustc_mir_dataflow/src/framework/direction.rs
compiler/rustc_mir_dataflow/src/framework/lattice.rs
compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs
compiler/rustc_mir_dataflow/src/value_analysis.rs
compiler/rustc_mir_transform/src/add_retag.rs
compiler/rustc_mir_transform/src/check_unsafety.rs
compiler/rustc_mir_transform/src/const_goto.rs
compiler/rustc_mir_transform/src/const_prop.rs
compiler/rustc_mir_transform/src/coverage/tests.rs
compiler/rustc_mir_transform/src/dataflow_const_prop.rs
compiler/rustc_mir_transform/src/dest_prop.rs
compiler/rustc_mir_transform/src/early_otherwise_branch.rs
compiler/rustc_mir_transform/src/generator.rs
compiler/rustc_mir_transform/src/inline.rs
compiler/rustc_mir_transform/src/match_branches.rs
compiler/rustc_mir_transform/src/remove_zsts.rs
compiler/rustc_mir_transform/src/shim.rs
compiler/rustc_mir_transform/src/simplify.rs
compiler/rustc_mir_transform/src/simplify_branches.rs
compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
compiler/rustc_mir_transform/src/unreachable_prop.rs
compiler/rustc_monomorphize/src/collector.rs
compiler/rustc_monomorphize/src/errors.rs
compiler/rustc_monomorphize/src/partitioning/mod.rs
compiler/rustc_monomorphize/src/polymorphize.rs
compiler/rustc_parse/src/errors.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/expr.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/stmt.rs
compiler/rustc_parse_format/Cargo.toml
compiler/rustc_parse_format/src/lib.rs
compiler/rustc_parse_format/src/tests.rs
compiler/rustc_passes/src/dead.rs
compiler/rustc_passes/src/hir_stats.rs
compiler/rustc_passes/src/lang_items.rs
compiler/rustc_privacy/src/lib.rs
compiler/rustc_query_system/src/dep_graph/graph.rs
compiler/rustc_query_system/src/dep_graph/serialized.rs
compiler/rustc_query_system/src/error.rs
compiler/rustc_query_system/src/ich/hcx.rs
compiler/rustc_query_system/src/query/caches.rs
compiler/rustc_query_system/src/query/job.rs
compiler/rustc_resolve/src/build_reduced_graph.rs
compiler/rustc_resolve/src/diagnostics.rs
compiler/rustc_resolve/src/effective_visibilities.rs
compiler/rustc_resolve/src/imports.rs
compiler/rustc_resolve/src/late.rs
compiler/rustc_resolve/src/late/diagnostics.rs
compiler/rustc_resolve/src/lib.rs
compiler/rustc_resolve/src/macros.rs
compiler/rustc_save_analysis/src/dump_visitor.rs
compiler/rustc_save_analysis/src/lib.rs
compiler/rustc_serialize/src/opaque.rs
compiler/rustc_session/Cargo.toml
compiler/rustc_session/src/code_stats.rs
compiler/rustc_session/src/config.rs
compiler/rustc_session/src/cstore.rs
compiler/rustc_session/src/errors.rs
compiler/rustc_session/src/filesearch.rs
compiler/rustc_session/src/options.rs
compiler/rustc_session/src/output.rs
compiler/rustc_session/src/session.rs
compiler/rustc_span/src/analyze_source_file.rs
compiler/rustc_span/src/def_id.rs
compiler/rustc_span/src/lib.rs
compiler/rustc_span/src/source_map.rs
compiler/rustc_span/src/symbol.rs
compiler/rustc_symbol_mangling/Cargo.toml
compiler/rustc_symbol_mangling/src/legacy.rs
compiler/rustc_symbol_mangling/src/typeid.rs
compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
compiler/rustc_symbol_mangling/src/v0.rs
compiler/rustc_target/src/lib.rs
compiler/rustc_target/src/spec/aarch64_unknown_none.rs
compiler/rustc_target/src/spec/apple_base.rs
compiler/rustc_target/src/spec/mod.rs
compiler/rustc_target/src/spec/powerpc64_ibm_aix.rs
compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs
compiler/rustc_target/src/spec/wasm32_wasi.rs
compiler/rustc_target/src/spec/x86_64_unknown_none.rs
compiler/rustc_trait_selection/src/traits/auto_trait.rs
compiler/rustc_trait_selection/src/traits/codegen.rs [deleted file]
compiler/rustc_trait_selection/src/traits/coherence.rs
compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs [new file with mode: 0644]
compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
compiler/rustc_trait_selection/src/traits/mod.rs
compiler/rustc_trait_selection/src/traits/object_safety.rs
compiler/rustc_trait_selection/src/traits/project.rs
compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
compiler/rustc_trait_selection/src/traits/query/normalize.rs
compiler/rustc_trait_selection/src/traits/relationships.rs
compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
compiler/rustc_trait_selection/src/traits/select/confirmation.rs
compiler/rustc_trait_selection/src/traits/select/mod.rs
compiler/rustc_trait_selection/src/traits/structural_match.rs
compiler/rustc_trait_selection/src/traits/util.rs
compiler/rustc_trait_selection/src/traits/vtable.rs [new file with mode: 0644]
compiler/rustc_trait_selection/src/traits/wf.rs
compiler/rustc_traits/src/chalk/db.rs
compiler/rustc_traits/src/chalk/lowering.rs
compiler/rustc_traits/src/codegen.rs [new file with mode: 0644]
compiler/rustc_traits/src/dropck_outlives.rs
compiler/rustc_traits/src/lib.rs
compiler/rustc_ty_utils/src/abi.rs
compiler/rustc_ty_utils/src/instance.rs
compiler/rustc_ty_utils/src/layout.rs
compiler/rustc_ty_utils/src/lib.rs
compiler/rustc_ty_utils/src/needs_drop.rs
compiler/rustc_ty_utils/src/structural_match.rs [new file with mode: 0644]
compiler/rustc_ty_utils/src/ty.rs
compiler/rustc_type_ir/src/lib.rs
compiler/rustc_type_ir/src/sty.rs
config.toml.example
library/alloc/src/collections/vec_deque/into_iter.rs
library/alloc/src/collections/vec_deque/mod.rs
library/alloc/src/collections/vec_deque/spec_from_iter.rs [new file with mode: 0644]
library/alloc/src/fmt.rs
library/alloc/src/vec/into_iter.rs
library/alloc/tests/vec_deque.rs
library/core/src/array/mod.rs
library/core/src/borrow.rs
library/core/src/clone.rs
library/core/src/convert/mod.rs
library/core/src/fmt/mod.rs
library/core/src/hint.rs
library/core/src/intrinsics/mir.rs
library/core/src/iter/traits/accum.rs
library/core/src/iter/traits/iterator.rs
library/core/src/num/mod.rs
library/core/src/ops/mod.rs
library/core/src/option.rs
library/core/src/ptr/const_ptr.rs
library/core/src/ptr/mod.rs
library/core/src/ptr/mut_ptr.rs
library/core/src/ptr/non_null.rs
library/core/src/result.rs
library/core/src/slice/mod.rs
library/core/src/str/mod.rs
library/core/src/sync/exclusive.rs
library/proc_macro/src/lib.rs
library/std/Cargo.toml
library/std/src/env.rs
library/std/src/fs/tests.rs
library/std/src/path.rs
library/std/src/process.rs
library/std/src/sys/itron/condvar.rs
library/std/src/sys/itron/mutex.rs
library/std/src/sys/itron/thread.rs
library/std/src/sys/sgx/mod.rs
library/std/src/sys/sgx/thread.rs
library/std/src/sys/sgx/thread_parker.rs [new file with mode: 0644]
library/std/src/sys/solid/io.rs
library/std/src/sys/solid/os.rs
library/std/src/sys/unix/fs.rs
library/std/src/sys/unix/kernel_copy.rs
library/std/src/sys/unix/locks/pthread_condvar.rs
library/std/src/sys/unix/mod.rs
library/std/src/sys/unix/pipe.rs
library/std/src/sys/unix/process/process_fuchsia.rs
library/std/src/sys/unix/process/process_unix.rs
library/std/src/sys/unix/process/process_unsupported.rs
library/std/src/sys/unix/process/process_vxworks.rs
library/std/src/sys/unix/stack_overflow.rs
library/std/src/sys/unix/thread.rs
library/std/src/sys/unix/thread_parker/pthread.rs
library/std/src/sys/unix/time.rs
library/std/src/sys/unix/weak.rs
library/std/src/sys/unsupported/pipe.rs
library/std/src/sys/unsupported/process.rs
library/std/src/sys/windows/pipe.rs
library/std/src/sys/windows/process.rs
library/std/src/sys_common/process.rs
library/std/src/sys_common/thread_parker/mod.rs
src/bootstrap/builder.rs
src/bootstrap/cache.rs
src/bootstrap/config.rs
src/bootstrap/config/tests.rs [new file with mode: 0644]
src/bootstrap/defaults/config.user.toml
src/bootstrap/dist.rs
src/bootstrap/flags.rs
src/bootstrap/format.rs
src/bootstrap/install.rs
src/bootstrap/lib.rs
src/bootstrap/setup.rs
src/bootstrap/tool.rs
src/ci/docker/host-x86_64/dist-powerpc64le-linux/Dockerfile
src/ci/docker/host-x86_64/mingw-check/Dockerfile
src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile
src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile
src/ci/docker/scripts/fuchsia-test-runner.py
src/ci/github-actions/ci.yml
src/ci/run.sh
src/doc/rustc/src/command-line-arguments.md
src/doc/rustc/src/exploit-mitigations.md
src/doc/rustc/src/linker-plugin-lto.md
src/doc/rustc/src/platform-support/android.md
src/doc/rustc/src/platform-support/armv6k-nintendo-3ds.md
src/doc/rustc/src/platform-support/fuchsia.md
src/doc/rustc/src/targets/custom.md
src/doc/unstable-book/src/compiler-flags/branch-protection.md
src/doc/unstable-book/src/compiler-flags/control-flow-guard.md
src/doc/unstable-book/src/compiler-flags/sanitizer.md
src/doc/unstable-book/src/compiler-flags/virtual-function-elimination.md
src/doc/unstable-book/src/language-features/auto-traits.md
src/doc/unstable-book/src/language-features/unboxed-closures.md
src/doc/unstable-book/src/library-features/default-free-fn.md
src/doc/unstable-book/src/library-features/fn-traits.md
src/librustdoc/clean/auto_trait.rs
src/librustdoc/clean/blanket_impl.rs
src/librustdoc/clean/cfg/tests.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/clean/types.rs
src/librustdoc/clean/utils.rs
src/librustdoc/config.rs
src/librustdoc/formats/item_type.rs
src/librustdoc/html/highlight.rs
src/librustdoc/html/markdown.rs
src/librustdoc/html/markdown/tests.rs
src/librustdoc/html/render/context.rs
src/librustdoc/html/render/mod.rs
src/librustdoc/html/render/print_item.rs
src/librustdoc/html/sources.rs
src/librustdoc/html/static/css/rustdoc.css
src/librustdoc/html/static/css/settings.css
src/librustdoc/html/static/css/themes/ayu.css
src/librustdoc/html/static/css/themes/dark.css
src/librustdoc/html/static/css/themes/light.css
src/librustdoc/html/static/js/main.js
src/librustdoc/html/static/js/scrape-examples.js
src/librustdoc/html/static/js/source-script.js
src/librustdoc/html/static/scrape-examples-help.md
src/librustdoc/lib.rs
src/librustdoc/markdown.rs
src/librustdoc/passes/collect_intra_doc_links.rs
src/librustdoc/passes/collect_trait_impls.rs
src/librustdoc/scrape_examples.rs
src/llvm-project
src/test/codegen/avr/avr-func-addrspace.rs
src/test/codegen/catch-unwind.rs
src/test/codegen/enum-match.rs
src/test/codegen/issue-105386-ub-in-debuginfo.rs [new file with mode: 0644]
src/test/codegen/pgo-counter-bias.rs [new file with mode: 0644]
src/test/codegen/remap_path_prefix/main.rs
src/test/codegen/repr-transparent-aggregates-1.rs
src/test/codegen/repr-transparent.rs
src/test/codegen/sanitizer-kcfi-add-kcfi-flag.rs [new file with mode: 0644]
src/test/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi.rs [new file with mode: 0644]
src/test/codegen/uninit-consts.rs
src/test/incremental/hashes/loop_expressions.rs
src/test/incremental/hashes/while_let_loops.rs
src/test/incremental/hashes/while_loops.rs
src/test/mir-opt/76803_regression.encode.SimplifyBranchSame.diff
src/test/mir-opt/bool_compare.opt1.InstCombine.diff
src/test/mir-opt/bool_compare.opt2.InstCombine.diff
src/test/mir-opt/bool_compare.opt3.InstCombine.diff
src/test/mir-opt/bool_compare.opt4.InstCombine.diff
src/test/mir-opt/building/custom/enums.rs [new file with mode: 0644]
src/test/mir-opt/building/custom/enums.set_discr.built.after.mir [new file with mode: 0644]
src/test/mir-opt/building/custom/enums.set_discr_repr.built.after.mir [new file with mode: 0644]
src/test/mir-opt/building/custom/enums.switch_bool.built.after.mir [new file with mode: 0644]
src/test/mir-opt/building/custom/enums.switch_option.built.after.mir [new file with mode: 0644]
src/test/mir-opt/building/custom/enums.switch_option_repr.built.after.mir [new file with mode: 0644]
src/test/mir-opt/building/custom/projections.rs [new file with mode: 0644]
src/test/mir-opt/building/custom/projections.set.built.after.mir [new file with mode: 0644]
src/test/mir-opt/building/custom/projections.simple_index.built.after.mir [new file with mode: 0644]
src/test/mir-opt/building/custom/projections.tuples.built.after.mir [new file with mode: 0644]
src/test/mir-opt/building/custom/projections.unions.built.after.mir [new file with mode: 0644]
src/test/mir-opt/building/custom/projections.unwrap.built.after.mir [new file with mode: 0644]
src/test/mir-opt/building/custom/projections.unwrap_deref.built.after.mir [new file with mode: 0644]
src/test/mir-opt/building/custom/references.raw_pointer.built.after.mir [new file with mode: 0644]
src/test/mir-opt/building/custom/references.rs
src/test/mir-opt/building/custom/terminators.assert_nonzero.built.after.mir [new file with mode: 0644]
src/test/mir-opt/building/custom/terminators.direct_call.built.after.mir [new file with mode: 0644]
src/test/mir-opt/building/custom/terminators.drop_first.built.after.mir [new file with mode: 0644]
src/test/mir-opt/building/custom/terminators.drop_second.built.after.mir [new file with mode: 0644]
src/test/mir-opt/building/custom/terminators.indirect_call.built.after.mir [new file with mode: 0644]
src/test/mir-opt/building/custom/terminators.rs [new file with mode: 0644]
src/test/mir-opt/building/issue_101867.main.built.after.mir
src/test/mir-opt/building/issue_49232.main.built.after.mir
src/test/mir-opt/building/match_false_edges.full_tested_match.built.after.mir
src/test/mir-opt/building/match_false_edges.full_tested_match2.built.after.mir
src/test/mir-opt/building/match_false_edges.main.built.after.mir
src/test/mir-opt/building/simple_match.match_bool.built.after.mir
src/test/mir-opt/const_goto.issue_77355_opt.ConstGoto.diff
src/test/mir-opt/const_goto_const_eval_fail.f.ConstGoto.diff
src/test/mir-opt/const_goto_storage.match_nested_if.ConstGoto.diff
src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff
src/test/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff
src/test/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff
src/test/mir-opt/const_prop/switch_int.main.ConstProp.diff
src/test/mir-opt/const_prop/switch_int.main.SimplifyConstCondition-after-const-prop.diff
src/test/mir-opt/coverage_graphviz.main.InstrumentCoverage.0.dot
src/test/mir-opt/dataflow-const-prop/enum.main.DataflowConstProp.diff
src/test/mir-opt/dataflow-const-prop/if.main.DataflowConstProp.diff
src/test/mir-opt/dataflow-const-prop/issue_81605.f.DataflowConstProp.diff
src/test/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff
src/test/mir-opt/deaggregator_test_enum_2.test1.Deaggregator.diff
src/test/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff
src/test/mir-opt/deref-patterns/string.foo.PreCodegen.after.mir
src/test/mir-opt/derefer_complex_case.main.Derefer.diff
src/test/mir-opt/derefer_terminator_test.main.Derefer.diff
src/test/mir-opt/dest-prop/branch.foo.DestinationPropagation.diff
src/test/mir-opt/dest-prop/unreachable.f.DestinationPropagation.diff [new file with mode: 0644]
src/test/mir-opt/dest-prop/unreachable.rs [new file with mode: 0644]
src/test/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff
src/test/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff
src/test/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff
src/test/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff
src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff
src/test/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff
src/test/mir-opt/early_otherwise_branch_soundness.no_deref_ptr.EarlyOtherwiseBranch.diff
src/test/mir-opt/early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff
src/test/mir-opt/equal_true.opt.InstCombine.diff
src/test/mir-opt/exponential_or.match_tuple.SimplifyCfg-initial.after.mir
src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff
src/test/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.mir
src/test/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir
src/test/mir-opt/if_condition_int.dont_opt_bool.SimplifyComparisonIntegral.diff
src/test/mir-opt/if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff
src/test/mir-opt/if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff
src/test/mir-opt/if_condition_int.opt_char.SimplifyComparisonIntegral.diff
src/test/mir-opt/if_condition_int.opt_i8.SimplifyComparisonIntegral.diff
src/test/mir-opt/if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff
src/test/mir-opt/if_condition_int.opt_negative.SimplifyComparisonIntegral.diff
src/test/mir-opt/if_condition_int.opt_u32.SimplifyComparisonIntegral.diff
src/test/mir-opt/inline/inline_diverging.g.Inline.diff
src/test/mir-opt/inline/inline_generator.main.Inline.diff
src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir
src/test/mir-opt/inline/inline_shims.drop.Inline.diff
src/test/mir-opt/instrument_coverage.main.InstrumentCoverage.diff
src/test/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir
src/test/mir-opt/issue_41110.main.ElaborateDrops.after.mir
src/test/mir-opt/issue_41110.test.ElaborateDrops.after.mir
src/test/mir-opt/issue_41888.main.ElaborateDrops.after.mir
src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir
src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff
src/test/mir-opt/issue_99325.main.built.after.mir
src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir
src/test/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff
src/test/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir
src/test/mir-opt/lower_array_len.array_bound.NormalizeArrayLen.diff
src/test/mir-opt/lower_array_len.array_bound_mut.NormalizeArrayLen.diff
src/test/mir-opt/lower_array_len_e2e.array_bound.PreCodegen.after.mir
src/test/mir-opt/lower_array_len_e2e.array_bound_mut.PreCodegen.after.mir
src/test/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff
src/test/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff
src/test/mir-opt/match_test.main.SimplifyCfg-initial.after.mir
src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff
src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff
src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.diff
src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff
src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff
src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir
src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir
src/test/mir-opt/no_drop_for_inactive_variant.unwrap.SimplifyCfg-elaborate-drops.after.mir
src/test/mir-opt/not_equal_false.opt.InstCombine.diff
src/test/mir-opt/remove_fake_borrows.match_guard.CleanupNonCodegenStatements.diff
src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff
src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir
src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir
src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir
src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir
src/test/mir-opt/retag.{impl#0}-foo.SimplifyCfg-elaborate-drops.after.mir
src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff
src/test/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff
src/test/mir-opt/simplify_cfg.main.SimplifyCfg-early-opt.diff
src/test/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff
src/test/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.diff
src/test/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals.diff
src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff
src/test/mir-opt/simplify_match.main.ConstProp.diff
src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir
src/test/mir-opt/sroa.enums.ScalarReplacementOfAggregates.diff
src/test/mir-opt/try_identity_e2e.new.PreCodegen.after.mir
src/test/mir-opt/try_identity_e2e.old.PreCodegen.after.mir
src/test/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir
src/test/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff
src/test/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir
src/test/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff
src/test/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UninhabitedEnumBranching.diff
src/test/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff
src/test/mir-opt/unreachable.main.UnreachablePropagation.diff
src/test/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff
src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff
src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir
src/test/run-make-fulldeps/core-no-fp-fmt-parse/Makefile
src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
src/test/run-make/coverage-reports/Makefile
src/test/run-make/issue-71519/Makefile
src/test/rustdoc-gui/basic.goml [deleted file]
src/test/rustdoc-gui/code-sidebar-toggle.goml
src/test/rustdoc-gui/codeblock-tooltip.goml
src/test/rustdoc-gui/cursor.goml
src/test/rustdoc-gui/docblock-big-code-mobile.goml
src/test/rustdoc-gui/docblock-code-block-line-number.goml
src/test/rustdoc-gui/docblock-table.goml
src/test/rustdoc-gui/help-page.goml
src/test/rustdoc-gui/impl-doc.goml [new file with mode: 0644]
src/test/rustdoc-gui/scrape-examples-button-focus.goml
src/test/rustdoc-gui/scrape-examples-toggle.goml [new file with mode: 0644]
src/test/rustdoc-gui/sidebar-source-code-display.goml
src/test/rustdoc-gui/source-code-page.goml
src/test/rustdoc-gui/src/test_docs/lib.rs
src/test/rustdoc-gui/stab-badge.goml [new file with mode: 0644]
src/test/rustdoc-ui/const-evalutation-ice.rs [new file with mode: 0644]
src/test/rustdoc-ui/const-evalutation-ice.stderr [new file with mode: 0644]
src/test/rustdoc-ui/doc-cfg.stderr
src/test/rustdoc-ui/unable-fulfill-trait.rs [new file with mode: 0644]
src/test/rustdoc-ui/unable-fulfill-trait.stderr [new file with mode: 0644]
src/test/rustdoc-ui/z-help.stdout
src/test/rustdoc/const-evalutation-ice.rs [deleted file]
src/test/rustdoc/read-more-unneeded.rs [new file with mode: 0644]
src/test/rustdoc/toggle-trait-fn.rs
src/test/rustdoc/trait-impl.rs
src/test/ui-fulldeps/internal-lints/ty_tykind_usage.rs
src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr
src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr
src/test/ui/allocator/no_std-alloc-error-handler-custom.rs
src/test/ui/allocator/no_std-alloc-error-handler-default.rs
src/test/ui/anonymous-higher-ranked-lifetime.stderr
src/test/ui/argument-suggestions/display-is-suggestable.rs [new file with mode: 0644]
src/test/ui/argument-suggestions/display-is-suggestable.stderr [new file with mode: 0644]
src/test/ui/array-slice-vec/infer_array_len.stderr
src/test/ui/associated-inherent-types/style.rs [new file with mode: 0644]
src/test/ui/associated-inherent-types/style.stderr [new file with mode: 0644]
src/test/ui/associated-item/issue-105449.rs [new file with mode: 0644]
src/test/ui/associated-type-bounds/const-projection-err.gce.stderr [new file with mode: 0644]
src/test/ui/associated-type-bounds/const-projection-err.rs [new file with mode: 0644]
src/test/ui/associated-type-bounds/const-projection-err.stock.stderr [new file with mode: 0644]
src/test/ui/associated-type-bounds/issue-99828.stderr
src/test/ui/associated-types/associated-types-overridden-binding-2.rs
src/test/ui/associated-types/associated-types-overridden-binding-2.stderr
src/test/ui/associated-types/associated-types-unconstrained.stderr
src/test/ui/associated-types/defaults-wf.stderr
src/test/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr
src/test/ui/async-await/async-await-let-else.drop-tracking.stderr
src/test/ui/async-await/async-await-let-else.no-drop-tracking.stderr
src/test/ui/async-await/drop-track-bad-field-in-fru.rs [new file with mode: 0644]
src/test/ui/async-await/drop-track-bad-field-in-fru.stderr [new file with mode: 0644]
src/test/ui/async-await/generator-desc.stderr
src/test/ui/async-await/in-trait/async-example-desugared-boxed.rs
src/test/ui/async-await/in-trait/async-example-desugared-boxed.stderr [new file with mode: 0644]
src/test/ui/async-await/in-trait/async-example-desugared-extra.rs [new file with mode: 0644]
src/test/ui/async-await/in-trait/async-example-desugared-manual.rs [new file with mode: 0644]
src/test/ui/async-await/in-trait/async-example-desugared-manual.stderr [new file with mode: 0644]
src/test/ui/async-await/in-trait/async-example-desugared.rs
src/test/ui/async-await/in-trait/bad-signatures.rs [new file with mode: 0644]
src/test/ui/async-await/in-trait/bad-signatures.stderr [new file with mode: 0644]
src/test/ui/async-await/in-trait/fn-not-async-err.rs
src/test/ui/async-await/in-trait/fn-not-async-err.stderr
src/test/ui/async-await/in-trait/fn-not-async-err2.rs
src/test/ui/async-await/in-trait/issue-104678.rs [new file with mode: 0644]
src/test/ui/async-await/in-trait/nested-rpit.rs [new file with mode: 0644]
src/test/ui/async-await/issue-70935-complex-spans.no_drop_tracking.stderr
src/test/ui/async-await/issue-72442.stderr
src/test/ui/async-await/issues/issue-65159.stderr
src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr
src/test/ui/async-await/issues/issue-67893.stderr
src/test/ui/async-await/pin-needed-to-poll-2.stderr
src/test/ui/async-await/pin-needed-to-poll.stderr
src/test/ui/async-await/track-caller/async-block.rs [new file with mode: 0644]
src/test/ui/async-await/track-caller/async-block.stderr [new file with mode: 0644]
src/test/ui/async-await/track-caller/async-closure-gate.rs [new file with mode: 0644]
src/test/ui/async-await/track-caller/async-closure-gate.stderr [new file with mode: 0644]
src/test/ui/async-await/track-caller/panic-track-caller.rs
src/test/ui/binop/binop-consume-args.stderr
src/test/ui/binop/binop-move-semantics.stderr
src/test/ui/binop/issue-28837.stderr
src/test/ui/binop/issue-3820.stderr
src/test/ui/borrowck/access-mode-in-closures.stderr
src/test/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.stderr
src/test/ui/borrowck/borrowck-issue-2657-2.fixed [new file with mode: 0644]
src/test/ui/borrowck/borrowck-issue-2657-2.rs
src/test/ui/borrowck/borrowck-issue-2657-2.stderr
src/test/ui/borrowck/borrowck-move-error-with-note.fixed [new file with mode: 0644]
src/test/ui/borrowck/borrowck-move-error-with-note.rs
src/test/ui/borrowck/borrowck-move-error-with-note.stderr
src/test/ui/borrowck/borrowck-move-from-unsafe-ptr.stderr
src/test/ui/borrowck/borrowck-move-in-irrefut-pat.stderr
src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.stderr
src/test/ui/borrowck/borrowck-move-out-of-overloaded-deref.stderr
src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.fixed [new file with mode: 0644]
src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.rs
src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.stderr
src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.fixed [new file with mode: 0644]
src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.rs
src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.stderr
src/test/ui/borrowck/borrowck-move-out-of-vec-tail.stderr
src/test/ui/borrowck/borrowck-overloaded-index-move-from-vec.stderr
src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs
src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr
src/test/ui/borrowck/issue-104639-lifetime-order.rs [new file with mode: 0644]
src/test/ui/borrowck/issue-17718-static-move.stderr
src/test/ui/borrowck/issue-20801.stderr
src/test/ui/borrowck/issue-29166.rs [new file with mode: 0644]
src/test/ui/borrowck/issue-47215-ice-from-drop-elab.stderr
src/test/ui/borrowck/issue-51301.rs [new file with mode: 0644]
src/test/ui/borrowck/issue-51301.stderr [new file with mode: 0644]
src/test/ui/borrowck/issue-51415.fixed [new file with mode: 0644]
src/test/ui/borrowck/issue-51415.rs
src/test/ui/borrowck/issue-51415.stderr
src/test/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.stderr
src/test/ui/borrowck/issue-81899.stderr
src/test/ui/borrowck/issue-83760.stderr
src/test/ui/borrowck/issue-87456-point-to-closure.stderr
src/test/ui/borrowck/issue-88434-minimal-example.stderr
src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr
src/test/ui/borrowck/move-error-snippets.stderr
src/test/ui/borrowck/reborrow-sugg-move-then-borrow.stderr
src/test/ui/borrowck/suggest-as-ref-on-mut-closure.stderr
src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr
src/test/ui/box/into-boxed-slice-fail.stderr
src/test/ui/by-move-pattern-binding.rs
src/test/ui/by-move-pattern-binding.stderr
src/test/ui/c-variadic/issue-86053-1.stderr
src/test/ui/chalkify/bugs/async.stderr
src/test/ui/check-static-values-constraints.stderr
src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr
src/test/ui/closures/closure-expected.stderr
src/test/ui/closures/closure-move-sync.stderr
src/test/ui/closures/closure-return-type-must-be-sized.stderr
src/test/ui/closures/coerce-unsafe-to-closure.stderr
src/test/ui/closures/issue-52437.stderr
src/test/ui/closures/issue-78720.stderr
src/test/ui/closures/issue-87461.stderr
src/test/ui/closures/issue-90871.stderr
src/test/ui/closures/multiple-fn-bounds.stderr
src/test/ui/codegen/issue-55976.rs [new file with mode: 0644]
src/test/ui/codemap_tests/tab_3.stderr
src/test/ui/conditional-compilation/cfg-attr-syntax-validation.stderr
src/test/ui/confuse-field-and-method/issue-33784.stderr
src/test/ui/const-generics/defaults/complex-unord-param.min.stderr [deleted file]
src/test/ui/const-generics/generic_arg_infer/issue-91614.stderr
src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr
src/test/ui/const-generics/generic_const_exprs/issue-105257.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/issue-105257.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/issue-105608.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/issue-105608.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr
src/test/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.stderr
src/test/ui/const-generics/generic_const_exprs/issue-80742.stderr
src/test/ui/const-generics/generic_const_exprs/normed_to_param_is_evaluatable.rs [new file with mode: 0644]
src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr
src/test/ui/const-generics/invalid-constant-in-args.stderr
src/test/ui/const-generics/issue-105689.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-100313.stderr
src/test/ui/const-generics/issues/issue-83249.stderr
src/test/ui/const-generics/type-after-const-ok.min.stderr [deleted file]
src/test/ui/const-ptr/forbidden_slices.32bit.stderr
src/test/ui/const-ptr/forbidden_slices.64bit.stderr
src/test/ui/const-ptr/forbidden_slices.rs
src/test/ui/const-ptr/out_of_bounds_read.stderr
src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr
src/test/ui/consts/const-eval/const_panic_track_caller.stderr
src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr
src/test/ui/consts/const-eval/ub-ref-ptr.32bit.stderr
src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr
src/test/ui/consts/const-eval/ub-ref-ptr.rs
src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr
src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr
src/test/ui/consts/const-eval/ub-wide-ptr.rs
src/test/ui/consts/const-eval/unwind-abort.stderr
src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr
src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr
src/test/ui/consts/const-float-bits-reject-conv.stderr
src/test/ui/consts/const-fn-error.stderr
src/test/ui/consts/const-for.stderr
src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr
src/test/ui/consts/const_unsafe_unreachable_ub.stderr
src/test/ui/consts/copy-intrinsic.rs
src/test/ui/consts/extra-const-ub/detect-extra-ub.rs
src/test/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr
src/test/ui/consts/issue-miri-1910.stderr
src/test/ui/consts/miri_unleashed/abi-mismatch.stderr
src/test/ui/consts/miri_unleashed/assoc_const.stderr
src/test/ui/consts/miri_unleashed/drop.stderr
src/test/ui/consts/missing_span_in_backtrace.rs [new file with mode: 0644]
src/test/ui/consts/missing_span_in_backtrace.stderr [new file with mode: 0644]
src/test/ui/consts/offset_from_ub.stderr
src/test/ui/consts/offset_ub.stderr
src/test/ui/consts/ptr_comparisons.stderr
src/test/ui/consts/recursive.stderr
src/test/ui/consts/uninhabited-const-issue-61744.stderr
src/test/ui/debuginfo/issue-105386-debuginfo-ub.rs [new file with mode: 0644]
src/test/ui/derives/derives-span-Eq-enum-struct-variant.stderr
src/test/ui/derives/derives-span-Eq-enum.stderr
src/test/ui/derives/derives-span-Eq-struct.stderr
src/test/ui/derives/derives-span-Eq-tuple-struct.stderr
src/test/ui/derives/deriving-meta-unknown-trait.stderr
src/test/ui/deriving/issue-103157.stderr
src/test/ui/destructuring-assignment/note-unsupported.stderr
src/test/ui/diagnostic-width/long-E0308.rs [new file with mode: 0644]
src/test/ui/diagnostic-width/long-E0308.stderr [new file with mode: 0644]
src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.fixed [new file with mode: 0644]
src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.rs
src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.stderr
src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.fixed [new file with mode: 0644]
src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.rs
src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.stderr
src/test/ui/disambiguate-identical-names.stderr
src/test/ui/drop/issue-21486.rs [new file with mode: 0644]
src/test/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr
src/test/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr
src/test/ui/dropck/dropck_no_diverge_on_nonregular_3.stderr
src/test/ui/dst/dst-rvalue.stderr
src/test/ui/dyn-star/dyn-to-rigid.rs [new file with mode: 0644]
src/test/ui/dyn-star/dyn-to-rigid.stderr [new file with mode: 0644]
src/test/ui/dyn-star/no-implicit-dyn-star.stderr
src/test/ui/empty/empty-struct-braces-expr.stderr
src/test/ui/error-codes/E0004-2.stderr
src/test/ui/error-codes/E0005.stderr
src/test/ui/error-codes/E0059.stderr
src/test/ui/error-codes/E0275.stderr
src/test/ui/error-codes/E0282.stderr
src/test/ui/error-codes/E0297.stderr
src/test/ui/error-codes/E0401.stderr
src/test/ui/error-codes/E0507.stderr
src/test/ui/error-codes/E0508-fail.stderr
src/test/ui/error-codes/E0508.stderr
src/test/ui/error-codes/E0509.stderr
src/test/ui/error-codes/E0790.stderr
src/test/ui/error-festival.stderr
src/test/ui/expr/malformed_closure/ruby_style_closure.stderr
src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr
src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr
src/test/ui/feature-gates/feature-gate-linkage.rs
src/test/ui/feature-gates/feature-gate-linkage.stderr
src/test/ui/feature-gates/feature-gate-unsized_fn_params.rs
src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr
src/test/ui/feature-gates/feature-gate-unsized_locals.stderr
src/test/ui/fmt/ifmt-bad-arg.stderr
src/test/ui/fmt/ifmt-unimpl.stderr
src/test/ui/functions-closures/fn-help-with-err.stderr
src/test/ui/generator/issue-102645.stderr
src/test/ui/generator/sized-yield.stderr
src/test/ui/generic-associated-types/cross-crate-bounds.stderr
src/test/ui/generic-associated-types/issue-101020.stderr
src/test/ui/generics/wrong-number-of-args.stderr
src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr
src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr
src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr
src/test/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.rs [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.stderr [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/issue-30786.stderr
src/test/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr
src/test/ui/hygiene/issue-15221.rs [new file with mode: 0644]
src/test/ui/illegal-sized-bound/mutability-mismatch.rs [new file with mode: 0644]
src/test/ui/illegal-sized-bound/mutability-mismatch.stderr [new file with mode: 0644]
src/test/ui/illegal-sized-bound/regular.rs [new file with mode: 0644]
src/test/ui/illegal-sized-bound/regular.stderr [new file with mode: 0644]
src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr
src/test/ui/impl-trait/impl-generic-mismatch.stderr
src/test/ui/impl-trait/in-trait/wf-bounds.stderr
src/test/ui/impl-trait/issues/issue-62742.stderr
src/test/ui/impl-trait/issues/issue-86719.stderr
src/test/ui/impl-trait/issues/issue-92305.stderr
src/test/ui/impl-trait/no-method-suggested-traits.stderr
src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr
src/test/ui/imports/issue-26930.rs [new file with mode: 0644]
src/test/ui/inference/deref-suggestion.stderr
src/test/ui/inference/erase-type-params-in-label.stderr
src/test/ui/inference/issue-71732.stderr
src/test/ui/inference/issue-72690.stderr
src/test/ui/infinite/infinite-recursion-const-fn.stderr
src/test/ui/inline-const/expr-unsafe-err.mir.stderr [new file with mode: 0644]
src/test/ui/inline-const/expr-unsafe-err.rs [new file with mode: 0644]
src/test/ui/inline-const/expr-unsafe-err.thir.stderr [new file with mode: 0644]
src/test/ui/inline-const/expr-unsafe.mir.stderr [new file with mode: 0644]
src/test/ui/inline-const/expr-unsafe.rs [new file with mode: 0644]
src/test/ui/inline-const/expr-unsafe.thir.stderr [new file with mode: 0644]
src/test/ui/inline-const/pat-unsafe-err.rs [new file with mode: 0644]
src/test/ui/inline-const/pat-unsafe.rs [new file with mode: 0644]
src/test/ui/interior-mutability/interior-mutability.stderr
src/test/ui/intrinsics/const-eval-select-bad.stderr
src/test/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADTARGET.stderr
src/test/ui/invalid-compile-flags/branch-protection-missing-pac-ret.rs
src/test/ui/invalid/invalid-no-sanitize.stderr
src/test/ui/issues/auxiliary/issue-11225-1.rs [deleted file]
src/test/ui/issues/auxiliary/issue-11225-2.rs [deleted file]
src/test/ui/issues/auxiliary/issue-11225-3.rs [deleted file]
src/test/ui/issues/issue-105330.stderr
src/test/ui/issues/issue-11225-1.rs [deleted file]
src/test/ui/issues/issue-11225-2.rs [deleted file]
src/test/ui/issues/issue-11225-3.rs [deleted file]
src/test/ui/issues/issue-12567.stderr
src/test/ui/issues/issue-14091-2.stderr
src/test/ui/issues/issue-14092.stderr
src/test/ui/issues/issue-15221.rs [deleted file]
src/test/ui/issues/issue-16966.stderr
src/test/ui/issues/issue-17546.stderr
src/test/ui/issues/issue-17651.stderr
src/test/ui/issues/issue-18107.stderr
src/test/ui/issues/issue-18159.stderr
src/test/ui/issues/issue-18423.stderr
src/test/ui/issues/issue-20162.stderr
src/test/ui/issues/issue-20413.stderr
src/test/ui/issues/issue-20433.stderr
src/test/ui/issues/issue-21058.rs [deleted file]
src/test/ui/issues/issue-21486.rs [deleted file]
src/test/ui/issues/issue-2151.stderr
src/test/ui/issues/issue-21974.stderr
src/test/ui/issues/issue-23024.stderr
src/test/ui/issues/issue-23122-2.stderr
src/test/ui/issues/issue-23966.stderr
src/test/ui/issues/issue-24036.stderr
src/test/ui/issues/issue-24424.stderr
src/test/ui/issues/issue-26930.rs [deleted file]
src/test/ui/issues/issue-27033.stderr
src/test/ui/issues/issue-29166.rs [deleted file]
src/test/ui/issues/issue-29227.rs [deleted file]
src/test/ui/issues/issue-30123.stderr
src/test/ui/issues/issue-3044.stderr
src/test/ui/issues/issue-31173.rs
src/test/ui/issues/issue-31173.stderr
src/test/ui/issues/issue-32655.stderr
src/test/ui/issues/issue-33575.rs [deleted file]
src/test/ui/issues/issue-33575.stderr [deleted file]
src/test/ui/issues/issue-33941.rs
src/test/ui/issues/issue-33941.stderr
src/test/ui/issues/issue-34334.stderr
src/test/ui/issues/issue-34721.stderr
src/test/ui/issues/issue-37515.rs [deleted file]
src/test/ui/issues/issue-37515.stderr [deleted file]
src/test/ui/issues/issue-38404.rs [deleted file]
src/test/ui/issues/issue-38404.stderr [deleted file]
src/test/ui/issues/issue-38857.stderr
src/test/ui/issues/issue-39616.rs [deleted file]
src/test/ui/issues/issue-39616.stderr [deleted file]
src/test/ui/issues/issue-40402-ref-hints/issue-40402-1.stderr
src/test/ui/issues/issue-40402-ref-hints/issue-40402-2.stderr
src/test/ui/issues/issue-41880.stderr
src/test/ui/issues/issue-42312.stderr
src/test/ui/issues/issue-42954.fixed [deleted file]
src/test/ui/issues/issue-42954.rs [deleted file]
src/test/ui/issues/issue-42954.stderr [deleted file]
src/test/ui/issues/issue-46845.rs [deleted file]
src/test/ui/issues/issue-47486.stderr
src/test/ui/issues/issue-48364.stderr
src/test/ui/issues/issue-49257.rs [deleted file]
src/test/ui/issues/issue-49257.stderr [deleted file]
src/test/ui/issues/issue-50480.rs [deleted file]
src/test/ui/issues/issue-50480.stderr [deleted file]
src/test/ui/issues/issue-51154.stderr
src/test/ui/issues/issue-51301.rs [deleted file]
src/test/ui/issues/issue-51301.stderr [deleted file]
src/test/ui/issues/issue-51848.rs [deleted file]
src/test/ui/issues/issue-51848.stderr [deleted file]
src/test/ui/issues/issue-5353.rs [deleted file]
src/test/ui/issues/issue-5883.stderr
src/test/ui/issues/issue-61108.stderr
src/test/ui/issues/issue-64559.stderr
src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr
src/test/ui/issues/issue-7607-1.stderr
src/test/ui/issues/issue-77002.rs [deleted file]
src/test/ui/issues/issue-83924.stderr
src/test/ui/iterators/collect-into-array.rs
src/test/ui/iterators/collect-into-array.stderr
src/test/ui/iterators/collect-into-slice.rs
src/test/ui/iterators/collect-into-slice.stderr
src/test/ui/iterators/invalid-iterator-chain.rs [new file with mode: 0644]
src/test/ui/iterators/invalid-iterator-chain.stderr [new file with mode: 0644]
src/test/ui/iterators/vec-on-unimplemented.stderr
src/test/ui/lazy-type-alias-impl-trait/branches.stderr
src/test/ui/lazy-type-alias-impl-trait/branches3.stderr
src/test/ui/lazy-type-alias-impl-trait/recursion4.stderr
src/test/ui/let-else/let-else-deref-coercion.stderr
src/test/ui/lifetimes/conflicting-bounds.rs [new file with mode: 0644]
src/test/ui/lifetimes/conflicting-bounds.stderr [new file with mode: 0644]
src/test/ui/lifetimes/issue-34979.stderr
src/test/ui/limits/issue-55878.stderr
src/test/ui/linkage-attr/auxiliary/def_external.rs [new file with mode: 0644]
src/test/ui/linkage-attr/auxiliary/def_illtyped_external.rs [deleted file]
src/test/ui/linkage-attr/linkage-import.rs [new file with mode: 0644]
src/test/ui/linkage-attr/linkage-requires-raw-ptr.rs [deleted file]
src/test/ui/linkage-attr/linkage-requires-raw-ptr.stderr [deleted file]
src/test/ui/linkage-attr/linkage2.rs
src/test/ui/linkage-attr/linkage2.stderr
src/test/ui/lint/invalid_value.stderr
src/test/ui/lint/lint-const-item-mutation.stderr
src/test/ui/lint/lint-missing-copy-implementations-allow.rs [new file with mode: 0644]
src/test/ui/lint/lint-uppercase-variables.rs
src/test/ui/lint/lint-uppercase-variables.stderr
src/test/ui/lint/unused/issue-54538-unused-parens-lint.fixed
src/test/ui/lint/unused/issue-54538-unused-parens-lint.rs
src/test/ui/lint/unused/issue-54538-unused-parens-lint.stderr
src/test/ui/loops/issue-82916.stderr
src/test/ui/lto/auxiliary/thinlto-dylib.rs [new file with mode: 0644]
src/test/ui/lto/issue-105637.rs [new file with mode: 0644]
src/test/ui/lto/issue-105637.run.stderr [new file with mode: 0644]
src/test/ui/macros/format-args-temporaries-in-write.stderr
src/test/ui/macros/issue-42954.fixed [new file with mode: 0644]
src/test/ui/macros/issue-42954.rs [new file with mode: 0644]
src/test/ui/macros/issue-42954.stderr [new file with mode: 0644]
src/test/ui/macros/issue-51848.rs [new file with mode: 0644]
src/test/ui/macros/issue-51848.stderr [new file with mode: 0644]
src/test/ui/macros/macro-in-expression-context.stderr
src/test/ui/macros/macro-name-typo.stderr
src/test/ui/macros/macro-path-prelude-fail-3.stderr
src/test/ui/macros/unknown-builtin.stderr
src/test/ui/malformed/malformed-derive-entry.stderr
src/test/ui/match/match-unresolved-one-arm.stderr
src/test/ui/methods/issues/issue-105732.rs [new file with mode: 0644]
src/test/ui/methods/issues/issue-105732.stderr [new file with mode: 0644]
src/test/ui/methods/issues/issue-90315.stderr
src/test/ui/methods/method-call-err-msg.stderr
src/test/ui/methods/method-call-lifetime-args-unresolved.stderr
src/test/ui/methods/method-not-found-generic-arg-elision.stderr
src/test/ui/mir/field-projection-invariant.rs [new file with mode: 0644]
src/test/ui/mir/field-ty-ascription-enums.rs [new file with mode: 0644]
src/test/ui/mir/field-ty-ascription.rs [new file with mode: 0644]
src/test/ui/mir/issue-29227.rs [new file with mode: 0644]
src/test/ui/mir/issue-46845.rs [new file with mode: 0644]
src/test/ui/mir/issue-77002.rs [new file with mode: 0644]
src/test/ui/mir/issue-95978-validator-lifetime-comparison.rs [deleted file]
src/test/ui/mir/validate/issue-95978-validator-lifetime-comparison.rs [new file with mode: 0644]
src/test/ui/mir/validate/needs-reveal-all.rs [new file with mode: 0644]
src/test/ui/mismatched_types/assignment-operator-unimplemented.stderr
src/test/ui/mismatched_types/closure-arg-count.stderr
src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr
src/test/ui/mismatched_types/issue-35030.stderr
src/test/ui/mismatched_types/issue-36053-2.stderr
src/test/ui/mismatched_types/issue-47706-trait.stderr
src/test/ui/mismatched_types/issue-47706.stderr
src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr
src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr
src/test/ui/mismatched_types/similar_paths.stderr
src/test/ui/mismatched_types/wrap-suggestion-privacy.stderr
src/test/ui/missing/missing-alloc_error_handler.rs [deleted file]
src/test/ui/missing/missing-alloc_error_handler.stderr [deleted file]
src/test/ui/moves/issue-99470-move-out-of-some.stderr
src/test/ui/moves/move-fn-self-receiver.stderr
src/test/ui/moves/move-out-of-array-ref.stderr
src/test/ui/moves/move-out-of-slice-1.stderr
src/test/ui/moves/move-out-of-slice-2.rs
src/test/ui/moves/move-out-of-slice-2.stderr
src/test/ui/moves/moves-based-on-type-access-to-field.stderr
src/test/ui/moves/moves-based-on-type-block-bad.stderr
src/test/ui/moves/moves-based-on-type-exprs.stderr
src/test/ui/never_type/fallback-closure-wrap.fallback.stderr
src/test/ui/never_type/feature-gate-never_type_fallback.stderr
src/test/ui/never_type/issue-52443.stderr
src/test/ui/never_type/issue-96335.stderr
src/test/ui/nll/cannot-move-block-spans.stderr
src/test/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.stderr
src/test/ui/nll/move-errors.stderr
src/test/ui/no-capture-arc.stderr
src/test/ui/no-reuse-move-arc.stderr
src/test/ui/no-send-res-ports.stderr
src/test/ui/not-clone-closure.stderr
src/test/ui/numeric/numeric-cast-binop.stderr
src/test/ui/numeric/numeric-cast-no-fix.stderr
src/test/ui/numeric/uppercase-base-prefix-invalid-no-fix.rs [new file with mode: 0644]
src/test/ui/numeric/uppercase-base-prefix-invalid-no-fix.stderr [new file with mode: 0644]
src/test/ui/on-unimplemented/sum.rs [new file with mode: 0644]
src/test/ui/on-unimplemented/sum.stderr [new file with mode: 0644]
src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr
src/test/ui/overloaded/overloaded-calls-nontuple.stderr
src/test/ui/parser/bare-struct-body.stderr
src/test/ui/parser/chained-comparison-suggestion.stderr
src/test/ui/parser/increment-autofix-2.fixed [new file with mode: 0644]
src/test/ui/parser/increment-autofix-2.rs [new file with mode: 0644]
src/test/ui/parser/increment-autofix-2.stderr [new file with mode: 0644]
src/test/ui/parser/increment-notfixed.rs [deleted file]
src/test/ui/parser/increment-notfixed.stderr [deleted file]
src/test/ui/parser/issue-104867-inc-dec-2.rs [new file with mode: 0644]
src/test/ui/parser/issue-104867-inc-dec-2.stderr [new file with mode: 0644]
src/test/ui/parser/issue-104867-inc-dec.rs [new file with mode: 0644]
src/test/ui/parser/issue-104867-inc-dec.stderr [new file with mode: 0644]
src/test/ui/parser/issue-105366.fixed [new file with mode: 0644]
src/test/ui/parser/issue-105366.rs [new file with mode: 0644]
src/test/ui/parser/issue-105366.stderr [new file with mode: 0644]
src/test/ui/parser/issue-39616.rs [new file with mode: 0644]
src/test/ui/parser/issue-39616.stderr [new file with mode: 0644]
src/test/ui/parser/issue-49257.rs [new file with mode: 0644]
src/test/ui/parser/issue-49257.stderr [new file with mode: 0644]
src/test/ui/parser/issues/issue-62894.stderr
src/test/ui/parser/kw-in-trait-bounds.stderr
src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.fixed [new file with mode: 0644]
src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.rs [new file with mode: 0644]
src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.stderr [new file with mode: 0644]
src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.rs
src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.stderr
src/test/ui/pattern/pat-tuple-bad-type.stderr
src/test/ui/pattern/rest-pat-semantic-disallowed.stderr
src/test/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.stderr
src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr
src/test/ui/pattern/usefulness/issue-35609.stderr
src/test/ui/pattern/usefulness/issue-3601.stderr
src/test/ui/pattern/usefulness/match-arm-statics-2.stderr
src/test/ui/pattern/usefulness/match-privately-empty.stderr
src/test/ui/pattern/usefulness/non-exhaustive-match.stderr
src/test/ui/pptypedef.stderr
src/test/ui/print_type_sizes/async.rs [new file with mode: 0644]
src/test/ui/print_type_sizes/async.stdout [new file with mode: 0644]
src/test/ui/print_type_sizes/generator.rs [new file with mode: 0644]
src/test/ui/print_type_sizes/generator.stdout [new file with mode: 0644]
src/test/ui/print_type_sizes/generator_discr_placement.rs [new file with mode: 0644]
src/test/ui/print_type_sizes/generator_discr_placement.stdout [new file with mode: 0644]
src/test/ui/print_type_sizes/generics.rs
src/test/ui/print_type_sizes/multiple_types.rs
src/test/ui/print_type_sizes/niche-filling.rs
src/test/ui/print_type_sizes/no_duplicates.rs
src/test/ui/print_type_sizes/packed.rs
src/test/ui/print_type_sizes/padding.rs
src/test/ui/print_type_sizes/repr-align.rs
src/test/ui/print_type_sizes/repr_int_c.rs
src/test/ui/print_type_sizes/uninhabited.rs
src/test/ui/print_type_sizes/variants.rs
src/test/ui/print_type_sizes/zero-sized-fields.rs
src/test/ui/privacy/associated-item-privacy-trait.rs
src/test/ui/privacy/associated-item-privacy-trait.stderr
src/test/ui/privacy/private-inferred-type-3.rs
src/test/ui/privacy/private-inferred-type-3.stderr
src/test/ui/proc-macro/attr-invalid-exprs.stderr
src/test/ui/proc-macro/attribute.rs
src/test/ui/proc-macro/attribute.stderr
src/test/ui/proc-macro/expand-expr.stderr
src/test/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr
src/test/ui/proc-macro/parent-source-spans.stderr
src/test/ui/proc-macro/resolve-error.stderr
src/test/ui/proc-macro/signature.stderr
src/test/ui/proc-macro/span-api-tests.rs
src/test/ui/range/issue-54505-no-literals.stderr
src/test/ui/range/issue-54505.stderr
src/test/ui/range/issue-73553-misinterp-range-literal.stderr
src/test/ui/range/range-1.stderr
src/test/ui/reachable/auxiliary/issue-11225-1.rs [new file with mode: 0644]
src/test/ui/reachable/auxiliary/issue-11225-2.rs [new file with mode: 0644]
src/test/ui/reachable/auxiliary/issue-11225-3.rs [new file with mode: 0644]
src/test/ui/reachable/issue-11225-1.rs [new file with mode: 0644]
src/test/ui/reachable/issue-11225-2.rs [new file with mode: 0644]
src/test/ui/reachable/issue-11225-3.rs [new file with mode: 0644]
src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr
src/test/ui/recursion/issue-83150.stderr
src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr
src/test/ui/regions/issue-102374.rs
src/test/ui/regions/issue-102374.stderr
src/test/ui/resolve/issue-104700-inner_scope.rs [new file with mode: 0644]
src/test/ui/resolve/issue-104700-inner_scope.stderr [new file with mode: 0644]
src/test/ui/resolve/issue-5035-2.stderr
src/test/ui/resolve/issue-85348.stderr
src/test/ui/resolve/levenshtein.stderr
src/test/ui/resolve/resolve-primitive-fallback.stderr
src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
src/test/ui/rfc-2005-default-binding-mode/for.stderr
src/test/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr
src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr
src/test/ui/rfc-2632-const-trait-impl/const-impl-trait.rs [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr
src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr
src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr
src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr
src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr
src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs
src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr
src/test/ui/span/issue-39018.stderr
src/test/ui/span/issue-71363.rs
src/test/ui/span/issue-71363.stderr
src/test/ui/span/method-and-field-eager-resolution.stderr
src/test/ui/span/missing-unit-argument.stderr
src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
src/test/ui/stability-attribute/stability-in-private-module.stderr
src/test/ui/std-uncopyable-atomics.stderr
src/test/ui/stdlib-unit-tests/issue-21058.rs [new file with mode: 0644]
src/test/ui/str/str-idx.stderr
src/test/ui/str/str-mut-idx.stderr
src/test/ui/structs/struct-record-suggestion.stderr
src/test/ui/structs/unresolved-struct-with-fru.rs [new file with mode: 0644]
src/test/ui/structs/unresolved-struct-with-fru.stderr [new file with mode: 0644]
src/test/ui/suggestions/args-instead-of-tuple-errors.stderr
src/test/ui/suggestions/args-instead-of-tuple.stderr
src/test/ui/suggestions/as-ref-2.stderr
src/test/ui/suggestions/attribute-typos.stderr
src/test/ui/suggestions/borrow-for-loop-head.stderr
src/test/ui/suggestions/bound-suggestions.stderr
src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.fixed [new file with mode: 0644]
src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.rs [new file with mode: 0644]
src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr [new file with mode: 0644]
src/test/ui/suggestions/derive-clone-for-eq.stderr
src/test/ui/suggestions/derive-trait-for-method-call.stderr
src/test/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr
src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs
src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.stderr
src/test/ui/suggestions/dont-suggest-ref/move-into-closure.rs
src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr
src/test/ui/suggestions/dont-suggest-ref/simple.rs
src/test/ui/suggestions/dont-suggest-ref/simple.stderr
src/test/ui/suggestions/dont-suggest-try_into-in-macros.stderr
src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
src/test/ui/suggestions/for-i-in-vec.stderr
src/test/ui/suggestions/imm-ref-trait-object.stderr
src/test/ui/suggestions/import-trait-for-method-call.stderr
src/test/ui/suggestions/issue-104287.stderr
src/test/ui/suggestions/issue-104327.rs [new file with mode: 0644]
src/test/ui/suggestions/issue-104327.stderr [new file with mode: 0644]
src/test/ui/suggestions/issue-104328.rs [new file with mode: 0644]
src/test/ui/suggestions/issue-104328.stderr [new file with mode: 0644]
src/test/ui/suggestions/issue-105226.rs [new file with mode: 0644]
src/test/ui/suggestions/issue-105226.stderr [new file with mode: 0644]
src/test/ui/suggestions/issue-62843.stderr
src/test/ui/suggestions/issue-71394-no-from-impl.stderr
src/test/ui/suggestions/issue-89064.stderr
src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr
src/test/ui/suggestions/option-content-move-from-tuple-match.stderr
src/test/ui/suggestions/option-content-move.stderr
src/test/ui/suggestions/option-to-bool.stderr
src/test/ui/suggestions/restrict-type-not-param.stderr
src/test/ui/suggestions/sugg-else-for-closure.stderr
src/test/ui/suggestions/suggest-change-mut.stderr
src/test/ui/suggestions/suggest-tryinto-edition-change.stderr
src/test/ui/suggestions/type-ascription-instead-of-path-in-type.stderr
src/test/ui/suggestions/unnecessary_dot_for_floating_point_literal.stderr
src/test/ui/traits/alias/generic-default-in-dyn.stderr
src/test/ui/traits/alias/object-fail.stderr
src/test/ui/traits/assoc-type-in-superbad.rs
src/test/ui/traits/assoc-type-in-superbad.stderr
src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr
src/test/ui/traits/bad-sized.stderr
src/test/ui/traits/bound/not-on-bare-trait.stderr
src/test/ui/traits/default-method/rustc_must_implement_one_of_duplicates.rs
src/test/ui/traits/default-method/rustc_must_implement_one_of_duplicates.stderr
src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs
src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr
src/test/ui/traits/issue-38404.rs [new file with mode: 0644]
src/test/ui/traits/issue-38404.stderr [new file with mode: 0644]
src/test/ui/traits/issue-50480.rs [new file with mode: 0644]
src/test/ui/traits/issue-50480.stderr [new file with mode: 0644]
src/test/ui/traits/issue-77982.stderr
src/test/ui/traits/issue-85735.stderr
src/test/ui/traits/issue-91949-hangs-on-recursion.stderr
src/test/ui/traits/issue-97576.stderr
src/test/ui/traits/mutual-recursion-issue-75860.stderr
src/test/ui/traits/object/issue-44454-1.rs [new file with mode: 0644]
src/test/ui/traits/object/issue-44454-1.stderr [new file with mode: 0644]
src/test/ui/traits/object/issue-44454-2.rs [new file with mode: 0644]
src/test/ui/traits/object/issue-44454-2.stderr [new file with mode: 0644]
src/test/ui/traits/object/issue-44454-3.rs [new file with mode: 0644]
src/test/ui/traits/object/issue-44454-3.stderr [new file with mode: 0644]
src/test/ui/traits/static-method-generic-inference.stderr
src/test/ui/traits/suggest-deferences/issue-39029.stderr
src/test/ui/traits/suggest-deferences/root-obligation.stderr
src/test/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.fixed [new file with mode: 0644]
src/test/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.rs [new file with mode: 0644]
src/test/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.stderr [new file with mode: 0644]
src/test/ui/traits/suggest-where-clause.stderr
src/test/ui/transmutability/issue-101739-2.stderr
src/test/ui/tuple/wrong_argument_ice-3.stderr
src/test/ui/tuple/wrong_argument_ice.stderr
src/test/ui/type-alias-impl-trait/closures_in_branches.stderr
src/test/ui/type-alias-impl-trait/issue-57961.rs
src/test/ui/type-alias-impl-trait/issue-57961.stderr
src/test/ui/type-alias/issue-37515.rs [new file with mode: 0644]
src/test/ui/type-alias/issue-37515.stderr [new file with mode: 0644]
src/test/ui/type/ascription/issue-34255-1.stderr
src/test/ui/type/type-annotation-needed.stderr
src/test/ui/type/type-ascription-instead-of-initializer.stderr
src/test/ui/type/type-ascription-precedence.stderr
src/test/ui/type/type-check/assignment-in-if.stderr
src/test/ui/type/type-check/issue-40294.stderr
src/test/ui/type/type-check/unknown_type_for_closure.stderr
src/test/ui/type/type-params-in-different-spaces-1.stderr
src/test/ui/type/type-path-err-node-types.stderr
src/test/ui/type_length_limit.stderr
src/test/ui/typeck/explain_clone_autoref.stderr
src/test/ui/typeck/issue-104582.rs [new file with mode: 0644]
src/test/ui/typeck/issue-104582.stderr [new file with mode: 0644]
src/test/ui/typeck/issue-13853.stderr
src/test/ui/typeck/issue-33575.rs [new file with mode: 0644]
src/test/ui/typeck/issue-33575.stderr [new file with mode: 0644]
src/test/ui/typeck/issue-46112.stderr
src/test/ui/typeck/issue-75883.stderr
src/test/ui/typeck/issue-83693.stderr
src/test/ui/typeck/issue-84768.stderr
src/test/ui/typeck/issue-92481.rs [new file with mode: 0644]
src/test/ui/typeck/issue-92481.stderr [new file with mode: 0644]
src/test/ui/typeck/struct-enum-wrong-args.stderr
src/test/ui/typeck/typeck-builtin-bound-type-parameters.stderr
src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr
src/test/ui/unboxed-closures/non-tupled-arg-mismatch.stderr
src/test/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr
src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
src/test/ui/union/union-borrow-move-parent-sibling.mirunsafeck.stderr
src/test/ui/union/union-borrow-move-parent-sibling.thirunsafeck.stderr
src/test/ui/union/union-derive-clone.mirunsafeck.stderr
src/test/ui/union/union-derive-clone.thirunsafeck.stderr
src/test/ui/union/union-derive-eq.mirunsafeck.stderr
src/test/ui/union/union-derive-eq.thirunsafeck.stderr
src/test/ui/unique-object-noncopyable.stderr
src/test/ui/unique-pinned-nocopy.stderr
src/test/ui/unop-move-semantics.stderr
src/test/ui/unsized-locals/borrow-after-move.stderr
src/test/ui/unsized-locals/double-move.stderr
src/test/ui/unsized/issue-71659.stderr
src/test/ui/use/use-after-move-self-based-on-type.stderr
src/test/ui/use/use-after-move-self.stderr
src/test/ui/walk-struct-literal-with.stderr
src/test/ui/wf/hir-wf-canonicalized.rs [new file with mode: 0644]
src/test/ui/wf/hir-wf-canonicalized.stderr [new file with mode: 0644]
src/test/ui/wf/hir-wf-check-erase-regions.stderr
src/test/ui/wf/wf-impl-self-type.stderr
src/test/ui/wrong-mul-method-signature.stderr
src/tools/cargo
src/tools/clippy/.github/workflows/clippy_bors.yml
src/tools/clippy/CHANGELOG.md
src/tools/clippy/Cargo.toml
src/tools/clippy/book/src/README.md
src/tools/clippy/build.rs
src/tools/clippy/clippy_lints/Cargo.toml
src/tools/clippy/clippy_lints/src/almost_complete_letter_range.rs [deleted file]
src/tools/clippy/clippy_lints/src/almost_complete_range.rs [new file with mode: 0644]
src/tools/clippy/clippy_lints/src/box_default.rs
src/tools/clippy/clippy_lints/src/casts/mod.rs
src/tools/clippy/clippy_lints/src/declared_lints.rs
src/tools/clippy/clippy_lints/src/dereference.rs
src/tools/clippy/clippy_lints/src/derive.rs
src/tools/clippy/clippy_lints/src/disallowed_macros.rs
src/tools/clippy/clippy_lints/src/format_args.rs
src/tools/clippy/clippy_lints/src/from_over_into.rs
src/tools/clippy/clippy_lints/src/future_not_send.rs
src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs
src/tools/clippy/clippy_lints/src/indexing_slicing.rs
src/tools/clippy/clippy_lints/src/invalid_utf8_in_unchecked.rs
src/tools/clippy/clippy_lints/src/large_include_file.rs
src/tools/clippy/clippy_lints/src/len_zero.rs
src/tools/clippy/clippy_lints/src/lib.rs
src/tools/clippy/clippy_lints/src/loops/utils.rs
src/tools/clippy/clippy_lints/src/manual_assert.rs
src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs
src/tools/clippy/clippy_lints/src/manual_let_else.rs
src/tools/clippy/clippy_lints/src/manual_retain.rs
src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs
src/tools/clippy/clippy_lints/src/methods/mod.rs
src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs
src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
src/tools/clippy/clippy_lints/src/misc.rs
src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
src/tools/clippy/clippy_lints/src/operators/identity_op.rs
src/tools/clippy/clippy_lints/src/operators/mod.rs
src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs
src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs
src/tools/clippy/clippy_lints/src/renamed_lints.rs
src/tools/clippy/clippy_lints/src/semicolon_block.rs [new file with mode: 0644]
src/tools/clippy/clippy_lints/src/strings.rs
src/tools/clippy/clippy_lints/src/utils/author.rs
src/tools/clippy/clippy_lints/src/utils/conf.rs
src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs
src/tools/clippy/clippy_utils/Cargo.toml
src/tools/clippy/clippy_utils/src/check_proc_macro.rs
src/tools/clippy/clippy_utils/src/consts.rs
src/tools/clippy/clippy_utils/src/lib.rs
src/tools/clippy/clippy_utils/src/macros.rs
src/tools/clippy/clippy_utils/src/msrvs.rs
src/tools/clippy/clippy_utils/src/paths.rs
src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
src/tools/clippy/clippy_utils/src/ty.rs
src/tools/clippy/declare_clippy_lint/Cargo.toml
src/tools/clippy/rust-toolchain
src/tools/clippy/rustc_tools_util/CHANGELOG.md [new file with mode: 0644]
src/tools/clippy/rustc_tools_util/Cargo.toml
src/tools/clippy/rustc_tools_util/README.md
src/tools/clippy/rustc_tools_util/src/lib.rs
src/tools/clippy/src/driver.rs
src/tools/clippy/src/main.rs
src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr
src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs
src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/clippy.toml
src/tools/clippy/tests/ui-toml/suppress_lint_in_const/clippy.toml [new file with mode: 0644]
src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.rs [new file with mode: 0644]
src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
src/tools/clippy/tests/ui/almost_complete_letter_range.fixed [deleted file]
src/tools/clippy/tests/ui/almost_complete_letter_range.rs [deleted file]
src/tools/clippy/tests/ui/almost_complete_letter_range.stderr [deleted file]
src/tools/clippy/tests/ui/almost_complete_range.fixed [new file with mode: 0644]
src/tools/clippy/tests/ui/almost_complete_range.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/almost_complete_range.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
src/tools/clippy/tests/ui/auxiliary/macro_rules.rs
src/tools/clippy/tests/ui/cast_lossless_integer.fixed
src/tools/clippy/tests/ui/cast_lossless_integer.rs
src/tools/clippy/tests/ui/collapsible_str_replace.fixed
src/tools/clippy/tests/ui/collapsible_str_replace.rs
src/tools/clippy/tests/ui/collapsible_str_replace.stderr
src/tools/clippy/tests/ui/explicit_counter_loop.rs
src/tools/clippy/tests/ui/from_over_into.fixed
src/tools/clippy/tests/ui/from_over_into.rs
src/tools/clippy/tests/ui/from_over_into.stderr
src/tools/clippy/tests/ui/identity_op.fixed
src/tools/clippy/tests/ui/identity_op.rs
src/tools/clippy/tests/ui/identity_op.stderr
src/tools/clippy/tests/ui/implicit_clone.fixed
src/tools/clippy/tests/ui/implicit_clone.rs
src/tools/clippy/tests/ui/indexing_slicing_index.rs
src/tools/clippy/tests/ui/indexing_slicing_index.stderr
src/tools/clippy/tests/ui/len_zero.fixed
src/tools/clippy/tests/ui/len_zero.rs
src/tools/clippy/tests/ui/len_zero.stderr
src/tools/clippy/tests/ui/manual_assert.edition2018.fixed
src/tools/clippy/tests/ui/manual_assert.edition2021.fixed
src/tools/clippy/tests/ui/manual_assert.edition2021.stderr
src/tools/clippy/tests/ui/manual_assert.rs
src/tools/clippy/tests/ui/manual_is_ascii_check.fixed
src/tools/clippy/tests/ui/manual_is_ascii_check.rs
src/tools/clippy/tests/ui/manual_is_ascii_check.stderr
src/tools/clippy/tests/ui/manual_let_else_match.rs
src/tools/clippy/tests/ui/manual_let_else_match.stderr
src/tools/clippy/tests/ui/needless_parens_on_range_literals.fixed
src/tools/clippy/tests/ui/needless_parens_on_range_literals.rs
src/tools/clippy/tests/ui/new_ret_no_self.rs
src/tools/clippy/tests/ui/new_ret_no_self.stderr
src/tools/clippy/tests/ui/redundant_static_lifetimes.fixed
src/tools/clippy/tests/ui/redundant_static_lifetimes.rs
src/tools/clippy/tests/ui/redundant_static_lifetimes.stderr
src/tools/clippy/tests/ui/rename.fixed
src/tools/clippy/tests/ui/rename.rs
src/tools/clippy/tests/ui/rename.stderr
src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.fixed
src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.rs
src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.stderr
src/tools/clippy/tests/ui/semicolon_inside_block.fixed [new file with mode: 0644]
src/tools/clippy/tests/ui/semicolon_inside_block.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/semicolon_inside_block.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/semicolon_outside_block.fixed [new file with mode: 0644]
src/tools/clippy/tests/ui/semicolon_outside_block.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/semicolon_outside_block.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/string_lit_as_bytes.fixed
src/tools/clippy/tests/ui/string_lit_as_bytes.rs
src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2018.fixed
src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2021.fixed
src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2021.stderr
src/tools/clippy/tests/ui/uninlined_format_args_panic.rs
src/tools/clippy/tests/ui/unnecessary_to_owned.fixed
src/tools/clippy/tests/ui/unnecessary_to_owned.rs
src/tools/clippy/tests/ui/zero_ptr_no_std.fixed [new file with mode: 0644]
src/tools/clippy/tests/ui/zero_ptr_no_std.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/zero_ptr_no_std.stderr [new file with mode: 0644]
src/tools/clippy/tests/versioncheck.rs
src/tools/clippy/triagebot.toml
src/tools/compiletest/src/header.rs
src/tools/compiletest/src/runtest.rs
src/tools/compiletest/src/util.rs
src/tools/miri/src/borrow_tracker/mod.rs
src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs
src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
src/tools/miri/src/diagnostics.rs
src/tools/miri/src/machine.rs
src/tools/miri/tests/fail/abort-terminator.stderr
src/tools/miri/tests/fail/alloc/deallocate-bad-alignment.stderr
src/tools/miri/tests/fail/alloc/deallocate-bad-size.stderr
src/tools/miri/tests/fail/alloc/deallocate-twice.stderr
src/tools/miri/tests/fail/alloc/global_system_mixup.stderr
src/tools/miri/tests/fail/alloc/reallocate-bad-size.stderr
src/tools/miri/tests/fail/alloc/reallocate-dangling.stderr
src/tools/miri/tests/fail/alloc/stack_free.stderr
src/tools/miri/tests/fail/box-cell-alias.stderr
src/tools/miri/tests/fail/concurrency/windows_join_detached.stderr
src/tools/miri/tests/fail/crates/tokio_mvp.stderr
src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr
src/tools/miri/tests/fail/data_race/stack_pop_race.stderr
src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr
src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr
src/tools/miri/tests/fail/generator-pinned-moved.stderr
src/tools/miri/tests/fail/intrinsics/simd-float-to-int.stderr
src/tools/miri/tests/fail/intrinsics/simd-gather.stderr
src/tools/miri/tests/fail/intrinsics/simd-scatter.stderr
src/tools/miri/tests/fail/issue-miri-1112.stderr
src/tools/miri/tests/fail/never_transmute_void.stderr
src/tools/miri/tests/fail/panic/bad_unwind.stderr
src/tools/miri/tests/fail/panic/double_panic.stderr
src/tools/miri/tests/fail/panic/no_std.stderr
src/tools/miri/tests/fail/panic/panic_abort1.stderr
src/tools/miri/tests/fail/panic/panic_abort2.stderr
src/tools/miri/tests/fail/panic/panic_abort3.stderr
src/tools/miri/tests/fail/panic/panic_abort4.stderr
src/tools/miri/tests/fail/provenance/provenance_transmute.stderr
src/tools/miri/tests/fail/shims/fs/isolated_file.stderr
src/tools/miri/tests/fail/shims/fs/mkstemp_immutable_arg.stderr
src/tools/miri/tests/fail/shims/fs/unix_open_missing_required_mode.stderr
src/tools/miri/tests/fail/should-pass/cpp20_rwc_syncs.stderr
src/tools/miri/tests/fail/stacked_borrows/aliasing_mut1.stderr
src/tools/miri/tests/fail/stacked_borrows/aliasing_mut2.stderr
src/tools/miri/tests/fail/stacked_borrows/aliasing_mut3.stderr
src/tools/miri/tests/fail/stacked_borrows/aliasing_mut4.stderr
src/tools/miri/tests/fail/stacked_borrows/box_exclusive_violation1.stderr
src/tools/miri/tests/fail/stacked_borrows/box_noalias_violation.stderr
src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector1.stderr
src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector2.stderr
src/tools/miri/tests/fail/stacked_borrows/illegal_dealloc1.stderr
src/tools/miri/tests/fail/stacked_borrows/illegal_write6.stderr
src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector1.stderr
src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector2.stderr
src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector3.stderr
src/tools/miri/tests/fail/stacked_borrows/issue-miri-1050-1.stderr
src/tools/miri/tests/fail/stacked_borrows/issue-miri-1050-2.stderr
src/tools/miri/tests/fail/stacked_borrows/mut_exclusive_violation1.stderr
src/tools/miri/tests/fail/stacked_borrows/newtype_pair_retagging.stderr
src/tools/miri/tests/fail/stacked_borrows/newtype_retagging.stderr
src/tools/miri/tests/fail/stacked_borrows/pointer_smuggling.stderr
src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr
src/tools/miri/tests/fail/stacked_borrows/retag_data_race_write.stderr
src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut.stderr
src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.stderr
src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr
src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr.stderr
src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_option.stderr
src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_tuple.stderr
src/tools/miri/tests/fail/stacked_borrows/shr_frozen_violation1.stderr
src/tools/miri/tests/fail/stacked_borrows/zst_slice.stderr
src/tools/miri/tests/fail/uninit_buffer.stderr
src/tools/miri/tests/fail/uninit_buffer_with_provenance.stderr
src/tools/miri/tests/pass/box.stderr
src/tools/remote-test-server/src/main.rs
src/tools/rustfmt/src/attr.rs
src/tools/tidy/src/deps.rs
src/tools/tidy/src/main.rs
src/tools/tidy/src/style.rs
src/tools/tidy/src/ui_tests.rs
src/tools/x/src/main.rs
src/version
triagebot.toml

index b93166b80a570846a57782b7d2758e6eab859aca..b29b3a418038ee4407809a38b67f67b7dcf3a010 100644 (file)
@@ -430,7 +430,7 @@ jobs:
             os: windows-latest-xl
           - name: dist-x86_64-msvc
             env:
-              RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --host=x86_64-pc-windows-msvc --target=x86_64-pc-windows-msvc --enable-full-tools --enable-profiler"
+              RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --host=x86_64-pc-windows-msvc --target=x86_64-pc-windows-msvc --enable-full-tools --enable-profiler --set rust.lto=thin"
               SCRIPT: PGO_HOST=x86_64-pc-windows-msvc src/ci/pgo.sh python x.py dist bootstrap --include-default-paths
               DIST_REQUIRE_ALL_TOOLS: 1
             os: windows-latest-xl
index c85049378061317bd6fe82f2fcc0a574a8318c89..4011a6fa6b95b3e0104a4f99ab5c912790d7a333 100644 (file)
@@ -28,7 +28,7 @@
 [submodule "src/llvm-project"]
        path = src/llvm-project
        url = https://github.com/rust-lang/llvm-project.git
-       branch = rustc/15.0-2022-08-09
+       branch = rustc/15.0-2022-12-07
 [submodule "src/doc/embedded-book"]
        path = src/doc/embedded-book
        url = https://github.com/rust-embedded/book.git
index 150a70341f5859c37b4a11800a6a5acb064ae6d8..cce203ef728fa6a85e0eea853b3f41c9b90ac58d 100644 (file)
@@ -394,7 +394,7 @@ dependencies = [
  "directories",
  "rustc-build-sysroot",
  "rustc-workspace-hack",
- "rustc_tools_util",
+ "rustc_tools_util 0.2.1",
  "rustc_version",
  "serde",
  "serde_json",
@@ -658,7 +658,7 @@ dependencies = [
 
 [[package]]
 name = "clippy"
-version = "0.1.67"
+version = "0.1.68"
 dependencies = [
  "clippy_lints",
  "clippy_utils",
@@ -673,7 +673,7 @@ dependencies = [
  "regex",
  "rustc-semver",
  "rustc-workspace-hack",
- "rustc_tools_util",
+ "rustc_tools_util 0.3.0",
  "semver",
  "serde",
  "syn",
@@ -700,7 +700,7 @@ dependencies = [
 
 [[package]]
 name = "clippy_lints"
-version = "0.1.67"
+version = "0.1.68"
 dependencies = [
  "cargo_metadata 0.14.0",
  "clippy_utils",
@@ -723,7 +723,7 @@ dependencies = [
 
 [[package]]
 name = "clippy_utils"
-version = "0.1.67"
+version = "0.1.68"
 dependencies = [
  "arrayvec",
  "if_chain",
@@ -809,9 +809,9 @@ dependencies = [
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.84"
+version = "0.1.85"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "989b2c1ca6e90ad06fdc69d1d1862fa28d27a977be6d92ae2fa762cf61fe0b10"
+checksum = "13e81c6cd7ab79f51a0c927d22858d61ad12bd0b3865f0b13ece02a4486aeabb"
 dependencies = [
  "cc",
  "rustc-std-workspace-core",
@@ -966,9 +966,9 @@ dependencies = [
 
 [[package]]
 name = "crossbeam-deque"
-version = "0.8.1"
+version = "0.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e"
+checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc"
 dependencies = [
  "cfg-if 1.0.0",
  "crossbeam-epoch",
@@ -977,25 +977,24 @@ dependencies = [
 
 [[package]]
 name = "crossbeam-epoch"
-version = "0.9.6"
+version = "0.9.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97242a70df9b89a65d0b6df3c4bf5b9ce03c5b7309019777fbde37e7537f8762"
+checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a"
 dependencies = [
+ "autocfg",
  "cfg-if 1.0.0",
  "crossbeam-utils",
- "lazy_static",
  "memoffset",
  "scopeguard",
 ]
 
 [[package]]
 name = "crossbeam-utils"
-version = "0.8.8"
+version = "0.8.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38"
+checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
 dependencies = [
  "cfg-if 1.0.0",
- "lazy_static",
 ]
 
 [[package]]
@@ -1068,7 +1067,7 @@ checksum = "a0afaad2b26fa326569eb264b1363e8ae3357618c43982b3f285f0774ce76b69"
 
 [[package]]
 name = "declare_clippy_lint"
-version = "0.1.67"
+version = "0.1.68"
 dependencies = [
  "itertools",
  "quote",
@@ -2379,9 +2378,9 @@ dependencies = [
 
 [[package]]
 name = "memoffset"
-version = "0.6.5"
+version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
+checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
 dependencies = [
  "autocfg",
 ]
@@ -4070,6 +4069,7 @@ dependencies = [
  "rustc_hir",
  "rustc_index",
  "rustc_infer",
+ "rustc_macros",
  "rustc_middle",
  "rustc_serialize",
  "rustc_session",
@@ -4168,6 +4168,7 @@ dependencies = [
 name = "rustc_parse_format"
 version = "0.0.0"
 dependencies = [
+ "rustc_data_structures",
  "rustc_lexer",
 ]
 
@@ -4342,12 +4343,14 @@ dependencies = [
  "rustc_feature",
  "rustc_fs_util",
  "rustc_hir",
+ "rustc_index",
  "rustc_lint_defs",
  "rustc_macros",
  "rustc_serialize",
  "rustc_span",
  "rustc_target",
  "smallvec",
+ "termize",
  "tracing",
  "winapi",
 ]
@@ -4401,6 +4404,7 @@ dependencies = [
  "rustc_span",
  "rustc_target",
  "tracing",
+ "twox-hash",
 ]
 
 [[package]]
@@ -4425,6 +4429,12 @@ version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "598f48ce2a421542b3e64828aa742b687cc1b91d2f96591cfdb7ac5988cd6366"
 
+[[package]]
+name = "rustc_tools_util"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ba09476327c4b70ccefb6180f046ef588c26a24cf5d269a9feba316eb4f029f"
+
 [[package]]
 name = "rustc_trait_selection"
 version = "0.0.0"
@@ -4623,9 +4633,9 @@ dependencies = [
 
 [[package]]
 name = "rustix"
-version = "0.36.3"
+version = "0.36.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b1fbb4dfc4eb1d390c02df47760bb19a84bb80b301ecc947ab5406394d8223e"
+checksum = "a3807b5d10909833d3e9acd1eb5fb988f79376ff10fce42937de71a449c4c588"
 dependencies = [
  "bitflags",
  "errno",
@@ -5391,6 +5401,17 @@ dependencies = [
  "tracing-subscriber",
 ]
 
+[[package]]
+name = "twox-hash"
+version = "1.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
+dependencies = [
+ "cfg-if 0.1.10",
+ "rand 0.8.5",
+ "static_assertions",
+]
+
 [[package]]
 name = "type-map"
 version = "0.4.0"
index 5c1990bb6c97bca9952a7bdefe4151cf24511a56..770dee7b54616dfdd0483f837d412d79a9b44ee5 100644 (file)
@@ -1,3 +1,94 @@
+Version 1.66.0 (2022-12-15)
+==========================
+
+Language
+--------
+- [Permit specifying explicit discriminants on all `repr(Int)` enums](https://github.com/rust-lang/rust/pull/95710/)
+  ```rust
+  #[repr(u8)]
+  enum Foo {
+      A(u8) = 0,
+      B(i8) = 1,
+      C(bool) = 42,
+  }
+  ```
+- [Allow transmutes between the same type differing only in lifetimes](https://github.com/rust-lang/rust/pull/101520/)
+- [Change constant evaluation errors from a deny-by-default lint to a hard error](https://github.com/rust-lang/rust/pull/102091/)
+- [Trigger `must_use` on `impl Trait` for supertraits](https://github.com/rust-lang/rust/pull/102287/)
+  This makes `impl ExactSizeIterator` respect the existing `#[must_use]` annotation on `Iterator`.
+- [Allow `..=X` in patterns](https://github.com/rust-lang/rust/pull/102275/)
+- [Uplift `clippy::for_loops_over_fallibles` lint into rustc](https://github.com/rust-lang/rust/pull/99696/)
+- [Stabilize `sym` operands in inline assembly](https://github.com/rust-lang/rust/pull/103168/)
+- [Update to Unicode 15](https://github.com/rust-lang/rust/pull/101912/)
+- [Opaque types no longer imply lifetime bounds](https://github.com/rust-lang/rust/pull/95474/)
+  This is a soundness fix which may break code that was erroneously relying on this behavior.
+
+Compiler
+--------
+- [Add armv5te-none-eabi and thumbv5te-none-eabi tier 3 targets](https://github.com/rust-lang/rust/pull/101329/)
+  - Refer to Rust's [platform support page][platform-support-doc] for more
+    information on Rust's tiered platform support.
+- [Add support for linking against macOS universal libraries](https://github.com/rust-lang/rust/pull/98736)
+
+Libraries
+---------
+- [Fix `#[derive(Default)]` on a generic `#[default]` enum adding unnecessary `Default` bounds](https://github.com/rust-lang/rust/pull/101040/)
+- [Update to Unicode 15](https://github.com/rust-lang/rust/pull/101821/)
+
+Stabilized APIs
+---------------
+
+- [`proc_macro::Span::source_text`](https://doc.rust-lang.org/stable/proc_macro/struct.Span.html#method.source_text)
+- [`uX::{checked_add_signed, overflowing_add_signed, saturating_add_signed, wrapping_add_signed}`](https://doc.rust-lang.org/stable/std/primitive.u8.html#method.checked_add_signed)
+- [`iX::{checked_add_unsigned, overflowing_add_unsigned, saturating_add_unsigned, wrapping_add_unsigned}`](https://doc.rust-lang.org/stable/std/primitive.i8.html#method.checked_add_unsigned)
+- [`iX::{checked_sub_unsigned, overflowing_sub_unsigned, saturating_sub_unsigned, wrapping_sub_unsigned}`](https://doc.rust-lang.org/stable/std/primitive.i8.html#method.checked_sub_unsigned)
+- [`BTreeSet::{first, last, pop_first, pop_last}`](https://doc.rust-lang.org/stable/std/collections/struct.BTreeSet.html#method.first)
+- [`BTreeMap::{first_key_value, last_key_value, first_entry, last_entry, pop_first, pop_last}`](https://doc.rust-lang.org/stable/std/collections/struct.BTreeMap.html#method.first_key_value)
+- [Add `AsFd` implementations for stdio lock types on WASI.](https://github.com/rust-lang/rust/pull/101768/)
+- [`impl TryFrom<Vec<T>> for Box<[T; N]>`](https://doc.rust-lang.org/stable/std/boxed/struct.Box.html#impl-TryFrom%3CVec%3CT%2C%20Global%3E%3E-for-Box%3C%5BT%3B%20N%5D%2C%20Global%3E)
+- [`core::hint::black_box`](https://doc.rust-lang.org/stable/std/hint/fn.black_box.html)
+- [`Duration::try_from_secs_{f32,f64}`](https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.try_from_secs_f32)
+- [`Option::unzip`](https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.unzip)
+- [`std::os::fd`](https://doc.rust-lang.org/stable/std/os/fd/index.html)
+
+
+Rustdoc
+-------
+
+- [Add Rustdoc warning for invalid HTML tags in the documentation](https://github.com/rust-lang/rust/pull/101720/)
+
+Cargo
+-----
+
+- [Added `cargo remove` to remove dependencies from Cargo.toml](https://doc.rust-lang.org/nightly/cargo/commands/cargo-remove.html)
+- [`cargo publish` now waits for the new version to be downloadable before exiting](https://github.com/rust-lang/cargo/pull/11062)
+
+See [detailed release notes](https://github.com/rust-lang/cargo/blob/master/CHANGELOG.md#cargo-166-2022-12-15) for more.
+
+Compatibility Notes
+-------------------
+
+- [Only apply `ProceduralMasquerade` hack to older versions of `rental`](https://github.com/rust-lang/rust/pull/94063/)
+- [Don't export `__heap_base` and `__data_end` on wasm32-wasi.](https://github.com/rust-lang/rust/pull/102385/)
+- [Don't export `__wasm_init_memory` on WebAssembly.](https://github.com/rust-lang/rust/pull/102426/)
+- [Only export `__tls_*` on wasm32-unknown-unknown.](https://github.com/rust-lang/rust/pull/102440/)
+- [Don't link to `libresolv` in libstd on Darwin](https://github.com/rust-lang/rust/pull/102766/)
+- [Update libstd's libc to 0.2.135 (to make `libstd` no longer pull in `libiconv.dylib` on Darwin)](https://github.com/rust-lang/rust/pull/103277/)
+- [Opaque types no longer imply lifetime bounds](https://github.com/rust-lang/rust/pull/95474/)
+  This is a soundness fix which may break code that was erroneously relying on this behavior.
+- [Make `order_dependent_trait_objects` show up in future-breakage reports](https://github.com/rust-lang/rust/pull/102635/)
+- [Change std::process::Command spawning to default to inheriting the parent's signal mask](https://github.com/rust-lang/rust/pull/101077/)
+
+Internal Changes
+----------------
+
+These changes do not affect any public interfaces of Rust, but they represent
+significant improvements to the performance or internals of rustc and related
+tools.
+
+- [Enable BOLT for LLVM compilation](https://github.com/rust-lang/rust/pull/94381/)
+- [Enable LTO for rustc_driver.so](https://github.com/rust-lang/rust/pull/101403/)
+
 Version 1.65.0 (2022-11-03)
 ==========================
 
index e14c9ea9a5d1a913d1af20f97776f5a7a43f4b9f..8c71332bfabb13d9f45813414978a05c1c9c2fcc 100644 (file)
@@ -1,6 +1,5 @@
 #![cfg_attr(feature = "nightly", feature(step_trait, rustc_attrs, min_specialization))]
 
-use std::convert::{TryFrom, TryInto};
 use std::fmt;
 #[cfg(feature = "nightly")]
 use std::iter::Step;
@@ -803,12 +802,9 @@ pub fn fit_unsigned(x: u128) -> Integer {
     pub fn for_align<C: HasDataLayout>(cx: &C, wanted: Align) -> Option<Integer> {
         let dl = cx.data_layout();
 
-        for candidate in [I8, I16, I32, I64, I128] {
-            if wanted == candidate.align(dl).abi && wanted.bytes() == candidate.size().bytes() {
-                return Some(candidate);
-            }
-        }
-        None
+        [I8, I16, I32, I64, I128].into_iter().find(|&candidate| {
+            wanted == candidate.align(dl).abi && wanted.bytes() == candidate.size().bytes()
+        })
     }
 
     /// Find the largest integer with the given alignment or less.
index 3db8adb2a244424a52cbf667128b7a722f92150a..2286712f02565974f2623901844c82328e562ff6 100644 (file)
@@ -2,7 +2,6 @@
 use crate::{Float, FloatConvert, ParseError, Round, Status, StatusAnd};
 
 use core::cmp::{self, Ordering};
-use core::convert::TryFrom;
 use core::fmt::{self, Write};
 use core::marker::PhantomData;
 use core::mem;
index 46dbbd83d19054e2c2aaf8e4751c68a9aaf974d0..4fae5ef845f7d95a2cfb947a25daeada6e46cdf7 100644 (file)
@@ -28,7 +28,7 @@
 use std::alloc::Layout;
 use std::cell::{Cell, RefCell};
 use std::cmp;
-use std::marker::{PhantomData, Send};
+use std::marker::PhantomData;
 use std::mem::{self, MaybeUninit};
 use std::ptr::{self, NonNull};
 use std::slice;
index 4d80f904ac461beafd03f212c83931e981fa1cff..f933b9b161ca91f56bfb0db9e3f39eaae37e4d54 100644 (file)
@@ -33,7 +33,6 @@
 use rustc_span::source_map::{respan, Spanned};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
-use std::convert::TryFrom;
 use std::fmt;
 use std::mem;
 use thin_vec::{thin_vec, ThinVec};
@@ -1735,8 +1734,10 @@ pub enum StrStyle {
 /// A literal in a meta item.
 #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
 pub struct MetaItemLit {
-    /// The original literal token as written in source code.
-    pub token_lit: token::Lit,
+    /// The original literal as written in the source code.
+    pub symbol: Symbol,
+    /// The original suffix as written in the source code.
+    pub suffix: Option<Symbol>,
     /// The "semantic" representation of the literal lowered from the original tokens.
     /// Strings are unescaped, hexadecimal forms are eliminated, etc.
     pub kind: LitKind,
@@ -1746,13 +1747,14 @@ pub struct MetaItemLit {
 /// Similar to `MetaItemLit`, but restricted to string literals.
 #[derive(Clone, Copy, Encodable, Decodable, Debug)]
 pub struct StrLit {
-    /// The original literal token as written in source code.
-    pub style: StrStyle,
+    /// The original literal as written in source code.
     pub symbol: Symbol,
+    /// The original suffix as written in source code.
     pub suffix: Option<Symbol>,
-    pub span: Span,
-    /// The unescaped "semantic" representation of the literal lowered from the original token.
+    /// The semantic (unescaped) representation of the literal.
     pub symbol_unescaped: Symbol,
+    pub style: StrStyle,
+    pub span: Span,
 }
 
 impl StrLit {
@@ -1798,8 +1800,9 @@ pub enum LitKind {
     /// A string literal (`"foo"`). The symbol is unescaped, and so may differ
     /// from the original token's symbol.
     Str(Symbol, StrStyle),
-    /// A byte string (`b"foo"`).
-    ByteStr(Lrc<[u8]>),
+    /// A byte string (`b"foo"`). Not stored as a symbol because it might be
+    /// non-utf8, and symbols only allow utf8 strings.
+    ByteStr(Lrc<[u8]>, StrStyle),
     /// A byte char (`b'f'`).
     Byte(u8),
     /// A character literal (`'a'`).
@@ -1824,7 +1827,7 @@ pub fn is_str(&self) -> bool {
 
     /// Returns `true` if this literal is byte literal string.
     pub fn is_bytestr(&self) -> bool {
-        matches!(self, LitKind::ByteStr(_))
+        matches!(self, LitKind::ByteStr(..))
     }
 
     /// Returns `true` if this is a numeric literal.
@@ -2463,7 +2466,7 @@ pub enum ModKind {
     Unloaded,
 }
 
-#[derive(Copy, Clone, Encodable, Decodable, Debug)]
+#[derive(Copy, Clone, Encodable, Decodable, Debug, Default)]
 pub struct ModSpans {
     /// `inner_span` covers the body of the module; for a file module, its the whole file.
     /// For an inline module, its the span inside the `{ ... }`, not including the curly braces.
@@ -2471,12 +2474,6 @@ pub struct ModSpans {
     pub inject_use_span: Span,
 }
 
-impl Default for ModSpans {
-    fn default() -> ModSpans {
-        ModSpans { inner_span: Default::default(), inject_use_span: Default::default() }
-    }
-}
-
 /// Foreign module declaration.
 ///
 /// E.g., `extern { .. }` or `extern "C" { .. }`.
@@ -3101,7 +3098,7 @@ mod size_asserts {
     static_assert_size!(ItemKind, 112);
     static_assert_size!(LitKind, 24);
     static_assert_size!(Local, 72);
-    static_assert_size!(MetaItemLit, 48);
+    static_assert_size!(MetaItemLit, 40);
     static_assert_size!(Param, 40);
     static_assert_size!(Pat, 88);
     static_assert_size!(Path, 24);
index 057cc26b5799e7eff82d0d6b7ad30eade281be53..d99f6ed2c1cd3d842964559774669b83e86dc75b 100644 (file)
@@ -1,15 +1,15 @@
 //! Functions dealing with attributes and meta items.
 
-use crate::ast;
 use crate::ast::{AttrArgs, AttrArgsEq, AttrId, AttrItem, AttrKind, AttrStyle, AttrVec, Attribute};
 use crate::ast::{DelimArgs, Expr, ExprKind, LitKind, MetaItemLit};
 use crate::ast::{MacDelimiter, MetaItem, MetaItemKind, NestedMetaItem, NormalAttr};
-use crate::ast::{Path, PathSegment, StrStyle, DUMMY_NODE_ID};
+use crate::ast::{Path, PathSegment, DUMMY_NODE_ID};
 use crate::ptr::P;
 use crate::token::{self, CommentKind, Delimiter, Token};
 use crate::tokenstream::{DelimSpan, Spacing, TokenTree};
 use crate::tokenstream::{LazyAttrTokenStream, TokenStream};
 use crate::util::comments;
+use crate::util::literal::escape_string_symbol;
 use rustc_data_structures::sync::WorkerLocal;
 use rustc_index::bit_set::GrowableBitSet;
 use rustc_span::symbol::{sym, Ident, Symbol};
@@ -321,18 +321,6 @@ pub fn tokens(&self) -> TokenStream {
     }
 }
 
-/* Constructors */
-
-pub fn mk_name_value_item_str(ident: Ident, str: Symbol, str_span: Span) -> MetaItem {
-    mk_name_value_item(ident, LitKind::Str(str, ast::StrStyle::Cooked), str_span)
-}
-
-pub fn mk_name_value_item(ident: Ident, kind: LitKind, lit_span: Span) -> MetaItem {
-    let lit = MetaItemLit { token_lit: kind.to_token_lit(), kind, span: lit_span };
-    let span = ident.span.to(lit_span);
-    MetaItem { path: Path::from_ident(ident), kind: MetaItemKind::NameValue(lit), span }
-}
-
 pub struct AttrIdGenerator(WorkerLocal<Cell<u32>>);
 
 #[cfg(debug_assertions)]
@@ -408,7 +396,7 @@ pub fn mk_attr_name_value_str(
     val: Symbol,
     span: Span,
 ) -> Attribute {
-    let lit = LitKind::Str(val, StrStyle::Cooked).to_token_lit();
+    let lit = token::Lit::new(token::Str, escape_string_symbol(val), None);
     let expr = P(Expr {
         id: DUMMY_NODE_ID,
         kind: ExprKind::Lit(lit),
index 30481eddf9160ee30009d679ade670127c96fc32..4b2850336a03db2479ec59804de725eb26ff23ae 100644 (file)
@@ -22,7 +22,6 @@
 //!   Moreover, a switch to, e.g., `P<'a, T>` would be easy and mostly automated.
 
 use std::fmt::{self, Debug, Display};
-use std::iter::FromIterator;
 use std::ops::{Deref, DerefMut};
 use std::{slice, vec};
 
index c0cc4e79a3d53161b3e985c45ba1daae69ee0efc..7b8c0d79a17e8519f3fc79a3f65149db2f2537dc 100644 (file)
@@ -114,7 +114,7 @@ pub fn from_token(token: &Token) -> Option<Lit> {
                 if let NtExpr(expr) | NtLiteral(expr) = &**nt
                 && let ast::ExprKind::Lit(token_lit) = expr.kind =>
             {
-                Some(token_lit.clone())
+                Some(token_lit)
             }
             _ => None,
         }
index 482c302950f01ae7e20b16002afb4b4e114e97f1..29a5eb4b7c509260a9034296eec158af8abcb123 100644 (file)
@@ -362,7 +362,7 @@ pub fn add_comma(&self) -> Option<(TokenStream, Span)> {
     }
 }
 
-impl iter::FromIterator<TokenTree> for TokenStream {
+impl FromIterator<TokenTree> for TokenStream {
     fn from_iter<I: IntoIterator<Item = TokenTree>>(iter: I) -> Self {
         TokenStream::new(iter.into_iter().collect::<Vec<TokenTree>>())
     }
index f6f186b51073b788d46438e87583c6afbcb755bc..0daeecb53a8b9d88a1432fa05440360de7096cad 100644 (file)
@@ -1,11 +1,31 @@
 //! Code related to parsing literals.
 
-use crate::ast::{self, LitKind, MetaItemLit};
+use crate::ast::{self, LitKind, MetaItemLit, StrStyle};
 use crate::token::{self, Token};
 use rustc_lexer::unescape::{byte_from_char, unescape_byte, unescape_char, unescape_literal, Mode};
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::Span;
-use std::ascii;
+use std::{ascii, fmt, str};
+
+// Escapes a string, represented as a symbol. Reuses the original symbol,
+// avoiding interning, if no changes are required.
+pub fn escape_string_symbol(symbol: Symbol) -> Symbol {
+    let s = symbol.as_str();
+    let escaped = s.escape_default().to_string();
+    if s == escaped { symbol } else { Symbol::intern(&escaped) }
+}
+
+// Escapes a char.
+pub fn escape_char_symbol(ch: char) -> Symbol {
+    let s: String = ch.escape_default().map(Into::<char>::into).collect();
+    Symbol::intern(&s)
+}
+
+// Escapes a byte string.
+pub fn escape_byte_str_symbol(bytes: &[u8]) -> Symbol {
+    let s = bytes.escape_ascii().to_string();
+    Symbol::intern(&s)
+}
 
 #[derive(Debug)]
 pub enum LitError {
@@ -115,9 +135,9 @@ pub fn from_token_lit(lit: token::Lit) -> Result<LitKind, LitError> {
                     }
                 });
                 error?;
-                LitKind::ByteStr(buf.into())
+                LitKind::ByteStr(buf.into(), StrStyle::Cooked)
             }
-            token::ByteStrRaw(_) => {
+            token::ByteStrRaw(n) => {
                 let s = symbol.as_str();
                 let bytes = if s.contains('\r') {
                     let mut buf = Vec::with_capacity(s.len());
@@ -136,69 +156,95 @@ pub fn from_token_lit(lit: token::Lit) -> Result<LitKind, LitError> {
                     symbol.to_string().into_bytes()
                 };
 
-                LitKind::ByteStr(bytes.into())
+                LitKind::ByteStr(bytes.into(), StrStyle::Raw(n))
             }
             token::Err => LitKind::Err,
         })
     }
+}
 
-    /// Attempts to recover a token from semantic literal.
-    /// This function is used when the original token doesn't exist (e.g. the literal is created
-    /// by an AST-based macro) or unavailable (e.g. from HIR pretty-printing).
-    pub fn to_token_lit(&self) -> token::Lit {
-        let (kind, symbol, suffix) = match *self {
-            LitKind::Str(symbol, ast::StrStyle::Cooked) => {
-                // Don't re-intern unless the escaped string is different.
-                let s = symbol.as_str();
-                let escaped = s.escape_default().to_string();
-                let symbol = if s == escaped { symbol } else { Symbol::intern(&escaped) };
-                (token::Str, symbol, None)
-            }
-            LitKind::Str(symbol, ast::StrStyle::Raw(n)) => (token::StrRaw(n), symbol, None),
-            LitKind::ByteStr(ref bytes) => {
-                let string = bytes.escape_ascii().to_string();
-                (token::ByteStr, Symbol::intern(&string), None)
+impl fmt::Display for LitKind {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match *self {
+            LitKind::Byte(b) => {
+                let b: String = ascii::escape_default(b).map(Into::<char>::into).collect();
+                write!(f, "b'{}'", b)?;
             }
-            LitKind::Byte(byte) => {
-                let string: String = ascii::escape_default(byte).map(Into::<char>::into).collect();
-                (token::Byte, Symbol::intern(&string), None)
+            LitKind::Char(ch) => write!(f, "'{}'", escape_char_symbol(ch))?,
+            LitKind::Str(sym, StrStyle::Cooked) => write!(f, "\"{}\"", escape_string_symbol(sym))?,
+            LitKind::Str(sym, StrStyle::Raw(n)) => write!(
+                f,
+                "r{delim}\"{string}\"{delim}",
+                delim = "#".repeat(n as usize),
+                string = sym
+            )?,
+            LitKind::ByteStr(ref bytes, StrStyle::Cooked) => {
+                write!(f, "b\"{}\"", escape_byte_str_symbol(bytes))?
             }
-            LitKind::Char(ch) => {
-                let string: String = ch.escape_default().map(Into::<char>::into).collect();
-                (token::Char, Symbol::intern(&string), None)
+            LitKind::ByteStr(ref bytes, StrStyle::Raw(n)) => {
+                // Unwrap because raw byte string literals can only contain ASCII.
+                let symbol = str::from_utf8(bytes).unwrap();
+                write!(
+                    f,
+                    "br{delim}\"{string}\"{delim}",
+                    delim = "#".repeat(n as usize),
+                    string = symbol
+                )?;
             }
             LitKind::Int(n, ty) => {
-                let suffix = match ty {
-                    ast::LitIntType::Unsigned(ty) => Some(ty.name()),
-                    ast::LitIntType::Signed(ty) => Some(ty.name()),
-                    ast::LitIntType::Unsuffixed => None,
-                };
-                (token::Integer, sym::integer(n), suffix)
+                write!(f, "{}", n)?;
+                match ty {
+                    ast::LitIntType::Unsigned(ty) => write!(f, "{}", ty.name())?,
+                    ast::LitIntType::Signed(ty) => write!(f, "{}", ty.name())?,
+                    ast::LitIntType::Unsuffixed => {}
+                }
             }
             LitKind::Float(symbol, ty) => {
-                let suffix = match ty {
-                    ast::LitFloatType::Suffixed(ty) => Some(ty.name()),
-                    ast::LitFloatType::Unsuffixed => None,
-                };
-                (token::Float, symbol, suffix)
+                write!(f, "{}", symbol)?;
+                match ty {
+                    ast::LitFloatType::Suffixed(ty) => write!(f, "{}", ty.name())?,
+                    ast::LitFloatType::Unsuffixed => {}
+                }
             }
-            LitKind::Bool(value) => {
-                let symbol = if value { kw::True } else { kw::False };
-                (token::Bool, symbol, None)
+            LitKind::Bool(b) => write!(f, "{}", if b { "true" } else { "false" })?,
+            LitKind::Err => {
+                // This only shows up in places like `-Zunpretty=hir` output, so we
+                // don't bother to produce something useful.
+                write!(f, "<bad-literal>")?;
             }
-            // This only shows up in places like `-Zunpretty=hir` output, so we
-            // don't bother to produce something useful.
-            LitKind::Err => (token::Err, Symbol::intern("<bad-literal>"), None),
-        };
+        }
 
-        token::Lit::new(kind, symbol, suffix)
+        Ok(())
     }
 }
 
 impl MetaItemLit {
-    /// Converts token literal into a meta item literal.
+    /// Converts token literal into a meta item literal.
     pub fn from_token_lit(token_lit: token::Lit, span: Span) -> Result<MetaItemLit, LitError> {
-        Ok(MetaItemLit { token_lit, kind: LitKind::from_token_lit(token_lit)?, span })
+        Ok(MetaItemLit {
+            symbol: token_lit.symbol,
+            suffix: token_lit.suffix,
+            kind: LitKind::from_token_lit(token_lit)?,
+            span,
+        })
+    }
+
+    /// Cheaply converts a meta item literal into a token literal.
+    pub fn as_token_lit(&self) -> token::Lit {
+        let kind = match self.kind {
+            LitKind::Bool(_) => token::Bool,
+            LitKind::Str(_, ast::StrStyle::Cooked) => token::Str,
+            LitKind::Str(_, ast::StrStyle::Raw(n)) => token::StrRaw(n),
+            LitKind::ByteStr(_, ast::StrStyle::Cooked) => token::ByteStr,
+            LitKind::ByteStr(_, ast::StrStyle::Raw(n)) => token::ByteStrRaw(n),
+            LitKind::Byte(_) => token::Byte,
+            LitKind::Char(_) => token::Char,
+            LitKind::Int(..) => token::Integer,
+            LitKind::Float(..) => token::Float,
+            LitKind::Err => token::Err,
+        };
+
+        token::Lit::new(kind, self.symbol, self.suffix)
     }
 
     /// Converts an arbitrary token into meta item literal.
index 9974ebff311fb8c536f140880172ab7f95c4b07f..e86e807279d6f10157264705e42e49c8b8c872d0 100644 (file)
@@ -31,6 +31,44 @@ pub(super) fn lower_expr(&mut self, e: &Expr) -> &'hir hir::Expr<'hir> {
 
     pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
         ensure_sufficient_stack(|| {
+            match &e.kind {
+                // Paranthesis expression does not have a HirId and is handled specially.
+                ExprKind::Paren(ex) => {
+                    let mut ex = self.lower_expr_mut(ex);
+                    // Include parens in span, but only if it is a super-span.
+                    if e.span.contains(ex.span) {
+                        ex.span = self.lower_span(e.span);
+                    }
+                    // Merge attributes into the inner expression.
+                    if !e.attrs.is_empty() {
+                        let old_attrs =
+                            self.attrs.get(&ex.hir_id.local_id).map(|la| *la).unwrap_or(&[]);
+                        self.attrs.insert(
+                            ex.hir_id.local_id,
+                            &*self.arena.alloc_from_iter(
+                                e.attrs
+                                    .iter()
+                                    .map(|a| self.lower_attr(a))
+                                    .chain(old_attrs.iter().cloned()),
+                            ),
+                        );
+                    }
+                    return ex;
+                }
+                // Desugar `ExprForLoop`
+                // from: `[opt_ident]: for <pat> in <head> <body>`
+                //
+                // This also needs special handling because the HirId of the returned `hir::Expr` will not
+                // correspond to the `e.id`, so `lower_expr_for` handles attribute lowering itself.
+                ExprKind::ForLoop(pat, head, body, opt_label) => {
+                    return self.lower_expr_for(e, pat, head, body, *opt_label);
+                }
+                _ => (),
+            }
+
+            let hir_id = self.lower_node_id(e.id);
+            self.lower_attrs(hir_id, &e.attrs);
+
             let kind = match &e.kind {
                 ExprKind::Box(inner) => hir::ExprKind::Box(self.lower_expr(inner)),
                 ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
@@ -48,7 +86,6 @@ pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
                     if e.attrs.get(0).map_or(false, |a| a.has_name(sym::rustc_box)) {
                         if let [inner] = &args[..] && e.attrs.len() == 1 {
                             let kind = hir::ExprKind::Box(self.lower_expr(&inner));
-                            let hir_id = self.lower_node_id(e.id);
                             return hir::Expr { hir_id, kind, span: self.lower_span(e.span) };
                         } else {
                             self.tcx.sess.emit_err(RustcBoxAttributeError { span: e.span });
@@ -97,7 +134,7 @@ pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
                 }
                 ExprKind::IncludedBytes(bytes) => hir::ExprKind::Lit(respan(
                     self.lower_span(e.span),
-                    LitKind::ByteStr(bytes.clone()),
+                    LitKind::ByteStr(bytes.clone(), StrStyle::Cooked),
                 )),
                 ExprKind::Cast(expr, ty) => {
                     let expr = self.lower_expr(expr);
@@ -147,7 +184,7 @@ pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
                 ),
                 ExprKind::Async(capture_clause, closure_node_id, block) => self.make_async_expr(
                     *capture_clause,
-                    None,
+                    hir_id,
                     *closure_node_id,
                     None,
                     e.span,
@@ -184,6 +221,7 @@ pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
                             binder,
                             *capture_clause,
                             e.id,
+                            hir_id,
                             *closure_id,
                             fn_decl,
                             body,
@@ -279,39 +317,12 @@ pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
                 ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()),
                 ExprKind::Err => hir::ExprKind::Err,
                 ExprKind::Try(sub_expr) => self.lower_expr_try(e.span, sub_expr),
-                ExprKind::Paren(ex) => {
-                    let mut ex = self.lower_expr_mut(ex);
-                    // Include parens in span, but only if it is a super-span.
-                    if e.span.contains(ex.span) {
-                        ex.span = self.lower_span(e.span);
-                    }
-                    // Merge attributes into the inner expression.
-                    if !e.attrs.is_empty() {
-                        let old_attrs =
-                            self.attrs.get(&ex.hir_id.local_id).map(|la| *la).unwrap_or(&[]);
-                        self.attrs.insert(
-                            ex.hir_id.local_id,
-                            &*self.arena.alloc_from_iter(
-                                e.attrs
-                                    .iter()
-                                    .map(|a| self.lower_attr(a))
-                                    .chain(old_attrs.iter().cloned()),
-                            ),
-                        );
-                    }
-                    return ex;
-                }
 
-                // Desugar `ExprForLoop`
-                // from: `[opt_ident]: for <pat> in <head> <body>`
-                ExprKind::ForLoop(pat, head, body, opt_label) => {
-                    return self.lower_expr_for(e, pat, head, body, *opt_label);
-                }
+                ExprKind::Paren(_) | ExprKind::ForLoop(..) => unreachable!("already handled"),
+
                 ExprKind::MacCall(_) => panic!("{:?} shouldn't exist here", e.span),
             };
 
-            let hir_id = self.lower_node_id(e.id);
-            self.lower_attrs(hir_id, &e.attrs);
             hir::Expr { hir_id, kind, span: self.lower_span(e.span) }
         })
     }
@@ -436,18 +447,14 @@ fn has_let_expr(expr: &Expr) -> bool {
                 let lhs = self.lower_cond(lhs);
                 let rhs = self.lower_cond(rhs);
 
-                self.arena.alloc(self.expr(
-                    cond.span,
-                    hir::ExprKind::Binary(op, lhs, rhs),
-                    AttrVec::new(),
-                ))
+                self.arena.alloc(self.expr(cond.span, hir::ExprKind::Binary(op, lhs, rhs)))
             }
             ExprKind::Let(..) => self.lower_expr(cond),
             _ => {
                 let cond = self.lower_expr(cond);
                 let reason = DesugaringKind::CondTemporary;
                 let span_block = self.mark_span_with_reason(reason, cond.span, None);
-                self.expr_drop_temps(span_block, cond, AttrVec::new())
+                self.expr_drop_temps(span_block, cond)
             }
         }
     }
@@ -477,12 +484,12 @@ fn lower_expr_while_in_loop_scope(
     ) -> hir::ExprKind<'hir> {
         let lowered_cond = self.with_loop_condition_scope(|t| t.lower_cond(cond));
         let then = self.lower_block_expr(body);
-        let expr_break = self.expr_break(span, AttrVec::new());
+        let expr_break = self.expr_break(span);
         let stmt_break = self.stmt_expr(span, expr_break);
         let else_blk = self.block_all(span, arena_vec![self; stmt_break], None);
-        let else_expr = self.arena.alloc(self.expr_block(else_blk, AttrVec::new()));
+        let else_expr = self.arena.alloc(self.expr_block(else_blk));
         let if_kind = hir::ExprKind::If(lowered_cond, self.arena.alloc(then), Some(else_expr));
-        let if_expr = self.expr(span, if_kind, AttrVec::new());
+        let if_expr = self.expr(span, if_kind);
         let block = self.block_expr(self.arena.alloc(if_expr));
         let span = self.lower_span(span.with_hi(cond.span.hi()));
         let opt_label = self.lower_label(opt_label);
@@ -538,12 +545,7 @@ fn wrap_in_try_constructor(
         expr: &'hir hir::Expr<'hir>,
         overall_span: Span,
     ) -> &'hir hir::Expr<'hir> {
-        let constructor = self.arena.alloc(self.expr_lang_item_path(
-            method_span,
-            lang_item,
-            AttrVec::new(),
-            None,
-        ));
+        let constructor = self.arena.alloc(self.expr_lang_item_path(method_span, lang_item, None));
         self.expr_call(overall_span, constructor, std::slice::from_ref(expr))
     }
 
@@ -585,7 +587,7 @@ fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> {
     pub(super) fn make_async_expr(
         &mut self,
         capture_clause: CaptureBy,
-        outer_hir_id: Option<hir::HirId>,
+        outer_hir_id: hir::HirId,
         closure_node_id: NodeId,
         ret_ty: Option<hir::FnRetTy<'hir>>,
         span: Span,
@@ -678,8 +680,9 @@ pub(super) fn make_async_expr(
             hir::ExprKind::Closure(c)
         };
 
-        let track_caller = outer_hir_id
-            .and_then(|id| self.attrs.get(&id.local_id))
+        let track_caller = self
+            .attrs
+            .get(&outer_hir_id.local_id)
             .map_or(false, |attrs| attrs.into_iter().any(|attr| attr.has_name(sym::track_caller)));
 
         let hir_id = self.lower_node_id(closure_node_id);
@@ -715,12 +718,8 @@ pub(super) fn make_async_expr(
         // E0700 in src/test/ui/self/self_lifetime-async.rs
 
         // `future::identity_future`:
-        let identity_future = self.expr_lang_item_path(
-            unstable_span,
-            hir::LangItem::IdentityFuture,
-            AttrVec::new(),
-            None,
-        );
+        let identity_future =
+            self.expr_lang_item_path(unstable_span, hir::LangItem::IdentityFuture, None);
 
         // `future::identity_future(generator)`:
         hir::ExprKind::Call(self.arena.alloc(identity_future), arena_vec![self; generator])
@@ -817,7 +816,7 @@ fn lower_expr_await(&mut self, dot_await_span: Span, expr: &Expr) -> hir::ExprKi
             let break_x = self.with_loop_scope(loop_node_id, move |this| {
                 let expr_break =
                     hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr));
-                this.arena.alloc(this.expr(gen_future_span, expr_break, AttrVec::new()))
+                this.arena.alloc(this.expr(gen_future_span, expr_break))
             });
             self.arm(ready_pat, break_x)
         };
@@ -850,17 +849,13 @@ fn lower_expr_await(&mut self, dot_await_span: Span, expr: &Expr) -> hir::ExprKi
             let yield_expr = self.expr(
                 span,
                 hir::ExprKind::Yield(unit, hir::YieldSource::Await { expr: Some(expr_hir_id) }),
-                AttrVec::new(),
             );
             let yield_expr = self.arena.alloc(yield_expr);
 
             if let Some(task_context_hid) = self.task_context {
                 let lhs = self.expr_ident(span, task_context_ident, task_context_hid);
-                let assign = self.expr(
-                    span,
-                    hir::ExprKind::Assign(lhs, yield_expr, self.lower_span(span)),
-                    AttrVec::new(),
-                );
+                let assign =
+                    self.expr(span, hir::ExprKind::Assign(lhs, yield_expr, self.lower_span(span)));
                 self.stmt_expr(span, assign)
             } else {
                 // Use of `await` outside of an async context. Return `yield_expr` so that we can
@@ -1002,6 +997,7 @@ fn lower_expr_async_closure(
         binder: &ClosureBinder,
         capture_clause: CaptureBy,
         closure_id: NodeId,
+        closure_hir_id: hir::HirId,
         inner_closure_id: NodeId,
         decl: &FnDecl,
         body: &Expr,
@@ -1035,16 +1031,14 @@ fn lower_expr_async_closure(
 
                 let async_body = this.make_async_expr(
                     capture_clause,
-                    // FIXME(nbdd0121): This should also use a proper HIR id so `#[track_caller]`
-                    // can be applied on async closures as well.
-                    None,
+                    closure_hir_id,
                     inner_closure_id,
                     async_ret_ty,
                     body.span,
                     hir::AsyncGeneratorKind::Closure,
                     |this| this.with_new_scopes(|this| this.lower_expr_mut(body)),
                 );
-                this.expr(fn_decl_span, async_body, AttrVec::new())
+                this.expr(fn_decl_span, async_body)
             });
             body_id
         });
@@ -1304,7 +1298,7 @@ fn destructure_assign_mut(
         let ident = self.expr_ident(lhs.span, ident, binding);
         let assign =
             hir::ExprKind::Assign(self.lower_expr(lhs), ident, self.lower_span(eq_sign_span));
-        let expr = self.expr(lhs.span, assign, AttrVec::new());
+        let expr = self.expr(lhs.span, assign);
         assignments.push(self.stmt_expr(lhs.span, expr));
         pat
     }
@@ -1345,8 +1339,7 @@ fn lower_expr_range_closed(&mut self, span: Span, e1: &Expr, e2: &Expr) -> hir::
         let e2 = self.lower_expr_mut(e2);
         let fn_path =
             hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, self.lower_span(span), None);
-        let fn_expr =
-            self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path), AttrVec::new()));
+        let fn_expr = self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path)));
         hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2])
     }
 
@@ -1518,8 +1511,7 @@ fn lower_expr_for(
 
         // `None => break`
         let none_arm = {
-            let break_expr =
-                self.with_loop_scope(e.id, |this| this.expr_break_alloc(for_span, AttrVec::new()));
+            let break_expr = self.with_loop_scope(e.id, |this| this.expr_break_alloc(for_span));
             let pat = self.pat_none(for_span);
             self.arm(pat, break_expr)
         };
@@ -1528,7 +1520,7 @@ fn lower_expr_for(
         let some_arm = {
             let some_pat = self.pat_some(pat_span, pat);
             let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false));
-            let body_expr = self.arena.alloc(self.expr_block(body_block, AttrVec::new()));
+            let body_expr = self.arena.alloc(self.expr_block(body_block));
             self.arm(some_pat, body_expr)
         };
 
@@ -1591,7 +1583,9 @@ fn lower_expr_for(
         // surrounding scope of the `match` since the `match` is not a terminating scope.
         //
         // Also, add the attributes to the outer returned expr node.
-        self.expr_drop_temps_mut(for_span, match_expr, e.attrs.clone())
+        let expr = self.expr_drop_temps_mut(for_span, match_expr);
+        self.lower_attrs(expr.hir_id, &e.attrs);
+        expr
     }
 
     /// Desugar `ExprKind::Try` from: `<expr>?` into:
@@ -1646,12 +1640,8 @@ fn lower_expr_try(&mut self, span: Span, sub_expr: &Expr) -> hir::ExprKind<'hir>
         let continue_arm = {
             let val_ident = Ident::with_dummy_span(sym::val);
             let (val_pat, val_pat_nid) = self.pat_ident(span, val_ident);
-            let val_expr = self.arena.alloc(self.expr_ident_with_attrs(
-                span,
-                val_ident,
-                val_pat_nid,
-                attrs.clone(),
-            ));
+            let val_expr = self.expr_ident(span, val_ident, val_pat_nid);
+            self.lower_attrs(val_expr.hir_id, &attrs);
             let continue_pat = self.pat_cf_continue(unstable_span, val_pat);
             self.arm(continue_pat, val_expr)
         };
@@ -1677,15 +1667,11 @@ fn lower_expr_try(&mut self, span: Span, sub_expr: &Expr) -> hir::ExprKind<'hir>
                         hir::Destination { label: None, target_id },
                         Some(from_residual_expr),
                     ),
-                    attrs,
                 ))
             } else {
-                self.arena.alloc(self.expr(
-                    try_span,
-                    hir::ExprKind::Ret(Some(from_residual_expr)),
-                    attrs,
-                ))
+                self.arena.alloc(self.expr(try_span, hir::ExprKind::Ret(Some(from_residual_expr))))
             };
+            self.lower_attrs(ret_expr.hir_id, &attrs);
 
             let break_pat = self.pat_cf_break(try_span, residual_local);
             self.arm(break_pat, ret_expr)
@@ -1750,18 +1736,16 @@ pub(super) fn expr_drop_temps(
         &mut self,
         span: Span,
         expr: &'hir hir::Expr<'hir>,
-        attrs: AttrVec,
     ) -> &'hir hir::Expr<'hir> {
-        self.arena.alloc(self.expr_drop_temps_mut(span, expr, attrs))
+        self.arena.alloc(self.expr_drop_temps_mut(span, expr))
     }
 
     pub(super) fn expr_drop_temps_mut(
         &mut self,
         span: Span,
         expr: &'hir hir::Expr<'hir>,
-        attrs: AttrVec,
     ) -> hir::Expr<'hir> {
-        self.expr(span, hir::ExprKind::DropTemps(expr), attrs)
+        self.expr(span, hir::ExprKind::DropTemps(expr))
     }
 
     fn expr_match(
@@ -1771,29 +1755,25 @@ fn expr_match(
         arms: &'hir [hir::Arm<'hir>],
         source: hir::MatchSource,
     ) -> hir::Expr<'hir> {
-        self.expr(span, hir::ExprKind::Match(arg, arms, source), AttrVec::new())
+        self.expr(span, hir::ExprKind::Match(arg, arms, source))
     }
 
-    fn expr_break(&mut self, span: Span, attrs: AttrVec) -> hir::Expr<'hir> {
+    fn expr_break(&mut self, span: Span) -> hir::Expr<'hir> {
         let expr_break = hir::ExprKind::Break(self.lower_loop_destination(None), None);
-        self.expr(span, expr_break, attrs)
+        self.expr(span, expr_break)
     }
 
-    fn expr_break_alloc(&mut self, span: Span, attrs: AttrVec) -> &'hir hir::Expr<'hir> {
-        let expr_break = self.expr_break(span, attrs);
+    fn expr_break_alloc(&mut self, span: Span) -> &'hir hir::Expr<'hir> {
+        let expr_break = self.expr_break(span);
         self.arena.alloc(expr_break)
     }
 
     fn expr_mut_addr_of(&mut self, span: Span, e: &'hir hir::Expr<'hir>) -> hir::Expr<'hir> {
-        self.expr(
-            span,
-            hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, e),
-            AttrVec::new(),
-        )
+        self.expr(span, hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, e))
     }
 
     fn expr_unit(&mut self, sp: Span) -> &'hir hir::Expr<'hir> {
-        self.arena.alloc(self.expr(sp, hir::ExprKind::Tup(&[]), AttrVec::new()))
+        self.arena.alloc(self.expr(sp, hir::ExprKind::Tup(&[])))
     }
 
     fn expr_call_mut(
@@ -1802,7 +1782,7 @@ fn expr_call_mut(
         e: &'hir hir::Expr<'hir>,
         args: &'hir [hir::Expr<'hir>],
     ) -> hir::Expr<'hir> {
-        self.expr(span, hir::ExprKind::Call(e, args), AttrVec::new())
+        self.expr(span, hir::ExprKind::Call(e, args))
     }
 
     fn expr_call(
@@ -1821,8 +1801,7 @@ fn expr_call_lang_item_fn_mut(
         args: &'hir [hir::Expr<'hir>],
         hir_id: Option<hir::HirId>,
     ) -> hir::Expr<'hir> {
-        let path =
-            self.arena.alloc(self.expr_lang_item_path(span, lang_item, AttrVec::new(), hir_id));
+        let path = self.arena.alloc(self.expr_lang_item_path(span, lang_item, hir_id));
         self.expr_call_mut(span, path, args)
     }
 
@@ -1840,13 +1819,11 @@ fn expr_lang_item_path(
         &mut self,
         span: Span,
         lang_item: hir::LangItem,
-        attrs: AttrVec,
         hir_id: Option<hir::HirId>,
     ) -> hir::Expr<'hir> {
         self.expr(
             span,
             hir::ExprKind::Path(hir::QPath::LangItem(lang_item, self.lower_span(span), hir_id)),
-            attrs,
         )
     }
 
@@ -1860,20 +1837,10 @@ pub(super) fn expr_ident(
     }
 
     pub(super) fn expr_ident_mut(
-        &mut self,
-        sp: Span,
-        ident: Ident,
-        binding: hir::HirId,
-    ) -> hir::Expr<'hir> {
-        self.expr_ident_with_attrs(sp, ident, binding, AttrVec::new())
-    }
-
-    fn expr_ident_with_attrs(
         &mut self,
         span: Span,
         ident: Ident,
         binding: hir::HirId,
-        attrs: AttrVec,
     ) -> hir::Expr<'hir> {
         let hir_id = self.next_id();
         let res = Res::Local(binding);
@@ -1886,7 +1853,7 @@ fn expr_ident_with_attrs(
             }),
         ));
 
-        self.expr(span, expr_path, attrs)
+        self.expr(span, expr_path)
     }
 
     fn expr_unsafe(&mut self, expr: &'hir hir::Expr<'hir>) -> hir::Expr<'hir> {
@@ -1905,32 +1872,21 @@ fn expr_unsafe(&mut self, expr: &'hir hir::Expr<'hir>) -> hir::Expr<'hir> {
                 }),
                 None,
             ),
-            AttrVec::new(),
         )
     }
 
     fn expr_block_empty(&mut self, span: Span) -> &'hir hir::Expr<'hir> {
         let blk = self.block_all(span, &[], None);
-        let expr = self.expr_block(blk, AttrVec::new());
+        let expr = self.expr_block(blk);
         self.arena.alloc(expr)
     }
 
-    pub(super) fn expr_block(
-        &mut self,
-        b: &'hir hir::Block<'hir>,
-        attrs: AttrVec,
-    ) -> hir::Expr<'hir> {
-        self.expr(b.span, hir::ExprKind::Block(b, None), attrs)
+    pub(super) fn expr_block(&mut self, b: &'hir hir::Block<'hir>) -> hir::Expr<'hir> {
+        self.expr(b.span, hir::ExprKind::Block(b, None))
     }
 
-    pub(super) fn expr(
-        &mut self,
-        span: Span,
-        kind: hir::ExprKind<'hir>,
-        attrs: AttrVec,
-    ) -> hir::Expr<'hir> {
+    pub(super) fn expr(&mut self, span: Span, kind: hir::ExprKind<'hir>) -> hir::Expr<'hir> {
         let hir_id = self.next_id();
-        self.lower_attrs(hir_id, &attrs);
         hir::Expr { hir_id, kind, span: self.lower_span(span) }
     }
 
index 9eda48e93294bb8f496cdf859e27b8d51051950c..73065ab516350fe33c50fae50de39a228278340f 100644 (file)
@@ -796,7 +796,7 @@ fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef {
 
     /// Construct `ExprKind::Err` for the given `span`.
     pub(crate) fn expr_err(&mut self, span: Span) -> hir::Expr<'hir> {
-        self.expr(span, hir::ExprKind::Err, AttrVec::new())
+        self.expr(span, hir::ExprKind::Err)
     }
 
     fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> {
@@ -1139,7 +1139,7 @@ fn lower_maybe_async_body(
 
             let async_expr = this.make_async_expr(
                 CaptureBy::Value,
-                Some(fn_id),
+                fn_id,
                 closure_id,
                 None,
                 body.span,
@@ -1151,11 +1151,8 @@ fn lower_maybe_async_body(
                     // Transform into `drop-temps { <user-body> }`, an expression:
                     let desugared_span =
                         this.mark_span_with_reason(DesugaringKind::Async, user_body.span, None);
-                    let user_body = this.expr_drop_temps(
-                        desugared_span,
-                        this.arena.alloc(user_body),
-                        AttrVec::new(),
-                    );
+                    let user_body =
+                        this.expr_drop_temps(desugared_span, this.arena.alloc(user_body));
 
                     // As noted above, create the final block like
                     //
@@ -1172,14 +1169,11 @@ fn lower_maybe_async_body(
                         Some(user_body),
                     );
 
-                    this.expr_block(body, AttrVec::new())
+                    this.expr_block(body)
                 },
             );
 
-            (
-                this.arena.alloc_from_iter(parameters),
-                this.expr(body.span, async_expr, AttrVec::new()),
-            )
+            (this.arena.alloc_from_iter(parameters), this.expr(body.span, async_expr))
         })
     }
 
index 0258f8fd2d9ab12ad7b1cf45b0abad80b954f526..d67ede6e1302ef731017cf5f61d9ec7ab56dc87a 100644 (file)
@@ -259,6 +259,8 @@ enum ImplTraitContext {
     },
     /// Impl trait in type aliases.
     TypeAliasesOpaqueTy,
+    /// `impl Trait` is unstably accepted in this position.
+    FeatureGated(ImplTraitPosition, Symbol),
     /// `impl Trait` is not accepted in this position.
     Disallowed(ImplTraitPosition),
 }
@@ -454,8 +456,8 @@ pub fn lower_to_hir<'hir>(tcx: TyCtxt<'hir>, (): ()) -> hir::Crate<'hir> {
     }
 
     // Drop AST to free memory
-    std::mem::drop(ast_index);
-    sess.time("drop_ast", || std::mem::drop(krate));
+    drop(ast_index);
+    sess.time("drop_ast", || drop(krate));
 
     // Discard hygiene data, which isn't required after lowering to HIR.
     if !sess.opts.unstable_opts.keep_hygiene_data {
@@ -956,7 +958,8 @@ fn lower_attr_args(&self, args: &AttrArgs) -> AttrArgs {
                     lit
                 } else {
                     MetaItemLit {
-                        token_lit: token::Lit::new(token::LitKind::Err, kw::Empty, None),
+                        symbol: kw::Empty,
+                        suffix: None,
                         kind: LitKind::Err,
                         span: DUMMY_SP,
                     }
@@ -1372,17 +1375,15 @@ fn lower_ty_direct(&mut self, t: &Ty, itctx: &ImplTraitContext) -> hir::Ty<'hir>
                         }
                         path
                     }
-                    ImplTraitContext::Disallowed(
-                        position @ (ImplTraitPosition::TraitReturn | ImplTraitPosition::ImplReturn),
-                    ) => {
+                    ImplTraitContext::FeatureGated(position, feature) => {
                         self.tcx
                             .sess
                             .create_feature_err(
                                 MisplacedImplTrait {
                                     span: t.span,
-                                    position: DiagnosticArgFromDisplay(&position),
+                                    position: DiagnosticArgFromDisplay(position),
                                 },
-                                sym::return_position_impl_trait_in_trait,
+                                *feature,
                             )
                             .emit();
                         hir::TyKind::Err
@@ -1390,7 +1391,7 @@ fn lower_ty_direct(&mut self, t: &Ty, itctx: &ImplTraitContext) -> hir::Ty<'hir>
                     ImplTraitContext::Disallowed(position) => {
                         self.tcx.sess.emit_err(MisplacedImplTrait {
                             span: t.span,
-                            position: DiagnosticArgFromDisplay(&position),
+                            position: DiagnosticArgFromDisplay(position),
                         });
                         hir::TyKind::Err
                     }
@@ -1739,14 +1740,14 @@ fn lower_fn_decl(
         } else {
             match &decl.output {
                 FnRetTy::Ty(ty) => {
-                    let mut context = if kind.return_impl_trait_allowed(self.tcx) {
+                    let context = if kind.return_impl_trait_allowed(self.tcx) {
                         let fn_def_id = self.local_def_id(fn_node_id);
                         ImplTraitContext::ReturnPositionOpaqueTy {
                             origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
                             in_trait: matches!(kind, FnDeclKind::Trait),
                         }
                     } else {
-                        ImplTraitContext::Disallowed(match kind {
+                        let position = match kind {
                             FnDeclKind::Fn | FnDeclKind::Inherent => {
                                 unreachable!("fn should allow in-band lifetimes")
                             }
@@ -1755,9 +1756,16 @@ fn lower_fn_decl(
                             FnDeclKind::Pointer => ImplTraitPosition::PointerReturn,
                             FnDeclKind::Trait => ImplTraitPosition::TraitReturn,
                             FnDeclKind::Impl => ImplTraitPosition::ImplReturn,
-                        })
+                        };
+                        match kind {
+                            FnDeclKind::Trait | FnDeclKind::Impl => ImplTraitContext::FeatureGated(
+                                position,
+                                sym::return_position_impl_trait_in_trait,
+                            ),
+                            _ => ImplTraitContext::Disallowed(position),
+                        }
                     };
-                    hir::FnRetTy::Return(self.lower_ty(ty, &mut context))
+                    hir::FnRetTy::Return(self.lower_ty(ty, &context))
                 }
                 FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(*span)),
             }
@@ -1938,7 +1946,10 @@ fn lower_async_fn_ret_ty(
                     output,
                     span,
                     if in_trait && !this.tcx.features().return_position_impl_trait_in_trait {
-                        ImplTraitContext::Disallowed(ImplTraitPosition::TraitReturn)
+                        ImplTraitContext::FeatureGated(
+                            ImplTraitPosition::TraitReturn,
+                            sym::return_position_impl_trait_in_trait,
+                        )
                     } else {
                         ImplTraitContext::ReturnPositionOpaqueTy {
                             origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
@@ -2291,7 +2302,7 @@ fn lower_generic_and_bounds(
     /// has no attributes and is not targeted by a `break`.
     fn lower_block_expr(&mut self, b: &Block) -> hir::Expr<'hir> {
         let block = self.lower_block(b, false);
-        self.expr_block(block, AttrVec::new())
+        self.expr_block(block)
     }
 
     fn lower_array_length(&mut self, c: &AnonConst) -> hir::ArrayLen {
index 8d23c26e603b77bf035aded708af0676d47dff59..592fc5aa6456f064e0d399f5a0c1487067f147ce 100644 (file)
@@ -9,7 +9,7 @@
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, PartialRes, Res};
 use rustc_hir::GenericArg;
-use rustc_span::symbol::{kw, Ident};
+use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{BytePos, Span, DUMMY_SP};
 
 use smallvec::{smallvec, SmallVec};
@@ -352,11 +352,18 @@ fn lower_parenthesized_parameter_data(
             // fn f(_: impl Fn() -> impl Debug) -> impl Fn() -> impl Debug
             // //      disallowed --^^^^^^^^^^        allowed --^^^^^^^^^^
             // ```
-            FnRetTy::Ty(ty)
-                if matches!(itctx, ImplTraitContext::ReturnPositionOpaqueTy { .. })
-                    && self.tcx.features().impl_trait_in_fn_trait_return =>
-            {
-                self.lower_ty(&ty, itctx)
+            FnRetTy::Ty(ty) if matches!(itctx, ImplTraitContext::ReturnPositionOpaqueTy { .. }) => {
+                if self.tcx.features().impl_trait_in_fn_trait_return {
+                    self.lower_ty(&ty, itctx)
+                } else {
+                    self.lower_ty(
+                        &ty,
+                        &ImplTraitContext::FeatureGated(
+                            ImplTraitPosition::FnTraitReturn,
+                            sym::impl_trait_in_fn_trait_return,
+                        ),
+                    )
+                }
             }
             FnRetTy::Ty(ty) => {
                 self.lower_ty(&ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn))
index eb9c841d80c16b05a74f3f0e7be3404b5c59a974..55ea12d25ea2ceead70b4c4e6c4de49548a84852 100644 (file)
@@ -42,7 +42,6 @@ enum SelfSemantic {
 /// What is the context that prevents using `~const`?
 enum DisallowTildeConstContext<'a> {
     TraitObject,
-    ImplTrait,
     Fn(FnKind<'a>),
 }
 
@@ -187,11 +186,7 @@ fn with_banned_assoc_ty_bound(&mut self, f: impl FnOnce(&mut Self)) {
 
     fn with_impl_trait(&mut self, outer: Option<Span>, f: impl FnOnce(&mut Self)) {
         let old = mem::replace(&mut self.outer_impl_trait, outer);
-        if outer.is_some() {
-            self.with_banned_tilde_const(DisallowTildeConstContext::ImplTrait, f);
-        } else {
-            f(self);
-        }
+        f(self);
         self.outer_impl_trait = old;
     }
 
@@ -1384,7 +1379,6 @@ fn visit_param_bound(&mut self, bound: &'a GenericBound, ctxt: BoundKind) {
                     let mut err = self.err_handler().struct_span_err(bound.span(), "`~const` is not allowed here");
                     match reason {
                         DisallowTildeConstContext::TraitObject => err.note("trait objects cannot have `~const` trait bounds"),
-                        DisallowTildeConstContext::ImplTrait => err.note("`impl Trait`s cannot have `~const` trait bounds"),
                         DisallowTildeConstContext::Fn(FnKind::Closure(..)) => err.note("closures cannot have `~const` trait bounds"),
                         DisallowTildeConstContext::Fn(FnKind::Fn(_, ident, ..)) => err.span_note(ident.span, "this function is not `const`, so it cannot have `~const` trait bounds"),
                     };
index 32f45f8b59e90a4050a7a41fb525d93ed9609ae5..039338f543cc591b19b88055b80f6888d47a9310 100644 (file)
@@ -630,7 +630,7 @@ fn check_incompatible_features(sess: &Session) {
             {
                 let spans = vec![f1_span, f2_span];
                 sess.struct_span_err(
-                    spans.clone(),
+                    spans,
                     &format!(
                         "features `{}` and `{}` are incompatible, using them at the same time \
                         is not allowed",
index d3d8431c163c728efa42dd52a248c6f692271a84..d0e4761a10db8978519b3326d5718ead15bf29b7 100644 (file)
@@ -376,7 +376,7 @@ fn print_remaining_comments(&mut self) {
     }
 
     fn print_meta_item_lit(&mut self, lit: &ast::MetaItemLit) {
-        self.print_token_literal(lit.token_lit, lit.span)
+        self.print_token_literal(lit.as_token_lit(), lit.span)
     }
 
     fn print_token_literal(&mut self, token_lit: token::Lit, span: Span) {
index 4ed16e337d297483ce5cec9d914ef69c03313a10..3b17f6dd627ebb15eeebb66b0ab4d4730b22aeaf 100644 (file)
@@ -2,6 +2,8 @@
 use crate::pprust::state::{AnnNode, IterDelimited, PrintState, State, INDENT_UNIT};
 
 use rustc_ast::ptr::P;
+use rustc_ast::token;
+use rustc_ast::util::literal::escape_byte_str_symbol;
 use rustc_ast::util::parser::{self, AssocOp, Fixity};
 use rustc_ast::{self as ast, BlockCheckMode};
 
@@ -323,7 +325,7 @@ pub(super) fn print_expr_outer_attr_style(&mut self, expr: &ast::Expr, is_inline
                 self.print_token_literal(*token_lit, expr.span);
             }
             ast::ExprKind::IncludedBytes(bytes) => {
-                let lit = ast::LitKind::ByteStr(bytes.clone()).to_token_lit();
+                let lit = token::Lit::new(token::ByteStr, escape_byte_str_symbol(bytes), None);
                 self.print_token_literal(lit, expr.span)
             }
             ast::ExprKind::Cast(expr, ty) => {
index 13b48d8f89ab4a6eea6f60a986d88369be7235d4..ab5e19050ead2ffbb0a0d475c69d985ec86fb588 100644 (file)
@@ -277,8 +277,7 @@ fn find_stability_generic<'a, I>(
             allowed_through_unstable_modules = true;
         }
         // attributes with data
-        else if let Some(MetaItem { kind: MetaItemKind::List(ref metas), .. }) = meta {
-            let meta = meta.as_ref().unwrap();
+        else if let Some(meta @ MetaItem { kind: MetaItemKind::List(metas), .. }) = &meta {
             let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
                 if item.is_some() {
                     handle_errors(
@@ -533,25 +532,24 @@ fn find_stability_generic<'a, I>(
 
     // Merge the const-unstable info into the stability info
     if promotable {
-        if let Some((ref mut stab, _)) = const_stab {
-            stab.promotable = promotable;
-        } else {
-            sess.emit_err(session_diagnostics::RustcPromotablePairing { span: item_sp });
+        match &mut const_stab {
+            Some((stab, _)) => stab.promotable = promotable,
+            _ => _ = sess.emit_err(session_diagnostics::RustcPromotablePairing { span: item_sp }),
         }
     }
 
     if allowed_through_unstable_modules {
-        if let Some((
-            Stability {
-                level: StabilityLevel::Stable { ref mut allowed_through_unstable_modules, .. },
-                ..
-            },
-            _,
-        )) = stab
-        {
-            *allowed_through_unstable_modules = true;
-        } else {
-            sess.emit_err(session_diagnostics::RustcAllowedUnstablePairing { span: item_sp });
+        match &mut stab {
+            Some((
+                Stability {
+                    level: StabilityLevel::Stable { allowed_through_unstable_modules, .. },
+                    ..
+                },
+                _,
+            )) => *allowed_through_unstable_modules = true,
+            _ => {
+                sess.emit_err(session_diagnostics::RustcAllowedUnstablePairing { span: item_sp });
+            }
         }
     }
 
@@ -654,8 +652,8 @@ pub fn eval_condition(
     features: Option<&Features>,
     eval: &mut impl FnMut(Condition) -> bool,
 ) -> bool {
-    match cfg.kind {
-        ast::MetaItemKind::List(ref mis) if cfg.name_or_empty() == sym::version => {
+    match &cfg.kind {
+        ast::MetaItemKind::List(mis) if cfg.name_or_empty() == sym::version => {
             try_gate_cfg(sym::version, cfg.span, sess, features);
             let (min_version, span) = match &mis[..] {
                 [NestedMetaItem::Lit(MetaItemLit { kind: LitKind::Str(sym, ..), span, .. })] => {
@@ -688,7 +686,7 @@ pub fn eval_condition(
                 rustc_version >= min_version
             }
         }
-        ast::MetaItemKind::List(ref mis) => {
+        ast::MetaItemKind::List(mis) => {
             for mi in mis.iter() {
                 if !mi.is_meta_item() {
                     handle_errors(
@@ -759,7 +757,7 @@ pub fn eval_condition(
             sess.emit_err(session_diagnostics::CfgPredicateIdentifier { span: cfg.path.span });
             true
         }
-        MetaItemKind::NameValue(ref lit) if !lit.kind.is_str() => {
+        MetaItemKind::NameValue(lit) if !lit.kind.is_str() => {
             handle_errors(
                 sess,
                 lit.span,
@@ -1036,52 +1034,58 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
                     });
                 }
             } else if let Some(meta_item) = item.meta_item() {
-                if let MetaItemKind::NameValue(ref value) = meta_item.kind {
-                    if meta_item.has_name(sym::align) || meta_item.has_name(sym::packed) {
-                        let name = meta_item.name_or_empty().to_ident_string();
-                        recognised = true;
-                        sess.emit_err(session_diagnostics::IncorrectReprFormatGeneric {
-                            span: item.span(),
-                            repr_arg: &name,
-                            cause: IncorrectReprFormatGenericCause::from_lit_kind(
-                                item.span(),
-                                &value.kind,
-                                &name,
-                            ),
-                        });
-                    } else if matches!(
-                        meta_item.name_or_empty(),
-                        sym::C | sym::simd | sym::transparent
-                    ) || int_type_of_word(meta_item.name_or_empty()).is_some()
-                    {
-                        recognised = true;
-                        sess.emit_err(session_diagnostics::InvalidReprHintNoValue {
-                            span: meta_item.span,
-                            name: meta_item.name_or_empty().to_ident_string(),
-                        });
+                match &meta_item.kind {
+                    MetaItemKind::NameValue(value) => {
+                        if meta_item.has_name(sym::align) || meta_item.has_name(sym::packed) {
+                            let name = meta_item.name_or_empty().to_ident_string();
+                            recognised = true;
+                            sess.emit_err(session_diagnostics::IncorrectReprFormatGeneric {
+                                span: item.span(),
+                                repr_arg: &name,
+                                cause: IncorrectReprFormatGenericCause::from_lit_kind(
+                                    item.span(),
+                                    &value.kind,
+                                    &name,
+                                ),
+                            });
+                        } else if matches!(
+                            meta_item.name_or_empty(),
+                            sym::C | sym::simd | sym::transparent
+                        ) || int_type_of_word(meta_item.name_or_empty()).is_some()
+                        {
+                            recognised = true;
+                            sess.emit_err(session_diagnostics::InvalidReprHintNoValue {
+                                span: meta_item.span,
+                                name: meta_item.name_or_empty().to_ident_string(),
+                            });
+                        }
                     }
-                } else if let MetaItemKind::List(_) = meta_item.kind {
-                    if meta_item.has_name(sym::align) {
-                        recognised = true;
-                        sess.emit_err(session_diagnostics::IncorrectReprFormatAlignOneArg {
-                            span: meta_item.span,
-                        });
-                    } else if meta_item.has_name(sym::packed) {
-                        recognised = true;
-                        sess.emit_err(session_diagnostics::IncorrectReprFormatPackedOneOrZeroArg {
-                            span: meta_item.span,
-                        });
-                    } else if matches!(
-                        meta_item.name_or_empty(),
-                        sym::C | sym::simd | sym::transparent
-                    ) || int_type_of_word(meta_item.name_or_empty()).is_some()
-                    {
-                        recognised = true;
-                        sess.emit_err(session_diagnostics::InvalidReprHintNoParen {
-                            span: meta_item.span,
-                            name: meta_item.name_or_empty().to_ident_string(),
-                        });
+                    MetaItemKind::List(_) => {
+                        if meta_item.has_name(sym::align) {
+                            recognised = true;
+                            sess.emit_err(session_diagnostics::IncorrectReprFormatAlignOneArg {
+                                span: meta_item.span,
+                            });
+                        } else if meta_item.has_name(sym::packed) {
+                            recognised = true;
+                            sess.emit_err(
+                                session_diagnostics::IncorrectReprFormatPackedOneOrZeroArg {
+                                    span: meta_item.span,
+                                },
+                            );
+                        } else if matches!(
+                            meta_item.name_or_empty(),
+                            sym::C | sym::simd | sym::transparent
+                        ) || int_type_of_word(meta_item.name_or_empty()).is_some()
+                        {
+                            recognised = true;
+                            sess.emit_err(session_diagnostics::InvalidReprHintNoParen {
+                                span: meta_item.span,
+                                name: meta_item.name_or_empty().to_ident_string(),
+                            });
+                        }
                     }
+                    _ => (),
                 }
             }
             if !recognised {
index 563ff056ae467245b67f5bacee32f7c2b5817ff0..5bb92a3582612f829cadce85e1b52118f4047916 100644 (file)
@@ -198,7 +198,7 @@ fn visit_assign(
         rvalue: &mir::Rvalue<'tcx>,
         location: mir::Location,
     ) {
-        if let mir::Rvalue::Ref(region, kind, ref borrowed_place) = *rvalue {
+        if let &mir::Rvalue::Ref(region, kind, borrowed_place) = rvalue {
             if borrowed_place.ignore_borrow(self.tcx, self.body, &self.locals_state_at_exit) {
                 debug!("ignoring_borrow of {:?}", borrowed_place);
                 return;
@@ -211,7 +211,7 @@ fn visit_assign(
                 region,
                 reserve_location: location,
                 activation_location: TwoPhaseActivation::NotTwoPhase,
-                borrowed_place: *borrowed_place,
+                borrowed_place,
                 assigned_place: *assigned_place,
             };
             let (idx, _) = self.location_map.insert_full(location, borrow);
@@ -273,14 +273,14 @@ fn visit_local(&mut self, temp: Local, context: PlaceContext, location: Location
     }
 
     fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: mir::Location) {
-        if let mir::Rvalue::Ref(region, kind, ref place) = *rvalue {
+        if let &mir::Rvalue::Ref(region, kind, place) = rvalue {
             // double-check that we already registered a BorrowData for this
 
             let borrow_data = &self.location_map[&location];
             assert_eq!(borrow_data.reserve_location, location);
             assert_eq!(borrow_data.kind, kind);
             assert_eq!(borrow_data.region, region.to_region_vid());
-            assert_eq!(borrow_data.borrowed_place, *place);
+            assert_eq!(borrow_data.borrowed_place, place);
         }
 
         self.super_rvalue(rvalue, location)
index 8070c0e6710ee0e1288cb9a0284fab5d47f8617f..f825b1d8f70ef502952699fe81e4aecf57edb849 100644 (file)
@@ -358,9 +358,9 @@ fn statement_effect(
         stmt: &mir::Statement<'tcx>,
         location: Location,
     ) {
-        match stmt.kind {
-            mir::StatementKind::Assign(box (lhs, ref rhs)) => {
-                if let mir::Rvalue::Ref(_, _, place) = *rhs {
+        match &stmt.kind {
+            mir::StatementKind::Assign(box (lhs, rhs)) => {
+                if let mir::Rvalue::Ref(_, _, place) = rhs {
                     if place.ignore_borrow(
                         self.tcx,
                         self.body,
@@ -377,13 +377,13 @@ fn statement_effect(
 
                 // Make sure there are no remaining borrows for variables
                 // that are assigned over.
-                self.kill_borrows_on_place(trans, lhs);
+                self.kill_borrows_on_place(trans, *lhs);
             }
 
             mir::StatementKind::StorageDead(local) => {
                 // Make sure there are no remaining borrows for locals that
                 // are gone out of scope.
-                self.kill_borrows_on_place(trans, Place::from(local));
+                self.kill_borrows_on_place(trans, Place::from(*local));
             }
 
             mir::StatementKind::FakeRead(..)
index e05566dc2c745151833d3523ca1b60d6682f964f..1550958ab8eee3942710ba5103fab472f560fa02 100644 (file)
@@ -243,9 +243,9 @@ fn nice_error(
         placeholder_region: ty::Region<'tcx>,
         error_region: Option<ty::Region<'tcx>>,
     ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
-        let (ref infcx, key, _) =
+        let (infcx, key, _) =
             mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
-        let ocx = ObligationCtxt::new(infcx);
+        let ocx = ObligationCtxt::new(&infcx);
         type_op_prove_predicate_with_cause(&ocx, key, cause);
         try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region)
     }
@@ -284,9 +284,9 @@ fn nice_error(
         placeholder_region: ty::Region<'tcx>,
         error_region: Option<ty::Region<'tcx>>,
     ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
-        let (ref infcx, key, _) =
+        let (infcx, key, _) =
             mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
-        let ocx = ObligationCtxt::new(infcx);
+        let ocx = ObligationCtxt::new(&infcx);
 
         // FIXME(lqd): Unify and de-duplicate the following with the actual
         // `rustc_traits::type_op::type_op_normalize` query to allow the span we need in the
@@ -328,9 +328,9 @@ fn nice_error(
         placeholder_region: ty::Region<'tcx>,
         error_region: Option<ty::Region<'tcx>>,
     ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
-        let (ref infcx, key, _) =
+        let (infcx, key, _) =
             mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
-        let ocx = ObligationCtxt::new(infcx);
+        let ocx = ObligationCtxt::new(&infcx);
         type_op_ascribe_user_type_with_span(&ocx, key, Some(cause.span)).ok()?;
         try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region)
     }
index d221da5c17ed0bd31d20d107933e548b89df2744..72c0257756ef2f15d1adfdc8f47a2e143ced6ccc 100644 (file)
@@ -265,7 +265,7 @@ pub(crate) fn report_use_of_moved_or_uninitialized(
                 DescribePlaceOpt { including_downcast: true, including_tuple_field: true },
             );
             let note_msg = match opt_name {
-                Some(ref name) => format!("`{}`", name),
+                Some(name) => format!("`{}`", name),
                 None => "value".to_owned(),
             };
             if self.suggest_borrow_fn_like(&mut err, ty, &move_site_vec, &note_msg) {
@@ -697,8 +697,8 @@ fn suggest_borrow_fn_like(
                     .map_bound(|p| p.predicates),
                 None,
             ),
-            ty::Opaque(did, substs) => {
-                find_fn_kind_from_did(tcx.bound_explicit_item_bounds(*did), Some(*substs))
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
+                find_fn_kind_from_did(tcx.bound_explicit_item_bounds(*def_id), Some(*substs))
             }
             ty::Closure(_, substs) => match substs.as_closure().kind() {
                 ty::ClosureKind::Fn => Some(hir::Mutability::Not),
@@ -745,7 +745,7 @@ fn suggest_cloning(&self, err: &mut Diagnostic, ty: Ty<'tcx>, span: Span) {
             err.span_suggestion_verbose(
                 span.shrink_to_hi(),
                 "consider cloning the value if the performance cost is acceptable",
-                ".clone()".to_string(),
+                ".clone()",
                 Applicability::MachineApplicable,
             );
         }
@@ -1417,7 +1417,7 @@ pub(crate) fn report_borrowed_value_does_not_live_long_enough(
             // then just use the normal error. The closure isn't escaping
             // and `move` will not help here.
             (
-                Some(ref name),
+                Some(name),
                 BorrowExplanation::MustBeValidFor {
                     category:
                         category @ (ConstraintCategory::Return(_)
@@ -1438,7 +1438,7 @@ pub(crate) fn report_borrowed_value_does_not_live_long_enough(
                     &format!("`{}`", name),
                 ),
             (
-                ref name,
+                name,
                 BorrowExplanation::MustBeValidFor {
                     category: ConstraintCategory::Assignment,
                     from_closure: false,
@@ -1450,7 +1450,7 @@ pub(crate) fn report_borrowed_value_does_not_live_long_enough(
                     span,
                     ..
                 },
-            ) => self.report_escaping_data(borrow_span, name, upvar_span, upvar_name, span),
+            ) => self.report_escaping_data(borrow_span, &name, upvar_span, upvar_name, span),
             (Some(name), explanation) => self.report_local_value_does_not_live_long_enough(
                 location,
                 &name,
@@ -2452,7 +2452,7 @@ fn annotate_argument_and_return_for_borrow(
         // and it'll make sense.
         let location = borrow.reserve_location;
         debug!("annotate_argument_and_return_for_borrow: location={:?}", location);
-        if let Some(&Statement { kind: StatementKind::Assign(box (ref reservation, _)), .. }) =
+        if let Some(Statement { kind: StatementKind::Assign(box (reservation, _)), .. }) =
             &self.body[location.block].statements.get(location.statement_index)
         {
             debug!("annotate_argument_and_return_for_borrow: reservation={:?}", reservation);
@@ -2480,8 +2480,8 @@ fn annotate_argument_and_return_for_borrow(
                         // Check if our `target` was captured by a closure.
                         if let Rvalue::Aggregate(
                             box AggregateKind::Closure(def_id, substs),
-                            ref operands,
-                        ) = *rvalue
+                            operands,
+                        ) = rvalue
                         {
                             for operand in operands {
                                 let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) = operand else {
@@ -2505,7 +2505,7 @@ fn annotate_argument_and_return_for_borrow(
                                 // into a place then we should annotate the closure in
                                 // case it ends up being assigned into the return place.
                                 annotated_closure =
-                                    self.annotate_fn_sig(def_id, substs.as_closure().sig());
+                                    self.annotate_fn_sig(*def_id, substs.as_closure().sig());
                                 debug!(
                                     "annotate_argument_and_return_for_borrow: \
                                      annotated_closure={:?} assigned_from_local={:?} \
index 582d683dd359320679164d3aff5c75991122b2a7..304683618d83ef9dc531c7fcb7f7ed91ed329a7f 100644 (file)
@@ -469,8 +469,8 @@ fn later_use_kind(
                 } else if self.was_captured_by_trait_object(borrow) {
                     LaterUseKind::TraitCapture
                 } else if location.statement_index == block.statements.len() {
-                    if let TerminatorKind::Call { ref func, from_hir_call: true, .. } =
-                        block.terminator().kind
+                    if let TerminatorKind::Call { func, from_hir_call: true, .. } =
+                        &block.terminator().kind
                     {
                         // Just point to the function, to reduce the chance of overlapping spans.
                         let function_span = match func {
@@ -515,19 +515,16 @@ fn was_captured_by_trait_object(&self, borrow: &BorrowData<'tcx>) -> bool {
         // will only ever have one item at any given time, but by using a vector, we can pop from
         // it which simplifies the termination logic.
         let mut queue = vec![location];
-        let mut target = if let Some(&Statement {
-            kind: StatementKind::Assign(box (ref place, _)),
-            ..
-        }) = stmt
-        {
-            if let Some(local) = place.as_local() {
-                local
+        let mut target =
+            if let Some(Statement { kind: StatementKind::Assign(box (place, _)), .. }) = stmt {
+                if let Some(local) = place.as_local() {
+                    local
+                } else {
+                    return false;
+                }
             } else {
                 return false;
-            }
-        } else {
-            return false;
-        };
+            };
 
         debug!("was_captured_by_trait: target={:?} queue={:?}", target, queue);
         while let Some(current_location) = queue.pop() {
index 86c5d9cfa8121c6885338bd6e0e8765795c151bf..cbd590052008c14a46f3ab0b099ea517ef6f7ce9 100644 (file)
@@ -78,7 +78,7 @@ pub(super) fn add_moved_or_invoked_closure_note(
             if let StatementKind::Assign(box (into, Rvalue::Use(from))) = &stmt.kind {
                 debug!("add_fnonce_closure_note: into={:?} from={:?}", into, from);
                 match from {
-                    Operand::Copy(ref place) | Operand::Move(ref place)
+                    Operand::Copy(place) | Operand::Move(place)
                         if target == place.local_or_deref_local() =>
                     {
                         target = into.local_or_deref_local()
@@ -101,7 +101,7 @@ pub(super) fn add_moved_or_invoked_closure_note(
                 debug!("add_moved_or_invoked_closure_note: id={:?}", id);
                 if Some(self.infcx.tcx.parent(id)) == self.infcx.tcx.lang_items().fn_once_trait() {
                     let closure = match args.first() {
-                        Some(Operand::Copy(ref place)) | Some(Operand::Move(ref place))
+                        Some(Operand::Copy(place) | Operand::Move(place))
                             if target == place.local_or_deref_local() =>
                         {
                             place.local_or_deref_local().unwrap()
@@ -439,9 +439,9 @@ pub(super) fn borrowed_content_source(
                     if !is_terminator {
                         continue;
                     } else if let Some(Terminator {
-                        kind: TerminatorKind::Call { ref func, from_hir_call: false, .. },
+                        kind: TerminatorKind::Call { func, from_hir_call: false, .. },
                         ..
-                    }) = bbd.terminator
+                    }) = &bbd.terminator
                     {
                         if let Some(source) =
                             BorrowedContentSource::from_call(func.ty(self.body, tcx), tcx)
@@ -811,33 +811,30 @@ pub(super) fn move_spans(
         };
 
         debug!("move_spans: moved_place={:?} location={:?} stmt={:?}", moved_place, location, stmt);
-        if let StatementKind::Assign(box (_, Rvalue::Aggregate(ref kind, ref places))) = stmt.kind {
-            match **kind {
-                AggregateKind::Closure(def_id, _) | AggregateKind::Generator(def_id, _, _) => {
-                    debug!("move_spans: def_id={:?} places={:?}", def_id, places);
-                    if let Some((args_span, generator_kind, capture_kind_span, path_span)) =
-                        self.closure_span(def_id, moved_place, places)
-                    {
-                        return ClosureUse {
-                            generator_kind,
-                            args_span,
-                            capture_kind_span,
-                            path_span,
-                        };
-                    }
-                }
-                _ => {}
+        if let StatementKind::Assign(box (_, Rvalue::Aggregate(kind, places))) = &stmt.kind
+            && let AggregateKind::Closure(def_id, _) | AggregateKind::Generator(def_id, _, _) = **kind
+        {
+            debug!("move_spans: def_id={:?} places={:?}", def_id, places);
+            if let Some((args_span, generator_kind, capture_kind_span, path_span)) =
+                self.closure_span(def_id, moved_place, places)
+            {
+                return ClosureUse {
+                    generator_kind,
+                    args_span,
+                    capture_kind_span,
+                    path_span,
+                };
             }
         }
 
         // StatementKind::FakeRead only contains a def_id if they are introduced as a result
         // of pattern matching within a closure.
-        if let StatementKind::FakeRead(box (cause, ref place)) = stmt.kind {
+        if let StatementKind::FakeRead(box (cause, place)) = stmt.kind {
             match cause {
                 FakeReadCause::ForMatchedPlace(Some(closure_def_id))
                 | FakeReadCause::ForLet(Some(closure_def_id)) => {
                     debug!("move_spans: def_id={:?} place={:?}", closure_def_id, place);
-                    let places = &[Operand::Move(*place)];
+                    let places = &[Operand::Move(place)];
                     if let Some((args_span, generator_kind, capture_kind_span, path_span)) =
                         self.closure_span(closure_def_id, moved_place, places)
                     {
@@ -924,7 +921,7 @@ pub(super) fn borrow_spans(&self, use_span: Span, location: Location) -> UseSpan
         debug!("borrow_spans: use_span={:?} location={:?}", use_span, location);
 
         let target = match self.body[location.block].statements.get(location.statement_index) {
-            Some(&Statement { kind: StatementKind::Assign(box (ref place, _)), .. }) => {
+            Some(Statement { kind: StatementKind::Assign(box (place, _)), .. }) => {
                 if let Some(local) = place.as_local() {
                     local
                 } else {
@@ -940,9 +937,7 @@ pub(super) fn borrow_spans(&self, use_span: Span, location: Location) -> UseSpan
         }
 
         for stmt in &self.body[location.block].statements[location.statement_index + 1..] {
-            if let StatementKind::Assign(box (_, Rvalue::Aggregate(ref kind, ref places))) =
-                stmt.kind
-            {
+            if let StatementKind::Assign(box (_, Rvalue::Aggregate(kind, places))) = &stmt.kind {
                 let (&def_id, is_generator) = match kind {
                     box AggregateKind::Closure(def_id, _) => (def_id, false),
                     box AggregateKind::Generator(def_id, _, _) => (def_id, true),
@@ -1064,17 +1059,12 @@ fn explain_captures(
                     );
                     if self.fn_self_span_reported.insert(fn_span) {
                         err.span_note(
-                            // Check whether the source is accessible
-                            if self.infcx.tcx.sess.source_map().is_span_accessible(self_arg.span) {
-                                self_arg.span
-                            } else {
-                                fn_call_span
-                            },
+                            self_arg.span,
                             "calling this operator moves the left-hand side",
                         );
                     }
                 }
-                CallKind::Normal { self_arg, desugaring, is_option_or_result } => {
+                CallKind::Normal { self_arg, desugaring, method_did } => {
                     let self_arg = self_arg.unwrap();
                     if let Some((CallDesugaringKind::ForLoopIntoIter, _)) = desugaring {
                         let ty = moved_place.ty(self.body, self.infcx.tcx).ty;
@@ -1144,14 +1134,27 @@ fn explain_captures(
                             ),
                         );
                     }
+                    let tcx = self.infcx.tcx;
                     // Avoid pointing to the same function in multiple different
                     // error messages.
                     if span != DUMMY_SP && self.fn_self_span_reported.insert(self_arg.span) {
+                        let func = tcx.def_path_str(method_did);
                         err.span_note(
                             self_arg.span,
-                            &format!("this function takes ownership of the receiver `self`, which moves {}", place_name)
+                            &format!("`{func}` takes ownership of the receiver `self`, which moves {place_name}")
                         );
                     }
+                    let parent_did = tcx.parent(method_did);
+                    let parent_self_ty = (tcx.def_kind(parent_did)
+                        == rustc_hir::def::DefKind::Impl)
+                        .then_some(parent_did)
+                        .and_then(|did| match tcx.type_of(did).kind() {
+                            ty::Adt(def, ..) => Some(def.did()),
+                            _ => None,
+                        });
+                    let is_option_or_result = parent_self_ty.map_or(false, |def_id| {
+                        matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result))
+                    });
                     if is_option_or_result && maybe_reinitialized_locations_is_empty {
                         err.span_label(
                             var_span,
index 5a47f45677ecbfd1b546f4f74f5ec83e833687cf..6db3c858ae7149b9a138dbd77c7813c3eeea298e 100644 (file)
@@ -4,7 +4,7 @@
 use rustc_mir_dataflow::move_paths::{
     IllegalMoveOrigin, IllegalMoveOriginKind, LookupResult, MoveError, MovePathIndex,
 };
-use rustc_span::Span;
+use rustc_span::{BytePos, Span};
 
 use crate::diagnostics::{DescribePlaceOpt, UseSpans};
 use crate::prefixes::PrefixSet;
@@ -148,7 +148,7 @@ fn append_binding_error(
         match_span: Span,
         statement_span: Span,
     ) {
-        debug!("append_binding_error(match_place={:?}, match_span={:?})", match_place, match_span);
+        debug!(?match_place, ?match_span, "append_binding_error");
 
         let from_simple_let = match_place.is_none();
         let match_place = match_place.unwrap_or(move_from);
@@ -160,7 +160,7 @@ fn append_binding_error(
                     if let GroupedMoveError::MovesFromPlace { span, binds_to, .. } = ge
                         && match_span == *span
                     {
-                        debug!("appending local({:?}) to list", bind_to);
+                        debug!("appending local({bind_to:?}) to list");
                         if !binds_to.is_empty() {
                             binds_to.push(bind_to);
                         }
@@ -198,7 +198,7 @@ fn append_binding_error(
                     } = ge
                     {
                         if match_span == *span && mpi == *other_mpi {
-                            debug!("appending local({:?}) to list", bind_to);
+                            debug!("appending local({bind_to:?}) to list");
                             binds_to.push(bind_to);
                             return;
                         }
@@ -410,15 +410,7 @@ fn report_cannot_move_from_borrowed_content(
     fn add_move_hints(&self, error: GroupedMoveError<'tcx>, err: &mut Diagnostic, span: Span) {
         match error {
             GroupedMoveError::MovesFromPlace { mut binds_to, move_from, .. } => {
-                if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) {
-                    err.span_suggestion(
-                        span,
-                        "consider borrowing here",
-                        format!("&{snippet}"),
-                        Applicability::Unspecified,
-                    );
-                }
-
+                self.add_borrow_suggestions(err, span);
                 if binds_to.is_empty() {
                     let place_ty = move_from.ty(self.body, self.infcx.tcx).ty;
                     let place_desc = match self.describe_place(move_from.as_ref()) {
@@ -461,39 +453,75 @@ fn add_move_hints(&self, error: GroupedMoveError<'tcx>, err: &mut Diagnostic, sp
         }
     }
 
+    fn add_borrow_suggestions(&self, err: &mut Diagnostic, span: Span) {
+        match self.infcx.tcx.sess.source_map().span_to_snippet(span) {
+            Ok(snippet) if snippet.starts_with('*') => {
+                err.span_suggestion_verbose(
+                    span.with_hi(span.lo() + BytePos(1)),
+                    "consider removing the dereference here",
+                    String::new(),
+                    Applicability::MaybeIncorrect,
+                );
+            }
+            _ => {
+                err.span_suggestion_verbose(
+                    span.shrink_to_lo(),
+                    "consider borrowing here",
+                    "&".to_string(),
+                    Applicability::MaybeIncorrect,
+                );
+            }
+        }
+    }
+
     fn add_move_error_suggestions(&self, err: &mut Diagnostic, binds_to: &[Local]) {
-        let mut suggestions: Vec<(Span, &str, String)> = Vec::new();
+        let mut suggestions: Vec<(Span, String, String)> = Vec::new();
         for local in binds_to {
             let bind_to = &self.body.local_decls[*local];
             if let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
                 VarBindingForm { pat_span, .. },
             )))) = bind_to.local_info
             {
-                if let Ok(pat_snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(pat_span)
+                let Ok(pat_snippet) =
+                    self.infcx.tcx.sess.source_map().span_to_snippet(pat_span) else { continue; };
+                let Some(stripped) = pat_snippet.strip_prefix('&') else {
+                    suggestions.push((
+                        bind_to.source_info.span.shrink_to_lo(),
+                        "consider borrowing the pattern binding".to_string(),
+                        "ref ".to_string(),
+                    ));
+                    continue;
+                };
+                let inner_pat_snippet = stripped.trim_start();
+                let (pat_span, suggestion, to_remove) = if inner_pat_snippet.starts_with("mut")
+                    && inner_pat_snippet["mut".len()..].starts_with(rustc_lexer::is_whitespace)
                 {
-                    if let Some(stripped) = pat_snippet.strip_prefix('&') {
-                        let pat_snippet = stripped.trim_start();
-                        let (suggestion, to_remove) = if pat_snippet.starts_with("mut")
-                            && pat_snippet["mut".len()..].starts_with(rustc_lexer::is_whitespace)
-                        {
-                            (pat_snippet["mut".len()..].trim_start(), "&mut")
-                        } else {
-                            (pat_snippet, "&")
-                        };
-                        suggestions.push((pat_span, to_remove, suggestion.to_owned()));
-                    }
-                }
+                    let inner_pat_snippet = inner_pat_snippet["mut".len()..].trim_start();
+                    let pat_span = pat_span.with_hi(
+                        pat_span.lo()
+                            + BytePos((pat_snippet.len() - inner_pat_snippet.len()) as u32),
+                    );
+                    (pat_span, String::new(), "mutable borrow")
+                } else {
+                    let pat_span = pat_span.with_hi(
+                        pat_span.lo()
+                            + BytePos(
+                                (pat_snippet.len() - inner_pat_snippet.trim_start().len()) as u32,
+                            ),
+                    );
+                    (pat_span, String::new(), "borrow")
+                };
+                suggestions.push((
+                    pat_span,
+                    format!("consider removing the {to_remove}"),
+                    suggestion.to_string(),
+                ));
             }
         }
         suggestions.sort_unstable_by_key(|&(span, _, _)| span);
         suggestions.dedup_by_key(|&mut (span, _, _)| span);
-        for (span, to_remove, suggestion) in suggestions {
-            err.span_suggestion(
-                span,
-                &format!("consider removing the `{to_remove}`"),
-                suggestion,
-                Applicability::MachineApplicable,
-            );
+        for (span, msg, suggestion) in suggestions {
+            err.span_suggestion_verbose(span, &msg, suggestion, Applicability::MachineApplicable);
         }
     }
 
@@ -521,8 +549,8 @@ fn add_move_error_details(&self, err: &mut Diagnostic, binds_to: &[Local]) {
 
         if binds_to.len() > 1 {
             err.note(
-                "move occurs because these variables have types that \
-                      don't implement the `Copy` trait",
+                "move occurs because these variables have types that don't implement the `Copy` \
+                 trait",
             );
         }
     }
index 0cf66e41001f84eff9a14acc0a0cb6cce9c0d47f..3319a80681fde277dc0fd3f361c2656adfafe6b6 100644 (file)
@@ -219,8 +219,8 @@ pub(crate) fn report_mutability_error(
             PlaceRef {
                 local,
                 projection:
-                    &[
-                        ref proj_base @ ..,
+                    [
+                        proj_base @ ..,
                         ProjectionElem::Deref,
                         ProjectionElem::Field(field, _),
                         ProjectionElem::Deref,
@@ -231,7 +231,7 @@ pub(crate) fn report_mutability_error(
                 if let Some(span) = get_mut_span_in_struct_field(
                     self.infcx.tcx,
                     Place::ty_from(local, proj_base, self.body, self.infcx.tcx).ty,
-                    field,
+                    *field,
                 ) {
                     err.span_suggestion_verbose(
                         span,
index 7aa099433a76d902145decf600c3fac97be5ded7..f8ec5e5e799149c888e001dd4ddc1b488847c8d2 100644 (file)
@@ -504,7 +504,7 @@ fn report_fnmut_error(
         let ErrorConstraintInfo { outlived_fr, span, .. } = errci;
 
         let mut output_ty = self.regioncx.universal_regions().unnormalized_output_ty;
-        if let ty::Opaque(def_id, _) = *output_ty.kind() {
+        if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *output_ty.kind() {
             output_ty = self.infcx.tcx.type_of(def_id)
         };
 
@@ -921,7 +921,7 @@ fn suggest_move_on_borrowing_closure(&self, diag: &mut Diagnostic) {
                 }
             }
             hir::ExprKind::Block(blk, _) => {
-                if let Some(ref expr) = blk.expr {
+                if let Some(expr) = blk.expr {
                     // only when the block is a closure
                     if let hir::ExprKind::Closure(hir::Closure {
                         capture_clause: hir::CaptureBy::Ref,
index 39173e70acfe93ccab8e84fe763c7555a36de5b6..171e62d91e136463dfd600eb3dc9b51977b6ca59 100644 (file)
@@ -254,7 +254,7 @@ pub(crate) fn give_region_a_name(&self, fr: RegionVid) -> Option<RegionName> {
             .or_else(|| self.give_name_if_anonymous_region_appears_in_impl_signature(fr))
             .or_else(|| self.give_name_if_anonymous_region_appears_in_arg_position_impl_trait(fr));
 
-        if let Some(ref value) = value {
+        if let Some(value) = &value {
             self.region_names.try_borrow_mut().unwrap().insert(fr, value.clone());
         }
 
index f5317a143aed7157d0801da0e688c7bd7a090246..6fd9290058c36383e1a5c155de33f467701ee93d 100644 (file)
@@ -69,9 +69,9 @@ fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
                 self.consume_operand(location, op);
             }
             StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(mir::CopyNonOverlapping {
-                ref src,
-                ref dst,
-                ref count,
+                src,
+                dst,
+                count,
             })) => {
                 self.consume_operand(location, src);
                 self.consume_operand(location, dst);
@@ -106,7 +106,7 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
         self.check_activations(location);
 
         match &terminator.kind {
-            TerminatorKind::SwitchInt { ref discr, switch_ty: _, targets: _ } => {
+            TerminatorKind::SwitchInt { discr, targets: _ } => {
                 self.consume_operand(location, discr);
             }
             TerminatorKind::Drop { place: drop_place, target: _, unwind: _ } => {
@@ -119,7 +119,7 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
             }
             TerminatorKind::DropAndReplace {
                 place: drop_place,
-                value: ref new_value,
+                value: new_value,
                 target: _,
                 unwind: _,
             } => {
@@ -127,8 +127,8 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
                 self.consume_operand(location, new_value);
             }
             TerminatorKind::Call {
-                ref func,
-                ref args,
+                func,
+                args,
                 destination,
                 target: _,
                 cleanup: _,
@@ -141,15 +141,15 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
                 }
                 self.mutate_place(location, *destination, Deep);
             }
-            TerminatorKind::Assert { ref cond, expected: _, ref msg, target: _, cleanup: _ } => {
+            TerminatorKind::Assert { cond, expected: _, msg, target: _, cleanup: _ } => {
                 self.consume_operand(location, cond);
                 use rustc_middle::mir::AssertKind;
-                if let AssertKind::BoundsCheck { ref len, ref index } = *msg {
+                if let AssertKind::BoundsCheck { len, index } = msg {
                     self.consume_operand(location, len);
                     self.consume_operand(location, index);
                 }
             }
-            TerminatorKind::Yield { ref value, resume, resume_arg, drop: _ } => {
+            TerminatorKind::Yield { value, resume, resume_arg, drop: _ } => {
                 self.consume_operand(location, value);
 
                 // Invalidate all borrows of local places
@@ -175,25 +175,25 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
             }
             TerminatorKind::InlineAsm {
                 template: _,
-                ref operands,
+                operands,
                 options: _,
                 line_spans: _,
                 destination: _,
                 cleanup: _,
             } => {
                 for op in operands {
-                    match *op {
-                        InlineAsmOperand::In { reg: _, ref value } => {
+                    match op {
+                        InlineAsmOperand::In { reg: _, value } => {
                             self.consume_operand(location, value);
                         }
                         InlineAsmOperand::Out { reg: _, late: _, place, .. } => {
-                            if let Some(place) = place {
+                            if let &Some(place) = place {
                                 self.mutate_place(location, place, Shallow(None));
                             }
                         }
-                        InlineAsmOperand::InOut { reg: _, late: _, ref in_value, out_place } => {
+                        InlineAsmOperand::InOut { reg: _, late: _, in_value, out_place } => {
                             self.consume_operand(location, in_value);
-                            if let Some(out_place) = out_place {
+                            if let &Some(out_place) = out_place {
                                 self.mutate_place(location, out_place, Shallow(None));
                             }
                         }
@@ -252,8 +252,8 @@ fn consume_operand(&mut self, location: Location, operand: &Operand<'tcx>) {
 
     // Simulates consumption of an rvalue
     fn consume_rvalue(&mut self, location: Location, rvalue: &Rvalue<'tcx>) {
-        match *rvalue {
-            Rvalue::Ref(_ /*rgn*/, bk, place) => {
+        match rvalue {
+            &Rvalue::Ref(_ /*rgn*/, bk, place) => {
                 let access_kind = match bk {
                     BorrowKind::Shallow => {
                         (Shallow(Some(ArtificialField::ShallowBorrow)), Read(ReadKind::Borrow(bk)))
@@ -272,7 +272,7 @@ fn consume_rvalue(&mut self, location: Location, rvalue: &Rvalue<'tcx>) {
                 self.access_place(location, place, access_kind, LocalMutationIsAllowed::No);
             }
 
-            Rvalue::AddressOf(mutability, place) => {
+            &Rvalue::AddressOf(mutability, place) => {
                 let access_kind = match mutability {
                     Mutability::Mut => (
                         Deep,
@@ -288,20 +288,19 @@ fn consume_rvalue(&mut self, location: Location, rvalue: &Rvalue<'tcx>) {
 
             Rvalue::ThreadLocalRef(_) => {}
 
-            Rvalue::Use(ref operand)
-            | Rvalue::Repeat(ref operand, _)
-            | Rvalue::UnaryOp(_ /*un_op*/, ref operand)
-            | Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/)
-            | Rvalue::ShallowInitBox(ref operand, _ /*ty*/) => {
-                self.consume_operand(location, operand)
-            }
-            Rvalue::CopyForDeref(ref place) => {
-                let op = &Operand::Copy(*place);
+            Rvalue::Use(operand)
+            | Rvalue::Repeat(operand, _)
+            | Rvalue::UnaryOp(_ /*un_op*/, operand)
+            | Rvalue::Cast(_ /*cast_kind*/, operand, _ /*ty*/)
+            | Rvalue::ShallowInitBox(operand, _ /*ty*/) => self.consume_operand(location, operand),
+
+            &Rvalue::CopyForDeref(place) => {
+                let op = &Operand::Copy(place);
                 self.consume_operand(location, op);
             }
 
-            Rvalue::Len(place) | Rvalue::Discriminant(place) => {
-                let af = match *rvalue {
+            &(Rvalue::Len(place) | Rvalue::Discriminant(place)) => {
+                let af = match rvalue {
                     Rvalue::Len(..) => Some(ArtificialField::ArrayLength),
                     Rvalue::Discriminant(..) => None,
                     _ => unreachable!(),
@@ -314,15 +313,15 @@ fn consume_rvalue(&mut self, location: Location, rvalue: &Rvalue<'tcx>) {
                 );
             }
 
-            Rvalue::BinaryOp(_bin_op, box (ref operand1, ref operand2))
-            | Rvalue::CheckedBinaryOp(_bin_op, box (ref operand1, ref operand2)) => {
+            Rvalue::BinaryOp(_bin_op, box (operand1, operand2))
+            | Rvalue::CheckedBinaryOp(_bin_op, box (operand1, operand2)) => {
                 self.consume_operand(location, operand1);
                 self.consume_operand(location, operand2);
             }
 
             Rvalue::NullaryOp(_op, _ty) => {}
 
-            Rvalue::Aggregate(_, ref operands) => {
+            Rvalue::Aggregate(_, operands) => {
                 for operand in operands {
                     self.consume_operand(location, operand);
                 }
index 4d87ecf5e44be224f7a692e233bac2b472d56d51..5289de9b0abf2ffa3d0d2d142904b392070dc2d9 100644 (file)
@@ -578,12 +578,12 @@ fn visit_statement_before_primary_effect(
         self.check_activations(location, span, flow_state);
 
         match &stmt.kind {
-            StatementKind::Assign(box (lhs, ref rhs)) => {
+            StatementKind::Assign(box (lhs, rhs)) => {
                 self.consume_rvalue(location, (rhs, span), flow_state);
 
                 self.mutate_place(location, (*lhs, span), Shallow(None), flow_state);
             }
-            StatementKind::FakeRead(box (_, ref place)) => {
+            StatementKind::FakeRead(box (_, place)) => {
                 // Read for match doesn't access any memory and is used to
                 // assert that a place is safe and live. So we don't have to
                 // do any checks here.
@@ -601,7 +601,7 @@ fn visit_statement_before_primary_effect(
                     flow_state,
                 );
             }
-            StatementKind::Intrinsic(box ref kind) => match kind {
+            StatementKind::Intrinsic(box kind) => match kind {
                 NonDivergingIntrinsic::Assume(op) => self.consume_operand(location, (op, span), flow_state),
                 NonDivergingIntrinsic::CopyNonOverlapping(..) => span_bug!(
                     span,
@@ -643,8 +643,8 @@ fn visit_terminator_before_primary_effect(
 
         self.check_activations(loc, span, flow_state);
 
-        match term.kind {
-            TerminatorKind::SwitchInt { ref discr, switch_ty: _, targets: _ } => {
+        match &term.kind {
+            TerminatorKind::SwitchInt { discr, targets: _ } => {
                 self.consume_operand(loc, (discr, span), flow_state);
             }
             TerminatorKind::Drop { place, target: _, unwind: _ } => {
@@ -656,7 +656,7 @@ fn visit_terminator_before_primary_effect(
 
                 self.access_place(
                     loc,
-                    (place, span),
+                    (*place, span),
                     (AccessDepth::Drop, Write(WriteKind::StorageDeadOrDrop)),
                     LocalMutationIsAllowed::Yes,
                     flow_state,
@@ -664,16 +664,16 @@ fn visit_terminator_before_primary_effect(
             }
             TerminatorKind::DropAndReplace {
                 place: drop_place,
-                value: ref new_value,
+                value: new_value,
                 target: _,
                 unwind: _,
             } => {
-                self.mutate_place(loc, (drop_place, span), Deep, flow_state);
+                self.mutate_place(loc, (*drop_place, span), Deep, flow_state);
                 self.consume_operand(loc, (new_value, span), flow_state);
             }
             TerminatorKind::Call {
-                ref func,
-                ref args,
+                func,
+                args,
                 destination,
                 target: _,
                 cleanup: _,
@@ -684,43 +684,43 @@ fn visit_terminator_before_primary_effect(
                 for arg in args {
                     self.consume_operand(loc, (arg, span), flow_state);
                 }
-                self.mutate_place(loc, (destination, span), Deep, flow_state);
+                self.mutate_place(loc, (*destination, span), Deep, flow_state);
             }
-            TerminatorKind::Assert { ref cond, expected: _, ref msg, target: _, cleanup: _ } => {
+            TerminatorKind::Assert { cond, expected: _, msg, target: _, cleanup: _ } => {
                 self.consume_operand(loc, (cond, span), flow_state);
                 use rustc_middle::mir::AssertKind;
-                if let AssertKind::BoundsCheck { ref len, ref index } = *msg {
+                if let AssertKind::BoundsCheck { len, index } = msg {
                     self.consume_operand(loc, (len, span), flow_state);
                     self.consume_operand(loc, (index, span), flow_state);
                 }
             }
 
-            TerminatorKind::Yield { ref value, resume: _, resume_arg, drop: _ } => {
+            TerminatorKind::Yield { value, resume: _, resume_arg, drop: _ } => {
                 self.consume_operand(loc, (value, span), flow_state);
-                self.mutate_place(loc, (resume_arg, span), Deep, flow_state);
+                self.mutate_place(loc, (*resume_arg, span), Deep, flow_state);
             }
 
             TerminatorKind::InlineAsm {
                 template: _,
-                ref operands,
+                operands,
                 options: _,
                 line_spans: _,
                 destination: _,
                 cleanup: _,
             } => {
                 for op in operands {
-                    match *op {
-                        InlineAsmOperand::In { reg: _, ref value } => {
+                    match op {
+                        InlineAsmOperand::In { reg: _, value } => {
                             self.consume_operand(loc, (value, span), flow_state);
                         }
                         InlineAsmOperand::Out { reg: _, late: _, place, .. } => {
                             if let Some(place) = place {
-                                self.mutate_place(loc, (place, span), Shallow(None), flow_state);
+                                self.mutate_place(loc, (*place, span), Shallow(None), flow_state);
                             }
                         }
-                        InlineAsmOperand::InOut { reg: _, late: _, ref in_value, out_place } => {
+                        InlineAsmOperand::InOut { reg: _, late: _, in_value, out_place } => {
                             self.consume_operand(loc, (in_value, span), flow_state);
-                            if let Some(out_place) = out_place {
+                            if let &Some(out_place) = out_place {
                                 self.mutate_place(
                                     loc,
                                     (out_place, span),
@@ -1164,8 +1164,8 @@ fn consume_rvalue(
         (rvalue, span): (&'cx Rvalue<'tcx>, Span),
         flow_state: &Flows<'cx, 'tcx>,
     ) {
-        match *rvalue {
-            Rvalue::Ref(_ /*rgn*/, bk, place) => {
+        match rvalue {
+            &Rvalue::Ref(_ /*rgn*/, bk, place) => {
                 let access_kind = match bk {
                     BorrowKind::Shallow => {
                         (Shallow(Some(ArtificialField::ShallowBorrow)), Read(ReadKind::Borrow(bk)))
@@ -1203,7 +1203,7 @@ fn consume_rvalue(
                 );
             }
 
-            Rvalue::AddressOf(mutability, place) => {
+            &Rvalue::AddressOf(mutability, place) => {
                 let access_kind = match mutability {
                     Mutability::Mut => (
                         Deep,
@@ -1232,14 +1232,15 @@ fn consume_rvalue(
 
             Rvalue::ThreadLocalRef(_) => {}
 
-            Rvalue::Use(ref operand)
-            | Rvalue::Repeat(ref operand, _)
-            | Rvalue::UnaryOp(_ /*un_op*/, ref operand)
-            | Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/)
-            | Rvalue::ShallowInitBox(ref operand, _ /*ty*/) => {
+            Rvalue::Use(operand)
+            | Rvalue::Repeat(operand, _)
+            | Rvalue::UnaryOp(_ /*un_op*/, operand)
+            | Rvalue::Cast(_ /*cast_kind*/, operand, _ /*ty*/)
+            | Rvalue::ShallowInitBox(operand, _ /*ty*/) => {
                 self.consume_operand(location, (operand, span), flow_state)
             }
-            Rvalue::CopyForDeref(place) => {
+
+            &Rvalue::CopyForDeref(place) => {
                 self.access_place(
                     location,
                     (place, span),
@@ -1257,7 +1258,7 @@ fn consume_rvalue(
                 );
             }
 
-            Rvalue::Len(place) | Rvalue::Discriminant(place) => {
+            &(Rvalue::Len(place) | Rvalue::Discriminant(place)) => {
                 let af = match *rvalue {
                     Rvalue::Len(..) => Some(ArtificialField::ArrayLength),
                     Rvalue::Discriminant(..) => None,
@@ -1278,8 +1279,8 @@ fn consume_rvalue(
                 );
             }
 
-            Rvalue::BinaryOp(_bin_op, box (ref operand1, ref operand2))
-            | Rvalue::CheckedBinaryOp(_bin_op, box (ref operand1, ref operand2)) => {
+            Rvalue::BinaryOp(_bin_op, box (operand1, operand2))
+            | Rvalue::CheckedBinaryOp(_bin_op, box (operand1, operand2)) => {
                 self.consume_operand(location, (operand1, span), flow_state);
                 self.consume_operand(location, (operand2, span), flow_state);
             }
@@ -1288,7 +1289,7 @@ fn consume_rvalue(
                 // nullary ops take no dynamic input; no borrowck effect.
             }
 
-            Rvalue::Aggregate(ref aggregate_kind, ref operands) => {
+            Rvalue::Aggregate(aggregate_kind, operands) => {
                 // We need to report back the list of mutable upvars that were
                 // moved into the closure and subsequently used by the closure,
                 // in order to populate our used_mut set.
index 90e2b6b698cf832ec4a2d45e266e173369a3062f..e9c98bdc514967a63f4f1dc39be0e6be7d1919ed 100644 (file)
@@ -747,27 +747,14 @@ fn apply_member_constraint(
         // Otherwise, we need to find the minimum remaining choice, if
         // any, and take that.
         debug!("choice_regions remaining are {:#?}", choice_regions);
-        let min = |r1: ty::RegionVid, r2: ty::RegionVid| -> Option<ty::RegionVid> {
-            let r1_outlives_r2 = self.universal_region_relations.outlives(r1, r2);
-            let r2_outlives_r1 = self.universal_region_relations.outlives(r2, r1);
-            match (r1_outlives_r2, r2_outlives_r1) {
-                (true, true) => Some(r1.min(r2)),
-                (true, false) => Some(r2),
-                (false, true) => Some(r1),
-                (false, false) => None,
-            }
+        let Some(&min_choice) = choice_regions.iter().find(|&r1| {
+            choice_regions.iter().all(|&r2| {
+                self.universal_region_relations.outlives(r2, *r1)
+            })
+        }) else {
+            debug!("no choice region outlived by all others");
+            return false;
         };
-        let mut min_choice = choice_regions[0];
-        for &other_option in &choice_regions[1..] {
-            debug!(?min_choice, ?other_option,);
-            match min(min_choice, other_option) {
-                Some(m) => min_choice = m,
-                None => {
-                    debug!(?min_choice, ?other_option, "incomparable; no min choice",);
-                    return false;
-                }
-            }
-        }
 
         let min_choice_scc = self.constraint_sccs.scc(min_choice);
         debug!(?min_choice, ?min_choice_scc);
index 18e3cbbb86a0eace8d8cdd611012ed7b2b1d2041..814bc275019ca0109e4e3d265406630f2cf07398 100644 (file)
@@ -1189,8 +1189,8 @@ fn tcx(&self) -> TyCtxt<'tcx> {
     fn check_stmt(&mut self, body: &Body<'tcx>, stmt: &Statement<'tcx>, location: Location) {
         let tcx = self.tcx();
         debug!("stmt kind: {:?}", stmt.kind);
-        match stmt.kind {
-            StatementKind::Assign(box (ref place, ref rv)) => {
+        match &stmt.kind {
+            StatementKind::Assign(box (place, rv)) => {
                 // Assignments to temporaries are not "interesting";
                 // they are not caused by the user, but rather artifacts
                 // of lowering. Assignments to other sorts of places *are* interesting
@@ -1279,11 +1279,11 @@ fn check_stmt(&mut self, body: &Body<'tcx>, stmt: &Statement<'tcx>, location: Lo
                     );
                 }
             }
-            StatementKind::AscribeUserType(box (ref place, ref projection), variance) => {
+            StatementKind::AscribeUserType(box (place, projection), variance) => {
                 let place_ty = place.ty(body, tcx).ty;
                 if let Err(terr) = self.relate_type_and_user_type(
                     place_ty,
-                    variance,
+                    *variance,
                     projection,
                     Locations::All(stmt.source_info.span),
                     ConstraintCategory::TypeAnnotation,
@@ -1300,7 +1300,7 @@ fn check_stmt(&mut self, body: &Body<'tcx>, stmt: &Statement<'tcx>, location: Lo
                     );
                 }
             }
-            StatementKind::Intrinsic(box ref kind) => match kind {
+            StatementKind::Intrinsic(box kind) => match kind {
                 NonDivergingIntrinsic::Assume(op) => self.check_operand(op, location),
                 NonDivergingIntrinsic::CopyNonOverlapping(..) => span_bug!(
                     stmt.source_info.span,
@@ -1328,7 +1328,7 @@ fn check_terminator(
     ) {
         let tcx = self.tcx();
         debug!("terminator kind: {:?}", term.kind);
-        match term.kind {
+        match &term.kind {
             TerminatorKind::Goto { .. }
             | TerminatorKind::Resume
             | TerminatorKind::Abort
@@ -1342,7 +1342,7 @@ fn check_terminator(
                 // no checks needed for these
             }
 
-            TerminatorKind::DropAndReplace { ref place, ref value, target: _, unwind: _ } => {
+            TerminatorKind::DropAndReplace { place, value, target: _, unwind: _ } => {
                 let place_ty = place.ty(body, tcx).ty;
                 let rv_ty = value.ty(body, tcx);
 
@@ -1360,38 +1360,16 @@ fn check_terminator(
                     );
                 }
             }
-            TerminatorKind::SwitchInt { ref discr, switch_ty, .. } => {
+            TerminatorKind::SwitchInt { discr, .. } => {
                 self.check_operand(discr, term_location);
 
-                let discr_ty = discr.ty(body, tcx);
-                if let Err(terr) = self.sub_types(
-                    discr_ty,
-                    switch_ty,
-                    term_location.to_locations(),
-                    ConstraintCategory::Assignment,
-                ) {
-                    span_mirbug!(
-                        self,
-                        term,
-                        "bad SwitchInt ({:?} on {:?}): {:?}",
-                        switch_ty,
-                        discr_ty,
-                        terr
-                    );
-                }
+                let switch_ty = discr.ty(body, tcx);
                 if !switch_ty.is_integral() && !switch_ty.is_char() && !switch_ty.is_bool() {
                     span_mirbug!(self, term, "bad SwitchInt discr ty {:?}", switch_ty);
                 }
                 // FIXME: check the values
             }
-            TerminatorKind::Call {
-                ref func,
-                ref args,
-                ref destination,
-                from_hir_call,
-                target,
-                ..
-            } => {
+            TerminatorKind::Call { func, args, destination, from_hir_call, target, .. } => {
                 self.check_operand(func, term_location);
                 for arg in args {
                     self.check_operand(arg, term_location);
@@ -1431,7 +1409,7 @@ fn check_terminator(
                     ConstraintCategory::Boring,
                 );
                 let sig = self.normalize(sig, term_location);
-                self.check_call_dest(body, term, &sig, *destination, target, term_location);
+                self.check_call_dest(body, term, &sig, *destination, *target, term_location);
 
                 // The ordinary liveness rules will ensure that all
                 // regions in the type of the callee are live here. We
@@ -1449,9 +1427,9 @@ fn check_terminator(
                         .add_element(region_vid, term_location);
                 }
 
-                self.check_call_inputs(body, term, &sig, args, term_location, from_hir_call);
+                self.check_call_inputs(body, term, &sig, args, term_location, *from_hir_call);
             }
-            TerminatorKind::Assert { ref cond, ref msg, .. } => {
+            TerminatorKind::Assert { cond, msg, .. } => {
                 self.check_operand(cond, term_location);
 
                 let cond_ty = cond.ty(body, tcx);
@@ -1459,7 +1437,7 @@ fn check_terminator(
                     span_mirbug!(self, term, "bad Assert ({:?}, not bool", cond_ty);
                 }
 
-                if let AssertKind::BoundsCheck { ref len, ref index } = *msg {
+                if let AssertKind::BoundsCheck { len, index } = msg {
                     if len.ty(body, tcx) != tcx.types.usize {
                         span_mirbug!(self, len, "bounds-check length non-usize {:?}", len)
                     }
@@ -1468,7 +1446,7 @@ fn check_terminator(
                     }
                 }
             }
-            TerminatorKind::Yield { ref value, .. } => {
+            TerminatorKind::Yield { value, .. } => {
                 self.check_operand(value, term_location);
 
                 let value_ty = value.ty(body, tcx);
@@ -2630,7 +2608,7 @@ fn prove_closure_bounds(
         substs: SubstsRef<'tcx>,
         location: Location,
     ) -> ty::InstantiatedPredicates<'tcx> {
-        if let Some(ref closure_requirements) = tcx.mir_borrowck(def_id).closure_requirements {
+        if let Some(closure_requirements) = &tcx.mir_borrowck(def_id).closure_requirements {
             constraint_conversion::ConstraintConversion::new(
                 self.infcx,
                 self.borrowck_context.universal_regions,
index 618da9e3253252886807c2413eb32a57a5d55af4..a4a0c5b90fed32d2a20372aa908806b81aa9a2fe 100644 (file)
@@ -587,9 +587,9 @@ fn compute_indices(
         let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.did.to_def_id());
         let identity_substs = InternalSubsts::identity_for_item(tcx, typeck_root_def_id);
         let fr_substs = match defining_ty {
-            DefiningTy::Closure(_, ref substs)
-            | DefiningTy::Generator(_, ref substs, _)
-            | DefiningTy::InlineConst(_, ref substs) => {
+            DefiningTy::Closure(_, substs)
+            | DefiningTy::Generator(_, substs, _)
+            | DefiningTy::InlineConst(_, substs) => {
                 // In the case of closures, we rely on the fact that
                 // the first N elements in the ClosureSubsts are
                 // inherited from the `typeck_root_def_id`.
index 460175ed2ac84bb35abb7d29181ac418ecb5cd61..dcf500ddbd3c8d9fc576d6eb8de1261a05f129b8 100644 (file)
@@ -17,32 +17,23 @@ pub fn expand(
     check_builtin_macro_attribute(ecx, meta_item, sym::alloc_error_handler);
 
     let orig_item = item.clone();
-    let not_function = || {
-        ecx.sess
-            .parse_sess
-            .span_diagnostic
-            .span_err(item.span(), "alloc_error_handler must be a function");
-        vec![orig_item.clone()]
-    };
 
     // Allow using `#[alloc_error_handler]` on an item statement
     // FIXME - if we get deref patterns, use them to reduce duplication here
-    let (item, is_stmt, sig_span) = match &item {
-        Annotatable::Item(item) => match item.kind {
-            ItemKind::Fn(ref fn_kind) => (item, false, ecx.with_def_site_ctxt(fn_kind.sig.span)),
-            _ => return not_function(),
-        },
-        Annotatable::Stmt(stmt) => match &stmt.kind {
-            StmtKind::Item(item_) => match item_.kind {
-                ItemKind::Fn(ref fn_kind) => {
-                    (item_, true, ecx.with_def_site_ctxt(fn_kind.sig.span))
-                }
-                _ => return not_function(),
-            },
-            _ => return not_function(),
-        },
-        _ => return not_function(),
-    };
+    let (item, is_stmt, sig_span) =
+        if let Annotatable::Item(item) = &item
+            && let ItemKind::Fn(fn_kind) = &item.kind
+        {
+            (item, false, ecx.with_def_site_ctxt(fn_kind.sig.span))
+        } else if let Annotatable::Stmt(stmt) = &item
+            && let StmtKind::Item(item) = &stmt.kind
+            && let ItemKind::Fn(fn_kind) = &item.kind
+        {
+            (item, true, ecx.with_def_site_ctxt(fn_kind.sig.span))
+        } else {
+            ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "alloc_error_handler must be a function");
+            return vec![orig_item];
+        };
 
     // Generate a bunch of new items using the AllocFnFactory
     let span = ecx.with_def_site_ctxt(item.span);
index d82bc0453f5722c0912c4a9463dcf461daf941ec..93b07801e035d7de24d995980ccd1568063ffb29 100644 (file)
@@ -191,19 +191,19 @@ fn build_panic(&self, expr_str: &str, panic_path: Path) -> P<Expr> {
     ///
     /// See [Self::manage_initial_capture] and [Self::manage_try_capture]
     fn manage_cond_expr(&mut self, expr: &mut P<Expr>) {
-        match (*expr).kind {
-            ExprKind::AddrOf(_, mutability, ref mut local_expr) => {
+        match &mut expr.kind {
+            ExprKind::AddrOf(_, mutability, local_expr) => {
                 self.with_is_consumed_management(
                     matches!(mutability, Mutability::Mut),
                     |this| this.manage_cond_expr(local_expr)
                 );
             }
-            ExprKind::Array(ref mut local_exprs) => {
+            ExprKind::Array(local_exprs) => {
                 for local_expr in local_exprs {
                     self.manage_cond_expr(local_expr);
                 }
             }
-            ExprKind::Binary(ref op, ref mut lhs, ref mut rhs) => {
+            ExprKind::Binary(op, lhs, rhs) => {
                 self.with_is_consumed_management(
                     matches!(
                         op.node,
@@ -226,56 +226,56 @@ fn manage_cond_expr(&mut self, expr: &mut P<Expr>) {
                     }
                 );
             }
-            ExprKind::Call(_, ref mut local_exprs) => {
+            ExprKind::Call(_, local_exprs) => {
                 for local_expr in local_exprs {
                     self.manage_cond_expr(local_expr);
                 }
             }
-            ExprKind::Cast(ref mut local_expr, _) => {
+            ExprKind::Cast(local_expr, _) => {
                 self.manage_cond_expr(local_expr);
             }
-            ExprKind::Index(ref mut prefix, ref mut suffix) => {
+            ExprKind::Index(prefix, suffix) => {
                 self.manage_cond_expr(prefix);
                 self.manage_cond_expr(suffix);
             }
-            ExprKind::MethodCall(ref mut call) => {
-                for arg in call.args.iter_mut() {
+            ExprKind::MethodCall(call) => {
+                for arg in &mut call.args {
                     self.manage_cond_expr(arg);
                 }
             }
-            ExprKind::Path(_, Path { ref segments, .. }) if let &[ref path_segment] = &segments[..] => {
+            ExprKind::Path(_, Path { segments, .. }) if let [path_segment] = &segments[..] => {
                 let path_ident = path_segment.ident;
                 self.manage_initial_capture(expr, path_ident);
             }
-            ExprKind::Paren(ref mut local_expr) => {
+            ExprKind::Paren(local_expr) => {
                 self.manage_cond_expr(local_expr);
             }
-            ExprKind::Range(ref mut prefix, ref mut suffix, _) => {
-                if let Some(ref mut elem) = prefix {
+            ExprKind::Range(prefix, suffix, _) => {
+                if let Some(elem) = prefix {
                     self.manage_cond_expr(elem);
                 }
-                if let Some(ref mut elem) = suffix {
+                if let Some(elem) = suffix {
                     self.manage_cond_expr(elem);
                 }
             }
-            ExprKind::Repeat(ref mut local_expr, ref mut elem) => {
+            ExprKind::Repeat(local_expr, elem) => {
                 self.manage_cond_expr(local_expr);
                 self.manage_cond_expr(&mut elem.value);
             }
-            ExprKind::Struct(ref mut elem) => {
+            ExprKind::Struct(elem) => {
                 for field in &mut elem.fields {
                     self.manage_cond_expr(&mut field.expr);
                 }
-                if let StructRest::Base(ref mut local_expr) = elem.rest {
+                if let StructRest::Base(local_expr) = &mut elem.rest {
                     self.manage_cond_expr(local_expr);
                 }
             }
-            ExprKind::Tup(ref mut local_exprs) => {
+            ExprKind::Tup(local_exprs) => {
                 for local_expr in local_exprs {
                     self.manage_cond_expr(local_expr);
                 }
             }
-            ExprKind::Unary(un_op, ref mut local_expr) => {
+            ExprKind::Unary(un_op, local_expr) => {
                 self.with_is_consumed_management(
                     matches!(un_op, UnOp::Neg | UnOp::Not),
                     |this| this.manage_cond_expr(local_expr)
index d579616ad1b84b25cb77fa516f312fd7ae35ce7b..7da9bdc38a2a8cd3d0b32d031afd5d7ebbf3f3e8 100644 (file)
@@ -4,14 +4,12 @@
 use rustc_session::errors::report_lit_error;
 use rustc_span::symbol::Symbol;
 
-use std::string::String;
-
 pub fn expand_concat(
     cx: &mut base::ExtCtxt<'_>,
     sp: rustc_span::Span,
     tts: TokenStream,
 ) -> Box<dyn base::MacResult + 'static> {
-    let Some(es) = base::get_exprs_from_tts(cx, sp, tts) else {
+    let Some(es) = base::get_exprs_from_tts(cx, tts) else {
         return DummyResult::any(sp);
     };
     let mut accumulator = String::new();
@@ -20,7 +18,7 @@ pub fn expand_concat(
     for e in es {
         match e.kind {
             ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) {
-                Ok(ast::LitKind::Str(ref s, _) | ast::LitKind::Float(ref s, _)) => {
+                Ok(ast::LitKind::Str(s, _) | ast::LitKind::Float(s, _)) => {
                     accumulator.push_str(s.as_str());
                 }
                 Ok(ast::LitKind::Char(c)) => {
index 161e3499584e24cb54b5fa206d1cc02a06332d68..4f1a7d709ff8c276900c255977d478fa9a3bec81 100644 (file)
@@ -69,7 +69,7 @@ fn invalid_type_err(
         Ok(ast::LitKind::Int(_, _)) => {
             cx.span_err(span, "numeric literal is not a `u8`");
         }
-        Ok(ast::LitKind::ByteStr(_) | ast::LitKind::Byte(_)) => unreachable!(),
+        Ok(ast::LitKind::ByteStr(..) | ast::LitKind::Byte(_)) => unreachable!(),
         Err(err) => {
             report_lit_error(&cx.sess.parse_sess, err, token_lit, span);
         }
@@ -97,7 +97,7 @@ fn handle_array_element(
             )) if val <= u8::MAX.into() => Some(val as u8),
 
             Ok(ast::LitKind::Byte(val)) => Some(val),
-            Ok(ast::LitKind::ByteStr(_)) => {
+            Ok(ast::LitKind::ByteStr(..)) => {
                 if !*has_errors {
                     cx.struct_span_err(expr.span, "cannot concatenate doubly nested array")
                         .note("byte strings are treated as arrays of bytes")
@@ -137,15 +137,15 @@ pub fn expand_concat_bytes(
     sp: rustc_span::Span,
     tts: TokenStream,
 ) -> Box<dyn base::MacResult + 'static> {
-    let Some(es) = base::get_exprs_from_tts(cx, sp, tts) else {
+    let Some(es) = base::get_exprs_from_tts(cx, tts) else {
         return DummyResult::any(sp);
     };
     let mut accumulator = Vec::new();
     let mut missing_literals = vec![];
     let mut has_errors = false;
     for e in es {
-        match e.kind {
-            ast::ExprKind::Array(ref exprs) => {
+        match &e.kind {
+            ast::ExprKind::Array(exprs) => {
                 for expr in exprs {
                     if let Some(elem) =
                         handle_array_element(cx, &mut has_errors, &mut missing_literals, expr)
@@ -154,7 +154,7 @@ pub fn expand_concat_bytes(
                     }
                 }
             }
-            ast::ExprKind::Repeat(ref expr, ref count) => {
+            ast::ExprKind::Repeat(expr, count) => {
                 if let ast::ExprKind::Lit(token_lit) = count.value.kind
                 && let Ok(ast::LitKind::Int(count_val, _)) =
                     ast::LitKind::from_token_lit(token_lit)
@@ -170,11 +170,11 @@ pub fn expand_concat_bytes(
                     cx.span_err(count.value.span, "repeat count is not a positive number");
                 }
             }
-            ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) {
+            &ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) {
                 Ok(ast::LitKind::Byte(val)) => {
                     accumulator.push(val);
                 }
-                Ok(ast::LitKind::ByteStr(ref bytes)) => {
+                Ok(ast::LitKind::ByteStr(ref bytes, _)) => {
                     accumulator.extend_from_slice(&bytes);
                 }
                 _ => {
@@ -184,7 +184,7 @@ pub fn expand_concat_bytes(
                     has_errors = true;
                 }
             },
-            ast::ExprKind::IncludedBytes(ref bytes) => {
+            ast::ExprKind::IncludedBytes(bytes) => {
                 accumulator.extend_from_slice(bytes);
             }
             ast::ExprKind::Err => {
@@ -196,7 +196,7 @@ pub fn expand_concat_bytes(
         }
     }
     if !missing_literals.is_empty() {
-        let mut err = cx.struct_span_err(missing_literals.clone(), "expected a byte literal");
+        let mut err = cx.struct_span_err(missing_literals, "expected a byte literal");
         err.note("only byte literals (like `b\"foo\"`, `b's'`, and `[3, 4, 5]`) can be passed to `concat_bytes!()`");
         err.emit();
         return base::MacEager::expr(DummyResult::raw_expr(sp, true));
index fa5a45730ac7afd8379eb696f2ef7098df42d389..2a8dc02849ea71e6a51701e7905a812966395b2c 100644 (file)
@@ -1,7 +1,7 @@
 use crate::cfg_eval::cfg_eval;
 
 use rustc_ast as ast;
-use rustc_ast::{token, GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind};
+use rustc_ast::{GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind};
 use rustc_errors::{struct_span_err, Applicability};
 use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier};
 use rustc_feature::AttributeTemplate;
@@ -130,9 +130,11 @@ fn report_bad_target(sess: &Session, item: &Annotatable, span: Span) -> bool {
 }
 
 fn report_unexpected_meta_item_lit(sess: &Session, lit: &ast::MetaItemLit) {
-    let help_msg = match lit.token_lit.kind {
-        token::Str if rustc_lexer::is_ident(lit.token_lit.symbol.as_str()) => {
-            format!("try using `#[derive({})]`", lit.token_lit.symbol)
+    let help_msg = match lit.kind {
+        ast::LitKind::Str(_, ast::StrStyle::Cooked)
+            if rustc_lexer::is_ident(lit.symbol.as_str()) =>
+        {
+            format!("try using `#[derive({})]`", lit.symbol)
         }
         _ => "for example, write `#[derive(Debug)]` for `Debug`".to_string(),
     };
index 23b96d4176d3a27391d2d5d80491eae91b2b719e..d59b3b8c86d35ef6303bb8a3adbd5e9aecf2d1f1 100644 (file)
@@ -32,10 +32,10 @@ pub fn expand_deriving_clone(
     let bounds;
     let substructure;
     let is_simple;
-    match *item {
-        Annotatable::Item(ref annitem) => match annitem.kind {
-            ItemKind::Struct(_, Generics { ref params, .. })
-            | ItemKind::Enum(_, Generics { ref params, .. }) => {
+    match item {
+        Annotatable::Item(annitem) => match &annitem.kind {
+            ItemKind::Struct(_, Generics { params, .. })
+            | ItemKind::Enum(_, Generics { params, .. }) => {
                 let container_id = cx.current_expansion.id.expn_data().parent.expect_local();
                 let has_derive_copy = cx.resolver.has_derive_copy(container_id);
                 if has_derive_copy
@@ -166,13 +166,13 @@ fn cs_clone(
     };
 
     let vdata;
-    match *substr.fields {
-        Struct(vdata_, ref af) => {
+    match substr.fields {
+        Struct(vdata_, af) => {
             ctor_path = cx.path(trait_span, vec![substr.type_ident]);
             all_fields = af;
-            vdata = vdata_;
+            vdata = *vdata_;
         }
-        EnumMatching(.., variant, ref af) => {
+        EnumMatching(.., variant, af) => {
             ctor_path = cx.path(trait_span, vec![substr.type_ident, variant.ident]);
             all_fields = af;
             vdata = &variant.data;
index 6d14875a9832293f7d238fdd7e525c385b57326a..62af02c2bb4b2d35304cf4eafd42036fba31d5ef 100644 (file)
@@ -78,11 +78,11 @@ fn decodable_substructure(
     let blkarg = Ident::new(sym::_d, trait_span);
     let blkdecoder = cx.expr_ident(trait_span, blkarg);
 
-    let expr = match *substr.fields {
-        StaticStruct(_, ref summary) => {
-            let nfields = match *summary {
-                Unnamed(ref fields, _) => fields.len(),
-                Named(ref fields) => fields.len(),
+    let expr = match substr.fields {
+        StaticStruct(_, summary) => {
+            let nfields = match summary {
+                Unnamed(fields, _) => fields.len(),
+                Named(fields) => fields.len(),
             };
             let fn_read_struct_field_path: Vec<_> =
                 cx.def_site_path(&[sym::rustc_serialize, sym::Decoder, sym::read_struct_field]);
@@ -119,7 +119,7 @@ fn decodable_substructure(
                 ],
             )
         }
-        StaticEnum(_, ref fields) => {
+        StaticEnum(_, fields) => {
             let variant = Ident::new(sym::i, trait_span);
 
             let mut arms = Vec::with_capacity(fields.len() + 1);
@@ -194,10 +194,10 @@ fn decode_static_fields<F>(
 where
     F: FnMut(&mut ExtCtxt<'_>, Span, Symbol, usize) -> P<Expr>,
 {
-    match *fields {
-        Unnamed(ref fields, is_tuple) => {
+    match fields {
+        Unnamed(fields, is_tuple) => {
             let path_expr = cx.expr_path(outer_pat_path);
-            if !is_tuple {
+            if !*is_tuple {
                 path_expr
             } else {
                 let fields = fields
@@ -209,7 +209,7 @@ fn decode_static_fields<F>(
                 cx.expr_call(trait_span, path_expr, fields)
             }
         }
-        Named(ref fields) => {
+        Named(fields) => {
             // use the field's span to get nicer error messages.
             let fields = fields
                 .iter()
index e88d2e409c63b0c95e1e900a7bac12d5e14c4081..eb66c4a69a69bc25bab4126e1649d5f3097a940f 100644 (file)
@@ -62,15 +62,12 @@ fn default_struct_substructure(
     let default_call = |span| cx.expr_call_global(span, default_ident.clone(), Vec::new());
 
     let expr = match summary {
-        Unnamed(ref fields, is_tuple) => {
-            if !is_tuple {
-                cx.expr_ident(trait_span, substr.type_ident)
-            } else {
-                let exprs = fields.iter().map(|sp| default_call(*sp)).collect();
-                cx.expr_call_ident(trait_span, substr.type_ident, exprs)
-            }
+        Unnamed(_, false) => cx.expr_ident(trait_span, substr.type_ident),
+        Unnamed(fields, true) => {
+            let exprs = fields.iter().map(|sp| default_call(*sp)).collect();
+            cx.expr_call_ident(trait_span, substr.type_ident, exprs)
         }
-        Named(ref fields) => {
+        Named(fields) => {
             let default_fields = fields
                 .iter()
                 .map(|&(ident, span)| cx.field_imm(span, ident, default_call(span)))
index 9a46ca815372653ab4696303896d31ea5a34cd5e..68bc0ff2ec0b41c553339586a0874ef5fcb6a1f1 100644 (file)
@@ -164,8 +164,8 @@ fn encodable_substructure(
         ],
     ));
 
-    match *substr.fields {
-        Struct(_, ref fields) => {
+    match substr.fields {
+        Struct(_, fields) => {
             let fn_emit_struct_field_path =
                 cx.def_site_path(&[sym::rustc_serialize, sym::Encoder, sym::emit_struct_field]);
             let mut stmts = Vec::new();
@@ -224,7 +224,7 @@ fn encodable_substructure(
             BlockOrExpr::new_expr(expr)
         }
 
-        EnumMatching(idx, _, variant, ref fields) => {
+        EnumMatching(idx, _, variant, fields) => {
             // We're not generating an AST that the borrow checker is expecting,
             // so we need to generate a unique local variable to take the
             // mutable loan out on, otherwise we get conflicts which don't
@@ -274,7 +274,7 @@ fn encodable_substructure(
                 vec![
                     blkencoder,
                     name,
-                    cx.expr_usize(trait_span, idx),
+                    cx.expr_usize(trait_span, *idx),
                     cx.expr_usize(trait_span, fields.len()),
                     blk,
                 ],
index 7fcaf0b436b9079742bd0261455ae0d613b9ad2f..beac591bfc879065a2c6fd411be0673ba59a3383 100644 (file)
@@ -369,15 +369,14 @@ struct Visitor<'a, 'b> {
 
     impl<'a, 'b> visit::Visitor<'a> for Visitor<'a, 'b> {
         fn visit_ty(&mut self, ty: &'a ast::Ty) {
-            if let ast::TyKind::Path(_, ref path) = ty.kind {
-                if let Some(segment) = path.segments.first() {
-                    if self.ty_param_names.contains(&segment.ident.name) {
-                        self.type_params.push(TypeParameter {
-                            bound_generic_params: self.bound_generic_params_stack.clone(),
-                            ty: P(ty.clone()),
-                        });
-                    }
-                }
+            if let ast::TyKind::Path(_, path) = &ty.kind
+                && let Some(segment) = path.segments.first()
+                && self.ty_param_names.contains(&segment.ident.name)
+            {
+                self.type_params.push(TypeParameter {
+                    bound_generic_params: self.bound_generic_params_stack.clone(),
+                    ty: P(ty.clone()),
+                });
             }
 
             visit::walk_ty(self, ty)
@@ -428,8 +427,8 @@ pub fn expand_ext(
         push: &mut dyn FnMut(Annotatable),
         from_scratch: bool,
     ) {
-        match *item {
-            Annotatable::Item(ref item) => {
+        match item {
+            Annotatable::Item(item) => {
                 let is_packed = item.attrs.iter().any(|attr| {
                     for r in attr::find_repr_attrs(&cx.sess, attr) {
                         if let attr::ReprPacked(_) = r {
@@ -438,10 +437,10 @@ pub fn expand_ext(
                     }
                     false
                 });
-                let has_no_type_params = match item.kind {
-                    ast::ItemKind::Struct(_, ref generics)
-                    | ast::ItemKind::Enum(_, ref generics)
-                    | ast::ItemKind::Union(_, ref generics) => !generics
+                let has_no_type_params = match &item.kind {
+                    ast::ItemKind::Struct(_, generics)
+                    | ast::ItemKind::Enum(_, generics)
+                    | ast::ItemKind::Union(_, generics) => !generics
                         .params
                         .iter()
                         .any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. })),
@@ -451,8 +450,8 @@ pub fn expand_ext(
                 let copy_fields =
                     is_packed && has_no_type_params && cx.resolver.has_derive_copy(container_id);
 
-                let newitem = match item.kind {
-                    ast::ItemKind::Struct(ref struct_def, ref generics) => self.expand_struct_def(
+                let newitem = match &item.kind {
+                    ast::ItemKind::Struct(struct_def, generics) => self.expand_struct_def(
                         cx,
                         &struct_def,
                         item.ident,
@@ -460,7 +459,7 @@ pub fn expand_ext(
                         from_scratch,
                         copy_fields,
                     ),
-                    ast::ItemKind::Enum(ref enum_def, ref generics) => {
+                    ast::ItemKind::Enum(enum_def, generics) => {
                         // We ignore `is_packed` here, because `repr(packed)`
                         // enums cause an error later on.
                         //
@@ -468,7 +467,7 @@ pub fn expand_ext(
                         // downstream in blatantly illegal code, so it is fine.
                         self.expand_enum_def(cx, enum_def, item.ident, generics, from_scratch)
                     }
-                    ast::ItemKind::Union(ref struct_def, ref generics) => {
+                    ast::ItemKind::Union(struct_def, generics) => {
                         if self.supports_unions {
                             self.expand_struct_def(
                                 cx,
@@ -663,12 +662,11 @@ fn create_derived_impl(
 
                     for field_ty_param in field_ty_params {
                         // if we have already handled this type, skip it
-                        if let ast::TyKind::Path(_, ref p) = field_ty_param.ty.kind {
-                            if p.segments.len() == 1
-                                && ty_param_names.contains(&p.segments[0].ident.name)
-                            {
-                                continue;
-                            };
+                        if let ast::TyKind::Path(_, p) = &field_ty_param.ty.kind
+                            && let [sole_segment] = &*p.segments
+                            && ty_param_names.contains(&sole_segment.ident.name)
+                        {
+                            continue;
                         }
                         let mut bounds: Vec<_> = self
                             .additional_bounds
index 36e2e29308694741deece6a0106b538a29ddc8b3..eaa4881906a8e3aed446cec6b99657d64972d02f 100644 (file)
@@ -115,7 +115,7 @@ pub fn to_path(
         self_ty: Ident,
         generics: &Generics,
     ) -> ast::Path {
-        match *self {
+        match self {
             Self_ => {
                 let params: Vec<_> = generics
                     .params
@@ -135,7 +135,7 @@ pub fn to_path(
 
                 cx.path_all(span, false, vec![self_ty], params)
             }
-            Path(ref p) => p.to_path(cx, span, self_ty, generics),
+            Path(p) => p.to_path(cx, span, self_ty, generics),
             Ref(..) => cx.span_bug(span, "ref in a path in generic `derive`"),
             Unit => cx.span_bug(span, "unit in a path in generic `derive`"),
         }
@@ -180,10 +180,7 @@ pub fn to_generics(
         let params = self
             .bounds
             .iter()
-            .map(|t| {
-                let (name, ref bounds) = *t;
-                mk_ty_param(cx, span, name, &bounds, self_ty, self_generics)
-            })
+            .map(|&(name, ref bounds)| mk_ty_param(cx, span, name, &bounds, self_ty, self_generics))
             .collect();
 
         Generics {
index 13fdd4fa68c43cd1e70c3683c6ed6db7a5cd7e12..de657e4e6006dcd8aea6ce578dd2657242a488b2 100644 (file)
@@ -125,12 +125,12 @@ fn inject_impl_of_structural_trait(
     structural_path: generic::ty::Path,
     push: &mut dyn FnMut(Annotatable),
 ) {
-    let Annotatable::Item(ref item) = *item else {
+    let Annotatable::Item(item) = item else {
         unreachable!();
     };
 
-    let generics = match item.kind {
-        ItemKind::Struct(_, ref generics) | ItemKind::Enum(_, ref generics) => generics,
+    let generics = match &item.kind {
+        ItemKind::Struct(_, generics) | ItemKind::Enum(_, generics) => generics,
         // Do not inject `impl Structural for Union`. (`PartialEq` does not
         // support unions, so we will see error downstream.)
         ItemKind::Union(..) => return,
index b8828fa671a5ddbc30a21e130a7923fc6282842f..a7283ea601b19e4c20a846beb76663562001da0f 100644 (file)
@@ -52,8 +52,8 @@ pub fn expand_env<'cx>(
     sp: Span,
     tts: TokenStream,
 ) -> Box<dyn base::MacResult + 'cx> {
-    let mut exprs = match get_exprs_from_tts(cx, sp, tts) {
-        Some(ref exprs) if exprs.is_empty() => {
+    let mut exprs = match get_exprs_from_tts(cx, tts) {
+        Some(exprs) if exprs.is_empty() => {
             cx.span_err(sp, "env! takes 1 or 2 arguments");
             return DummyResult::any(sp);
         }
index 8b07c110663572175c42f3da08ef5740f1ff639d..63bc0d552c11e7e24e17bbb45ff095590fd1f18b 100644 (file)
@@ -333,7 +333,7 @@ enum ArgRef<'a> {
             parse::Piece::String(s) => {
                 unfinished_literal.push_str(s);
             }
-            parse::Piece::NextArgument(parse::Argument { position, position_span, format }) => {
+            parse::Piece::NextArgument(box parse::Argument { position, position_span, format }) => {
                 if !unfinished_literal.is_empty() {
                     template.push(FormatArgsPiece::Literal(Symbol::intern(&unfinished_literal)));
                     unfinished_literal.clear();
index ecd16736e7c302e4a518113e20d0c29604b5d718..6f7fc3a95ba640e21311aca2d37b403f0f25a2c4 100644 (file)
@@ -13,23 +13,23 @@ pub enum Substitution<'a> {
 
     impl<'a> Substitution<'a> {
         pub fn as_str(&self) -> &str {
-            match *self {
-                Substitution::Format(ref fmt) => fmt.span,
+            match self {
+                Substitution::Format(fmt) => fmt.span,
                 Substitution::Escape(_) => "%%",
             }
         }
 
         pub fn position(&self) -> Option<InnerSpan> {
-            match *self {
-                Substitution::Format(ref fmt) => Some(fmt.position),
-                Substitution::Escape((start, end)) => Some(InnerSpan::new(start, end)),
+            match self {
+                Substitution::Format(fmt) => Some(fmt.position),
+                &Substitution::Escape((start, end)) => Some(InnerSpan::new(start, end)),
             }
         }
 
         pub fn set_position(&mut self, start: usize, end: usize) {
             match self {
-                Substitution::Format(ref mut fmt) => fmt.position = InnerSpan::new(start, end),
-                Substitution::Escape(ref mut pos) => *pos = (start, end),
+                Substitution::Format(fmt) => fmt.position = InnerSpan::new(start, end),
+                Substitution::Escape(pos) => *pos = (start, end),
             }
         }
 
@@ -38,8 +38,8 @@ pub fn set_position(&mut self, start: usize, end: usize) {
         /// This ignores cases where the substitution does not have an exact equivalent, or where
         /// the substitution would be unnecessary.
         pub fn translate(&self) -> Result<String, Option<String>> {
-            match *self {
-                Substitution::Format(ref fmt) => fmt.translate(),
+            match self {
+                Substitution::Format(fmt) => fmt.translate(),
                 Substitution::Escape(_) => Err(None),
             }
         }
@@ -635,23 +635,17 @@ pub fn as_str(&self) -> String {
         }
 
         pub fn position(&self) -> Option<InnerSpan> {
-            match self {
-                Substitution::Ordinal(_, pos)
-                | Substitution::Name(_, pos)
-                | Substitution::Escape(pos) => Some(InnerSpan::new(pos.0, pos.1)),
-            }
+            let (Self::Ordinal(_, pos) | Self::Name(_, pos) | Self::Escape(pos)) = self;
+            Some(InnerSpan::new(pos.0, pos.1))
         }
 
         pub fn set_position(&mut self, start: usize, end: usize) {
-            match self {
-                Substitution::Ordinal(_, ref mut pos)
-                | Substitution::Name(_, ref mut pos)
-                | Substitution::Escape(ref mut pos) => *pos = (start, end),
-            }
+            let (Self::Ordinal(_, pos) | Self::Name(_, pos) | Self::Escape(pos)) = self;
+            *pos = (start, end);
         }
 
         pub fn translate(&self) -> Result<String, Option<String>> {
-            match *self {
+            match self {
                 Substitution::Ordinal(n, _) => Ok(format!("{{{}}}", n)),
                 Substitution::Name(n, _) => Ok(format!("{{{}}}", n)),
                 Substitution::Escape(_) => Err(None),
index 0817aed037ef814aab672a3f132da1b57f2c865b..f8761653bf5b7d80dde81339468a465eb1f0cfb3 100644 (file)
@@ -20,27 +20,23 @@ pub fn expand(
     check_builtin_macro_attribute(ecx, meta_item, sym::global_allocator);
 
     let orig_item = item.clone();
-    let not_static = || {
-        ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "allocators must be statics");
-        vec![orig_item.clone()]
-    };
 
     // Allow using `#[global_allocator]` on an item statement
     // FIXME - if we get deref patterns, use them to reduce duplication here
-    let (item, is_stmt, ty_span) = match &item {
-        Annotatable::Item(item) => match item.kind {
-            ItemKind::Static(ref ty, ..) => (item, false, ecx.with_def_site_ctxt(ty.span)),
-            _ => return not_static(),
-        },
-        Annotatable::Stmt(stmt) => match &stmt.kind {
-            StmtKind::Item(item_) => match item_.kind {
-                ItemKind::Static(ref ty, ..) => (item_, true, ecx.with_def_site_ctxt(ty.span)),
-                _ => return not_static(),
-            },
-            _ => return not_static(),
-        },
-        _ => return not_static(),
-    };
+    let (item, is_stmt, ty_span) =
+        if let Annotatable::Item(item) = &item
+            && let ItemKind::Static(ty, ..) = &item.kind
+        {
+            (item, false, ecx.with_def_site_ctxt(ty.span))
+        } else if let Annotatable::Stmt(stmt) = &item
+            && let StmtKind::Item(item) = &stmt.kind
+            && let ItemKind::Static(ty, ..) = &item.kind
+        {
+            (item, true, ecx.with_def_site_ctxt(ty.span))
+        } else {
+            ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "allocators must be statics");
+            return vec![orig_item];
+        };
 
     // Generate a bunch of new items using the AllocFnFactory
     let span = ecx.with_def_site_ctxt(item.span);
index 3bcb60478efbc58db96665ce497c42373806fac3..729ae4071e2008b53e1e7276484ab8fb4e021ceb 100644 (file)
@@ -239,8 +239,7 @@ pub fn expand_test_or_bench(
             cx.attr_nested_word(sym::cfg, sym::test, attr_sp),
             // #[rustc_test_marker = "test_case_sort_key"]
             cx.attr_name_value_str(sym::rustc_test_marker, test_path_symbol, attr_sp),
-        ]
-        .into(),
+        ],
         // const $ident: test::TestDescAndFn =
         ast::ItemKind::Const(
             ast::Defaultness::Final,
@@ -466,61 +465,67 @@ fn test_type(cx: &ExtCtxt<'_>) -> TestType {
 fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
     let has_should_panic_attr = cx.sess.contains_name(&i.attrs, sym::should_panic);
     let sd = &cx.sess.parse_sess.span_diagnostic;
-    if let ast::ItemKind::Fn(box ast::Fn { ref sig, ref generics, .. }) = i.kind {
-        if let ast::Unsafe::Yes(span) = sig.header.unsafety {
-            sd.struct_span_err(i.span, "unsafe functions cannot be used for tests")
-                .span_label(span, "`unsafe` because of this")
-                .emit();
-            return false;
-        }
-        if let ast::Async::Yes { span, .. } = sig.header.asyncness {
-            sd.struct_span_err(i.span, "async functions cannot be used for tests")
-                .span_label(span, "`async` because of this")
-                .emit();
-            return false;
-        }
-
-        // If the termination trait is active, the compiler will check that the output
-        // type implements the `Termination` trait as `libtest` enforces that.
-        let has_output = match sig.decl.output {
-            ast::FnRetTy::Default(..) => false,
-            ast::FnRetTy::Ty(ref t) if t.kind.is_unit() => false,
-            _ => true,
-        };
-
-        if !sig.decl.inputs.is_empty() {
-            sd.span_err(i.span, "functions used as tests can not have any arguments");
-            return false;
-        }
+    match &i.kind {
+        ast::ItemKind::Fn(box ast::Fn { sig, generics, .. }) => {
+            if let ast::Unsafe::Yes(span) = sig.header.unsafety {
+                sd.struct_span_err(i.span, "unsafe functions cannot be used for tests")
+                    .span_label(span, "`unsafe` because of this")
+                    .emit();
+                return false;
+            }
+            if let ast::Async::Yes { span, .. } = sig.header.asyncness {
+                sd.struct_span_err(i.span, "async functions cannot be used for tests")
+                    .span_label(span, "`async` because of this")
+                    .emit();
+                return false;
+            }
 
-        match (has_output, has_should_panic_attr) {
-            (true, true) => {
-                sd.span_err(i.span, "functions using `#[should_panic]` must return `()`");
-                false
+            // If the termination trait is active, the compiler will check that the output
+            // type implements the `Termination` trait as `libtest` enforces that.
+            let has_output = match &sig.decl.output {
+                ast::FnRetTy::Default(..) => false,
+                ast::FnRetTy::Ty(t) if t.kind.is_unit() => false,
+                _ => true,
+            };
+
+            if !sig.decl.inputs.is_empty() {
+                sd.span_err(i.span, "functions used as tests can not have any arguments");
+                return false;
             }
-            (true, false) => {
-                if !generics.params.is_empty() {
-                    sd.span_err(i.span, "functions used as tests must have signature fn() -> ()");
+
+            match (has_output, has_should_panic_attr) {
+                (true, true) => {
+                    sd.span_err(i.span, "functions using `#[should_panic]` must return `()`");
                     false
-                } else {
-                    true
                 }
+                (true, false) => {
+                    if !generics.params.is_empty() {
+                        sd.span_err(
+                            i.span,
+                            "functions used as tests must have signature fn() -> ()",
+                        );
+                        false
+                    } else {
+                        true
+                    }
+                }
+                (false, _) => true,
             }
-            (false, _) => true,
         }
-    } else {
-        // should be unreachable because `is_test_fn_item` should catch all non-fn items
-        false
+        _ => {
+            // should be unreachable because `is_test_fn_item` should catch all non-fn items
+            debug_assert!(false);
+            false
+        }
     }
 }
 
 fn has_bench_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
-    let has_sig = if let ast::ItemKind::Fn(box ast::Fn { ref sig, .. }) = i.kind {
+    let has_sig = match &i.kind {
         // N.B., inadequate check, but we're running
         // well before resolve, can't get too deep.
-        sig.decl.inputs.len() == 1
-    } else {
-        false
+        ast::ItemKind::Fn(box ast::Fn { sig, .. }) => sig.decl.inputs.len() == 1,
+        _ => false,
     };
 
     if !has_sig {
index b5bce9278a907311d22e90493dba96dff9aee7b2..ad8871080910640e11e123b8f27221101f2a543d 100644 (file)
@@ -131,8 +131,9 @@ fn visit_crate(&mut self, c: &mut ast::Crate) {
 
         // We don't want to recurse into anything other than mods, since
         // mods or tests inside of functions will break things
-        if let ast::ItemKind::Mod(_, ModKind::Loaded(.., ref spans)) = item.kind {
-            let ast::ModSpans { inner_span: span, inject_use_span: _ } = *spans;
+        if let ast::ItemKind::Mod(_, ModKind::Loaded(.., ast::ModSpans { inner_span: span, .. })) =
+            item.kind
+        {
             let prev_tests = mem::take(&mut self.tests);
             noop_visit_item_kind(&mut item.kind, self);
             self.add_test_cases(item.id, span, prev_tests);
index 732edd66196d7de4c3d8d18e0c944e05d279906c..d627c2ee09c4ef7555f820cc2a239b73c3133269 100644 (file)
@@ -12,8 +12,6 @@ task:
     folder: target
   prepare_script:
     - . $HOME/.cargo/env
-    - git config --global user.email "user@example.com"
-    - git config --global user.name "User"
     - ./y.rs prepare
   test_script:
     - . $HOME/.cargo/env
index 5061010c86cd3451d4b8e7858b05cecf7efc8631..a6bb12a66a247d66441c390105655e9ff0910978 100644 (file)
@@ -19,6 +19,7 @@ jobs:
     - name: Rustfmt
       run: |
         cargo fmt --check
+        rustfmt --check build_system/mod.rs
 
   build:
     runs-on: ${{ matrix.os }}
@@ -28,7 +29,7 @@ jobs:
       fail-fast: false
       matrix:
         include:
-          - os: ubuntu-latest
+          - os: ubuntu-20.04 # FIXME switch to ubuntu-22.04 once #1303 is fixed
             env:
               TARGET_TRIPLE: x86_64-unknown-linux-gnu
           - os: macos-latest
@@ -41,18 +42,22 @@ jobs:
           - os: ubuntu-latest
             env:
               TARGET_TRIPLE: aarch64-unknown-linux-gnu
+          # s390x requires QEMU 6.1 or greater, we could build it from source, but ubuntu 22.04 comes with 6.2 by default
+          - os: ubuntu-latest
+            env:
+              TARGET_TRIPLE: s390x-unknown-linux-gnu
 
     steps:
     - uses: actions/checkout@v3
 
     - name: Cache cargo installed crates
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
         path: ~/.cargo/bin
         key: ${{ runner.os }}-cargo-installed-crates
 
     - name: Cache cargo registry and index
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
         path: |
             ~/.cargo/registry
@@ -60,9 +65,9 @@ jobs:
         key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
 
     - name: Cache cargo target dir
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
-        path: target
+        path: build/cg_clif
         key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
 
     - name: Install MinGW toolchain and wine
@@ -78,11 +83,14 @@ jobs:
         sudo apt-get update
         sudo apt-get install -y gcc-aarch64-linux-gnu qemu-user
 
-    - name: Prepare dependencies
+    - name: Install s390x toolchain and qemu
+      if: matrix.env.TARGET_TRIPLE == 's390x-unknown-linux-gnu'
       run: |
-        git config --global user.email "user@example.com"
-        git config --global user.name "User"
-        ./y.rs prepare
+        sudo apt-get update
+        sudo apt-get install -y gcc-s390x-linux-gnu qemu-user
+
+    - name: Prepare dependencies
+      run: ./y.rs prepare
 
     - name: Build without unstable features
       env:
@@ -110,7 +118,7 @@ jobs:
         ./y.rs test
 
     - name: Package prebuilt cg_clif
-      run: tar cvfJ cg_clif.tar.xz build
+      run: tar cvfJ cg_clif.tar.xz dist
 
     - name: Upload prebuilt cg_clif
       if: matrix.env.TARGET_TRIPLE != 'x86_64-pc-windows-gnu'
@@ -121,7 +129,7 @@ jobs:
 
     - name: Upload prebuilt cg_clif (cross compile)
       if: matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
-      uses: actions/upload-artifact@v2
+      uses: actions/upload-artifact@v3
       with:
         name: cg_clif-${{ runner.os }}-cross-x86_64-mingw
         path: cg_clif.tar.xz
@@ -147,13 +155,13 @@ jobs:
     - uses: actions/checkout@v3
 
     - name: Cache cargo installed crates
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
         path: ~/.cargo/bin
         key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-installed-crates
 
     - name: Cache cargo registry and index
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
         path: |
             ~/.cargo/registry
@@ -161,9 +169,9 @@ jobs:
         key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
 
     - name: Cache cargo target dir
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
-        path: target
+        path: build/cg_clif
         key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
 
     - name: Set MinGW as the default toolchain
@@ -172,8 +180,6 @@ jobs:
 
     - name: Prepare dependencies
       run: |
-        git config --global user.email "user@example.com"
-        git config --global user.name "User"
         git config --global core.autocrlf false
         rustc y.rs -o y.exe -g
         ./y.exe prepare
@@ -198,24 +204,24 @@ jobs:
 
         # Enable extra checks
         $Env:CG_CLIF_ENABLE_VERIFIER=1
-        
+
         # WIP Disable some tests
-        
+
         # This fails due to some weird argument handling by hyperfine, not an actual regression
         # more of a build system issue
         (Get-Content config.txt) -replace '(bench.simple-raytracer)', '# $1' |  Out-File config.txt
-        
-        # This fails with a different output than expected 
+
+        # This fails with a different output than expected
         (Get-Content config.txt) -replace '(test.regex-shootout-regex-dna)', '# $1' |  Out-File config.txt
 
         ./y.exe test
 
     - name: Package prebuilt cg_clif
       # don't use compression as xzip isn't supported by tar on windows and bzip2 hangs
-      run: tar cvf cg_clif.tar build
+      run: tar cvf cg_clif.tar dist
 
     - name: Upload prebuilt cg_clif
-      uses: actions/upload-artifact@v2
+      uses: actions/upload-artifact@v3
       with:
         name: cg_clif-${{ matrix.env.TARGET_TRIPLE }}
         path: cg_clif.tar
index 0a3e7ca073b45debb68785811cf0f727a7e0bde7..d0d58d2a7eacbd19a07442af167bdb0e2926274a 100644 (file)
@@ -14,7 +14,7 @@ jobs:
     - uses: actions/checkout@v3
 
     - name: Cache cargo installed crates
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
         path: ~/.cargo/bin
         key: ubuntu-latest-cargo-installed-crates
index b8a98b83ebe5eb1a5d292f5fa6b2b7df1168a5a9..bef806318efa836aeeb8d6df06d880b77be677fb 100644 (file)
@@ -11,13 +11,13 @@ jobs:
     - uses: actions/checkout@v3
 
     - name: Cache cargo installed crates
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
         path: ~/.cargo/bin
         key: ${{ runner.os }}-cargo-installed-crates
 
     - name: Cache cargo registry and index
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
         path: |
             ~/.cargo/registry
@@ -25,9 +25,9 @@ jobs:
         key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
 
     - name: Cache cargo target dir
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
-        path: target
+        path: build/cg_clif
         key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
 
     - name: Prepare dependencies
@@ -49,13 +49,13 @@ jobs:
     - uses: actions/checkout@v3
 
     - name: Cache cargo installed crates
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
         path: ~/.cargo/bin
         key: ${{ runner.os }}-cargo-installed-crates
 
     - name: Cache cargo registry and index
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
         path: |
             ~/.cargo/registry
@@ -63,9 +63,9 @@ jobs:
         key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
 
     - name: Cache cargo target dir
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
-        path: target
+        path: build/cg_clif
         key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
 
     - name: Prepare dependencies
index fae09592c6ac0dc91be2641093896c0adc9559d8..b443fd58a1b98344bec2720e26139b6467907d89 100644 (file)
@@ -14,5 +14,6 @@ perf.data.old
 /build_sysroot/sysroot_src
 /build_sysroot/compiler-builtins
 /build_sysroot/rustc_version
+/dist
 /rust
 /download
index 13301bf20a5ed7d57051c9b45fa4165a98e8b7b5..bc914e37d2b51dda8d3a0e4ef090a4cc1399fc90 100644 (file)
@@ -4,16 +4,10 @@
     "rust-analyzer.imports.granularity.enforce": true,
     "rust-analyzer.imports.granularity.group": "module",
     "rust-analyzer.imports.prefix": "crate",
-    "rust-analyzer.cargo.features": ["unstable-features"],
+    "rust-analyzer.cargo.features": ["unstable-features", "__check_build_system_using_ra"],
     "rust-analyzer.linkedProjects": [
         "./Cargo.toml",
-        //"./build_sysroot/sysroot_src/library/std/Cargo.toml",
         {
-            "roots": [
-                "./example/mini_core.rs",
-                "./example/mini_core_hello_world.rs",
-                "./example/mod_bench.rs"
-            ],
             "crates": [
                 {
                     "root_module": "./example/mini_core.rs",
             ]
         },
         {
-            "roots": ["./example/std_example.rs"],
+            "sysroot_src": "./build_sysroot/sysroot_src/library",
             "crates": [
                 {
                     "root_module": "./example/std_example.rs",
-                    "edition": "2018",
-                    "deps": [{ "crate": 1, "name": "std" }],
-                    "cfg": [],
-                },
-                {
-                    "root_module": "./build_sysroot/sysroot_src/library/std/src/lib.rs",
-                    "edition": "2018",
-                    "deps": [],
-                    "cfg": [],
-                },
-            ]
-        },
-        {
-            "roots": ["./y.rs"],
-            "crates": [
-                {
-                    "root_module": "./y.rs",
-                    "edition": "2018",
-                    "deps": [{ "crate": 1, "name": "std" }],
-                    "cfg": [],
-                },
-                {
-                    "root_module": "./build_sysroot/sysroot_src/library/std/src/lib.rs",
-                    "edition": "2018",
+                    "edition": "2015",
                     "deps": [],
                     "cfg": [],
                 },
index 3b406036c356e9e3023964f049184a2d1f0121f5..e4d3e9ca5ae0a8676863063216c420232248a554 100644 (file)
@@ -15,9 +15,9 @@ dependencies = [
 
 [[package]]
 name = "anyhow"
-version = "1.0.60"
+version = "1.0.66"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c794e162a5eff65c72ef524dfe393eb923c354e350bb78b9c7383df13f3bc142"
+checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
 
 [[package]]
 name = "arrayvec"
@@ -39,9 +39,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
 [[package]]
 name = "bumpalo"
-version = "3.11.0"
+version = "3.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
+checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
 
 [[package]]
 name = "byteorder"
@@ -57,24 +57,25 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "cranelift-bforest"
-version = "0.88.1"
+version = "0.90.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44409ccf2d0f663920cab563d2b79fcd6b2e9a2bcc6e929fef76c8f82ad6c17a"
+checksum = "b62c772976416112fa4484cbd688cb6fb35fd430005c1c586224fc014018abad"
 dependencies = [
  "cranelift-entity",
 ]
 
 [[package]]
 name = "cranelift-codegen"
-version = "0.88.1"
+version = "0.90.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "98de2018ad96eb97f621f7d6b900a0cc661aec8d02ea4a50e56ecb48e5a2fcaf"
+checksum = "9b40ed2dd13c2ac7e24f88a3090c68ad3414eb1d066a95f8f1f7b3b819cb4e46"
 dependencies = [
  "arrayvec",
  "bumpalo",
  "cranelift-bforest",
  "cranelift-codegen-meta",
  "cranelift-codegen-shared",
+ "cranelift-egraph",
  "cranelift-entity",
  "cranelift-isle",
  "gimli",
@@ -86,30 +87,44 @@ dependencies = [
 
 [[package]]
 name = "cranelift-codegen-meta"
-version = "0.88.1"
+version = "0.90.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5287ce36e6c4758fbaf298bd1a8697ad97a4f2375a3d1b61142ea538db4877e5"
+checksum = "bb927a8f1c27c34ee3759b6b0ffa528d2330405d5cc4511f0cab33fe2279f4b5"
 dependencies = [
  "cranelift-codegen-shared",
 ]
 
 [[package]]
 name = "cranelift-codegen-shared"
-version = "0.88.1"
+version = "0.90.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2855c24219e2f08827f3f4ffb2da92e134ae8d8ecc185b11ec8f9878cf5f588e"
+checksum = "43dfa417b884a9ab488d95fd6b93b25e959321fe7bfd7a0a960ba5d7fb7ab927"
+
+[[package]]
+name = "cranelift-egraph"
+version = "0.90.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0a66b39785efd8513d2cca967ede56d6cc57c8d7986a595c7c47d0c78de8dce"
+dependencies = [
+ "cranelift-entity",
+ "fxhash",
+ "hashbrown",
+ "indexmap",
+ "log",
+ "smallvec",
+]
 
 [[package]]
 name = "cranelift-entity"
-version = "0.88.1"
+version = "0.90.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b65673279d75d34bf11af9660ae2dbd1c22e6d28f163f5c72f4e1dc56d56103"
+checksum = "0637ffde963cb5d759bc4d454cfa364b6509e6c74cdaa21298add0ed9276f346"
 
 [[package]]
 name = "cranelift-frontend"
-version = "0.88.1"
+version = "0.90.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ed2b3d7a4751163f6c4a349205ab1b7d9c00eecf19dcea48592ef1f7688eefc"
+checksum = "fb72b8342685e850cb037350418f62cc4fc55d6c2eb9c7ca01b82f9f1a6f3d56"
 dependencies = [
  "cranelift-codegen",
  "log",
@@ -119,15 +134,15 @@ dependencies = [
 
 [[package]]
 name = "cranelift-isle"
-version = "0.88.1"
+version = "0.90.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3be64cecea9d90105fc6a2ba2d003e98c867c1d6c4c86cc878f97ad9fb916293"
+checksum = "850579cb9e4b448f7c301f1e6e6cbad99abe3f1f1d878a4994cb66e33c6db8cd"
 
 [[package]]
 name = "cranelift-jit"
-version = "0.88.1"
+version = "0.90.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f98ed42a70a0c9c388e34ec9477f57fc7300f541b1e5136a0e2ea02b1fac6015"
+checksum = "9add822ad66dcbe152b5ab57de10240a2df4505099f2f6c27159acb711890bd4"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -138,14 +153,15 @@ dependencies = [
  "log",
  "region",
  "target-lexicon",
+ "wasmtime-jit-icache-coherence",
  "windows-sys",
 ]
 
 [[package]]
 name = "cranelift-module"
-version = "0.88.1"
+version = "0.90.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d658ac7f156708bfccb647216cc8b9387469f50d352ba4ad80150541e4ae2d49"
+checksum = "406b772626fc2664864cf947f3895a23b619895c7fff635f3622e2d857f4492f"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -153,9 +169,9 @@ dependencies = [
 
 [[package]]
 name = "cranelift-native"
-version = "0.88.1"
+version = "0.90.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4a03a6ac1b063e416ca4b93f6247978c991475e8271465340caa6f92f3c16a4"
+checksum = "2d0a279e5bcba3e0466c734d8d8eb6bfc1ad29e95c37f3e4955b492b5616335e"
 dependencies = [
  "cranelift-codegen",
  "libc",
@@ -164,9 +180,9 @@ dependencies = [
 
 [[package]]
 name = "cranelift-object"
-version = "0.88.1"
+version = "0.90.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eef0b4119b645b870a43a036d76c0ada3a076b1f82e8b8487659304c8b09049b"
+checksum = "39793c550f0c1d7db96c2fc1324583670c8143befe6edbfbaf1c68aba53be983"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -185,6 +201,12 @@ dependencies = [
  "cfg-if",
 ]
 
+[[package]]
+name = "fallible-iterator"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
+
 [[package]]
 name = "fxhash"
 version = "0.2.1"
@@ -196,9 +218,9 @@ dependencies = [
 
 [[package]]
 name = "getrandom"
-version = "0.2.7"
+version = "0.2.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
+checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
 dependencies = [
  "cfg-if",
  "libc",
@@ -211,7 +233,9 @@ version = "0.26.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
 dependencies = [
+ "fallible-iterator",
  "indexmap",
+ "stable_deref_trait",
 ]
 
 [[package]]
@@ -225,9 +249,9 @@ dependencies = [
 
 [[package]]
 name = "indexmap"
-version = "1.9.1"
+version = "1.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
+checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
 dependencies = [
  "autocfg",
  "hashbrown",
@@ -235,15 +259,15 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.127"
+version = "0.2.138"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b"
+checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
 
 [[package]]
 name = "libloading"
-version = "0.7.3"
+version = "0.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd"
+checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
 dependencies = [
  "cfg-if",
  "winapi",
@@ -287,15 +311,15 @@ dependencies = [
 
 [[package]]
 name = "once_cell"
-version = "1.13.0"
+version = "1.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
+checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
 
 [[package]]
 name = "regalloc2"
-version = "0.3.2"
+version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d43a209257d978ef079f3d446331d0f1794f5e0fc19b306a199983857833a779"
+checksum = "91b2eab54204ea0117fe9a060537e0b07a4e72f7c7d182361ecc346cab2240e5"
 dependencies = [
  "fxhash",
  "log",
@@ -342,15 +366,21 @@ checksum = "03b634d87b960ab1a38c4fe143b508576f075e7c978bfad18217645ebfdfa2ec"
 
 [[package]]
 name = "smallvec"
-version = "1.9.0"
+version = "1.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"
+checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
+
+[[package]]
+name = "stable_deref_trait"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
 
 [[package]]
 name = "target-lexicon"
-version = "0.12.4"
+version = "0.12.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c02424087780c9b71cc96799eaeddff35af2bc513278cda5c99fc1f5d026d3c1"
+checksum = "9410d0f6853b1d94f0e519fb95df60f29d2c1eff2d921ffdf01a4c8a3b54f12d"
 
 [[package]]
 name = "version_check"
@@ -364,6 +394,17 @@ version = "0.11.0+wasi-snapshot-preview1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
+[[package]]
+name = "wasmtime-jit-icache-coherence"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6bbabb309c06cc238ee91b1455b748c45f0bdcab0dda2c2db85b0a1e69fcb66"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "windows-sys",
+]
+
 [[package]]
 name = "winapi"
 version = "0.3.9"
index 0fdd5de118ccb10cb4db0776c5ca9c69b19cc07f..2b216ca072f0096832412085a0eae3fda4dc79ff 100644 (file)
@@ -3,17 +3,24 @@ name = "rustc_codegen_cranelift"
 version = "0.1.0"
 edition = "2021"
 
+[[bin]]
+# This is used just to teach rust-analyzer how to check the build system. required-features is used
+# to disable it for regular builds.
+name = "y"
+path = "./y.rs"
+required-features = ["__check_build_system_using_ra"]
+
 [lib]
 crate-type = ["dylib"]
 
 [dependencies]
 # These have to be in sync with each other
-cranelift-codegen = { version = "0.88.1", features = ["unwind", "all-arch"] }
-cranelift-frontend = "0.88.1"
-cranelift-module = "0.88.1"
-cranelift-native = "0.88.1"
-cranelift-jit = { version = "0.88.1", optional = true }
-cranelift-object = "0.88.1"
+cranelift-codegen = { version = "0.90.1", features = ["unwind", "all-arch"] }
+cranelift-frontend = "0.90.1"
+cranelift-module = "0.90.1"
+cranelift-native = "0.90.1"
+cranelift-jit = { version = "0.90.1", optional = true }
+cranelift-object = "0.90.1"
 target-lexicon = "0.12.0"
 gimli = { version = "0.26.0", default-features = false, features = ["write"]}
 object = { version = "0.29.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
@@ -39,6 +46,7 @@ smallvec = "1.8.1"
 unstable-features = ["jit", "inline_asm"]
 jit = ["cranelift-jit", "libloading"]
 inline_asm = []
+__check_build_system_using_ra = []
 
 [package.metadata.rust-analyzer]
 rustc_private = true
index 1e84c7fa3657b37afeb26614a49896fab8846b40..0e9c77244d4cc85d765371e97370db5c0adebf11 100644 (file)
@@ -37,7 +37,7 @@ Assuming `$cg_clif_dir` is the directory you cloned this repo into and you follo
 In the directory with your project (where you can do the usual `cargo build`), run:
 
 ```bash
-$ $cg_clif_dir/build/cargo-clif build
+$ $cg_clif_dir/dist/cargo-clif build
 ```
 
 This will build your project with rustc_codegen_cranelift instead of the usual LLVM backend.
index f6a9cb67290c7d88d591a72b2abfafaa2df67c28..bba3210536ef7832e44ba9dbb5e46c3ee036baf6 100644 (file)
@@ -4,9 +4,9 @@ version = 3
 
 [[package]]
 name = "addr2line"
-version = "0.16.0"
+version = "0.17.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e61f2b7f93d2c7d2b08263acaa4a363b3e276806c68af6134c44f523bf1aacd"
+checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
 dependencies = [
  "compiler_builtins",
  "gimli",
@@ -32,27 +32,11 @@ dependencies = [
  "core",
 ]
 
-[[package]]
-name = "autocfg"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
-
 [[package]]
 name = "cc"
-version = "1.0.73"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
-
-[[package]]
-name = "cfg-if"
-version = "0.1.10"
+version = "1.0.77"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
-dependencies = [
- "compiler_builtins",
- "rustc-std-workspace-core",
-]
+checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"
 
 [[package]]
 name = "cfg-if"
@@ -66,9 +50,9 @@ dependencies = [
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.82"
+version = "0.1.85"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18cd7635fea7bb481ea543b392789844c1ad581299da70184c7175ce3af76603"
+checksum = "13e81c6cd7ab79f51a0c927d22858d61ad12bd0b3865f0b13ece02a4486aeabb"
 dependencies = [
  "rustc-std-workspace-core",
 ]
@@ -111,9 +95,9 @@ dependencies = [
 
 [[package]]
 name = "gimli"
-version = "0.25.0"
+version = "0.26.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7"
+checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
 dependencies = [
  "compiler_builtins",
  "rustc-std-workspace-alloc",
@@ -145,9 +129,9 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.135"
+version = "0.2.138"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c"
+checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
 dependencies = [
  "rustc-std-workspace-core",
 ]
@@ -164,12 +148,11 @@ dependencies = [
 
 [[package]]
 name = "miniz_oxide"
-version = "0.4.4"
+version = "0.5.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
+checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34"
 dependencies = [
  "adler",
- "autocfg",
  "compiler_builtins",
  "rustc-std-workspace-alloc",
  "rustc-std-workspace-core",
@@ -177,9 +160,9 @@ dependencies = [
 
 [[package]]
 name = "object"
-version = "0.26.2"
+version = "0.29.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39f37e50073ccad23b6d09bcb5b263f4e76d3bb6038e4a3c08e52162ffa8abc2"
+checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
 dependencies = [
  "compiler_builtins",
  "memchr",
@@ -192,7 +175,7 @@ name = "panic_abort"
 version = "0.0.0"
 dependencies = [
  "alloc",
- "cfg-if 0.1.10",
+ "cfg-if",
  "compiler_builtins",
  "core",
  "libc",
@@ -203,7 +186,7 @@ name = "panic_unwind"
 version = "0.0.0"
 dependencies = [
  "alloc",
- "cfg-if 0.1.10",
+ "cfg-if",
  "compiler_builtins",
  "core",
  "libc",
@@ -255,7 +238,7 @@ version = "0.0.0"
 dependencies = [
  "addr2line",
  "alloc",
- "cfg-if 1.0.0",
+ "cfg-if",
  "compiler_builtins",
  "core",
  "dlmalloc",
@@ -277,7 +260,7 @@ dependencies = [
 name = "std_detect"
 version = "0.1.5"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
  "compiler_builtins",
  "libc",
  "rustc-std-workspace-alloc",
@@ -299,7 +282,7 @@ dependencies = [
 name = "test"
 version = "0.0.0"
 dependencies = [
- "cfg-if 0.1.10",
+ "cfg-if",
  "core",
  "getopts",
  "libc",
@@ -325,7 +308,7 @@ name = "unwind"
 version = "0.0.0"
 dependencies = [
  "cc",
- "cfg-if 0.1.10",
+ "cfg-if",
  "compiler_builtins",
  "core",
  "libc",
index fae5b27163680badc511023892f92fe462ddfbaf..a081fdaa1c7e6475a727f764c033f07090b2b87e 100644 (file)
@@ -1,16 +1,21 @@
-use std::env;
 use std::path::Path;
 
 use super::build_sysroot;
 use super::config;
-use super::prepare;
-use super::utils::{cargo_command, spawn_and_wait};
+use super::path::Dirs;
+use super::prepare::GitRepo;
+use super::utils::{spawn_and_wait, CargoProject, Compiler};
 use super::SysrootKind;
 
+pub(crate) static ABI_CAFE_REPO: GitRepo =
+    GitRepo::github("Gankra", "abi-cafe", "4c6dc8c9c687e2b3a760ff2176ce236872b37212", "abi-cafe");
+
+static ABI_CAFE: CargoProject = CargoProject::new(&ABI_CAFE_REPO.source_dir(), "abi_cafe");
+
 pub(crate) fn run(
     channel: &str,
     sysroot_kind: SysrootKind,
-    target_dir: &Path,
+    dirs: &Dirs,
     cg_clif_dylib: &Path,
     host_triple: &str,
     target_triple: &str,
@@ -27,26 +32,25 @@ pub(crate) fn run(
 
     eprintln!("Building sysroot for abi-cafe");
     build_sysroot::build_sysroot(
+        dirs,
         channel,
         sysroot_kind,
-        target_dir,
         cg_clif_dylib,
         host_triple,
         target_triple,
     );
 
     eprintln!("Running abi-cafe");
-    let abi_cafe_path = prepare::ABI_CAFE.source_dir();
-    env::set_current_dir(abi_cafe_path.clone()).unwrap();
 
     let pairs = ["rustc_calls_cgclif", "cgclif_calls_rustc", "cgclif_calls_cc", "cc_calls_cgclif"];
 
-    let mut cmd = cargo_command("cargo", "run", Some(target_triple), &abi_cafe_path);
+    let mut cmd = ABI_CAFE.run(&Compiler::host(), dirs);
     cmd.arg("--");
     cmd.arg("--pairs");
     cmd.args(pairs);
     cmd.arg("--add-rustc-codegen-backend");
     cmd.arg(format!("cgclif:{}", cg_clif_dylib.display()));
+    cmd.current_dir(ABI_CAFE.source_dir(dirs));
 
     spawn_and_wait(cmd);
 }
index cda468bcfa2dfc2e0bfe494bd5a1a9414a97eed6..fde8ef424ccc5441e0198ef7b33b23c39dbe37bc 100644 (file)
@@ -1,16 +1,19 @@
 use std::env;
 use std::path::PathBuf;
 
+use super::path::{Dirs, RelPath};
 use super::rustc_info::get_file_name;
-use super::utils::{cargo_command, is_ci};
+use super::utils::{is_ci, CargoProject, Compiler};
+
+static CG_CLIF: CargoProject = CargoProject::new(&RelPath::SOURCE, "cg_clif");
 
 pub(crate) fn build_backend(
+    dirs: &Dirs,
     channel: &str,
     host_triple: &str,
     use_unstable_features: bool,
 ) -> PathBuf {
-    let source_dir = std::env::current_dir().unwrap();
-    let mut cmd = cargo_command("cargo", "build", Some(host_triple), &source_dir);
+    let mut cmd = CG_CLIF.build(&Compiler::host(), dirs);
 
     cmd.env("CARGO_BUILD_INCREMENTAL", "true"); // Force incr comp even in release mode
 
@@ -41,8 +44,8 @@ pub(crate) fn build_backend(
     eprintln!("[BUILD] rustc_codegen_cranelift");
     super::utils::spawn_and_wait(cmd);
 
-    source_dir
-        .join("target")
+    CG_CLIF
+        .target_dir(dirs)
         .join(host_triple)
         .join(channel)
         .join(get_file_name("rustc_codegen_cranelift", "dylib"))
index 856aecc49fd1c05f476c91232c9bb0b429c4c907..cbbf09b9b97b8422ab06caff3b59b34c6352dfd4 100644 (file)
@@ -1,57 +1,60 @@
 use std::fs;
-use std::path::{Path, PathBuf};
+use std::path::Path;
 use std::process::{self, Command};
 
+use super::path::{Dirs, RelPath};
 use super::rustc_info::{get_file_name, get_rustc_version, get_wrapper_file_name};
-use super::utils::{cargo_command, spawn_and_wait, try_hard_link};
+use super::utils::{spawn_and_wait, try_hard_link, CargoProject, Compiler};
 use super::SysrootKind;
 
+static DIST_DIR: RelPath = RelPath::DIST;
+static BIN_DIR: RelPath = RelPath::DIST.join("bin");
+static LIB_DIR: RelPath = RelPath::DIST.join("lib");
+static RUSTLIB_DIR: RelPath = LIB_DIR.join("rustlib");
+
 pub(crate) fn build_sysroot(
+    dirs: &Dirs,
     channel: &str,
     sysroot_kind: SysrootKind,
-    target_dir: &Path,
     cg_clif_dylib_src: &Path,
     host_triple: &str,
     target_triple: &str,
 ) {
     eprintln!("[BUILD] sysroot {:?}", sysroot_kind);
 
-    if target_dir.exists() {
-        fs::remove_dir_all(target_dir).unwrap();
-    }
-    fs::create_dir_all(target_dir.join("bin")).unwrap();
-    fs::create_dir_all(target_dir.join("lib")).unwrap();
+    DIST_DIR.ensure_fresh(dirs);
+    BIN_DIR.ensure_exists(dirs);
+    LIB_DIR.ensure_exists(dirs);
 
     // Copy the backend
-    let cg_clif_dylib_path = target_dir
-        .join(if cfg!(windows) {
-            // Windows doesn't have rpath support, so the cg_clif dylib needs to be next to the
-            // binaries.
-            "bin"
-        } else {
-            "lib"
-        })
-        .join(get_file_name("rustc_codegen_cranelift", "dylib"));
+    let cg_clif_dylib_path = if cfg!(windows) {
+        // Windows doesn't have rpath support, so the cg_clif dylib needs to be next to the
+        // binaries.
+        BIN_DIR
+    } else {
+        LIB_DIR
+    }
+    .to_path(dirs)
+    .join(get_file_name("rustc_codegen_cranelift", "dylib"));
     try_hard_link(cg_clif_dylib_src, &cg_clif_dylib_path);
 
     // Build and copy rustc and cargo wrappers
-    for wrapper in ["rustc-clif", "cargo-clif"] {
+    for wrapper in ["rustc-clif", "rustdoc-clif", "cargo-clif"] {
         let wrapper_name = get_wrapper_file_name(wrapper, "bin");
 
         let mut build_cargo_wrapper_cmd = Command::new("rustc");
         build_cargo_wrapper_cmd
-            .arg(PathBuf::from("scripts").join(format!("{wrapper}.rs")))
+            .arg(RelPath::SCRIPTS.to_path(dirs).join(&format!("{wrapper}.rs")))
             .arg("-o")
-            .arg(target_dir.join(wrapper_name))
+            .arg(DIST_DIR.to_path(dirs).join(wrapper_name))
             .arg("-g");
         spawn_and_wait(build_cargo_wrapper_cmd);
     }
 
     let default_sysroot = super::rustc_info::get_default_sysroot();
 
-    let rustlib = target_dir.join("lib").join("rustlib");
-    let host_rustlib_lib = rustlib.join(host_triple).join("lib");
-    let target_rustlib_lib = rustlib.join(target_triple).join("lib");
+    let host_rustlib_lib = RUSTLIB_DIR.to_path(dirs).join(host_triple).join("lib");
+    let target_rustlib_lib = RUSTLIB_DIR.to_path(dirs).join(target_triple).join("lib");
     fs::create_dir_all(&host_rustlib_lib).unwrap();
     fs::create_dir_all(&target_rustlib_lib).unwrap();
 
@@ -112,24 +115,18 @@ pub(crate) fn build_sysroot(
             }
         }
         SysrootKind::Clif => {
-            build_clif_sysroot_for_triple(
-                channel,
-                target_dir,
-                host_triple,
-                &cg_clif_dylib_path,
-                None,
-            );
+            build_clif_sysroot_for_triple(dirs, channel, host_triple, &cg_clif_dylib_path, None);
 
             if host_triple != target_triple {
                 // When cross-compiling it is often necessary to manually pick the right linker
-                let linker = if target_triple == "aarch64-unknown-linux-gnu" {
-                    Some("aarch64-linux-gnu-gcc")
-                } else {
-                    None
+                let linker = match target_triple {
+                    "aarch64-unknown-linux-gnu" => Some("aarch64-linux-gnu-gcc"),
+                    "s390x-unknown-linux-gnu" => Some("s390x-linux-gnu-gcc"),
+                    _ => None,
                 };
                 build_clif_sysroot_for_triple(
+                    dirs,
                     channel,
-                    target_dir,
                     target_triple,
                     &cg_clif_dylib_path,
                     linker,
@@ -142,21 +139,26 @@ pub(crate) fn build_sysroot(
                 let file = file.unwrap().path();
                 let filename = file.file_name().unwrap().to_str().unwrap();
                 if filename.contains("std-") && !filename.contains(".rlib") {
-                    try_hard_link(&file, target_dir.join("lib").join(file.file_name().unwrap()));
+                    try_hard_link(&file, LIB_DIR.to_path(dirs).join(file.file_name().unwrap()));
                 }
             }
         }
     }
 }
 
+// FIXME move to download/ or dist/
+pub(crate) static SYSROOT_RUSTC_VERSION: RelPath = RelPath::BUILD_SYSROOT.join("rustc_version");
+pub(crate) static SYSROOT_SRC: RelPath = RelPath::BUILD_SYSROOT.join("sysroot_src");
+static STANDARD_LIBRARY: CargoProject = CargoProject::new(&RelPath::BUILD_SYSROOT, "build_sysroot");
+
 fn build_clif_sysroot_for_triple(
+    dirs: &Dirs,
     channel: &str,
-    target_dir: &Path,
     triple: &str,
     cg_clif_dylib_path: &Path,
     linker: Option<&str>,
 ) {
-    match fs::read_to_string(Path::new("build_sysroot").join("rustc_version")) {
+    match fs::read_to_string(SYSROOT_RUSTC_VERSION.to_path(dirs)) {
         Err(e) => {
             eprintln!("Failed to get rustc version for patched sysroot source: {}", e);
             eprintln!("Hint: Try `./y.rs prepare` to patch the sysroot source");
@@ -174,7 +176,7 @@ fn build_clif_sysroot_for_triple(
         }
     }
 
-    let build_dir = Path::new("build_sysroot").join("target").join(triple).join(channel);
+    let build_dir = STANDARD_LIBRARY.target_dir(dirs).join(triple).join(channel);
 
     if !super::config::get_bool("keep_sysroot") {
         // Cleanup the deps dir, but keep build scripts and the incremental cache for faster
@@ -185,27 +187,27 @@ fn build_clif_sysroot_for_triple(
     }
 
     // Build sysroot
-    let mut build_cmd = cargo_command("cargo", "build", Some(triple), Path::new("build_sysroot"));
     let mut rustflags = "-Zforce-unstable-if-unmarked -Cpanic=abort".to_string();
     rustflags.push_str(&format!(" -Zcodegen-backend={}", cg_clif_dylib_path.to_str().unwrap()));
-    rustflags.push_str(&format!(" --sysroot={}", target_dir.to_str().unwrap()));
+    rustflags.push_str(&format!(" --sysroot={}", DIST_DIR.to_path(dirs).to_str().unwrap()));
     if channel == "release" {
-        build_cmd.arg("--release");
         rustflags.push_str(" -Zmir-opt-level=3");
     }
     if let Some(linker) = linker {
         use std::fmt::Write;
         write!(rustflags, " -Clinker={}", linker).unwrap();
     }
-    build_cmd.env("RUSTFLAGS", rustflags);
+    let mut compiler = Compiler::with_triple(triple.to_owned());
+    compiler.rustflags = rustflags;
+    let mut build_cmd = STANDARD_LIBRARY.build(&compiler, dirs);
+    if channel == "release" {
+        build_cmd.arg("--release");
+    }
     build_cmd.env("__CARGO_DEFAULT_LIB_METADATA", "cg_clif");
     spawn_and_wait(build_cmd);
 
     // Copy all relevant files to the sysroot
-    for entry in
-        fs::read_dir(Path::new("build_sysroot/target").join(triple).join(channel).join("deps"))
-            .unwrap()
-    {
+    for entry in fs::read_dir(build_dir.join("deps")).unwrap() {
         let entry = entry.unwrap();
         if let Some(ext) = entry.path().extension() {
             if ext == "rmeta" || ext == "d" || ext == "dSYM" || ext == "clif" {
@@ -216,7 +218,7 @@ fn build_clif_sysroot_for_triple(
         };
         try_hard_link(
             entry.path(),
-            target_dir.join("lib").join("rustlib").join(triple).join("lib").join(entry.file_name()),
+            RUSTLIB_DIR.to_path(dirs).join(triple).join("lib").join(entry.file_name()),
         );
     }
 }
index b25270d832ceb4fd483cfdbad2b6b712a4ee1a50..1afc9a55c73b5318bbc9ed006899c4f5ab3647c3 100644 (file)
@@ -8,20 +8,37 @@
 mod build_backend;
 mod build_sysroot;
 mod config;
+mod path;
 mod prepare;
 mod rustc_info;
 mod tests;
 mod utils;
 
+const USAGE: &str = r#"The build system of cg_clif.
+
+USAGE:
+    ./y.rs prepare [--out-dir DIR]
+    ./y.rs build [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--no-unstable-features]
+    ./y.rs test [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--no-unstable-features]
+
+OPTIONS:
+    --sysroot none|clif|llvm
+            Which sysroot libraries to use:
+            `none` will not include any standard library in the sysroot.
+            `clif` will build the standard library using Cranelift.
+            `llvm` will use the pre-compiled standard library of rustc which is compiled with LLVM.
+
+    --out-dir DIR
+            Specify the directory in which the download, build and dist directories are stored.
+            By default this is the working directory.
+
+    --no-unstable-features
+            fSome features are not yet ready for production usage. This option will disable these
+            features. This includes the JIT mode and inline assembly support.
+"#;
+
 fn usage() {
-    eprintln!("Usage:");
-    eprintln!("  ./y.rs prepare");
-    eprintln!(
-        "  ./y.rs build [--debug] [--sysroot none|clif|llvm] [--target-dir DIR] [--no-unstable-features]"
-    );
-    eprintln!(
-        "  ./y.rs test [--debug] [--sysroot none|clif|llvm] [--target-dir DIR] [--no-unstable-features]"
-    );
+    eprintln!("{USAGE}");
 }
 
 macro_rules! arg_error {
@@ -34,6 +51,7 @@ macro_rules! arg_error {
 
 #[derive(PartialEq, Debug)]
 enum Command {
+    Prepare,
     Build,
     Test,
 }
@@ -48,8 +66,6 @@ pub(crate) enum SysrootKind {
 pub fn main() {
     env::set_var("CG_CLIF_DISPLAY_CG_TIME", "1");
     env::set_var("CG_CLIF_DISABLE_INCR_CACHE", "1");
-    // The target dir is expected in the default location. Guard against the user changing it.
-    env::set_var("CARGO_TARGET_DIR", "target");
 
     if is_ci() {
         // Disabling incr comp reduces cache size and incr comp doesn't save as much on CI anyway
@@ -58,13 +74,7 @@ pub fn main() {
 
     let mut args = env::args().skip(1);
     let command = match args.next().as_deref() {
-        Some("prepare") => {
-            if args.next().is_some() {
-                arg_error!("./y.rs prepare doesn't expect arguments");
-            }
-            prepare::prepare();
-            process::exit(0);
-        }
+        Some("prepare") => Command::Prepare,
         Some("build") => Command::Build,
         Some("test") => Command::Test,
         Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag),
@@ -75,15 +85,15 @@ pub fn main() {
         }
     };
 
-    let mut target_dir = PathBuf::from("build");
+    let mut out_dir = PathBuf::from(".");
     let mut channel = "release";
     let mut sysroot_kind = SysrootKind::Clif;
     let mut use_unstable_features = true;
     while let Some(arg) = args.next().as_deref() {
         match arg {
-            "--target-dir" => {
-                target_dir = PathBuf::from(args.next().unwrap_or_else(|| {
-                    arg_error!("--target-dir requires argument");
+            "--out-dir" => {
+                out_dir = PathBuf::from(args.next().unwrap_or_else(|| {
+                    arg_error!("--out-dir requires argument");
                 }))
             }
             "--debug" => channel = "debug",
@@ -101,7 +111,6 @@ pub fn main() {
             arg => arg_error!("Unexpected argument {}", arg),
         }
     }
-    target_dir = std::env::current_dir().unwrap().join(target_dir);
 
     let host_triple = if let Ok(host_triple) = std::env::var("HOST_TRIPLE") {
         host_triple
@@ -122,13 +131,43 @@ pub fn main() {
         host_triple.clone()
     };
 
-    let cg_clif_dylib = build_backend::build_backend(channel, &host_triple, use_unstable_features);
+    // FIXME allow changing the location of these dirs using cli arguments
+    let current_dir = std::env::current_dir().unwrap();
+    out_dir = current_dir.join(out_dir);
+    let dirs = path::Dirs {
+        source_dir: current_dir.clone(),
+        download_dir: out_dir.join("download"),
+        build_dir: out_dir.join("build"),
+        dist_dir: out_dir.join("dist"),
+    };
+
+    path::RelPath::BUILD.ensure_exists(&dirs);
+
+    {
+        // Make sure we always explicitly specify the target dir
+        let target =
+            path::RelPath::BUILD.join("target_dir_should_be_set_explicitly").to_path(&dirs);
+        env::set_var("CARGO_TARGET_DIR", &target);
+        let _ = std::fs::remove_file(&target);
+        std::fs::File::create(target).unwrap();
+    }
+
+    if command == Command::Prepare {
+        prepare::prepare(&dirs);
+        process::exit(0);
+    }
+
+    let cg_clif_dylib =
+        build_backend::build_backend(&dirs, channel, &host_triple, use_unstable_features);
     match command {
+        Command::Prepare => {
+            // Handled above
+        }
         Command::Test => {
             tests::run_tests(
+                &dirs,
                 channel,
                 sysroot_kind,
-                &target_dir,
                 &cg_clif_dylib,
                 &host_triple,
                 &target_triple,
@@ -137,7 +176,7 @@ pub fn main() {
             abi_cafe::run(
                 channel,
                 sysroot_kind,
-                &target_dir,
+                &dirs,
                 &cg_clif_dylib,
                 &host_triple,
                 &target_triple,
@@ -145,9 +184,9 @@ pub fn main() {
         }
         Command::Build => {
             build_sysroot::build_sysroot(
+                &dirs,
                 channel,
                 sysroot_kind,
-                &target_dir,
                 &cg_clif_dylib,
                 &host_triple,
                 &target_triple,
diff --git a/compiler/rustc_codegen_cranelift/build_system/path.rs b/compiler/rustc_codegen_cranelift/build_system/path.rs
new file mode 100644 (file)
index 0000000..e93981f
--- /dev/null
@@ -0,0 +1,70 @@
+use std::fs;
+use std::path::PathBuf;
+
+#[derive(Debug, Clone)]
+pub(crate) struct Dirs {
+    pub(crate) source_dir: PathBuf,
+    pub(crate) download_dir: PathBuf,
+    pub(crate) build_dir: PathBuf,
+    pub(crate) dist_dir: PathBuf,
+}
+
+#[doc(hidden)]
+#[derive(Debug, Copy, Clone)]
+pub(crate) enum PathBase {
+    Source,
+    Download,
+    Build,
+    Dist,
+}
+
+impl PathBase {
+    fn to_path(self, dirs: &Dirs) -> PathBuf {
+        match self {
+            PathBase::Source => dirs.source_dir.clone(),
+            PathBase::Download => dirs.download_dir.clone(),
+            PathBase::Build => dirs.build_dir.clone(),
+            PathBase::Dist => dirs.dist_dir.clone(),
+        }
+    }
+}
+
+#[derive(Debug, Copy, Clone)]
+pub(crate) enum RelPath {
+    Base(PathBase),
+    Join(&'static RelPath, &'static str),
+}
+
+impl RelPath {
+    pub(crate) const SOURCE: RelPath = RelPath::Base(PathBase::Source);
+    pub(crate) const DOWNLOAD: RelPath = RelPath::Base(PathBase::Download);
+    pub(crate) const BUILD: RelPath = RelPath::Base(PathBase::Build);
+    pub(crate) const DIST: RelPath = RelPath::Base(PathBase::Dist);
+
+    pub(crate) const SCRIPTS: RelPath = RelPath::SOURCE.join("scripts");
+    pub(crate) const BUILD_SYSROOT: RelPath = RelPath::SOURCE.join("build_sysroot");
+    pub(crate) const PATCHES: RelPath = RelPath::SOURCE.join("patches");
+
+    pub(crate) const fn join(&'static self, suffix: &'static str) -> RelPath {
+        RelPath::Join(self, suffix)
+    }
+
+    pub(crate) fn to_path(&self, dirs: &Dirs) -> PathBuf {
+        match self {
+            RelPath::Base(base) => base.to_path(dirs),
+            RelPath::Join(base, suffix) => base.to_path(dirs).join(suffix),
+        }
+    }
+
+    pub(crate) fn ensure_exists(&self, dirs: &Dirs) {
+        fs::create_dir_all(self.to_path(dirs)).unwrap();
+    }
+
+    pub(crate) fn ensure_fresh(&self, dirs: &Dirs) {
+        let path = self.to_path(dirs);
+        if path.exists() {
+            fs::remove_dir_all(&path).unwrap();
+        }
+        fs::create_dir_all(path).unwrap();
+    }
+}
index 3111f62f6c2156eaec0ef00a9a7213acf8950f88..8ac67e8f9422823090a97ffab654c0da5a848e12 100644 (file)
@@ -1,92 +1,75 @@
-use std::env;
 use std::ffi::OsStr;
 use std::fs;
 use std::path::{Path, PathBuf};
 use std::process::Command;
 
+use super::build_sysroot::{SYSROOT_RUSTC_VERSION, SYSROOT_SRC};
+use super::path::{Dirs, RelPath};
 use super::rustc_info::{get_file_name, get_rustc_path, get_rustc_version};
-use super::utils::{cargo_command, copy_dir_recursively, spawn_and_wait};
-
-pub(crate) const ABI_CAFE: GitRepo =
-    GitRepo::github("Gankra", "abi-cafe", "4c6dc8c9c687e2b3a760ff2176ce236872b37212", "abi-cafe");
-
-pub(crate) const RAND: GitRepo =
-    GitRepo::github("rust-random", "rand", "0f933f9c7176e53b2a3c7952ded484e1783f0bf1", "rand");
-
-pub(crate) const REGEX: GitRepo =
-    GitRepo::github("rust-lang", "regex", "341f207c1071f7290e3f228c710817c280c8dca1", "regex");
-
-pub(crate) const PORTABLE_SIMD: GitRepo = GitRepo::github(
-    "rust-lang",
-    "portable-simd",
-    "d5cd4a8112d958bd3a252327e0d069a6363249bd",
-    "portable-simd",
-);
-
-pub(crate) const SIMPLE_RAYTRACER: GitRepo = GitRepo::github(
-    "ebobby",
-    "simple-raytracer",
-    "804a7a21b9e673a482797aa289a18ed480e4d813",
-    "<none>",
-);
-
-pub(crate) fn prepare() {
-    if Path::new("download").exists() {
-        std::fs::remove_dir_all(Path::new("download")).unwrap();
+use super::utils::{copy_dir_recursively, spawn_and_wait, Compiler};
+
+pub(crate) fn prepare(dirs: &Dirs) {
+    if RelPath::DOWNLOAD.to_path(dirs).exists() {
+        std::fs::remove_dir_all(RelPath::DOWNLOAD.to_path(dirs)).unwrap();
     }
-    std::fs::create_dir_all(Path::new("download")).unwrap();
+    std::fs::create_dir_all(RelPath::DOWNLOAD.to_path(dirs)).unwrap();
 
-    prepare_sysroot();
+    prepare_sysroot(dirs);
 
     // FIXME maybe install this only locally?
     eprintln!("[INSTALL] hyperfine");
-    Command::new("cargo").arg("install").arg("hyperfine").spawn().unwrap().wait().unwrap();
+    Command::new("cargo")
+        .arg("install")
+        .arg("hyperfine")
+        .env_remove("CARGO_TARGET_DIR")
+        .spawn()
+        .unwrap()
+        .wait()
+        .unwrap();
 
-    ABI_CAFE.fetch();
-    RAND.fetch();
-    REGEX.fetch();
-    PORTABLE_SIMD.fetch();
-    SIMPLE_RAYTRACER.fetch();
+    super::abi_cafe::ABI_CAFE_REPO.fetch(dirs);
+    super::tests::RAND_REPO.fetch(dirs);
+    super::tests::REGEX_REPO.fetch(dirs);
+    super::tests::PORTABLE_SIMD_REPO.fetch(dirs);
+    super::tests::SIMPLE_RAYTRACER_REPO.fetch(dirs);
 
     eprintln!("[LLVM BUILD] simple-raytracer");
-    let build_cmd = cargo_command("cargo", "build", None, &SIMPLE_RAYTRACER.source_dir());
+    let host_compiler = Compiler::host();
+    let build_cmd = super::tests::SIMPLE_RAYTRACER.build(&host_compiler, dirs);
     spawn_and_wait(build_cmd);
     fs::copy(
-        SIMPLE_RAYTRACER
-            .source_dir()
-            .join("target")
+        super::tests::SIMPLE_RAYTRACER
+            .target_dir(dirs)
+            .join(&host_compiler.triple)
             .join("debug")
             .join(get_file_name("main", "bin")),
-        SIMPLE_RAYTRACER.source_dir().join(get_file_name("raytracer_cg_llvm", "bin")),
+        RelPath::BUILD.to_path(dirs).join(get_file_name("raytracer_cg_llvm", "bin")),
     )
     .unwrap();
 }
 
-fn prepare_sysroot() {
+fn prepare_sysroot(dirs: &Dirs) {
     let rustc_path = get_rustc_path();
     let sysroot_src_orig = rustc_path.parent().unwrap().join("../lib/rustlib/src/rust");
-    let sysroot_src = env::current_dir().unwrap().join("build_sysroot").join("sysroot_src");
+    let sysroot_src = SYSROOT_SRC;
 
     assert!(sysroot_src_orig.exists());
 
-    if sysroot_src.exists() {
-        fs::remove_dir_all(&sysroot_src).unwrap();
-    }
-    fs::create_dir_all(sysroot_src.join("library")).unwrap();
+    sysroot_src.ensure_fresh(dirs);
+    fs::create_dir_all(sysroot_src.to_path(dirs).join("library")).unwrap();
     eprintln!("[COPY] sysroot src");
-    copy_dir_recursively(&sysroot_src_orig.join("library"), &sysroot_src.join("library"));
+    copy_dir_recursively(
+        &sysroot_src_orig.join("library"),
+        &sysroot_src.to_path(dirs).join("library"),
+    );
 
     let rustc_version = get_rustc_version();
-    fs::write(Path::new("build_sysroot").join("rustc_version"), &rustc_version).unwrap();
+    fs::write(SYSROOT_RUSTC_VERSION.to_path(dirs), &rustc_version).unwrap();
 
     eprintln!("[GIT] init");
-    let mut git_init_cmd = Command::new("git");
-    git_init_cmd.arg("init").arg("-q").current_dir(&sysroot_src);
-    spawn_and_wait(git_init_cmd);
-
-    init_git_repo(&sysroot_src);
+    init_git_repo(&sysroot_src.to_path(dirs));
 
-    apply_patches("sysroot", &sysroot_src);
+    apply_patches(dirs, "sysroot", &sysroot_src.to_path(dirs));
 }
 
 pub(crate) struct GitRepo {
@@ -100,7 +83,7 @@ enum GitRepoUrl {
 }
 
 impl GitRepo {
-    const fn github(
+    pub(crate) const fn github(
         user: &'static str,
         repo: &'static str,
         rev: &'static str,
@@ -109,21 +92,25 @@ const fn github(
         GitRepo { url: GitRepoUrl::Github { user, repo }, rev, patch_name }
     }
 
-    pub(crate) fn source_dir(&self) -> PathBuf {
+    pub(crate) const fn source_dir(&self) -> RelPath {
         match self.url {
-            GitRepoUrl::Github { user: _, repo } => {
-                std::env::current_dir().unwrap().join("download").join(repo)
-            }
+            GitRepoUrl::Github { user: _, repo } => RelPath::DOWNLOAD.join(repo),
         }
     }
 
-    fn fetch(&self) {
+    fn fetch(&self, dirs: &Dirs) {
         match self.url {
             GitRepoUrl::Github { user, repo } => {
-                clone_repo_shallow_github(&self.source_dir(), user, repo, self.rev);
+                clone_repo_shallow_github(
+                    dirs,
+                    &self.source_dir().to_path(dirs),
+                    user,
+                    repo,
+                    self.rev,
+                );
             }
         }
-        apply_patches(self.patch_name, &self.source_dir());
+        apply_patches(dirs, self.patch_name, &self.source_dir().to_path(dirs));
     }
 }
 
@@ -142,18 +129,16 @@ fn clone_repo(download_dir: &Path, repo: &str, rev: &str) {
     spawn_and_wait(checkout_cmd);
 }
 
-fn clone_repo_shallow_github(download_dir: &Path, user: &str, repo: &str, rev: &str) {
+fn clone_repo_shallow_github(dirs: &Dirs, download_dir: &Path, user: &str, repo: &str, rev: &str) {
     if cfg!(windows) {
         // Older windows doesn't have tar or curl by default. Fall back to using git.
         clone_repo(download_dir, &format!("https://github.com/{}/{}.git", user, repo), rev);
         return;
     }
 
-    let downloads_dir = std::env::current_dir().unwrap().join("download");
-
     let archive_url = format!("https://github.com/{}/{}/archive/{}.tar.gz", user, repo, rev);
-    let archive_file = downloads_dir.join(format!("{}.tar.gz", rev));
-    let archive_dir = downloads_dir.join(format!("{}-{}", repo, rev));
+    let archive_file = RelPath::DOWNLOAD.to_path(dirs).join(format!("{}.tar.gz", rev));
+    let archive_dir = RelPath::DOWNLOAD.to_path(dirs).join(format!("{}-{}", repo, rev));
 
     eprintln!("[DOWNLOAD] {}/{} from {}", user, repo, archive_url);
 
@@ -169,7 +154,7 @@ fn clone_repo_shallow_github(download_dir: &Path, user: &str, repo: &str, rev: &
 
     // Unpack tar archive
     let mut unpack_cmd = Command::new("tar");
-    unpack_cmd.arg("xf").arg(&archive_file).current_dir(downloads_dir);
+    unpack_cmd.arg("xf").arg(&archive_file).current_dir(RelPath::DOWNLOAD.to_path(dirs));
     spawn_and_wait(unpack_cmd);
 
     // Rename unpacked dir to the expected name
@@ -191,12 +176,21 @@ fn init_git_repo(repo_dir: &Path) {
     spawn_and_wait(git_add_cmd);
 
     let mut git_commit_cmd = Command::new("git");
-    git_commit_cmd.arg("commit").arg("-m").arg("Initial commit").arg("-q").current_dir(repo_dir);
+    git_commit_cmd
+        .arg("-c")
+        .arg("user.name=Dummy")
+        .arg("-c")
+        .arg("user.email=dummy@example.com")
+        .arg("commit")
+        .arg("-m")
+        .arg("Initial commit")
+        .arg("-q")
+        .current_dir(repo_dir);
     spawn_and_wait(git_commit_cmd);
 }
 
-fn get_patches(source_dir: &Path, crate_name: &str) -> Vec<PathBuf> {
-    let mut patches: Vec<_> = fs::read_dir(source_dir.join("patches"))
+fn get_patches(dirs: &Dirs, crate_name: &str) -> Vec<PathBuf> {
+    let mut patches: Vec<_> = fs::read_dir(RelPath::PATCHES.to_path(dirs))
         .unwrap()
         .map(|entry| entry.unwrap().path())
         .filter(|path| path.extension() == Some(OsStr::new("patch")))
@@ -215,19 +209,27 @@ fn get_patches(source_dir: &Path, crate_name: &str) -> Vec<PathBuf> {
     patches
 }
 
-fn apply_patches(crate_name: &str, target_dir: &Path) {
+fn apply_patches(dirs: &Dirs, crate_name: &str, target_dir: &Path) {
     if crate_name == "<none>" {
         return;
     }
 
-    for patch in get_patches(&std::env::current_dir().unwrap(), crate_name) {
+    for patch in get_patches(dirs, crate_name) {
         eprintln!(
             "[PATCH] {:?} <- {:?}",
             target_dir.file_name().unwrap(),
             patch.file_name().unwrap()
         );
         let mut apply_patch_cmd = Command::new("git");
-        apply_patch_cmd.arg("am").arg(patch).arg("-q").current_dir(target_dir);
+        apply_patch_cmd
+            .arg("-c")
+            .arg("user.name=Dummy")
+            .arg("-c")
+            .arg("user.email=dummy@example.com")
+            .arg("am")
+            .arg(patch)
+            .arg("-q")
+            .current_dir(target_dir);
         spawn_and_wait(apply_patch_cmd);
     }
 }
index 3c08b6fa3894d61277a0c0b6499e23ddcdc544a9..8e5ab688e131b35325af4fb83a3387b8c6228449 100644 (file)
@@ -23,6 +23,16 @@ pub(crate) fn get_host_triple() -> String {
         .to_owned()
 }
 
+pub(crate) fn get_cargo_path() -> PathBuf {
+    let cargo_path = Command::new("rustup")
+        .stderr(Stdio::inherit())
+        .args(&["which", "cargo"])
+        .output()
+        .unwrap()
+        .stdout;
+    Path::new(String::from_utf8(cargo_path).unwrap().trim()).to_owned()
+}
+
 pub(crate) fn get_rustc_path() -> PathBuf {
     let rustc_path = Command::new("rustup")
         .stderr(Stdio::inherit())
@@ -33,6 +43,16 @@ pub(crate) fn get_rustc_path() -> PathBuf {
     Path::new(String::from_utf8(rustc_path).unwrap().trim()).to_owned()
 }
 
+pub(crate) fn get_rustdoc_path() -> PathBuf {
+    let rustc_path = Command::new("rustup")
+        .stderr(Stdio::inherit())
+        .args(&["which", "rustdoc"])
+        .output()
+        .unwrap()
+        .stdout;
+    Path::new(String::from_utf8(rustc_path).unwrap().trim()).to_owned()
+}
+
 pub(crate) fn get_default_sysroot() -> PathBuf {
     let default_sysroot = Command::new("rustc")
         .stderr(Stdio::inherit())
index a414b60f4e06b2b79dccc1ee64bc233f32ae6ba1..1c372736ed65d9121dccf04ae5bcf504d45127bc 100644 (file)
@@ -1,15 +1,20 @@
 use super::build_sysroot;
 use super::config;
-use super::prepare;
-use super::rustc_info::get_wrapper_file_name;
-use super::utils::{cargo_command, hyperfine_command, spawn_and_wait, spawn_and_wait_with_input};
-use build_system::SysrootKind;
+use super::path::{Dirs, RelPath};
+use super::prepare::GitRepo;
+use super::rustc_info::{get_cargo_path, get_wrapper_file_name};
+use super::utils::{
+    hyperfine_command, spawn_and_wait, spawn_and_wait_with_input, CargoProject, Compiler,
+};
+use super::SysrootKind;
 use std::env;
 use std::ffi::OsStr;
 use std::fs;
-use std::path::{Path, PathBuf};
+use std::path::Path;
 use std::process::Command;
 
+static BUILD_EXAMPLE_OUT_DIR: RelPath = RelPath::BUILD.join("example");
+
 struct TestCase {
     config: &'static str,
     func: &'static dyn Fn(&TestRunner),
@@ -30,7 +35,7 @@ const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
             "--crate-type",
             "lib,dylib",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
     }),
     TestCase::new("build.example", &|runner| {
@@ -39,7 +44,7 @@ const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
             "--crate-type",
             "lib",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
     }),
     TestCase::new("jit.mini_core_hello_world", &|runner| {
@@ -51,7 +56,7 @@ const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
             "--cfg",
             "jit",
             "--target",
-            &runner.host_triple,
+            &runner.target_compiler.triple,
         ]);
         jit_cmd.env("CG_CLIF_JIT_ARGS", "abc bcd");
         spawn_and_wait(jit_cmd);
@@ -65,7 +70,7 @@ const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
             "--cfg",
             "jit",
             "--target",
-            &runner.host_triple,
+            &runner.target_compiler.triple,
         ]);
         jit_cmd.env("CG_CLIF_JIT_ARGS", "abc bcd");
         spawn_and_wait(jit_cmd);
@@ -79,7 +84,7 @@ const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
             "bin",
             "-g",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
         runner.run_out_command("mini_core_hello_world", ["abc", "bcd"]);
     }),
@@ -94,7 +99,7 @@ const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
             "--crate-type",
             "bin",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
         runner.run_out_command("arbitrary_self_types_pointers_and_wrappers", []);
     }),
@@ -106,7 +111,7 @@ const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
             "--crate-type",
             "bin",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
         runner.run_out_command("issue_91827_extern_types", []);
     }),
@@ -116,7 +121,7 @@ const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
             "--crate-type",
             "lib",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
     }),
     TestCase::new("aot.alloc_example", &|runner| {
@@ -125,7 +130,7 @@ const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
             "--crate-type",
             "bin",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
         runner.run_out_command("alloc_example", []);
     }),
@@ -136,7 +141,7 @@ const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
             "-Cprefer-dynamic",
             "example/std_example.rs",
             "--target",
-            &runner.host_triple,
+            &runner.target_compiler.triple,
         ]);
 
         eprintln!("[JIT-lazy] std_example");
@@ -146,7 +151,7 @@ const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
             "-Cprefer-dynamic",
             "example/std_example.rs",
             "--target",
-            &runner.host_triple,
+            &runner.target_compiler.triple,
         ]);
     }),
     TestCase::new("aot.std_example", &|runner| {
@@ -155,7 +160,7 @@ const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
             "--crate-type",
             "bin",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
         runner.run_out_command("std_example", ["arg"]);
     }),
@@ -167,7 +172,7 @@ const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
             "--crate-type",
             "bin",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
         runner.run_out_command("dst_field_align", []);
     }),
@@ -178,7 +183,7 @@ const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
             "bin",
             "-Cpanic=abort",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
         runner.run_out_command("subslice-patterns-const-eval", []);
     }),
@@ -189,7 +194,7 @@ const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
             "bin",
             "-Cpanic=abort",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
         runner.run_out_command("track-caller-attribute", []);
     }),
@@ -200,7 +205,7 @@ const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
             "bin",
             "-Cpanic=abort",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
         runner.run_out_command("float-minmax-pass", []);
     }),
@@ -210,205 +215,252 @@ const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
             "--crate-type",
             "bin",
             "--target",
-            &runner.target_triple,
+            &runner.target_compiler.triple,
         ]);
         runner.run_out_command("mod_bench", []);
     }),
+    TestCase::new("aot.issue-72793", &|runner| {
+        runner.run_rustc([
+            "example/issue-72793.rs",
+            "--crate-type",
+            "bin",
+            "--target",
+            &runner.target_compiler.triple,
+        ]);
+        runner.run_out_command("issue-72793", []);
+    }),
 ];
 
+pub(crate) static RAND_REPO: GitRepo =
+    GitRepo::github("rust-random", "rand", "0f933f9c7176e53b2a3c7952ded484e1783f0bf1", "rand");
+
+static RAND: CargoProject = CargoProject::new(&RAND_REPO.source_dir(), "rand");
+
+pub(crate) static REGEX_REPO: GitRepo =
+    GitRepo::github("rust-lang", "regex", "341f207c1071f7290e3f228c710817c280c8dca1", "regex");
+
+static REGEX: CargoProject = CargoProject::new(&REGEX_REPO.source_dir(), "regex");
+
+pub(crate) static PORTABLE_SIMD_REPO: GitRepo = GitRepo::github(
+    "rust-lang",
+    "portable-simd",
+    "d5cd4a8112d958bd3a252327e0d069a6363249bd",
+    "portable-simd",
+);
+
+static PORTABLE_SIMD: CargoProject =
+    CargoProject::new(&PORTABLE_SIMD_REPO.source_dir(), "portable_simd");
+
+pub(crate) static SIMPLE_RAYTRACER_REPO: GitRepo = GitRepo::github(
+    "ebobby",
+    "simple-raytracer",
+    "804a7a21b9e673a482797aa289a18ed480e4d813",
+    "<none>",
+);
+
+pub(crate) static SIMPLE_RAYTRACER: CargoProject =
+    CargoProject::new(&SIMPLE_RAYTRACER_REPO.source_dir(), "simple_raytracer");
+
+static LIBCORE_TESTS: CargoProject =
+    CargoProject::new(&RelPath::BUILD_SYSROOT.join("sysroot_src/library/core/tests"), "core_tests");
+
 const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
     TestCase::new("test.rust-random/rand", &|runner| {
-        runner.in_dir(prepare::RAND.source_dir(), |runner| {
-            runner.run_cargo("clean", []);
-
-            if runner.host_triple == runner.target_triple {
-                eprintln!("[TEST] rust-random/rand");
-                runner.run_cargo("test", ["--workspace"]);
-            } else {
-                eprintln!("[AOT] rust-random/rand");
-                runner.run_cargo("build", ["--workspace", "--tests"]);
-            }
-        });
+        spawn_and_wait(RAND.clean(&runner.target_compiler.cargo, &runner.dirs));
+
+        if runner.is_native {
+            eprintln!("[TEST] rust-random/rand");
+            let mut test_cmd = RAND.test(&runner.target_compiler, &runner.dirs);
+            test_cmd.arg("--workspace");
+            spawn_and_wait(test_cmd);
+        } else {
+            eprintln!("[AOT] rust-random/rand");
+            let mut build_cmd = RAND.build(&runner.target_compiler, &runner.dirs);
+            build_cmd.arg("--workspace").arg("--tests");
+            spawn_and_wait(build_cmd);
+        }
     }),
     TestCase::new("bench.simple-raytracer", &|runner| {
-        runner.in_dir(prepare::SIMPLE_RAYTRACER.source_dir(), |runner| {
-            let run_runs = env::var("RUN_RUNS").unwrap_or("10".to_string()).parse().unwrap();
-
-            if runner.host_triple == runner.target_triple {
-                eprintln!("[BENCH COMPILE] ebobby/simple-raytracer");
-                let prepare = runner.cargo_command("clean", []);
-
-                let llvm_build_cmd = cargo_command("cargo", "build", None, Path::new("."));
-
-                let cargo_clif = runner
-                    .root_dir
-                    .clone()
-                    .join("build")
-                    .join(get_wrapper_file_name("cargo-clif", "bin"));
-                let clif_build_cmd = cargo_command(cargo_clif, "build", None, Path::new("."));
-
-                let bench_compile =
-                    hyperfine_command(1, run_runs, Some(prepare), llvm_build_cmd, clif_build_cmd);
-
-                spawn_and_wait(bench_compile);
-
-                eprintln!("[BENCH RUN] ebobby/simple-raytracer");
-                fs::copy(PathBuf::from("./target/debug/main"), PathBuf::from("raytracer_cg_clif"))
-                    .unwrap();
-
-                let bench_run = hyperfine_command(
-                    0,
-                    run_runs,
-                    None,
-                    Command::new("./raytracer_cg_llvm"),
-                    Command::new("./raytracer_cg_clif"),
-                );
-                spawn_and_wait(bench_run);
-            } else {
-                runner.run_cargo("clean", []);
-                eprintln!("[BENCH COMPILE] ebobby/simple-raytracer (skipped)");
-                eprintln!("[COMPILE] ebobby/simple-raytracer");
-                runner.run_cargo("build", []);
-                eprintln!("[BENCH RUN] ebobby/simple-raytracer (skipped)");
-            }
-        });
+        let run_runs = env::var("RUN_RUNS").unwrap_or("10".to_string()).parse().unwrap();
+
+        if runner.is_native {
+            eprintln!("[BENCH COMPILE] ebobby/simple-raytracer");
+            let cargo_clif = RelPath::DIST
+                .to_path(&runner.dirs)
+                .join(get_wrapper_file_name("cargo-clif", "bin"));
+            let manifest_path = SIMPLE_RAYTRACER.manifest_path(&runner.dirs);
+            let target_dir = SIMPLE_RAYTRACER.target_dir(&runner.dirs);
+
+            let clean_cmd = format!(
+                "cargo clean --manifest-path {manifest_path} --target-dir {target_dir}",
+                manifest_path = manifest_path.display(),
+                target_dir = target_dir.display(),
+            );
+            let llvm_build_cmd = format!(
+                "cargo build --manifest-path {manifest_path} --target-dir {target_dir}",
+                manifest_path = manifest_path.display(),
+                target_dir = target_dir.display(),
+            );
+            let clif_build_cmd = format!(
+                "{cargo_clif} build --manifest-path {manifest_path} --target-dir {target_dir}",
+                cargo_clif = cargo_clif.display(),
+                manifest_path = manifest_path.display(),
+                target_dir = target_dir.display(),
+            );
+
+            let bench_compile =
+                hyperfine_command(1, run_runs, Some(&clean_cmd), &llvm_build_cmd, &clif_build_cmd);
+
+            spawn_and_wait(bench_compile);
+
+            eprintln!("[BENCH RUN] ebobby/simple-raytracer");
+            fs::copy(
+                target_dir.join("debug").join("main"),
+                RelPath::BUILD.to_path(&runner.dirs).join("raytracer_cg_clif"),
+            )
+            .unwrap();
+
+            let mut bench_run =
+                hyperfine_command(0, run_runs, None, "./raytracer_cg_llvm", "./raytracer_cg_clif");
+            bench_run.current_dir(RelPath::BUILD.to_path(&runner.dirs));
+            spawn_and_wait(bench_run);
+        } else {
+            spawn_and_wait(SIMPLE_RAYTRACER.clean(&runner.target_compiler.cargo, &runner.dirs));
+            eprintln!("[BENCH COMPILE] ebobby/simple-raytracer (skipped)");
+            eprintln!("[COMPILE] ebobby/simple-raytracer");
+            spawn_and_wait(SIMPLE_RAYTRACER.build(&runner.target_compiler, &runner.dirs));
+            eprintln!("[BENCH RUN] ebobby/simple-raytracer (skipped)");
+        }
     }),
     TestCase::new("test.libcore", &|runner| {
-        runner.in_dir(
-            std::env::current_dir()
-                .unwrap()
-                .join("build_sysroot")
-                .join("sysroot_src")
-                .join("library")
-                .join("core")
-                .join("tests"),
-            |runner| {
-                runner.run_cargo("clean", []);
-
-                if runner.host_triple == runner.target_triple {
-                    runner.run_cargo("test", []);
-                } else {
-                    eprintln!("Cross-Compiling: Not running tests");
-                    runner.run_cargo("build", ["--tests"]);
-                }
-            },
-        );
+        spawn_and_wait(LIBCORE_TESTS.clean(&runner.host_compiler.cargo, &runner.dirs));
+
+        if runner.is_native {
+            spawn_and_wait(LIBCORE_TESTS.test(&runner.target_compiler, &runner.dirs));
+        } else {
+            eprintln!("Cross-Compiling: Not running tests");
+            let mut build_cmd = LIBCORE_TESTS.build(&runner.target_compiler, &runner.dirs);
+            build_cmd.arg("--tests");
+            spawn_and_wait(build_cmd);
+        }
     }),
     TestCase::new("test.regex-shootout-regex-dna", &|runner| {
-        runner.in_dir(prepare::REGEX.source_dir(), |runner| {
-            runner.run_cargo("clean", []);
-
-            // newer aho_corasick versions throw a deprecation warning
-            let lint_rust_flags = format!("{} --cap-lints warn", runner.rust_flags);
-
-            let mut build_cmd = runner.cargo_command("build", ["--example", "shootout-regex-dna"]);
-            build_cmd.env("RUSTFLAGS", lint_rust_flags.clone());
-            spawn_and_wait(build_cmd);
-
-            if runner.host_triple == runner.target_triple {
-                let mut run_cmd = runner.cargo_command("run", ["--example", "shootout-regex-dna"]);
-                run_cmd.env("RUSTFLAGS", lint_rust_flags);
-
-                let input =
-                    fs::read_to_string(PathBuf::from("examples/regexdna-input.txt")).unwrap();
-                let expected_path = PathBuf::from("examples/regexdna-output.txt");
-                let expected = fs::read_to_string(&expected_path).unwrap();
-
-                let output = spawn_and_wait_with_input(run_cmd, input);
-                // Make sure `[codegen mono items] start` doesn't poison the diff
-                let output = output
-                    .lines()
-                    .filter(|line| !line.contains("codegen mono items"))
-                    .chain(Some("")) // This just adds the trailing newline
-                    .collect::<Vec<&str>>()
-                    .join("\r\n");
-
-                let output_matches = expected.lines().eq(output.lines());
-                if !output_matches {
-                    let res_path = PathBuf::from("res.txt");
-                    fs::write(&res_path, &output).unwrap();
-
-                    if cfg!(windows) {
-                        println!("Output files don't match!");
-                        println!("Expected Output:\n{}", expected);
-                        println!("Actual Output:\n{}", output);
-                    } else {
-                        let mut diff = Command::new("diff");
-                        diff.arg("-u");
-                        diff.arg(res_path);
-                        diff.arg(expected_path);
-                        spawn_and_wait(diff);
-                    }
-
-                    std::process::exit(1);
+        spawn_and_wait(REGEX.clean(&runner.target_compiler.cargo, &runner.dirs));
+
+        // newer aho_corasick versions throw a deprecation warning
+        let lint_rust_flags = format!("{} --cap-lints warn", runner.target_compiler.rustflags);
+
+        let mut build_cmd = REGEX.build(&runner.target_compiler, &runner.dirs);
+        build_cmd.arg("--example").arg("shootout-regex-dna");
+        build_cmd.env("RUSTFLAGS", lint_rust_flags.clone());
+        spawn_and_wait(build_cmd);
+
+        if runner.is_native {
+            let mut run_cmd = REGEX.run(&runner.target_compiler, &runner.dirs);
+            run_cmd.arg("--example").arg("shootout-regex-dna");
+            run_cmd.env("RUSTFLAGS", lint_rust_flags);
+
+            let input = fs::read_to_string(
+                REGEX.source_dir(&runner.dirs).join("examples").join("regexdna-input.txt"),
+            )
+            .unwrap();
+            let expected_path =
+                REGEX.source_dir(&runner.dirs).join("examples").join("regexdna-output.txt");
+            let expected = fs::read_to_string(&expected_path).unwrap();
+
+            let output = spawn_and_wait_with_input(run_cmd, input);
+            // Make sure `[codegen mono items] start` doesn't poison the diff
+            let output = output
+                .lines()
+                .filter(|line| !line.contains("codegen mono items"))
+                .chain(Some("")) // This just adds the trailing newline
+                .collect::<Vec<&str>>()
+                .join("\r\n");
+
+            let output_matches = expected.lines().eq(output.lines());
+            if !output_matches {
+                let res_path = REGEX.source_dir(&runner.dirs).join("res.txt");
+                fs::write(&res_path, &output).unwrap();
+
+                if cfg!(windows) {
+                    println!("Output files don't match!");
+                    println!("Expected Output:\n{}", expected);
+                    println!("Actual Output:\n{}", output);
+                } else {
+                    let mut diff = Command::new("diff");
+                    diff.arg("-u");
+                    diff.arg(res_path);
+                    diff.arg(expected_path);
+                    spawn_and_wait(diff);
                 }
+
+                std::process::exit(1);
             }
-        });
+        }
     }),
     TestCase::new("test.regex", &|runner| {
-        runner.in_dir(prepare::REGEX.source_dir(), |runner| {
-            runner.run_cargo("clean", []);
-
-            // newer aho_corasick versions throw a deprecation warning
-            let lint_rust_flags = format!("{} --cap-lints warn", runner.rust_flags);
-
-            if runner.host_triple == runner.target_triple {
-                let mut run_cmd = runner.cargo_command(
-                    "test",
-                    [
-                        "--tests",
-                        "--",
-                        "--exclude-should-panic",
-                        "--test-threads",
-                        "1",
-                        "-Zunstable-options",
-                        "-q",
-                    ],
-                );
-                run_cmd.env("RUSTFLAGS", lint_rust_flags);
-                spawn_and_wait(run_cmd);
-            } else {
-                eprintln!("Cross-Compiling: Not running tests");
-                let mut build_cmd =
-                    runner.cargo_command("build", ["--tests", "--target", &runner.target_triple]);
-                build_cmd.env("RUSTFLAGS", lint_rust_flags.clone());
-                spawn_and_wait(build_cmd);
-            }
-        });
+        spawn_and_wait(REGEX.clean(&runner.host_compiler.cargo, &runner.dirs));
+
+        // newer aho_corasick versions throw a deprecation warning
+        let lint_rust_flags = format!("{} --cap-lints warn", runner.target_compiler.rustflags);
+
+        if runner.is_native {
+            let mut run_cmd = REGEX.test(&runner.target_compiler, &runner.dirs);
+            run_cmd.args([
+                "--tests",
+                "--",
+                "--exclude-should-panic",
+                "--test-threads",
+                "1",
+                "-Zunstable-options",
+                "-q",
+            ]);
+            run_cmd.env("RUSTFLAGS", lint_rust_flags);
+            spawn_and_wait(run_cmd);
+        } else {
+            eprintln!("Cross-Compiling: Not running tests");
+            let mut build_cmd = REGEX.build(&runner.target_compiler, &runner.dirs);
+            build_cmd.arg("--tests");
+            build_cmd.env("RUSTFLAGS", lint_rust_flags.clone());
+            spawn_and_wait(build_cmd);
+        }
     }),
     TestCase::new("test.portable-simd", &|runner| {
-        runner.in_dir(prepare::PORTABLE_SIMD.source_dir(), |runner| {
-            runner.run_cargo("clean", []);
-            runner.run_cargo("build", ["--all-targets", "--target", &runner.target_triple]);
+        spawn_and_wait(PORTABLE_SIMD.clean(&runner.host_compiler.cargo, &runner.dirs));
 
-            if runner.host_triple == runner.target_triple {
-                runner.run_cargo("test", ["-q"]);
-            }
-        });
+        let mut build_cmd = PORTABLE_SIMD.build(&runner.target_compiler, &runner.dirs);
+        build_cmd.arg("--all-targets");
+        spawn_and_wait(build_cmd);
+
+        if runner.is_native {
+            let mut test_cmd = PORTABLE_SIMD.test(&runner.target_compiler, &runner.dirs);
+            test_cmd.arg("-q");
+            spawn_and_wait(test_cmd);
+        }
     }),
 ];
 
 pub(crate) fn run_tests(
+    dirs: &Dirs,
     channel: &str,
     sysroot_kind: SysrootKind,
-    target_dir: &Path,
     cg_clif_dylib: &Path,
     host_triple: &str,
     target_triple: &str,
 ) {
-    let runner = TestRunner::new(host_triple.to_string(), target_triple.to_string());
+    let runner = TestRunner::new(dirs.clone(), host_triple.to_string(), target_triple.to_string());
 
     if config::get_bool("testsuite.no_sysroot") {
         build_sysroot::build_sysroot(
+            dirs,
             channel,
             SysrootKind::None,
-            &target_dir,
             cg_clif_dylib,
             &host_triple,
             &target_triple,
         );
 
-        let _ = fs::remove_dir_all(Path::new("target").join("out"));
+        BUILD_EXAMPLE_OUT_DIR.ensure_fresh(dirs);
         runner.run_testsuite(NO_SYSROOT_SUITE);
     } else {
         eprintln!("[SKIP] no_sysroot tests");
@@ -419,9 +471,9 @@ pub(crate) fn run_tests(
 
     if run_base_sysroot || run_extended_sysroot {
         build_sysroot::build_sysroot(
+            dirs,
             channel,
             sysroot_kind,
-            &target_dir,
             cg_clif_dylib,
             &host_triple,
             &target_triple,
@@ -442,40 +494,50 @@ pub(crate) fn run_tests(
 }
 
 struct TestRunner {
-    root_dir: PathBuf,
-    out_dir: PathBuf,
+    is_native: bool,
     jit_supported: bool,
-    rust_flags: String,
-    run_wrapper: Vec<String>,
-    host_triple: String,
-    target_triple: String,
+    dirs: Dirs,
+    host_compiler: Compiler,
+    target_compiler: Compiler,
 }
 
 impl TestRunner {
-    pub fn new(host_triple: String, target_triple: String) -> Self {
-        let root_dir = env::current_dir().unwrap();
-
-        let mut out_dir = root_dir.clone();
-        out_dir.push("target");
-        out_dir.push("out");
-
+    pub fn new(dirs: Dirs, host_triple: String, target_triple: String) -> Self {
         let is_native = host_triple == target_triple;
         let jit_supported =
             target_triple.contains("x86_64") && is_native && !host_triple.contains("windows");
 
-        let mut rust_flags = env::var("RUSTFLAGS").ok().unwrap_or("".to_string());
-        let mut run_wrapper = Vec::new();
+        let rustc_clif =
+            RelPath::DIST.to_path(&dirs).join(get_wrapper_file_name("rustc-clif", "bin"));
+        let rustdoc_clif =
+            RelPath::DIST.to_path(&dirs).join(get_wrapper_file_name("rustdoc-clif", "bin"));
+
+        let mut rustflags = env::var("RUSTFLAGS").ok().unwrap_or("".to_string());
+        let mut runner = vec![];
 
         if !is_native {
             match target_triple.as_str() {
                 "aarch64-unknown-linux-gnu" => {
                     // We are cross-compiling for aarch64. Use the correct linker and run tests in qemu.
-                    rust_flags = format!("-Clinker=aarch64-linux-gnu-gcc{}", rust_flags);
-                    run_wrapper = vec!["qemu-aarch64", "-L", "/usr/aarch64-linux-gnu"];
+                    rustflags = format!("-Clinker=aarch64-linux-gnu-gcc{}", rustflags);
+                    runner = vec![
+                        "qemu-aarch64".to_owned(),
+                        "-L".to_owned(),
+                        "/usr/aarch64-linux-gnu".to_owned(),
+                    ];
+                }
+                "s390x-unknown-linux-gnu" => {
+                    // We are cross-compiling for s390x. Use the correct linker and run tests in qemu.
+                    rustflags = format!("-Clinker=s390x-linux-gnu-gcc{}", rustflags);
+                    runner = vec![
+                        "qemu-s390x".to_owned(),
+                        "-L".to_owned(),
+                        "/usr/s390x-linux-gnu".to_owned(),
+                    ];
                 }
                 "x86_64-pc-windows-gnu" => {
                     // We are cross-compiling for Windows. Run tests in wine.
-                    run_wrapper = vec!["wine"];
+                    runner = vec!["wine".to_owned()];
                 }
                 _ => {
                     println!("Unknown non-native platform");
@@ -484,19 +546,31 @@ pub fn new(host_triple: String, target_triple: String) -> Self {
         }
 
         // FIXME fix `#[linkage = "extern_weak"]` without this
-        if host_triple.contains("darwin") {
-            rust_flags = format!("{} -Clink-arg=-undefined -Clink-arg=dynamic_lookup", rust_flags);
+        if target_triple.contains("darwin") {
+            rustflags = format!("{} -Clink-arg=-undefined -Clink-arg=dynamic_lookup", rustflags);
         }
 
-        Self {
-            root_dir,
-            out_dir,
-            jit_supported,
-            rust_flags,
-            run_wrapper: run_wrapper.iter().map(|s| s.to_string()).collect(),
-            host_triple,
-            target_triple,
-        }
+        let host_compiler = Compiler {
+            cargo: get_cargo_path(),
+            rustc: rustc_clif.clone(),
+            rustdoc: rustdoc_clif.clone(),
+            rustflags: String::new(),
+            rustdocflags: String::new(),
+            triple: host_triple,
+            runner: vec![],
+        };
+
+        let target_compiler = Compiler {
+            cargo: get_cargo_path(),
+            rustc: rustc_clif,
+            rustdoc: rustdoc_clif,
+            rustflags: rustflags.clone(),
+            rustdocflags: rustflags,
+            triple: target_triple,
+            runner,
+        };
+
+        Self { is_native, jit_supported, dirs, host_compiler, target_compiler }
     }
 
     pub fn run_testsuite(&self, tests: &[TestCase]) {
@@ -516,29 +590,18 @@ pub fn run_testsuite(&self, tests: &[TestCase]) {
         }
     }
 
-    fn in_dir(&self, new: impl AsRef<Path>, callback: impl FnOnce(&TestRunner)) {
-        let current = env::current_dir().unwrap();
-
-        env::set_current_dir(new).unwrap();
-        callback(self);
-        env::set_current_dir(current).unwrap();
-    }
-
+    #[must_use]
     fn rustc_command<I, S>(&self, args: I) -> Command
     where
         I: IntoIterator<Item = S>,
         S: AsRef<OsStr>,
     {
-        let mut rustc_clif = self.root_dir.clone();
-        rustc_clif.push("build");
-        rustc_clif.push(get_wrapper_file_name("rustc-clif", "bin"));
-
-        let mut cmd = Command::new(rustc_clif);
-        cmd.args(self.rust_flags.split_whitespace());
+        let mut cmd = Command::new(&self.target_compiler.rustc);
+        cmd.args(self.target_compiler.rustflags.split_whitespace());
         cmd.arg("-L");
-        cmd.arg(format!("crate={}", self.out_dir.display()));
+        cmd.arg(format!("crate={}", BUILD_EXAMPLE_OUT_DIR.to_path(&self.dirs).display()));
         cmd.arg("--out-dir");
-        cmd.arg(format!("{}", self.out_dir.display()));
+        cmd.arg(format!("{}", BUILD_EXAMPLE_OUT_DIR.to_path(&self.dirs).display()));
         cmd.arg("-Cdebuginfo=2");
         cmd.args(args);
         cmd
@@ -559,15 +622,13 @@ fn run_out_command<'a, I>(&self, name: &str, args: I)
         let mut full_cmd = vec![];
 
         // Prepend the RUN_WRAPPER's
-        if !self.run_wrapper.is_empty() {
-            full_cmd.extend(self.run_wrapper.iter().cloned());
+        if !self.target_compiler.runner.is_empty() {
+            full_cmd.extend(self.target_compiler.runner.iter().cloned());
         }
 
-        full_cmd.push({
-            let mut out_path = self.out_dir.clone();
-            out_path.push(name);
-            out_path.to_str().unwrap().to_string()
-        });
+        full_cmd.push(
+            BUILD_EXAMPLE_OUT_DIR.to_path(&self.dirs).join(name).to_str().unwrap().to_string(),
+        );
 
         for arg in args.into_iter() {
             full_cmd.push(arg.to_string());
@@ -581,30 +642,4 @@ fn run_out_command<'a, I>(&self, name: &str, args: I)
 
         spawn_and_wait(cmd);
     }
-
-    fn cargo_command<'a, I>(&self, subcommand: &str, args: I) -> Command
-    where
-        I: IntoIterator<Item = &'a str>,
-    {
-        let mut cargo_clif = self.root_dir.clone();
-        cargo_clif.push("build");
-        cargo_clif.push(get_wrapper_file_name("cargo-clif", "bin"));
-
-        let mut cmd = cargo_command(
-            cargo_clif,
-            subcommand,
-            if subcommand == "clean" { None } else { Some(&self.target_triple) },
-            Path::new("."),
-        );
-        cmd.args(args);
-        cmd.env("RUSTFLAGS", &self.rust_flags);
-        cmd
-    }
-
-    fn run_cargo<'a, I>(&self, subcommand: &str, args: I)
-    where
-        I: IntoIterator<Item = &'a str>,
-    {
-        spawn_and_wait(self.cargo_command(subcommand, args));
-    }
 }
index c627af4e62fe14073bc539d195cb5623afd7dabe..2be70e8e421b2961e97b53c99f38c83256940365 100644 (file)
 use std::env;
 use std::fs;
 use std::io::Write;
-use std::path::Path;
+use std::path::{Path, PathBuf};
 use std::process::{self, Command, Stdio};
 
-pub(crate) fn cargo_command(
-    cargo: impl AsRef<Path>,
-    subcommand: &str,
-    triple: Option<&str>,
-    source_dir: &Path,
-) -> Command {
-    let mut cmd = Command::new(cargo.as_ref());
-    cmd.arg(subcommand)
-        .arg("--manifest-path")
-        .arg(source_dir.join("Cargo.toml"))
-        .arg("--target-dir")
-        .arg(source_dir.join("target"));
+use super::path::{Dirs, RelPath};
+use super::rustc_info::{get_cargo_path, get_host_triple, get_rustc_path, get_rustdoc_path};
+
+pub(crate) struct Compiler {
+    pub(crate) cargo: PathBuf,
+    pub(crate) rustc: PathBuf,
+    pub(crate) rustdoc: PathBuf,
+    pub(crate) rustflags: String,
+    pub(crate) rustdocflags: String,
+    pub(crate) triple: String,
+    pub(crate) runner: Vec<String>,
+}
+
+impl Compiler {
+    pub(crate) fn host() -> Compiler {
+        Compiler {
+            cargo: get_cargo_path(),
+            rustc: get_rustc_path(),
+            rustdoc: get_rustdoc_path(),
+            rustflags: String::new(),
+            rustdocflags: String::new(),
+            triple: get_host_triple(),
+            runner: vec![],
+        }
+    }
+
+    pub(crate) fn with_triple(triple: String) -> Compiler {
+        Compiler {
+            cargo: get_cargo_path(),
+            rustc: get_rustc_path(),
+            rustdoc: get_rustdoc_path(),
+            rustflags: String::new(),
+            rustdocflags: String::new(),
+            triple,
+            runner: vec![],
+        }
+    }
+}
+
+pub(crate) struct CargoProject {
+    source: &'static RelPath,
+    target: &'static str,
+}
+
+impl CargoProject {
+    pub(crate) const fn new(path: &'static RelPath, target: &'static str) -> CargoProject {
+        CargoProject { source: path, target }
+    }
+
+    pub(crate) fn source_dir(&self, dirs: &Dirs) -> PathBuf {
+        self.source.to_path(dirs)
+    }
+
+    pub(crate) fn manifest_path(&self, dirs: &Dirs) -> PathBuf {
+        self.source_dir(dirs).join("Cargo.toml")
+    }
+
+    pub(crate) fn target_dir(&self, dirs: &Dirs) -> PathBuf {
+        RelPath::BUILD.join(self.target).to_path(dirs)
+    }
 
-    if let Some(triple) = triple {
-        cmd.arg("--target").arg(triple);
+    fn base_cmd(&self, command: &str, cargo: &Path, dirs: &Dirs) -> Command {
+        let mut cmd = Command::new(cargo);
+
+        cmd.arg(command)
+            .arg("--manifest-path")
+            .arg(self.manifest_path(dirs))
+            .arg("--target-dir")
+            .arg(self.target_dir(dirs));
+
+        cmd
+    }
+
+    fn build_cmd(&self, command: &str, compiler: &Compiler, dirs: &Dirs) -> Command {
+        let mut cmd = self.base_cmd(command, &compiler.cargo, dirs);
+
+        cmd.arg("--target").arg(&compiler.triple);
+
+        cmd.env("RUSTC", &compiler.rustc);
+        cmd.env("RUSTDOC", &compiler.rustdoc);
+        cmd.env("RUSTFLAGS", &compiler.rustflags);
+        cmd.env("RUSTDOCFLAGS", &compiler.rustdocflags);
+        if !compiler.runner.is_empty() {
+            cmd.env(
+                format!("CARGO_TARGET_{}_RUNNER", compiler.triple.to_uppercase().replace('-', "_")),
+                compiler.runner.join(" "),
+            );
+        }
+
+        cmd
     }
 
-    cmd
+    #[must_use]
+    pub(crate) fn fetch(&self, cargo: impl AsRef<Path>, dirs: &Dirs) -> Command {
+        let mut cmd = Command::new(cargo.as_ref());
+
+        cmd.arg("fetch").arg("--manifest-path").arg(self.manifest_path(dirs));
+
+        cmd
+    }
+
+    #[must_use]
+    pub(crate) fn clean(&self, cargo: &Path, dirs: &Dirs) -> Command {
+        self.base_cmd("clean", cargo, dirs)
+    }
+
+    #[must_use]
+    pub(crate) fn build(&self, compiler: &Compiler, dirs: &Dirs) -> Command {
+        self.build_cmd("build", compiler, dirs)
+    }
+
+    #[must_use]
+    pub(crate) fn test(&self, compiler: &Compiler, dirs: &Dirs) -> Command {
+        self.build_cmd("test", compiler, dirs)
+    }
+
+    #[must_use]
+    pub(crate) fn run(&self, compiler: &Compiler, dirs: &Dirs) -> Command {
+        self.build_cmd("run", compiler, dirs)
+    }
 }
 
+#[must_use]
 pub(crate) fn hyperfine_command(
     warmup: u64,
     runs: u64,
-    prepare: Option<Command>,
-    a: Command,
-    b: Command,
+    prepare: Option<&str>,
+    a: &str,
+    b: &str,
 ) -> Command {
     let mut bench = Command::new("hyperfine");
 
@@ -42,10 +145,10 @@ pub(crate) fn hyperfine_command(
     }
 
     if let Some(prepare) = prepare {
-        bench.arg("--prepare").arg(format!("{:?}", prepare));
+        bench.arg("--prepare").arg(prepare);
     }
 
-    bench.arg(format!("{:?}", a)).arg(format!("{:?}", b));
+    bench.arg(a).arg(b);
 
     bench
 }
index fedab2433aa05f66f33949f35ea62cd88ec3f4ed..1760e5836ecce00a48f7a0236748dfb94329fce0 100755 (executable)
@@ -2,7 +2,7 @@
 set -e
 
 rm -rf build_sysroot/{sysroot_src/,target/,compiler-builtins/,rustc_version}
-rm -rf target/ build/ perf.data{,.old} y.bin
+rm -rf target/ build/ dist/ perf.data{,.old} y.bin
 rm -rf download/
 
 # Kept for now in case someone updates their checkout of cg_clif before running clean_all.sh
index 0d539191b12f95936b65e6d134d460b31d96c3e6..258b67e931476850a25cab17bbc2c3300a243821 100644 (file)
@@ -40,6 +40,7 @@ aot.subslice-patterns-const-eval
 aot.track-caller-attribute
 aot.float-minmax-pass
 aot.mod_bench
+aot.issue-72793
 
 testsuite.extended_sysroot
 test.rust-random/rand
index 33f146e7ba27aec13e57e55d40ebb79e3f28e359..4c2b0fa170498812b976b67041cc62ab73ff3f81 100644 (file)
@@ -9,7 +9,7 @@ Assuming `$cg_clif_dir` is the directory you cloned this repo into and you follo
 In the directory with your project (where you can do the usual `cargo build`), run:
 
 ```bash
-$ $cg_clif_dir/build/cargo-clif build
+$ $cg_clif_dir/dist/cargo-clif build
 ```
 
 This will build your project with rustc_codegen_cranelift instead of the usual LLVM backend.
@@ -19,7 +19,7 @@ This will build your project with rustc_codegen_cranelift instead of the usual L
 > You should prefer using the Cargo method.
 
 ```bash
-$ $cg_clif_dir/build/rustc-clif my_crate.rs
+$ $cg_clif_dir/dist/rustc-clif my_crate.rs
 ```
 
 ## Jit mode
@@ -32,20 +32,20 @@ In jit mode cg_clif will immediately execute your code without creating an execu
 > The jit mode will probably need cargo integration to make this possible.
 
 ```bash
-$ $cg_clif_dir/build/cargo-clif jit
+$ $cg_clif_dir/dist/cargo-clif jit
 ```
 
 or
 
 ```bash
-$ $cg_clif_dir/build/rustc-clif -Zunstable-features -Cllvm-args=mode=jit -Cprefer-dynamic my_crate.rs
+$ $cg_clif_dir/dist/rustc-clif -Zunstable-features -Cllvm-args=mode=jit -Cprefer-dynamic my_crate.rs
 ```
 
 There is also an experimental lazy jit mode. In this mode functions are only compiled once they are
 first called.
 
 ```bash
-$ $cg_clif_dir/build/cargo-clif lazy-jit
+$ $cg_clif_dir/dist/cargo-clif lazy-jit
 ```
 
 ## Shell
@@ -54,7 +54,7 @@ These are a few functions that allow you to easily run rust code from the shell
 
 ```bash
 function jit_naked() {
-    echo "$@" | $cg_clif_dir/build/rustc-clif - -Zunstable-features -Cllvm-args=mode=jit -Cprefer-dynamic
+    echo "$@" | $cg_clif_dir/dist/rustc-clif - -Zunstable-features -Cllvm-args=mode=jit -Cprefer-dynamic
 }
 
 function jit() {
diff --git a/compiler/rustc_codegen_cranelift/example/issue-72793.rs b/compiler/rustc_codegen_cranelift/example/issue-72793.rs
new file mode 100644 (file)
index 0000000..b1bb9b8
--- /dev/null
@@ -0,0 +1,24 @@
+// Adapted from rustc ui test suite (ui/type-alias-impl-trait/issue-72793.rs)
+
+#![feature(type_alias_impl_trait)]
+
+trait T { type Item; }
+
+type Alias<'a> = impl T<Item = &'a ()>;
+
+struct S;
+impl<'a> T for &'a S {
+    type Item = &'a ();
+}
+
+fn filter_positive<'a>() -> Alias<'a> {
+    &S
+}
+
+fn with_positive(fun: impl Fn(Alias<'_>)) {
+    fun(filter_positive());
+}
+
+fn main() {
+    with_positive(|_| ());
+}
index 7f85b52f083a7c2a8de18913a937a65e711474b7..1f9db1eb2a97affce42fe9395435a0b5cd0b8341 100644 (file)
@@ -19,6 +19,9 @@ pub trait Sized {}
 #[lang = "destruct"]
 pub trait Destruct {}
 
+#[lang = "tuple_trait"]
+pub trait Tuple {}
+
 #[lang = "unsize"]
 pub trait Unsize<T: ?Sized> {}
 
@@ -443,7 +446,7 @@ pub enum Option<T> {
 
 #[lang = "fn_once"]
 #[rustc_paren_sugar]
-pub trait FnOnce<Args> {
+pub trait FnOnce<Args: Tuple> {
     #[lang = "fn_once_output"]
     type Output;
 
@@ -452,7 +455,7 @@ pub trait FnOnce<Args> {
 
 #[lang = "fn_mut"]
 #[rustc_paren_sugar]
-pub trait FnMut<Args>: FnOnce<Args> {
+pub trait FnMut<Args: Tuple>: FnOnce<Args> {
     extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
 }
 
index 215d3556a17ca8cf2b5eb7a7673b5a090612da70..c00f8a2e0cdad3229ad1362047bffeb8a4be2ad9 100644 (file)
@@ -171,8 +171,6 @@ fn main() {
 
     assert_eq!(slice_ptr as usize % 4, 0);
 
-    //return;
-
     unsafe {
         printf("Hello %s\n\0" as *const str as *const i8, "printf\0" as *const str as *const i8);
 
index ad108c34992e30efa101dc5d71fa5f832e45788f..8481d9c39a3cf672e83f85b03220fabdacf61817 100644 (file)
@@ -164,6 +164,8 @@ unsafe fn test_simd() {
     let cmp_eq = _mm_cmpeq_epi8(y, y);
     let cmp_lt = _mm_cmplt_epi8(y, y);
 
+    let (zero0, zero1) = std::mem::transmute::<_, (u64, u64)>(x);
+    assert_eq!((zero0, zero1), (0, 0));
     assert_eq!(std::mem::transmute::<_, [u16; 8]>(or), [7, 7, 7, 7, 7, 7, 7, 7]);
     assert_eq!(std::mem::transmute::<_, [u16; 8]>(cmp_eq), [0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff]);
     assert_eq!(std::mem::transmute::<_, [u16; 8]>(cmp_lt), [0, 0, 0, 0, 0, 0, 0, 0]);
index c0a2e7a7883fcb14031a9ea5a38289d564d30d4a..d8f28dbcc15c8c43d9631834b087f34ed547cebb 100644 (file)
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2022-10-23"
+channel = "nightly-2022-12-13"
 components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
index 2bd8f7d1bc15d7a6690a34aad18f968f7af9bd3c..ebeca8662a5195c6408e8707a06248c189ffab99 100644 (file)
@@ -1,3 +1,5 @@
+ignore = ["y.rs"]
+
 # Matches rustfmt.toml of rustc
 version = "Two"
 use_small_heuristics = "Max"
index e6f60d1c0cb230985bf85311076b15199291a807..f782671fe36f9b45fab05a5c6f335d9880211c23 100755 (executable)
@@ -2,7 +2,7 @@
 #![forbid(unsafe_code)]/* This line is ignored by bash
 # This block is ignored by rustc
 pushd $(dirname "$0")/../
-RUSTC="$(pwd)/build/rustc-clif"
+RUSTC="$(pwd)/dist/rustc-clif"
 popd
 PROFILE=$1 OUTPUT=$2 exec $RUSTC -Zunstable-options -Cllvm-args=mode=jit -Cprefer-dynamic $0
 #*/
diff --git a/compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs b/compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs
new file mode 100644 (file)
index 0000000..a19d72a
--- /dev/null
@@ -0,0 +1,36 @@
+use std::env;
+use std::ffi::OsString;
+#[cfg(unix)]
+use std::os::unix::process::CommandExt;
+use std::path::PathBuf;
+use std::process::Command;
+
+fn main() {
+    let sysroot = PathBuf::from(env::current_exe().unwrap().parent().unwrap());
+
+    let cg_clif_dylib_path = sysroot.join(if cfg!(windows) { "bin" } else { "lib" }).join(
+        env::consts::DLL_PREFIX.to_string() + "rustc_codegen_cranelift" + env::consts::DLL_SUFFIX,
+    );
+
+    let mut args = std::env::args_os().skip(1).collect::<Vec<_>>();
+    args.push(OsString::from("-Cpanic=abort"));
+    args.push(OsString::from("-Zpanic-abort-tests"));
+    let mut codegen_backend_arg = OsString::from("-Zcodegen-backend=");
+    codegen_backend_arg.push(cg_clif_dylib_path);
+    args.push(codegen_backend_arg);
+    if !args.contains(&OsString::from("--sysroot")) {
+        args.push(OsString::from("--sysroot"));
+        args.push(OsString::from(sysroot.to_str().unwrap()));
+    }
+
+    // Ensure that the right toolchain is used
+    env::set_var("RUSTUP_TOOLCHAIN", env!("RUSTUP_TOOLCHAIN"));
+
+    #[cfg(unix)]
+    Command::new("rustdoc").args(args).exec();
+
+    #[cfg(not(unix))]
+    std::process::exit(
+        Command::new("rustdoc").args(args).spawn().unwrap().wait().unwrap().code().unwrap_or(1),
+    );
+}
index d6a37789599fe8d0621de8a2577fc77aa45b1be3..6c64b7de7daa10d863a903a186e0ee9c4846aeed 100644 (file)
@@ -27,24 +27,6 @@ index d95b5b7f17f..00b6f0e3635 100644
  [dev-dependencies]
  rand = "0.7"
  rand_xorshift = "0.2"
-diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
-index 8431aa7b818..a3ff7e68ce5 100644
---- a/src/tools/compiletest/src/runtest.rs
-+++ b/src/tools/compiletest/src/runtest.rs
-@@ -3489,12 +3489,7 @@ fn normalize_output(&self, output: &str, custom_rules: &[(String, String)]) -> S
-         let compiler_src_dir = base_dir.join("compiler");
-         normalize_path(&compiler_src_dir, "$(echo '$COMPILER_DIR')");
-
--        if let Some(virtual_rust_source_base_dir) =
--            option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR").map(PathBuf::from)
--        {
--            normalize_path(&virtual_rust_source_base_dir.join("library"), "$(echo '$SRC_DIR')");
--            normalize_path(&virtual_rust_source_base_dir.join("compiler"), "$(echo '$COMPILER_DIR')");
--        }
-+        normalize_path(&Path::new("$(cd ../build_sysroot/sysroot_src/library; pwd)"), "$(echo '$SRC_DIR')");
-
-         // Paths into the build directory
-         let test_build_dir = &self.config.build_base;
 EOF
 
 cat > config.toml <<EOF
@@ -54,7 +36,7 @@ changelog-seen = 2
 ninja = false
 
 [build]
-rustc = "$(pwd)/../build/rustc-clif"
+rustc = "$(pwd)/../dist/rustc-clif"
 cargo = "$(rustup which cargo)"
 full-bootstrap = true
 local-rebuild = true
@@ -69,6 +51,8 @@ popd
 # FIXME remove once inline asm is fully supported
 export RUSTFLAGS="$RUSTFLAGS --cfg=rustix_use_libc"
 
+export CFG_VIRTUAL_RUST_SOURCE_BASE_DIR="$(cd build_sysroot/sysroot_src; pwd)"
+
 # Allow the testsuite to use llvm tools
 host_triple=$(rustc -vV | grep host | cut -d: -f2 | tr -d " ")
 export LLVM_BIN_DIR="$(rustc --print sysroot)/lib/rustlib/$host_triple/bin"
index 9b5db3cf81f0e3341f553398f6354c9320cf0640..04ad77ec97eac3a76d01166d875cf18bc073f76f 100755 (executable)
@@ -20,6 +20,7 @@ for test in $(rg -i --files-with-matches "//(\[\w+\])?~[^\|]*\s*ERR|// error-pat
 done
 
 git checkout -- src/test/ui/issues/auxiliary/issue-3136-a.rs # contains //~ERROR, but shouldn't be removed
+git checkout -- src/test/ui/proc-macro/pretty-print-hack/
 
 # missing features
 # ================
@@ -30,6 +31,7 @@ rm src/test/incremental/issue-80691-bad-eval-cache.rs # -Cpanic=abort causes abo
 
 # requires compiling with -Cpanic=unwind
 rm -r src/test/ui/macros/rfc-2011-nicer-assert-messages/
+rm -r src/test/run-make/test-benches
 
 # vendor intrinsics
 rm src/test/ui/sse2.rs # cpuid not supported, so sse2 not detected
@@ -64,6 +66,8 @@ rm src/test/ui/fn/dyn-fn-alignment.rs # wants a 256 byte alignment
 rm -r src/test/run-make/emit-named-files # requires full --emit support
 rm src/test/ui/abi/stack-probes.rs # stack probes not yet implemented
 rm src/test/ui/simd/intrinsic/ptr-cast.rs # simd_expose_addr intrinsic unimplemented
+rm -r src/test/run-make/repr128-dwarf # debuginfo test
+rm src/test/codegen-units/item-collection/asm-sym.rs # requires support for sym in asm!()
 
 # optimization tests
 # ==================
@@ -82,20 +86,20 @@ rm src/test/ui/abi/stack-protector.rs # requires stack protector support
 rm src/test/ui/mir/mir_misc_casts.rs # depends on deduplication of constants
 rm src/test/ui/mir/mir_raw_fat_ptr.rs # same
 rm src/test/ui/consts/issue-33537.rs # same
+rm src/test/ui/layout/valid_range_oob.rs # different ICE message
 
 # doesn't work due to the way the rustc test suite is invoked.
 # should work when using ./x.py test the way it is intended
 # ============================================================
-rm -r src/test/run-make/emit-shared-files # requires the rustdoc executable in build/bin/
+rm -r src/test/run-make/emit-shared-files # requires the rustdoc executable in dist/bin/
 rm -r src/test/run-make/unstable-flag-required # same
 rm -r src/test/run-make/rustdoc-* # same
 rm -r src/test/run-make/issue-88756-default-output # same
 rm -r src/test/run-make/remap-path-prefix-dwarf # requires llvm-dwarfdump
+rm -r src/test/ui/consts/missing_span_in_backtrace.rs # expects sysroot source to be elsewhere
 
 # genuine bugs
 # ============
-rm src/test/ui/allocator/no_std-alloc-error-handler-default.rs # missing rust_oom definition
-
 rm src/test/incremental/spike-neg1.rs # errors out for some reason
 rm src/test/incremental/spike-neg2.rs # same
 rm src/test/ui/issues/issue-74564-if-expr-stack-overflow.rs # gives a stackoverflow before the backend runs
@@ -104,6 +108,8 @@ rm src/test/ui/type-alias-impl-trait/assoc-projection-ice.rs # produces ICE
 
 rm src/test/ui/simd/intrinsic/generic-reduction-pass.rs # simd_reduce_add_unordered doesn't accept an accumulator for integer vectors
 
+rm src/test/ui/runtime/out-of-stack.rs # SIGSEGV instead of SIGABRT for some reason (#1301)
+
 # bugs in the test suite
 # ======================
 rm src/test/ui/backtrace.rs # TODO warning
@@ -111,6 +117,8 @@ rm src/test/ui/simple_global_asm.rs # TODO add needs-asm-support
 rm src/test/ui/test-attrs/test-type.rs # TODO panic message on stderr. correct stdout
 # not sure if this is actually a bug in the test suite, but the symbol list shows the function without leading _ for some reason
 rm -r src/test/run-make/native-link-modifier-bundle
+rm src/test/ui/process/nofile-limit.rs # TODO some AArch64 linking issue
+rm src/test/ui/dyn-star/dispatch-on-pin-mut.rs # TODO failed assertion in vtable::get_ptr_and_method_ref
 
 rm src/test/ui/stdio-is-blocking.rs # really slow with unoptimized libstd
 
index 1e22537c2ba42ac27202012738cf55ce004042b7..65cc6b4376713d8c7e855c2fca1f833894a3cd09 100644 (file)
@@ -56,13 +56,13 @@ pub(crate) fn conv_to_call_conv(c: Conv, default_call_conv: CallConv) -> CallCon
 
 pub(crate) fn get_function_sig<'tcx>(
     tcx: TyCtxt<'tcx>,
-    triple: &target_lexicon::Triple,
+    default_call_conv: CallConv,
     inst: Instance<'tcx>,
 ) -> Signature {
     assert!(!inst.substs.needs_infer());
     clif_sig_from_fn_abi(
         tcx,
-        CallConv::triple_default(triple),
+        default_call_conv,
         &RevealAllLayoutCx(tcx).fn_abi_of_instance(inst, ty::List::empty()),
     )
 }
@@ -74,7 +74,7 @@ pub(crate) fn import_function<'tcx>(
     inst: Instance<'tcx>,
 ) -> FuncId {
     let name = tcx.symbol_name(inst).name;
-    let sig = get_function_sig(tcx, module.isa().triple(), inst);
+    let sig = get_function_sig(tcx, module.target_config().default_call_conv, inst);
     match module.declare_function(name, Linkage::Import, &sig) {
         Ok(func_id) => func_id,
         Err(ModuleError::IncompatibleDeclaration(_)) => tcx.sess.fatal(&format!(
@@ -341,18 +341,16 @@ pub(crate) fn codegen_terminator_call<'tcx>(
     destination: Place<'tcx>,
     target: Option<BasicBlock>,
 ) {
-    let fn_ty = fx.monomorphize(func.ty(fx.mir, fx.tcx));
-    let fn_sig =
-        fx.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), fn_ty.fn_sig(fx.tcx));
+    let func = codegen_operand(fx, func);
+    let fn_sig = func.layout().ty.fn_sig(fx.tcx);
 
     let ret_place = codegen_place(fx, destination);
 
     // Handle special calls like intrinsics and empty drop glue.
-    let instance = if let ty::FnDef(def_id, substs) = *fn_ty.kind() {
-        let instance = ty::Instance::resolve(fx.tcx, ty::ParamEnv::reveal_all(), def_id, substs)
-            .unwrap()
-            .unwrap()
-            .polymorphize(fx.tcx);
+    let instance = if let ty::FnDef(def_id, substs) = *func.layout().ty.kind() {
+        let instance =
+            ty::Instance::expect_resolve(fx.tcx, ty::ParamEnv::reveal_all(), def_id, substs)
+                .polymorphize(fx.tcx);
 
         if fx.tcx.symbol_name(instance).name.starts_with("llvm.") {
             crate::intrinsics::codegen_llvm_intrinsic_call(
@@ -391,17 +389,17 @@ pub(crate) fn codegen_terminator_call<'tcx>(
         None
     };
 
-    let extra_args = &args[fn_sig.inputs().len()..];
+    let extra_args = &args[fn_sig.inputs().skip_binder().len()..];
     let extra_args = fx
         .tcx
         .mk_type_list(extra_args.iter().map(|op_arg| fx.monomorphize(op_arg.ty(fx.mir, fx.tcx))));
     let fn_abi = if let Some(instance) = instance {
         RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(instance, extra_args)
     } else {
-        RevealAllLayoutCx(fx.tcx).fn_abi_of_fn_ptr(fn_ty.fn_sig(fx.tcx), extra_args)
+        RevealAllLayoutCx(fx.tcx).fn_abi_of_fn_ptr(fn_sig, extra_args)
     };
 
-    let is_cold = if fn_sig.abi == Abi::RustCold {
+    let is_cold = if fn_sig.abi() == Abi::RustCold {
         true
     } else {
         instance
@@ -418,7 +416,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
     }
 
     // Unpack arguments tuple for closures
-    let mut args = if fn_sig.abi == Abi::RustCall {
+    let mut args = if fn_sig.abi() == Abi::RustCall {
         assert_eq!(args.len(), 2, "rust-call abi requires two arguments");
         let self_arg = codegen_call_argument_operand(fx, &args[0]);
         let pack_arg = codegen_call_argument_operand(fx, &args[1]);
@@ -486,7 +484,7 @@ enum CallTarget {
                 fx.add_comment(nop_inst, "indirect call");
             }
 
-            let func = codegen_operand(fx, func).load_scalar(fx);
+            let func = func.load_scalar(fx);
             let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi);
             let sig = fx.bcx.import_signature(sig);
 
@@ -517,11 +515,11 @@ enum CallTarget {
         };
 
         // FIXME find a cleaner way to support varargs
-        if fn_sig.c_variadic {
-            if !matches!(fn_sig.abi, Abi::C { .. }) {
+        if fn_sig.c_variadic() {
+            if !matches!(fn_sig.abi(), Abi::C { .. }) {
                 fx.tcx.sess.span_fatal(
                     source_info.span,
-                    &format!("Variadic call for non-C abi {:?}", fn_sig.abi),
+                    &format!("Variadic call for non-C abi {:?}", fn_sig.abi()),
                 );
             }
             let sig_ref = fx.bcx.func.dfg.call_signature(call_inst).unwrap();
index 12bb00d346db42c42c88adfad2d5939df371c1f6..8508227179ac611fb77c350c541e5835e0313936 100644 (file)
@@ -66,7 +66,7 @@ fn codegen_inner(
         };
 
         let sig = Signature {
-            call_conv: CallConv::triple_default(module.isa().triple()),
+            call_conv: module.target_config().default_call_conv,
             params: arg_tys.iter().cloned().map(AbiParam::new).collect(),
             returns: output.into_iter().map(AbiParam::new).collect(),
         };
@@ -104,7 +104,7 @@ fn codegen_inner(
     }
 
     let sig = Signature {
-        call_conv: CallConv::triple_default(module.isa().triple()),
+        call_conv: module.target_config().default_call_conv,
         params: vec![AbiParam::new(usize_ty), AbiParam::new(usize_ty)],
         returns: vec![],
     };
index 1db44502742e921b4bcbbdff9d76bce7e1e5e849..89d955e8bf2e1d84c1a40045d0b063140d325525 100644 (file)
@@ -59,7 +59,7 @@ pub(crate) fn codegen_fn<'tcx>(
 
     // Declare function
     let symbol_name = tcx.symbol_name(instance).name.to_string();
-    let sig = get_function_sig(tcx, module.isa().triple(), instance);
+    let sig = get_function_sig(tcx, module.target_config().default_call_conv, instance);
     let func_id = module.declare_function(&symbol_name, Linkage::Local, &sig).unwrap();
 
     // Make the FunctionBuilder
@@ -372,8 +372,10 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
                 }
             }
 
-            TerminatorKind::SwitchInt { discr, switch_ty, targets } => {
-                let discr = codegen_operand(fx, discr).load_scalar(fx);
+            TerminatorKind::SwitchInt { discr, targets } => {
+                let discr = codegen_operand(fx, discr);
+                let switch_ty = discr.layout().ty;
+                let discr = discr.load_scalar(fx);
 
                 let use_bool_opt = switch_ty.kind() == fx.tcx.types.bool.kind()
                     || (targets.iter().count() == 1 && targets.iter().next().unwrap().0 == 0);
@@ -388,11 +390,9 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
                         _ => unreachable!("{:?}", targets),
                     };
 
-                    let discr = crate::optimize::peephole::maybe_unwrap_bint(&mut fx.bcx, discr);
                     let (discr, is_inverted) =
                         crate::optimize::peephole::maybe_unwrap_bool_not(&mut fx.bcx, discr);
                     let test_zero = if is_inverted { !test_zero } else { test_zero };
-                    let discr = crate::optimize::peephole::maybe_unwrap_bint(&mut fx.bcx, discr);
                     if let Some(taken) = crate::optimize::peephole::maybe_known_branch_taken(
                         &fx.bcx, discr, test_zero,
                     ) {
@@ -569,7 +569,7 @@ fn codegen_stmt<'tcx>(
                         UnOp::Not => match layout.ty.kind() {
                             ty::Bool => {
                                 let res = fx.bcx.ins().icmp_imm(IntCC::Equal, val, 0);
-                                CValue::by_val(fx.bcx.ins().bint(types::I8, res), layout)
+                                CValue::by_val(res, layout)
                             }
                             ty::Uint(_) | ty::Int(_) => {
                                 CValue::by_val(fx.bcx.ins().bnot(val), layout)
@@ -577,12 +577,6 @@ fn codegen_stmt<'tcx>(
                             _ => unreachable!("un op Not for {:?}", layout.ty),
                         },
                         UnOp::Neg => match layout.ty.kind() {
-                            ty::Int(IntTy::I128) => {
-                                // FIXME remove this case once ineg.i128 works
-                                let zero =
-                                    CValue::const_val(fx, layout, ty::ScalarInt::null(layout.size));
-                                crate::num::codegen_int_binop(fx, BinOp::Sub, zero, operand)
-                            }
                             ty::Int(_) => CValue::by_val(fx.bcx.ins().ineg(val), layout),
                             ty::Float(_) => CValue::by_val(fx.bcx.ins().fneg(val), layout),
                             _ => unreachable!("un op Neg for {:?}", layout.ty),
index bad5d1f08a9cf5454766b36de3f2614e5a6020a4..5091c5a9fedacbb7f4dda7b4d5ab7f086f17d1d7 100644 (file)
@@ -149,7 +149,7 @@ pub(crate) fn clif_int_or_float_cast(
         }
 
         let is_not_nan = fx.bcx.ins().fcmp(FloatCC::Equal, from, from);
-        let zero = fx.bcx.ins().iconst(to_ty, 0);
+        let zero = type_zero_value(&mut fx.bcx, to_ty);
         fx.bcx.ins().select(is_not_nan, val, zero)
     } else if from_ty.is_float() && to_ty.is_float() {
         // float -> float
index 589594465783e1611c688cd17f5c82325ae9576f..2dcd42fbd8f431833ac46b414c539e40c828f0e8 100644 (file)
@@ -162,11 +162,20 @@ pub(crate) fn codegen_icmp_imm(
             }
         }
     } else {
-        let rhs = i64::try_from(rhs).expect("codegen_icmp_imm rhs out of range for <128bit int");
+        let rhs = rhs as i64; // Truncates on purpose in case rhs is actually an unsigned value
         fx.bcx.ins().icmp_imm(intcc, lhs, rhs)
     }
 }
 
+pub(crate) fn type_zero_value(bcx: &mut FunctionBuilder<'_>, ty: Type) -> Value {
+    if ty == types::I128 {
+        let zero = bcx.ins().iconst(types::I64, 0);
+        bcx.ins().iconcat(zero, zero)
+    } else {
+        bcx.ins().iconst(ty, 0)
+    }
+}
+
 pub(crate) fn type_min_max_value(
     bcx: &mut FunctionBuilder<'_>,
     ty: Type,
index a6bde88408497ed9d12a7cd28a82966d7fc52439..dee6fb5b5130d1f27abaf1fda1581605a82973b5 100644 (file)
@@ -28,9 +28,7 @@ pub(crate) fn new() -> Self {
     }
 
     pub(crate) fn finalize(mut self, tcx: TyCtxt<'_>, module: &mut dyn Module) {
-        //println!("todo {:?}", self.todo);
         define_all_allocs(tcx, module, &mut self);
-        //println!("done {:?}", self.done);
         self.done.clear();
     }
 }
@@ -268,16 +266,7 @@ fn data_id_for_static(
     def_id: DefId,
     definition: bool,
 ) -> DataId {
-    let rlinkage = tcx.codegen_fn_attrs(def_id).linkage;
-    let linkage = if definition {
-        crate::linkage::get_static_linkage(tcx, def_id)
-    } else if rlinkage == Some(rustc_middle::mir::mono::Linkage::ExternalWeak)
-        || rlinkage == Some(rustc_middle::mir::mono::Linkage::WeakAny)
-    {
-        Linkage::Preemptible
-    } else {
-        Linkage::Import
-    };
+    let attrs = tcx.codegen_fn_attrs(def_id);
 
     let instance = Instance::mono(tcx, def_id).polymorphize(tcx);
     let symbol_name = tcx.symbol_name(instance).name;
@@ -289,22 +278,30 @@ fn data_id_for_static(
     };
     let align = tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap().align.pref.bytes();
 
-    let attrs = tcx.codegen_fn_attrs(def_id);
+    if let Some(import_linkage) = attrs.import_linkage {
+        assert!(!definition);
 
-    let data_id = match module.declare_data(
-        &*symbol_name,
-        linkage,
-        is_mutable,
-        attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL),
-    ) {
-        Ok(data_id) => data_id,
-        Err(ModuleError::IncompatibleDeclaration(_)) => tcx.sess.fatal(&format!(
-            "attempt to declare `{symbol_name}` as static, but it was already declared as function"
-        )),
-        Err(err) => Err::<_, _>(err).unwrap(),
-    };
+        let linkage = if import_linkage == rustc_middle::mir::mono::Linkage::ExternalWeak
+            || import_linkage == rustc_middle::mir::mono::Linkage::WeakAny
+        {
+            Linkage::Preemptible
+        } else {
+            Linkage::Import
+        };
+
+        let data_id = match module.declare_data(
+            &*symbol_name,
+            linkage,
+            is_mutable,
+            attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL),
+        ) {
+            Ok(data_id) => data_id,
+            Err(ModuleError::IncompatibleDeclaration(_)) => tcx.sess.fatal(&format!(
+                "attempt to declare `{symbol_name}` as static, but it was already declared as function"
+            )),
+            Err(err) => Err::<_, _>(err).unwrap(),
+        };
 
-    if rlinkage.is_some() {
         // Comment copied from https://github.com/rust-lang/rust/blob/45060c2a66dfd667f88bd8b94261b28a58d85bd5/src/librustc_codegen_llvm/consts.rs#L141
         // Declare an internal global `extern_with_linkage_foo` which
         // is initialized with the address of `foo`.  If `foo` is
@@ -326,10 +323,34 @@ fn data_id_for_static(
             Err(ModuleError::DuplicateDefinition(_)) => {}
             res => res.unwrap(),
         }
-        ref_data_id
-    } else {
-        data_id
+
+        return ref_data_id;
     }
+
+    let linkage = if definition {
+        crate::linkage::get_static_linkage(tcx, def_id)
+    } else if attrs.linkage == Some(rustc_middle::mir::mono::Linkage::ExternalWeak)
+        || attrs.linkage == Some(rustc_middle::mir::mono::Linkage::WeakAny)
+    {
+        Linkage::Preemptible
+    } else {
+        Linkage::Import
+    };
+
+    let data_id = match module.declare_data(
+        &*symbol_name,
+        linkage,
+        is_mutable,
+        attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL),
+    ) {
+        Ok(data_id) => data_id,
+        Err(ModuleError::IncompatibleDeclaration(_)) => tcx.sess.fatal(&format!(
+            "attempt to declare `{symbol_name}` as static, but it was already declared as function"
+        )),
+        Err(err) => Err::<_, _>(err).unwrap(),
+    };
+
+    data_id
 }
 
 fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut ConstantCx) {
@@ -348,8 +369,6 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
                 (data_id, alloc, None)
             }
             TodoItem::Static(def_id) => {
-                //println!("static {:?}", def_id);
-
                 let section_name = tcx.codegen_fn_attrs(def_id).link_section;
 
                 let alloc = tcx.eval_static_initializer(def_id).unwrap();
@@ -359,7 +378,6 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
             }
         };
 
-        //("data_id {}", data_id);
         if cx.done.contains(&data_id) {
             continue;
         }
index d26392c4913b508a3ab68335d2ea771243c6b42d..493359c743f119d6bcee87920e595c943a009642 100644 (file)
@@ -39,7 +39,9 @@ pub(crate) fn new(isa: &dyn TargetIsa, pic_eh_frame: bool) -> Self {
     }
 
     pub(crate) fn add_function(&mut self, func_id: FuncId, context: &Context, isa: &dyn TargetIsa) {
-        let unwind_info = if let Some(unwind_info) = context.create_unwind_info(isa).unwrap() {
+        let unwind_info = if let Some(unwind_info) =
+            context.compiled_code().unwrap().create_unwind_info(isa).unwrap()
+        {
             unwind_info
         } else {
             return;
index 97b395bcd05186b199e59026ddec9fda4472dc77..3cbf313adf0df5a69887cdb1f0516245f2b23232 100644 (file)
@@ -1,6 +1,7 @@
 //! Handling of enum discriminants
 //!
-//! Adapted from <https://github.com/rust-lang/rust/blob/d760df5aea483aae041c9a241e7acacf48f75035/src/librustc_codegen_ssa/mir/place.rs>
+//! Adapted from <https://github.com/rust-lang/rust/blob/31c0645b9d2539f47eecb096142474b29dc542f7/compiler/rustc_codegen_ssa/src/mir/place.rs>
+//! (<https://github.com/rust-lang/rust/pull/104535>)
 
 use rustc_target::abi::{Int, TagEncoding, Variants};
 
@@ -47,13 +48,19 @@ pub(crate) fn codegen_set_discriminant<'tcx>(
         } => {
             if variant_index != untagged_variant {
                 let niche = place.place_field(fx, mir::Field::new(tag_field));
+                let niche_type = fx.clif_type(niche.layout().ty).unwrap();
                 let niche_value = variant_index.as_u32() - niche_variants.start().as_u32();
-                let niche_value = ty::ScalarInt::try_from_uint(
-                    u128::from(niche_value).wrapping_add(niche_start),
-                    niche.layout().size,
-                )
-                .unwrap();
-                let niche_llval = CValue::const_val(fx, niche.layout(), niche_value);
+                let niche_value = (niche_value as u128).wrapping_add(niche_start);
+                let niche_value = match niche_type {
+                    types::I128 => {
+                        let lsb = fx.bcx.ins().iconst(types::I64, niche_value as u64 as i64);
+                        let msb =
+                            fx.bcx.ins().iconst(types::I64, (niche_value >> 64) as u64 as i64);
+                        fx.bcx.ins().iconcat(lsb, msb)
+                    }
+                    ty => fx.bcx.ins().iconst(ty, niche_value as i64),
+                };
+                let niche_llval = CValue::by_val(niche_value, niche.layout());
                 niche.write_cvalue(fx, niche_llval);
             }
         }
@@ -96,6 +103,7 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
         }
     };
 
+    let cast_to_size = dest_layout.layout.size();
     let cast_to = fx.clif_type(dest_layout.ty).unwrap();
 
     // Read the tag/niche-encoded discriminant from memory.
@@ -114,21 +122,128 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
             dest.write_cvalue(fx, res);
         }
         TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start } => {
-            // Rebase from niche values to discriminants, and check
-            // whether the result is in range for the niche variants.
-
-            // We first compute the "relative discriminant" (wrt `niche_variants`),
-            // that is, if `n = niche_variants.end() - niche_variants.start()`,
-            // we remap `niche_start..=niche_start + n` (which may wrap around)
-            // to (non-wrap-around) `0..=n`, to be able to check whether the
-            // discriminant corresponds to a niche variant with one comparison.
-            // We also can't go directly to the (variant index) discriminant
-            // and check that it is in the range `niche_variants`, because
-            // that might not fit in the same type, on top of needing an extra
-            // comparison (see also the comment on `let niche_discr`).
-            let relative_discr = if niche_start == 0 {
-                tag
+            let tag_size = tag_scalar.size(fx);
+            let max_unsigned = tag_size.unsigned_int_max();
+            let max_signed = tag_size.signed_int_max() as u128;
+            let min_signed = max_signed + 1;
+            let relative_max = niche_variants.end().as_u32() - niche_variants.start().as_u32();
+            let niche_end = niche_start.wrapping_add(relative_max as u128) & max_unsigned;
+            let range = tag_scalar.valid_range(fx);
+
+            let sle = |lhs: u128, rhs: u128| -> bool {
+                // Signed and unsigned comparisons give the same results,
+                // except that in signed comparisons an integer with the
+                // sign bit set is less than one with the sign bit clear.
+                // Toggle the sign bit to do a signed comparison.
+                (lhs ^ min_signed) <= (rhs ^ min_signed)
+            };
+
+            // We have a subrange `niche_start..=niche_end` inside `range`.
+            // If the value of the tag is inside this subrange, it's a
+            // "niche value", an increment of the discriminant. Otherwise it
+            // indicates the untagged variant.
+            // A general algorithm to extract the discriminant from the tag
+            // is:
+            // relative_tag = tag - niche_start
+            // is_niche = relative_tag <= (ule) relative_max
+            // discr = if is_niche {
+            //     cast(relative_tag) + niche_variants.start()
+            // } else {
+            //     untagged_variant
+            // }
+            // However, we will likely be able to emit simpler code.
+
+            // Find the least and greatest values in `range`, considered
+            // both as signed and unsigned.
+            let (low_unsigned, high_unsigned) =
+                if range.start <= range.end { (range.start, range.end) } else { (0, max_unsigned) };
+            let (low_signed, high_signed) = if sle(range.start, range.end) {
+                (range.start, range.end)
             } else {
+                (min_signed, max_signed)
+            };
+
+            let niches_ule = niche_start <= niche_end;
+            let niches_sle = sle(niche_start, niche_end);
+            let cast_smaller = cast_to_size <= tag_size;
+
+            // In the algorithm above, we can change
+            // cast(relative_tag) + niche_variants.start()
+            // into
+            // cast(tag + (niche_variants.start() - niche_start))
+            // if either the casted type is no larger than the original
+            // type, or if the niche values are contiguous (in either the
+            // signed or unsigned sense).
+            let can_incr = cast_smaller || niches_ule || niches_sle;
+
+            let data_for_boundary_niche = || -> Option<(IntCC, u128)> {
+                if !can_incr {
+                    None
+                } else if niche_start == low_unsigned {
+                    Some((IntCC::UnsignedLessThanOrEqual, niche_end))
+                } else if niche_end == high_unsigned {
+                    Some((IntCC::UnsignedGreaterThanOrEqual, niche_start))
+                } else if niche_start == low_signed {
+                    Some((IntCC::SignedLessThanOrEqual, niche_end))
+                } else if niche_end == high_signed {
+                    Some((IntCC::SignedGreaterThanOrEqual, niche_start))
+                } else {
+                    None
+                }
+            };
+
+            let (is_niche, tagged_discr, delta) = if relative_max == 0 {
+                // Best case scenario: only one tagged variant. This will
+                // likely become just a comparison and a jump.
+                // The algorithm is:
+                // is_niche = tag == niche_start
+                // discr = if is_niche {
+                //     niche_start
+                // } else {
+                //     untagged_variant
+                // }
+                let is_niche = codegen_icmp_imm(fx, IntCC::Equal, tag, niche_start as i128);
+                let tagged_discr =
+                    fx.bcx.ins().iconst(cast_to, niche_variants.start().as_u32() as i64);
+                (is_niche, tagged_discr, 0)
+            } else if let Some((predicate, constant)) = data_for_boundary_niche() {
+                // The niche values are either the lowest or the highest in
+                // `range`. We can avoid the first subtraction in the
+                // algorithm.
+                // The algorithm is now this:
+                // is_niche = tag <= niche_end
+                // discr = if is_niche {
+                //     cast(tag + (niche_variants.start() - niche_start))
+                // } else {
+                //     untagged_variant
+                // }
+                // (the first line may instead be tag >= niche_start,
+                // and may be a signed or unsigned comparison)
+                // The arithmetic must be done before the cast, so we can
+                // have the correct wrapping behavior. See issue #104519 for
+                // the consequences of getting this wrong.
+                let is_niche = codegen_icmp_imm(fx, predicate, tag, constant as i128);
+                let delta = (niche_variants.start().as_u32() as u128).wrapping_sub(niche_start);
+                let incr_tag = if delta == 0 {
+                    tag
+                } else {
+                    let delta = match fx.bcx.func.dfg.value_type(tag) {
+                        types::I128 => {
+                            let lsb = fx.bcx.ins().iconst(types::I64, delta as u64 as i64);
+                            let msb = fx.bcx.ins().iconst(types::I64, (delta >> 64) as u64 as i64);
+                            fx.bcx.ins().iconcat(lsb, msb)
+                        }
+                        ty => fx.bcx.ins().iconst(ty, delta as i64),
+                    };
+                    fx.bcx.ins().iadd(tag, delta)
+                };
+
+                let cast_tag = clif_intcast(fx, incr_tag, cast_to, !niches_ule);
+
+                (is_niche, cast_tag, 0)
+            } else {
+                // The special cases don't apply, so we'll have to go with
+                // the general algorithm.
                 let niche_start = match fx.bcx.func.dfg.value_type(tag) {
                     types::I128 => {
                         let lsb = fx.bcx.ins().iconst(types::I64, niche_start as u64 as i64);
@@ -138,40 +253,40 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
                     }
                     ty => fx.bcx.ins().iconst(ty, niche_start as i64),
                 };
-                fx.bcx.ins().isub(tag, niche_start)
-            };
-            let relative_max = niche_variants.end().as_u32() - niche_variants.start().as_u32();
-            let is_niche = {
-                codegen_icmp_imm(
+                let relative_discr = fx.bcx.ins().isub(tag, niche_start);
+                let cast_tag = clif_intcast(fx, relative_discr, cast_to, false);
+                let is_niche = crate::common::codegen_icmp_imm(
                     fx,
                     IntCC::UnsignedLessThanOrEqual,
                     relative_discr,
                     i128::from(relative_max),
-                )
+                );
+                (is_niche, cast_tag, niche_variants.start().as_u32() as u128)
             };
 
-            // NOTE(eddyb) this addition needs to be performed on the final
-            // type, in case the niche itself can't represent all variant
-            // indices (e.g. `u8` niche with more than `256` variants,
-            // but enough uninhabited variants so that the remaining variants
-            // fit in the niche).
-            // In other words, `niche_variants.end - niche_variants.start`
-            // is representable in the niche, but `niche_variants.end`
-            // might not be, in extreme cases.
-            let niche_discr = {
-                let relative_discr = if relative_max == 0 {
-                    // HACK(eddyb) since we have only one niche, we know which
-                    // one it is, and we can avoid having a dynamic value here.
-                    fx.bcx.ins().iconst(cast_to, 0)
-                } else {
-                    clif_intcast(fx, relative_discr, cast_to, false)
+            let tagged_discr = if delta == 0 {
+                tagged_discr
+            } else {
+                let delta = match cast_to {
+                    types::I128 => {
+                        let lsb = fx.bcx.ins().iconst(types::I64, delta as u64 as i64);
+                        let msb = fx.bcx.ins().iconst(types::I64, (delta >> 64) as u64 as i64);
+                        fx.bcx.ins().iconcat(lsb, msb)
+                    }
+                    ty => fx.bcx.ins().iconst(ty, delta as i64),
                 };
-                fx.bcx.ins().iadd_imm(relative_discr, i64::from(niche_variants.start().as_u32()))
+                fx.bcx.ins().iadd(tagged_discr, delta)
             };
 
-            let untagged_variant =
-                fx.bcx.ins().iconst(cast_to, i64::from(untagged_variant.as_u32()));
-            let discr = fx.bcx.ins().select(is_niche, niche_discr, untagged_variant);
+            let untagged_variant = if cast_to == types::I128 {
+                let zero = fx.bcx.ins().iconst(types::I64, 0);
+                let untagged_variant =
+                    fx.bcx.ins().iconst(types::I64, i64::from(untagged_variant.as_u32()));
+                fx.bcx.ins().iconcat(untagged_variant, zero)
+            } else {
+                fx.bcx.ins().iconst(cast_to, i64::from(untagged_variant.as_u32()))
+            };
+            let discr = fx.bcx.ins().select(is_niche, tagged_discr, untagged_variant);
             let res = CValue::by_val(discr, dest_layout);
             dest.write_cvalue(fx, res);
         }
index 6a430b5215e36d11b483213b5bb7e74c75425727..be1b8c9ead3bf2e133d326818df523e19f201fda 100644 (file)
@@ -159,7 +159,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
 
     tcx.sess.abort_if_errors();
 
-    jit_module.finalize_definitions();
+    jit_module.finalize_definitions().unwrap();
     unsafe { cx.unwind_context.register_jit(&jit_module) };
 
     println!(
@@ -245,7 +245,11 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) ->
             let backend_config = lazy_jit_state.backend_config.clone();
 
             let name = tcx.symbol_name(instance).name;
-            let sig = crate::abi::get_function_sig(tcx, jit_module.isa().triple(), instance);
+            let sig = crate::abi::get_function_sig(
+                tcx,
+                jit_module.target_config().default_call_conv,
+                instance,
+            );
             let func_id = jit_module.declare_function(name, Linkage::Export, &sig).unwrap();
 
             let current_ptr = jit_module.read_got_entry(func_id);
@@ -278,7 +282,7 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) ->
             });
 
             assert!(cx.global_asm.is_empty());
-            jit_module.finalize_definitions();
+            jit_module.finalize_definitions().unwrap();
             unsafe { cx.unwind_context.register_jit(&jit_module) };
             jit_module.get_finalized_function(func_id)
         })
@@ -344,7 +348,7 @@ fn codegen_shim<'tcx>(
     let pointer_type = module.target_config().pointer_type();
 
     let name = tcx.symbol_name(inst).name;
-    let sig = crate::abi::get_function_sig(tcx, module.isa().triple(), inst);
+    let sig = crate::abi::get_function_sig(tcx, module.target_config().default_call_conv, inst);
     let func_id = module.declare_function(name, Linkage::Export, &sig).unwrap();
 
     let instance_ptr = Box::into_raw(Box::new(inst));
index 8f5714ecb417704e446edda114f65b4966facb66..6e925cea277078b68ac5d03de3cc18fae0e91e71 100644 (file)
@@ -24,7 +24,8 @@ fn predefine_mono_items<'tcx>(
                 MonoItem::Fn(instance) => {
                     let name = tcx.symbol_name(instance).name;
                     let _inst_guard = crate::PrintOnPanic(|| format!("{:?} {}", instance, name));
-                    let sig = get_function_sig(tcx, module.isa().triple(), instance);
+                    let sig =
+                        get_function_sig(tcx, module.target_config().default_call_conv, instance);
                     let linkage = crate::linkage::get_clif_linkage(
                         mono_item,
                         linkage,
index 783d426c30bcc0d14cf94bb658b854e1e4b337fb..f722e52284fe8205f269103a620fec33015ef9a4 100644 (file)
 pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
     fx: &mut FunctionCx<'_, '_, 'tcx>,
     intrinsic: &str,
-    _substs: SubstsRef<'tcx>,
+    substs: SubstsRef<'tcx>,
     args: &[mir::Operand<'tcx>],
     ret: CPlace<'tcx>,
     target: Option<BasicBlock>,
 ) {
-    match intrinsic {
-        "llvm.x86.sse2.pause" | "llvm.aarch64.isb" => {
-            // Spin loop hint
-        }
+    if intrinsic.starts_with("llvm.aarch64") {
+        return llvm_aarch64::codegen_aarch64_llvm_intrinsic_call(
+            fx, intrinsic, substs, args, ret, target,
+        );
+    }
+    if intrinsic.starts_with("llvm.x86") {
+        return llvm_x86::codegen_x86_llvm_intrinsic_call(fx, intrinsic, substs, args, ret, target);
+    }
 
-        // Used by `_mm_movemask_epi8` and `_mm256_movemask_epi8`
-        "llvm.x86.sse2.pmovmskb.128" | "llvm.x86.avx2.pmovmskb" | "llvm.x86.sse2.movmsk.pd" => {
+    match intrinsic {
+        _ if intrinsic.starts_with("llvm.ctlz.v") => {
             intrinsic_args!(fx, args => (a); intrinsic);
 
-            let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx);
-            let lane_ty = fx.clif_type(lane_ty).unwrap();
-            assert!(lane_count <= 32);
-
-            let mut res = fx.bcx.ins().iconst(types::I32, 0);
-
-            for lane in (0..lane_count).rev() {
-                let a_lane = a.value_lane(fx, lane).load_scalar(fx);
-
-                // cast float to int
-                let a_lane = match lane_ty {
-                    types::F32 => fx.bcx.ins().bitcast(types::I32, a_lane),
-                    types::F64 => fx.bcx.ins().bitcast(types::I64, a_lane),
-                    _ => a_lane,
-                };
-
-                // extract sign bit of an int
-                let a_lane_sign = fx.bcx.ins().ushr_imm(a_lane, i64::from(lane_ty.bits() - 1));
-
-                // shift sign bit into result
-                let a_lane_sign = clif_intcast(fx, a_lane_sign, types::I32, false);
-                res = fx.bcx.ins().ishl_imm(res, 1);
-                res = fx.bcx.ins().bor(res, a_lane_sign);
-            }
-
-            let res = CValue::by_val(res, fx.layout_of(fx.tcx.types.i32));
-            ret.write_cvalue(fx, res);
-        }
-        "llvm.x86.sse2.cmp.ps" | "llvm.x86.sse2.cmp.pd" => {
-            let (x, y, kind) = match args {
-                [x, y, kind] => (x, y, kind),
-                _ => bug!("wrong number of args for intrinsic {intrinsic}"),
-            };
-            let x = codegen_operand(fx, x);
-            let y = codegen_operand(fx, y);
-            let kind = crate::constant::mir_operand_get_const_val(fx, kind)
-                .expect("llvm.x86.sse2.cmp.* kind not const");
-
-            let flt_cc = match kind
-                .try_to_bits(Size::from_bytes(1))
-                .unwrap_or_else(|| panic!("kind not scalar: {:?}", kind))
-            {
-                0 => FloatCC::Equal,
-                1 => FloatCC::LessThan,
-                2 => FloatCC::LessThanOrEqual,
-                7 => FloatCC::Ordered,
-                3 => FloatCC::Unordered,
-                4 => FloatCC::NotEqual,
-                5 => FloatCC::UnorderedOrGreaterThanOrEqual,
-                6 => FloatCC::UnorderedOrGreaterThan,
-                kind => unreachable!("kind {:?}", kind),
-            };
-
-            simd_pair_for_each_lane(fx, x, y, ret, &|fx, lane_ty, res_lane_ty, x_lane, y_lane| {
-                let res_lane = match lane_ty.kind() {
-                    ty::Float(_) => fx.bcx.ins().fcmp(flt_cc, x_lane, y_lane),
-                    _ => unreachable!("{:?}", lane_ty),
-                };
-                bool_to_zero_or_max_uint(fx, res_lane_ty, res_lane)
+            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
+                fx.bcx.ins().clz(lane)
             });
         }
-        "llvm.x86.sse2.psrli.d" => {
-            let (a, imm8) = match args {
-                [a, imm8] => (a, imm8),
-                _ => bug!("wrong number of args for intrinsic {intrinsic}"),
-            };
-            let a = codegen_operand(fx, a);
-            let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8)
-                .expect("llvm.x86.sse2.psrli.d imm8 not const");
 
-            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| match imm8
-                .try_to_bits(Size::from_bytes(4))
-                .unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8))
-            {
-                imm8 if imm8 < 32 => fx.bcx.ins().ushr_imm(lane, i64::from(imm8 as u8)),
-                _ => fx.bcx.ins().iconst(types::I32, 0),
-            });
-        }
-        "llvm.x86.sse2.pslli.d" => {
-            let (a, imm8) = match args {
-                [a, imm8] => (a, imm8),
-                _ => bug!("wrong number of args for intrinsic {intrinsic}"),
-            };
-            let a = codegen_operand(fx, a);
-            let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8)
-                .expect("llvm.x86.sse2.psrli.d imm8 not const");
+        _ if intrinsic.starts_with("llvm.ctpop.v") => {
+            intrinsic_args!(fx, args => (a); intrinsic);
 
-            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| match imm8
-                .try_to_bits(Size::from_bytes(4))
-                .unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8))
-            {
-                imm8 if imm8 < 32 => fx.bcx.ins().ishl_imm(lane, i64::from(imm8 as u8)),
-                _ => fx.bcx.ins().iconst(types::I32, 0),
+            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
+                fx.bcx.ins().popcnt(lane)
             });
         }
-        "llvm.x86.sse2.storeu.dq" => {
-            intrinsic_args!(fx, args => (mem_addr, a); intrinsic);
-            let mem_addr = mem_addr.load_scalar(fx);
-
-            // FIXME correctly handle the unalignment
-            let dest = CPlace::for_ptr(Pointer::new(mem_addr), a.layout());
-            dest.write_cvalue(fx, a);
-        }
-        "llvm.x86.addcarry.64" => {
-            intrinsic_args!(fx, args => (c_in, a, b); intrinsic);
-            let c_in = c_in.load_scalar(fx);
-
-            llvm_add_sub(fx, BinOp::Add, ret, c_in, a, b);
-        }
-        "llvm.x86.subborrow.64" => {
-            intrinsic_args!(fx, args => (b_in, a, b); intrinsic);
-            let b_in = b_in.load_scalar(fx);
 
-            llvm_add_sub(fx, BinOp::Sub, ret, b_in, a, b);
-        }
         _ => {
             fx.tcx
                 .sess
@@ -150,47 +52,3 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
     let ret_block = fx.get_block(dest);
     fx.bcx.ins().jump(ret_block, &[]);
 }
-
-// llvm.x86.avx2.vperm2i128
-// llvm.x86.ssse3.pshuf.b.128
-// llvm.x86.avx2.pshuf.b
-// llvm.x86.avx2.psrli.w
-// llvm.x86.sse2.psrli.w
-
-fn llvm_add_sub<'tcx>(
-    fx: &mut FunctionCx<'_, '_, 'tcx>,
-    bin_op: BinOp,
-    ret: CPlace<'tcx>,
-    cb_in: Value,
-    a: CValue<'tcx>,
-    b: CValue<'tcx>,
-) {
-    assert_eq!(
-        a.layout().ty,
-        fx.tcx.types.u64,
-        "llvm.x86.addcarry.64/llvm.x86.subborrow.64 second operand must be u64"
-    );
-    assert_eq!(
-        b.layout().ty,
-        fx.tcx.types.u64,
-        "llvm.x86.addcarry.64/llvm.x86.subborrow.64 third operand must be u64"
-    );
-
-    // c + carry -> c + first intermediate carry or borrow respectively
-    let int0 = crate::num::codegen_checked_int_binop(fx, bin_op, a, b);
-    let c = int0.value_field(fx, mir::Field::new(0));
-    let cb0 = int0.value_field(fx, mir::Field::new(1)).load_scalar(fx);
-
-    // c + carry -> c + second intermediate carry or borrow respectively
-    let cb_in_as_u64 = fx.bcx.ins().uextend(types::I64, cb_in);
-    let cb_in_as_u64 = CValue::by_val(cb_in_as_u64, fx.layout_of(fx.tcx.types.u64));
-    let int1 = crate::num::codegen_checked_int_binop(fx, bin_op, c, cb_in_as_u64);
-    let (c, cb1) = int1.load_scalar_pair(fx);
-
-    // carry0 | carry1 -> carry or borrow respectively
-    let cb_out = fx.bcx.ins().bor(cb0, cb1);
-
-    let layout = fx.layout_of(fx.tcx.mk_tup([fx.tcx.types.u8, fx.tcx.types.u64].iter()));
-    let val = CValue::by_val_pair(cb_out, c, layout);
-    ret.write_cvalue(fx, val);
-}
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs
new file mode 100644 (file)
index 0000000..b431158
--- /dev/null
@@ -0,0 +1,222 @@
+//! Emulate AArch64 LLVM intrinsics
+
+use crate::intrinsics::*;
+use crate::prelude::*;
+
+use rustc_middle::ty::subst::SubstsRef;
+
+pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>(
+    fx: &mut FunctionCx<'_, '_, 'tcx>,
+    intrinsic: &str,
+    _substs: SubstsRef<'tcx>,
+    args: &[mir::Operand<'tcx>],
+    ret: CPlace<'tcx>,
+    target: Option<BasicBlock>,
+) {
+    // llvm.aarch64.neon.sqshl.v*i*
+
+    match intrinsic {
+        "llvm.aarch64.isb" => {
+            fx.bcx.ins().fence();
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.abs.v") => {
+            intrinsic_args!(fx, args => (a); intrinsic);
+
+            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
+                fx.bcx.ins().iabs(lane)
+            });
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.cls.v") => {
+            intrinsic_args!(fx, args => (a); intrinsic);
+
+            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
+                fx.bcx.ins().cls(lane)
+            });
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.rbit.v") => {
+            intrinsic_args!(fx, args => (a); intrinsic);
+
+            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
+                fx.bcx.ins().bitrev(lane)
+            });
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.sqadd.v") => {
+            intrinsic_args!(fx, args => (x, y); intrinsic);
+
+            simd_pair_for_each_lane_typed(fx, x, y, ret, &|fx, x_lane, y_lane| {
+                crate::num::codegen_saturating_int_binop(fx, BinOp::Add, x_lane, y_lane)
+            });
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.sqsub.v") => {
+            intrinsic_args!(fx, args => (x, y); intrinsic);
+
+            simd_pair_for_each_lane_typed(fx, x, y, ret, &|fx, x_lane, y_lane| {
+                crate::num::codegen_saturating_int_binop(fx, BinOp::Sub, x_lane, y_lane)
+            });
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.smax.v") => {
+            intrinsic_args!(fx, args => (x, y); intrinsic);
+
+            simd_pair_for_each_lane(
+                fx,
+                x,
+                y,
+                ret,
+                &|fx, _lane_ty, _res_lane_ty, x_lane, y_lane| {
+                    let gt = fx.bcx.ins().icmp(IntCC::SignedGreaterThan, x_lane, y_lane);
+                    fx.bcx.ins().select(gt, x_lane, y_lane)
+                },
+            );
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.umax.v") => {
+            intrinsic_args!(fx, args => (x, y); intrinsic);
+
+            simd_pair_for_each_lane(
+                fx,
+                x,
+                y,
+                ret,
+                &|fx, _lane_ty, _res_lane_ty, x_lane, y_lane| {
+                    let gt = fx.bcx.ins().icmp(IntCC::UnsignedGreaterThan, x_lane, y_lane);
+                    fx.bcx.ins().select(gt, x_lane, y_lane)
+                },
+            );
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.smaxv.i") => {
+            intrinsic_args!(fx, args => (v); intrinsic);
+
+            simd_reduce(fx, v, None, ret, &|fx, _ty, a, b| {
+                let gt = fx.bcx.ins().icmp(IntCC::SignedGreaterThan, a, b);
+                fx.bcx.ins().select(gt, a, b)
+            });
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.umaxv.i") => {
+            intrinsic_args!(fx, args => (v); intrinsic);
+
+            simd_reduce(fx, v, None, ret, &|fx, _ty, a, b| {
+                let gt = fx.bcx.ins().icmp(IntCC::UnsignedGreaterThan, a, b);
+                fx.bcx.ins().select(gt, a, b)
+            });
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.smin.v") => {
+            intrinsic_args!(fx, args => (x, y); intrinsic);
+
+            simd_pair_for_each_lane(
+                fx,
+                x,
+                y,
+                ret,
+                &|fx, _lane_ty, _res_lane_ty, x_lane, y_lane| {
+                    let gt = fx.bcx.ins().icmp(IntCC::SignedLessThan, x_lane, y_lane);
+                    fx.bcx.ins().select(gt, x_lane, y_lane)
+                },
+            );
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.umin.v") => {
+            intrinsic_args!(fx, args => (x, y); intrinsic);
+
+            simd_pair_for_each_lane(
+                fx,
+                x,
+                y,
+                ret,
+                &|fx, _lane_ty, _res_lane_ty, x_lane, y_lane| {
+                    let gt = fx.bcx.ins().icmp(IntCC::UnsignedLessThan, x_lane, y_lane);
+                    fx.bcx.ins().select(gt, x_lane, y_lane)
+                },
+            );
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.sminv.i") => {
+            intrinsic_args!(fx, args => (v); intrinsic);
+
+            simd_reduce(fx, v, None, ret, &|fx, _ty, a, b| {
+                let gt = fx.bcx.ins().icmp(IntCC::SignedLessThan, a, b);
+                fx.bcx.ins().select(gt, a, b)
+            });
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.uminv.i") => {
+            intrinsic_args!(fx, args => (v); intrinsic);
+
+            simd_reduce(fx, v, None, ret, &|fx, _ty, a, b| {
+                let gt = fx.bcx.ins().icmp(IntCC::UnsignedLessThan, a, b);
+                fx.bcx.ins().select(gt, a, b)
+            });
+        }
+
+        /*
+        _ if intrinsic.starts_with("llvm.aarch64.neon.sshl.v")
+            || intrinsic.starts_with("llvm.aarch64.neon.sqshl.v")
+            // FIXME split this one out once saturating is implemented
+            || intrinsic.starts_with("llvm.aarch64.neon.sqshlu.v") =>
+        {
+            intrinsic_args!(fx, args => (a, b); intrinsic);
+
+            simd_pair_for_each_lane(fx, a, b, ret, &|fx, _lane_ty, _res_lane_ty, a, b| {
+                // FIXME saturate?
+                fx.bcx.ins().ishl(a, b)
+            });
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.sqshrn.v") => {
+            let (a, imm32) = match args {
+                [a, imm32] => (a, imm32),
+                _ => bug!("wrong number of args for intrinsic {intrinsic}"),
+            };
+            let a = codegen_operand(fx, a);
+            let imm32 = crate::constant::mir_operand_get_const_val(fx, imm32)
+                .expect("llvm.aarch64.neon.sqshrn.v* imm32 not const");
+
+            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| match imm32
+                .try_to_bits(Size::from_bytes(4))
+                .unwrap_or_else(|| panic!("imm32 not scalar: {:?}", imm32))
+            {
+                imm32 if imm32 < 32 => fx.bcx.ins().sshr_imm(lane, i64::from(imm32 as u8)),
+                _ => fx.bcx.ins().iconst(types::I32, 0),
+            });
+        }
+
+        _ if intrinsic.starts_with("llvm.aarch64.neon.sqshrun.v") => {
+            let (a, imm32) = match args {
+                [a, imm32] => (a, imm32),
+                _ => bug!("wrong number of args for intrinsic {intrinsic}"),
+            };
+            let a = codegen_operand(fx, a);
+            let imm32 = crate::constant::mir_operand_get_const_val(fx, imm32)
+                .expect("llvm.aarch64.neon.sqshrn.v* imm32 not const");
+
+            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| match imm32
+                .try_to_bits(Size::from_bytes(4))
+                .unwrap_or_else(|| panic!("imm32 not scalar: {:?}", imm32))
+            {
+                imm32 if imm32 < 32 => fx.bcx.ins().ushr_imm(lane, i64::from(imm32 as u8)),
+                _ => fx.bcx.ins().iconst(types::I32, 0),
+            });
+        }
+        */
+        _ => {
+            fx.tcx.sess.warn(&format!(
+                "unsupported AArch64 llvm intrinsic {}; replacing with trap",
+                intrinsic
+            ));
+            crate::trap::trap_unimplemented(fx, intrinsic);
+            return;
+        }
+    }
+
+    let dest = target.expect("all llvm intrinsics used by stdlib should return");
+    let ret_block = fx.get_block(dest);
+    fx.bcx.ins().jump(ret_block, &[]);
+}
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
new file mode 100644 (file)
index 0000000..7bc161f
--- /dev/null
@@ -0,0 +1,197 @@
+//! Emulate x86 LLVM intrinsics
+
+use crate::intrinsics::*;
+use crate::prelude::*;
+
+use rustc_middle::ty::subst::SubstsRef;
+
+pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
+    fx: &mut FunctionCx<'_, '_, 'tcx>,
+    intrinsic: &str,
+    _substs: SubstsRef<'tcx>,
+    args: &[mir::Operand<'tcx>],
+    ret: CPlace<'tcx>,
+    target: Option<BasicBlock>,
+) {
+    match intrinsic {
+        "llvm.x86.sse2.pause" | "llvm.aarch64.isb" => {
+            // Spin loop hint
+        }
+
+        // Used by `_mm_movemask_epi8` and `_mm256_movemask_epi8`
+        "llvm.x86.sse2.pmovmskb.128" | "llvm.x86.avx2.pmovmskb" | "llvm.x86.sse2.movmsk.pd" => {
+            intrinsic_args!(fx, args => (a); intrinsic);
+
+            let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx);
+            let lane_ty = fx.clif_type(lane_ty).unwrap();
+            assert!(lane_count <= 32);
+
+            let mut res = fx.bcx.ins().iconst(types::I32, 0);
+
+            for lane in (0..lane_count).rev() {
+                let a_lane = a.value_lane(fx, lane).load_scalar(fx);
+
+                // cast float to int
+                let a_lane = match lane_ty {
+                    types::F32 => fx.bcx.ins().bitcast(types::I32, a_lane),
+                    types::F64 => fx.bcx.ins().bitcast(types::I64, a_lane),
+                    _ => a_lane,
+                };
+
+                // extract sign bit of an int
+                let a_lane_sign = fx.bcx.ins().ushr_imm(a_lane, i64::from(lane_ty.bits() - 1));
+
+                // shift sign bit into result
+                let a_lane_sign = clif_intcast(fx, a_lane_sign, types::I32, false);
+                res = fx.bcx.ins().ishl_imm(res, 1);
+                res = fx.bcx.ins().bor(res, a_lane_sign);
+            }
+
+            let res = CValue::by_val(res, fx.layout_of(fx.tcx.types.i32));
+            ret.write_cvalue(fx, res);
+        }
+        "llvm.x86.sse2.cmp.ps" | "llvm.x86.sse2.cmp.pd" => {
+            let (x, y, kind) = match args {
+                [x, y, kind] => (x, y, kind),
+                _ => bug!("wrong number of args for intrinsic {intrinsic}"),
+            };
+            let x = codegen_operand(fx, x);
+            let y = codegen_operand(fx, y);
+            let kind = crate::constant::mir_operand_get_const_val(fx, kind)
+                .expect("llvm.x86.sse2.cmp.* kind not const");
+
+            let flt_cc = match kind
+                .try_to_bits(Size::from_bytes(1))
+                .unwrap_or_else(|| panic!("kind not scalar: {:?}", kind))
+            {
+                0 => FloatCC::Equal,
+                1 => FloatCC::LessThan,
+                2 => FloatCC::LessThanOrEqual,
+                7 => FloatCC::Ordered,
+                3 => FloatCC::Unordered,
+                4 => FloatCC::NotEqual,
+                5 => FloatCC::UnorderedOrGreaterThanOrEqual,
+                6 => FloatCC::UnorderedOrGreaterThan,
+                kind => unreachable!("kind {:?}", kind),
+            };
+
+            simd_pair_for_each_lane(fx, x, y, ret, &|fx, lane_ty, res_lane_ty, x_lane, y_lane| {
+                let res_lane = match lane_ty.kind() {
+                    ty::Float(_) => fx.bcx.ins().fcmp(flt_cc, x_lane, y_lane),
+                    _ => unreachable!("{:?}", lane_ty),
+                };
+                bool_to_zero_or_max_uint(fx, res_lane_ty, res_lane)
+            });
+        }
+        "llvm.x86.sse2.psrli.d" => {
+            let (a, imm8) = match args {
+                [a, imm8] => (a, imm8),
+                _ => bug!("wrong number of args for intrinsic {intrinsic}"),
+            };
+            let a = codegen_operand(fx, a);
+            let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8)
+                .expect("llvm.x86.sse2.psrli.d imm8 not const");
+
+            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| match imm8
+                .try_to_bits(Size::from_bytes(4))
+                .unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8))
+            {
+                imm8 if imm8 < 32 => fx.bcx.ins().ushr_imm(lane, i64::from(imm8 as u8)),
+                _ => fx.bcx.ins().iconst(types::I32, 0),
+            });
+        }
+        "llvm.x86.sse2.pslli.d" => {
+            let (a, imm8) = match args {
+                [a, imm8] => (a, imm8),
+                _ => bug!("wrong number of args for intrinsic {intrinsic}"),
+            };
+            let a = codegen_operand(fx, a);
+            let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8)
+                .expect("llvm.x86.sse2.psrli.d imm8 not const");
+
+            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| match imm8
+                .try_to_bits(Size::from_bytes(4))
+                .unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8))
+            {
+                imm8 if imm8 < 32 => fx.bcx.ins().ishl_imm(lane, i64::from(imm8 as u8)),
+                _ => fx.bcx.ins().iconst(types::I32, 0),
+            });
+        }
+        "llvm.x86.sse2.storeu.dq" => {
+            intrinsic_args!(fx, args => (mem_addr, a); intrinsic);
+            let mem_addr = mem_addr.load_scalar(fx);
+
+            // FIXME correctly handle the unalignment
+            let dest = CPlace::for_ptr(Pointer::new(mem_addr), a.layout());
+            dest.write_cvalue(fx, a);
+        }
+        "llvm.x86.addcarry.64" => {
+            intrinsic_args!(fx, args => (c_in, a, b); intrinsic);
+            let c_in = c_in.load_scalar(fx);
+
+            llvm_add_sub(fx, BinOp::Add, ret, c_in, a, b);
+        }
+        "llvm.x86.subborrow.64" => {
+            intrinsic_args!(fx, args => (b_in, a, b); intrinsic);
+            let b_in = b_in.load_scalar(fx);
+
+            llvm_add_sub(fx, BinOp::Sub, ret, b_in, a, b);
+        }
+        _ => {
+            fx.tcx.sess.warn(&format!(
+                "unsupported x86 llvm intrinsic {}; replacing with trap",
+                intrinsic
+            ));
+            crate::trap::trap_unimplemented(fx, intrinsic);
+            return;
+        }
+    }
+
+    let dest = target.expect("all llvm intrinsics used by stdlib should return");
+    let ret_block = fx.get_block(dest);
+    fx.bcx.ins().jump(ret_block, &[]);
+}
+
+// llvm.x86.avx2.vperm2i128
+// llvm.x86.ssse3.pshuf.b.128
+// llvm.x86.avx2.pshuf.b
+// llvm.x86.avx2.psrli.w
+// llvm.x86.sse2.psrli.w
+
+fn llvm_add_sub<'tcx>(
+    fx: &mut FunctionCx<'_, '_, 'tcx>,
+    bin_op: BinOp,
+    ret: CPlace<'tcx>,
+    cb_in: Value,
+    a: CValue<'tcx>,
+    b: CValue<'tcx>,
+) {
+    assert_eq!(
+        a.layout().ty,
+        fx.tcx.types.u64,
+        "llvm.x86.addcarry.64/llvm.x86.subborrow.64 second operand must be u64"
+    );
+    assert_eq!(
+        b.layout().ty,
+        fx.tcx.types.u64,
+        "llvm.x86.addcarry.64/llvm.x86.subborrow.64 third operand must be u64"
+    );
+
+    // c + carry -> c + first intermediate carry or borrow respectively
+    let int0 = crate::num::codegen_checked_int_binop(fx, bin_op, a, b);
+    let c = int0.value_field(fx, mir::Field::new(0));
+    let cb0 = int0.value_field(fx, mir::Field::new(1)).load_scalar(fx);
+
+    // c + carry -> c + second intermediate carry or borrow respectively
+    let cb_in_as_u64 = fx.bcx.ins().uextend(types::I64, cb_in);
+    let cb_in_as_u64 = CValue::by_val(cb_in_as_u64, fx.layout_of(fx.tcx.types.u64));
+    let int1 = crate::num::codegen_checked_int_binop(fx, bin_op, c, cb_in_as_u64);
+    let (c, cb1) = int1.load_scalar_pair(fx);
+
+    // carry0 | carry1 -> carry or borrow respectively
+    let cb_out = fx.bcx.ins().bor(cb0, cb1);
+
+    let layout = fx.layout_of(fx.tcx.mk_tup([fx.tcx.types.u8, fx.tcx.types.u64].iter()));
+    let val = CValue::by_val_pair(cb_out, c, layout);
+    ret.write_cvalue(fx, val);
+}
index 0302b843aa226345328a278674026baa33fda632..7a380acf798572a7606130959a7517cfecb2462b 100644 (file)
@@ -14,6 +14,8 @@ macro_rules! intrinsic_args {
 
 mod cpuid;
 mod llvm;
+mod llvm_aarch64;
+mod llvm_x86;
 mod simd;
 
 pub(crate) use cpuid::codegen_cpuid_call;
@@ -195,8 +197,7 @@ fn bool_to_zero_or_max_uint<'tcx>(
         ty => ty,
     };
 
-    let val = fx.bcx.ins().bint(int_ty, val);
-    let mut res = fx.bcx.ins().ineg(val);
+    let mut res = fx.bcx.ins().bmask(int_ty, val);
 
     if ty.is_float() {
         res = fx.bcx.ins().bitcast(ty, res);
@@ -632,85 +633,15 @@ fn codegen_regular_intrinsic_call<'tcx>(
             ret.write_cvalue(fx, res);
         }
         sym::bswap => {
-            // FIXME(CraneStation/cranelift#794) add bswap instruction to cranelift
-            fn swap(bcx: &mut FunctionBuilder<'_>, v: Value) -> Value {
-                match bcx.func.dfg.value_type(v) {
-                    types::I8 => v,
-
-                    // https://code.woboq.org/gcc/include/bits/byteswap.h.html
-                    types::I16 => {
-                        let tmp1 = bcx.ins().ishl_imm(v, 8);
-                        let n1 = bcx.ins().band_imm(tmp1, 0xFF00);
-
-                        let tmp2 = bcx.ins().ushr_imm(v, 8);
-                        let n2 = bcx.ins().band_imm(tmp2, 0x00FF);
-
-                        bcx.ins().bor(n1, n2)
-                    }
-                    types::I32 => {
-                        let tmp1 = bcx.ins().ishl_imm(v, 24);
-                        let n1 = bcx.ins().band_imm(tmp1, 0xFF00_0000);
-
-                        let tmp2 = bcx.ins().ishl_imm(v, 8);
-                        let n2 = bcx.ins().band_imm(tmp2, 0x00FF_0000);
-
-                        let tmp3 = bcx.ins().ushr_imm(v, 8);
-                        let n3 = bcx.ins().band_imm(tmp3, 0x0000_FF00);
-
-                        let tmp4 = bcx.ins().ushr_imm(v, 24);
-                        let n4 = bcx.ins().band_imm(tmp4, 0x0000_00FF);
-
-                        let or_tmp1 = bcx.ins().bor(n1, n2);
-                        let or_tmp2 = bcx.ins().bor(n3, n4);
-                        bcx.ins().bor(or_tmp1, or_tmp2)
-                    }
-                    types::I64 => {
-                        let tmp1 = bcx.ins().ishl_imm(v, 56);
-                        let n1 = bcx.ins().band_imm(tmp1, 0xFF00_0000_0000_0000u64 as i64);
-
-                        let tmp2 = bcx.ins().ishl_imm(v, 40);
-                        let n2 = bcx.ins().band_imm(tmp2, 0x00FF_0000_0000_0000u64 as i64);
-
-                        let tmp3 = bcx.ins().ishl_imm(v, 24);
-                        let n3 = bcx.ins().band_imm(tmp3, 0x0000_FF00_0000_0000u64 as i64);
-
-                        let tmp4 = bcx.ins().ishl_imm(v, 8);
-                        let n4 = bcx.ins().band_imm(tmp4, 0x0000_00FF_0000_0000u64 as i64);
-
-                        let tmp5 = bcx.ins().ushr_imm(v, 8);
-                        let n5 = bcx.ins().band_imm(tmp5, 0x0000_0000_FF00_0000u64 as i64);
-
-                        let tmp6 = bcx.ins().ushr_imm(v, 24);
-                        let n6 = bcx.ins().band_imm(tmp6, 0x0000_0000_00FF_0000u64 as i64);
-
-                        let tmp7 = bcx.ins().ushr_imm(v, 40);
-                        let n7 = bcx.ins().band_imm(tmp7, 0x0000_0000_0000_FF00u64 as i64);
-
-                        let tmp8 = bcx.ins().ushr_imm(v, 56);
-                        let n8 = bcx.ins().band_imm(tmp8, 0x0000_0000_0000_00FFu64 as i64);
-
-                        let or_tmp1 = bcx.ins().bor(n1, n2);
-                        let or_tmp2 = bcx.ins().bor(n3, n4);
-                        let or_tmp3 = bcx.ins().bor(n5, n6);
-                        let or_tmp4 = bcx.ins().bor(n7, n8);
-
-                        let or_tmp5 = bcx.ins().bor(or_tmp1, or_tmp2);
-                        let or_tmp6 = bcx.ins().bor(or_tmp3, or_tmp4);
-                        bcx.ins().bor(or_tmp5, or_tmp6)
-                    }
-                    types::I128 => {
-                        let (lo, hi) = bcx.ins().isplit(v);
-                        let lo = swap(bcx, lo);
-                        let hi = swap(bcx, hi);
-                        bcx.ins().iconcat(hi, lo)
-                    }
-                    ty => unreachable!("bswap {}", ty),
-                }
-            }
             intrinsic_args!(fx, args => (arg); intrinsic);
             let val = arg.load_scalar(fx);
 
-            let res = CValue::by_val(swap(&mut fx.bcx, val), arg.layout());
+            let res = if fx.bcx.func.dfg.value_type(val) == types::I8 {
+                val
+            } else {
+                fx.bcx.ins().bswap(val)
+            };
+            let res = CValue::by_val(res, arg.layout());
             ret.write_cvalue(fx, res);
         }
         sym::assert_inhabited | sym::assert_zero_valid | sym::assert_uninit_valid => {
@@ -936,8 +867,7 @@ fn swap(bcx: &mut FunctionBuilder<'_>, v: Value) -> Value {
             let old = fx.bcx.ins().atomic_cas(MemFlags::trusted(), ptr, test_old, new);
             let is_eq = fx.bcx.ins().icmp(IntCC::Equal, old, test_old);
 
-            let ret_val =
-                CValue::by_val_pair(old, fx.bcx.ins().bint(types::I8, is_eq), ret.layout());
+            let ret_val = CValue::by_val_pair(old, is_eq, ret.layout());
             ret.write_cvalue(fx, ret_val)
         }
 
@@ -1259,8 +1189,7 @@ fn swap(bcx: &mut FunctionBuilder<'_>, v: Value) -> Value {
                 flags.set_notrap();
                 let lhs_val = fx.bcx.ins().load(clty, flags, lhs_ref, 0);
                 let rhs_val = fx.bcx.ins().load(clty, flags, rhs_ref, 0);
-                let eq = fx.bcx.ins().icmp(IntCC::Equal, lhs_val, rhs_val);
-                fx.bcx.ins().bint(types::I8, eq)
+                fx.bcx.ins().icmp(IntCC::Equal, lhs_val, rhs_val)
             } else {
                 // Just call `memcmp` (like slices do in core) when the
                 // size is too large or it's not a power-of-two.
@@ -1270,8 +1199,7 @@ fn swap(bcx: &mut FunctionBuilder<'_>, v: Value) -> Value {
                 let returns = vec![AbiParam::new(types::I32)];
                 let args = &[lhs_ref, rhs_ref, bytes_val];
                 let cmp = fx.lib_call("memcmp", params, returns, args)[0];
-                let eq = fx.bcx.ins().icmp_imm(IntCC::Equal, cmp, 0);
-                fx.bcx.ins().bint(types::I8, eq)
+                fx.bcx.ins().icmp_imm(IntCC::Equal, cmp, 0)
             };
             ret.write_cvalue(fx, CValue::by_val(is_eq_value, ret.layout()));
         }
index 51fce8c854bdb5307149680f288fa590ed8a8b53..14f5e9187399fac76f2a64d0147f2f647a904929 100644 (file)
@@ -112,10 +112,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
                     _ => unreachable!(),
                 };
 
-                let ty = fx.clif_type(res_lane_ty).unwrap();
-
-                let res_lane = fx.bcx.ins().bint(ty, res_lane);
-                fx.bcx.ins().ineg(res_lane)
+                bool_to_zero_or_max_uint(fx, res_lane_ty, res_lane)
             });
         }
 
@@ -716,7 +713,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
 
             let res_type =
                 Type::int_with_byte_size(u16::try_from(expected_bytes).unwrap()).unwrap();
-            let mut res = fx.bcx.ins().iconst(res_type, 0);
+            let mut res = type_zero_value(&mut fx.bcx, res_type);
 
             let lanes = match fx.tcx.sess.target.endian {
                 Endian::Big => Box::new(0..lane_count) as Box<dyn Iterator<Item = u64>>,
index f7434633ea442b40fa30f4a85370135e8c134017..c10054e7f0d2c971711364aafdfe563558e3fd5d 100644 (file)
@@ -65,7 +65,7 @@ fn create_entry_fn(
             returns: vec![AbiParam::new(m.target_config().pointer_type() /*isize*/)],
             call_conv: crate::conv_to_call_conv(
                 tcx.sess.target.options.entry_abi,
-                CallConv::triple_default(m.isa().triple()),
+                m.target_config().default_call_conv,
             ),
         };
 
@@ -75,7 +75,7 @@ fn create_entry_fn(
         let instance = Instance::mono(tcx, rust_main_def_id).polymorphize(tcx);
 
         let main_name = tcx.symbol_name(instance).name;
-        let main_sig = get_function_sig(tcx, m.isa().triple(), instance);
+        let main_sig = get_function_sig(tcx, m.target_config().default_call_conv, instance);
         let main_func_id = m.declare_function(main_name, Linkage::Import, &main_sig).unwrap();
 
         let mut ctx = Context::new();
@@ -119,7 +119,7 @@ fn create_entry_fn(
                 .polymorphize(tcx);
 
                 let report_name = tcx.symbol_name(report).name;
-                let report_sig = get_function_sig(tcx, m.isa().triple(), report);
+                let report_sig = get_function_sig(tcx, m.target_config().default_call_conv, report);
                 let report_func_id =
                     m.declare_function(report_name, Linkage::Import, &report_sig).unwrap();
                 let report_func_ref = m.declare_func_in_func(report_func_id, &mut bcx.func);
index ecbab408ded972889b6cbca8840daee8c2e837f4..afacbec644582195440bcb8e3e9c58d6d99b3c74 100644 (file)
@@ -49,7 +49,6 @@ fn codegen_compare_bin_op<'tcx>(
 ) -> CValue<'tcx> {
     let intcc = crate::num::bin_op_to_intcc(bin_op, signed).unwrap();
     let val = fx.bcx.ins().icmp(intcc, lhs, rhs);
-    let val = fx.bcx.ins().bint(types::I8, val);
     CValue::by_val(val, fx.layout_of(fx.tcx.types.bool))
 }
 
@@ -290,8 +289,6 @@ pub(crate) fn codegen_checked_int_binop<'tcx>(
         _ => bug!("binop {:?} on checked int/uint lhs: {:?} rhs: {:?}", bin_op, in_lhs, in_rhs),
     };
 
-    let has_overflow = fx.bcx.ins().bint(types::I8, has_overflow);
-
     let out_layout = fx.layout_of(fx.tcx.mk_tup([in_lhs.layout().ty, fx.tcx.types.bool].iter()));
     CValue::by_val_pair(res, has_overflow, out_layout)
 }
@@ -368,7 +365,6 @@ pub(crate) fn codegen_float_binop<'tcx>(
                 _ => unreachable!(),
             };
             let val = fx.bcx.ins().fcmp(fltcc, lhs, rhs);
-            let val = fx.bcx.ins().bint(types::I8, val);
             return CValue::by_val(val, fx.layout_of(fx.tcx.types.bool));
         }
         _ => unreachable!("{:?}({:?}, {:?})", bin_op, in_lhs, in_rhs),
@@ -440,7 +436,7 @@ pub(crate) fn codegen_ptr_binop<'tcx>(
             _ => panic!("bin_op {:?} on ptr", bin_op),
         };
 
-        CValue::by_val(fx.bcx.ins().bint(types::I8, res), fx.layout_of(fx.tcx.types.bool))
+        CValue::by_val(res, fx.layout_of(fx.tcx.types.bool))
     }
 }
 
index d637b4d89293cea0a0a855ebb97378b111c3789b..7f45bbd8f28136a43b8271ba5f3e2755d19d522d 100644 (file)
@@ -3,19 +3,6 @@
 use cranelift_codegen::ir::{condcodes::IntCC, InstructionData, Opcode, Value, ValueDef};
 use cranelift_frontend::FunctionBuilder;
 
-/// If the given value was produced by a `bint` instruction, return it's input, otherwise return the
-/// given value.
-pub(crate) fn maybe_unwrap_bint(bcx: &mut FunctionBuilder<'_>, arg: Value) -> Value {
-    if let ValueDef::Result(arg_inst, 0) = bcx.func.dfg.value_def(arg) {
-        match bcx.func.dfg[arg_inst] {
-            InstructionData::Unary { opcode: Opcode::Bint, arg } => arg,
-            _ => arg,
-        }
-    } else {
-        arg
-    }
-}
-
 /// If the given value was produced by the lowering of `Rvalue::Not` return the input and true,
 /// otherwise return the given value and false.
 pub(crate) fn maybe_unwrap_bool_not(bcx: &mut FunctionBuilder<'_>, arg: Value) -> (Value, bool) {
@@ -48,13 +35,6 @@ pub(crate) fn maybe_known_branch_taken(
     };
 
     match bcx.func.dfg[arg_inst] {
-        InstructionData::UnaryBool { opcode: Opcode::Bconst, imm } => {
-            if test_zero {
-                Some(!imm)
-            } else {
-                Some(imm)
-            }
-        }
         InstructionData::UnaryImm { opcode: Opcode::Iconst, imm } => {
             if test_zero {
                 Some(imm.bits() == 0)
index 34746ff6b6645c11bdda409d0af1f627908e65a0..fe8af21ac6de567cff94a34ec13e625f8876fe4a 100644 (file)
@@ -392,7 +392,7 @@ pub(crate) fn new_var(
         local: Local,
         layout: TyAndLayout<'tcx>,
     ) -> CPlace<'tcx> {
-        let var = Variable::with_u32(fx.next_ssa_var);
+        let var = Variable::from_u32(fx.next_ssa_var);
         fx.next_ssa_var += 1;
         fx.bcx.declare_var(var, fx.clif_type(layout.ty).unwrap());
         CPlace { inner: CPlaceInner::Var(local, var), layout }
@@ -403,9 +403,9 @@ pub(crate) fn new_var_pair(
         local: Local,
         layout: TyAndLayout<'tcx>,
     ) -> CPlace<'tcx> {
-        let var1 = Variable::with_u32(fx.next_ssa_var);
+        let var1 = Variable::from_u32(fx.next_ssa_var);
         fx.next_ssa_var += 1;
-        let var2 = Variable::with_u32(fx.next_ssa_var);
+        let var2 = Variable::from_u32(fx.next_ssa_var);
         fx.next_ssa_var += 1;
 
         let (ty1, ty2) = fx.clif_pair_type(layout.ty).unwrap();
@@ -515,9 +515,7 @@ fn transmute_value<'tcx>(
                 | (types::F32, types::I32)
                 | (types::I64, types::F64)
                 | (types::F64, types::I64) => fx.bcx.ins().bitcast(dst_ty, data),
-                _ if src_ty.is_vector() && dst_ty.is_vector() => {
-                    fx.bcx.ins().raw_bitcast(dst_ty, data)
-                }
+                _ if src_ty.is_vector() && dst_ty.is_vector() => fx.bcx.ins().bitcast(dst_ty, data),
                 _ if src_ty.is_vector() || dst_ty.is_vector() => {
                     // FIXME do something more efficient for transmutes between vectors and integers.
                     let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData {
@@ -590,7 +588,10 @@ fn transmute_value<'tcx>(
                 return;
             }
             CPlaceInner::VarPair(_local, var1, var2) => {
-                let (data1, data2) = CValue(from.0, dst_layout).load_scalar_pair(fx);
+                let (ptr, meta) = from.force_stack(fx);
+                assert!(meta.is_none());
+                let (data1, data2) =
+                    CValue(CValueInner::ByRef(ptr, None), dst_layout).load_scalar_pair(fx);
                 let (dst_ty1, dst_ty2) = fx.clif_pair_type(self.layout().ty).unwrap();
                 transmute_value(fx, var1, data1, dst_ty1);
                 transmute_value(fx, var2, data2, dst_ty2);
index 3d929a1d50ce2435307a7834c1fe04c1c73b94bd..13e7784539d5a9b9cdb3c81dd7f548afcb0c418b 100755 (executable)
@@ -1,2 +1,2 @@
 #!/usr/bin/env bash
-exec ./y.rs test
+exec ./y.rs test "$@"
index f177b91c2c4876a4ac7b62dd653a3e4ea0857453..02e1e21ade1de98f4d72256adbe70755a3997a55 100755 (executable)
@@ -3,7 +3,7 @@
 # This block is ignored by rustc
 set -e
 echo "[BUILD] y.rs" 1>&2
-rustc $0 -o ${0/.rs/.bin} -Cdebuginfo=1
+rustc $0 -o ${0/.rs/.bin} -Cdebuginfo=1 --edition 2021
 exec ${0/.rs/.bin} $@
 */
 
index 782f6856654a6f974f8043c72e6a4e543a8b9410..effb2de4827518c08360bed61995f5ffe3c86a58 100644 (file)
@@ -1119,18 +1119,18 @@ fn set_personality_fn(&mut self, _personality: RValue<'gcc>) {
         // TODO(antoyo)
     }
 
-    fn cleanup_landing_pad(&mut self, _ty: Type<'gcc>, _pers_fn: RValue<'gcc>) -> RValue<'gcc> {
-        let field1 = self.context.new_field(None, self.u8_type.make_pointer(), "landing_pad_field_1");
-        let field2 = self.context.new_field(None, self.i32_type, "landing_pad_field_1");
-        let struct_type = self.context.new_struct_type(None, "landing_pad", &[field1, field2]);
-        self.current_func().new_local(None, struct_type.as_type(), "landing_pad")
-            .to_rvalue()
+    fn cleanup_landing_pad(&mut self, _pers_fn: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
+        (
+            self.current_func().new_local(None, self.u8_type.make_pointer(), "landing_pad0")
+                .to_rvalue(),
+            self.current_func().new_local(None, self.i32_type, "landing_pad1").to_rvalue(),
+        )
         // TODO(antoyo): Properly implement unwinding.
         // the above is just to make the compilation work as it seems
         // rustc_codegen_ssa now calls the unwinding builder methods even on panic=abort.
     }
 
-    fn resume(&mut self, _exn: RValue<'gcc>) {
+    fn resume(&mut self, _exn0: RValue<'gcc>, _exn1: RValue<'gcc>) {
         // TODO(bjorn3): Properly implement unwinding.
         self.unreachable();
     }
index 111bfeb1322038961f693f4d924b9ff18754d600..ea8ab76114604208ed7a9b619dc257e4e9e9c4ff 100644 (file)
@@ -8,13 +8,11 @@
 use rustc_middle::ty::{self, Instance, Ty};
 use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::mir::interpret::{self, ConstAllocation, ErrorHandled, Scalar as InterpScalar, read_target_uint};
-use rustc_span::Span;
 use rustc_span::def_id::DefId;
 use rustc_target::abi::{self, Align, HasDataLayout, Primitive, Size, WrappingRange};
 
 use crate::base;
 use crate::context::CodegenCx;
-use crate::errors::LinkageConstOrMutType;
 use crate::type_of::LayoutGccExt;
 
 impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
@@ -239,12 +237,12 @@ pub fn get_static(&self, def_id: DefId) -> LValue<'gcc> {
                     }
 
                     Node::ForeignItem(&hir::ForeignItem {
-                        span,
+                        span: _,
                         kind: hir::ForeignItemKind::Static(..),
                         ..
                     }) => {
                         let fn_attrs = self.tcx.codegen_fn_attrs(def_id);
-                        check_and_apply_linkage(&self, &fn_attrs, ty, sym, span)
+                        check_and_apply_linkage(&self, &fn_attrs, ty, sym)
                     }
 
                     item => bug!("get_static: expected static, found {:?}", item),
@@ -257,8 +255,7 @@ pub fn get_static(&self, def_id: DefId) -> LValue<'gcc> {
                 //debug!("get_static: sym={} item_attr={:?}", sym, self.tcx.item_attrs(def_id));
 
                 let attrs = self.tcx.codegen_fn_attrs(def_id);
-                let span = self.tcx.def_span(def_id);
-                let global = check_and_apply_linkage(&self, &attrs, ty, sym, span);
+                let global = check_and_apply_linkage(&self, &attrs, ty, sym);
 
                 let needs_dll_storage_attr = false; // TODO(antoyo)
 
@@ -355,24 +352,12 @@ pub fn codegen_static_initializer<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, def_id
     Ok((const_alloc_to_gcc(cx, alloc), alloc))
 }
 
-fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &CodegenFnAttrs, ty: Ty<'tcx>, sym: &str, span: Span) -> LValue<'gcc> {
+fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &CodegenFnAttrs, ty: Ty<'tcx>, sym: &str) -> LValue<'gcc> {
     let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL);
     let llty = cx.layout_of(ty).gcc_type(cx, true);
-    if let Some(linkage) = attrs.linkage {
-        // If this is a static with a linkage specified, then we need to handle
-        // it a little specially. The typesystem prevents things like &T and
-        // extern "C" fn() from being non-null, so we can't just declare a
-        // static and call it a day. Some linkages (like weak) will make it such
-        // that the static actually has a null value.
-        let llty2 =
-            if let ty::RawPtr(ref mt) = ty.kind() {
-                cx.layout_of(mt.ty).gcc_type(cx, true)
-            }
-            else {
-                cx.sess().emit_fatal(LinkageConstOrMutType { span: span })
-            };
+    if let Some(linkage) = attrs.import_linkage {
         // Declare a symbol `foo` with the desired linkage.
-        let global1 = cx.declare_global_with_linkage(&sym, llty2, base::global_linkage_to_gcc(linkage));
+        let global1 = cx.declare_global_with_linkage(&sym, cx.type_i8(), base::global_linkage_to_gcc(linkage));
 
         // Declare an internal global `extern_with_linkage_foo` which
         // is initialized with the address of `foo`.  If `foo` is
index 89fed7be1315614e91331d4b2c05fb58ff320989..d0ba7e2479111fed3ee8661f86984a3fbfd18cf2 100644 (file)
@@ -211,13 +211,6 @@ pub(crate) struct InvalidMonomorphizationUnsupportedOperation<'a> {
     pub in_elem: Ty<'a>,
 }
 
-#[derive(Diagnostic)]
-#[diag(codegen_gcc_linkage_const_or_mut_type)]
-pub(crate) struct LinkageConstOrMutType {
-    #[primary_span]
-    pub span: Span,
-}
-
 #[derive(Diagnostic)]
 #[diag(codegen_gcc_lto_not_supported)]
 pub(crate) struct LTONotSupported;
index bdf7318ce48c9505887b2287c0201bf66742bc54..89a415cdb36cd2d8d98c0b1f132541e018364f39 100644 (file)
@@ -300,4 +300,8 @@ fn typeid_metadata(&self, _typeid: String) -> RValue<'gcc> {
         // Unsupported.
         self.context.new_rvalue_from_int(self.int_type, 0)
     }
+
+    fn set_kcfi_type_metadata(&self, _function: RValue<'gcc>, _kcfi_typeid: u32) {
+        // Unsupported.
+    }
 }
index fed56cdd43821e6cb2dd76a0918e7dcc5c55bf32..668d929270530023e08c94352b9d7522b3871e75 100644 (file)
@@ -88,7 +88,8 @@ pub(crate) unsafe fn codegen(
             callee,
             args.as_ptr(),
             args.len() as c_uint,
-            None,
+            [].as_ptr(),
+            0 as c_uint,
         );
         llvm::LLVMSetTailCall(ret, True);
         if output.is_some() {
@@ -132,8 +133,15 @@ pub(crate) unsafe fn codegen(
         .enumerate()
         .map(|(i, _)| llvm::LLVMGetParam(llfn, i as c_uint))
         .collect::<Vec<_>>();
-    let ret =
-        llvm::LLVMRustBuildCall(llbuilder, ty, callee, args.as_ptr(), args.len() as c_uint, None);
+    let ret = llvm::LLVMRustBuildCall(
+        llbuilder,
+        ty,
+        callee,
+        args.as_ptr(),
+        args.len() as c_uint,
+        [].as_ptr(),
+        0 as c_uint,
+    );
     llvm::LLVMSetTailCall(ret, True);
     llvm::LLVMBuildRetVoid(llbuilder);
     llvm::LLVMDisposeBuilder(llbuilder);
index 0aee1a1439b9bcd2867bb2da9681092891c257d5..36aba5bb740bd6120030c0cbf0e5d6654fa0afc8 100644 (file)
@@ -15,8 +15,8 @@
 use crate::llvm::archive_ro::{ArchiveRO, Child};
 use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
 use rustc_codegen_ssa::back::archive::{
-    get_native_object_symbols, try_extract_macho_fat_archive, ArArchiveBuilder,
-    ArchiveBuildFailure, ArchiveBuilder, ArchiveBuilderBuilder, UnknownArchiveKind,
+    get_native_object_symbols, ArArchiveBuilder, ArchiveBuildFailure, ArchiveBuilder,
+    ArchiveBuilderBuilder, UnknownArchiveKind,
 };
 
 use rustc_session::cstore::DllImport;
@@ -66,13 +66,7 @@ fn add_archive(
         archive: &Path,
         skip: Box<dyn FnMut(&str) -> bool + 'static>,
     ) -> io::Result<()> {
-        let mut archive = archive.to_path_buf();
-        if self.sess.target.llvm_target.contains("-apple-macosx") {
-            if let Some(new_archive) = try_extract_macho_fat_archive(&self.sess, &archive)? {
-                archive = new_archive
-            }
-        }
-        let archive_ro = match ArchiveRO::open(&archive) {
+        let archive_ro = match ArchiveRO::open(archive) {
             Ok(ar) => ar,
             Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
         };
@@ -80,7 +74,7 @@ fn add_archive(
             return Ok(());
         }
         self.additions.push(Addition::Archive {
-            path: archive,
+            path: archive.to_path_buf(),
             archive: archive_ro,
             skip: Box::new(skip),
         });
index 3fa21355b7f4c9b46349591904aac80717541976..6c0faf37a63ce453b906185924ccb6d420dffb09 100644 (file)
@@ -133,6 +133,10 @@ fn prepare_lto(
         }
     }
 
+    // __llvm_profile_counter_bias is pulled in at link time by an undefined reference to
+    // __llvm_profile_runtime, therefore we won't know until link time if this symbol
+    // should have default visibility.
+    symbols_below_threshold.push(CString::new("__llvm_profile_counter_bias").unwrap());
     Ok((symbols_below_threshold, upstream_modules))
 }
 
@@ -206,7 +210,7 @@ pub(crate) fn run_thin(
 }
 
 pub(crate) fn prepare_thin(module: ModuleCodegen<ModuleLlvm>) -> (String, ThinBuffer) {
-    let name = module.name.clone();
+    let name = module.name;
     let buffer = ThinBuffer::new(module.module_llvm.llmod(), true);
     (name, buffer)
 }
@@ -421,7 +425,7 @@ fn thin_lto(
         info!("going for that thin, thin LTO");
 
         let green_modules: FxHashMap<_, _> =
-            cached_modules.iter().map(|&(_, ref wp)| (wp.cgu_name.clone(), wp.clone())).collect();
+            cached_modules.iter().map(|(_, wp)| (wp.cgu_name.clone(), wp.clone())).collect();
 
         let full_scope_len = modules.len() + serialized_modules.len() + cached_modules.len();
         let mut thin_buffers = Vec::with_capacity(modules.len());
index 77dd15ef4d8078e8c37162776318f6068b272687..853a8b82853f43400a223804c629bd7b0b9c0e75 100644 (file)
@@ -20,6 +20,7 @@
 };
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::Span;
+use rustc_symbol_mangling::typeid::kcfi_typeid_for_fnabi;
 use rustc_target::abi::{self, call::FnAbi, Align, Size, WrappingRange};
 use rustc_target::spec::{HasTargetSpec, Target};
 use std::borrow::Cow;
@@ -225,9 +226,25 @@ fn invoke(
         debug!("invoke {:?} with args ({:?})", llfn, args);
 
         let args = self.check_call("invoke", llty, llfn, args);
-        let bundle = funclet.map(|funclet| funclet.bundle());
-        let bundle = bundle.as_ref().map(|b| &*b.raw);
+        let funclet_bundle = funclet.map(|funclet| funclet.bundle());
+        let funclet_bundle = funclet_bundle.as_ref().map(|b| &*b.raw);
+        let mut bundles = vec![funclet_bundle];
+
+        // Set KCFI operand bundle
+        let is_indirect_call = unsafe { llvm::LLVMIsAFunction(llfn).is_none() };
+        let kcfi_bundle =
+            if self.tcx.sess.is_sanitizer_kcfi_enabled() && fn_abi.is_some() && is_indirect_call {
+                let kcfi_typeid = kcfi_typeid_for_fnabi(self.tcx, fn_abi.unwrap());
+                Some(llvm::OperandBundleDef::new("kcfi", &[self.const_u32(kcfi_typeid)]))
+            } else {
+                None
+            };
+        if kcfi_bundle.is_some() {
+            let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw);
+            bundles.push(kcfi_bundle);
+        }
 
+        bundles.retain(|bundle| bundle.is_some());
         let invoke = unsafe {
             llvm::LLVMRustBuildInvoke(
                 self.llbuilder,
@@ -237,7 +254,8 @@ fn invoke(
                 args.len() as c_uint,
                 then,
                 catch,
-                bundle,
+                bundles.as_ptr(),
+                bundles.len() as c_uint,
                 UNNAMED,
             )
         };
@@ -961,15 +979,20 @@ fn set_personality_fn(&mut self, personality: &'ll Value) {
         }
     }
 
-    fn cleanup_landing_pad(&mut self, ty: &'ll Type, pers_fn: &'ll Value) -> &'ll Value {
+    fn cleanup_landing_pad(&mut self, pers_fn: &'ll Value) -> (&'ll Value, &'ll Value) {
+        let ty = self.type_struct(&[self.type_i8p(), self.type_i32()], false);
         let landing_pad = self.landing_pad(ty, pers_fn, 1 /* FIXME should this be 0? */);
         unsafe {
             llvm::LLVMSetCleanup(landing_pad, llvm::True);
         }
-        landing_pad
+        (self.extract_value(landing_pad, 0), self.extract_value(landing_pad, 1))
     }
 
-    fn resume(&mut self, exn: &'ll Value) {
+    fn resume(&mut self, exn0: &'ll Value, exn1: &'ll Value) {
+        let ty = self.type_struct(&[self.type_i8p(), self.type_i32()], false);
+        let mut exn = self.const_undef(ty);
+        exn = self.insert_value(exn, exn0, 0);
+        exn = self.insert_value(exn, exn1, 1);
         unsafe {
             llvm::LLVMBuildResume(self.llbuilder, exn);
         }
@@ -1143,7 +1166,8 @@ fn instrprof_increment(
                 llfn,
                 args.as_ptr() as *const &llvm::Value,
                 args.len() as c_uint,
-                None,
+                [].as_ptr(),
+                0 as c_uint,
             );
         }
     }
@@ -1159,9 +1183,25 @@ fn call(
         debug!("call {:?} with args ({:?})", llfn, args);
 
         let args = self.check_call("call", llty, llfn, args);
-        let bundle = funclet.map(|funclet| funclet.bundle());
-        let bundle = bundle.as_ref().map(|b| &*b.raw);
+        let funclet_bundle = funclet.map(|funclet| funclet.bundle());
+        let funclet_bundle = funclet_bundle.as_ref().map(|b| &*b.raw);
+        let mut bundles = vec![funclet_bundle];
+
+        // Set KCFI operand bundle
+        let is_indirect_call = unsafe { llvm::LLVMIsAFunction(llfn).is_none() };
+        let kcfi_bundle =
+            if self.tcx.sess.is_sanitizer_kcfi_enabled() && fn_abi.is_some() && is_indirect_call {
+                let kcfi_typeid = kcfi_typeid_for_fnabi(self.tcx, fn_abi.unwrap());
+                Some(llvm::OperandBundleDef::new("kcfi", &[self.const_u32(kcfi_typeid)]))
+            } else {
+                None
+            };
+        if kcfi_bundle.is_some() {
+            let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw);
+            bundles.push(kcfi_bundle);
+        }
 
+        bundles.retain(|bundle| bundle.is_some());
         let call = unsafe {
             llvm::LLVMRustBuildCall(
                 self.llbuilder,
@@ -1169,7 +1209,8 @@ fn call(
                 llfn,
                 args.as_ptr() as *const &llvm::Value,
                 args.len() as c_uint,
-                bundle,
+                bundles.as_ptr(),
+                bundles.len() as c_uint,
             )
         };
         if let Some(fn_abi) = fn_abi {
index 3c324359565c1081699b70ea2e432b23322ced98..3626aa901c0ef45b02dfa23fe54487d491436f11 100644 (file)
@@ -1,7 +1,7 @@
 use crate::base;
 use crate::common::{self, CodegenCx};
 use crate::debuginfo;
-use crate::errors::{InvalidMinimumAlignment, LinkageConstOrMutType, SymbolAlreadyDefined};
+use crate::errors::{InvalidMinimumAlignment, SymbolAlreadyDefined};
 use crate::llvm::{self, True};
 use crate::llvm_util;
 use crate::type_::Type;
@@ -162,22 +162,12 @@ fn check_and_apply_linkage<'ll, 'tcx>(
     def_id: DefId,
 ) -> &'ll Value {
     let llty = cx.layout_of(ty).llvm_type(cx);
-    if let Some(linkage) = attrs.linkage {
+    if let Some(linkage) = attrs.import_linkage {
         debug!("get_static: sym={} linkage={:?}", sym, linkage);
 
-        // If this is a static with a linkage specified, then we need to handle
-        // it a little specially. The typesystem prevents things like &T and
-        // extern "C" fn() from being non-null, so we can't just declare a
-        // static and call it a day. Some linkages (like weak) will make it such
-        // that the static actually has a null value.
-        let llty2 = if let ty::RawPtr(ref mt) = ty.kind() {
-            cx.layout_of(mt.ty).llvm_type(cx)
-        } else {
-            cx.sess().emit_fatal(LinkageConstOrMutType { span: cx.tcx.def_span(def_id) })
-        };
         unsafe {
             // Declare a symbol `foo` with the desired linkage.
-            let g1 = cx.declare_global(sym, llty2);
+            let g1 = cx.declare_global(sym, cx.type_i8());
             llvm::LLVMRustSetLinkage(g1, base::linkage_to_llvm(linkage));
 
             // Declare an internal global `extern_with_linkage_foo` which
@@ -195,7 +185,7 @@ fn check_and_apply_linkage<'ll, 'tcx>(
                 })
             });
             llvm::LLVMRustSetLinkage(g2, llvm::Linkage::InternalLinkage);
-            llvm::LLVMSetInitializer(g2, g1);
+            llvm::LLVMSetInitializer(g2, cx.const_ptrcast(g1, llty));
             g2
         }
     } else if cx.tcx.sess.target.arch == "x86" &&
index 4dcc7cd54477def2a32ab3ea7e06b9f566b08b0c..f3bff5d57161e25422ab811186ab2a1367cecefa 100644 (file)
@@ -3,7 +3,6 @@
 use crate::callee::get_fn;
 use crate::coverageinfo;
 use crate::debuginfo;
-use crate::errors::BranchProtectionRequiresAArch64;
 use crate::llvm;
 use crate::llvm_util;
 use crate::type_::Type;
@@ -250,6 +249,11 @@ pub unsafe fn create_module<'ll>(
         );
     }
 
+    if sess.is_sanitizer_kcfi_enabled() {
+        let kcfi = "kcfi\0".as_ptr().cast();
+        llvm::LLVMRustAddModuleFlag(llmod, llvm::LLVMModFlagBehavior::Override, kcfi, 1);
+    }
+
     // Control Flow Guard is currently only supported by the MSVC linker on Windows.
     if sess.target.is_like_msvc {
         match sess.opts.cg.control_flow_guard {
@@ -276,9 +280,7 @@ pub unsafe fn create_module<'ll>(
     }
 
     if let Some(BranchProtection { bti, pac_ret }) = sess.opts.unstable_opts.branch_protection {
-        if sess.target.arch != "aarch64" {
-            sess.emit_err(BranchProtectionRequiresAArch64);
-        } else {
+        if sess.target.arch == "aarch64" {
             llvm::LLVMRustAddModuleFlag(
                 llmod,
                 llvm::LLVMModFlagBehavior::Error,
@@ -304,6 +306,11 @@ pub unsafe fn create_module<'ll>(
                 "sign-return-address-with-bkey\0".as_ptr().cast(),
                 u32::from(pac_opts.key == PAuthKey::B),
             );
+        } else {
+            bug!(
+                "branch-protection used on non-AArch64 target; \
+                  this should be checked in rustc_session."
+            );
         }
     }
 
index d87117dffdc60b41c33f6fc778a11ae719561864..a9e3dcf4cb39a7c56663f6bb271c82e0003ea71f 100644 (file)
@@ -27,9 +27,7 @@
 use rustc_fs_util::path_to_c_string;
 use rustc_hir::def::CtorKind;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
-use rustc_index::vec::{Idx, IndexVec};
 use rustc_middle::bug;
-use rustc_middle::mir::{self, GeneratorLayout};
 use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::{
@@ -1026,33 +1024,6 @@ fn build_struct_type_di_node<'ll, 'tcx>(
 // Tuples
 //=-----------------------------------------------------------------------------
 
-/// Returns names of captured upvars for closures and generators.
-///
-/// Here are some examples:
-///  - `name__field1__field2` when the upvar is captured by value.
-///  - `_ref__name__field` when the upvar is captured by reference.
-///
-/// For generators this only contains upvars that are shared by all states.
-fn closure_saved_names_of_captured_variables(tcx: TyCtxt<'_>, def_id: DefId) -> SmallVec<String> {
-    let body = tcx.optimized_mir(def_id);
-
-    body.var_debug_info
-        .iter()
-        .filter_map(|var| {
-            let is_ref = match var.value {
-                mir::VarDebugInfoContents::Place(place) if place.local == mir::Local::new(1) => {
-                    // The projection is either `[.., Field, Deref]` or `[.., Field]`. It
-                    // implies whether the variable is captured by value or by reference.
-                    matches!(place.projection.last().unwrap(), mir::ProjectionElem::Deref)
-                }
-                _ => return None,
-            };
-            let prefix = if is_ref { "_ref__" } else { "" };
-            Some(prefix.to_owned() + var.name.as_str())
-        })
-        .collect()
-}
-
 /// Builds the DW_TAG_member debuginfo nodes for the upvars of a closure or generator.
 /// For a generator, this will handle upvars shared by all states.
 fn build_upvar_field_di_nodes<'ll, 'tcx>(
@@ -1083,7 +1054,7 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>(
             .all(|&t| t == cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t))
     );
 
-    let capture_names = closure_saved_names_of_captured_variables(cx.tcx, def_id);
+    let capture_names = cx.tcx.closure_saved_names_of_captured_variables(def_id);
     let layout = cx.layout_of(closure_or_generator_ty);
 
     up_var_tys
@@ -1229,43 +1200,6 @@ fn build_union_type_di_node<'ll, 'tcx>(
     )
 }
 
-// FIXME(eddyb) maybe precompute this? Right now it's computed once
-// per generator monomorphization, but it doesn't depend on substs.
-fn generator_layout_and_saved_local_names<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    def_id: DefId,
-) -> (&'tcx GeneratorLayout<'tcx>, IndexVec<mir::GeneratorSavedLocal, Option<Symbol>>) {
-    let body = tcx.optimized_mir(def_id);
-    let generator_layout = body.generator_layout().unwrap();
-    let mut generator_saved_local_names = IndexVec::from_elem(None, &generator_layout.field_tys);
-
-    let state_arg = mir::Local::new(1);
-    for var in &body.var_debug_info {
-        let mir::VarDebugInfoContents::Place(place) = &var.value else { continue };
-        if place.local != state_arg {
-            continue;
-        }
-        match place.projection[..] {
-            [
-                // Deref of the `Pin<&mut Self>` state argument.
-                mir::ProjectionElem::Field(..),
-                mir::ProjectionElem::Deref,
-                // Field of a variant of the state.
-                mir::ProjectionElem::Downcast(_, variant),
-                mir::ProjectionElem::Field(field, _),
-            ] => {
-                let name = &mut generator_saved_local_names
-                    [generator_layout.variant_fields[variant][field]];
-                if name.is_none() {
-                    name.replace(var.name);
-                }
-            }
-            _ => {}
-        }
-    }
-    (generator_layout, generator_saved_local_names)
-}
-
 /// Computes the type parameters for a type, if any, for the given metadata.
 fn build_generic_type_param_di_nodes<'ll, 'tcx>(
     cx: &CodegenCx<'ll, 'tcx>,
index 53e8a291d1e8aa4d9a4cd90530b27ed0ad04edfa..69443b9b828e2caf3a19ba382557c3431ada8169 100644 (file)
@@ -22,9 +22,9 @@
     common::CodegenCx,
     debuginfo::{
         metadata::{
-            build_field_di_node, closure_saved_names_of_captured_variables,
+            build_field_di_node,
             enums::{tag_base_type, DiscrResult},
-            file_metadata, generator_layout_and_saved_local_names, size_and_align_of, type_di_node,
+            file_metadata, size_and_align_of, type_di_node,
             type_map::{self, Stub, UniqueTypeId},
             unknown_file_metadata, DINodeCreationResult, SmallVec, NO_GENERICS, NO_SCOPE_METADATA,
             UNKNOWN_LINE_NUMBER,
@@ -677,9 +677,9 @@ fn build_union_fields_for_direct_tag_generator<'ll, 'tcx>(
     };
 
     let (generator_layout, state_specific_upvar_names) =
-        generator_layout_and_saved_local_names(cx.tcx, generator_def_id);
+        cx.tcx.generator_layout_and_saved_local_names(generator_def_id);
 
-    let common_upvar_names = closure_saved_names_of_captured_variables(cx.tcx, generator_def_id);
+    let common_upvar_names = cx.tcx.closure_saved_names_of_captured_variables(generator_def_id);
     let variant_range = generator_substs.variant_range(generator_def_id, cx.tcx);
     let variant_count = (variant_range.start.as_u32()..variant_range.end.as_u32()).len();
 
index becbccc434d9ac33ee30091225aa0b87278986b7..93419d27a6236c5356a1a4045c7e05b0225794a6 100644 (file)
@@ -4,9 +4,8 @@
     common::CodegenCx,
     debuginfo::{
         metadata::{
-            closure_saved_names_of_captured_variables,
             enums::tag_base_type,
-            file_metadata, generator_layout_and_saved_local_names, size_and_align_of, type_di_node,
+            file_metadata, size_and_align_of, type_di_node,
             type_map::{self, Stub, StubInfo, UniqueTypeId},
             unknown_file_metadata, DINodeCreationResult, SmallVec, NO_GENERICS,
             UNKNOWN_LINE_NUMBER,
@@ -157,7 +156,7 @@ pub(super) fn build_generator_di_node<'ll, 'tcx>(
         ),
         |cx, generator_type_di_node| {
             let (generator_layout, state_specific_upvar_names) =
-                generator_layout_and_saved_local_names(cx.tcx, generator_def_id);
+                cx.tcx.generator_layout_and_saved_local_names(generator_def_id);
 
             let Variants::Multiple { tag_encoding: TagEncoding::Direct, ref variants, .. } = generator_type_and_layout.variants else {
                 bug!(
@@ -167,7 +166,7 @@ pub(super) fn build_generator_di_node<'ll, 'tcx>(
             };
 
             let common_upvar_names =
-                closure_saved_names_of_captured_variables(cx.tcx, generator_def_id);
+                cx.tcx.closure_saved_names_of_captured_variables(generator_def_id);
 
             // Build variant struct types
             let variant_struct_type_di_nodes: SmallVec<_> = variants
index dc21a02cec44a144fef0c9704b3a16af5c1868d2..6a575095f7e45dbc5e05a7b86cebd7ce2851925e 100644 (file)
@@ -20,7 +20,7 @@
 use crate::value::Value;
 use rustc_codegen_ssa::traits::TypeMembershipMethods;
 use rustc_middle::ty::Ty;
-use rustc_symbol_mangling::typeid::typeid_for_fnabi;
+use rustc_symbol_mangling::typeid::{kcfi_typeid_for_fnabi, typeid_for_fnabi};
 use smallvec::SmallVec;
 
 /// Declare a function.
@@ -136,6 +136,11 @@ pub fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> &'ll Val
             self.set_type_metadata(llfn, typeid);
         }
 
+        if self.tcx.sess.is_sanitizer_kcfi_enabled() {
+            let kcfi_typeid = kcfi_typeid_for_fnabi(self.tcx, fn_abi);
+            self.set_kcfi_type_metadata(llfn, kcfi_typeid);
+        }
+
         llfn
     }
 
index fddfbb23c67d5737a7d3031eee72f77707ca7fe9..b46209972421fe894fd4b217013d7072558d6682 100644 (file)
@@ -51,23 +51,12 @@ pub(crate) struct SymbolAlreadyDefined<'a> {
     pub symbol_name: &'a str,
 }
 
-#[derive(Diagnostic)]
-#[diag(codegen_llvm_branch_protection_requires_aarch64)]
-pub(crate) struct BranchProtectionRequiresAArch64;
-
 #[derive(Diagnostic)]
 #[diag(codegen_llvm_invalid_minimum_alignment)]
 pub(crate) struct InvalidMinimumAlignment {
     pub err: String,
 }
 
-#[derive(Diagnostic)]
-#[diag(codegen_llvm_linkage_const_or_mut_type)]
-pub(crate) struct LinkageConstOrMutType {
-    #[primary_span]
-    pub span: Span,
-}
-
 #[derive(Diagnostic)]
 #[diag(codegen_llvm_sanitizer_memtag_requires_mte)]
 pub(crate) struct SanitizerMemtagRequiresMte;
index 2f5dd519b2600af5113b40afb83fb0c6ac04d376..907517bf6ce950b148bed7f1916c847d0b80c5bd 100644 (file)
@@ -424,7 +424,9 @@ fn type_checked_load(
         typeid: &'ll Value,
     ) -> Self::Value {
         let vtable_byte_offset = self.const_i32(vtable_byte_offset as i32);
-        self.call_intrinsic("llvm.type.checked.load", &[llvtable, vtable_byte_offset, typeid])
+        let type_checked_load =
+            self.call_intrinsic("llvm.type.checked.load", &[llvtable, vtable_byte_offset, typeid]);
+        self.extract_value(type_checked_load, 0)
     }
 
     fn va_start(&mut self, va_list: &'ll Value) -> &'ll Value {
index 8a9392255b861881e13a5ba12ed1e0c389a2ac14..e61dbe8b8fc50dfbd2c0fe6de8fc8c7604b06974 100644 (file)
@@ -427,6 +427,7 @@ pub enum MetadataType {
     MD_type = 19,
     MD_vcall_visibility = 28,
     MD_noundef = 29,
+    MD_kcfi_type = 36,
 }
 
 /// LLVMRustAsmDialect
@@ -1063,6 +1064,7 @@ pub fn LLVMStructTypeInContext<'a>(
     pub fn LLVMGlobalSetMetadata<'a>(Val: &'a Value, KindID: c_uint, Metadata: &'a Metadata);
     pub fn LLVMRustGlobalAddMetadata<'a>(Val: &'a Value, KindID: c_uint, Metadata: &'a Metadata);
     pub fn LLVMValueAsMetadata(Node: &Value) -> &Metadata;
+    pub fn LLVMIsAFunction(Val: &Value) -> Option<&Value>;
 
     // Operations on constants of any type
     pub fn LLVMConstNull(Ty: &Type) -> &Value;
@@ -1273,7 +1275,8 @@ pub fn LLVMRustBuildInvoke<'a>(
         NumArgs: c_uint,
         Then: &'a BasicBlock,
         Catch: &'a BasicBlock,
-        Bundle: Option<&OperandBundleDef<'a>>,
+        OpBundles: *const Option<&OperandBundleDef<'a>>,
+        NumOpBundles: c_uint,
         Name: *const c_char,
     ) -> &'a Value;
     pub fn LLVMBuildLandingPad<'a>(
@@ -1643,7 +1646,8 @@ pub fn LLVMRustBuildCall<'a>(
         Fn: &'a Value,
         Args: *const &'a Value,
         NumArgs: c_uint,
-        Bundle: Option<&OperandBundleDef<'a>>,
+        OpBundles: *const Option<&OperandBundleDef<'a>>,
+        NumOpBundles: c_uint,
     ) -> &'a Value;
     pub fn LLVMRustBuildMemCpy<'a>(
         B: &Builder<'a>,
index 5772b7e1d812afa3c2566ecb3fd31e042e078f80..ff111d96f840b1bc817ceb7bfbecf29aa1ee0e6d 100644 (file)
@@ -316,4 +316,19 @@ fn typeid_metadata(&self, typeid: String) -> &'ll Value {
             )
         }
     }
+
+    fn set_kcfi_type_metadata(&self, function: &'ll Value, kcfi_typeid: u32) {
+        let kcfi_type_metadata = self.const_u32(kcfi_typeid);
+        unsafe {
+            llvm::LLVMGlobalSetMetadata(
+                function,
+                llvm::MD_kcfi_type as c_uint,
+                llvm::LLVMMDNodeInContext2(
+                    self.llcx,
+                    &llvm::LLVMValueAsMetadata(kcfi_type_metadata),
+                    1,
+                ),
+            )
+        }
+    }
 }
index 58558fb8c4ba2912b53f7fcef66c10c676c4a7aa..5266d8858d47d35dcc9c12e0e935bb9327b1d4f0 100644 (file)
@@ -14,7 +14,7 @@
 
 use std::error::Error;
 use std::fs::File;
-use std::io::{self, Write};
+use std::io;
 use std::path::{Path, PathBuf};
 
 // Re-exporting for rustc_codegen_llvm::back::archive
@@ -116,12 +116,11 @@ pub fn new(
     }
 }
 
-fn try_filter_fat_archs(
+fn try_filter_fat_archs<'a>(
     archs: object::read::Result<&[impl FatArch]>,
     target_arch: object::Architecture,
-    archive_path: &Path,
-    archive_map_data: &[u8],
-) -> io::Result<Option<PathBuf>> {
+    archive_map_data: &'a [u8],
+) -> io::Result<Option<(&'a [u8], u64)>> {
     let archs = archs.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
 
     let desired = match archs.iter().filter(|a| a.architecture() == target_arch).next() {
@@ -129,38 +128,30 @@ fn try_filter_fat_archs(
         None => return Ok(None),
     };
 
-    let (mut new_f, extracted_path) = tempfile::Builder::new()
-        .suffix(archive_path.file_name().unwrap())
-        .tempfile()?
-        .keep()
-        .unwrap();
-
-    new_f.write_all(
+    Ok(Some((
         desired.data(archive_map_data).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?,
-    )?;
-
-    Ok(Some(extracted_path))
+        desired.offset().into(),
+    )))
 }
 
-pub fn try_extract_macho_fat_archive(
+pub fn try_extract_macho_fat_archive<'a>(
     sess: &Session,
-    archive_path: &Path,
-) -> io::Result<Option<PathBuf>> {
-    let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? };
+    archive_bytes: &'a [u8],
+) -> io::Result<Option<(&'a [u8], u64)>> {
     let target_arch = match sess.target.arch.as_ref() {
         "aarch64" => object::Architecture::Aarch64,
         "x86_64" => object::Architecture::X86_64,
         _ => return Ok(None),
     };
 
-    match object::macho::FatHeader::parse(&*archive_map) {
+    match object::macho::FatHeader::parse(archive_bytes) {
         Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC => {
-            let archs = object::macho::FatHeader::parse_arch32(&*archive_map);
-            try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map)
+            let archs = object::macho::FatHeader::parse_arch32(archive_bytes);
+            try_filter_fat_archs(archs, target_arch, archive_bytes)
         }
         Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC_64 => {
-            let archs = object::macho::FatHeader::parse_arch64(&*archive_map);
-            try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map)
+            let archs = object::macho::FatHeader::parse_arch64(archive_bytes);
+            try_filter_fat_archs(archs, target_arch, archive_bytes)
         }
         // Not a FatHeader at all, just return None.
         _ => Ok(None),
@@ -173,21 +164,24 @@ fn add_archive(
         archive_path: &Path,
         mut skip: Box<dyn FnMut(&str) -> bool + 'static>,
     ) -> io::Result<()> {
-        let mut archive_path = archive_path.to_path_buf();
-        if self.sess.target.llvm_target.contains("-apple-macosx") {
-            if let Some(new_archive_path) =
-                try_extract_macho_fat_archive(&self.sess, &archive_path)?
-            {
-                archive_path = new_archive_path
-            }
-        }
-
+        let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? };
         if self.src_archives.iter().any(|archive| archive.0 == archive_path) {
             return Ok(());
         }
 
-        let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? };
-        let archive = ArchiveFile::parse(&*archive_map)
+        let (archive_bytes, offset) = if self.sess.target.llvm_target.contains("-apple-macosx") {
+            if let Some((sub_archive, archive_offset)) =
+                try_extract_macho_fat_archive(&self.sess, &*archive_map)?
+            {
+                (sub_archive, Some(archive_offset))
+            } else {
+                (&*archive_map, None)
+            }
+        } else {
+            (&*archive_map, None)
+        };
+
+        let archive = ArchiveFile::parse(&*archive_bytes)
             .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
         let archive_index = self.src_archives.len();
 
@@ -196,9 +190,13 @@ fn add_archive(
             let file_name = String::from_utf8(entry.name().to_vec())
                 .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
             if !skip(&file_name) {
+                let mut range = entry.file_range();
+                if let Some(offset) = offset {
+                    range.0 += offset;
+                }
                 self.entries.push((
                     file_name.into_bytes(),
-                    ArchiveEntry::FromArchive { archive_index, file_range: entry.file_range() },
+                    ArchiveEntry::FromArchive { archive_index, file_range: range },
                 ));
             }
         }
index 7cb4f5503a101f1da94d1b78ed4020154c83317b..a1c77ec0cfca7b7f24a90324cf10bb666b0f0a17 100644 (file)
@@ -102,7 +102,7 @@ pub fn link_binary<'a>(
                 sess,
                 crate_type,
                 outputs,
-                codegen_results.crate_info.local_crate_name.as_str(),
+                codegen_results.crate_info.local_crate_name,
             );
             match crate_type {
                 CrateType::Rlib => {
@@ -253,7 +253,7 @@ pub fn each_linked_rlib(
     };
     for &cnum in crates {
         match fmts.get(cnum.as_usize() - 1) {
-            Some(&Linkage::NotLinked | &Linkage::IncludedFromDylib) => continue,
+            Some(&Linkage::NotLinked | &Linkage::Dynamic | &Linkage::IncludedFromDylib) => continue,
             Some(_) => {}
             None => return Err(errors::LinkRlibError::MissingFormat),
         }
@@ -722,7 +722,7 @@ fn link_natively<'a>(
 
     linker::disable_localization(&mut cmd);
 
-    for &(ref k, ref v) in sess.target.link_env.as_ref() {
+    for (k, v) in sess.target.link_env.as_ref() {
         cmd.env(k.as_ref(), v.as_ref());
     }
     for k in sess.target.link_env_remove.as_ref() {
@@ -2352,15 +2352,6 @@ fn add_native_libs_from_crate(
                                 &search_paths.get_or_init(|| archive_search_paths(sess)),
                             );
                         } else {
-                            // HACK/FIXME: Fixup a circular dependency between libgcc and libc
-                            // with glibc. This logic should be moved to the libc crate.
-                            if cnum != LOCAL_CRATE
-                                && sess.target.os == "linux"
-                                && sess.target.env == "gnu"
-                                && name == "c"
-                            {
-                                cmd.link_staticlib("gcc", false);
-                            }
                             cmd.link_staticlib(name, verbatim)
                         }
                     }
index f087d903e5568f835476c6a43d8dd8c4f7dda6ce..0268659d3b9a13d8515eace64f9d4d2851945bec 100644 (file)
@@ -108,7 +108,7 @@ pub fn get_linker<'a>(
     if sess.target.is_like_msvc {
         if let Some(ref tool) = msvc_tool {
             cmd.args(tool.args());
-            for &(ref k, ref v) in tool.env() {
+            for (k, v) in tool.env() {
                 if k == "PATH" {
                     new_path.extend(env::split_paths(v));
                     msvc_changed_path = true;
index 4f396e970ad70969228cae3756eec5273af4a483..664697e0edaa406f5018d4a014fe7973730785f8 100644 (file)
@@ -41,7 +41,6 @@
 use rustc_target::abi::{Align, Size, VariantIdx};
 
 use std::collections::BTreeSet;
-use std::convert::TryFrom;
 use std::time::{Duration, Instant};
 
 use itertools::Itertools;
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
new file mode 100644 (file)
index 0000000..c7f2e19
--- /dev/null
@@ -0,0 +1,688 @@
+use rustc_ast::{ast, MetaItemKind, NestedMetaItem};
+use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr};
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
+use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
+use rustc_hir::{lang_items, weak_lang_items::WEAK_LANG_ITEMS, LangItem};
+use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
+use rustc_middle::mir::mono::Linkage;
+use rustc_middle::ty::query::Providers;
+use rustc_middle::ty::{self as ty, DefIdTree, TyCtxt};
+use rustc_session::{lint, parse::feature_err};
+use rustc_span::{sym, Span};
+use rustc_target::spec::{abi, SanitizerSet};
+
+use crate::target_features::from_target_feature;
+use crate::{errors::ExpectedUsedSymbol, target_features::check_target_feature_trait_unsafe};
+
+fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage {
+    use rustc_middle::mir::mono::Linkage::*;
+
+    // Use the names from src/llvm/docs/LangRef.rst here. Most types are only
+    // applicable to variable declarations and may not really make sense for
+    // Rust code in the first place but allow them anyway and trust that the
+    // user knows what they're doing. Who knows, unanticipated use cases may pop
+    // up in the future.
+    //
+    // ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
+    // and don't have to be, LLVM treats them as no-ops.
+    match name {
+        "appending" => Appending,
+        "available_externally" => AvailableExternally,
+        "common" => Common,
+        "extern_weak" => ExternalWeak,
+        "external" => External,
+        "internal" => Internal,
+        "linkonce" => LinkOnceAny,
+        "linkonce_odr" => LinkOnceODR,
+        "private" => Private,
+        "weak" => WeakAny,
+        "weak_odr" => WeakODR,
+        _ => tcx.sess.span_fatal(tcx.def_span(def_id), "invalid linkage specified"),
+    }
+}
+
+fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
+    if cfg!(debug_assertions) {
+        let def_kind = tcx.def_kind(did);
+        assert!(
+            def_kind.has_codegen_attrs(),
+            "unexpected `def_kind` in `codegen_fn_attrs`: {def_kind:?}",
+        );
+    }
+
+    let did = did.expect_local();
+    let attrs = tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(did));
+    let mut codegen_fn_attrs = CodegenFnAttrs::new();
+    if tcx.should_inherit_track_caller(did) {
+        codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
+    }
+
+    let supported_target_features = tcx.supported_target_features(LOCAL_CRATE);
+
+    let mut inline_span = None;
+    let mut link_ordinal_span = None;
+    let mut no_sanitize_span = None;
+    for attr in attrs.iter() {
+        if attr.has_name(sym::cold) {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD;
+        } else if attr.has_name(sym::rustc_allocator) {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR;
+        } else if attr.has_name(sym::ffi_returns_twice) {
+            if tcx.is_foreign_item(did) {
+                codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE;
+            } else {
+                // `#[ffi_returns_twice]` is only allowed `extern fn`s.
+                struct_span_err!(
+                    tcx.sess,
+                    attr.span,
+                    E0724,
+                    "`#[ffi_returns_twice]` may only be used on foreign functions"
+                )
+                .emit();
+            }
+        } else if attr.has_name(sym::ffi_pure) {
+            if tcx.is_foreign_item(did) {
+                if attrs.iter().any(|a| a.has_name(sym::ffi_const)) {
+                    // `#[ffi_const]` functions cannot be `#[ffi_pure]`
+                    struct_span_err!(
+                        tcx.sess,
+                        attr.span,
+                        E0757,
+                        "`#[ffi_const]` function cannot be `#[ffi_pure]`"
+                    )
+                    .emit();
+                } else {
+                    codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE;
+                }
+            } else {
+                // `#[ffi_pure]` is only allowed on foreign functions
+                struct_span_err!(
+                    tcx.sess,
+                    attr.span,
+                    E0755,
+                    "`#[ffi_pure]` may only be used on foreign functions"
+                )
+                .emit();
+            }
+        } else if attr.has_name(sym::ffi_const) {
+            if tcx.is_foreign_item(did) {
+                codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST;
+            } else {
+                // `#[ffi_const]` is only allowed on foreign functions
+                struct_span_err!(
+                    tcx.sess,
+                    attr.span,
+                    E0756,
+                    "`#[ffi_const]` may only be used on foreign functions"
+                )
+                .emit();
+            }
+        } else if attr.has_name(sym::rustc_nounwind) {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
+        } else if attr.has_name(sym::rustc_reallocator) {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::REALLOCATOR;
+        } else if attr.has_name(sym::rustc_deallocator) {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::DEALLOCATOR;
+        } else if attr.has_name(sym::rustc_allocator_zeroed) {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED;
+        } else if attr.has_name(sym::naked) {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED;
+        } else if attr.has_name(sym::no_mangle) {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
+        } else if attr.has_name(sym::no_coverage) {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE;
+        } else if attr.has_name(sym::rustc_std_internal_symbol) {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
+        } else if attr.has_name(sym::used) {
+            let inner = attr.meta_item_list();
+            match inner.as_deref() {
+                Some([item]) if item.has_name(sym::linker) => {
+                    if !tcx.features().used_with_arg {
+                        feature_err(
+                            &tcx.sess.parse_sess,
+                            sym::used_with_arg,
+                            attr.span,
+                            "`#[used(linker)]` is currently unstable",
+                        )
+                        .emit();
+                    }
+                    codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_LINKER;
+                }
+                Some([item]) if item.has_name(sym::compiler) => {
+                    if !tcx.features().used_with_arg {
+                        feature_err(
+                            &tcx.sess.parse_sess,
+                            sym::used_with_arg,
+                            attr.span,
+                            "`#[used(compiler)]` is currently unstable",
+                        )
+                        .emit();
+                    }
+                    codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED;
+                }
+                Some(_) => {
+                    tcx.sess.emit_err(ExpectedUsedSymbol { span: attr.span });
+                }
+                None => {
+                    // Unfortunately, unconditionally using `llvm.used` causes
+                    // issues in handling `.init_array` with the gold linker,
+                    // but using `llvm.compiler.used` caused a nontrival amount
+                    // of unintentional ecosystem breakage -- particularly on
+                    // Mach-O targets.
+                    //
+                    // As a result, we emit `llvm.compiler.used` only on ELF
+                    // targets. This is somewhat ad-hoc, but actually follows
+                    // our pre-LLVM 13 behavior (prior to the ecosystem
+                    // breakage), and seems to match `clang`'s behavior as well
+                    // (both before and after LLVM 13), possibly because they
+                    // have similar compatibility concerns to us. See
+                    // https://github.com/rust-lang/rust/issues/47384#issuecomment-1019080146
+                    // and following comments for some discussion of this, as
+                    // well as the comments in `rustc_codegen_llvm` where these
+                    // flags are handled.
+                    //
+                    // Anyway, to be clear: this is still up in the air
+                    // somewhat, and is subject to change in the future (which
+                    // is a good thing, because this would ideally be a bit
+                    // more firmed up).
+                    let is_like_elf = !(tcx.sess.target.is_like_osx
+                        || tcx.sess.target.is_like_windows
+                        || tcx.sess.target.is_like_wasm);
+                    codegen_fn_attrs.flags |= if is_like_elf {
+                        CodegenFnAttrFlags::USED
+                    } else {
+                        CodegenFnAttrFlags::USED_LINKER
+                    };
+                }
+            }
+        } else if attr.has_name(sym::cmse_nonsecure_entry) {
+            if !matches!(tcx.fn_sig(did).abi(), abi::Abi::C { .. }) {
+                struct_span_err!(
+                    tcx.sess,
+                    attr.span,
+                    E0776,
+                    "`#[cmse_nonsecure_entry]` requires C ABI"
+                )
+                .emit();
+            }
+            if !tcx.sess.target.llvm_target.contains("thumbv8m") {
+                struct_span_err!(tcx.sess, attr.span, E0775, "`#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension")
+                    .emit();
+            }
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY;
+        } else if attr.has_name(sym::thread_local) {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL;
+        } else if attr.has_name(sym::track_caller) {
+            if !tcx.is_closure(did.to_def_id()) && tcx.fn_sig(did).abi() != abi::Abi::Rust {
+                struct_span_err!(tcx.sess, attr.span, E0737, "`#[track_caller]` requires Rust ABI")
+                    .emit();
+            }
+            if tcx.is_closure(did.to_def_id()) && !tcx.features().closure_track_caller {
+                feature_err(
+                    &tcx.sess.parse_sess,
+                    sym::closure_track_caller,
+                    attr.span,
+                    "`#[track_caller]` on closures is currently unstable",
+                )
+                .emit();
+            }
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
+        } else if attr.has_name(sym::export_name) {
+            if let Some(s) = attr.value_str() {
+                if s.as_str().contains('\0') {
+                    // `#[export_name = ...]` will be converted to a null-terminated string,
+                    // so it may not contain any null characters.
+                    struct_span_err!(
+                        tcx.sess,
+                        attr.span,
+                        E0648,
+                        "`export_name` may not contain null characters"
+                    )
+                    .emit();
+                }
+                codegen_fn_attrs.export_name = Some(s);
+            }
+        } else if attr.has_name(sym::target_feature) {
+            if !tcx.is_closure(did.to_def_id())
+                && tcx.fn_sig(did).unsafety() == hir::Unsafety::Normal
+            {
+                if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc {
+                    // The `#[target_feature]` attribute is allowed on
+                    // WebAssembly targets on all functions, including safe
+                    // ones. Other targets require that `#[target_feature]` is
+                    // only applied to unsafe functions (pending the
+                    // `target_feature_11` feature) because on most targets
+                    // execution of instructions that are not supported is
+                    // considered undefined behavior. For WebAssembly which is a
+                    // 100% safe target at execution time it's not possible to
+                    // execute undefined instructions, and even if a future
+                    // feature was added in some form for this it would be a
+                    // deterministic trap. There is no undefined behavior when
+                    // executing WebAssembly so `#[target_feature]` is allowed
+                    // on safe functions (but again, only for WebAssembly)
+                    //
+                    // Note that this is also allowed if `actually_rustdoc` so
+                    // if a target is documenting some wasm-specific code then
+                    // it's not spuriously denied.
+                } else if !tcx.features().target_feature_11 {
+                    let mut err = feature_err(
+                        &tcx.sess.parse_sess,
+                        sym::target_feature_11,
+                        attr.span,
+                        "`#[target_feature(..)]` can only be applied to `unsafe` functions",
+                    );
+                    err.span_label(tcx.def_span(did), "not an `unsafe` function");
+                    err.emit();
+                } else {
+                    check_target_feature_trait_unsafe(tcx, did, attr.span);
+                }
+            }
+            from_target_feature(
+                tcx,
+                attr,
+                supported_target_features,
+                &mut codegen_fn_attrs.target_features,
+            );
+        } else if attr.has_name(sym::linkage) {
+            if let Some(val) = attr.value_str() {
+                let linkage = Some(linkage_by_name(tcx, did, val.as_str()));
+                if tcx.is_foreign_item(did) {
+                    codegen_fn_attrs.import_linkage = linkage;
+                } else {
+                    codegen_fn_attrs.linkage = linkage;
+                }
+            }
+        } else if attr.has_name(sym::link_section) {
+            if let Some(val) = attr.value_str() {
+                if val.as_str().bytes().any(|b| b == 0) {
+                    let msg = format!(
+                        "illegal null byte in link_section \
+                         value: `{}`",
+                        &val
+                    );
+                    tcx.sess.span_err(attr.span, &msg);
+                } else {
+                    codegen_fn_attrs.link_section = Some(val);
+                }
+            }
+        } else if attr.has_name(sym::link_name) {
+            codegen_fn_attrs.link_name = attr.value_str();
+        } else if attr.has_name(sym::link_ordinal) {
+            link_ordinal_span = Some(attr.span);
+            if let ordinal @ Some(_) = check_link_ordinal(tcx, attr) {
+                codegen_fn_attrs.link_ordinal = ordinal;
+            }
+        } else if attr.has_name(sym::no_sanitize) {
+            no_sanitize_span = Some(attr.span);
+            if let Some(list) = attr.meta_item_list() {
+                for item in list.iter() {
+                    if item.has_name(sym::address) {
+                        codegen_fn_attrs.no_sanitize |= SanitizerSet::ADDRESS;
+                    } else if item.has_name(sym::cfi) {
+                        codegen_fn_attrs.no_sanitize |= SanitizerSet::CFI;
+                    } else if item.has_name(sym::kcfi) {
+                        codegen_fn_attrs.no_sanitize |= SanitizerSet::KCFI;
+                    } else if item.has_name(sym::memory) {
+                        codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMORY;
+                    } else if item.has_name(sym::memtag) {
+                        codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMTAG;
+                    } else if item.has_name(sym::shadow_call_stack) {
+                        codegen_fn_attrs.no_sanitize |= SanitizerSet::SHADOWCALLSTACK;
+                    } else if item.has_name(sym::thread) {
+                        codegen_fn_attrs.no_sanitize |= SanitizerSet::THREAD;
+                    } else if item.has_name(sym::hwaddress) {
+                        codegen_fn_attrs.no_sanitize |= SanitizerSet::HWADDRESS;
+                    } else {
+                        tcx.sess
+                            .struct_span_err(item.span(), "invalid argument for `no_sanitize`")
+                            .note("expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread`")
+                            .emit();
+                    }
+                }
+            }
+        } else if attr.has_name(sym::instruction_set) {
+            codegen_fn_attrs.instruction_set = match attr.meta_kind() {
+                Some(MetaItemKind::List(ref items)) => match items.as_slice() {
+                    [NestedMetaItem::MetaItem(set)] => {
+                        let segments =
+                            set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>();
+                        match segments.as_slice() {
+                            [sym::arm, sym::a32] | [sym::arm, sym::t32] => {
+                                if !tcx.sess.target.has_thumb_interworking {
+                                    struct_span_err!(
+                                        tcx.sess.diagnostic(),
+                                        attr.span,
+                                        E0779,
+                                        "target does not support `#[instruction_set]`"
+                                    )
+                                    .emit();
+                                    None
+                                } else if segments[1] == sym::a32 {
+                                    Some(InstructionSetAttr::ArmA32)
+                                } else if segments[1] == sym::t32 {
+                                    Some(InstructionSetAttr::ArmT32)
+                                } else {
+                                    unreachable!()
+                                }
+                            }
+                            _ => {
+                                struct_span_err!(
+                                    tcx.sess.diagnostic(),
+                                    attr.span,
+                                    E0779,
+                                    "invalid instruction set specified",
+                                )
+                                .emit();
+                                None
+                            }
+                        }
+                    }
+                    [] => {
+                        struct_span_err!(
+                            tcx.sess.diagnostic(),
+                            attr.span,
+                            E0778,
+                            "`#[instruction_set]` requires an argument"
+                        )
+                        .emit();
+                        None
+                    }
+                    _ => {
+                        struct_span_err!(
+                            tcx.sess.diagnostic(),
+                            attr.span,
+                            E0779,
+                            "cannot specify more than one instruction set"
+                        )
+                        .emit();
+                        None
+                    }
+                },
+                _ => {
+                    struct_span_err!(
+                        tcx.sess.diagnostic(),
+                        attr.span,
+                        E0778,
+                        "must specify an instruction set"
+                    )
+                    .emit();
+                    None
+                }
+            };
+        } else if attr.has_name(sym::repr) {
+            codegen_fn_attrs.alignment = match attr.meta_item_list() {
+                Some(items) => match items.as_slice() {
+                    [item] => match item.name_value_literal() {
+                        Some((sym::align, literal)) => {
+                            let alignment = rustc_attr::parse_alignment(&literal.kind);
+
+                            match alignment {
+                                Ok(align) => Some(align),
+                                Err(msg) => {
+                                    struct_span_err!(
+                                        tcx.sess.diagnostic(),
+                                        attr.span,
+                                        E0589,
+                                        "invalid `repr(align)` attribute: {}",
+                                        msg
+                                    )
+                                    .emit();
+
+                                    None
+                                }
+                            }
+                        }
+                        _ => None,
+                    },
+                    [] => None,
+                    _ => None,
+                },
+                None => None,
+            };
+        }
+    }
+
+    codegen_fn_attrs.inline = attrs.iter().fold(InlineAttr::None, |ia, attr| {
+        if !attr.has_name(sym::inline) {
+            return ia;
+        }
+        match attr.meta_kind() {
+            Some(MetaItemKind::Word) => InlineAttr::Hint,
+            Some(MetaItemKind::List(ref items)) => {
+                inline_span = Some(attr.span);
+                if items.len() != 1 {
+                    struct_span_err!(
+                        tcx.sess.diagnostic(),
+                        attr.span,
+                        E0534,
+                        "expected one argument"
+                    )
+                    .emit();
+                    InlineAttr::None
+                } else if list_contains_name(&items, sym::always) {
+                    InlineAttr::Always
+                } else if list_contains_name(&items, sym::never) {
+                    InlineAttr::Never
+                } else {
+                    struct_span_err!(
+                        tcx.sess.diagnostic(),
+                        items[0].span(),
+                        E0535,
+                        "invalid argument"
+                    )
+                    .help("valid inline arguments are `always` and `never`")
+                    .emit();
+
+                    InlineAttr::None
+                }
+            }
+            Some(MetaItemKind::NameValue(_)) => ia,
+            None => ia,
+        }
+    });
+
+    codegen_fn_attrs.optimize = attrs.iter().fold(OptimizeAttr::None, |ia, attr| {
+        if !attr.has_name(sym::optimize) {
+            return ia;
+        }
+        let err = |sp, s| struct_span_err!(tcx.sess.diagnostic(), sp, E0722, "{}", s).emit();
+        match attr.meta_kind() {
+            Some(MetaItemKind::Word) => {
+                err(attr.span, "expected one argument");
+                ia
+            }
+            Some(MetaItemKind::List(ref items)) => {
+                inline_span = Some(attr.span);
+                if items.len() != 1 {
+                    err(attr.span, "expected one argument");
+                    OptimizeAttr::None
+                } else if list_contains_name(&items, sym::size) {
+                    OptimizeAttr::Size
+                } else if list_contains_name(&items, sym::speed) {
+                    OptimizeAttr::Speed
+                } else {
+                    err(items[0].span(), "invalid argument");
+                    OptimizeAttr::None
+                }
+            }
+            Some(MetaItemKind::NameValue(_)) => ia,
+            None => ia,
+        }
+    });
+
+    // #73631: closures inherit `#[target_feature]` annotations
+    if tcx.features().target_feature_11 && tcx.is_closure(did.to_def_id()) {
+        let owner_id = tcx.parent(did.to_def_id());
+        if tcx.def_kind(owner_id).has_codegen_attrs() {
+            codegen_fn_attrs
+                .target_features
+                .extend(tcx.codegen_fn_attrs(owner_id).target_features.iter().copied());
+        }
+    }
+
+    // If a function uses #[target_feature] it can't be inlined into general
+    // purpose functions as they wouldn't have the right target features
+    // enabled. For that reason we also forbid #[inline(always)] as it can't be
+    // respected.
+    if !codegen_fn_attrs.target_features.is_empty() {
+        if codegen_fn_attrs.inline == InlineAttr::Always {
+            if let Some(span) = inline_span {
+                tcx.sess.span_err(
+                    span,
+                    "cannot use `#[inline(always)]` with \
+                     `#[target_feature]`",
+                );
+            }
+        }
+    }
+
+    if !codegen_fn_attrs.no_sanitize.is_empty() {
+        if codegen_fn_attrs.inline == InlineAttr::Always {
+            if let (Some(no_sanitize_span), Some(inline_span)) = (no_sanitize_span, inline_span) {
+                let hir_id = tcx.hir().local_def_id_to_hir_id(did);
+                tcx.struct_span_lint_hir(
+                    lint::builtin::INLINE_NO_SANITIZE,
+                    hir_id,
+                    no_sanitize_span,
+                    "`no_sanitize` will have no effect after inlining",
+                    |lint| lint.span_note(inline_span, "inlining requested here"),
+                )
+            }
+        }
+    }
+
+    if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
+        codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE;
+        codegen_fn_attrs.inline = InlineAttr::Never;
+    }
+
+    // Weak lang items have the same semantics as "std internal" symbols in the
+    // sense that they're preserved through all our LTO passes and only
+    // strippable by the linker.
+    //
+    // Additionally weak lang items have predetermined symbol names.
+    if WEAK_LANG_ITEMS.iter().any(|&l| tcx.lang_items().get(l) == Some(did.to_def_id())) {
+        codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
+    }
+    if let Some((name, _)) = lang_items::extract(attrs)
+        && let Some(lang_item) = LangItem::from_name(name)
+        && let Some(link_name) = lang_item.link_name()
+    {
+        codegen_fn_attrs.export_name = Some(link_name);
+        codegen_fn_attrs.link_name = Some(link_name);
+    }
+    check_link_name_xor_ordinal(tcx, &codegen_fn_attrs, link_ordinal_span);
+
+    // Internal symbols to the standard library all have no_mangle semantics in
+    // that they have defined symbol names present in the function name. This
+    // also applies to weak symbols where they all have known symbol names.
+    if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
+        codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
+    }
+
+    // Any linkage to LLVM intrinsics for now forcibly marks them all as never
+    // unwinds since LLVM sometimes can't handle codegen which `invoke`s
+    // intrinsic functions.
+    if let Some(name) = &codegen_fn_attrs.link_name {
+        if name.as_str().starts_with("llvm.") {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
+        }
+    }
+
+    codegen_fn_attrs
+}
+
+/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
+/// applied to the method prototype.
+fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
+    if let Some(impl_item) = tcx.opt_associated_item(def_id)
+        && let ty::AssocItemContainer::ImplContainer = impl_item.container
+        && let Some(trait_item) = impl_item.trait_item_def_id
+    {
+        return tcx
+            .codegen_fn_attrs(trait_item)
+            .flags
+            .intersects(CodegenFnAttrFlags::TRACK_CALLER);
+    }
+
+    false
+}
+
+fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option<u16> {
+    use rustc_ast::{LitIntType, LitKind, MetaItemLit};
+    if !tcx.features().raw_dylib && tcx.sess.target.arch == "x86" {
+        feature_err(
+            &tcx.sess.parse_sess,
+            sym::raw_dylib,
+            attr.span,
+            "`#[link_ordinal]` is unstable on x86",
+        )
+        .emit();
+    }
+    let meta_item_list = attr.meta_item_list();
+    let meta_item_list = meta_item_list.as_deref();
+    let sole_meta_list = match meta_item_list {
+        Some([item]) => item.lit(),
+        Some(_) => {
+            tcx.sess
+                .struct_span_err(attr.span, "incorrect number of arguments to `#[link_ordinal]`")
+                .note("the attribute requires exactly one argument")
+                .emit();
+            return None;
+        }
+        _ => None,
+    };
+    if let Some(MetaItemLit { kind: LitKind::Int(ordinal, LitIntType::Unsuffixed), .. }) =
+        sole_meta_list
+    {
+        // According to the table at https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-header,
+        // the ordinal must fit into 16 bits.  Similarly, the Ordinal field in COFFShortExport (defined
+        // in llvm/include/llvm/Object/COFFImportFile.h), which we use to communicate import information
+        // to LLVM for `#[link(kind = "raw-dylib"_])`, is also defined to be uint16_t.
+        //
+        // FIXME: should we allow an ordinal of 0?  The MSVC toolchain has inconsistent support for this:
+        // both LINK.EXE and LIB.EXE signal errors and abort when given a .DEF file that specifies
+        // a zero ordinal.  However, llvm-dlltool is perfectly happy to generate an import library
+        // for such a .DEF file, and MSVC's LINK.EXE is also perfectly happy to consume an import
+        // library produced by LLVM with an ordinal of 0, and it generates an .EXE.  (I don't know yet
+        // if the resulting EXE runs, as I haven't yet built the necessary DLL -- see earlier comment
+        // about LINK.EXE failing.)
+        if *ordinal <= u16::MAX as u128 {
+            Some(*ordinal as u16)
+        } else {
+            let msg = format!("ordinal value in `link_ordinal` is too large: `{}`", &ordinal);
+            tcx.sess
+                .struct_span_err(attr.span, &msg)
+                .note("the value may not exceed `u16::MAX`")
+                .emit();
+            None
+        }
+    } else {
+        tcx.sess
+            .struct_span_err(attr.span, "illegal ordinal format in `link_ordinal`")
+            .note("an unsuffixed integer value, e.g., `1`, is expected")
+            .emit();
+        None
+    }
+}
+
+fn check_link_name_xor_ordinal(
+    tcx: TyCtxt<'_>,
+    codegen_fn_attrs: &CodegenFnAttrs,
+    inline_span: Option<Span>,
+) {
+    if codegen_fn_attrs.link_name.is_none() || codegen_fn_attrs.link_ordinal.is_none() {
+        return;
+    }
+    let msg = "cannot use `#[link_name]` with `#[link_ordinal]`";
+    if let Some(span) = inline_span {
+        tcx.sess.span_err(span, msg);
+    } else {
+        tcx.sess.err(msg);
+    }
+}
+
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers { codegen_fn_attrs, should_inherit_track_caller, ..*providers };
+}
index b004fbf85a97f8bcbefa345dd17da85503dd777b..819c2678d6c4d4ccead480763760400e56cae706 100644 (file)
@@ -235,7 +235,7 @@ fn push_debuginfo_type_name<'tcx>(
                 let projection_bounds: SmallVec<[_; 4]> = trait_data
                     .projection_bounds()
                     .map(|bound| {
-                        let ExistentialProjection { item_def_id, term, .. } =
+                        let ExistentialProjection { def_id: item_def_id, term, .. } =
                             tcx.erase_late_bound_regions(bound);
                         // FIXME(associated_const_equality): allow for consts here
                         (item_def_id, term.ty().unwrap())
@@ -411,9 +411,8 @@ fn push_debuginfo_type_name<'tcx>(
         ty::Error(_)
         | ty::Infer(_)
         | ty::Placeholder(..)
-        | ty::Projection(..)
+        | ty::Alias(..)
         | ty::Bound(..)
-        | ty::Opaque(..)
         | ty::GeneratorWitness(..) => {
             bug!(
                 "debuginfo: Trying to create type name for \
index e3b6fbf1bc7f0e1bf07f39e7f6d581d1d8046427..0620000201f0254f81ff6dd4200876324b02fd0a 100644 (file)
@@ -548,3 +548,10 @@ pub struct ArchiveBuildFailure {
 pub struct UnknownArchiveKind<'a> {
     pub kind: &'a str,
 }
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_expected_used_symbol)]
+pub struct ExpectedUsedSymbol {
+    #[primary_span]
+    pub span: Span,
+}
index def6390f6a36bcbd15d9610ceaa412eef883eeda..0e6596d4ba781bfd7a859a0329105f26a7a2ef60 100644 (file)
@@ -42,6 +42,7 @@
 
 pub mod back;
 pub mod base;
+pub mod codegen_attrs;
 pub mod common;
 pub mod coverageinfo;
 pub mod debuginfo;
@@ -180,6 +181,7 @@ pub fn provide(providers: &mut Providers) {
     crate::back::symbol_export::provide(providers);
     crate::base::provide(providers);
     crate::target_features::provide(providers);
+    crate::codegen_attrs::provide(providers);
 }
 
 pub fn provide_extern(providers: &mut ExternProviders) {
index cae46ebd2e9a7c366ab173be7226f136bb3cb05b..d96ca921f1f4d90d931a01c5945e1c9dd584728b 100644 (file)
@@ -31,8 +31,7 @@ pub fn get_fn<Bx: BuilderMethods<'a, 'tcx>>(
             let typeid =
                 bx.typeid_metadata(typeid_for_trait_ref(bx.tcx(), expect_dyn_trait_in_self(ty)));
             let vtable_byte_offset = self.0 * bx.data_layout().pointer_size.bytes();
-            let type_checked_load = bx.type_checked_load(llvtable, vtable_byte_offset, typeid);
-            let func = bx.extract_value(type_checked_load, 0);
+            let func = bx.type_checked_load(llvtable, vtable_byte_offset, typeid);
             bx.pointercast(func, llty)
         } else {
             let ptr_align = bx.tcx().data_layout.pointer_align.abi;
index 03d833fbba87cf4afbc49318c9fa55b52d8a57e3..3860138018bb14c2a69bdfe4a5cfc37bfc1e6da3 100644 (file)
@@ -289,16 +289,13 @@ fn codegen_resume_terminator(&mut self, helper: TerminatorCodegenHelper<'tcx>, b
             bx.cleanup_ret(funclet, None);
         } else {
             let slot = self.get_personality_slot(bx);
-            let lp0 = slot.project_field(bx, 0);
-            let lp0 = bx.load_operand(lp0).immediate();
-            let lp1 = slot.project_field(bx, 1);
-            let lp1 = bx.load_operand(lp1).immediate();
+            let exn0 = slot.project_field(bx, 0);
+            let exn0 = bx.load_operand(exn0).immediate();
+            let exn1 = slot.project_field(bx, 1);
+            let exn1 = bx.load_operand(exn1).immediate();
             slot.storage_dead(bx);
 
-            let mut lp = bx.const_undef(self.landing_pad_type());
-            lp = bx.insert_value(lp, lp0, 0);
-            lp = bx.insert_value(lp, lp1, 1);
-            bx.resume(lp);
+            bx.resume(exn0, exn1);
         }
     }
 
@@ -307,12 +304,10 @@ fn codegen_switchint_terminator(
         helper: TerminatorCodegenHelper<'tcx>,
         bx: &mut Bx,
         discr: &mir::Operand<'tcx>,
-        switch_ty: Ty<'tcx>,
         targets: &SwitchTargets,
     ) {
         let discr = self.codegen_operand(bx, &discr);
-        // `switch_ty` is redundant, sanity-check that.
-        assert_eq!(discr.layout.ty, switch_ty);
+        let switch_ty = discr.layout.ty;
         let mut target_iter = targets.iter();
         if target_iter.len() == 1 {
             // If there are two targets (one conditional, one fallback), emit `br` instead of
@@ -753,10 +748,13 @@ fn codegen_call_terminator(
         let (instance, mut llfn) = match *callee.layout.ty.kind() {
             ty::FnDef(def_id, substs) => (
                 Some(
-                    ty::Instance::resolve(bx.tcx(), ty::ParamEnv::reveal_all(), def_id, substs)
-                        .unwrap()
-                        .unwrap()
-                        .polymorphize(bx.tcx()),
+                    ty::Instance::expect_resolve(
+                        bx.tcx(),
+                        ty::ParamEnv::reveal_all(),
+                        def_id,
+                        substs,
+                    )
+                    .polymorphize(bx.tcx()),
                 ),
                 None,
             ),
@@ -1293,8 +1291,8 @@ fn codegen_terminator(
                 helper.funclet_br(self, bx, target, mergeable_succ())
             }
 
-            mir::TerminatorKind::SwitchInt { ref discr, switch_ty, ref targets } => {
-                self.codegen_switchint_terminator(helper, bx, discr, switch_ty, targets);
+            mir::TerminatorKind::SwitchInt { ref discr, ref targets } => {
+                self.codegen_switchint_terminator(helper, bx, discr, targets);
                 MergingSucc::False
             }
 
@@ -1635,24 +1633,17 @@ fn landing_pad_for_uncached(&mut self, bb: mir::BasicBlock) -> Bx::BasicBlock {
             let mut cleanup_bx = Bx::build(self.cx, cleanup_llbb);
 
             let llpersonality = self.cx.eh_personality();
-            let llretty = self.landing_pad_type();
-            let lp = cleanup_bx.cleanup_landing_pad(llretty, llpersonality);
+            let (exn0, exn1) = cleanup_bx.cleanup_landing_pad(llpersonality);
 
             let slot = self.get_personality_slot(&mut cleanup_bx);
             slot.storage_live(&mut cleanup_bx);
-            Pair(cleanup_bx.extract_value(lp, 0), cleanup_bx.extract_value(lp, 1))
-                .store(&mut cleanup_bx, slot);
+            Pair(exn0, exn1).store(&mut cleanup_bx, slot);
 
             cleanup_bx.br(llbb);
             cleanup_llbb
         }
     }
 
-    fn landing_pad_type(&self) -> Bx::Type {
-        let cx = self.cx;
-        cx.type_struct(&[cx.type_i8p(), cx.type_i32()], false)
-    }
-
     fn unreachable_block(&mut self) -> Bx::BasicBlock {
         self.unreachable_block.unwrap_or_else(|| {
             let llbb = Bx::append_block(self.cx, self.llfn, "unreachable");
@@ -1672,8 +1663,7 @@ fn double_unwind_guard(&mut self) -> Bx::BasicBlock {
             self.set_debug_loc(&mut bx, mir::SourceInfo::outermost(self.mir.span));
 
             let llpersonality = self.cx.eh_personality();
-            let llretty = self.landing_pad_type();
-            bx.cleanup_landing_pad(llretty, llpersonality);
+            bx.cleanup_landing_pad(llpersonality);
 
             let (fn_abi, fn_ptr) = common::build_langcall(&bx, None, LangItem::PanicNoUnwind);
             let fn_ty = bx.fn_decl_backend_type(&fn_abi);
@@ -1812,15 +1802,20 @@ fn codegen_transmute_into(
         match (src.layout.abi, dst.layout.abi) {
             (abi::Abi::Scalar(src_scalar), abi::Abi::Scalar(dst_scalar)) => {
                 // HACK(eddyb) LLVM doesn't like `bitcast`s between pointers and non-pointers.
-                if (src_scalar.primitive() == abi::Pointer)
-                    == (dst_scalar.primitive() == abi::Pointer)
-                {
+                let src_is_ptr = src_scalar.primitive() == abi::Pointer;
+                let dst_is_ptr = dst_scalar.primitive() == abi::Pointer;
+                if src_is_ptr == dst_is_ptr {
                     assert_eq!(src.layout.size, dst.layout.size);
 
                     // NOTE(eddyb) the `from_immediate` and `to_immediate_scalar`
                     // conversions allow handling `bool`s the same as `u8`s.
                     let src = bx.from_immediate(src.immediate());
-                    let src_as_dst = bx.bitcast(src, bx.backend_type(dst.layout));
+                    // LLVM also doesn't like `bitcast`s between pointers in different address spaces.
+                    let src_as_dst = if src_is_ptr {
+                        bx.pointercast(src, bx.backend_type(dst.layout))
+                    } else {
+                        bx.bitcast(src, bx.backend_type(dst.layout))
+                    };
                     Immediate(bx.to_immediate_scalar(src_as_dst, dst_scalar)).store(bx, dst);
                     return;
                 }
index 99283d3bb29f44735efd789ebbe7e0417bc0c77e..b7982b633f57fa8b38b93983d078358152820d68 100644 (file)
@@ -3,12 +3,12 @@
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::mir;
 use rustc_middle::ty;
+use rustc_middle::ty::layout::TyAndLayout;
 use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
 use rustc_session::config::DebugInfo;
 use rustc_span::symbol::{kw, Symbol};
 use rustc_span::{BytePos, Span};
-use rustc_target::abi::Abi;
-use rustc_target::abi::Size;
+use rustc_target::abi::{Abi, Size, VariantIdx};
 
 use super::operand::{OperandRef, OperandValue};
 use super::place::PlaceRef;
@@ -76,6 +76,106 @@ pub fn adjust_dbg_scope_for_span<Cx: CodegenMethods<'tcx, DIScope = S, DILocatio
     }
 }
 
+trait DebugInfoOffsetLocation<'tcx, Bx> {
+    fn deref(&self, bx: &mut Bx) -> Self;
+    fn layout(&self) -> TyAndLayout<'tcx>;
+    fn project_field(&self, bx: &mut Bx, field: mir::Field) -> Self;
+    fn downcast(&self, bx: &mut Bx, variant: VariantIdx) -> Self;
+}
+
+impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> DebugInfoOffsetLocation<'tcx, Bx>
+    for PlaceRef<'tcx, Bx::Value>
+{
+    fn deref(&self, bx: &mut Bx) -> Self {
+        bx.load_operand(*self).deref(bx.cx())
+    }
+
+    fn layout(&self) -> TyAndLayout<'tcx> {
+        self.layout
+    }
+
+    fn project_field(&self, bx: &mut Bx, field: mir::Field) -> Self {
+        PlaceRef::project_field(*self, bx, field.index())
+    }
+
+    fn downcast(&self, bx: &mut Bx, variant: VariantIdx) -> Self {
+        self.project_downcast(bx, variant)
+    }
+}
+
+impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> DebugInfoOffsetLocation<'tcx, Bx>
+    for TyAndLayout<'tcx>
+{
+    fn deref(&self, bx: &mut Bx) -> Self {
+        bx.cx().layout_of(
+            self.ty.builtin_deref(true).unwrap_or_else(|| bug!("cannot deref `{}`", self.ty)).ty,
+        )
+    }
+
+    fn layout(&self) -> TyAndLayout<'tcx> {
+        *self
+    }
+
+    fn project_field(&self, bx: &mut Bx, field: mir::Field) -> Self {
+        self.field(bx.cx(), field.index())
+    }
+
+    fn downcast(&self, bx: &mut Bx, variant: VariantIdx) -> Self {
+        self.for_variant(bx.cx(), variant)
+    }
+}
+
+struct DebugInfoOffset<T> {
+    /// Offset from the `base` used to calculate the debuginfo offset.
+    direct_offset: Size,
+    /// Each offset in this vector indicates one level of indirection from the base or previous
+    /// indirect offset plus a dereference.
+    indirect_offsets: Vec<Size>,
+    /// The final location debuginfo should point to.
+    result: T,
+}
+
+fn calculate_debuginfo_offset<
+    'a,
+    'tcx,
+    Bx: BuilderMethods<'a, 'tcx>,
+    L: DebugInfoOffsetLocation<'tcx, Bx>,
+>(
+    bx: &mut Bx,
+    local: mir::Local,
+    var: &PerLocalVarDebugInfo<'tcx, Bx::DIVariable>,
+    base: L,
+) -> DebugInfoOffset<L> {
+    let mut direct_offset = Size::ZERO;
+    // FIXME(eddyb) use smallvec here.
+    let mut indirect_offsets = vec![];
+    let mut place = base;
+
+    for elem in &var.projection[..] {
+        match *elem {
+            mir::ProjectionElem::Deref => {
+                indirect_offsets.push(Size::ZERO);
+                place = place.deref(bx);
+            }
+            mir::ProjectionElem::Field(field, _) => {
+                let offset = indirect_offsets.last_mut().unwrap_or(&mut direct_offset);
+                *offset += place.layout().fields.offset(field.index());
+                place = place.project_field(bx, field);
+            }
+            mir::ProjectionElem::Downcast(_, variant) => {
+                place = place.downcast(bx, variant);
+            }
+            _ => span_bug!(
+                var.source_info.span,
+                "unsupported var debuginfo place `{:?}`",
+                mir::Place { local, projection: var.projection },
+            ),
+        }
+    }
+
+    DebugInfoOffset { direct_offset, indirect_offsets, result: place }
+}
+
 impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     pub fn set_debug_loc(&self, bx: &mut Bx, source_info: mir::SourceInfo) {
         bx.set_span(source_info.span);
@@ -262,33 +362,8 @@ pub fn debug_introduce_local(&self, bx: &mut Bx, local: mir::Local) {
             let Some(dbg_var) = var.dbg_var else { continue };
             let Some(dbg_loc) = self.dbg_loc(var.source_info) else { continue };
 
-            let mut direct_offset = Size::ZERO;
-            // FIXME(eddyb) use smallvec here.
-            let mut indirect_offsets = vec![];
-            let mut place = base;
-
-            for elem in &var.projection[..] {
-                match *elem {
-                    mir::ProjectionElem::Deref => {
-                        indirect_offsets.push(Size::ZERO);
-                        place = bx.load_operand(place).deref(bx.cx());
-                    }
-                    mir::ProjectionElem::Field(field, _) => {
-                        let i = field.index();
-                        let offset = indirect_offsets.last_mut().unwrap_or(&mut direct_offset);
-                        *offset += place.layout.fields.offset(i);
-                        place = place.project_field(bx, i);
-                    }
-                    mir::ProjectionElem::Downcast(_, variant) => {
-                        place = place.project_downcast(bx, variant);
-                    }
-                    _ => span_bug!(
-                        var.source_info.span,
-                        "unsupported var debuginfo place `{:?}`",
-                        mir::Place { local, projection: var.projection },
-                    ),
-                }
-            }
+            let DebugInfoOffset { direct_offset, indirect_offsets, result: _ } =
+                calculate_debuginfo_offset(bx, local, &var, base.layout);
 
             // When targeting MSVC, create extra allocas for arguments instead of pointing multiple
             // dbg_var_addr() calls into the same alloca with offsets. MSVC uses CodeView records
@@ -306,6 +381,9 @@ pub fn debug_introduce_local(&self, bx: &mut Bx, local: mir::Local) {
                     || !matches!(&indirect_offsets[..], [Size::ZERO] | []));
 
             if should_create_individual_allocas {
+                let DebugInfoOffset { direct_offset: _, indirect_offsets: _, result: place } =
+                    calculate_debuginfo_offset(bx, local, &var, base);
+
                 // Create a variable which will be a pointer to the actual value
                 let ptr_ty = bx.tcx().mk_ty(ty::RawPtr(ty::TypeAndMut {
                     mutbl: mir::Mutability::Mut,
index 9ad96f7a44742f87d227114f102f388b5c110e01..23196c8cbaea1ebf4f3d9c9e9d82ab681d9aa5b6 100644 (file)
@@ -462,7 +462,7 @@ pub fn codegen_rvalue_operand(
                 assert!(bx.cx().tcx().is_static(def_id));
                 let static_ = bx.get_static(def_id);
                 let layout = bx.layout_of(bx.cx().tcx().static_ptr_ty(def_id));
-                OperandRef::from_immediate_or_packed_pair(bx, static_, layout)
+                OperandRef { val: OperandValue::Immediate(static_), layout }
             }
             mir::Rvalue::Use(ref operand) => self.codegen_operand(bx, operand),
             mir::Rvalue::Repeat(..) | mir::Rvalue::Aggregate(..) => {
index 301683e8e85449370652ce4825c666715b488e8d..0dabe96b60277e032ad0214d2260277915f6a02d 100644 (file)
@@ -1,8 +1,19 @@
+use rustc_ast::ast;
+use rustc_attr::InstructionSetAttr;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::Applicability;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::LocalDefId;
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_middle::ty::query::Providers;
+use rustc_middle::ty::TyCtxt;
+use rustc_session::parse::feature_err;
 use rustc_session::Session;
 use rustc_span::symbol::sym;
 use rustc_span::symbol::Symbol;
+use rustc_span::Span;
 
 /// Features that control behaviour of rustc, rather than the codegen.
 pub const RUSTC_SPECIFIC_FEATURES: &[&str] = &["crt-static"];
@@ -322,15 +333,148 @@ pub fn tied_target_features(sess: &Session) -> &'static [&'static [&'static str]
     }
 }
 
-pub(crate) fn provide(providers: &mut Providers) {
-    providers.supported_target_features = |tcx, cnum| {
-        assert_eq!(cnum, LOCAL_CRATE);
-        if tcx.sess.opts.actually_rustdoc {
-            // rustdoc needs to be able to document functions that use all the features, so
-            // whitelist them all
-            all_known_features().map(|(a, b)| (a.to_string(), b)).collect()
-        } else {
-            supported_target_features(tcx.sess).iter().map(|&(a, b)| (a.to_string(), b)).collect()
-        }
+pub fn from_target_feature(
+    tcx: TyCtxt<'_>,
+    attr: &ast::Attribute,
+    supported_target_features: &FxHashMap<String, Option<Symbol>>,
+    target_features: &mut Vec<Symbol>,
+) {
+    let Some(list) = attr.meta_item_list() else { return };
+    let bad_item = |span| {
+        let msg = "malformed `target_feature` attribute input";
+        let code = "enable = \"..\"";
+        tcx.sess
+            .struct_span_err(span, msg)
+            .span_suggestion(span, "must be of the form", code, Applicability::HasPlaceholders)
+            .emit();
     };
+    let rust_features = tcx.features();
+    for item in list {
+        // Only `enable = ...` is accepted in the meta-item list.
+        if !item.has_name(sym::enable) {
+            bad_item(item.span());
+            continue;
+        }
+
+        // Must be of the form `enable = "..."` (a string).
+        let Some(value) = item.value_str() else {
+            bad_item(item.span());
+            continue;
+        };
+
+        // We allow comma separation to enable multiple features.
+        target_features.extend(value.as_str().split(',').filter_map(|feature| {
+            let Some(feature_gate) = supported_target_features.get(feature) else {
+                let msg =
+                    format!("the feature named `{}` is not valid for this target", feature);
+                let mut err = tcx.sess.struct_span_err(item.span(), &msg);
+                err.span_label(
+                    item.span(),
+                    format!("`{}` is not valid for this target", feature),
+                );
+                if let Some(stripped) = feature.strip_prefix('+') {
+                    let valid = supported_target_features.contains_key(stripped);
+                    if valid {
+                        err.help("consider removing the leading `+` in the feature name");
+                    }
+                }
+                err.emit();
+                return None;
+            };
+
+            // Only allow features whose feature gates have been enabled.
+            let allowed = match feature_gate.as_ref().copied() {
+                Some(sym::arm_target_feature) => rust_features.arm_target_feature,
+                Some(sym::hexagon_target_feature) => rust_features.hexagon_target_feature,
+                Some(sym::powerpc_target_feature) => rust_features.powerpc_target_feature,
+                Some(sym::mips_target_feature) => rust_features.mips_target_feature,
+                Some(sym::riscv_target_feature) => rust_features.riscv_target_feature,
+                Some(sym::avx512_target_feature) => rust_features.avx512_target_feature,
+                Some(sym::sse4a_target_feature) => rust_features.sse4a_target_feature,
+                Some(sym::tbm_target_feature) => rust_features.tbm_target_feature,
+                Some(sym::wasm_target_feature) => rust_features.wasm_target_feature,
+                Some(sym::cmpxchg16b_target_feature) => rust_features.cmpxchg16b_target_feature,
+                Some(sym::movbe_target_feature) => rust_features.movbe_target_feature,
+                Some(sym::rtm_target_feature) => rust_features.rtm_target_feature,
+                Some(sym::f16c_target_feature) => rust_features.f16c_target_feature,
+                Some(sym::ermsb_target_feature) => rust_features.ermsb_target_feature,
+                Some(sym::bpf_target_feature) => rust_features.bpf_target_feature,
+                Some(sym::aarch64_ver_target_feature) => rust_features.aarch64_ver_target_feature,
+                Some(name) => bug!("unknown target feature gate {}", name),
+                None => true,
+            };
+            if !allowed {
+                feature_err(
+                    &tcx.sess.parse_sess,
+                    feature_gate.unwrap(),
+                    item.span(),
+                    &format!("the target feature `{}` is currently unstable", feature),
+                )
+                .emit();
+            }
+            Some(Symbol::intern(feature))
+        }));
+    }
+}
+
+/// Computes the set of target features used in a function for the purposes of
+/// inline assembly.
+fn asm_target_features<'tcx>(tcx: TyCtxt<'tcx>, did: DefId) -> &'tcx FxHashSet<Symbol> {
+    let mut target_features = tcx.sess.unstable_target_features.clone();
+    if tcx.def_kind(did).has_codegen_attrs() {
+        let attrs = tcx.codegen_fn_attrs(did);
+        target_features.extend(&attrs.target_features);
+        match attrs.instruction_set {
+            None => {}
+            Some(InstructionSetAttr::ArmA32) => {
+                target_features.remove(&sym::thumb_mode);
+            }
+            Some(InstructionSetAttr::ArmT32) => {
+                target_features.insert(sym::thumb_mode);
+            }
+        }
+    }
+
+    tcx.arena.alloc(target_features)
+}
+
+/// Checks the function annotated with `#[target_feature]` is not a safe
+/// trait method implementation, reporting an error if it is.
+pub fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_span: Span) {
+    let hir_id = tcx.hir().local_def_id_to_hir_id(id);
+    let node = tcx.hir().get(hir_id);
+    if let hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) = node {
+        let parent_id = tcx.hir().get_parent_item(hir_id);
+        let parent_item = tcx.hir().expect_item(parent_id.def_id);
+        if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = parent_item.kind {
+            tcx.sess
+                .struct_span_err(
+                    attr_span,
+                    "`#[target_feature(..)]` cannot be applied to safe trait method",
+                )
+                .span_label(attr_span, "cannot be applied to safe trait method")
+                .span_label(tcx.def_span(id), "not an `unsafe` function")
+                .emit();
+        }
+    }
+}
+
+pub(crate) fn provide(providers: &mut Providers) {
+    *providers = Providers {
+        supported_target_features: |tcx, cnum| {
+            assert_eq!(cnum, LOCAL_CRATE);
+            if tcx.sess.opts.actually_rustdoc {
+                // rustdoc needs to be able to document functions that use all the features, so
+                // whitelist them all
+                all_known_features().map(|(a, b)| (a.to_string(), b)).collect()
+            } else {
+                supported_target_features(tcx.sess)
+                    .iter()
+                    .map(|&(a, b)| (a.to_string(), b))
+                    .collect()
+            }
+        },
+        asm_target_features,
+        ..*providers
+    }
 }
index bc679a5dc87b122a4fcc7ea8111216f8b871b8f3..194768d946674e4ae28c1a1bf7abb352def8dd63 100644 (file)
@@ -271,8 +271,8 @@ fn select(
     fn set_personality_fn(&mut self, personality: Self::Value);
 
     // These are used by everyone except msvc
-    fn cleanup_landing_pad(&mut self, ty: Self::Type, pers_fn: Self::Value) -> Self::Value;
-    fn resume(&mut self, exn: Self::Value);
+    fn cleanup_landing_pad(&mut self, pers_fn: Self::Value) -> (Self::Value, Self::Value);
+    fn resume(&mut self, exn0: Self::Value, exn1: Self::Value);
 
     // These are used only by msvc
     fn cleanup_pad(&mut self, parent: Option<Self::Value>, args: &[Self::Value]) -> Self::Funclet;
index 86481d5d758d6d251c5b916163079905a8dd805f..109161ccc836865e36ea8151bc61f236125347db 100644 (file)
@@ -122,6 +122,7 @@ fn scalar_pair_element_backend_type(
 pub trait TypeMembershipMethods<'tcx>: Backend<'tcx> {
     fn set_type_metadata(&self, function: Self::Function, typeid: String);
     fn typeid_metadata(&self, typeid: String) -> Self::Value;
+    fn set_kcfi_type_metadata(&self, function: Self::Function, typeid: u32);
 }
 
 pub trait ArgAbiMethods<'tcx>: HasCodegen<'tcx> {
index e3dfd72d5f0e3ff60dba77499174cb40d443ad1a..13472cc2bfa0a5c4b8ed7ba81baa6eb3114ac9f9 100644 (file)
@@ -86,6 +86,59 @@ pub(super) fn report(&self, tcx: TyCtxtAt<'tcx>, message: &str) -> ErrorHandled
         self.report_decorated(tcx, message, |_| {})
     }
 
+    #[instrument(level = "trace", skip(self, decorate))]
+    pub(super) fn decorate(&self, err: &mut Diagnostic, decorate: impl FnOnce(&mut Diagnostic)) {
+        trace!("reporting const eval failure at {:?}", self.span);
+        // Add some more context for select error types.
+        match self.error {
+            InterpError::Unsupported(
+                UnsupportedOpInfo::ReadPointerAsBytes
+                | UnsupportedOpInfo::PartialPointerOverwrite(_)
+                | UnsupportedOpInfo::PartialPointerCopy(_),
+            ) => {
+                err.help("this code performed an operation that depends on the underlying bytes representing a pointer");
+                err.help("the absolute address of a pointer is not known at compile-time, so such operations are not supported");
+            }
+            _ => {}
+        }
+        // Add spans for the stacktrace. Don't print a single-line backtrace though.
+        if self.stacktrace.len() > 1 {
+            // Helper closure to print duplicated lines.
+            let mut flush_last_line = |last_frame, times| {
+                if let Some((line, span)) = last_frame {
+                    err.span_note(span, &line);
+                    // Don't print [... additional calls ...] if the number of lines is small
+                    if times < 3 {
+                        for _ in 0..times {
+                            err.span_note(span, &line);
+                        }
+                    } else {
+                        err.span_note(
+                            span,
+                            format!("[... {} additional calls {} ...]", times, &line),
+                        );
+                    }
+                }
+            };
+
+            let mut last_frame = None;
+            let mut times = 0;
+            for frame_info in &self.stacktrace {
+                let frame = (frame_info.to_string(), frame_info.span);
+                if last_frame.as_ref() == Some(&frame) {
+                    times += 1;
+                } else {
+                    flush_last_line(last_frame, times);
+                    last_frame = Some(frame);
+                    times = 0;
+                }
+            }
+            flush_last_line(last_frame, times);
+        }
+        // Let the caller attach any additional information it wants.
+        decorate(err);
+    }
+
     /// Create a diagnostic for this const eval error.
     ///
     /// Sets the message passed in via `message` and adds span labels with detailed error
@@ -101,88 +154,30 @@ pub(super) fn report_decorated(
         message: &str,
         decorate: impl FnOnce(&mut Diagnostic),
     ) -> ErrorHandled {
-        let finish = |err: &mut Diagnostic, span_msg: Option<String>| {
-            trace!("reporting const eval failure at {:?}", self.span);
-            if let Some(span_msg) = span_msg {
-                err.span_label(self.span, span_msg);
-            }
-            // Add some more context for select error types.
-            match self.error {
-                InterpError::Unsupported(
-                    UnsupportedOpInfo::ReadPointerAsBytes
-                    | UnsupportedOpInfo::PartialPointerOverwrite(_)
-                    | UnsupportedOpInfo::PartialPointerCopy(_),
-                ) => {
-                    err.help("this code performed an operation that depends on the underlying bytes representing a pointer");
-                    err.help("the absolute address of a pointer is not known at compile-time, so such operations are not supported");
-                }
-                _ => {}
-            }
-            // Add spans for the stacktrace. Don't print a single-line backtrace though.
-            if self.stacktrace.len() > 1 {
-                // Helper closure to print duplicated lines.
-                let mut flush_last_line = |last_frame, times| {
-                    if let Some((line, span)) = last_frame {
-                        err.span_label(span, &line);
-                        // Don't print [... additional calls ...] if the number of lines is small
-                        if times < 3 {
-                            for _ in 0..times {
-                                err.span_label(span, &line);
-                            }
-                        } else {
-                            err.span_label(
-                                span,
-                                format!("[... {} additional calls {} ...]", times, &line),
-                            );
-                        }
-                    }
-                };
-
-                let mut last_frame = None;
-                let mut times = 0;
-                for frame_info in &self.stacktrace {
-                    let frame = (frame_info.to_string(), frame_info.span);
-                    if last_frame.as_ref() == Some(&frame) {
-                        times += 1;
-                    } else {
-                        flush_last_line(last_frame, times);
-                        last_frame = Some(frame);
-                        times = 0;
-                    }
-                }
-                flush_last_line(last_frame, times);
-            }
-            // Let the caller attach any additional information it wants.
-            decorate(err);
-        };
-
         debug!("self.error: {:?}", self.error);
         // Special handling for certain errors
         match &self.error {
             // Don't emit a new diagnostic for these errors
             err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => {
-                return ErrorHandled::TooGeneric;
-            }
-            err_inval!(AlreadyReported(error_reported)) => {
-                return ErrorHandled::Reported(*error_reported);
+                ErrorHandled::TooGeneric
             }
+            err_inval!(AlreadyReported(error_reported)) => ErrorHandled::Reported(*error_reported),
             err_inval!(Layout(LayoutError::SizeOverflow(_))) => {
                 // We must *always* hard error on these, even if the caller wants just a lint.
                 // The `message` makes little sense here, this is a more serious error than the
                 // caller thinks anyway.
                 // See <https://github.com/rust-lang/rust/pull/63152>.
                 let mut err = struct_error(tcx, &self.error.to_string());
-                finish(&mut err, None);
-                return ErrorHandled::Reported(err.emit());
+                self.decorate(&mut err, decorate);
+                ErrorHandled::Reported(err.emit())
             }
-            _ => {}
-        };
-
-        let err_msg = self.error.to_string();
-
-        // Report as hard error.
-        let mut err = struct_error(tcx, message);
-        finish(&mut err, Some(err_msg));
-        ErrorHandled::Reported(err.emit())
+            _ => {
+                // Report as hard error.
+                let mut err = struct_error(tcx, message);
+                err.span_label(self.span, self.error.to_string());
+                self.decorate(&mut err, decorate);
+                ErrorHandled::Reported(err.emit())
+            }
+        }
     }
 }
index c27790d8887a377a67a59da57daa99ca84f5f9b3..18e01567ca35e44888e52e19abd6bb07edca0d0e 100644 (file)
@@ -1,5 +1,5 @@
+use crate::const_eval::CheckAlignment;
 use std::borrow::Cow;
-use std::convert::TryInto;
 
 use either::{Left, Right};
 
@@ -77,7 +77,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
             None => InternKind::Constant,
         }
     };
-    ecx.machine.check_alignment = false; // interning doesn't need to respect alignment
+    ecx.machine.check_alignment = CheckAlignment::No; // interning doesn't need to respect alignment
     intern_const_alloc_recursive(ecx, intern_kind, &ret)?;
     // we leave alignment checks off, since this `ecx` will not be used for further evaluation anyway
 
@@ -103,11 +103,7 @@ pub(super) fn mk_eval_cx<'mir, 'tcx>(
         tcx,
         root_span,
         param_env,
-        CompileTimeInterpreter::new(
-            tcx.const_eval_limit(),
-            can_access_statics,
-            /*check_alignment:*/ false,
-        ),
+        CompileTimeInterpreter::new(tcx.const_eval_limit(), can_access_statics, CheckAlignment::No),
     )
 }
 
@@ -312,7 +308,11 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
         CompileTimeInterpreter::new(
             tcx.const_eval_limit(),
             /*can_access_statics:*/ is_static,
-            /*check_alignment:*/ tcx.sess.opts.unstable_opts.extra_const_ub_checks,
+            if tcx.sess.opts.unstable_opts.extra_const_ub_checks {
+                CheckAlignment::Error
+            } else {
+                CheckAlignment::FutureIncompat
+            },
         ),
     );
 
index 3dfded2d930a052c305859ed257536285303eda8..e006a62feeabd12bc568da7c5c42e76bdde1cc2f 100644 (file)
@@ -1,9 +1,10 @@
 use rustc_hir::def::DefKind;
-use rustc_hir::LangItem;
+use rustc_hir::{LangItem, CRATE_HIR_ID};
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::PointerArithmetic;
 use rustc_middle::ty::layout::FnAbiOf;
 use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_session::lint::builtin::INVALID_ALIGNMENT;
 use std::borrow::Borrow;
 use std::hash::Hash;
 use std::ops::ControlFlow;
@@ -47,14 +48,34 @@ pub struct CompileTimeInterpreter<'mir, 'tcx> {
     pub(super) can_access_statics: bool,
 
     /// Whether to check alignment during evaluation.
-    pub(super) check_alignment: bool,
+    pub(super) check_alignment: CheckAlignment,
+}
+
+#[derive(Copy, Clone)]
+pub enum CheckAlignment {
+    /// Ignore alignment when following relocations.
+    /// This is mainly used in interning.
+    No,
+    /// Hard error when dereferencing a misaligned pointer.
+    Error,
+    /// Emit a future incompat lint when dereferencing a misaligned pointer.
+    FutureIncompat,
+}
+
+impl CheckAlignment {
+    pub fn should_check(&self) -> bool {
+        match self {
+            CheckAlignment::No => false,
+            CheckAlignment::Error | CheckAlignment::FutureIncompat => true,
+        }
+    }
 }
 
 impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> {
     pub(crate) fn new(
         const_eval_limit: Limit,
         can_access_statics: bool,
-        check_alignment: bool,
+        check_alignment: CheckAlignment,
     ) -> Self {
         CompileTimeInterpreter {
             steps_remaining: const_eval_limit.0,
@@ -309,7 +330,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
     const PANIC_ON_ALLOC_FAIL: bool = false; // will be raised as a proper error
 
     #[inline(always)]
-    fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
+    fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> CheckAlignment {
         ecx.machine.check_alignment
     }
 
@@ -318,6 +339,36 @@ fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
         ecx.tcx.sess.opts.unstable_opts.extra_const_ub_checks
     }
 
+    fn alignment_check_failed(
+        ecx: &InterpCx<'mir, 'tcx, Self>,
+        has: Align,
+        required: Align,
+        check: CheckAlignment,
+    ) -> InterpResult<'tcx, ()> {
+        let err = err_ub!(AlignmentCheckFailed { has, required }).into();
+        match check {
+            CheckAlignment::Error => Err(err),
+            CheckAlignment::No => span_bug!(
+                ecx.cur_span(),
+                "`alignment_check_failed` called when no alignment check requested"
+            ),
+            CheckAlignment::FutureIncompat => {
+                let err = ConstEvalErr::new(ecx, err, None);
+                ecx.tcx.struct_span_lint_hir(
+                    INVALID_ALIGNMENT,
+                    ecx.stack().iter().find_map(|frame| frame.lint_root()).unwrap_or(CRATE_HIR_ID),
+                    err.span,
+                    err.error.to_string(),
+                    |db| {
+                        err.decorate(db, |_| {});
+                        db
+                    },
+                );
+                Ok(())
+            }
+        }
+    }
+
     fn load_mir(
         ecx: &InterpCx<'mir, 'tcx, Self>,
         instance: ty::InstanceDef<'tcx>,
index f4da11883957a73f0376d35c2202c659a2d1a8ab..498c008738793912e46e0b25afca0b8180a07d34 100644 (file)
@@ -142,12 +142,11 @@ pub(crate) fn const_to_valtree_inner<'tcx>(
         | ty::Foreign(..)
         | ty::Infer(ty::FreshIntTy(_))
         | ty::Infer(ty::FreshFloatTy(_))
-        | ty::Projection(..)
+        // FIXME(oli-obk): we could look behind opaque types
+        | ty::Alias(..)
         | ty::Param(_)
         | ty::Bound(..)
         | ty::Placeholder(..)
-        // FIXME(oli-obk): we could look behind opaque types
-        | ty::Opaque(..)
         | ty::Infer(_)
         // FIXME(oli-obk): we can probably encode closures just like structs
         | ty::Closure(..)
@@ -307,11 +306,10 @@ pub fn valtree_to_const_value<'tcx>(
         | ty::Foreign(..)
         | ty::Infer(ty::FreshIntTy(_))
         | ty::Infer(ty::FreshFloatTy(_))
-        | ty::Projection(..)
+        | ty::Alias(..)
         | ty::Param(_)
         | ty::Bound(..)
         | ty::Placeholder(..)
-        | ty::Opaque(..)
         | ty::Infer(_)
         | ty::Closure(..)
         | ty::Generator(..)
index 269ae15d4974547f929544764313ce900982ecc0..986b6d655300168046dad275e318667b1adff014 100644 (file)
@@ -1,5 +1,4 @@
 use std::assert_matches::assert_matches;
-use std::convert::TryFrom;
 
 use rustc_apfloat::ieee::{Double, Single};
 use rustc_apfloat::{Float, FloatConvert};
@@ -333,7 +332,7 @@ fn unsize_into_ptr(
                     Immediate::new_slice(ptr, length.eval_usize(*self.tcx, self.param_env), self);
                 self.write_immediate(val, dest)
             }
-            (&ty::Dynamic(ref data_a, ..), &ty::Dynamic(ref data_b, ..)) => {
+            (ty::Dynamic(data_a, ..), ty::Dynamic(data_b, ..)) => {
                 let val = self.read_immediate(src)?;
                 if data_a.principal() == data_b.principal() {
                     // A NOP cast that doesn't actually change anything, should be allowed even with mismatching vtables.
index e17d3e516a64fb72ae438726e275956340bb2e24..f551b5c29114d9984fcf108ceb1b9e12628db580 100644 (file)
@@ -17,7 +17,7 @@
 };
 use rustc_mir_dataflow::storage::always_storage_live_locals;
 use rustc_session::Limit;
-use rustc_span::{Pos, Span};
+use rustc_span::Span;
 use rustc_target::abi::{call::FnAbi, Align, HasDataLayout, Size, TargetDataLayout};
 
 use super::{
@@ -248,6 +248,15 @@ pub fn current_span(&self) -> Span {
             Right(span) => span,
         }
     }
+
+    pub fn lint_root(&self) -> Option<hir::HirId> {
+        self.current_source_info().and_then(|source_info| {
+            match &self.body.source_scopes[source_info.scope].local_data {
+                mir::ClearCrossCrate::Set(data) => Some(data.lint_root),
+                mir::ClearCrossCrate::Clear => None,
+            }
+        })
+    }
 }
 
 impl<'tcx> fmt::Display for FrameInfo<'tcx> {
@@ -256,25 +265,13 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             if tcx.def_key(self.instance.def_id()).disambiguated_data.data
                 == DefPathData::ClosureExpr
             {
-                write!(f, "inside closure")?;
+                write!(f, "inside closure")
             } else {
                 // Note: this triggers a `good_path_bug` state, which means that if we ever get here
                 // we must emit a diagnostic. We should never display a `FrameInfo` unless we
                 // actually want to emit a warning or error to the user.
-                write!(f, "inside `{}`", self.instance)?;
+                write!(f, "inside `{}`", self.instance)
             }
-            if !self.span.is_dummy() {
-                let sm = tcx.sess.source_map();
-                let lo = sm.lookup_char_pos(self.span.lo());
-                write!(
-                    f,
-                    " at {}:{}:{}",
-                    sm.filename_for_diagnostics(&lo.file.name),
-                    lo.line,
-                    lo.col.to_usize() + 1
-                )?;
-            }
-            Ok(())
         })
     }
 }
@@ -966,12 +963,7 @@ pub fn generate_stacktrace_from_stack(
         // This deliberately does *not* honor `requires_caller_location` since it is used for much
         // more than just panics.
         for frame in stack.iter().rev() {
-            let lint_root = frame.current_source_info().and_then(|source_info| {
-                match &frame.body.source_scopes[source_info.scope].local_data {
-                    mir::ClearCrossCrate::Set(data) => Some(data.lint_root),
-                    mir::ClearCrossCrate::Clear => None,
-                }
-            });
+            let lint_root = frame.lint_root();
             let span = frame.current_span();
 
             frames.push(FrameInfo { span, instance: frame.instance, lint_root });
index 7940efcd2b11f1517a22631f0d5a4d77616ece7d..9b56757eb3951a4ee201a538268f286f7b12edce 100644 (file)
@@ -2,8 +2,6 @@
 //! looking at their MIR. Intrinsics/functions supported here are shared by CTFE
 //! and miri.
 
-use std::convert::TryFrom;
-
 use rustc_hir::def_id::DefId;
 use rustc_middle::mir::{
     self,
@@ -84,11 +82,9 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
             ty::Adt(ref adt, _) => {
                 ConstValue::from_machine_usize(adt.variants().len() as u64, &tcx)
             }
-            ty::Projection(_)
-            | ty::Opaque(_, _)
-            | ty::Param(_)
-            | ty::Placeholder(_)
-            | ty::Infer(_) => throw_inval!(TooGeneric),
+            ty::Alias(..) | ty::Param(_) | ty::Placeholder(_) | ty::Infer(_) => {
+                throw_inval!(TooGeneric)
+            }
             ty::Bound(_, _) => bug!("bound ty during ctfe"),
             ty::Bool
             | ty::Char
index 7d94a22c43d71e467d3c8eeed2963ebc0dbcbff4..77c7b4bacb8c8a96d68b42704478166e754d0772 100644 (file)
@@ -1,5 +1,3 @@
-use std::convert::TryFrom;
-
 use rustc_ast::Mutability;
 use rustc_hir::lang_items::LangItem;
 use rustc_middle::mir::TerminatorKind;
index 88d25be6bd861d66f8a0788b5a9243ebdf7b105b..1d4ef20d0651f7bd11d7cb466f0290d375ff27d8 100644 (file)
 use rustc_middle::mir;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::def_id::DefId;
-use rustc_target::abi::Size;
+use rustc_target::abi::{Align, Size};
 use rustc_target::spec::abi::Abi as CallAbi;
 
+use crate::const_eval::CheckAlignment;
+
 use super::{
     AllocId, AllocRange, Allocation, ConstAllocation, Frame, ImmTy, InterpCx, InterpResult,
     MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, StackPopUnwind,
@@ -122,7 +124,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
     const PANIC_ON_ALLOC_FAIL: bool;
 
     /// Whether memory accesses should be alignment-checked.
-    fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
+    fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> CheckAlignment;
 
     /// Whether, when checking alignment, we should look at the actual address and thus support
     /// custom alignment logic based on whatever the integer address happens to be.
@@ -130,6 +132,13 @@ pub trait Machine<'mir, 'tcx>: Sized {
     /// If this returns true, Provenance::OFFSET_IS_ADDR must be true.
     fn use_addr_for_alignment_check(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
 
+    fn alignment_check_failed(
+        ecx: &InterpCx<'mir, 'tcx, Self>,
+        has: Align,
+        required: Align,
+        check: CheckAlignment,
+    ) -> InterpResult<'tcx, ()>;
+
     /// Whether to enforce the validity invariant
     fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
 
@@ -373,9 +382,21 @@ fn before_memory_deallocation(
         Ok(())
     }
 
-    /// Executes a retagging operation.
+    /// Executes a retagging operation for a single pointer.
+    /// Returns the possibly adjusted pointer.
+    #[inline]
+    fn retag_ptr_value(
+        _ecx: &mut InterpCx<'mir, 'tcx, Self>,
+        _kind: mir::RetagKind,
+        val: &ImmTy<'tcx, Self::Provenance>,
+    ) -> InterpResult<'tcx, ImmTy<'tcx, Self::Provenance>> {
+        Ok(val.clone())
+    }
+
+    /// Executes a retagging operation on a compound value.
+    /// Replaces all pointers stored in the given place.
     #[inline]
-    fn retag(
+    fn retag_place_contents(
         _ecx: &mut InterpCx<'mir, 'tcx, Self>,
         _kind: mir::RetagKind,
         _place: &PlaceTy<'tcx, Self::Provenance>,
index 528c1cb06c0ebadf1e2ca0cb324cc51bd8c0e794..5b1ac6b2f65e29f7bc7a726d3044a6fd5cb95654 100644 (file)
@@ -18,6 +18,8 @@
 use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TyCtxt};
 use rustc_target::abi::{Align, HasDataLayout, Size};
 
+use crate::const_eval::CheckAlignment;
+
 use super::{
     alloc_range, AllocId, AllocMap, AllocRange, Allocation, CheckInAllocMsg, GlobalAlloc, InterpCx,
     InterpResult, Machine, MayLeak, Pointer, PointerArithmetic, Provenance, Scalar,
@@ -349,11 +351,11 @@ fn get_ptr_access(
         size: Size,
         align: Align,
     ) -> InterpResult<'tcx, Option<(AllocId, Size, M::ProvenanceExtra)>> {
-        let align = M::enforce_alignment(&self).then_some(align);
         self.check_and_deref_ptr(
             ptr,
             size,
             align,
+            M::enforce_alignment(self),
             CheckInAllocMsg::MemoryAccessTest,
             |alloc_id, offset, prov| {
                 let (size, align) = self.get_live_alloc_size_and_align(alloc_id)?;
@@ -373,10 +375,17 @@ pub fn check_ptr_access_align(
         align: Align,
         msg: CheckInAllocMsg,
     ) -> InterpResult<'tcx> {
-        self.check_and_deref_ptr(ptr, size, Some(align), msg, |alloc_id, _, _| {
-            let (size, align) = self.get_live_alloc_size_and_align(alloc_id)?;
-            Ok((size, align, ()))
-        })?;
+        self.check_and_deref_ptr(
+            ptr,
+            size,
+            align,
+            CheckAlignment::Error,
+            msg,
+            |alloc_id, _, _| {
+                let (size, align) = self.get_live_alloc_size_and_align(alloc_id)?;
+                Ok((size, align, ()))
+            },
+        )?;
         Ok(())
     }
 
@@ -388,7 +397,8 @@ fn check_and_deref_ptr<T>(
         &self,
         ptr: Pointer<Option<M::Provenance>>,
         size: Size,
-        align: Option<Align>,
+        align: Align,
+        check: CheckAlignment,
         msg: CheckInAllocMsg,
         alloc_size: impl FnOnce(
             AllocId,
@@ -396,19 +406,6 @@ fn check_and_deref_ptr<T>(
             M::ProvenanceExtra,
         ) -> InterpResult<'tcx, (Size, Align, T)>,
     ) -> InterpResult<'tcx, Option<T>> {
-        fn check_offset_align<'tcx>(offset: u64, align: Align) -> InterpResult<'tcx> {
-            if offset % align.bytes() == 0 {
-                Ok(())
-            } else {
-                // The biggest power of two through which `offset` is divisible.
-                let offset_pow2 = 1 << offset.trailing_zeros();
-                throw_ub!(AlignmentCheckFailed {
-                    has: Align::from_bytes(offset_pow2).unwrap(),
-                    required: align,
-                })
-            }
-        }
-
         Ok(match self.ptr_try_get_alloc_id(ptr) {
             Err(addr) => {
                 // We couldn't get a proper allocation. This is only okay if the access size is 0,
@@ -417,8 +414,8 @@ fn check_offset_align<'tcx>(offset: u64, align: Align) -> InterpResult<'tcx> {
                     throw_ub!(DanglingIntPointer(addr, msg));
                 }
                 // Must be aligned.
-                if let Some(align) = align {
-                    check_offset_align(addr, align)?;
+                if check.should_check() {
+                    self.check_offset_align(addr, align, check)?;
                 }
                 None
             }
@@ -441,16 +438,16 @@ fn check_offset_align<'tcx>(offset: u64, align: Align) -> InterpResult<'tcx> {
                 }
                 // Test align. Check this last; if both bounds and alignment are violated
                 // we want the error to be about the bounds.
-                if let Some(align) = align {
+                if check.should_check() {
                     if M::use_addr_for_alignment_check(self) {
                         // `use_addr_for_alignment_check` can only be true if `OFFSET_IS_ADDR` is true.
-                        check_offset_align(ptr.addr().bytes(), align)?;
+                        self.check_offset_align(ptr.addr().bytes(), align, check)?;
                     } else {
                         // Check allocation alignment and offset alignment.
                         if alloc_align.bytes() < align.bytes() {
-                            throw_ub!(AlignmentCheckFailed { has: alloc_align, required: align });
+                            M::alignment_check_failed(self, alloc_align, align, check)?;
                         }
-                        check_offset_align(offset.bytes(), align)?;
+                        self.check_offset_align(offset.bytes(), align, check)?;
                     }
                 }
 
@@ -460,6 +457,21 @@ fn check_offset_align<'tcx>(offset: u64, align: Align) -> InterpResult<'tcx> {
             }
         })
     }
+
+    fn check_offset_align(
+        &self,
+        offset: u64,
+        align: Align,
+        check: CheckAlignment,
+    ) -> InterpResult<'tcx> {
+        if offset % align.bytes() == 0 {
+            Ok(())
+        } else {
+            // The biggest power of two through which `offset` is divisible.
+            let offset_pow2 = 1 << offset.trailing_zeros();
+            M::alignment_check_failed(self, Align::from_bytes(offset_pow2).unwrap(), align, check)
+        }
+    }
 }
 
 /// Allocation accessors
@@ -560,11 +572,11 @@ pub fn get_ptr_alloc<'a>(
         size: Size,
         align: Align,
     ) -> InterpResult<'tcx, Option<AllocRef<'a, 'tcx, M::Provenance, M::AllocExtra>>> {
-        let align = M::enforce_alignment(self).then_some(align);
         let ptr_and_alloc = self.check_and_deref_ptr(
             ptr,
             size,
             align,
+            M::enforce_alignment(self),
             CheckInAllocMsg::MemoryAccessTest,
             |alloc_id, offset, prov| {
                 let alloc = self.get_alloc_raw(alloc_id)?;
index 221e359d24ab8d517a1d98ed60de780bdea9c468..f9e3a2bdc06fe528dcb3bcfa7ef980a2cf3a2d41 100644 (file)
@@ -39,7 +39,7 @@ pub enum Immediate<Prov: Provenance = AllocId> {
 impl<Prov: Provenance> From<Scalar<Prov>> for Immediate<Prov> {
     #[inline(always)]
     fn from(val: Scalar<Prov>) -> Self {
-        Immediate::Scalar(val.into())
+        Immediate::Scalar(val)
     }
 }
 
@@ -53,7 +53,7 @@ pub fn from_maybe_pointer(p: Pointer<Option<Prov>>, cx: &impl HasDataLayout) ->
     }
 
     pub fn new_slice(val: Scalar<Prov>, len: u64, cx: &impl HasDataLayout) -> Self {
-        Immediate::ScalarPair(val.into(), Scalar::from_machine_usize(len, cx).into())
+        Immediate::ScalarPair(val, Scalar::from_machine_usize(len, cx))
     }
 
     pub fn new_dyn_trait(
@@ -61,7 +61,7 @@ pub fn new_dyn_trait(
         vtable: Pointer<Option<Prov>>,
         cx: &impl HasDataLayout,
     ) -> Self {
-        Immediate::ScalarPair(val.into(), Scalar::from_maybe_pointer(vtable, cx))
+        Immediate::ScalarPair(val, Scalar::from_maybe_pointer(vtable, cx))
     }
 
     #[inline]
@@ -341,10 +341,7 @@ fn read_immediate_from_mplace_raw(
                     alloc_range(b_offset, b_size),
                     /*read_provenance*/ b.is_ptr(),
                 )?;
-                Some(ImmTy {
-                    imm: Immediate::ScalarPair(a_val.into(), b_val.into()),
-                    layout: mplace.layout,
-                })
+                Some(ImmTy { imm: Immediate::ScalarPair(a_val, b_val), layout: mplace.layout })
             }
             _ => {
                 // Neither a scalar nor scalar pair.
index 1f1d0665139d093f005f9c0a81edd2e6d0c7c19a..e8ff70e3a4095075ebe765e16a18549decfd866d 100644 (file)
@@ -1,5 +1,3 @@
-use std::convert::TryFrom;
-
 use rustc_apfloat::Float;
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::{InterpResult, Scalar};
@@ -38,7 +36,7 @@ pub fn binop_with_overflow(
         if let Abi::ScalarPair(..) = dest.layout.abi {
             // We can use the optimized path and avoid `place_field` (which might do
             // `force_allocation`).
-            let pair = Immediate::ScalarPair(val.into(), Scalar::from_bool(overflowed).into());
+            let pair = Immediate::ScalarPair(val, Scalar::from_bool(overflowed));
             self.write_immediate(pair, dest)?;
         } else {
             assert!(self.tcx.sess.opts.unstable_opts.randomize_layout);
index c47cfe8bb69fd05831734e1f42cf16e3781d7049..97a73e98abcbca9d563027620fc8a74630014606 100644 (file)
@@ -141,7 +141,7 @@ pub fn to_ref(self, cx: &impl HasDataLayout) -> Immediate<Prov> {
         match self.meta {
             MemPlaceMeta::None => Immediate::from(Scalar::from_maybe_pointer(self.ptr, cx)),
             MemPlaceMeta::Meta(meta) => {
-                Immediate::ScalarPair(Scalar::from_maybe_pointer(self.ptr, cx).into(), meta.into())
+                Immediate::ScalarPair(Scalar::from_maybe_pointer(self.ptr, cx), meta)
             }
         }
     }
@@ -364,13 +364,8 @@ pub fn check_mplace(&self, mplace: MPlaceTy<'tcx, M::Provenance>) -> InterpResul
             .size_and_align_of_mplace(&mplace)?
             .unwrap_or((mplace.layout.size, mplace.layout.align.abi));
         assert!(mplace.align <= align, "dynamic alignment less strict than static one?");
-        let align = M::enforce_alignment(self).then_some(align);
-        self.check_ptr_access_align(
-            mplace.ptr,
-            size,
-            align.unwrap_or(Align::ONE),
-            CheckInAllocMsg::DerefTest,
-        )?;
+        let align = if M::enforce_alignment(self).should_check() { align } else { Align::ONE };
+        self.check_ptr_access_align(mplace.ptr, size, align, CheckInAllocMsg::DerefTest)?;
         Ok(())
     }
 
index 60578246eedcccb01cf885385d53caa5839602f7..81b44a49484d0a72e213d8a32b510e784b7938b1 100644 (file)
@@ -8,7 +8,7 @@
 use rustc_middle::mir::interpret::{InterpResult, Scalar};
 use rustc_middle::ty::layout::LayoutOf;
 
-use super::{InterpCx, Machine};
+use super::{ImmTy, InterpCx, Machine};
 
 /// Classify whether an operator is "left-homogeneous", i.e., the LHS has the
 /// same type as the result.
@@ -108,7 +108,7 @@ pub fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> InterpResult<'tcx> {
             // Stacked Borrows.
             Retag(kind, place) => {
                 let dest = self.eval_place(**place)?;
-                M::retag(self, *kind, &dest)?;
+                M::retag_place_contents(self, *kind, &dest)?;
             }
 
             Intrinsic(box ref intrinsic) => self.emulate_nondiverging_intrinsic(intrinsic)?,
@@ -247,10 +247,41 @@ pub fn eval_rvalue_into_place(
                 self.write_scalar(Scalar::from_machine_usize(len, self), &dest)?;
             }
 
-            AddressOf(_, place) | Ref(_, _, place) => {
+            Ref(_, borrow_kind, place) => {
                 let src = self.eval_place(place)?;
                 let place = self.force_allocation(&src)?;
-                self.write_immediate(place.to_ref(self), &dest)?;
+                let val = ImmTy::from_immediate(place.to_ref(self), dest.layout);
+                // A fresh reference was created, make sure it gets retagged.
+                let val = M::retag_ptr_value(
+                    self,
+                    if borrow_kind.allows_two_phase_borrow() {
+                        mir::RetagKind::TwoPhase
+                    } else {
+                        mir::RetagKind::Default
+                    },
+                    &val,
+                )?;
+                self.write_immediate(*val, &dest)?;
+            }
+
+            AddressOf(_, place) => {
+                // Figure out whether this is an addr_of of an already raw place.
+                let place_base_raw = if place.has_deref() {
+                    let ty = self.frame().body.local_decls[place.local].ty;
+                    ty.is_unsafe_ptr()
+                } else {
+                    // Not a deref, and thus not raw.
+                    false
+                };
+
+                let src = self.eval_place(place)?;
+                let place = self.force_allocation(&src)?;
+                let mut val = ImmTy::from_immediate(place.to_ref(self), dest.layout);
+                if !place_base_raw {
+                    // If this was not already raw, it needs retagging.
+                    val = M::retag_ptr_value(self, mir::RetagKind::Raw, &val)?;
+                }
+                self.write_immediate(*val, &dest)?;
             }
 
             NullaryOp(null_op, ty) => {
index 57e40e168fa48e0b281541ee9beaef7ce7293f95..0e7ffcdffc97aae54f0b020282f3b61aa9dfa701 100644 (file)
@@ -29,10 +29,9 @@ pub(super) fn eval_terminator(
 
             Goto { target } => self.go_to_block(target),
 
-            SwitchInt { ref discr, ref targets, switch_ty } => {
+            SwitchInt { ref discr, ref targets } => {
                 let discr = self.read_immediate(&self.eval_operand(discr, None)?)?;
                 trace!("SwitchInt({:?})", *discr);
-                assert_eq!(discr.layout.ty, switch_ty);
 
                 // Branch to the `otherwise` case by default, if no match is found.
                 let mut target_block = targets.otherwise();
index 2bc521d5bbe0b8bca7c3ea812ee8f8d9bd38c0ba..e4f716c31945c68aacdfce6490c13a7116824508 100644 (file)
@@ -1,6 +1,5 @@
 use rustc_middle::mir::interpret::InterpResult;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
-use std::convert::TryInto;
 use std::ops::ControlFlow;
 
 /// Checks whether a type contains generic parameters which require substitution.
index 0e85c7d11bce560b3af9d507a25f23b2e0aa0eaf..f905d3fb479a0b7e343c7dd187239f94f3543705 100644 (file)
@@ -4,7 +4,6 @@
 //! That's useful because it means other passes (e.g. promotion) can rely on `const`s
 //! to be const-safe.
 
-use std::convert::TryFrom;
 use std::fmt::{Display, Write};
 use std::num::NonZeroUsize;
 
@@ -602,8 +601,7 @@ fn try_visit_primitive(
             | ty::Placeholder(..)
             | ty::Bound(..)
             | ty::Param(..)
-            | ty::Opaque(..)
-            | ty::Projection(..)
+            | ty::Alias(..)
             | ty::GeneratorWitness(..) => bug!("Encountered invalid type {:?}", ty),
         }
     }
index bf700d3122465c584b1d15efc54a71ffe1ab88e1..bb897b95b2c53cd1122663b41945764ccd354960 100644 (file)
@@ -2,6 +2,7 @@
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_index::bit_set::BitSet;
+use rustc_infer::traits::Reveal;
 use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::mir::visit::NonUseContext::VarDebugInfo;
 use rustc_middle::mir::visit::{PlaceContext, Visitor};
@@ -44,11 +45,14 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             return;
         }
         let def_id = body.source.def_id();
-        let param_env = tcx.param_env(def_id);
         let mir_phase = self.mir_phase;
+        let param_env = match mir_phase.reveal() {
+            Reveal::UserFacing => tcx.param_env(def_id),
+            Reveal::All => tcx.param_env_reveal_all_normalized(def_id),
+        };
 
         let always_live_locals = always_storage_live_locals(body);
-        let storage_liveness = MaybeStorageLive::new(always_live_locals)
+        let storage_liveness = MaybeStorageLive::new(std::borrow::Cow::Owned(always_live_locals))
             .into_engine(tcx, body)
             .iterate_to_fixpoint()
             .into_results_cursor(body);
@@ -75,7 +79,7 @@ struct TypeChecker<'a, 'tcx> {
     param_env: ParamEnv<'tcx>,
     mir_phase: MirPhase,
     reachable_blocks: BitSet<BasicBlock>,
-    storage_liveness: ResultsCursor<'a, 'tcx, MaybeStorageLive>,
+    storage_liveness: ResultsCursor<'a, 'tcx, MaybeStorageLive<'static>>,
     place_cache: Vec<PlaceRef<'tcx>>,
     value_cache: Vec<u128>,
 }
@@ -237,7 +241,7 @@ fn visit_projection_elem(
                 };
 
                 let kind = match parent_ty.ty.kind() {
-                    &ty::Opaque(def_id, substs) => {
+                    &ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
                         self.tcx.bound_type_of(def_id).subst(self.tcx, substs).kind()
                     }
                     kind => kind,
@@ -648,7 +652,7 @@ fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
                     self.fail(location, "`SetDiscriminant`is not allowed until deaggregation");
                 }
                 let pty = place.ty(&self.body.local_decls, self.tcx).ty.kind();
-                if !matches!(pty, ty::Adt(..) | ty::Generator(..) | ty::Opaque(..)) {
+                if !matches!(pty, ty::Adt(..) | ty::Generator(..) | ty::Alias(ty::Opaque, ..)) {
                     self.fail(
                         location,
                         format!(
@@ -682,17 +686,8 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
             TerminatorKind::Goto { target } => {
                 self.check_edge(location, *target, EdgeKind::Normal);
             }
-            TerminatorKind::SwitchInt { targets, switch_ty, discr } => {
-                let ty = discr.ty(&self.body.local_decls, self.tcx);
-                if ty != *switch_ty {
-                    self.fail(
-                        location,
-                        format!(
-                            "encountered `SwitchInt` terminator with type mismatch: {:?} != {:?}",
-                            ty, switch_ty,
-                        ),
-                    );
-                }
+            TerminatorKind::SwitchInt { targets, discr } => {
+                let switch_ty = discr.ty(&self.body.local_decls, self.tcx);
 
                 let target_width = self.tcx.sess.target.pointer_width;
 
index c43de3368c62fd190ec6e242e287803f9a2b1d78..10783c5ed1d1cd7389fd67f5aa72e83f74763108 100644 (file)
@@ -3,7 +3,6 @@
 use rustc_middle::ty::{Ty, TyCtxt};
 use rustc_target::abi::VariantIdx;
 
-use std::convert::TryFrom;
 use std::iter::TrustedLen;
 
 /// Expand `lhs = Rvalue::Aggregate(kind, operands)` into assignments to the fields.
index b38a6c551388e473b7771d0e03f805f0db0b173b..38d9b044981cd723687c8962d06345fc226aa39a 100644 (file)
@@ -5,7 +5,7 @@
 use rustc_hir::def_id::DefId;
 use rustc_hir::{lang_items, LangItem};
 use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, AssocItemContainer, DefIdTree, Instance, ParamEnv, Ty, TyCtxt};
+use rustc_middle::ty::{AssocItemContainer, Instance, ParamEnv, Ty, TyCtxt};
 use rustc_span::symbol::Ident;
 use rustc_span::{sym, DesugaringKind, Span};
 
@@ -39,9 +39,7 @@ pub enum CallKind<'tcx> {
     Normal {
         self_arg: Option<Ident>,
         desugaring: Option<(CallDesugaringKind, Ty<'tcx>)>,
-        /// Whether the self type of the method call has an `.as_ref()` method.
-        /// Used for better diagnostics.
-        is_option_or_result: bool,
+        method_did: DefId,
     },
     /// A call to `Fn(..)::call(..)`, desugared from `my_closure(a, b, c)`
     FnCall { fn_trait_id: DefId, self_ty: Ty<'tcx> },
@@ -133,16 +131,6 @@ pub fn call_kind<'tcx>(
         } else {
             None
         };
-        let parent_did = tcx.parent(method_did);
-        let parent_self_ty = (tcx.def_kind(parent_did) == rustc_hir::def::DefKind::Impl)
-            .then_some(parent_did)
-            .and_then(|did| match tcx.type_of(did).kind() {
-                ty::Adt(def, ..) => Some(def.did()),
-                _ => None,
-            });
-        let is_option_or_result = parent_self_ty.map_or(false, |def_id| {
-            matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result))
-        });
-        CallKind::Normal { self_arg, desugaring, is_option_or_result }
+        CallKind::Normal { self_arg, desugaring, method_did }
     })
 }
index 6ca71223391d2a5828b39b655cb113473cd0e46f..4ce107ea68d4f0f3869cebe3cce00c706a42f58d 100644 (file)
@@ -3,7 +3,7 @@
 use rustc_session::Limit;
 use rustc_target::abi::{Abi, FieldsShape, InitKind, Scalar, Variants};
 
-use crate::const_eval::CompileTimeInterpreter;
+use crate::const_eval::{CheckAlignment, CompileTimeInterpreter};
 use crate::interpret::{InterpCx, MemoryKind, OpTy};
 
 /// Determines if this type permits "raw" initialization by just transmuting some memory into an
@@ -41,7 +41,7 @@ fn might_permit_raw_init_strict<'tcx>(
     let machine = CompileTimeInterpreter::new(
         Limit::new(0),
         /*can_access_statics:*/ false,
-        /*check_alignment:*/ true,
+        CheckAlignment::Error,
     );
 
     let mut cx = InterpCx::new(tcx, rustc_span::DUMMY_SP, ParamEnv::reveal_all(), machine);
index 14c8c88028bdac0448ad5321272730a4842fcfe0..c4122f66498143a70950219d6afb696c91d58f40 100644 (file)
@@ -58,8 +58,7 @@ fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
             // Types with identity (print the module path).
             ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did: def_id, .. }, _)), substs)
             | ty::FnDef(def_id, substs)
-            | ty::Opaque(def_id, substs)
-            | ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs })
+            | ty::Alias(_, ty::AliasTy { def_id, substs, .. })
             | ty::Closure(def_id, substs)
             | ty::Generator(def_id, substs, _) => self.print_def_path(def_id, substs),
             ty::Foreign(def_id) => self.print_def_path(def_id, &[]),
index 3c7bea27124096f35fd2cda702e5cb7ccc930b96..4567759c004dad7140b008d9569fc811c07fe642 100644 (file)
@@ -9,7 +9,7 @@
 pub const ALPHANUMERIC_ONLY: usize = 62;
 pub const CASE_INSENSITIVE: usize = 36;
 
-const BASE_64: &[u8; MAX_BASE as usize] =
+const BASE_64: &[u8; MAX_BASE] =
     b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@$";
 
 #[inline]
index d98f4e43fe8843890fa1044df400b9b8113ea49f..b6e866f15efe3c576285798a16b4d9ce9d051afb 100644 (file)
@@ -1,6 +1,5 @@
 use crate::stable_hasher;
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
-use std::convert::TryInto;
 use std::hash::{Hash, Hasher};
 
 #[cfg(test)]
index 7099ca7eb88c2db01f8b5ed0af656a99e6bca869..b31092eca9837bb0a0c5536b1be7e05c188fcbf5 100644 (file)
@@ -9,7 +9,6 @@
 use crate::graph::vec_graph::VecGraph;
 use crate::graph::{DirectedGraph, GraphSuccessors, WithNumEdges, WithNumNodes, WithSuccessors};
 use rustc_index::vec::{Idx, IndexVec};
-use std::cmp::Ord;
 use std::ops::Range;
 
 #[cfg(test)]
index e8efbd09a2c38c815647ec4cd62b5acae103bbc7..94232bb7626ec885327699322d6d1357b4a9da40 100644 (file)
@@ -1,5 +1,3 @@
-use std::cmp::Ord;
-
 use crate::graph::{DirectedGraph, GraphSuccessors, WithNumEdges, WithNumNodes, WithSuccessors};
 use rustc_index::vec::{Idx, IndexVec};
 
index 980a540ccba7a5c0758f954cabd9cc5b8fc4a05a..d1d92b905b82e0b9da4db953f10c263d8bce4838 100644 (file)
@@ -867,11 +867,9 @@ pub fn try_new<F, E>(o: O, f: F) -> Result<Self, E>
 /////////////////////////////////////////////////////////////////////////////
 
 use std::borrow::Borrow;
-use std::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
-use std::convert::From;
+use std::cmp::Ordering;
 use std::fmt::{self, Debug};
 use std::hash::{Hash, Hasher};
-use std::marker::{Send, Sync};
 
 impl<O, T: ?Sized> Deref for OwningRef<O, T> {
     type Target = T;
@@ -1096,7 +1094,6 @@ fn hash<H: Hasher>(&self, state: &mut H) {
 // std types integration and convenience type defs
 /////////////////////////////////////////////////////////////////////////////
 
-use std::boxed::Box;
 use std::cell::{Ref, RefCell, RefMut};
 use std::rc::Rc;
 use std::sync::Arc;
index 320c03d5139f4ba0985dbaae066f61c3b92c0fe8..a9b187c4ce0a79f979ae4c562ebe56ab598c40bb 100644 (file)
@@ -3,7 +3,7 @@
 mod owning_ref {
     use super::super::OwningRef;
     use super::super::{BoxRef, Erased, ErasedBoxRef, RcRef};
-    use std::cmp::{Ord, Ordering, PartialEq, PartialOrd};
+    use std::cmp::Ordering;
     use std::collections::hash_map::DefaultHasher;
     use std::collections::HashMap;
     use std::hash::{Hash, Hasher};
@@ -368,7 +368,7 @@ fn owning_handle_safe_2() {
 mod owning_ref_mut {
     use super::super::BoxRef;
     use super::super::{BoxRefMut, Erased, ErasedBoxRefMut, OwningRefMut};
-    use std::cmp::{Ord, Ordering, PartialEq, PartialOrd};
+    use std::cmp::Ordering;
     use std::collections::hash_map::DefaultHasher;
     use std::collections::HashMap;
     use std::hash::{Hash, Hasher};
index aa7a01eed15c9a1438dbfb133632091fc4018a02..1d4014f05acdc3e5a208d301ebd534a504fb411c 100644 (file)
@@ -86,7 +86,6 @@
 
 use std::borrow::Borrow;
 use std::collections::hash_map::Entry;
-use std::convert::Into;
 use std::error::Error;
 use std::fs;
 use std::path::Path;
index d13313dfd0ebfc4c145ad4a8756141a9f62c7a7c..05f059c89d5cd0fea01ea73e00e8d8419b4b3c9e 100644 (file)
@@ -1,7 +1,6 @@
 use crate::stable_hasher::{HashStable, StableHasher, StableOrd};
 use std::borrow::Borrow;
 use std::cmp::Ordering;
-use std::iter::FromIterator;
 use std::mem;
 use std::ops::{Bound, Index, IndexMut, RangeBounds};
 
@@ -127,13 +126,13 @@ pub fn iter(&self) -> std::slice::Iter<'_, (K, V)> {
     /// Iterate over the keys, sorted
     #[inline]
     pub fn keys(&self) -> impl Iterator<Item = &K> + ExactSizeIterator + DoubleEndedIterator {
-        self.data.iter().map(|&(ref k, _)| k)
+        self.data.iter().map(|(k, _)| k)
     }
 
     /// Iterate over values, sorted by key
     #[inline]
     pub fn values(&self) -> impl Iterator<Item = &V> + ExactSizeIterator + DoubleEndedIterator {
-        self.data.iter().map(|&(_, ref v)| v)
+        self.data.iter().map(|(_, v)| v)
     }
 
     #[inline]
@@ -223,7 +222,7 @@ fn lookup_index_for<Q>(&self, key: &Q) -> Result<usize, usize>
         K: Borrow<Q>,
         Q: Ord + ?Sized,
     {
-        self.data.binary_search_by(|&(ref x, _)| x.borrow().cmp(key))
+        self.data.binary_search_by(|(x, _)| x.borrow().cmp(key))
     }
 
     #[inline]
@@ -301,7 +300,7 @@ impl<K: Ord, V> FromIterator<(K, V)> for SortedMap<K, V> {
     fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
         let mut data: Vec<(K, V)> = iter.into_iter().collect();
 
-        data.sort_unstable_by(|&(ref k1, _), &(ref k2, _)| k1.cmp(k2));
+        data.sort_unstable_by(|(k1, _), (k2, _)| k1.cmp(k2));
         data.dedup_by(|&mut (ref k1, _), &mut (ref k2, _)| k1.cmp(k2) == Ordering::Equal);
 
         SortedMap { data }
index c2f0ae328962be15a9ac787fd62f51dd2f464b19..7af5c14942adf8c30ac0c0bc898655b97251a708 100644 (file)
@@ -1,7 +1,6 @@
 //! A variant of `SortedMap` that preserves insertion order.
 
 use std::hash::{Hash, Hasher};
-use std::iter::FromIterator;
 
 use crate::stable_hasher::{HashStable, StableHasher};
 use rustc_index::vec::{Idx, IndexVec};
index 131eeef4582de6fc35df95d90470cf9881bf48e1..bca6c0955b905f8732fb72b598fc75e62d924152 100644 (file)
@@ -1,7 +1,5 @@
 use std::fmt;
-use std::iter::ExactSizeIterator;
 use std::iter::FusedIterator;
-use std::iter::Iterator;
 
 /// Iterator which may contain instance of
 /// one of two specific implementations.
index ec6a62016a87cffad47430832d96f4554d5567aa..7cdac58197714840081099415c7fadd866b76f75 100644 (file)
@@ -3,7 +3,6 @@
 use arrayvec::ArrayVec;
 use std::fmt;
 use std::hash::Hash;
-use std::iter::FromIterator;
 use std::ops::Index;
 
 // For pointer-sized arguments arrays
index 406f0270dcc1b50587a35354ad677152f7287f47..a4b40138933dedc2cf12c370df798509f1aca3f7 100644 (file)
@@ -1,6 +1,5 @@
 use std::fmt;
 use std::hash::Hash;
-use std::iter::FromIterator;
 
 use super::map::SsoHashMap;
 
index e4f47b22ac3584d5336ed0d42d5c030f2e82872e..ed5341c40ef08b70ee2fae389ad86b949f80ba8b 100644 (file)
@@ -138,7 +138,7 @@ macro_rules! parallel {
             }
         }
 
-        pub use std::iter::Iterator as ParallelIterator;
+        pub use Iterator as ParallelIterator;
 
         pub fn par_iter<T: IntoIterator>(t: T) -> T::IntoIter {
             t.into_iter()
index d44ccd368b3cbb507c630fca26432c7a7da39da2..b0315c93d934d7a359266dd89ddfa86268c5d4a4 100644 (file)
@@ -76,7 +76,7 @@ impl<P, T, const COMPARE_PACKED: bool> Drop for TaggedPtr<P, T, COMPARE_PACKED>
     fn drop(&mut self) {
         // No need to drop the tag, as it's Copy
         unsafe {
-            std::mem::drop(P::from_usize(self.raw.pointer_raw()));
+            drop(P::from_usize(self.raw.pointer_raw()));
         }
     }
 }
index 86be0bd8775d76cdcca9553035d3a8c973fc590c..2417df66bb9d8a2b0dd0d4ac09744a0d8dba0cdc 100644 (file)
@@ -1,6 +1,5 @@
 use std::borrow::Borrow;
 use std::fmt::Debug;
-use std::iter::FromIterator;
 use std::slice::Iter;
 use std::vec::IntoIter;
 
index 22f87514dd8fa133fe2f9993400ecc7d18c37060..711eed2b2723118a11a64ceeb11f01ca651f30da 100644 (file)
@@ -25,6 +25,7 @@
 use rustc_errors::registry::{InvalidErrorCode, Registry};
 use rustc_errors::{ErrorGuaranteed, PResult};
 use rustc_feature::find_gated_cfg;
+use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_interface::util::{self, collect_crate_types, get_codegen_backend};
 use rustc_interface::{interface, Queries};
 use rustc_lint::LintStore;
@@ -44,7 +45,6 @@
 
 use std::borrow::Cow;
 use std::cmp::max;
-use std::default::Default;
 use std::env;
 use std::ffi::OsString;
 use std::fs;
@@ -374,14 +374,14 @@ fn run_compiler(
             queries.global_ctxt()?.peek_mut().enter(|tcx| {
                 let result = tcx.analysis(());
                 if sess.opts.unstable_opts.save_analysis {
-                    let crate_name = queries.crate_name()?.peek().clone();
+                    let crate_name = tcx.crate_name(LOCAL_CRATE);
                     sess.time("save_analysis", || {
                         save::process_crate(
                             tcx,
-                            &crate_name,
+                            crate_name,
                             compiler.input(),
                             None,
-                            DumpHandler::new(compiler.output_dir().as_deref(), &crate_name),
+                            DumpHandler::new(compiler.output_dir().as_deref(), crate_name),
                         )
                     });
                 }
@@ -678,7 +678,7 @@ fn print_crate_info(
                 let crate_types = collect_crate_types(sess, attrs);
                 for &style in &crate_types {
                     let fname =
-                        rustc_session::output::filename_for_input(sess, style, &id, &t_outputs);
+                        rustc_session::output::filename_for_input(sess, style, id, &t_outputs);
                     println!("{}", fname.file_name().unwrap().to_string_lossy());
                 }
             }
index 1e86d159668ffe5d6b1bca194df8bb1a359c6d18..67c512e98d68d6902e654b8a113f124b1ad657b2 100644 (file)
 E0312: include_str!("./error_codes/E0312.md"),
 E0316: include_str!("./error_codes/E0316.md"),
 E0317: include_str!("./error_codes/E0317.md"),
+E0320: include_str!("./error_codes/E0320.md"),
 E0321: include_str!("./error_codes/E0321.md"),
 E0322: include_str!("./error_codes/E0322.md"),
 E0323: include_str!("./error_codes/E0323.md"),
 E0787: include_str!("./error_codes/E0787.md"),
 E0788: include_str!("./error_codes/E0788.md"),
 E0790: include_str!("./error_codes/E0790.md"),
+E0791: include_str!("./error_codes/E0791.md"),
 ;
 //  E0006, // merged with E0005
 //  E0008, // cannot bind by-move into a pattern guard
 //  E0314, // closure outlives stack frame
 //  E0315, // cannot invoke closure outside of its lifetime
 //  E0319, // trait impls for defaulted traits allowed just for structs/enums
-    E0320, // recursive overflow during dropck
 //  E0372, // coherence not object safe
     E0377, // the trait `CoerceUnsized` may only be implemented for a coercion
            // between structures with the same definition
index 0a9ef9c39385cc6aa18af1c4e22df9a05ba70179..03b93d925c19a3f5c0eab3202af14735ab04cfdf 100644 (file)
@@ -1,38 +1,53 @@
-An associated const has been referenced in a pattern.
+An associated `const`, `const` parameter or `static` has been referenced
+in a pattern.
 
 Erroneous code example:
 
 ```compile_fail,E0158
-enum EFoo { A, B, C, D }
+enum Foo {
+    One,
+    Two
+}
 
-trait Foo {
-    const X: EFoo;
+trait Bar {
+    const X: Foo;
 }
 
-fn test<A: Foo>(arg: EFoo) {
+fn test<A: Bar>(arg: Foo) {
     match arg {
-        A::X => { // error!
-            println!("A::X");
-        }
+        A::X => println!("A::X"), // error: E0158: associated consts cannot be
+                                  //        referenced in patterns
+        Foo::Two => println!("Two")
     }
 }
 ```
 
-`const` and `static` mean different things. A `const` is a compile-time
-constant, an alias for a literal value. This property means you can match it
-directly within a pattern.
+Associated `const`s cannot be referenced in patterns because it is impossible
+for the compiler to prove exhaustiveness (that some pattern will always match).
+Take the above example, because Rust does type checking in the *generic*
+method, not the *monomorphized* specific instance. So because `Bar` could have
+theoretically infinite implementations, there's no way to always be sure that
+`A::X` is `Foo::One`. So this code must be rejected. Even if code can be
+proven exhaustive by a programmer, the compiler cannot currently prove this.
 
-The `static` keyword, on the other hand, guarantees a fixed location in memory.
-This does not always mean that the value is constant. For example, a global
-mutex can be declared `static` as well.
+The same holds true of `const` parameters and `static`s.
 
-If you want to match against a `static`, consider using a guard instead:
+If you want to match against an associated `const`, `const` parameter or
+`static` consider using a guard instead:
 
 ```
-static FORTY_TWO: i32 = 42;
+trait Trait {
+    const X: char;
+}
+
+static FOO: char = 'j';
 
-match Some(42) {
-    Some(x) if x == FORTY_TWO => {}
-    _ => {}
+fn test<A: Trait, const Y: char>(arg: char) {
+    match arg {
+        c if c == A::X => println!("A::X"),
+        c if c == Y => println!("Y"),
+        c if c == FOO => println!("FOO"),
+        _ => ()
+    }
 }
 ```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0320.md b/compiler/rustc_error_codes/src/error_codes/E0320.md
new file mode 100644 (file)
index 0000000..e6e1b7c
--- /dev/null
@@ -0,0 +1,27 @@
+Recursion limit reached while creating drop-check rules.
+
+Example of erroneous code:
+
+```compile_fail,E0320
+enum A<T> {
+    B,
+    C(T, Box<A<(T, T)>>)
+}
+
+fn foo<T>() {
+    A::<T>::B; // error: overflow while adding drop-check rules for A<T>
+}
+```
+
+The Rust compiler must be able to reason about how a type is [`Drop`]ped, and
+by extension the types of its fields, to be able to generate the glue to
+properly drop a value. The code example above shows a type where this inference
+is impossible because it is recursive. Note that this is *not* the same as
+[E0072](E0072.html), where a type has an infinite size; the type here has a
+finite size but any attempt to `Drop` it would recurse infinitely. For more
+information, read [the `Drop` docs](../std/ops/trait.Drop.html).
+
+It is not possible to define a type with recursive drop-check rules. All such
+recursion must be removed.
+
+[`Drop`]: ../std/ops/trait.Drop.html
index 79e7c069a91c42cdb62d62be42c245702a32798d..7c0719dc217d06089d726acca31a965d7a99a69f 100644 (file)
@@ -55,7 +55,6 @@ wrapper:
 
 ```
 use std::cell::Cell;
-use std::marker::Sync;
 
 struct NotThreadSafe<T> {
     value: Cell<T>,
diff --git a/compiler/rustc_error_codes/src/error_codes/E0791.md b/compiler/rustc_error_codes/src/error_codes/E0791.md
new file mode 100644 (file)
index 0000000..61d2f51
--- /dev/null
@@ -0,0 +1,41 @@
+Static variables with the `#[linkage]` attribute within external blocks
+must have one of the following types, which are equivalent to a nullable
+pointer in C:
+
+* `*mut T` or `*const T`, where `T` may be any type.
+
+* An enumerator type with no `#[repr]` attribute and with two variants, where
+  one of the variants has no fields, and the other has a single field of one of
+  the following non-nullable types:
+  * Reference type
+  * Function pointer type
+
+  The variants can appear in either order.
+
+For example, the following declaration is invalid:
+
+```compile_fail,E0791
+#![feature(linkage)]
+
+extern "C" {
+    #[linkage = "extern_weak"]
+    static foo: i8;
+}
+```
+
+The following declarations are valid:
+
+```
+#![feature(linkage)]
+
+extern "C" {
+    #[linkage = "extern_weak"]
+    static foo: Option<unsafe extern "C" fn()>;
+
+    #[linkage = "extern_weak"]
+    static bar: Option<&'static i8>;
+
+    #[linkage = "extern_weak"]
+    static baz: *mut i8;
+}
+```
index a1b7afeb7099d5084e8f619e528a3408e794c56b..08ce5172574ac3bb1af28314ec2200a26b8d221a 100644 (file)
@@ -1,6 +1,3 @@
-codegen_gcc_linkage_const_or_mut_type =
-    must have type `*const T` or `*mut T` due to `#[linkage]` attribute
-
 codegen_gcc_unwinding_inline_asm =
     GCC backend does not support unwinding from inline asm
 
index e273476b60bb69d2c44ce27185cb56ea9af7653e..860212b051f39c4a8739110e9bf1edf220aa23cf 100644 (file)
@@ -17,15 +17,9 @@ codegen_llvm_instrument_coverage_requires_llvm_12 =
 codegen_llvm_symbol_already_defined =
     symbol `{$symbol_name}` is already defined
 
-codegen_llvm_branch_protection_requires_aarch64 =
-    -Zbranch-protection is only supported on aarch64
-
 codegen_llvm_invalid_minimum_alignment =
     invalid minimum global alignment: {$err}
 
-codegen_llvm_linkage_const_or_mut_type =
-    must have type `*const T` or `*mut T` due to `#[linkage]` attribute
-
 codegen_llvm_sanitizer_memtag_requires_mte =
     `-Zsanitizer=memtag` requires `-Ctarget-feature=+mte`
 
index 4d1f9c1c901fc63d7fc4d877c76379baa2634e8b..db4c82b35c77822d718d16039112205dada7972c 100644 (file)
@@ -192,3 +192,5 @@ codegen_ssa_archive_build_failure =
 
 codegen_ssa_unknown_archive_kind =
     Don't know how to build archive of type: {$kind}
+
+codegen_ssa_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
index 5720591154f9914e2ff3f9ada81c45edb4252118..df0e8ae5dd8f5d11bb0577d502ef388e44d132e3 100644 (file)
@@ -20,3 +20,110 @@ expand_var_still_repeating =
     variable '{$ident}' is still repeating at this depth
 
 expand_meta_var_dif_seq_matchers = {$msg}
+
+expand_macro_const_stability =
+    macros cannot have const stability attributes
+    .label = invalid const stability attribute
+    .label2 = const stability attribute affects this macro
+
+expand_macro_body_stability =
+    macros cannot have body stability attributes
+    .label = invalid body stability attribute
+    .label2 = body stability attribute affects this macro
+
+expand_resolve_relative_path =
+    cannot resolve relative path in non-file source `{$path}`
+
+expand_attr_no_arguments =
+    attribute must have either one or two arguments
+
+expand_not_a_meta_item =
+    not a meta item
+
+expand_only_one_word =
+    must only be one word
+
+expand_cannot_be_name_of_macro =
+    `{$trait_ident}` cannot be a name of {$macro_type} macro
+
+expand_arg_not_attributes =
+    second argument must be `attributes`
+
+expand_attributes_wrong_form =
+    attribute must be of form: `attributes(foo, bar)`
+
+expand_attribute_meta_item =
+    attribute must be a meta item, not a literal
+
+expand_attribute_single_word =
+    attribute must only be a single word
+
+expand_helper_attribute_name_invalid =
+    `{$name}` cannot be a name of derive helper attribute
+
+expand_expected_comma_in_list =
+    expected token: `,`
+
+expand_only_one_argument =
+    {$name} takes 1 argument
+
+expand_takes_no_arguments =
+    {$name} takes no arguments
+
+expand_feature_included_in_edition =
+    the feature `{$feature}` is included in the Rust {$edition} edition
+
+expand_feature_removed =
+    feature has been removed
+    .label = feature has been removed
+    .reason = {$reason}
+
+expand_feature_not_allowed =
+    the feature `{$name}` is not in the list of allowed features
+
+expand_recursion_limit_reached =
+    recursion limit reached while expanding `{$descr}`
+    .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
+
+expand_malformed_feature_attribute =
+    malformed `feature` attribute input
+    .expected = expected just one word
+
+expand_remove_expr_not_supported =
+    removing an expression is not supported in this position
+
+expand_invalid_cfg_no_parens = `cfg` is not followed by parentheses
+expand_invalid_cfg_no_predicate = `cfg` predicate is not specified
+expand_invalid_cfg_multiple_predicates = multiple `cfg` predicates are specified
+expand_invalid_cfg_predicate_literal = `cfg` predicate key cannot be a literal
+expand_invalid_cfg_expected_syntax = expected syntax is
+
+expand_wrong_fragment_kind =
+    non-{$kind} macro in {$kind} position: {$name}
+
+expand_unsupported_key_value =
+    key-value macro attributes are not supported
+
+expand_incomplete_parse =
+    macro expansion ignores token `{$token}` and any following
+    .label = caused by the macro expansion here
+    .note = the usage of `{$macro_path}!` is likely invalid in {$kind_name} context
+    .suggestion_add_semi = you might be missing a semicolon here
+
+expand_remove_node_not_supported =
+    removing {$descr} is not supported in this position
+
+expand_module_circular =
+    circular modules: {$modules}
+
+expand_module_in_block =
+    cannot declare a non-inline module inside a block unless it has a path attribute
+    .note = maybe `use` the module `{$name}` instead of redeclaring it
+
+expand_module_file_not_found =
+    file not found for module `{$name}`
+    .help = to create the module `{$name}`, create file "{$default_path}" or "{$secondary_path}"
+
+expand_module_multiple_candidates =
+    file for module `{$name}` found at both "{$default_path}" and "{$secondary_path}"
+    .help = delete or rename one of them to remove the ambiguity
index a5cb8a88819df2d09a4ecd141748f5c5000de062..26cdf8a58f3fb5e975342ef93f2237c095a2932d 100644 (file)
@@ -20,6 +20,10 @@ hir_analysis_lifetimes_or_bounds_mismatch_on_trait =
     .where_label = this `where` clause might not match the one in the trait
     .bounds_label = this bound might be missing in the impl
 
+hir_analysis_async_trait_impl_should_be_async =
+    method `{$method_name}` should be async because the method from the trait is async
+    .trait_item_label = required because the trait method is async
+
 hir_analysis_drop_impl_on_wrong_item =
     the `Drop` trait may only be implemented for local structs, enums, and unions
     .label = must be a struct, enum, or union in the current crate
@@ -101,8 +105,6 @@ hir_analysis_extern_crate_not_idiomatic =
     `extern crate` is not idiomatic in the new edition
     .suggestion = convert it to a `{$msg_code}`
 
-hir_analysis_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
-
 hir_analysis_const_impl_for_non_const_trait =
     const `impl` for trait `{$trait_name}` which is not marked with `#[const_trait]`
     .suggestion = mark `{$trait_name}` as const
@@ -115,3 +117,6 @@ hir_analysis_const_bound_for_non_const_trait =
 hir_analysis_self_in_impl_self =
     `Self` is not valid in the self type of an impl block
     .note = replace `Self` with a different type
+
+hir_analysis_linkage_type =
+    invalid type for variable with `#[linkage]` attribute
index d1e1fd54db9bf22bcacc11f105c8b56be3dc5c36..b3ca540417da79876f17449c5a2d4aa82d767861 100644 (file)
@@ -166,12 +166,6 @@ metadata_conflicting_alloc_error_handler =
 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_alloc_func_required =
-    `#[alloc_error_handler]` function required, but not found
-
-metadata_missing_alloc_error_handler =
-    use `#![feature(default_alloc_error_handler)]` for a default error handler
-
 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}`
 
diff --git a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl
new file mode 100644 (file)
index 0000000..60d3d3e
--- /dev/null
@@ -0,0 +1,301 @@
+mir_build_unconditional_recursion = function cannot return without recursing
+    .label = cannot return without recursing
+    .help = a `loop` may express intention better if this is on purpose
+
+mir_build_unconditional_recursion_call_site_label = recursive call site
+
+mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe =
+    call to unsafe function `{$function}` is unsafe and requires unsafe block (error E0133)
+    .note = consult the function's documentation for information on how to avoid undefined behavior
+    .label = call to unsafe function
+
+mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe_nameless =
+    call to unsafe function is unsafe and requires unsafe block (error E0133)
+    .note = consult the function's documentation for information on how to avoid undefined behavior
+    .label = call to unsafe function
+
+mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe =
+    use of inline assembly is unsafe and requires unsafe block (error E0133)
+    .note = inline assembly is entirely unchecked and can cause undefined behavior
+    .label = use of inline assembly
+
+mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe =
+    initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe
+    block (error E0133)
+    .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
+    .label = initializing type with `rustc_layout_scalar_valid_range` attr
+
+mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe =
+    use of mutable static is unsafe and requires unsafe block (error E0133)
+    .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+    .label = use of mutable static
+
+mir_build_unsafe_op_in_unsafe_fn_extern_static_requires_unsafe =
+    use of extern static is unsafe and requires unsafe block (error E0133)
+    .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+    .label = use of extern static
+
+mir_build_unsafe_op_in_unsafe_fn_deref_raw_pointer_requires_unsafe =
+    dereference of raw pointer is unsafe and requires unsafe block (error E0133)
+    .note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+    .label = dereference of raw pointer
+
+mir_build_unsafe_op_in_unsafe_fn_union_field_requires_unsafe =
+    access to union field is unsafe and requires unsafe block (error E0133)
+    .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior
+    .label = access to union field
+
+mir_build_unsafe_op_in_unsafe_fn_mutation_of_layout_constrained_field_requires_unsafe =
+    mutation of layout constrained field is unsafe and requires unsafe block (error E0133)
+    .note = mutating layout constrained fields cannot statically be checked for valid values
+    .label = mutation of layout constrained field
+
+mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe =
+    borrow of layout constrained field with interior mutability is unsafe and requires unsafe block (error E0133)
+    .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
+    .label = borrow of layout constrained field with interior mutability
+
+mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe =
+    call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block (error E0133)
+    .note = can only be called if the required target features are available
+    .label = call to function with `#[target_feature]`
+
+mir_build_call_to_unsafe_fn_requires_unsafe =
+    call to unsafe function `{$function}` is unsafe and requires unsafe block
+    .note = consult the function's documentation for information on how to avoid undefined behavior
+    .label = call to unsafe function
+
+mir_build_call_to_unsafe_fn_requires_unsafe_nameless =
+    call to unsafe function is unsafe and requires unsafe block
+    .note = consult the function's documentation for information on how to avoid undefined behavior
+    .label = call to unsafe function
+
+mir_build_call_to_unsafe_fn_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+    call to unsafe function `{$function}` is unsafe and requires unsafe function or block
+    .note = consult the function's documentation for information on how to avoid undefined behavior
+    .label = call to unsafe function
+
+mir_build_call_to_unsafe_fn_requires_unsafe_nameless_unsafe_op_in_unsafe_fn_allowed =
+    call to unsafe function is unsafe and requires unsafe function or block
+    .note = consult the function's documentation for information on how to avoid undefined behavior
+    .label = call to unsafe function
+
+mir_build_inline_assembly_requires_unsafe =
+    use of inline assembly is unsafe and requires unsafe block
+    .note = inline assembly is entirely unchecked and can cause undefined behavior
+    .label = use of inline assembly
+
+mir_build_inline_assembly_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+    use of inline assembly is unsafe and requires unsafe function or block
+    .note = inline assembly is entirely unchecked and can cause undefined behavior
+    .label = use of inline assembly
+
+mir_build_initializing_type_with_requires_unsafe =
+    initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe block
+    .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
+    .label = initializing type with `rustc_layout_scalar_valid_range` attr
+
+mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+    initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe function or block
+    .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
+    .label = initializing type with `rustc_layout_scalar_valid_range` attr
+
+mir_build_mutable_static_requires_unsafe =
+    use of mutable static is unsafe and requires unsafe block
+    .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+    .label = use of mutable static
+
+mir_build_mutable_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+    use of mutable static is unsafe and requires unsafe function or block
+    .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+    .label = use of mutable static
+
+mir_build_extern_static_requires_unsafe =
+    use of extern static is unsafe and requires unsafe block
+    .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+    .label = use of extern static
+
+mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+    use of extern static is unsafe and requires unsafe function or block
+    .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+    .label = use of extern static
+
+mir_build_deref_raw_pointer_requires_unsafe =
+    dereference of raw pointer is unsafe and requires unsafe block
+    .note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+    .label = dereference of raw pointer
+
+mir_build_deref_raw_pointer_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+    dereference of raw pointer is unsafe and requires unsafe function or block
+    .note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+    .label = dereference of raw pointer
+
+mir_build_union_field_requires_unsafe =
+    access to union field is unsafe and requires unsafe block
+    .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior
+    .label = access to union field
+
+mir_build_union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+    access to union field is unsafe and requires unsafe function or block
+    .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior
+    .label = access to union field
+
+mir_build_mutation_of_layout_constrained_field_requires_unsafe =
+    mutation of layout constrained field is unsafe and requires unsafe block
+    .note = mutating layout constrained fields cannot statically be checked for valid values
+    .label = mutation of layout constrained field
+
+mir_build_mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+    mutation of layout constrained field is unsafe and requires unsafe function or block
+    .note = mutating layout constrained fields cannot statically be checked for valid values
+    .label = mutation of layout constrained field
+
+mir_build_borrow_of_layout_constrained_field_requires_unsafe =
+    borrow of layout constrained field with interior mutability is unsafe and requires unsafe block
+    .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
+    .label = borrow of layout constrained field with interior mutability
+
+mir_build_borrow_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+    borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block
+    .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
+    .label = borrow of layout constrained field with interior mutability
+
+mir_build_call_to_fn_with_requires_unsafe =
+    call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block
+    .note = can only be called if the required target features are available
+    .label = call to function with `#[target_feature]`
+
+mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+    call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe function or block
+    .note = can only be called if the required target features are available
+    .label = call to function with `#[target_feature]`
+
+mir_build_unused_unsafe = unnecessary `unsafe` block
+    .label = unnecessary `unsafe` block
+
+mir_build_unused_unsafe_enclosing_block_label = because it's nested under this `unsafe` block
+mir_build_unused_unsafe_enclosing_fn_label = because it's nested under this `unsafe` fn
+
+mir_build_non_exhaustive_patterns_type_not_empty = non-exhaustive patterns: type `{$ty}` is non-empty
+    .def_note = `{$peeled_ty}` defined here
+    .type_note = the matched value is of type `{$ty}`
+    .non_exhaustive_type_note = the matched value is of type `{$ty}`, which is marked as non-exhaustive
+    .reference_note = references are always considered inhabited
+    .suggestion = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+    .help = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
+
+mir_build_static_in_pattern = statics cannot be referenced in patterns
+
+mir_build_assoc_const_in_pattern = associated consts cannot be referenced in patterns
+
+mir_build_const_param_in_pattern = const parameters cannot be referenced in patterns
+
+mir_build_non_const_path = runtime values cannot be referenced in patterns
+
+mir_build_unreachable_pattern = unreachable pattern
+    .label = unreachable pattern
+    .catchall_label = matches any value
+
+mir_build_const_pattern_depends_on_generic_parameter =
+    constant pattern depends on a generic parameter
+
+mir_build_could_not_eval_const_pattern = could not evaluate constant pattern
+
+mir_build_lower_range_bound_must_be_less_than_or_equal_to_upper =
+    lower range bound must be less than or equal to upper
+    .label = lower bound larger than upper bound
+    .teach_note = When matching against a range, the compiler verifies that the range is non-empty. Range patterns include both end-points, so this is equivalent to requiring the start of the range to be less than or equal to the end of the range.
+
+mir_build_lower_range_bound_must_be_less_than_upper = lower range bound must be less than upper
+
+mir_build_leading_irrefutable_let_patterns = leading irrefutable {$count ->
+        [one] pattern
+        *[other] patterns
+    } in let chain
+    .note = {$count ->
+        [one] this pattern
+        *[other] these patterns
+    } will always match
+    .help = consider moving {$count ->
+        [one] it
+        *[other] them
+    } outside of the construct
+
+mir_build_trailing_irrefutable_let_patterns = trailing irrefutable {$count ->
+        [one] pattern
+        *[other] patterns
+    } in let chain
+    .note = {$count ->
+        [one] this pattern
+        *[other] these patterns
+    } will always match
+    .help = consider moving {$count ->
+        [one] it
+        *[other] them
+    } into the body
+
+mir_build_bindings_with_variant_name =
+    pattern binding `{$ident}` is named the same as one of the variants of the type `{$ty_path}`
+    .suggestion = to match on the variant, qualify the path
+
+mir_build_irrefutable_let_patterns_generic_let = irrefutable `let` {$count ->
+        [one] pattern
+        *[other] patterns
+    }
+    .note = {$count ->
+        [one] this pattern
+        *[other] these patterns
+    } will always match, so the `let` is useless
+    .help = consider removing `let`
+
+mir_build_irrefutable_let_patterns_if_let = irrefutable `if let` {$count ->
+        [one] pattern
+        *[other] patterns
+    }
+    .note = {$count ->
+        [one] this pattern
+        *[other] these patterns
+    } will always match, so the `if let` is useless
+    .help = consider replacing the `if let` with a `let`
+
+mir_build_irrefutable_let_patterns_if_let_guard = irrefutable `if let` guard {$count ->
+        [one] pattern
+        *[other] patterns
+    }
+    .note = {$count ->
+        [one] this pattern
+        *[other] these patterns
+    } will always match, so the guard is useless
+    .help = consider removing the guard and adding a `let` inside the match arm
+
+mir_build_irrefutable_let_patterns_let_else = irrefutable `let...else` {$count ->
+        [one] pattern
+        *[other] patterns
+    }
+    .note = {$count ->
+        [one] this pattern
+        *[other] these patterns
+    } will always match, so the `else` clause is useless
+    .help = consider removing the `else` clause
+
+mir_build_irrefutable_let_patterns_while_let = irrefutable `while let` {$count ->
+        [one] pattern
+        *[other] patterns
+    }
+    .note = {$count ->
+        [one] this pattern
+        *[other] these patterns
+    } will always match, so the loop will never exit
+    .help = consider instead using a `loop {"{"} ... {"}"}` with a `let` inside it
+
+mir_build_borrow_of_moved_value = borrow of moved value
+    .label = value moved into `{$name}` here
+    .occurs_because_label = move occurs because `{$name}` has type `{$ty}` which does not implement the `Copy` trait
+    .value_borrowed_label = value borrowed here after move
+    .suggestion = borrow this binding in the pattern to avoid moving the value
+
+mir_build_multiple_mut_borrows = cannot borrow value as mutable more than once at a time
+    .label = first mutable borrow, by `{$name}`, occurs here
+    .mutable_borrow = another mutable borrow, by `{$name_mut}`, occurs here
+    .immutable_borrow = also borrowed as immutable, by `{$name_immut}`, here
+    .moved = also moved into `{$name_moved}` here
index 48ddb54b79e795eb3c67f96b69bb5dda24e32f01..243d10bfa062150bf9bda530541b8f235d35ceae 100644 (file)
@@ -21,3 +21,6 @@ monomorphize_large_assignments =
     moving {$size} bytes
     .label = value moved from here
     .note = The current maximum size is {$limit}, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
+
+monomorphize_couldnt_dump_mono_stats =
+    unexpected error occurred while dumping monomorphization stats: {$error}
index 114b7ec16288bb7b99f0abcb1ed89ba8559d68ad..b53550e5fd556c02e58acd21fbae26252bb2b69a 100644 (file)
@@ -362,3 +362,6 @@ parse_fn_ptr_with_generics = function pointer types may not have generic paramet
 
 parse_invalid_identifier_with_leading_number = expected identifier, found number literal
     .label = identifiers cannot start with a number
+
+parse_maybe_fn_typo_with_impl = you might have meant to write `impl` instead of `fn`
+    .suggestion = replace `fn` with `impl` here
index 983eb926213ea587946629576a3c1b78fbf202e5..ab9e8b6baae6ad4a3e30bbd92ff4bafe18e66e4c 100644 (file)
@@ -41,6 +41,8 @@ session_unsupported_dwarf_version = requested DWARF version {$dwarf_version} is
 
 session_target_stack_protector_not_supported = `-Z stack-protector={$stack_protector}` is not supported for target {$target_triple} and will be ignored
 
+session_branch_protection_requires_aarch64 = `-Zbranch-protection` is only supported on aarch64
+
 session_split_debuginfo_unstable_platform = `-Csplit-debuginfo={$debuginfo}` is unstable on this platform
 
 session_file_is_not_writeable = output file {$file} is not writeable -- check its permissions
index 418ba3c74d7761cb574d8ad0840fd0dd09c93249..25d0e736e599f5ee4d66e501bb62bff8617a2102 100644 (file)
@@ -57,6 +57,7 @@
     lint => "../locales/en-US/lint.ftl",
     metadata => "../locales/en-US/metadata.ftl",
     middle => "../locales/en-US/middle.ftl",
+    mir_build => "../locales/en-US/mir_build.ftl",
     mir_dataflow => "../locales/en-US/mir_dataflow.ftl",
     monomorphize => "../locales/en-US/monomorphize.ftl",
     parse => "../locales/en-US/parse.ftl",
index 06bb5edc090f48c8b6c326961982ce9730aa6957..585a54308c62e1c0bf07ab9c1478bd51ec0fca2c 100644 (file)
@@ -370,7 +370,11 @@ pub fn replace_span_with(&mut self, after: Span) -> &mut Self {
         self.set_span(after);
         for span_label in before.span_labels() {
             if let Some(label) = span_label.label {
-                self.span.push_span_label(after, label);
+                if span_label.is_primary {
+                    self.span.push_span_label(after, label);
+                } else {
+                    self.span.push_span_label(span_label.span, label);
+                }
             }
         }
         self
@@ -802,7 +806,7 @@ pub fn multipart_suggestions(
         debug_assert!(
             !(suggestions
                 .iter()
-                .flat_map(|suggs| suggs)
+                .flatten()
                 .any(|(sp, suggestion)| sp.is_empty() && suggestion.is_empty())),
             "Span must not be empty and have no suggestion"
         );
index 7155db32e53b7f75e71c4e592c70aa58a4278362..628cb90903feedebcfe049f7cfeef978e6f053e3 100644 (file)
@@ -59,7 +59,7 @@ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
     i128,
     u128,
     std::io::Error,
-    std::boxed::Box<dyn std::error::Error>,
+    Box<dyn std::error::Error>,
     std::num::NonZeroU32,
     hir::Target,
     Edition,
@@ -152,6 +152,12 @@ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
     }
 }
 
+impl IntoDiagnosticArg for &ast::Path {
+    fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+        DiagnosticArgValue::Str(Cow::Owned(pprust::path_to_string(self)))
+    }
+}
+
 impl IntoDiagnosticArg for ast::token::Token {
     fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
         DiagnosticArgValue::Str(pprust::token_to_string(&self))
index db595df8ec18c8cfc2c8c5428996a4bfda4febde..e2a0e436fd5e2677a9524066380a034907ef59b0 100644 (file)
@@ -24,7 +24,7 @@
 
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
 use rustc_data_structures::sync::Lrc;
-use rustc_error_messages::FluentArgs;
+use rustc_error_messages::{FluentArgs, SpanLabel};
 use rustc_span::hygiene::{ExpnKind, MacroKind};
 use std::borrow::Cow;
 use std::cmp::{max, min, Reverse};
@@ -773,6 +773,7 @@ fn draw_line(
         draw_col_separator_no_space(buffer, line_offset, width_offset - 2);
     }
 
+    #[instrument(level = "trace", skip(self), ret)]
     fn render_source_line(
         &self,
         buffer: &mut StyledBuffer,
@@ -804,6 +805,7 @@ fn render_source_line(
             Some(s) => normalize_whitespace(&s),
             None => return Vec::new(),
         };
+        trace!(?source_string);
 
         let line_offset = buffer.num_lines();
 
@@ -1306,7 +1308,7 @@ fn style_or_override(style: Style, override_: Option<Style>) -> Style {
         //                see how it *looks* with
         //                very *weird* formats
         //                see?
-        for &(ref text, ref style) in msg.iter() {
+        for (text, style) in msg.iter() {
             let text = self.translate_message(text, args);
             let lines = text.split('\n').collect::<Vec<_>>();
             if lines.len() > 1 {
@@ -1323,6 +1325,7 @@ fn style_or_override(style: Style, override_: Option<Style>) -> Style {
         }
     }
 
+    #[instrument(level = "trace", skip(self, args), ret)]
     fn emit_message_default(
         &mut self,
         msp: &MultiSpan,
@@ -1367,7 +1370,7 @@ fn emit_message_default(
                 buffer.append(0, ": ", header_style);
                 label_width += 2;
             }
-            for &(ref text, _) in msg.iter() {
+            for (text, _) in msg.iter() {
                 let text = self.translate_message(text, args);
                 // Account for newlines to align output to its label.
                 for (line, text) in normalize_whitespace(&text).lines().enumerate() {
@@ -1384,22 +1387,15 @@ fn emit_message_default(
             }
         }
         let mut annotated_files = FileWithAnnotatedLines::collect_annotations(self, args, msp);
+        trace!("{annotated_files:#?}");
 
         // Make sure our primary file comes first
-        let (primary_lo, sm) = if let (Some(sm), Some(ref primary_span)) =
-            (self.sm.as_ref(), msp.primary_span().as_ref())
-        {
-            if !primary_span.is_dummy() {
-                (sm.lookup_char_pos(primary_span.lo()), sm)
-            } else {
-                emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?;
-                return Ok(());
-            }
-        } else {
+        let primary_span = msp.primary_span().unwrap_or_default();
+        let (Some(sm), false) = (self.sm.as_ref(), primary_span.is_dummy()) else {
             // If we don't have span information, emit and exit
-            emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?;
-            return Ok(());
+            return emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message);
         };
+        let primary_lo = sm.lookup_char_pos(primary_span.lo());
         if let Ok(pos) =
             annotated_files.binary_search_by(|x| x.file.name.cmp(&primary_lo.file.name))
         {
@@ -1410,6 +1406,63 @@ fn emit_message_default(
         for annotated_file in annotated_files {
             // we can't annotate anything if the source is unavailable.
             if !sm.ensure_source_file_source_present(annotated_file.file.clone()) {
+                if !self.short_message {
+                    // We'll just print an unannotated message.
+                    for (annotation_id, line) in annotated_file.lines.iter().enumerate() {
+                        let mut annotations = line.annotations.clone();
+                        annotations.sort_by_key(|a| Reverse(a.start_col));
+                        let mut line_idx = buffer.num_lines();
+
+                        let labels: Vec<_> = annotations
+                            .iter()
+                            .filter_map(|a| Some((a.label.as_ref()?, a.is_primary)))
+                            .filter(|(l, _)| !l.is_empty())
+                            .collect();
+
+                        if annotation_id == 0 || !labels.is_empty() {
+                            buffer.append(
+                                line_idx,
+                                &format!(
+                                    "{}:{}:{}",
+                                    sm.filename_for_diagnostics(&annotated_file.file.name),
+                                    sm.doctest_offset_line(
+                                        &annotated_file.file.name,
+                                        line.line_index
+                                    ),
+                                    annotations[0].start_col + 1,
+                                ),
+                                Style::LineAndColumn,
+                            );
+                            if annotation_id == 0 {
+                                buffer.prepend(line_idx, "--> ", Style::LineNumber);
+                            } else {
+                                buffer.prepend(line_idx, "::: ", Style::LineNumber);
+                            }
+                            for _ in 0..max_line_num_len {
+                                buffer.prepend(line_idx, " ", Style::NoStyle);
+                            }
+                            line_idx += 1;
+                        }
+                        for (label, is_primary) in labels.into_iter() {
+                            let style = if is_primary {
+                                Style::LabelPrimary
+                            } else {
+                                Style::LabelSecondary
+                            };
+                            buffer.prepend(line_idx, " |", Style::LineNumber);
+                            for _ in 0..max_line_num_len {
+                                buffer.prepend(line_idx, " ", Style::NoStyle);
+                            }
+                            line_idx += 1;
+                            buffer.append(line_idx, " = note: ", style);
+                            for _ in 0..max_line_num_len {
+                                buffer.prepend(line_idx, " ", Style::NoStyle);
+                            }
+                            buffer.append(line_idx, label, style);
+                            line_idx += 1;
+                        }
+                    }
+                }
                 continue;
             }
 
@@ -1656,6 +1709,7 @@ fn emit_message_default(
                     multilines.extend(&to_add);
                 }
             }
+            trace!("buffer: {:#?}", buffer.render());
         }
 
         if let Some(tracked) = emitted_at {
@@ -1979,6 +2033,7 @@ fn emit_suggestion_default(
         Ok(())
     }
 
+    #[instrument(level = "trace", skip(self, args, code, children, suggestions))]
     fn emit_messages_default(
         &mut self,
         level: &Level,
@@ -2209,46 +2264,28 @@ fn add_annotation_to_file(
         let mut multiline_annotations = vec![];
 
         if let Some(ref sm) = emitter.source_map() {
-            for span_label in msp.span_labels() {
-                let fixup_lo_hi = |span: Span| {
-                    let lo = sm.lookup_char_pos(span.lo());
-                    let mut hi = sm.lookup_char_pos(span.hi());
-
-                    // Watch out for "empty spans". If we get a span like 6..6, we
-                    // want to just display a `^` at 6, so convert that to
-                    // 6..7. This is degenerate input, but it's best to degrade
-                    // gracefully -- and the parser likes to supply a span like
-                    // that for EOF, in particular.
-
-                    if lo.col_display == hi.col_display && lo.line == hi.line {
-                        hi.col_display += 1;
-                    }
-                    (lo, hi)
+            for SpanLabel { span, is_primary, label } in msp.span_labels() {
+                // If we don't have a useful span, pick the primary span if that exists.
+                // Worst case we'll just print an error at the top of the main file.
+                let span = match (span.is_dummy(), msp.primary_span()) {
+                    (_, None) | (false, _) => span,
+                    (true, Some(span)) => span,
                 };
 
-                if span_label.span.is_dummy() {
-                    if let Some(span) = msp.primary_span() {
-                        // if we don't know where to render the annotation, emit it as a note
-                        // on the primary span.
-
-                        let (lo, hi) = fixup_lo_hi(span);
-
-                        let ann = Annotation {
-                            start_col: lo.col_display,
-                            end_col: hi.col_display,
-                            is_primary: span_label.is_primary,
-                            label: span_label
-                                .label
-                                .as_ref()
-                                .map(|m| emitter.translate_message(m, args).to_string()),
-                            annotation_type: AnnotationType::Singleline,
-                        };
-                        add_annotation_to_file(&mut output, lo.file, lo.line, ann);
-                    }
-                    continue;
+                let lo = sm.lookup_char_pos(span.lo());
+                let mut hi = sm.lookup_char_pos(span.hi());
+
+                // Watch out for "empty spans". If we get a span like 6..6, we
+                // want to just display a `^` at 6, so convert that to
+                // 6..7. This is degenerate input, but it's best to degrade
+                // gracefully -- and the parser likes to supply a span like
+                // that for EOF, in particular.
+
+                if lo.col_display == hi.col_display && lo.line == hi.line {
+                    hi.col_display += 1;
                 }
 
-                let (lo, hi) = fixup_lo_hi(span_label.span);
+                let label = label.as_ref().map(|m| emitter.translate_message(m, args).to_string());
 
                 if lo.line != hi.line {
                     let ml = MultilineAnnotation {
@@ -2257,11 +2294,8 @@ fn add_annotation_to_file(
                         line_end: hi.line,
                         start_col: lo.col_display,
                         end_col: hi.col_display,
-                        is_primary: span_label.is_primary,
-                        label: span_label
-                            .label
-                            .as_ref()
-                            .map(|m| emitter.translate_message(m, args).to_string()),
+                        is_primary,
+                        label,
                         overlaps_exactly: false,
                     };
                     multiline_annotations.push((lo.file, ml));
@@ -2269,11 +2303,8 @@ fn add_annotation_to_file(
                     let ann = Annotation {
                         start_col: lo.col_display,
                         end_col: hi.col_display,
-                        is_primary: span_label.is_primary,
-                        label: span_label
-                            .label
-                            .as_ref()
-                            .map(|m| emitter.translate_message(m, args).to_string()),
+                        is_primary,
+                        label,
                         annotation_type: AnnotationType::Singleline,
                     };
                     add_annotation_to_file(&mut output, lo.file, lo.line, ann);
@@ -2282,7 +2313,7 @@ fn add_annotation_to_file(
         }
 
         // Find overlapping multiline annotations, put them at different depths
-        multiline_annotations.sort_by_key(|&(_, ref ml)| (ml.line_start, usize::MAX - ml.line_end));
+        multiline_annotations.sort_by_key(|(_, ml)| (ml.line_start, usize::MAX - ml.line_end));
         for (_, ann) in multiline_annotations.clone() {
             for (_, a) in multiline_annotations.iter_mut() {
                 // Move all other multiline annotations overlapping with this one
index eb0506c459afa732b0bf07918bf8adfde11659af..518b5ec10f8906122c4ab9fb26cc19e80231bf8a 100644 (file)
@@ -324,7 +324,7 @@ fn push_trailing(
                         // Account for the difference between the width of the current code and the
                         // snippet being suggested, so that the *later* suggestions are correctly
                         // aligned on the screen.
-                        acc += len as isize - (cur_hi.col.0 - cur_lo.col.0) as isize;
+                        acc += len - (cur_hi.col.0 - cur_lo.col.0) as isize;
                     }
                     prev_hi = cur_hi;
                     prev_line = sf.get_line(prev_hi.line - 1);
index 13e2d1ebbe7869530fc7e514d3884e3f6dd55926..00453f78287efb8ab9067dbbf1fae3a27e43984e 100644 (file)
@@ -1,3 +1,11 @@
+#![deny(rustc::untranslatable_diagnostic)]
+
+use crate::errors::{
+    ArgumentNotAttributes, AttrNoArguments, AttributeMetaItem, AttributeSingleWord,
+    AttributesWrongForm, CannotBeNameOfMacro, ExpectedCommaInList, HelperAttributeNameInvalid,
+    MacroBodyStability, MacroConstStability, NotAMetaItem, OnlyOneArgument, OnlyOneWord,
+    ResolveRelativePath, TakesNoArguments,
+};
 use crate::expand::{self, AstFragment, Invocation};
 use crate::module::DirOwnership;
 
@@ -26,7 +34,6 @@
 use rustc_span::{BytePos, FileName, RealFileName, Span, DUMMY_SP};
 use smallvec::{smallvec, SmallVec};
 
-use std::default::Default;
 use std::iter;
 use std::path::PathBuf;
 use std::rc::Rc;
@@ -789,26 +796,16 @@ pub fn new(
             .unwrap_or_else(|| (None, helper_attrs));
         let (stability, const_stability, body_stability) = attr::find_stability(&sess, attrs, span);
         if let Some((_, sp)) = const_stability {
-            sess.parse_sess
-                .span_diagnostic
-                .struct_span_err(sp, "macros cannot have const stability attributes")
-                .span_label(sp, "invalid const stability attribute")
-                .span_label(
-                    sess.source_map().guess_head_span(span),
-                    "const stability attribute affects this macro",
-                )
-                .emit();
+            sess.emit_err(MacroConstStability {
+                span: sp,
+                head_span: sess.source_map().guess_head_span(span),
+            });
         }
         if let Some((_, sp)) = body_stability {
-            sess.parse_sess
-                .span_diagnostic
-                .struct_span_err(sp, "macros cannot have body stability attributes")
-                .span_label(sp, "invalid body stability attribute")
-                .span_label(
-                    sess.source_map().guess_head_span(span),
-                    "body stability attribute affects this macro",
-                )
-                .emit();
+            sess.emit_err(MacroBodyStability {
+                span: sp,
+                head_span: sess.source_map().guess_head_span(span),
+            });
         }
 
         SyntaxExtension {
@@ -960,7 +957,7 @@ fn pre_expansion_lint(
         node_id: NodeId,
         attrs: &[Attribute],
         items: &[P<Item>],
-        name: &str,
+        name: Symbol,
     );
 }
 
@@ -1200,13 +1197,11 @@ pub fn resolve_path(
                 .expect("attempting to resolve a file path in an external file"),
             FileName::DocTest(path, _) => path,
             other => {
-                return Err(parse_sess.span_diagnostic.struct_span_err(
+                return Err(ResolveRelativePath {
                     span,
-                    &format!(
-                        "cannot resolve relative path in non-file source `{}`",
-                        parse_sess.source_map().filename_for_diagnostics(&other)
-                    ),
-                ));
+                    path: parse_sess.source_map().filename_for_diagnostics(&other).to_string(),
+                }
+                .into_diagnostic(&parse_sess.span_diagnostic));
             }
         };
         result.pop();
@@ -1222,6 +1217,8 @@ pub fn resolve_path(
 /// The returned bool indicates whether an applicable suggestion has already been
 /// added to the diagnostic to avoid emitting multiple suggestions. `Err(None)`
 /// indicates that an ast error was encountered.
+// FIXME(Nilstrieb) Make this function setup translatable
+#[allow(rustc::untranslatable_diagnostic)]
 pub fn expr_to_spanned_string<'a>(
     cx: &'a mut ExtCtxt<'_>,
     expr: P<ast::Expr>,
@@ -1234,7 +1231,7 @@ pub fn expr_to_spanned_string<'a>(
     Err(match expr.kind {
         ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) {
             Ok(ast::LitKind::Str(s, style)) => return Ok((s, style, expr.span)),
-            Ok(ast::LitKind::ByteStr(_)) => {
+            Ok(ast::LitKind::ByteStr(..)) => {
                 let mut err = cx.struct_span_err(expr.span, err_msg);
                 let span = expr.span.shrink_to_lo();
                 err.span_suggestion(
@@ -1280,9 +1277,9 @@ pub fn expr_to_string(
 /// compilation should call
 /// `cx.parse_sess.span_diagnostic.abort_if_errors()` (this should be
 /// done as rarely as possible).
-pub fn check_zero_tts(cx: &ExtCtxt<'_>, sp: Span, tts: TokenStream, name: &str) {
+pub fn check_zero_tts(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream, name: &str) {
     if !tts.is_empty() {
-        cx.span_err(sp, &format!("{} takes no arguments", name));
+        cx.emit_err(TakesNoArguments { span, name });
     }
 }
 
@@ -1304,31 +1301,27 @@ pub fn parse_expr(p: &mut parser::Parser<'_>) -> Option<P<ast::Expr>> {
 /// expect exactly one string literal, or emit an error and return `None`.
 pub fn get_single_str_from_tts(
     cx: &mut ExtCtxt<'_>,
-    sp: Span,
+    span: Span,
     tts: TokenStream,
     name: &str,
 ) -> Option<Symbol> {
     let mut p = cx.new_parser_from_tts(tts);
     if p.token == token::Eof {
-        cx.span_err(sp, &format!("{} takes 1 argument", name));
+        cx.emit_err(OnlyOneArgument { span, name });
         return None;
     }
     let ret = parse_expr(&mut p)?;
     let _ = p.eat(&token::Comma);
 
     if p.token != token::Eof {
-        cx.span_err(sp, &format!("{} takes 1 argument", name));
+        cx.emit_err(OnlyOneArgument { span, name });
     }
     expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| s)
 }
 
 /// Extracts comma-separated expressions from `tts`.
 /// On error, emit it, and return `None`.
-pub fn get_exprs_from_tts(
-    cx: &mut ExtCtxt<'_>,
-    sp: Span,
-    tts: TokenStream,
-) -> Option<Vec<P<ast::Expr>>> {
+pub fn get_exprs_from_tts(cx: &mut ExtCtxt<'_>, tts: TokenStream) -> Option<Vec<P<ast::Expr>>> {
     let mut p = cx.new_parser_from_tts(tts);
     let mut es = Vec::new();
     while p.token != token::Eof {
@@ -1343,7 +1336,7 @@ pub fn get_exprs_from_tts(
             continue;
         }
         if p.token != token::Eof {
-            cx.span_err(sp, "expected token: `,`");
+            cx.emit_err(ExpectedCommaInList { span: p.token.span });
             return None;
         }
     }
@@ -1353,64 +1346,58 @@ pub fn get_exprs_from_tts(
 pub fn parse_macro_name_and_helper_attrs(
     diag: &rustc_errors::Handler,
     attr: &Attribute,
-    descr: &str,
+    macro_type: &str,
 ) -> Option<(Symbol, Vec<Symbol>)> {
     // Once we've located the `#[proc_macro_derive]` attribute, verify
     // that it's of the form `#[proc_macro_derive(Foo)]` or
     // `#[proc_macro_derive(Foo, attributes(A, ..))]`
     let list = attr.meta_item_list()?;
     if list.len() != 1 && list.len() != 2 {
-        diag.span_err(attr.span, "attribute must have either one or two arguments");
+        diag.emit_err(AttrNoArguments { span: attr.span });
         return None;
     }
     let Some(trait_attr) = list[0].meta_item() else {
-        diag.span_err(list[0].span(), "not a meta item");
+        diag.emit_err(NotAMetaItem {span: list[0].span()});
         return None;
     };
     let trait_ident = match trait_attr.ident() {
         Some(trait_ident) if trait_attr.is_word() => trait_ident,
         _ => {
-            diag.span_err(trait_attr.span, "must only be one word");
+            diag.emit_err(OnlyOneWord { span: trait_attr.span });
             return None;
         }
     };
 
     if !trait_ident.name.can_be_raw() {
-        diag.span_err(
-            trait_attr.span,
-            &format!("`{}` cannot be a name of {} macro", trait_ident, descr),
-        );
+        diag.emit_err(CannotBeNameOfMacro { span: trait_attr.span, trait_ident, macro_type });
     }
 
     let attributes_attr = list.get(1);
     let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr {
         if !attr.has_name(sym::attributes) {
-            diag.span_err(attr.span(), "second argument must be `attributes`");
+            diag.emit_err(ArgumentNotAttributes { span: attr.span() });
         }
         attr.meta_item_list()
             .unwrap_or_else(|| {
-                diag.span_err(attr.span(), "attribute must be of form: `attributes(foo, bar)`");
+                diag.emit_err(AttributesWrongForm { span: attr.span() });
                 &[]
             })
             .iter()
             .filter_map(|attr| {
                 let Some(attr) = attr.meta_item() else {
-                    diag.span_err(attr.span(), "not a meta item");
+                    diag.emit_err(AttributeMetaItem { span: attr.span() });
                     return None;
                 };
 
                 let ident = match attr.ident() {
                     Some(ident) if attr.is_word() => ident,
                     _ => {
-                        diag.span_err(attr.span, "must only be one word");
+                        diag.emit_err(AttributeSingleWord { span: attr.span });
                         return None;
                     }
                 };
                 if !ident.name.can_be_raw() {
-                    diag.span_err(
-                        attr.span,
-                        &format!("`{}` cannot be a name of derive helper attribute", ident),
-                    );
+                    diag.emit_err(HelperAttributeNameInvalid { span: attr.span, name: ident });
                 }
 
                 Some(ident.name)
index 4812bdd9dd8b9c50097fab9ebaa332a65f896bc5..ef50efb81253fccd1c224c92f9a61e7d34b9471c 100644 (file)
@@ -1,8 +1,7 @@
 use crate::base::ExtCtxt;
-use rustc_ast::attr;
 use rustc_ast::ptr::P;
 use rustc_ast::{self as ast, AttrVec, BlockCheckMode, Expr, LocalKind, PatKind, UnOp};
-use rustc_data_structures::sync::Lrc;
+use rustc_ast::{attr, token, util::literal};
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::Span;
@@ -332,36 +331,36 @@ pub fn expr_struct_ident(
         self.expr_struct(span, self.path_ident(span, id), fields)
     }
 
-    fn expr_lit(&self, span: Span, lit_kind: ast::LitKind) -> P<ast::Expr> {
-        let token_lit = lit_kind.to_token_lit();
-        self.expr(span, ast::ExprKind::Lit(token_lit))
+    pub fn expr_usize(&self, span: Span, n: usize) -> P<ast::Expr> {
+        let suffix = Some(ast::UintTy::Usize.name());
+        let lit = token::Lit::new(token::Integer, sym::integer(n), suffix);
+        self.expr(span, ast::ExprKind::Lit(lit))
     }
 
-    pub fn expr_usize(&self, span: Span, i: usize) -> P<ast::Expr> {
-        self.expr_lit(
-            span,
-            ast::LitKind::Int(i as u128, ast::LitIntType::Unsigned(ast::UintTy::Usize)),
-        )
-    }
-
-    pub fn expr_u32(&self, sp: Span, u: u32) -> P<ast::Expr> {
-        self.expr_lit(sp, ast::LitKind::Int(u as u128, ast::LitIntType::Unsigned(ast::UintTy::U32)))
+    pub fn expr_u32(&self, span: Span, n: u32) -> P<ast::Expr> {
+        let suffix = Some(ast::UintTy::U32.name());
+        let lit = token::Lit::new(token::Integer, sym::integer(n), suffix);
+        self.expr(span, ast::ExprKind::Lit(lit))
     }
 
-    pub fn expr_bool(&self, sp: Span, value: bool) -> P<ast::Expr> {
-        self.expr_lit(sp, ast::LitKind::Bool(value))
+    pub fn expr_bool(&self, span: Span, value: bool) -> P<ast::Expr> {
+        let lit = token::Lit::new(token::Bool, if value { kw::True } else { kw::False }, None);
+        self.expr(span, ast::ExprKind::Lit(lit))
     }
 
-    pub fn expr_str(&self, sp: Span, s: Symbol) -> P<ast::Expr> {
-        self.expr_lit(sp, ast::LitKind::Str(s, ast::StrStyle::Cooked))
+    pub fn expr_str(&self, span: Span, s: Symbol) -> P<ast::Expr> {
+        let lit = token::Lit::new(token::Str, literal::escape_string_symbol(s), None);
+        self.expr(span, ast::ExprKind::Lit(lit))
     }
 
-    pub fn expr_char(&self, sp: Span, ch: char) -> P<ast::Expr> {
-        self.expr_lit(sp, ast::LitKind::Char(ch))
+    pub fn expr_char(&self, span: Span, ch: char) -> P<ast::Expr> {
+        let lit = token::Lit::new(token::Char, literal::escape_char_symbol(ch), None);
+        self.expr(span, ast::ExprKind::Lit(lit))
     }
 
-    pub fn expr_byte_str(&self, sp: Span, bytes: Vec<u8>) -> P<ast::Expr> {
-        self.expr_lit(sp, ast::LitKind::ByteStr(Lrc::from(bytes)))
+    pub fn expr_byte_str(&self, span: Span, bytes: Vec<u8>) -> P<ast::Expr> {
+        let lit = token::Lit::new(token::ByteStr, literal::escape_byte_str_symbol(&bytes), None);
+        self.expr(span, ast::ExprKind::Lit(lit))
     }
 
     /// `[expr1, expr2, ...]`
index 2510795c2e3ed5073c6aa07a2331b06c87f02e17..f4c6f3386ade23ce244e629ce715ce72a37d83e7 100644 (file)
@@ -1,5 +1,9 @@
 //! Conditional compilation stripping.
 
+use crate::errors::{
+    FeatureIncludedInEdition, FeatureNotAllowed, FeatureRemoved, FeatureRemovedReason, InvalidCfg,
+    MalformedFeatureAttribute, MalformedFeatureAttributeHelp, RemoveExprNotSupported,
+};
 use rustc_ast::ptr::P;
 use rustc_ast::token::{Delimiter, Token, TokenKind};
 use rustc_ast::tokenstream::{AttrTokenStream, AttrTokenTree};
@@ -10,7 +14,6 @@
 use rustc_attr as attr;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::map_in_place::MapInPlace;
-use rustc_errors::{error_code, struct_span_err, Applicability, Handler};
 use rustc_feature::{Feature, Features, State as FeatureState};
 use rustc_feature::{
     ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES, STABLE_REMOVED_FEATURES,
@@ -33,18 +36,12 @@ pub struct StripUnconfigured<'a> {
     pub lint_node_id: NodeId,
 }
 
-fn get_features(
-    sess: &Session,
-    span_handler: &Handler,
-    krate_attrs: &[ast::Attribute],
-) -> Features {
-    fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) {
-        let mut err = struct_span_err!(span_handler, span, E0557, "feature has been removed");
-        err.span_label(span, "feature has been removed");
-        if let Some(reason) = reason {
-            err.note(reason);
-        }
-        err.emit();
+fn get_features(sess: &Session, krate_attrs: &[ast::Attribute]) -> Features {
+    fn feature_removed(sess: &Session, span: Span, reason: Option<&str>) {
+        sess.emit_err(FeatureRemoved {
+            span,
+            reason: reason.map(|reason| FeatureRemovedReason { reason }),
+        });
     }
 
     fn active_features_up_to(edition: Edition) -> impl Iterator<Item = &'static Feature> {
@@ -117,34 +114,34 @@ fn active_features_up_to(edition: Edition) -> impl Iterator<Item = &'static Feat
             continue;
         };
 
-        let bad_input = |span| {
-            struct_span_err!(span_handler, span, E0556, "malformed `feature` attribute input")
-        };
-
         for mi in list {
             let name = match mi.ident() {
                 Some(ident) if mi.is_word() => ident.name,
                 Some(ident) => {
-                    bad_input(mi.span())
-                        .span_suggestion(
-                            mi.span(),
-                            "expected just one word",
-                            ident.name,
-                            Applicability::MaybeIncorrect,
-                        )
-                        .emit();
+                    sess.emit_err(MalformedFeatureAttribute {
+                        span: mi.span(),
+                        help: MalformedFeatureAttributeHelp::Suggestion {
+                            span: mi.span(),
+                            suggestion: ident.name,
+                        },
+                    });
                     continue;
                 }
                 None => {
-                    bad_input(mi.span()).span_label(mi.span(), "expected just one word").emit();
+                    sess.emit_err(MalformedFeatureAttribute {
+                        span: mi.span(),
+                        help: MalformedFeatureAttributeHelp::Label { span: mi.span() },
+                    });
                     continue;
                 }
             };
 
-            if let Some(edition) = edition_enabled_features.get(&name) {
-                let msg =
-                    &format!("the feature `{}` is included in the Rust {} edition", name, edition);
-                span_handler.struct_span_warn_with_code(mi.span(), msg, error_code!(E0705)).emit();
+            if let Some(&edition) = edition_enabled_features.get(&name) {
+                sess.emit_warning(FeatureIncludedInEdition {
+                    span: mi.span(),
+                    feature: name,
+                    edition,
+                });
                 continue;
             }
 
@@ -159,7 +156,7 @@ fn active_features_up_to(edition: Edition) -> impl Iterator<Item = &'static Feat
                 if let FeatureState::Removed { reason } | FeatureState::Stabilized { reason } =
                     state
                 {
-                    feature_removed(span_handler, mi.span(), *reason);
+                    feature_removed(sess, mi.span(), *reason);
                     continue;
                 }
             }
@@ -173,14 +170,7 @@ fn active_features_up_to(edition: Edition) -> impl Iterator<Item = &'static Feat
 
             if let Some(allowed) = sess.opts.unstable_opts.allow_features.as_ref() {
                 if allowed.iter().all(|f| name.as_str() != f) {
-                    struct_span_err!(
-                        span_handler,
-                        mi.span(),
-                        E0725,
-                        "the feature `{}` is not in the list of allowed features",
-                        name
-                    )
-                    .emit();
+                    sess.emit_err(FeatureNotAllowed { span: mi.span(), name });
                     continue;
                 }
             }
@@ -221,7 +211,7 @@ pub fn features(
         }
         Some(attrs) => {
             krate.attrs = attrs;
-            let features = get_features(sess, diag, &krate.attrs);
+            let features = get_features(sess, &krate.attrs);
             if err_count == diag.err_count() {
                 // Avoid reconfiguring malformed `cfg_attr`s.
                 strip_unconfigured.features = Some(&features);
@@ -503,8 +493,7 @@ pub fn configure_expr(&self, expr: &mut P<ast::Expr>, method_receiver: bool) {
         // N.B., this is intentionally not part of the visit_expr() function
         //     in order for filter_map_expr() to be able to avoid this check
         if let Some(attr) = expr.attrs().iter().find(|a| is_cfg(*a)) {
-            let msg = "removing an expression is not supported in this position";
-            self.sess.parse_sess.span_diagnostic.span_err(attr.span, msg);
+            self.sess.emit_err(RemoveExprNotSupported { span: attr.span });
         }
 
         self.process_cfg_attrs(expr);
@@ -513,27 +502,26 @@ pub fn configure_expr(&self, expr: &mut P<ast::Expr>, method_receiver: bool) {
 }
 
 pub fn parse_cfg<'a>(meta_item: &'a MetaItem, sess: &Session) -> Option<&'a MetaItem> {
-    let error = |span, msg, suggestion: &str| {
-        let mut err = sess.parse_sess.span_diagnostic.struct_span_err(span, msg);
-        if !suggestion.is_empty() {
-            err.span_suggestion(
-                span,
-                "expected syntax is",
-                suggestion,
-                Applicability::HasPlaceholders,
-            );
-        }
-        err.emit();
-        None
-    };
     let span = meta_item.span;
     match meta_item.meta_item_list() {
-        None => error(span, "`cfg` is not followed by parentheses", "cfg(/* predicate */)"),
-        Some([]) => error(span, "`cfg` predicate is not specified", ""),
-        Some([_, .., l]) => error(l.span(), "multiple `cfg` predicates are specified", ""),
+        None => {
+            sess.emit_err(InvalidCfg::NotFollowedByParens { span });
+            None
+        }
+        Some([]) => {
+            sess.emit_err(InvalidCfg::NoPredicate { span });
+            None
+        }
+        Some([_, .., l]) => {
+            sess.emit_err(InvalidCfg::MultiplePredicates { span: l.span() });
+            None
+        }
         Some([single]) => match single.meta_item() {
             Some(meta_item) => Some(meta_item),
-            None => error(single.span(), "`cfg` predicate key cannot be a literal", ""),
+            None => {
+                sess.emit_err(InvalidCfg::PredicateLiteral { span: single.span() });
+                None
+            }
         },
     }
 }
index d383f4832f6999469ed43a96dbddd7d7a532b3a7..afe5169d3f5c0b616754ddf8ac7fa80ebd12b894 100644 (file)
@@ -1,6 +1,10 @@
+use rustc_ast::ast;
 use rustc_macros::Diagnostic;
-use rustc_span::symbol::MacroRulesNormalizedIdent;
-use rustc_span::Span;
+use rustc_session::Limit;
+use rustc_span::edition::Edition;
+use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent};
+use rustc_span::{Span, Symbol};
+use std::borrow::Cow;
 
 #[derive(Diagnostic)]
 #[diag(expand_expr_repeat_no_syntax_vars)]
@@ -46,3 +50,321 @@ pub(crate) struct MetaVarsDifSeqMatchers {
     pub span: Span,
     pub msg: String,
 }
+
+#[derive(Diagnostic)]
+#[diag(expand_resolve_relative_path)]
+pub(crate) struct ResolveRelativePath {
+    #[primary_span]
+    pub span: Span,
+    pub path: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_macro_const_stability)]
+pub(crate) struct MacroConstStability {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    #[label(label2)]
+    pub head_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_macro_body_stability)]
+pub(crate) struct MacroBodyStability {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    #[label(label2)]
+    pub head_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_attr_no_arguments)]
+pub(crate) struct AttrNoArguments {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_not_a_meta_item)]
+pub(crate) struct NotAMetaItem {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_only_one_word)]
+pub(crate) struct OnlyOneWord {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_cannot_be_name_of_macro)]
+pub(crate) struct CannotBeNameOfMacro<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub trait_ident: Ident,
+    pub macro_type: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_arg_not_attributes)]
+pub(crate) struct ArgumentNotAttributes {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_attributes_wrong_form)]
+pub(crate) struct AttributesWrongForm {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_attribute_meta_item)]
+pub(crate) struct AttributeMetaItem {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_attribute_single_word)]
+pub(crate) struct AttributeSingleWord {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_helper_attribute_name_invalid)]
+pub(crate) struct HelperAttributeNameInvalid {
+    #[primary_span]
+    pub span: Span,
+    pub name: Ident,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_expected_comma_in_list)]
+pub(crate) struct ExpectedCommaInList {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_only_one_argument)]
+pub(crate) struct OnlyOneArgument<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub name: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_takes_no_arguments)]
+pub(crate) struct TakesNoArguments<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub name: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_feature_included_in_edition, code = "E0705")]
+pub(crate) struct FeatureIncludedInEdition {
+    #[primary_span]
+    pub span: Span,
+    pub feature: Symbol,
+    pub edition: Edition,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_feature_removed, code = "E0557")]
+pub(crate) struct FeatureRemoved<'a> {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    #[subdiagnostic]
+    pub reason: Option<FeatureRemovedReason<'a>>,
+}
+
+#[derive(Subdiagnostic)]
+#[note(reason)]
+pub(crate) struct FeatureRemovedReason<'a> {
+    pub reason: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_feature_not_allowed, code = "E0725")]
+pub(crate) struct FeatureNotAllowed {
+    #[primary_span]
+    pub span: Span,
+    pub name: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_recursion_limit_reached)]
+#[help]
+pub(crate) struct RecursionLimitReached<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub descr: String,
+    pub suggested_limit: Limit,
+    pub crate_name: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_malformed_feature_attribute, code = "E0556")]
+pub(crate) struct MalformedFeatureAttribute {
+    #[primary_span]
+    pub span: Span,
+    #[subdiagnostic]
+    pub help: MalformedFeatureAttributeHelp,
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum MalformedFeatureAttributeHelp {
+    #[label(expected)]
+    Label {
+        #[primary_span]
+        span: Span,
+    },
+    #[suggestion(expected, code = "{suggestion}", applicability = "maybe-incorrect")]
+    Suggestion {
+        #[primary_span]
+        span: Span,
+        suggestion: Symbol,
+    },
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_remove_expr_not_supported)]
+pub(crate) struct RemoveExprNotSupported {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+pub(crate) enum InvalidCfg {
+    #[diag(expand_invalid_cfg_no_parens)]
+    NotFollowedByParens {
+        #[primary_span]
+        #[suggestion(
+            expand_invalid_cfg_expected_syntax,
+            code = "cfg(/* predicate */)",
+            applicability = "has-placeholders"
+        )]
+        span: Span,
+    },
+    #[diag(expand_invalid_cfg_no_predicate)]
+    NoPredicate {
+        #[primary_span]
+        #[suggestion(
+            expand_invalid_cfg_expected_syntax,
+            code = "cfg(/* predicate */)",
+            applicability = "has-placeholders"
+        )]
+        span: Span,
+    },
+    #[diag(expand_invalid_cfg_multiple_predicates)]
+    MultiplePredicates {
+        #[primary_span]
+        span: Span,
+    },
+    #[diag(expand_invalid_cfg_predicate_literal)]
+    PredicateLiteral {
+        #[primary_span]
+        span: Span,
+    },
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_wrong_fragment_kind)]
+pub(crate) struct WrongFragmentKind<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub kind: &'a str,
+    pub name: &'a ast::Path,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_unsupported_key_value)]
+pub(crate) struct UnsupportedKeyValue {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_incomplete_parse)]
+#[note]
+pub(crate) struct IncompleteParse<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub token: Cow<'a, str>,
+    #[label]
+    pub label_span: Span,
+    pub macro_path: &'a ast::Path,
+    pub kind_name: &'a str,
+
+    #[suggestion(
+        suggestion_add_semi,
+        style = "verbose",
+        code = ";",
+        applicability = "maybe-incorrect"
+    )]
+    pub add_semicolon: Option<Span>,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_remove_node_not_supported)]
+pub(crate) struct RemoveNodeNotSupported {
+    #[primary_span]
+    pub span: Span,
+    pub descr: &'static str,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_module_circular)]
+pub(crate) struct ModuleCircular {
+    #[primary_span]
+    pub span: Span,
+    pub modules: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_module_in_block)]
+pub(crate) struct ModuleInBlock {
+    #[primary_span]
+    pub span: Span,
+    #[subdiagnostic]
+    pub name: Option<ModuleInBlockName>,
+}
+
+#[derive(Subdiagnostic)]
+#[note(note)]
+pub(crate) struct ModuleInBlockName {
+    #[primary_span]
+    pub span: Span,
+    pub name: Ident,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_module_file_not_found, code = "E0583")]
+#[help]
+pub(crate) struct ModuleFileNotFound {
+    #[primary_span]
+    pub span: Span,
+    pub name: Ident,
+    pub default_path: String,
+    pub secondary_path: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_module_multiple_candidates, code = "E0761")]
+#[help]
+pub(crate) struct ModuleMultipleCandidates {
+    #[primary_span]
+    pub span: Span,
+    pub name: Ident,
+    pub default_path: String,
+    pub secondary_path: String,
+}
index e799fa404f6fd127465d6e5c0bf8d571e55e745b..e26c16dcd7ee7784e4597cddbb6f073c9ea56657 100644 (file)
@@ -1,5 +1,9 @@
 use crate::base::*;
 use crate::config::StripUnconfigured;
+use crate::errors::{
+    IncompleteParse, RecursionLimitReached, RemoveExprNotSupported, RemoveNodeNotSupported,
+    UnsupportedKeyValue, WrongFragmentKind,
+};
 use crate::hygiene::SyntaxContext;
 use crate::mbe::diagnostics::annotate_err_with_kind;
 use crate::module::{mod_dir_path, parse_external_mod, DirOwnership, ParsedExternalMod};
@@ -18,7 +22,7 @@
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::map_in_place::MapInPlace;
 use rustc_data_structures::sync::Lrc;
-use rustc_errors::{Applicability, PResult};
+use rustc_errors::PResult;
 use rustc_feature::Features;
 use rustc_parse::parser::{
     AttemptLocalParseRecovery, CommaRecoveryMode, ForceCollect, Parser, RecoverColon, RecoverComma,
@@ -606,29 +610,22 @@ fn error_recursion_limit_reached(&mut self) {
             Limit(0) => Limit(2),
             limit => limit * 2,
         };
-        self.cx
-            .struct_span_err(
-                expn_data.call_site,
-                &format!("recursion limit reached while expanding `{}`", expn_data.kind.descr()),
-            )
-            .help(&format!(
-                "consider increasing the recursion limit by adding a \
-                 `#![recursion_limit = \"{}\"]` attribute to your crate (`{}`)",
-                suggested_limit, self.cx.ecfg.crate_name,
-            ))
-            .emit();
+
+        self.cx.emit_err(RecursionLimitReached {
+            span: expn_data.call_site,
+            descr: expn_data.kind.descr(),
+            suggested_limit,
+            crate_name: &self.cx.ecfg.crate_name,
+        });
+
         self.cx.trace_macros_diag();
     }
 
     /// A macro's expansion does not fit in this fragment kind.
     /// For example, a non-type macro in a type position.
     fn error_wrong_fragment_kind(&mut self, kind: AstFragmentKind, mac: &ast::MacCall, span: Span) {
-        let msg = format!(
-            "non-{kind} macro in {kind} position: {path}",
-            kind = kind.name(),
-            path = pprust::path_to_string(&mac.path),
-        );
-        self.cx.span_err(span, &msg);
+        self.cx.emit_err(WrongFragmentKind { span, kind: kind.name(), name: &mac.path });
+
         self.cx.trace_macros_diag();
     }
 
@@ -707,7 +704,7 @@ fn expand_invoc(
                     };
                     let attr_item = attr.unwrap_normal_item();
                     if let AttrArgs::Eq(..) = attr_item.args {
-                        self.cx.span_err(span, "key-value macro attributes are not supported");
+                        self.cx.emit_err(UnsupportedKeyValue { span });
                     }
                     let inner_tokens = attr_item.args.inner_tokens();
                     let Ok(tok_result) = expander.expand(self.cx, span, inner_tokens, tokens) else {
@@ -729,9 +726,7 @@ fn expand_invoc(
                                 }
                             };
                             if fragment_kind == AstFragmentKind::Expr && items.is_empty() {
-                                let msg =
-                                    "removing an expression is not supported in this position";
-                                self.cx.span_err(span, msg);
+                                self.cx.emit_err(RemoveExprNotSupported { span });
                                 fragment_kind.dummy(span)
                             } else {
                                 fragment_kind.expect_from_annotatables(items)
@@ -939,38 +934,32 @@ pub fn parse_ast_fragment<'a>(
 }
 
 pub fn ensure_complete_parse<'a>(
-    this: &mut Parser<'a>,
+    parser: &mut Parser<'a>,
     macro_path: &ast::Path,
     kind_name: &str,
     span: Span,
 ) {
-    if this.token != token::Eof {
-        let token = pprust::token_to_string(&this.token);
-        let msg = format!("macro expansion ignores token `{}` and any following", token);
+    if parser.token != token::Eof {
+        let token = pprust::token_to_string(&parser.token);
         // Avoid emitting backtrace info twice.
-        let def_site_span = this.token.span.with_ctxt(SyntaxContext::root());
-        let mut err = this.struct_span_err(def_site_span, &msg);
-        err.span_label(span, "caused by the macro expansion here");
-        let msg = format!(
-            "the usage of `{}!` is likely invalid in {} context",
-            pprust::path_to_string(macro_path),
-            kind_name,
-        );
-        err.note(&msg);
+        let def_site_span = parser.token.span.with_ctxt(SyntaxContext::root());
 
-        let semi_span = this.sess.source_map().next_point(span);
-        match this.sess.source_map().span_to_snippet(semi_span) {
+        let semi_span = parser.sess.source_map().next_point(span);
+        let add_semicolon = match parser.sess.source_map().span_to_snippet(semi_span) {
             Ok(ref snippet) if &snippet[..] != ";" && kind_name == "expression" => {
-                err.span_suggestion(
-                    span.shrink_to_hi(),
-                    "you might be missing a semicolon here",
-                    ";",
-                    Applicability::MaybeIncorrect,
-                );
+                Some(span.shrink_to_hi())
             }
-            _ => {}
-        }
-        err.emit();
+            _ => None,
+        };
+
+        parser.sess.emit_err(IncompleteParse {
+            span: def_site_span,
+            token,
+            label_span: span,
+            macro_path,
+            kind_name,
+            add_semicolon,
+        });
     }
 }
 
@@ -1122,7 +1111,7 @@ fn wrap_flat_map_node_noop_flat_map(
                         ecx.current_expansion.lint_node_id,
                         &attrs,
                         &items,
-                        ident.name.as_str(),
+                        ident.name,
                     );
                 }
 
@@ -1766,9 +1755,8 @@ fn visit_node<Node: InvocationCollectorNode<OutputTy = Node> + DummyAstNode>(
                         if self.expand_cfg_true(node, attr, pos) {
                             continue;
                         }
-                        let msg =
-                            format!("removing {} is not supported in this position", Node::descr());
-                        self.cx.span_err(span, &msg);
+
+                        self.cx.emit_err(RemoveNodeNotSupported { span, descr: Node::descr() });
                         continue;
                     }
                     sym::cfg_attr => {
index b34de94fb7db4a43579cf08200ccf1b0399d012b..897268566358a5b0fae9d68c08e4c6655a3e57b5 100644 (file)
@@ -10,6 +10,7 @@
 #![feature(rustc_attrs)]
 #![feature(try_blocks)]
 #![recursion_limit = "256"]
+#![deny(rustc::untranslatable_diagnostic)]
 
 #[macro_use]
 extern crate rustc_macros;
 pub mod errors;
 pub mod expand;
 pub mod module;
+
+// FIXME(Nilstrieb) Translate proc_macro diagnostics
+#[allow(rustc::untranslatable_diagnostic)]
 pub mod proc_macro;
 
+// FIXME(Nilstrieb) Translate macro_rules diagnostics
+#[allow(rustc::untranslatable_diagnostic)]
 pub(crate) mod mbe;
 
 // HACK(Centril, #64197): These shouldn't really be here.
index 8994a2f78919f046bdad82d253460101ebb2cdbf..0b8847f827df1aa6ad9b8a056ccadba7d03ed9aa 100644 (file)
@@ -468,7 +468,7 @@ fn check_nested_occurrences(
                 // We check that the meta-variable is correctly used.
                 check_occurrences(sess, node_id, tt, macros, binders, ops, valid);
             }
-            (NestedMacroState::MacroName, &TokenTree::Delimited(_, ref del))
+            (NestedMacroState::MacroName, TokenTree::Delimited(_, del))
                 if del.delim == Delimiter::Parenthesis =>
             {
                 state = NestedMacroState::MacroNameParen;
@@ -483,7 +483,7 @@ fn check_nested_occurrences(
                     valid,
                 );
             }
-            (NestedMacroState::MacroNameParen, &TokenTree::Delimited(_, ref del))
+            (NestedMacroState::MacroNameParen, TokenTree::Delimited(_, del))
                 if del.delim == Delimiter::Brace =>
             {
                 state = NestedMacroState::Empty;
index 2dbb90e2190f0db42004859a03b5455d9995f19a..320c533a66e5d0bfc1b47367765394d928277d10 100644 (file)
@@ -792,7 +792,7 @@ fn first(&self, tts: &'tt [mbe::TokenTree]) -> TokenSet<'tt> {
                 TokenTree::Sequence(sp, ref seq_rep) => {
                     let subfirst_owned;
                     let subfirst = match self.first.get(&sp.entire()) {
-                        Some(&Some(ref subfirst)) => subfirst,
+                        Some(Some(subfirst)) => subfirst,
                         Some(&None) => {
                             subfirst_owned = self.first(&seq_rep.tts);
                             &subfirst_owned
index 9002a24e42f9df671dc913fe744306dd480909ef..07f47a9c3a4f2c80f9097d22e55b2581440f5135 100644 (file)
@@ -1,13 +1,17 @@
 use crate::base::ModuleData;
+use crate::errors::{
+    ModuleCircular, ModuleFileNotFound, ModuleInBlock, ModuleInBlockName, ModuleMultipleCandidates,
+};
 use rustc_ast::ptr::P;
 use rustc_ast::{token, AttrVec, Attribute, Inline, Item, ModSpans};
-use rustc_errors::{struct_span_err, DiagnosticBuilder, ErrorGuaranteed};
+use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
 use rustc_parse::new_parser_from_file;
 use rustc_parse::validate_attr;
 use rustc_session::parse::ParseSess;
 use rustc_session::Session;
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::Span;
+use std::iter::once;
 
 use std::path::{self, Path, PathBuf};
 
@@ -242,57 +246,41 @@ pub fn default_submod_path<'a>(
 
 impl ModError<'_> {
     fn report(self, sess: &Session, span: Span) -> ErrorGuaranteed {
-        let diag = &sess.parse_sess.span_diagnostic;
         match self {
             ModError::CircularInclusion(file_paths) => {
-                let mut msg = String::from("circular modules: ");
-                for file_path in &file_paths {
-                    msg.push_str(&file_path.display().to_string());
-                    msg.push_str(" -> ");
-                }
-                msg.push_str(&file_paths[0].display().to_string());
-                diag.struct_span_err(span, &msg)
-            }
-            ModError::ModInBlock(ident) => {
-                let msg = "cannot declare a non-inline module inside a block unless it has a path attribute";
-                let mut err = diag.struct_span_err(span, msg);
-                if let Some(ident) = ident {
-                    let note =
-                        format!("maybe `use` the module `{}` instead of redeclaring it", ident);
-                    err.span_note(span, &note);
-                }
-                err
+                let path_to_string = |path: &PathBuf| path.display().to_string();
+
+                let paths = file_paths
+                    .iter()
+                    .map(path_to_string)
+                    .chain(once(path_to_string(&file_paths[0])))
+                    .collect::<Vec<_>>();
+
+                let modules = paths.join(" -> ");
+
+                sess.emit_err(ModuleCircular { span, modules })
             }
-            ModError::FileNotFound(ident, default_path, secondary_path) => {
-                let mut err = struct_span_err!(
-                    diag,
+            ModError::ModInBlock(ident) => sess.emit_err(ModuleInBlock {
+                span,
+                name: ident.map(|name| ModuleInBlockName { span, name }),
+            }),
+            ModError::FileNotFound(name, default_path, secondary_path) => {
+                sess.emit_err(ModuleFileNotFound {
                     span,
-                    E0583,
-                    "file not found for module `{}`",
-                    ident,
-                );
-                err.help(&format!(
-                    "to create the module `{}`, create file \"{}\" or \"{}\"",
-                    ident,
-                    default_path.display(),
-                    secondary_path.display(),
-                ));
-                err
+                    name,
+                    default_path: default_path.display().to_string(),
+                    secondary_path: secondary_path.display().to_string(),
+                })
             }
-            ModError::MultipleCandidates(ident, default_path, secondary_path) => {
-                let mut err = struct_span_err!(
-                    diag,
+            ModError::MultipleCandidates(name, default_path, secondary_path) => {
+                sess.emit_err(ModuleMultipleCandidates {
                     span,
-                    E0761,
-                    "file for module `{}` found at both \"{}\" and \"{}\"",
-                    ident,
-                    default_path.display(),
-                    secondary_path.display(),
-                );
-                err.help("delete or rename one of them to remove the ambiguity");
-                err
+                    name,
+                    default_path: default_path.display().to_string(),
+                    secondary_path: secondary_path.display().to_string(),
+                })
             }
-            ModError::ParserError(err) => err,
-        }.emit()
+            ModError::ParserError(mut err) => err.emit(),
+        }
     }
 }
index 7616579611711984161c740745240ab4a9bac203..768bdab8a54199a10aec996bc8c9a6bfa897f17c 100644 (file)
@@ -6,6 +6,7 @@
 use rustc_ast as ast;
 use rustc_ast::token;
 use rustc_ast::tokenstream::{self, Spacing::*, TokenStream};
+use rustc_ast::util::literal::escape_byte_str_symbol;
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
@@ -526,7 +527,7 @@ fn expand_expr(&mut self, stream: &Self::TokenStream) -> Result<Self::TokenStrea
                 Ok(tokenstream::TokenStream::token_alone(token::Literal(*token_lit), expr.span))
             }
             ast::ExprKind::IncludedBytes(bytes) => {
-                let lit = ast::LitKind::ByteStr(bytes.clone()).to_token_lit();
+                let lit = token::Lit::new(token::ByteStr, escape_byte_str_symbol(bytes), None);
                 Ok(tokenstream::TokenStream::token_alone(token::TokenKind::Literal(lit), expr.span))
             }
             ast::ExprKind::Unary(ast::UnOp::Neg, e) => match &e.kind {
index 539b04535a0d028f8f45f2cbabfe8828e97802ce..8f3bea29ffd2897ee30178c82969f485fcb9c8b3 100644 (file)
@@ -154,6 +154,7 @@ fn test_harness(file_text: &str, span_labels: Vec<SpanLabel>, expected_output: &
             false,
         );
         let handler = Handler::with_emitter(true, None, Box::new(emitter));
+        #[allow(rustc::untranslatable_diagnostic)]
         handler.span_err(msp, "foo");
 
         assert!(
index 7678ce323dfbc04fb0f254e47e214ca9ed833e68..e5348039edd62c396847e0f581e14846566ce648 100644 (file)
@@ -126,6 +126,8 @@ macro_rules! declare_features {
     (accepted, copy_closures, "1.26.0", Some(44490), None),
     /// Allows `crate` in paths.
     (accepted, crate_in_paths, "1.30.0", Some(45477), None),
+    /// Allows rustc to inject a default alloc_error_handler
+    (accepted, default_alloc_error_handler, "CURRENT_RUSTC_VERSION", Some(66741), None),
     /// Allows using assigning a default type to type parameters in algebraic data type definitions.
     (accepted, default_type_params, "1.0.0", None, None),
     /// Allows `#[deprecated]` attribute.
index 69c5297bf6b82564395b902052c9ce01ec38e3fa..a616dd70f8e6ddb2e216ce73a9e97dde707f75a4 100644 (file)
@@ -368,8 +368,6 @@ pub fn set(&self, features: &mut Features, span: Span) {
     (active, debugger_visualizer, "1.62.0", Some(95939), None),
     /// Allows declarative macros 2.0 (`macro`).
     (active, decl_macro, "1.17.0", Some(39412), None),
-    /// Allows rustc to inject a default alloc_error_handler
-    (active, default_alloc_error_handler, "1.48.0", Some(66741), None),
     /// Allows default type parameters to influence type inference.
     (active, default_type_parameter_fallback, "1.3.0", Some(27336), None),
     /// Allows using `#[deprecated_safe]` to deprecate the safeness of a function or trait
index 4b6e068db4312505c647c66023a49332d133cd57..6d8e78a0f185dc6a16c577b6bb2a6c386f51389a 100644 (file)
@@ -394,7 +394,7 @@ pub struct BuiltinAttribute {
     ungated!(instruction_set, Normal, template!(List: "set"), ErrorPreceding),
     gated!(
         no_sanitize, Normal,
-        template!(List: "address, memory, thread"), DuplicatesOk,
+        template!(List: "address, kcfi, memory, thread"), DuplicatesOk,
         experimental!(no_sanitize)
     ),
     gated!(no_coverage, Normal, template!(Word), WarnFollowing, experimental!(no_coverage)),
index 636e6e1b48d0ed61e8c64ca9aca4dd3442bddd77..91825c29258ac10bd345aedbd19fcf35faa1da72 100644 (file)
@@ -548,12 +548,7 @@ pub const fn empty() -> &'hir Generics<'hir> {
     }
 
     pub fn get_named(&self, name: Symbol) -> Option<&GenericParam<'hir>> {
-        for param in self.params {
-            if name == param.name.ident().name {
-                return Some(param);
-            }
-        }
-        None
+        self.params.iter().find(|&param| name == param.name.ident().name)
     }
 
     pub fn spans(&self) -> MultiSpan {
@@ -827,7 +822,7 @@ pub fn get(&self, id: ItemLocalId) -> &'tcx [Attribute] {
 pub struct OwnerNodes<'tcx> {
     /// Pre-computed hash of the full HIR.
     pub hash_including_bodies: Fingerprint,
-    /// Pre-computed hash of the item signature, sithout recursing into the body.
+    /// Pre-computed hash of the item signature, without recursing into the body.
     pub hash_without_bodies: Fingerprint,
     /// Full HIR for the current owner.
     // The zeroth node's parent should never be accessed: the owner's parent is computed by the
index 6e2fbf96cbfb3f26aabf1eb23901dffc687d68d8..e870aa543d0b5ce9737ae0deb2b0ae7de088714e 100644 (file)
@@ -6,7 +6,7 @@
 use rustc_span::symbol::Ident;
 use rustc_span::Span;
 
-use std::iter::{Enumerate, ExactSizeIterator};
+use std::iter::Enumerate;
 
 pub struct EnumerateAndAdjust<I> {
     enumerate: Enumerate<I>,
index 4636d515249d9809ed55b2fe182ef3a2c63e7ab8..d4791150947fb1fa3fa9f7a529ee113f59fea059 100644 (file)
@@ -1,5 +1,7 @@
 use crate::definitions::{DefKey, DefPathData, DisambiguatedDefPathData};
 use rustc_span::def_id::{DefPathHash, StableCrateId};
+use rustc_span::edition::Edition;
+use rustc_span::{create_session_if_not_set_then, Symbol};
 
 #[test]
 fn def_path_hash_depends_on_crate_id() {
@@ -11,26 +13,28 @@ fn def_path_hash_depends_on_crate_id() {
     // the crate by changing the crate disambiguator (e.g. via bumping the
     // crate's version number).
 
-    let id0 = StableCrateId::new("foo", false, vec!["1".to_string()]);
-    let id1 = StableCrateId::new("foo", false, vec!["2".to_string()]);
+    create_session_if_not_set_then(Edition::Edition2024, |_| {
+        let id0 = StableCrateId::new(Symbol::intern("foo"), false, vec!["1".to_string()]);
+        let id1 = StableCrateId::new(Symbol::intern("foo"), false, vec!["2".to_string()]);
 
-    let h0 = mk_test_hash(id0);
-    let h1 = mk_test_hash(id1);
+        let h0 = mk_test_hash(id0);
+        let h1 = mk_test_hash(id1);
 
-    assert_ne!(h0.stable_crate_id(), h1.stable_crate_id());
-    assert_ne!(h0.local_hash(), h1.local_hash());
+        assert_ne!(h0.stable_crate_id(), h1.stable_crate_id());
+        assert_ne!(h0.local_hash(), h1.local_hash());
 
-    fn mk_test_hash(stable_crate_id: StableCrateId) -> DefPathHash {
-        let parent_hash = DefPathHash::new(stable_crate_id, 0);
+        fn mk_test_hash(stable_crate_id: StableCrateId) -> DefPathHash {
+            let parent_hash = DefPathHash::new(stable_crate_id, 0);
 
-        let key = DefKey {
-            parent: None,
-            disambiguated_data: DisambiguatedDefPathData {
-                data: DefPathData::CrateRoot,
-                disambiguator: 0,
-            },
-        };
+            let key = DefKey {
+                parent: None,
+                disambiguated_data: DisambiguatedDefPathData {
+                    data: DefPathData::CrateRoot,
+                    disambiguator: 0,
+                },
+            };
 
-        key.compute_stable_hash(parent_hash)
-    }
+            key.compute_stable_hash(parent_hash)
+        }
+    })
 }
index 66906b331da2ece663b3b06fb9883a144b5d474a..71f26eb60c9628e880f5f5b71ca4274e4fed5598 100644 (file)
@@ -680,7 +680,7 @@ fn instantiate_poly_trait_ref_inner(
         let assoc_bindings = self.create_assoc_bindings_for_generic_args(args);
 
         let poly_trait_ref =
-            ty::Binder::bind_with_vars(ty::TraitRef::new(trait_def_id, substs), bound_vars);
+            ty::Binder::bind_with_vars(tcx.mk_trait_ref(trait_def_id, substs), bound_vars);
 
         debug!(?poly_trait_ref, ?assoc_bindings);
         bounds.trait_bounds.push((poly_trait_ref, span, constness));
@@ -813,7 +813,7 @@ fn ast_path_to_mono_trait_ref(
         if let Some(b) = trait_segment.args().bindings.first() {
             Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
         }
-        ty::TraitRef::new(trait_def_id, substs)
+        self.tcx().mk_trait_ref(trait_def_id, substs)
     }
 
     #[instrument(level = "debug", skip(self, span))]
@@ -1146,10 +1146,7 @@ fn add_predicates_for_ast_type_binding(
 
             debug!(?substs_trait_ref_and_assoc_item);
 
-            ty::ProjectionTy {
-                item_def_id: assoc_item.def_id,
-                substs: substs_trait_ref_and_assoc_item,
-            }
+            self.tcx().mk_alias_ty(assoc_item.def_id, substs_trait_ref_and_assoc_item)
         });
 
         if !speculative {
@@ -1195,7 +1192,7 @@ fn add_predicates_for_ast_type_binding(
                 // the "projection predicate" for:
                 //
                 // `<T as Iterator>::Item = u32`
-                let assoc_item_def_id = projection_ty.skip_binder().item_def_id;
+                let assoc_item_def_id = projection_ty.skip_binder().def_id;
                 let def_kind = tcx.def_kind(assoc_item_def_id);
                 match (def_kind, term.unpack()) {
                     (hir::def::DefKind::AssocTy, ty::TermKind::Ty(_))
@@ -1244,7 +1241,7 @@ fn add_predicates_for_ast_type_binding(
                 //
                 // Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
                 // parameter to have a skipped binder.
-                let param_ty = tcx.mk_ty(ty::Projection(projection_ty.skip_binder()));
+                let param_ty = tcx.mk_ty(ty::Alias(ty::Projection, projection_ty.skip_binder()));
                 self.add_bounds(param_ty, ast_bounds.iter(), bounds, candidate.bound_vars());
             }
         }
index 069b405423c46b16aa023d60acb5be0419dcba7a..aa01feb3a1ea4d686e5b84401d4100913088ae76 100644 (file)
@@ -1,4 +1,5 @@
 use crate::check::intrinsicck::InlineAsmCtxt;
+use crate::errors::LinkageType;
 
 use super::compare_method::check_type_bounds;
 use super::compare_method::{compare_impl_method, compare_ty_impl};
@@ -20,7 +21,7 @@
 use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::util::{Discr, IntTypeExt};
-use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable};
+use rustc_middle::ty::{self, AdtDef, ParamEnv, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable};
 use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS};
 use rustc_span::symbol::sym;
 use rustc_span::{self, Span};
@@ -478,6 +479,36 @@ fn check_opaque_meets_bounds<'tcx>(
     let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
 }
 
+fn is_enum_of_nonnullable_ptr<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    adt_def: AdtDef<'tcx>,
+    substs: SubstsRef<'tcx>,
+) -> bool {
+    if adt_def.repr().inhibit_enum_layout_opt() {
+        return false;
+    }
+
+    let [var_one, var_two] = &adt_def.variants().raw[..] else {
+        return false;
+    };
+    let (([], [field]) | ([field], [])) = (&var_one.fields[..], &var_two.fields[..]) else {
+        return false;
+    };
+    matches!(field.ty(tcx, substs).kind(), ty::FnPtr(..) | ty::Ref(..))
+}
+
+fn check_static_linkage<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {
+    if tcx.codegen_fn_attrs(def_id).import_linkage.is_some() {
+        if match tcx.type_of(def_id).kind() {
+            ty::RawPtr(_) => false,
+            ty::Adt(adt_def, substs) => !is_enum_of_nonnullable_ptr(tcx, *adt_def, *substs),
+            _ => true,
+        } {
+            tcx.sess.emit_err(LinkageType { span: tcx.def_span(def_id) });
+        }
+    }
+}
+
 fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
     debug!(
         "check_item_type(it.def_id={:?}, it.name={})",
@@ -490,6 +521,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
             tcx.ensure().typeck(id.owner_id.def_id);
             maybe_check_static_with_link_section(tcx, id.owner_id.def_id);
             check_static_inhabited(tcx, id.owner_id.def_id);
+            check_static_linkage(tcx, id.owner_id.def_id);
         }
         DefKind::Const => {
             tcx.ensure().typeck(id.owner_id.def_id);
@@ -538,7 +570,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
                             assoc_item,
                             assoc_item,
                             default.span,
-                            ty::TraitRef { def_id: it.owner_id.to_def_id(), substs: trait_substs },
+                            tcx.mk_trait_ref(it.owner_id.to_def_id(), trait_substs),
                         );
                     }
                     _ => {}
@@ -627,6 +659,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
                         }
                         hir::ForeignItemKind::Static(..) => {
                             check_static_inhabited(tcx, def_id);
+                            check_static_linkage(tcx, def_id);
                         }
                         _ => {}
                     }
@@ -1407,7 +1440,7 @@ fn opaque_type_cycle_error(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) -> E
                 impl<'tcx> ty::visit::TypeVisitor<'tcx> for OpaqueTypeCollector {
                     fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
                         match *t.kind() {
-                            ty::Opaque(def, _) => {
+                            ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
                                 self.0.push(def);
                                 ControlFlow::CONTINUE
                             }
index 1d6f9b29176518a30f487dca7eab58e0610b3ccf..b69728c24aa514ffd4b3604a2380ac3b318ca480 100644 (file)
@@ -67,6 +67,10 @@ pub(crate) fn compare_impl_method<'tcx>(
         return;
     }
 
+    if let Err(_) = compare_asyncness(tcx, impl_m, impl_m_span, trait_m, trait_item_span) {
+        return;
+    }
+
     if let Err(_) = compare_predicate_entailment(tcx, impl_m, impl_m_span, trait_m, impl_trait_ref)
     {
         return;
@@ -323,6 +327,34 @@ fn compare_predicate_entailment<'tcx>(
     Ok(())
 }
 
+fn compare_asyncness<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    impl_m: &ty::AssocItem,
+    impl_m_span: Span,
+    trait_m: &ty::AssocItem,
+    trait_item_span: Option<Span>,
+) -> Result<(), ErrorGuaranteed> {
+    if tcx.asyncness(trait_m.def_id) == hir::IsAsync::Async {
+        match tcx.fn_sig(impl_m.def_id).skip_binder().output().kind() {
+            ty::Alias(ty::Opaque, ..) => {
+                // allow both `async fn foo()` and `fn foo() -> impl Future`
+            }
+            ty::Error(rustc_errors::ErrorGuaranteed { .. }) => {
+                // We don't know if it's ok, but at least it's already an error.
+            }
+            _ => {
+                return Err(tcx.sess.emit_err(crate::errors::AsyncTraitImplShouldBeAsync {
+                    span: impl_m_span,
+                    method_name: trait_m.name,
+                    trait_item_span,
+                }));
+            }
+        };
+    }
+
+    Ok(())
+}
+
 #[instrument(skip(tcx), level = "debug", ret)]
 pub fn collect_trait_impl_trait_tys<'tcx>(
     tcx: TyCtxt<'tcx>,
@@ -373,6 +405,7 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
             tcx.fn_sig(impl_m.def_id),
         ),
     );
+    impl_sig.error_reported()?;
     let impl_return_ty = impl_sig.output();
 
     // Normalize the trait signature with liberated bound vars, passing it through
@@ -387,6 +420,7 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
         )
         .fold_with(&mut collector);
     let trait_sig = ocx.normalize(&norm_cause, param_env, unnormalized_trait_sig);
+    trait_sig.error_reported()?;
     let trait_return_ty = trait_sig.output();
 
     let wf_tys = FxIndexSet::from_iter(
@@ -571,10 +605,10 @@ fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
     }
 
     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        if let ty::Projection(proj) = ty.kind()
-            && self.tcx().def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder
+        if let ty::Alias(ty::Projection, proj) = ty.kind()
+            && self.tcx().def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder
         {
-            if let Some((ty, _)) = self.types.get(&proj.item_def_id) {
+            if let Some((ty, _)) = self.types.get(&proj.def_id) {
                 return *ty;
             }
             //FIXME(RPITIT): Deny nested RPITIT in substs too
@@ -586,9 +620,9 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 span: self.span,
                 kind: TypeVariableOriginKind::MiscVariable,
             });
-            self.types.insert(proj.item_def_id, (infer_ty, proj.substs));
+            self.types.insert(proj.def_id, (infer_ty, proj.substs));
             // Recurse into bounds
-            for (pred, pred_span) in self.tcx().bound_explicit_item_bounds(proj.item_def_id).subst_iter_copied(self.tcx(), proj.substs) {
+            for (pred, pred_span) in self.tcx().bound_explicit_item_bounds(proj.def_id).subst_iter_copied(self.tcx(), proj.substs) {
                 let pred = pred.fold_with(self);
                 let pred = self.ocx.normalize(
                     &ObligationCause::misc(self.span, self.body_id),
@@ -601,7 +635,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                     ObligationCause::new(
                         self.span,
                         self.body_id,
-                        ObligationCauseCode::BindingObligation(proj.item_def_id, pred_span),
+                        ObligationCauseCode::BindingObligation(proj.def_id, pred_span),
                     ),
                     self.param_env,
                     pred,
@@ -1734,8 +1768,8 @@ pub fn check_type_bounds<'tcx>(
     let normalize_param_env = {
         let mut predicates = param_env.caller_bounds().iter().collect::<Vec<_>>();
         match impl_ty_value.kind() {
-            ty::Projection(proj)
-                if proj.item_def_id == trait_ty.def_id && proj.substs == rebased_substs =>
+            ty::Alias(ty::Projection, proj)
+                if proj.def_id == trait_ty.def_id && proj.substs == rebased_substs =>
             {
                 // Don't include this predicate if the projected type is
                 // exactly the same as the projection. This can occur in
@@ -1746,10 +1780,7 @@ pub fn check_type_bounds<'tcx>(
             _ => predicates.push(
                 ty::Binder::bind_with_vars(
                     ty::ProjectionPredicate {
-                        projection_ty: ty::ProjectionTy {
-                            item_def_id: trait_ty.def_id,
-                            substs: rebased_substs,
-                        },
+                        projection_ty: tcx.mk_alias_ty(trait_ty.def_id, rebased_substs),
                         term: impl_ty_value.into(),
                     },
                     bound_vars,
index 29255472a2516dd0917642ff3e83886320db7fd7..57f0cae12bb312bb5afd14d971fed8bac0ad31a1 100644 (file)
@@ -352,11 +352,7 @@ fn bounds_from_generic_predicates<'tcx>(
         // insert the associated types where they correspond, but for now let's be "lazy" and
         // propose this instead of the following valid resugaring:
         // `T: Trait, Trait::Assoc = K` → `T: Trait<Assoc = K>`
-        where_clauses.push(format!(
-            "{} = {}",
-            tcx.def_path_str(p.projection_ty.item_def_id),
-            p.term,
-        ));
+        where_clauses.push(format!("{} = {}", tcx.def_path_str(p.projection_ty.def_id), p.term));
     }
     let where_clauses = if where_clauses.is_empty() {
         String::new()
index b065ace6bf5e15f826f54eecaa60c0b918be0e7c..94d333c336ef3f2768267d1ea3ce72147dd57e25 100644 (file)
@@ -31,7 +31,6 @@
 };
 
 use std::cell::LazyCell;
-use std::convert::TryInto;
 use std::iter;
 use std::ops::{ControlFlow, Deref};
 
@@ -760,7 +759,7 @@ impl<'tcx> TypeVisitor<'tcx> for GATSubstCollector<'tcx> {
 
     fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
         match t.kind() {
-            ty::Projection(p) if p.item_def_id == self.gat => {
+            ty::Alias(ty::Projection, p) if p.def_id == self.gat => {
                 for (idx, subst) in p.substs.iter().enumerate() {
                     match subst.unpack() {
                         GenericArgKind::Lifetime(lt) if !lt.is_late_bound() => {
@@ -1593,12 +1592,12 @@ fn check_return_position_impl_trait_in_trait_bounds<'tcx>(
     {
         for arg in fn_output.walk() {
             if let ty::GenericArgKind::Type(ty) = arg.unpack()
-                && let ty::Projection(proj) = ty.kind()
-                && tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder
-                && tcx.impl_trait_in_trait_parent(proj.item_def_id) == fn_def_id.to_def_id()
+                && let ty::Alias(ty::Projection, proj) = ty.kind()
+                && tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder
+                && tcx.impl_trait_in_trait_parent(proj.def_id) == fn_def_id.to_def_id()
             {
-                let span = tcx.def_span(proj.item_def_id);
-                let bounds = wfcx.tcx().explicit_item_bounds(proj.item_def_id);
+                let span = tcx.def_span(proj.def_id);
+                let bounds = wfcx.tcx().explicit_item_bounds(proj.def_id);
                 let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| {
                     let bound = ty::EarlyBinder(bound).subst(tcx, proj.substs);
                     let normalized_bound = wfcx.normalize(span, None, bound);
index 2890c149b3afe3f2ac1eba2ecc37a438e9824e75..6469f389bf91b313141ce01452fe74cb68b72f98 100644 (file)
@@ -223,7 +223,7 @@ fn check_item(&mut self, id: hir::ItemId) {
             | ty::Tuple(..) => {
                 self.check_primitive_impl(item.owner_id.def_id, self_ty, items, ty.span)
             }
-            ty::Projection(..) | ty::Opaque(..) | ty::Param(_) => {
+            ty::Alias(..) | ty::Param(_) => {
                 let mut err = struct_span_err!(
                     self.tcx.sess,
                     ty.span,
index b7084303aafb1d0b85c1c0f2c0423b30c6e519f5..0c4649cea14edda97552e175a99e877201d87690 100644 (file)
 use crate::astconv::AstConv;
 use crate::check::intrinsic::intrinsic_operation_unsafety;
 use crate::errors;
-use rustc_ast as ast;
-use rustc_ast::{MetaItemKind, NestedMetaItem};
-use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr};
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey};
 use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS;
-use rustc_hir::{lang_items, GenericParamKind, LangItem, Node};
+use rustc_hir::{GenericParamKind, Node};
 use rustc_middle::hir::nested_filter;
-use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
-use rustc_middle::mir::mono::Linkage;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::util::{Discr, IntTypeExt};
-use rustc_middle::ty::{self, AdtKind, Const, DefIdTree, IsSuggestable, ToPredicate, Ty, TyCtxt};
-use rustc_session::lint;
-use rustc_session::parse::feature_err;
+use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, ToPredicate, Ty, TyCtxt};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::Span;
-use rustc_target::spec::{abi, SanitizerSet};
+use rustc_target::spec::abi;
 use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName;
 use std::iter;
 
@@ -78,10 +70,7 @@ pub fn provide(providers: &mut Providers) {
         impl_polarity,
         is_foreign_item,
         generator_kind,
-        codegen_fn_attrs,
-        asm_target_features,
         collect_mod_item_types,
-        should_inherit_track_caller,
         ..*providers
     };
 }
@@ -500,7 +489,7 @@ fn projected_ty_from_poly_trait_ref(
                         format!(
                             "{}::",
                             // Erase named lt, we want `<A as B<'_>::C`, not `<A as B<'a>::C`.
-                            self.tcx.anonymize_late_bound_regions(poly_trait_ref).skip_binder(),
+                            self.tcx.anonymize_bound_vars(poly_trait_ref).skip_binder(),
                         ),
                         Applicability::MaybeIncorrect,
                     );
@@ -955,7 +944,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
                     .struct_span_err(
                         attr.span,
                         "the `#[rustc_must_implement_one_of]` attribute must be \
-                        used with at least 2 args",
+                         used with at least 2 args",
                     )
                     .emit();
 
@@ -987,7 +976,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
                             tcx.sess
                                 .struct_span_err(
                                     item.span,
-                                    "This function doesn't have a default implementation",
+                                    "function doesn't have a default implementation",
                                 )
                                 .span_note(attr_span, "required by this annotation")
                                 .emit();
@@ -999,17 +988,17 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
                     }
                     Some(item) => {
                         tcx.sess
-                            .struct_span_err(item.span, "Not a function")
+                            .struct_span_err(item.span, "not a function")
                             .span_note(attr_span, "required by this annotation")
                             .note(
-                                "All `#[rustc_must_implement_one_of]` arguments \
-                            must be associated function names",
+                                "all `#[rustc_must_implement_one_of]` arguments must be associated \
+                                 function names",
                             )
                             .emit();
                     }
                     None => {
                         tcx.sess
-                            .struct_span_err(ident.span, "Function not found in this trait")
+                            .struct_span_err(ident.span, "function not found in this trait")
                             .emit();
                     }
                 }
@@ -1027,11 +1016,8 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
             for ident in &*list {
                 if let Some(dup) = set.insert(ident.name, ident.span) {
                     tcx.sess
-                        .struct_span_err(vec![dup, ident.span], "Functions names are duplicated")
-                        .note(
-                            "All `#[rustc_must_implement_one_of]` arguments \
-                            must be unique",
-                        )
+                        .struct_span_err(vec![dup, ident.span], "functions names are duplicated")
+                        .note("all `#[rustc_must_implement_one_of]` arguments must be unique")
                         .emit();
 
                     no_dups = false;
@@ -1458,790 +1444,3 @@ fn generator_kind(tcx: TyCtxt<'_>, def_id: DefId) -> Option<hir::GeneratorKind>
         _ => bug!("generator_kind applied to non-local def-id {:?}", def_id),
     }
 }
-
-fn from_target_feature(
-    tcx: TyCtxt<'_>,
-    attr: &ast::Attribute,
-    supported_target_features: &FxHashMap<String, Option<Symbol>>,
-    target_features: &mut Vec<Symbol>,
-) {
-    let Some(list) = attr.meta_item_list() else { return };
-    let bad_item = |span| {
-        let msg = "malformed `target_feature` attribute input";
-        let code = "enable = \"..\"";
-        tcx.sess
-            .struct_span_err(span, msg)
-            .span_suggestion(span, "must be of the form", code, Applicability::HasPlaceholders)
-            .emit();
-    };
-    let rust_features = tcx.features();
-    for item in list {
-        // Only `enable = ...` is accepted in the meta-item list.
-        if !item.has_name(sym::enable) {
-            bad_item(item.span());
-            continue;
-        }
-
-        // Must be of the form `enable = "..."` (a string).
-        let Some(value) = item.value_str() else {
-            bad_item(item.span());
-            continue;
-        };
-
-        // We allow comma separation to enable multiple features.
-        target_features.extend(value.as_str().split(',').filter_map(|feature| {
-            let Some(feature_gate) = supported_target_features.get(feature) else {
-                let msg =
-                    format!("the feature named `{}` is not valid for this target", feature);
-                let mut err = tcx.sess.struct_span_err(item.span(), &msg);
-                err.span_label(
-                    item.span(),
-                    format!("`{}` is not valid for this target", feature),
-                );
-                if let Some(stripped) = feature.strip_prefix('+') {
-                    let valid = supported_target_features.contains_key(stripped);
-                    if valid {
-                        err.help("consider removing the leading `+` in the feature name");
-                    }
-                }
-                err.emit();
-                return None;
-            };
-
-            // Only allow features whose feature gates have been enabled.
-            let allowed = match feature_gate.as_ref().copied() {
-                Some(sym::arm_target_feature) => rust_features.arm_target_feature,
-                Some(sym::hexagon_target_feature) => rust_features.hexagon_target_feature,
-                Some(sym::powerpc_target_feature) => rust_features.powerpc_target_feature,
-                Some(sym::mips_target_feature) => rust_features.mips_target_feature,
-                Some(sym::riscv_target_feature) => rust_features.riscv_target_feature,
-                Some(sym::avx512_target_feature) => rust_features.avx512_target_feature,
-                Some(sym::sse4a_target_feature) => rust_features.sse4a_target_feature,
-                Some(sym::tbm_target_feature) => rust_features.tbm_target_feature,
-                Some(sym::wasm_target_feature) => rust_features.wasm_target_feature,
-                Some(sym::cmpxchg16b_target_feature) => rust_features.cmpxchg16b_target_feature,
-                Some(sym::movbe_target_feature) => rust_features.movbe_target_feature,
-                Some(sym::rtm_target_feature) => rust_features.rtm_target_feature,
-                Some(sym::f16c_target_feature) => rust_features.f16c_target_feature,
-                Some(sym::ermsb_target_feature) => rust_features.ermsb_target_feature,
-                Some(sym::bpf_target_feature) => rust_features.bpf_target_feature,
-                Some(sym::aarch64_ver_target_feature) => rust_features.aarch64_ver_target_feature,
-                Some(name) => bug!("unknown target feature gate {}", name),
-                None => true,
-            };
-            if !allowed {
-                feature_err(
-                    &tcx.sess.parse_sess,
-                    feature_gate.unwrap(),
-                    item.span(),
-                    &format!("the target feature `{}` is currently unstable", feature),
-                )
-                .emit();
-            }
-            Some(Symbol::intern(feature))
-        }));
-    }
-}
-
-fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage {
-    use rustc_middle::mir::mono::Linkage::*;
-
-    // Use the names from src/llvm/docs/LangRef.rst here. Most types are only
-    // applicable to variable declarations and may not really make sense for
-    // Rust code in the first place but allow them anyway and trust that the
-    // user knows what they're doing. Who knows, unanticipated use cases may pop
-    // up in the future.
-    //
-    // ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
-    // and don't have to be, LLVM treats them as no-ops.
-    match name {
-        "appending" => Appending,
-        "available_externally" => AvailableExternally,
-        "common" => Common,
-        "extern_weak" => ExternalWeak,
-        "external" => External,
-        "internal" => Internal,
-        "linkonce" => LinkOnceAny,
-        "linkonce_odr" => LinkOnceODR,
-        "private" => Private,
-        "weak" => WeakAny,
-        "weak_odr" => WeakODR,
-        _ => tcx.sess.span_fatal(tcx.def_span(def_id), "invalid linkage specified"),
-    }
-}
-
-fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
-    if cfg!(debug_assertions) {
-        let def_kind = tcx.def_kind(did);
-        assert!(
-            def_kind.has_codegen_attrs(),
-            "unexpected `def_kind` in `codegen_fn_attrs`: {def_kind:?}",
-        );
-    }
-
-    let did = did.expect_local();
-    let attrs = tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(did));
-    let mut codegen_fn_attrs = CodegenFnAttrs::new();
-    if tcx.should_inherit_track_caller(did) {
-        codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
-    }
-
-    let supported_target_features = tcx.supported_target_features(LOCAL_CRATE);
-
-    let mut inline_span = None;
-    let mut link_ordinal_span = None;
-    let mut no_sanitize_span = None;
-    for attr in attrs.iter() {
-        if attr.has_name(sym::cold) {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD;
-        } else if attr.has_name(sym::rustc_allocator) {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR;
-        } else if attr.has_name(sym::ffi_returns_twice) {
-            if tcx.is_foreign_item(did) {
-                codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE;
-            } else {
-                // `#[ffi_returns_twice]` is only allowed `extern fn`s.
-                struct_span_err!(
-                    tcx.sess,
-                    attr.span,
-                    E0724,
-                    "`#[ffi_returns_twice]` may only be used on foreign functions"
-                )
-                .emit();
-            }
-        } else if attr.has_name(sym::ffi_pure) {
-            if tcx.is_foreign_item(did) {
-                if attrs.iter().any(|a| a.has_name(sym::ffi_const)) {
-                    // `#[ffi_const]` functions cannot be `#[ffi_pure]`
-                    struct_span_err!(
-                        tcx.sess,
-                        attr.span,
-                        E0757,
-                        "`#[ffi_const]` function cannot be `#[ffi_pure]`"
-                    )
-                    .emit();
-                } else {
-                    codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE;
-                }
-            } else {
-                // `#[ffi_pure]` is only allowed on foreign functions
-                struct_span_err!(
-                    tcx.sess,
-                    attr.span,
-                    E0755,
-                    "`#[ffi_pure]` may only be used on foreign functions"
-                )
-                .emit();
-            }
-        } else if attr.has_name(sym::ffi_const) {
-            if tcx.is_foreign_item(did) {
-                codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST;
-            } else {
-                // `#[ffi_const]` is only allowed on foreign functions
-                struct_span_err!(
-                    tcx.sess,
-                    attr.span,
-                    E0756,
-                    "`#[ffi_const]` may only be used on foreign functions"
-                )
-                .emit();
-            }
-        } else if attr.has_name(sym::rustc_nounwind) {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
-        } else if attr.has_name(sym::rustc_reallocator) {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::REALLOCATOR;
-        } else if attr.has_name(sym::rustc_deallocator) {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::DEALLOCATOR;
-        } else if attr.has_name(sym::rustc_allocator_zeroed) {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED;
-        } else if attr.has_name(sym::naked) {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED;
-        } else if attr.has_name(sym::no_mangle) {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
-        } else if attr.has_name(sym::no_coverage) {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE;
-        } else if attr.has_name(sym::rustc_std_internal_symbol) {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
-        } else if attr.has_name(sym::used) {
-            let inner = attr.meta_item_list();
-            match inner.as_deref() {
-                Some([item]) if item.has_name(sym::linker) => {
-                    if !tcx.features().used_with_arg {
-                        feature_err(
-                            &tcx.sess.parse_sess,
-                            sym::used_with_arg,
-                            attr.span,
-                            "`#[used(linker)]` is currently unstable",
-                        )
-                        .emit();
-                    }
-                    codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_LINKER;
-                }
-                Some([item]) if item.has_name(sym::compiler) => {
-                    if !tcx.features().used_with_arg {
-                        feature_err(
-                            &tcx.sess.parse_sess,
-                            sym::used_with_arg,
-                            attr.span,
-                            "`#[used(compiler)]` is currently unstable",
-                        )
-                        .emit();
-                    }
-                    codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED;
-                }
-                Some(_) => {
-                    tcx.sess.emit_err(errors::ExpectedUsedSymbol { span: attr.span });
-                }
-                None => {
-                    // Unfortunately, unconditionally using `llvm.used` causes
-                    // issues in handling `.init_array` with the gold linker,
-                    // but using `llvm.compiler.used` caused a nontrival amount
-                    // of unintentional ecosystem breakage -- particularly on
-                    // Mach-O targets.
-                    //
-                    // As a result, we emit `llvm.compiler.used` only on ELF
-                    // targets. This is somewhat ad-hoc, but actually follows
-                    // our pre-LLVM 13 behavior (prior to the ecosystem
-                    // breakage), and seems to match `clang`'s behavior as well
-                    // (both before and after LLVM 13), possibly because they
-                    // have similar compatibility concerns to us. See
-                    // https://github.com/rust-lang/rust/issues/47384#issuecomment-1019080146
-                    // and following comments for some discussion of this, as
-                    // well as the comments in `rustc_codegen_llvm` where these
-                    // flags are handled.
-                    //
-                    // Anyway, to be clear: this is still up in the air
-                    // somewhat, and is subject to change in the future (which
-                    // is a good thing, because this would ideally be a bit
-                    // more firmed up).
-                    let is_like_elf = !(tcx.sess.target.is_like_osx
-                        || tcx.sess.target.is_like_windows
-                        || tcx.sess.target.is_like_wasm);
-                    codegen_fn_attrs.flags |= if is_like_elf {
-                        CodegenFnAttrFlags::USED
-                    } else {
-                        CodegenFnAttrFlags::USED_LINKER
-                    };
-                }
-            }
-        } else if attr.has_name(sym::cmse_nonsecure_entry) {
-            if !matches!(tcx.fn_sig(did).abi(), abi::Abi::C { .. }) {
-                struct_span_err!(
-                    tcx.sess,
-                    attr.span,
-                    E0776,
-                    "`#[cmse_nonsecure_entry]` requires C ABI"
-                )
-                .emit();
-            }
-            if !tcx.sess.target.llvm_target.contains("thumbv8m") {
-                struct_span_err!(tcx.sess, attr.span, E0775, "`#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension")
-                    .emit();
-            }
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY;
-        } else if attr.has_name(sym::thread_local) {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL;
-        } else if attr.has_name(sym::track_caller) {
-            if !tcx.is_closure(did.to_def_id()) && tcx.fn_sig(did).abi() != abi::Abi::Rust {
-                struct_span_err!(tcx.sess, attr.span, E0737, "`#[track_caller]` requires Rust ABI")
-                    .emit();
-            }
-            if tcx.is_closure(did.to_def_id()) && !tcx.features().closure_track_caller {
-                feature_err(
-                    &tcx.sess.parse_sess,
-                    sym::closure_track_caller,
-                    attr.span,
-                    "`#[track_caller]` on closures is currently unstable",
-                )
-                .emit();
-            }
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
-        } else if attr.has_name(sym::export_name) {
-            if let Some(s) = attr.value_str() {
-                if s.as_str().contains('\0') {
-                    // `#[export_name = ...]` will be converted to a null-terminated string,
-                    // so it may not contain any null characters.
-                    struct_span_err!(
-                        tcx.sess,
-                        attr.span,
-                        E0648,
-                        "`export_name` may not contain null characters"
-                    )
-                    .emit();
-                }
-                codegen_fn_attrs.export_name = Some(s);
-            }
-        } else if attr.has_name(sym::target_feature) {
-            if !tcx.is_closure(did.to_def_id())
-                && tcx.fn_sig(did).unsafety() == hir::Unsafety::Normal
-            {
-                if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc {
-                    // The `#[target_feature]` attribute is allowed on
-                    // WebAssembly targets on all functions, including safe
-                    // ones. Other targets require that `#[target_feature]` is
-                    // only applied to unsafe functions (pending the
-                    // `target_feature_11` feature) because on most targets
-                    // execution of instructions that are not supported is
-                    // considered undefined behavior. For WebAssembly which is a
-                    // 100% safe target at execution time it's not possible to
-                    // execute undefined instructions, and even if a future
-                    // feature was added in some form for this it would be a
-                    // deterministic trap. There is no undefined behavior when
-                    // executing WebAssembly so `#[target_feature]` is allowed
-                    // on safe functions (but again, only for WebAssembly)
-                    //
-                    // Note that this is also allowed if `actually_rustdoc` so
-                    // if a target is documenting some wasm-specific code then
-                    // it's not spuriously denied.
-                } else if !tcx.features().target_feature_11 {
-                    let mut err = feature_err(
-                        &tcx.sess.parse_sess,
-                        sym::target_feature_11,
-                        attr.span,
-                        "`#[target_feature(..)]` can only be applied to `unsafe` functions",
-                    );
-                    err.span_label(tcx.def_span(did), "not an `unsafe` function");
-                    err.emit();
-                } else {
-                    check_target_feature_trait_unsafe(tcx, did, attr.span);
-                }
-            }
-            from_target_feature(
-                tcx,
-                attr,
-                supported_target_features,
-                &mut codegen_fn_attrs.target_features,
-            );
-        } else if attr.has_name(sym::linkage) {
-            if let Some(val) = attr.value_str() {
-                codegen_fn_attrs.linkage = Some(linkage_by_name(tcx, did, val.as_str()));
-            }
-        } else if attr.has_name(sym::link_section) {
-            if let Some(val) = attr.value_str() {
-                if val.as_str().bytes().any(|b| b == 0) {
-                    let msg = format!(
-                        "illegal null byte in link_section \
-                         value: `{}`",
-                        &val
-                    );
-                    tcx.sess.span_err(attr.span, &msg);
-                } else {
-                    codegen_fn_attrs.link_section = Some(val);
-                }
-            }
-        } else if attr.has_name(sym::link_name) {
-            codegen_fn_attrs.link_name = attr.value_str();
-        } else if attr.has_name(sym::link_ordinal) {
-            link_ordinal_span = Some(attr.span);
-            if let ordinal @ Some(_) = check_link_ordinal(tcx, attr) {
-                codegen_fn_attrs.link_ordinal = ordinal;
-            }
-        } else if attr.has_name(sym::no_sanitize) {
-            no_sanitize_span = Some(attr.span);
-            if let Some(list) = attr.meta_item_list() {
-                for item in list.iter() {
-                    if item.has_name(sym::address) {
-                        codegen_fn_attrs.no_sanitize |= SanitizerSet::ADDRESS;
-                    } else if item.has_name(sym::cfi) {
-                        codegen_fn_attrs.no_sanitize |= SanitizerSet::CFI;
-                    } else if item.has_name(sym::memory) {
-                        codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMORY;
-                    } else if item.has_name(sym::memtag) {
-                        codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMTAG;
-                    } else if item.has_name(sym::shadow_call_stack) {
-                        codegen_fn_attrs.no_sanitize |= SanitizerSet::SHADOWCALLSTACK;
-                    } else if item.has_name(sym::thread) {
-                        codegen_fn_attrs.no_sanitize |= SanitizerSet::THREAD;
-                    } else if item.has_name(sym::hwaddress) {
-                        codegen_fn_attrs.no_sanitize |= SanitizerSet::HWADDRESS;
-                    } else {
-                        tcx.sess
-                            .struct_span_err(item.span(), "invalid argument for `no_sanitize`")
-                            .note("expected one of: `address`, `cfi`, `hwaddress`, `memory`, `memtag`, `shadow-call-stack`, or `thread`")
-                            .emit();
-                    }
-                }
-            }
-        } else if attr.has_name(sym::instruction_set) {
-            codegen_fn_attrs.instruction_set = match attr.meta_kind() {
-                Some(MetaItemKind::List(ref items)) => match items.as_slice() {
-                    [NestedMetaItem::MetaItem(set)] => {
-                        let segments =
-                            set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>();
-                        match segments.as_slice() {
-                            [sym::arm, sym::a32] | [sym::arm, sym::t32] => {
-                                if !tcx.sess.target.has_thumb_interworking {
-                                    struct_span_err!(
-                                        tcx.sess.diagnostic(),
-                                        attr.span,
-                                        E0779,
-                                        "target does not support `#[instruction_set]`"
-                                    )
-                                    .emit();
-                                    None
-                                } else if segments[1] == sym::a32 {
-                                    Some(InstructionSetAttr::ArmA32)
-                                } else if segments[1] == sym::t32 {
-                                    Some(InstructionSetAttr::ArmT32)
-                                } else {
-                                    unreachable!()
-                                }
-                            }
-                            _ => {
-                                struct_span_err!(
-                                    tcx.sess.diagnostic(),
-                                    attr.span,
-                                    E0779,
-                                    "invalid instruction set specified",
-                                )
-                                .emit();
-                                None
-                            }
-                        }
-                    }
-                    [] => {
-                        struct_span_err!(
-                            tcx.sess.diagnostic(),
-                            attr.span,
-                            E0778,
-                            "`#[instruction_set]` requires an argument"
-                        )
-                        .emit();
-                        None
-                    }
-                    _ => {
-                        struct_span_err!(
-                            tcx.sess.diagnostic(),
-                            attr.span,
-                            E0779,
-                            "cannot specify more than one instruction set"
-                        )
-                        .emit();
-                        None
-                    }
-                },
-                _ => {
-                    struct_span_err!(
-                        tcx.sess.diagnostic(),
-                        attr.span,
-                        E0778,
-                        "must specify an instruction set"
-                    )
-                    .emit();
-                    None
-                }
-            };
-        } else if attr.has_name(sym::repr) {
-            codegen_fn_attrs.alignment = match attr.meta_item_list() {
-                Some(items) => match items.as_slice() {
-                    [item] => match item.name_value_literal() {
-                        Some((sym::align, literal)) => {
-                            let alignment = rustc_attr::parse_alignment(&literal.kind);
-
-                            match alignment {
-                                Ok(align) => Some(align),
-                                Err(msg) => {
-                                    struct_span_err!(
-                                        tcx.sess.diagnostic(),
-                                        attr.span,
-                                        E0589,
-                                        "invalid `repr(align)` attribute: {}",
-                                        msg
-                                    )
-                                    .emit();
-
-                                    None
-                                }
-                            }
-                        }
-                        _ => None,
-                    },
-                    [] => None,
-                    _ => None,
-                },
-                None => None,
-            };
-        }
-    }
-
-    codegen_fn_attrs.inline = attrs.iter().fold(InlineAttr::None, |ia, attr| {
-        if !attr.has_name(sym::inline) {
-            return ia;
-        }
-        match attr.meta_kind() {
-            Some(MetaItemKind::Word) => InlineAttr::Hint,
-            Some(MetaItemKind::List(ref items)) => {
-                inline_span = Some(attr.span);
-                if items.len() != 1 {
-                    struct_span_err!(
-                        tcx.sess.diagnostic(),
-                        attr.span,
-                        E0534,
-                        "expected one argument"
-                    )
-                    .emit();
-                    InlineAttr::None
-                } else if list_contains_name(&items, sym::always) {
-                    InlineAttr::Always
-                } else if list_contains_name(&items, sym::never) {
-                    InlineAttr::Never
-                } else {
-                    struct_span_err!(
-                        tcx.sess.diagnostic(),
-                        items[0].span(),
-                        E0535,
-                        "invalid argument"
-                    )
-                    .help("valid inline arguments are `always` and `never`")
-                    .emit();
-
-                    InlineAttr::None
-                }
-            }
-            Some(MetaItemKind::NameValue(_)) => ia,
-            None => ia,
-        }
-    });
-
-    codegen_fn_attrs.optimize = attrs.iter().fold(OptimizeAttr::None, |ia, attr| {
-        if !attr.has_name(sym::optimize) {
-            return ia;
-        }
-        let err = |sp, s| struct_span_err!(tcx.sess.diagnostic(), sp, E0722, "{}", s).emit();
-        match attr.meta_kind() {
-            Some(MetaItemKind::Word) => {
-                err(attr.span, "expected one argument");
-                ia
-            }
-            Some(MetaItemKind::List(ref items)) => {
-                inline_span = Some(attr.span);
-                if items.len() != 1 {
-                    err(attr.span, "expected one argument");
-                    OptimizeAttr::None
-                } else if list_contains_name(&items, sym::size) {
-                    OptimizeAttr::Size
-                } else if list_contains_name(&items, sym::speed) {
-                    OptimizeAttr::Speed
-                } else {
-                    err(items[0].span(), "invalid argument");
-                    OptimizeAttr::None
-                }
-            }
-            Some(MetaItemKind::NameValue(_)) => ia,
-            None => ia,
-        }
-    });
-
-    // #73631: closures inherit `#[target_feature]` annotations
-    if tcx.features().target_feature_11 && tcx.is_closure(did.to_def_id()) {
-        let owner_id = tcx.parent(did.to_def_id());
-        if tcx.def_kind(owner_id).has_codegen_attrs() {
-            codegen_fn_attrs
-                .target_features
-                .extend(tcx.codegen_fn_attrs(owner_id).target_features.iter().copied());
-        }
-    }
-
-    // If a function uses #[target_feature] it can't be inlined into general
-    // purpose functions as they wouldn't have the right target features
-    // enabled. For that reason we also forbid #[inline(always)] as it can't be
-    // respected.
-    if !codegen_fn_attrs.target_features.is_empty() {
-        if codegen_fn_attrs.inline == InlineAttr::Always {
-            if let Some(span) = inline_span {
-                tcx.sess.span_err(
-                    span,
-                    "cannot use `#[inline(always)]` with \
-                     `#[target_feature]`",
-                );
-            }
-        }
-    }
-
-    if !codegen_fn_attrs.no_sanitize.is_empty() {
-        if codegen_fn_attrs.inline == InlineAttr::Always {
-            if let (Some(no_sanitize_span), Some(inline_span)) = (no_sanitize_span, inline_span) {
-                let hir_id = tcx.hir().local_def_id_to_hir_id(did);
-                tcx.struct_span_lint_hir(
-                    lint::builtin::INLINE_NO_SANITIZE,
-                    hir_id,
-                    no_sanitize_span,
-                    "`no_sanitize` will have no effect after inlining",
-                    |lint| lint.span_note(inline_span, "inlining requested here"),
-                )
-            }
-        }
-    }
-
-    if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
-        codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE;
-        codegen_fn_attrs.inline = InlineAttr::Never;
-    }
-
-    // Weak lang items have the same semantics as "std internal" symbols in the
-    // sense that they're preserved through all our LTO passes and only
-    // strippable by the linker.
-    //
-    // Additionally weak lang items have predetermined symbol names.
-    if WEAK_LANG_ITEMS.iter().any(|&l| tcx.lang_items().get(l) == Some(did.to_def_id())) {
-        codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
-    }
-    if let Some((name, _)) = lang_items::extract(attrs)
-        && let Some(lang_item) = LangItem::from_name(name)
-        && let Some(link_name) = lang_item.link_name()
-    {
-        codegen_fn_attrs.export_name = Some(link_name);
-        codegen_fn_attrs.link_name = Some(link_name);
-    }
-    check_link_name_xor_ordinal(tcx, &codegen_fn_attrs, link_ordinal_span);
-
-    // Internal symbols to the standard library all have no_mangle semantics in
-    // that they have defined symbol names present in the function name. This
-    // also applies to weak symbols where they all have known symbol names.
-    if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
-        codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
-    }
-
-    // Any linkage to LLVM intrinsics for now forcibly marks them all as never
-    // unwinds since LLVM sometimes can't handle codegen which `invoke`s
-    // intrinsic functions.
-    if let Some(name) = &codegen_fn_attrs.link_name {
-        if name.as_str().starts_with("llvm.") {
-            codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
-        }
-    }
-
-    codegen_fn_attrs
-}
-
-/// Computes the set of target features used in a function for the purposes of
-/// inline assembly.
-fn asm_target_features<'tcx>(tcx: TyCtxt<'tcx>, did: DefId) -> &'tcx FxHashSet<Symbol> {
-    let mut target_features = tcx.sess.unstable_target_features.clone();
-    if tcx.def_kind(did).has_codegen_attrs() {
-        let attrs = tcx.codegen_fn_attrs(did);
-        target_features.extend(&attrs.target_features);
-        match attrs.instruction_set {
-            None => {}
-            Some(InstructionSetAttr::ArmA32) => {
-                target_features.remove(&sym::thumb_mode);
-            }
-            Some(InstructionSetAttr::ArmT32) => {
-                target_features.insert(sym::thumb_mode);
-            }
-        }
-    }
-
-    tcx.arena.alloc(target_features)
-}
-
-/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
-/// applied to the method prototype.
-fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
-    if let Some(impl_item) = tcx.opt_associated_item(def_id)
-        && let ty::AssocItemContainer::ImplContainer = impl_item.container
-        && let Some(trait_item) = impl_item.trait_item_def_id
-    {
-        return tcx
-            .codegen_fn_attrs(trait_item)
-            .flags
-            .intersects(CodegenFnAttrFlags::TRACK_CALLER);
-    }
-
-    false
-}
-
-fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option<u16> {
-    use rustc_ast::{LitIntType, LitKind, MetaItemLit};
-    if !tcx.features().raw_dylib && tcx.sess.target.arch == "x86" {
-        feature_err(
-            &tcx.sess.parse_sess,
-            sym::raw_dylib,
-            attr.span,
-            "`#[link_ordinal]` is unstable on x86",
-        )
-        .emit();
-    }
-    let meta_item_list = attr.meta_item_list();
-    let meta_item_list = meta_item_list.as_deref();
-    let sole_meta_list = match meta_item_list {
-        Some([item]) => item.lit(),
-        Some(_) => {
-            tcx.sess
-                .struct_span_err(attr.span, "incorrect number of arguments to `#[link_ordinal]`")
-                .note("the attribute requires exactly one argument")
-                .emit();
-            return None;
-        }
-        _ => None,
-    };
-    if let Some(MetaItemLit { kind: LitKind::Int(ordinal, LitIntType::Unsuffixed), .. }) =
-        sole_meta_list
-    {
-        // According to the table at https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-header,
-        // the ordinal must fit into 16 bits.  Similarly, the Ordinal field in COFFShortExport (defined
-        // in llvm/include/llvm/Object/COFFImportFile.h), which we use to communicate import information
-        // to LLVM for `#[link(kind = "raw-dylib"_])`, is also defined to be uint16_t.
-        //
-        // FIXME: should we allow an ordinal of 0?  The MSVC toolchain has inconsistent support for this:
-        // both LINK.EXE and LIB.EXE signal errors and abort when given a .DEF file that specifies
-        // a zero ordinal.  However, llvm-dlltool is perfectly happy to generate an import library
-        // for such a .DEF file, and MSVC's LINK.EXE is also perfectly happy to consume an import
-        // library produced by LLVM with an ordinal of 0, and it generates an .EXE.  (I don't know yet
-        // if the resulting EXE runs, as I haven't yet built the necessary DLL -- see earlier comment
-        // about LINK.EXE failing.)
-        if *ordinal <= u16::MAX as u128 {
-            Some(*ordinal as u16)
-        } else {
-            let msg = format!("ordinal value in `link_ordinal` is too large: `{}`", &ordinal);
-            tcx.sess
-                .struct_span_err(attr.span, &msg)
-                .note("the value may not exceed `u16::MAX`")
-                .emit();
-            None
-        }
-    } else {
-        tcx.sess
-            .struct_span_err(attr.span, "illegal ordinal format in `link_ordinal`")
-            .note("an unsuffixed integer value, e.g., `1`, is expected")
-            .emit();
-        None
-    }
-}
-
-fn check_link_name_xor_ordinal(
-    tcx: TyCtxt<'_>,
-    codegen_fn_attrs: &CodegenFnAttrs,
-    inline_span: Option<Span>,
-) {
-    if codegen_fn_attrs.link_name.is_none() || codegen_fn_attrs.link_ordinal.is_none() {
-        return;
-    }
-    let msg = "cannot use `#[link_name]` with `#[link_ordinal]`";
-    if let Some(span) = inline_span {
-        tcx.sess.span_err(span, msg);
-    } else {
-        tcx.sess.err(msg);
-    }
-}
-
-/// Checks the function annotated with `#[target_feature]` is not a safe
-/// trait method implementation, reporting an error if it is.
-fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_span: Span) {
-    let hir_id = tcx.hir().local_def_id_to_hir_id(id);
-    let node = tcx.hir().get(hir_id);
-    if let Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) = node {
-        let parent_id = tcx.hir().get_parent_item(hir_id);
-        let parent_item = tcx.hir().expect_item(parent_id.def_id);
-        if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = parent_item.kind {
-            tcx.sess
-                .struct_span_err(
-                    attr_span,
-                    "`#[target_feature(..)]` cannot be applied to safe trait method",
-                )
-                .span_label(attr_span, "cannot be applied to safe trait method")
-                .span_label(tcx.def_span(id), "not an `unsafe` function")
-                .emit();
-        }
-    }
-}
index 639f81f20bfb9d2389ee19f73ae3cf2043e5087b..cb4c35c0ce177e527e1bab8feba86b319ce53878 100644 (file)
@@ -4,7 +4,6 @@
     GenericParamKind, HirId, Node,
 };
 use rustc_hir as hir;
-use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::lint;
@@ -79,7 +78,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
                     let generics = tcx.generics_of(parent_def_id.to_def_id());
                     let param_def_idx = generics.param_def_id_to_index[&param_id.to_def_id()];
                     // In the above example this would be .params[..N#0]
-                    let params = generics.params[..param_def_idx as usize].to_owned();
+                    let params = generics.params_to(param_def_idx as usize, tcx).to_owned();
                     let param_def_id_to_index =
                         params.iter().map(|param| (param.def_id, param.index)).collect();
 
@@ -143,20 +142,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
             Some(tcx.typeck_root_def_id(def_id))
         }
         Node::Item(item) => match item.kind {
-            ItemKind::OpaqueTy(hir::OpaqueTy {
-                origin:
-                    hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
-                in_trait,
-                ..
-            }) => {
-                if in_trait {
-                    assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn))
-                } else {
-                    assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn | DefKind::Fn))
-                }
-                Some(fn_def_id.to_def_id())
-            }
-            ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => {
+            ItemKind::OpaqueTy(hir::OpaqueTy { .. }) => {
                 let parent_id = tcx.hir().get_parent_item(hir_id);
                 assert_ne!(parent_id, hir::CRATE_OWNER_ID);
                 debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id);
index 9a7b261fffd4ded6cde9bc8bee5f84f8af042336..b4ad3467e7d87ac67cac22c7705cedb92ea5cccf 100644 (file)
@@ -1749,7 +1749,7 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<!> {
                 ty::Param(param_ty) => {
                     self.arg_is_constrained[param_ty.index as usize] = true;
                 }
-                ty::Projection(_) => return ControlFlow::Continue(()),
+                ty::Alias(ty::Projection, _) => return ControlFlow::Continue(()),
                 _ => (),
             }
             t.super_visit_with(self)
index 45e241f4e093d523cf2d6e35f380dc2a961cf464..79d75231e5d76d04024a44ebcc76621ea4449ecb 100644 (file)
@@ -75,7 +75,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
 
     const NO_GENERICS: &hir::Generics<'_> = hir::Generics::empty();
 
-    // We use an `IndexSet` to preserves order of insertion.
+    // We use an `IndexSet` to preserve order of insertion.
     // Preserving the order of insertion is important here so as not to break UI tests.
     let mut predicates: FxIndexSet<(ty::Predicate<'_>, Span)> = FxIndexSet::default();
 
@@ -97,11 +97,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
             | ItemKind::Struct(_, ref generics)
             | ItemKind::Union(_, ref generics) => *generics,
 
-            ItemKind::Trait(_, _, ref generics, ..) => {
-                is_trait = Some(ty::TraitRef::identity(tcx, def_id));
-                *generics
-            }
-            ItemKind::TraitAlias(ref generics, _) => {
+            ItemKind::Trait(_, _, ref generics, ..) | ItemKind::TraitAlias(ref generics, _) => {
                 is_trait = Some(ty::TraitRef::identity(tcx, def_id));
                 *generics
             }
@@ -406,14 +402,15 @@ pub(super) fn explicit_predicates_of<'tcx>(
             // For a predicate from a where clause to become a bound on an
             // associated type:
             // * It must use the identity substs of the item.
-            //     * Since any generic parameters on the item are not in scope,
-            //       this means that the item is not a GAT, and its identity
-            //       substs are the same as the trait's.
+            //   * We're in the scope of the trait, so we can't name any
+            //     parameters of the GAT. That means that all we need to
+            //     check are that the substs of the projection are the
+            //     identity substs of the trait.
             // * It must be an associated type for this trait (*not* a
             //   supertrait).
-            if let ty::Projection(projection) = ty.kind() {
+            if let ty::Alias(ty::Projection, projection) = ty.kind() {
                 projection.substs == trait_identity_substs
-                    && tcx.associated_item(projection.item_def_id).container_id(tcx) == def_id
+                    && tcx.associated_item(projection.def_id).container_id(tcx) == def_id
             } else {
                 false
             }
index 9bd1715ce39ffe21fe413a4bb0dee0c95b30e890..b678990f94e918ba6f9f26ad160b9771b19366b7 100644 (file)
@@ -52,7 +52,7 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
             // Using the ItemCtxt convert the HIR for the unresolved assoc type into a
             // ty which is a fully resolved projection.
             // For the code example above, this would mean converting Self::Assoc<3>
-            // into a ty::Projection(<Self as Foo>::Assoc<3>)
+            // into a ty::Alias(ty::Projection, <Self as Foo>::Assoc<3>)
             let item_hir_id = tcx
                 .hir()
                 .parent_iter(hir_id)
@@ -68,8 +68,8 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
             // the def_id that this query was called with. We filter to only type and const args here
             // as a precaution for if it's ever allowed to elide lifetimes in GAT's. It currently isn't
             // but it can't hurt to be safe ^^
-            if let ty::Projection(projection) = ty.kind() {
-                let generics = tcx.generics_of(projection.item_def_id);
+            if let ty::Alias(ty::Projection, projection) = ty.kind() {
+                let generics = tcx.generics_of(projection.def_id);
 
                 let arg_index = segment
                     .args
@@ -666,7 +666,7 @@ fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
 
     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
     let scope = tcx.hir().get_defining_scope(hir_id);
-    let mut locator = ConstraintLocator { def_id: def_id, tcx, found: None, typeck_types: vec![] };
+    let mut locator = ConstraintLocator { def_id, tcx, found: None, typeck_types: vec![] };
 
     debug!(?scope);
 
@@ -803,7 +803,7 @@ fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
     if let Some(concrete) = concrete {
         let scope = tcx.hir().local_def_id_to_hir_id(owner_def_id);
         debug!(?scope);
-        let mut locator = ConstraintChecker { def_id: def_id, tcx, found: concrete };
+        let mut locator = ConstraintChecker { def_id, tcx, found: concrete };
 
         match tcx.hir().get(scope) {
             Node::Item(it) => intravisit::walk_item(&mut locator, it),
index b4057df7896f30fa331f932e1c838bf91a35527d..95c971c0d7845eee2d63668b8527c419b67eb4e6 100644 (file)
@@ -59,7 +59,7 @@ struct ParameterCollector {
 impl<'tcx> TypeVisitor<'tcx> for ParameterCollector {
     fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
         match *t.kind() {
-            ty::Projection(..) if !self.include_nonconstraining => {
+            ty::Alias(ty::Projection, ..) if !self.include_nonconstraining => {
                 // projections are not injective
                 return ControlFlow::CONTINUE;
             }
index 5156d432b5b3720cbdfc7acdd57fcfbbc0ca2007..d383fcacb3a9c914ce0b862daf1386e8b52c453e 100644 (file)
@@ -51,6 +51,17 @@ pub struct LifetimesOrBoundsMismatchOnTrait {
     pub ident: Ident,
 }
 
+#[derive(Diagnostic)]
+#[diag(hir_analysis_async_trait_impl_should_be_async)]
+pub struct AsyncTraitImplShouldBeAsync {
+    #[primary_span]
+    // #[label]
+    pub span: Span,
+    #[label(trait_item_label)]
+    pub trait_item_span: Option<Span>,
+    pub method_name: Symbol,
+}
+
 #[derive(Diagnostic)]
 #[diag(hir_analysis_drop_impl_on_wrong_item, code = "E0120")]
 pub struct DropImplOnWrongItem {
@@ -253,13 +264,6 @@ pub struct ExternCrateNotIdiomatic {
     pub suggestion_code: String,
 }
 
-#[derive(Diagnostic)]
-#[diag(hir_analysis_expected_used_symbol)]
-pub struct ExpectedUsedSymbol {
-    #[primary_span]
-    pub span: Span,
-}
-
 #[derive(Diagnostic)]
 #[diag(hir_analysis_const_impl_for_non_const_trait)]
 pub struct ConstImplForNonConstTrait {
@@ -289,3 +293,10 @@ pub struct SelfInImplSelf {
     #[note]
     pub note: (),
 }
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_linkage_type, code = "E0791")]
+pub(crate) struct LinkageType {
+    #[primary_span]
+    pub span: Span,
+}
index 90c6edb65e46faa6aac8214fb3587c9abd5a5723..af8d7e8515865583d84f4769944025e7d6483ded 100644 (file)
@@ -196,13 +196,13 @@ fn insert_required_predicates_to_be_wf<'tcx>(
                 }
             }
 
-            ty::Projection(obj) => {
+            ty::Alias(ty::Projection, obj) => {
                 // This corresponds to `<T as Foo<'a>>::Bar`. In this case, we should use the
                 // explicit predicates as well.
                 debug!("Projection");
                 check_explicit_predicates(
                     tcx,
-                    tcx.parent(obj.item_def_id),
+                    tcx.parent(obj.def_id),
                     obj.substs,
                     required_predicates,
                     explicit_map,
index 0409c7081dc4f5cde6e626905b82b9255e83f6f2..b51b740d08e2e7a2e87f7bb578205bbcc430237c 100644 (file)
@@ -90,7 +90,7 @@ pub(crate) fn insert_outlives_predicate<'tcx>(
                         // ```
                         //
                         // Here we want to add an explicit `where <T as Iterator>::Item: 'a`.
-                        let ty: Ty<'tcx> = tcx.mk_projection(proj_ty.item_def_id, proj_ty.substs);
+                        let ty: Ty<'tcx> = tcx.mk_projection(proj_ty.def_id, proj_ty.substs);
                         required_predicates
                             .entry(ty::OutlivesPredicate(ty.into(), outlived_region))
                             .or_insert(span);
index 6ce0c18bf45f1368730d97a460aa0716eeca2900..5e4d82b6fd5697ce31b095b0431a804f67d383f5 100644 (file)
@@ -249,14 +249,10 @@ fn add_constraints_from_ty(
                 self.add_constraints_from_substs(current, def.did(), substs, variance);
             }
 
-            ty::Projection(ref data) => {
+            ty::Alias(_, ref data) => {
                 self.add_constraints_from_invariant_substs(current, data.substs, variance);
             }
 
-            ty::Opaque(_, substs) => {
-                self.add_constraints_from_invariant_substs(current, substs, variance);
-            }
-
             ty::Dynamic(data, r, _) => {
                 // The type `Foo<T+'a>` is contravariant w/r/t `'a`:
                 let contra = self.contravariant(variance);
index 8b2719c2f8aaaef1add2f372c81751f7b6bdc8c2..24008f88814339d1f343fe38c0cf368165afe994 100644 (file)
@@ -111,11 +111,13 @@ fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
         #[instrument(level = "trace", skip(self), ret)]
         fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
             match t.kind() {
-                ty::Opaque(def_id, substs) => self.visit_opaque(*def_id, substs),
-                ty::Projection(proj)
-                    if self.tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder =>
+                ty::Alias(_, ty::AliasTy { def_id, substs, .. })
+                    if matches!(
+                        self.tcx.def_kind(*def_id),
+                        DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder
+                    ) =>
                 {
-                    self.visit_opaque(proj.item_def_id, proj.substs)
+                    self.visit_opaque(*def_id, substs)
                 }
                 _ => t.super_visit_with(self),
             }
@@ -158,7 +160,7 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
         // instead of requiring an additional `+ 'a`.
         match pred.kind().skip_binder() {
             ty::PredicateKind::Clause(ty::Clause::Trait(ty::TraitPredicate {
-                trait_ref: ty::TraitRef { def_id: _, substs },
+                trait_ref: ty::TraitRef { def_id: _, substs, .. },
                 constness: _,
                 polarity: _,
             })) => {
@@ -167,7 +169,7 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
                 }
             }
             ty::PredicateKind::Clause(ty::Clause::Projection(ty::ProjectionPredicate {
-                projection_ty: ty::ProjectionTy { substs, item_def_id: _ },
+                projection_ty: ty::AliasTy { substs, .. },
                 term,
             })) => {
                 for subst in &substs[1..] {
index 94bab9f339d8c9e0b8d0c5741975506184e1bbca..29a6902ccb0772591f896c431ec61e9d45ce37e1 100644 (file)
@@ -1245,7 +1245,7 @@ fn print_expr_addr_of(
 
     fn print_literal(&mut self, lit: &hir::Lit) {
         self.maybe_print_comment(lit.span.lo());
-        self.word(lit.node.to_token_lit().to_string())
+        self.word(lit.node.to_string())
     }
 
     fn print_inline_asm(&mut self, asm: &hir::InlineAsm<'_>) {
@@ -1757,7 +1757,6 @@ pub fn print_pat(&mut self, pat: &hir::Pat<'_>) {
                 self.print_qpath(qpath, true);
                 self.popen();
                 if let Some(ddpos) = ddpos.as_opt_usize() {
-                    let ddpos = ddpos as usize;
                     self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p));
                     if ddpos != 0 {
                         self.word_space(",");
index e25a9e9036a15607e6b2000aac8c03f8281eaa63..ab12cae4e2b08a0b48fc57e8b687f841b7b59509 100644 (file)
@@ -212,7 +212,7 @@ fn suggest_removing_semicolon_for_coerce(
                 self.can_coerce(arm_ty, ret_ty)
                     && prior_arm.map_or(true, |(_, ty, _)| self.can_coerce(ty, ret_ty))
                     // The match arms need to unify for the case of `impl Trait`.
-                    && !matches!(ret_ty.kind(), ty::Opaque(..))
+                    && !matches!(ret_ty.kind(), ty::Alias(ty::Opaque, ..))
             }
             _ => false,
         };
@@ -518,7 +518,7 @@ pub(crate) fn opt_suggest_box_span(
 
                 let substs = sig.output().walk().find_map(|arg| {
                     if let ty::GenericArgKind::Type(ty) = arg.unpack()
-                        && let ty::Opaque(def_id, substs) = *ty.kind()
+                        && let ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) = *ty.kind()
                         && def_id == rpit_def_id
                     {
                         Some(substs)
@@ -542,15 +542,12 @@ pub(crate) fn opt_suggest_box_span(
                             ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => {
                                 assert_eq!(trait_pred.trait_ref.self_ty(), opaque_ty);
                                 ty::PredicateKind::Clause(ty::Clause::Trait(
-                                    trait_pred.with_self_type(self.tcx, ty),
+                                    trait_pred.with_self_ty(self.tcx, ty),
                                 ))
                             }
                             ty::PredicateKind::Clause(ty::Clause::Projection(mut proj_pred)) => {
                                 assert_eq!(proj_pred.projection_ty.self_ty(), opaque_ty);
-                                proj_pred.projection_ty.substs = self.tcx.mk_substs_trait(
-                                    ty,
-                                    proj_pred.projection_ty.substs.iter().skip(1),
-                                );
+                                proj_pred = proj_pred.with_self_ty(self.tcx, ty);
                                 ty::PredicateKind::Clause(ty::Clause::Projection(proj_pred))
                             }
                             _ => continue,
index b09ddf80e2a52577292e3d602fca7e3cff198dc2..7a5191b77f1d45759a88ce6f7c6740f1b257df6d 100644 (file)
@@ -521,7 +521,7 @@ fn suggest_call_as_method(
                 callee_expr,
                 call_expr,
                 callee_ty,
-                pick,
+                &pick,
                 segment,
             );
             if pick.illegal_sized_bound.is_some() {
index 890a068a7befc8c78cc14ad9d9c0d4fe96851cb7..042a50f2fd42eb89906167fde85ed9b0e4eb1622 100644 (file)
@@ -38,7 +38,6 @@
 use rustc_middle::ty::adjustment::AllowTwoPhase;
 use rustc_middle::ty::cast::{CastKind, CastTy};
 use rustc_middle::ty::error::TypeError;
-use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{self, Ty, TypeAndMut, TypeVisitable, VariantDef};
 use rustc_session::lint;
 use rustc_session::Session;
@@ -75,10 +74,8 @@ enum PointerKind<'tcx> {
     VTable(Option<DefId>),
     /// Slice
     Length,
-    /// The unsize info of this projection
-    OfProjection(ty::ProjectionTy<'tcx>),
-    /// The unsize info of this opaque ty
-    OfOpaque(DefId, SubstsRef<'tcx>),
+    /// The unsize info of this projection or opaque type
+    OfAlias(ty::AliasTy<'tcx>),
     /// The unsize info of this parameter
     OfParam(ty::ParamTy),
 }
@@ -118,8 +115,7 @@ fn pointer_kind(
             // Pointers to foreign types are thin, despite being unsized
             ty::Foreign(..) => Some(PointerKind::Thin),
             // We should really try to normalize here.
-            ty::Projection(pi) => Some(PointerKind::OfProjection(pi)),
-            ty::Opaque(def_id, substs) => Some(PointerKind::OfOpaque(def_id, substs)),
+            ty::Alias(_, pi) => Some(PointerKind::OfAlias(pi)),
             ty::Param(p) => Some(PointerKind::OfParam(p)),
             // Insufficient type information.
             ty::Placeholder(..) | ty::Bound(..) | ty::Infer(_) => None,
@@ -851,13 +847,15 @@ pub fn do_check(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result<CastKind, CastError> {
 
             (Int(_) | Float, Int(_) | Float) => Ok(CastKind::NumericCast),
 
-            (_, DynStar) | (DynStar, _) => {
+            (_, DynStar) => {
                 if fcx.tcx.features().dyn_star {
                     bug!("should be handled by `try_coerce`")
                 } else {
                     Err(CastError::IllegalCast)
                 }
             }
+
+            (DynStar, _) => Err(CastError::IllegalCast),
         }
     }
 
@@ -976,11 +974,9 @@ fn check_addr_ptr_cast(
             Some(PointerKind::Thin) => Ok(CastKind::AddrPtrCast),
             Some(PointerKind::VTable(_)) => Err(CastError::IntToFatCast(Some("a vtable"))),
             Some(PointerKind::Length) => Err(CastError::IntToFatCast(Some("a length"))),
-            Some(
-                PointerKind::OfProjection(_)
-                | PointerKind::OfOpaque(_, _)
-                | PointerKind::OfParam(_),
-            ) => Err(CastError::IntToFatCast(None)),
+            Some(PointerKind::OfAlias(_) | PointerKind::OfParam(_)) => {
+                Err(CastError::IntToFatCast(None))
+            }
         }
     }
 
index 0c9a350c295f4227866c20eb5e4ae887b027ed7d..32f86b8042c11c39d36baa268dc8cb40d1c1a1c3 100644 (file)
@@ -1,7 +1,7 @@
 use crate::coercion::CoerceMany;
 use crate::gather_locals::GatherLocalsVisitor;
 use crate::FnCtxt;
-use crate::{GeneratorTypes, UnsafetyState};
+use crate::GeneratorTypes;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::intravisit::Visitor;
@@ -30,7 +30,6 @@ pub(super) fn check_fn<'a, 'tcx>(
     can_be_generator: Option<hir::Movability>,
 ) -> Option<GeneratorTypes<'tcx>> {
     let fn_id = fcx.tcx.hir().local_def_id_to_hir_id(fn_def_id);
-    fcx.ps.set(UnsafetyState::function(fn_sig.unsafety, fn_id));
 
     let tcx = fcx.tcx;
     let hir = tcx.hir();
index 429cb60ba2b6161692c9153041a068ce638e69d5..5bd02dff73bfc1f033318eff0d0568c9e382d9cb 100644 (file)
@@ -167,9 +167,10 @@ fn deduce_expectations_from_expected_type(
         expected_ty: Ty<'tcx>,
     ) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) {
         match *expected_ty.kind() {
-            ty::Opaque(def_id, substs) => self.deduce_signature_from_predicates(
-                self.tcx.bound_explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs),
-            ),
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => self
+                .deduce_signature_from_predicates(
+                    self.tcx.bound_explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs),
+                ),
             ty::Dynamic(ref object_type, ..) => {
                 let sig = object_type.projection_bounds().find_map(|pb| {
                     let pb = pb.with_self_ty(self.tcx, self.tcx.types.trait_object_dummy_self);
@@ -425,7 +426,7 @@ fn sig_of_closure_with_expectation(
         // `deduce_expectations_from_expected_type` introduces
         // late-bound lifetimes defined elsewhere, which we now
         // anonymize away, so as not to confuse the user.
-        let bound_sig = self.tcx.anonymize_late_bound_regions(bound_sig);
+        let bound_sig = self.tcx.anonymize_bound_vars(bound_sig);
 
         let closure_sigs = self.closure_sigs(expr_def_id, body, bound_sig);
 
@@ -677,17 +678,17 @@ fn deduce_future_output_from_obligations(
                     get_future_output(obligation.predicate, obligation.cause.span)
                 })?
             }
-            ty::Opaque(def_id, substs) => self
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => self
                 .tcx
                 .bound_explicit_item_bounds(def_id)
                 .subst_iter_copied(self.tcx, substs)
                 .find_map(|(p, s)| get_future_output(p, s))?,
             ty::Error(_) => return None,
-            ty::Projection(proj)
-                if self.tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder =>
+            ty::Alias(ty::Projection, proj)
+                if self.tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder =>
             {
                 self.tcx
-                    .bound_explicit_item_bounds(proj.item_def_id)
+                    .bound_explicit_item_bounds(proj.def_id)
                     .subst_iter_copied(self.tcx, proj.substs)
                     .find_map(|(p, s)| get_future_output(p, s))?
             }
@@ -743,11 +744,11 @@ fn deduce_future_output_from_projection(
         // The `Future` trait has only one associated item, `Output`,
         // so check that this is what we see.
         let output_assoc_item = self.tcx.associated_item_def_ids(future_trait)[0];
-        if output_assoc_item != predicate.projection_ty.item_def_id {
+        if output_assoc_item != predicate.projection_ty.def_id {
             span_bug!(
                 cause_span,
                 "projecting associated item `{:?}` from future, which is not Output `{:?}`",
-                predicate.projection_ty.item_def_id,
+                predicate.projection_ty.def_id,
                 output_assoc_item,
             );
         }
index f0b349f0c98dd667f349083ab9555df2aa758589..36cf4791492dd1c8c8b36d1125289dc008cb3fed 100644 (file)
@@ -1805,7 +1805,7 @@ fn add_impl_trait_explanation<'a>(
         {
             let ty = <dyn AstConv<'_>>::ast_ty_to_ty(fcx, ty);
             // Get the `impl Trait`'s `DefId`.
-            if let ty::Opaque(def_id, _) = ty.kind()
+            if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = ty.kind()
                 // Get the `impl Trait`'s `Item` so that we can get its trait bounds and
                 // get the `Trait`'s `DefId`.
                 && let hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }) =
index 24184bdbf5cdcd74b125f185243919086905910f..87abd01c7fd8fb90679ad147f38cea605db1b80c 100644 (file)
@@ -189,7 +189,7 @@ fn annotate_expected_due_to_let_ty(
         &self,
         err: &mut Diagnostic,
         expr: &hir::Expr<'_>,
-        error: Option<TypeError<'_>>,
+        error: Option<TypeError<'tcx>>,
     ) {
         let parent = self.tcx.hir().get_parent_node(expr.hir_id);
         match (self.tcx.hir().find(parent), error) {
@@ -286,6 +286,16 @@ fn annotate_expected_due_to_let_ty(
                     err.downgrade_to_delayed_bug();
                 }
             }
+            (
+                Some(hir::Node::Expr(hir::Expr {
+                    kind: hir::ExprKind::Binary(_, lhs, rhs), ..
+                })),
+                Some(TypeError::Sorts(ExpectedFound { expected, .. })),
+            ) if rhs.hir_id == expr.hir_id
+                && self.typeck_results.borrow().expr_ty_adjusted_opt(lhs) == Some(expected) =>
+            {
+                err.span_label(lhs.span, &format!("expected because this is `{expected}`"));
+            }
             _ => {}
         }
     }
@@ -1265,7 +1275,7 @@ pub fn check_for_cast(
             };
 
         match (&expected_ty.kind(), &checked_ty.kind()) {
-            (&ty::Int(ref exp), &ty::Int(ref found)) => {
+            (ty::Int(exp), ty::Int(found)) => {
                 let (f2e_is_fallible, e2f_is_fallible) = match (exp.bit_width(), found.bit_width())
                 {
                     (Some(exp), Some(found)) if exp < found => (true, false),
@@ -1278,7 +1288,7 @@ pub fn check_for_cast(
                 suggest_to_change_suffix_or_into(err, f2e_is_fallible, e2f_is_fallible);
                 true
             }
-            (&ty::Uint(ref exp), &ty::Uint(ref found)) => {
+            (ty::Uint(exp), ty::Uint(found)) => {
                 let (f2e_is_fallible, e2f_is_fallible) = match (exp.bit_width(), found.bit_width())
                 {
                     (Some(exp), Some(found)) if exp < found => (true, false),
@@ -1311,7 +1321,7 @@ pub fn check_for_cast(
                 suggest_to_change_suffix_or_into(err, f2e_is_fallible, e2f_is_fallible);
                 true
             }
-            (&ty::Float(ref exp), &ty::Float(ref found)) => {
+            (ty::Float(exp), ty::Float(found)) => {
                 if found.bit_width() < exp.bit_width() {
                     suggest_to_change_suffix_or_into(err, false, true);
                 } else if literal_is_ty_suffixed(expr) {
@@ -1347,7 +1357,7 @@ pub fn check_for_cast(
                 }
                 true
             }
-            (&ty::Float(ref exp), &ty::Uint(ref found)) => {
+            (ty::Float(exp), ty::Uint(found)) => {
                 // if `found` is `None` (meaning found is `usize`), don't suggest `.into()`
                 if exp.bit_width() > found.bit_width().unwrap_or(256) {
                     err.multipart_suggestion_verbose(
@@ -1376,7 +1386,7 @@ pub fn check_for_cast(
                 }
                 true
             }
-            (&ty::Float(ref exp), &ty::Int(ref found)) => {
+            (ty::Float(exp), ty::Int(found)) => {
                 // if `found` is `None` (meaning found is `isize`), don't suggest `.into()`
                 if exp.bit_width() > found.bit_width().unwrap_or(256) {
                     err.multipart_suggestion_verbose(
index 4a112e80f1d98f0ec775795fe304feb3c83c8e2d..edbbb7272ac77d899b02d2aa3116a2decf497c04 100644 (file)
@@ -1647,6 +1647,9 @@ fn check_expr_struct_fields(
         // the fields with the base_expr. This could cause us to hit errors later
         // when certain fields are assumed to exist that in fact do not.
         if error_happened {
+            if let Some(base_expr) = base_expr {
+                self.check_expr(base_expr);
+            }
             return;
         }
 
@@ -1871,7 +1874,7 @@ fn suggest_fru_from_range(
         // I don't use 'is_range_literal' because only double-sided, half-open ranges count.
         if let ExprKind::Struct(
                 QPath::LangItem(LangItem::Range, ..),
-                &[ref range_start, ref range_end],
+                [range_start, range_end],
                 _,
             ) = last_expr_field.expr.kind
             && let variant_field =
@@ -2388,7 +2391,7 @@ fn ban_nonexisting_field(
             ty::Param(param_ty) => {
                 self.point_at_param_definition(&mut err, param_ty);
             }
-            ty::Opaque(_, _) => {
+            ty::Alias(ty::Opaque, _) => {
                 self.suggest_await_on_field_access(&mut err, ident, base, base_ty.peel_refs());
             }
             _ => {}
index e5e798f4b933f2ec18ae1dc5bdc8c4e6bd411cbe..03b174c77955fb400eab47aa6071b3cec6bef94a 100644 (file)
@@ -523,6 +523,11 @@ fn walk_struct_expr<'hir>(
         // Consume the expressions supplying values for each field.
         for field in fields {
             self.consume_expr(field.expr);
+
+            // The struct path probably didn't resolve
+            if self.mc.typeck_results.opt_field_index(field.hir_id).is_none() {
+                self.tcx().sess.delay_span_bug(field.span, "couldn't resolve index for field");
+            }
         }
 
         let with_expr = match *opt_with {
@@ -540,9 +545,9 @@ fn walk_struct_expr<'hir>(
             ty::Adt(adt, substs) if adt.is_struct() => {
                 // Consume those fields of the with expression that are needed.
                 for (f_index, with_field) in adt.non_enum_variant().fields.iter().enumerate() {
-                    let is_mentioned = fields.iter().any(|f| {
-                        self.tcx().field_index(f.hir_id, self.mc.typeck_results) == f_index
-                    });
+                    let is_mentioned = fields
+                        .iter()
+                        .any(|f| self.mc.typeck_results.opt_field_index(f.hir_id) == Some(f_index));
                     if !is_mentioned {
                         let field_place = self.mc.cat_projection(
                             &*with_expr,
index 952d2726259187c736488ccd827d17973b571ed7..1a4e6bf763821b05ee33737dc392ef35d145eb8a 100644 (file)
@@ -716,7 +716,7 @@ pub(in super::super) fn expected_inputs_for_expected_output(
         if formal_ret.has_infer_types() {
             for ty in ret_ty.walk() {
                 if let ty::subst::GenericArgKind::Type(ty) = ty.unpack()
-                    && let ty::Opaque(def_id, _) = *ty.kind()
+                    && let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *ty.kind()
                     && let Some(def_id) = def_id.as_local()
                     && self.opaque_type_origin(def_id, DUMMY_SP).is_some() {
                     return None;
index 8a875e05b19b7db2280c4b2356e7a827eb8217e3..8e520e563ff630ecdeb62b0e4a1b046feb7dbe14 100644 (file)
@@ -1169,7 +1169,7 @@ pub(in super::super) fn check_lit(
 
         match lit.node {
             ast::LitKind::Str(..) => tcx.mk_static_str(),
-            ast::LitKind::ByteStr(ref v) => {
+            ast::LitKind::ByteStr(ref v, _) => {
                 tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_array(tcx.types.u8, v.len() as u64))
             }
             ast::LitKind::Byte(_) => tcx.types.u8,
@@ -1393,8 +1393,6 @@ pub(in super::super) fn check_block_with_expected(
         blk: &'tcx hir::Block<'tcx>,
         expected: Expectation<'tcx>,
     ) -> Ty<'tcx> {
-        let prev = self.ps.replace(self.ps.get().recurse(blk));
-
         // In some cases, blocks have just one exit, but other blocks
         // can be targeted by multiple breaks. This can happen both
         // with labeled blocks as well as when we desugar
@@ -1558,7 +1556,6 @@ pub(in super::super) fn check_block_with_expected(
 
         self.write_ty(blk.hir_id, ty);
 
-        self.ps.set(prev);
         ty
     }
 
@@ -2127,7 +2124,7 @@ fn label_fn_like(
                         }
                     }
                 }
-                ty::Opaque(new_def_id, _)
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id: new_def_id, .. })
                 | ty::Closure(new_def_id, _)
                 | ty::FnDef(new_def_id, _) => {
                     def_id = new_def_id;
@@ -2135,19 +2132,15 @@ fn label_fn_like(
                 _ => {
                     // Look for a user-provided impl of a `Fn` trait, and point to it.
                     let new_def_id = self.probe(|_| {
-                        let trait_ref = ty::TraitRef::new(
+                        let trait_ref = self.tcx.mk_trait_ref(
                             call_kind.to_def_id(self.tcx),
-                            self.tcx.mk_substs(
-                                [
-                                    ty::GenericArg::from(callee_ty),
-                                    self.next_ty_var(TypeVariableOrigin {
-                                        kind: TypeVariableOriginKind::MiscVariable,
-                                        span: rustc_span::DUMMY_SP,
-                                    })
-                                    .into(),
-                                ]
-                                .into_iter(),
-                            ),
+                            [
+                                callee_ty,
+                                self.next_ty_var(TypeVariableOrigin {
+                                    kind: TypeVariableOriginKind::MiscVariable,
+                                    span: rustc_span::DUMMY_SP,
+                                }),
+                            ],
                         );
                         let obligation = traits::Obligation::new(
                             self.tcx,
@@ -2220,7 +2213,7 @@ fn find_param_in_ty<'tcx>(ty: Ty<'tcx>, param_to_point_at: ty::GenericArg<'tcx>)
         if arg == param_to_point_at {
             return true;
         } else if let ty::GenericArgKind::Type(ty) = arg.unpack()
-            && let ty::Projection(..) = ty.kind()
+            && let ty::Alias(ty::Projection, ..) = ty.kind()
         {
             // This logic may seem a bit strange, but typically when
             // we have a projection type in a function signature, the
index 1e9b57521308580fe83adfb40e844bfc38606dc9..30b59da7852d46f1e96543ef7566668e00834910 100644 (file)
@@ -8,7 +8,7 @@
 pub use suggestions::*;
 
 use crate::coercion::DynamicCoerceMany;
-use crate::{Diverges, EnclosingBreakables, Inherited, UnsafetyState};
+use crate::{Diverges, EnclosingBreakables, Inherited};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir_analysis::astconv::AstConv;
@@ -74,8 +74,6 @@ pub struct FnCtxt<'a, 'tcx> {
 
     pub(super) resume_yield_tys: Option<(Ty<'tcx>, Ty<'tcx>)>,
 
-    pub(super) ps: Cell<UnsafetyState>,
-
     /// Whether the last checked node generates a divergence (e.g.,
     /// `return` will set this to `Always`). In general, when entering
     /// an expression or other node in the tree, the initial value
@@ -129,7 +127,6 @@ pub fn new(
             ret_coercion: None,
             ret_coercion_span: Cell::new(None),
             resume_yield_tys: None,
-            ps: Cell::new(UnsafetyState::function(hir::Unsafety::Normal, hir::CRATE_HIR_ID)),
             diverges: Cell::new(Diverges::Maybe),
             enclosing_breakables: RefCell::new(EnclosingBreakables {
                 stack: Vec::new(),
index 4f92477b5d87ef221239c71054742025efb7bf32..ca4c50c49aae253dc973cb4b9c8730bc108b7003 100644 (file)
@@ -13,7 +13,9 @@
 use rustc_infer::infer;
 use rustc_infer::traits::{self, StatementAsExpression};
 use rustc_middle::lint::in_external_macro;
-use rustc_middle::ty::{self, Binder, DefIdTree, IsSuggestable, ToPredicate, Ty};
+use rustc_middle::ty::{
+    self, suggest_constraining_type_params, Binder, DefIdTree, IsSuggestable, ToPredicate, Ty,
+};
 use rustc_session::errors::ExprParenthesesNeeded;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
@@ -174,10 +176,10 @@ pub(in super::super) fn extract_callable_info(
                     let fn_sig = substs.as_closure().sig();
                     Some((DefIdOrName::DefId(def_id), fn_sig.output(), fn_sig.inputs().map_bound(|inputs| &inputs[1..])))
                 }
-                ty::Opaque(def_id, substs) => {
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
                     self.tcx.bound_item_bounds(def_id).subst(self.tcx, substs).iter().find_map(|pred| {
                         if let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) = pred.kind().skip_binder()
-                        && Some(proj.projection_ty.item_def_id) == self.tcx.lang_items().fn_once_output()
+                        && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output()
                         // args tuple will always be substs[1]
                         && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind()
                         {
@@ -194,7 +196,7 @@ pub(in super::super) fn extract_callable_info(
                 ty::Dynamic(data, _, ty::Dyn) => {
                     data.iter().find_map(|pred| {
                         if let ty::ExistentialPredicate::Projection(proj) = pred.skip_binder()
-                        && Some(proj.item_def_id) == self.tcx.lang_items().fn_once_output()
+                        && Some(proj.def_id) == self.tcx.lang_items().fn_once_output()
                         // for existential projection, substs are shifted over by 1
                         && let ty::Tuple(args) = proj.substs.type_at(0).kind()
                         {
@@ -212,7 +214,7 @@ pub(in super::super) fn extract_callable_info(
                     let def_id = self.tcx.generics_of(self.body_id.owner).type_param(&param, self.tcx).def_id;
                     self.tcx.predicates_of(self.body_id.owner).predicates.iter().find_map(|(pred, _)| {
                         if let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) = pred.kind().skip_binder()
-                        && Some(proj.projection_ty.item_def_id) == self.tcx.lang_items().fn_once_output()
+                        && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output()
                         && proj.projection_ty.self_ty() == found
                         // args tuple will always be substs[1]
                         && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind()
@@ -752,7 +754,7 @@ pub(in super::super) fn suggest_missing_return_type(
                     return true
                 }
             }
-            &hir::FnRetTy::Return(ref ty) => {
+            hir::FnRetTy::Return(ty) => {
                 // Only point to return type if the expected type is the return type, as if they
                 // are not, the expectation must have been caused by something else.
                 debug!("suggest_missing_return_type: return type {:?} node {:?}", ty, ty.kind);
@@ -1276,18 +1278,14 @@ pub(crate) fn note_type_is_not_clone(
             && !results.expr_adjustments(callee_expr).iter().any(|adj| matches!(adj.kind, ty::adjustment::Adjust::Deref(..)))
             // Check that we're in fact trying to clone into the expected type
             && self.can_coerce(*pointee_ty, expected_ty)
+            && let trait_ref = ty::Binder::dummy(self.tcx.mk_trait_ref(clone_trait_did, [expected_ty]))
             // And the expected type doesn't implement `Clone`
-            && !self.predicate_must_hold_considering_regions(&traits::Obligation {
-                cause: traits::ObligationCause::dummy(),
-                param_env: self.param_env,
-                recursion_depth: 0,
-                predicate: ty::Binder::dummy(ty::TraitRef {
-                    def_id: clone_trait_did,
-                    substs: self.tcx.mk_substs([expected_ty.into()].iter()),
-                })
-                .without_const()
-                .to_predicate(self.tcx),
-            })
+            && !self.predicate_must_hold_considering_regions(&traits::Obligation::new(
+                self.tcx,
+                traits::ObligationCause::dummy(),
+                self.param_env,
+                trait_ref,
+            ))
         {
             diag.span_note(
                 callee_expr.span,
@@ -1295,6 +1293,19 @@ pub(crate) fn note_type_is_not_clone(
                     "`{expected_ty}` does not implement `Clone`, so `{found_ty}` was cloned instead"
                 ),
             );
+            let owner = self.tcx.hir().enclosing_body_owner(expr.hir_id);
+            if let ty::Param(param) = expected_ty.kind()
+                && let Some(generics) = self.tcx.hir().get_generics(owner)
+            {
+                suggest_constraining_type_params(
+                    self.tcx,
+                    generics,
+                    diag,
+                    vec![(param.name.as_str(), "Clone", Some(clone_trait_did))].into_iter(),
+                );
+            } else {
+                self.suggest_derive(diag, &[(trait_ref.to_predicate(self.tcx), None, None)]);
+            }
         }
     }
 
index 3b1518ff79b4e8e0859f8436615258b3587ea096..93f2ceed777b5be20bda25798be7d198ef998950 100644 (file)
@@ -563,7 +563,7 @@ fn check_must_not_suspend_ty<'tcx>(
         }
         ty::Adt(def, _) => check_must_not_suspend_def(fcx.tcx, def.did(), hir_id, data),
         // FIXME: support adding the attribute to TAITs
-        ty::Opaque(def, _) => {
+        ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
             let mut has_emitted = false;
             for &(predicate, _) in fcx.tcx.explicit_item_bounds(def) {
                 // We only look at the `DefId`, so it is safe to skip the binder here.
index 09bd123350dfd1e3f794a4f7e13210a7acf50f3e..5b2352cda34b3ee5fa9bcfa2f98d11acee4af2c4 100644 (file)
@@ -89,38 +89,6 @@ pub struct LocalTy<'tcx> {
     revealed_ty: Ty<'tcx>,
 }
 
-#[derive(Copy, Clone)]
-pub struct UnsafetyState {
-    pub def: hir::HirId,
-    pub unsafety: hir::Unsafety,
-    from_fn: bool,
-}
-
-impl UnsafetyState {
-    pub fn function(unsafety: hir::Unsafety, def: hir::HirId) -> UnsafetyState {
-        UnsafetyState { def, unsafety, from_fn: true }
-    }
-
-    pub fn recurse(self, blk: &hir::Block<'_>) -> UnsafetyState {
-        use hir::BlockCheckMode;
-        match self.unsafety {
-            // If this unsafe, then if the outer function was already marked as
-            // unsafe we shouldn't attribute the unsafe'ness to the block. This
-            // way the block can be warned about instead of ignoring this
-            // extraneous block (functions are never warned about).
-            hir::Unsafety::Unsafe if self.from_fn => self,
-
-            unsafety => {
-                let (unsafety, def) = match blk.rules {
-                    BlockCheckMode::UnsafeBlock(..) => (hir::Unsafety::Unsafe, blk.hir_id),
-                    BlockCheckMode::DefaultBlock => (unsafety, self.def),
-                };
-                UnsafetyState { def, unsafety, from_fn: false }
-            }
-        }
-    }
-}
-
 /// If this `DefId` is a "primary tables entry", returns
 /// `Some((body_id, body_ty, fn_sig))`. Otherwise, returns `None`.
 ///
index 03d0e7926de1166fc5103cc7f0167ea4eb153048..218c54688aa3e959a187f7b69aded369e9ab8a99 100644 (file)
@@ -45,7 +45,7 @@ pub fn confirm_method(
         self_expr: &'tcx hir::Expr<'tcx>,
         call_expr: &'tcx hir::Expr<'tcx>,
         unadjusted_self_ty: Ty<'tcx>,
-        pick: probe::Pick<'tcx>,
+        pick: &probe::Pick<'tcx>,
         segment: &hir::PathSegment<'_>,
     ) -> ConfirmResult<'tcx> {
         debug!(
@@ -71,7 +71,7 @@ fn new(
     fn confirm(
         &mut self,
         unadjusted_self_ty: Ty<'tcx>,
-        pick: probe::Pick<'tcx>,
+        pick: &probe::Pick<'tcx>,
         segment: &hir::PathSegment<'_>,
     ) -> ConfirmResult<'tcx> {
         // Adjust the self expression the user provided and obtain the adjusted type.
index a2ca5c3b7b7493a9d0330b772fd87e9bdbced645..3f3af53d199b12918512a1597a9f7b1eb34532a5 100644 (file)
@@ -192,8 +192,7 @@ pub fn lookup_method(
 
         self.tcx.check_stability(pick.item.def_id, Some(call_expr.hir_id), span, None);
 
-        let result =
-            self.confirm_method(span, self_expr, call_expr, self_ty, pick.clone(), segment);
+        let result = self.confirm_method(span, self_expr, call_expr, self_ty, &pick, segment);
         debug!("result = {:?}", result);
 
         if let Some(span) = result.illegal_sized_bound {
@@ -210,7 +209,7 @@ pub fn lookup_method(
                     ProbeScope::TraitsInScope,
                 ) {
                     Ok(ref new_pick) if pick.differs_from(new_pick) => {
-                        needs_mut = true;
+                        needs_mut = new_pick.self_ty.ref_mutability() != self_ty.ref_mutability();
                     }
                     _ => {}
                 }
@@ -286,7 +285,7 @@ pub(super) fn obligation_for_method(
             self.var_for_def(span, param)
         });
 
-        let trait_ref = ty::TraitRef::new(trait_def_id, substs);
+        let trait_ref = self.tcx.mk_trait_ref(trait_def_id, substs);
 
         // Construct an obligation
         let poly_trait_ref = ty::Binder::dummy(trait_ref);
@@ -327,7 +326,7 @@ pub(super) fn obligation_for_op_method(
             self.var_for_def(span, param)
         });
 
-        let trait_ref = ty::TraitRef::new(trait_def_id, substs);
+        let trait_ref = self.tcx.mk_trait_ref(trait_def_id, substs);
 
         // Construct an obligation
         let poly_trait_ref = ty::Binder::dummy(trait_ref);
index ae299cc9d13706d1402600eef7c2a61328144f87..b9e7830bf079214af2a29491fff1ab458fbee011 100644 (file)
@@ -38,9 +38,9 @@
 use rustc_trait_selection::traits::query::CanonicalTyGoal;
 use rustc_trait_selection::traits::NormalizeExt;
 use rustc_trait_selection::traits::{self, ObligationCause};
+use std::cell::RefCell;
 use std::cmp::max;
 use std::iter;
-use std::mem;
 use std::ops::Deref;
 
 use smallvec::{smallvec, SmallVec};
@@ -62,28 +62,29 @@ struct ProbeContext<'a, 'tcx> {
 
     /// This is the OriginalQueryValues for the steps queries
     /// that are answered in steps.
-    orig_steps_var_values: OriginalQueryValues<'tcx>,
+    orig_steps_var_values: &'a OriginalQueryValues<'tcx>,
     steps: &'tcx [CandidateStep<'tcx>],
 
     inherent_candidates: Vec<Candidate<'tcx>>,
     extension_candidates: Vec<Candidate<'tcx>>,
     impl_dups: FxHashSet<DefId>,
 
-    /// Collects near misses when the candidate functions are missing a `self` keyword and is only
-    /// used for error reporting
-    static_candidates: Vec<CandidateSource>,
-
     /// When probing for names, include names that are close to the
-    /// requested name (by Levensthein distance)
+    /// requested name (by Levenshtein distance)
     allow_similar_names: bool,
 
     /// Some(candidate) if there is a private candidate
     private_candidate: Option<(DefKind, DefId)>,
 
+    /// Collects near misses when the candidate functions are missing a `self` keyword and is only
+    /// used for error reporting
+    static_candidates: RefCell<Vec<CandidateSource>>,
+
     /// Collects near misses when trait bounds for type parameters are unsatisfied and is only used
     /// for error reporting
-    unsatisfied_predicates:
+    unsatisfied_predicates: RefCell<
         Vec<(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>, Option<ObligationCause<'tcx>>)>,
+    >,
 
     scope_expr_id: hir::HirId,
 }
@@ -334,7 +335,7 @@ fn probe_op<OP, R>(
         op: OP,
     ) -> Result<R, MethodError<'tcx>>
     where
-        OP: FnOnce(ProbeContext<'a, 'tcx>) -> Result<R, MethodError<'tcx>>,
+        OP: FnOnce(ProbeContext<'_, 'tcx>) -> Result<R, MethodError<'tcx>>,
     {
         let mut orig_values = OriginalQueryValues::default();
         let param_env_and_self_ty = self.canonicalize_query(
@@ -445,7 +446,7 @@ fn probe_op<OP, R>(
                 mode,
                 method_name,
                 return_type,
-                orig_values,
+                &orig_values,
                 steps.steps,
                 scope_expr_id,
             );
@@ -539,7 +540,7 @@ fn new(
         mode: Mode,
         method_name: Option<Ident>,
         return_type: Option<Ty<'tcx>>,
-        orig_steps_var_values: OriginalQueryValues<'tcx>,
+        orig_steps_var_values: &'a OriginalQueryValues<'tcx>,
         steps: &'tcx [CandidateStep<'tcx>],
         scope_expr_id: hir::HirId,
     ) -> ProbeContext<'a, 'tcx> {
@@ -554,10 +555,10 @@ fn new(
             impl_dups: FxHashSet::default(),
             orig_steps_var_values,
             steps,
-            static_candidates: Vec::new(),
             allow_similar_names: false,
             private_candidate: None,
-            unsatisfied_predicates: Vec::new(),
+            static_candidates: RefCell::new(Vec::new()),
+            unsatisfied_predicates: RefCell::new(Vec::new()),
             scope_expr_id,
         }
     }
@@ -566,8 +567,9 @@ fn reset(&mut self) {
         self.inherent_candidates.clear();
         self.extension_candidates.clear();
         self.impl_dups.clear();
-        self.static_candidates.clear();
         self.private_candidate = None;
+        self.static_candidates.borrow_mut().clear();
+        self.unsatisfied_predicates.borrow_mut().clear();
     }
 
     ///////////////////////////////////////////////////////////////////////////
@@ -918,7 +920,7 @@ fn assemble_extension_candidates_for_trait(
     ) {
         debug!("assemble_extension_candidates_for_trait(trait_def_id={:?})", trait_def_id);
         let trait_substs = self.fresh_item_substs(trait_def_id);
-        let trait_ref = ty::TraitRef::new(trait_def_id, trait_substs);
+        let trait_ref = self.tcx.mk_trait_ref(trait_def_id, trait_substs);
 
         if self.tcx.is_trait_alias(trait_def_id) {
             // For trait aliases, assume all supertraits are relevant.
@@ -1003,9 +1005,9 @@ fn pick(mut self) -> PickResult<'tcx> {
 
         debug!("pick: actual search failed, assemble diagnostics");
 
-        let static_candidates = mem::take(&mut self.static_candidates);
+        let static_candidates = std::mem::take(self.static_candidates.get_mut());
         let private_candidate = self.private_candidate.take();
-        let unsatisfied_predicates = mem::take(&mut self.unsatisfied_predicates);
+        let unsatisfied_predicates = std::mem::take(self.unsatisfied_predicates.get_mut());
 
         // things failed, so lets look at all traits, for diagnostic purposes now:
         self.reset();
@@ -1050,7 +1052,7 @@ fn pick(mut self) -> PickResult<'tcx> {
         }))
     }
 
-    fn pick_core(&mut self) -> Option<PickResult<'tcx>> {
+    fn pick_core(&self) -> Option<PickResult<'tcx>> {
         let pick = self.pick_all_method(Some(&mut vec![]));
 
         // In this case unstable picking is done by `pick_method`.
@@ -1065,11 +1067,10 @@ fn pick_core(&mut self) -> Option<PickResult<'tcx>> {
     }
 
     fn pick_all_method(
-        &mut self,
+        &self,
         mut unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
     ) -> Option<PickResult<'tcx>> {
-        let steps = self.steps.clone();
-        steps
+        self.steps
             .iter()
             .filter(|step| {
                 debug!("pick_all_method: step={:?}", step);
@@ -1123,7 +1124,7 @@ fn pick_all_method(
     /// to transparently pass `&mut` pointers, in particular, without consuming
     /// them for their entire lifetime.
     fn pick_by_value_method(
-        &mut self,
+        &self,
         step: &CandidateStep<'tcx>,
         self_ty: Ty<'tcx>,
         unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
@@ -1151,7 +1152,7 @@ fn pick_by_value_method(
     }
 
     fn pick_autorefd_method(
-        &mut self,
+        &self,
         step: &CandidateStep<'tcx>,
         self_ty: Ty<'tcx>,
         mutbl: hir::Mutability,
@@ -1177,7 +1178,7 @@ fn pick_autorefd_method(
     /// special case for this is because going from `*mut T` to `*const T` with autoderefs and
     /// autorefs would require dereferencing the pointer, which is not safe.
     fn pick_const_ptr_method(
-        &mut self,
+        &self,
         step: &CandidateStep<'tcx>,
         self_ty: Ty<'tcx>,
         unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
@@ -1202,7 +1203,7 @@ fn pick_const_ptr_method(
         })
     }
 
-    fn pick_method_with_unstable(&mut self, self_ty: Ty<'tcx>) -> Option<PickResult<'tcx>> {
+    fn pick_method_with_unstable(&self, self_ty: Ty<'tcx>) -> Option<PickResult<'tcx>> {
         debug!("pick_method_with_unstable(self_ty={})", self.ty_to_string(self_ty));
 
         let mut possibly_unsatisfied_predicates = Vec::new();
@@ -1213,7 +1214,7 @@ fn pick_method_with_unstable(&mut self, self_ty: Ty<'tcx>) -> Option<PickResult<
             debug!("searching {} candidates", kind);
             let res = self.consider_candidates(
                 self_ty,
-                candidates.iter(),
+                candidates,
                 &mut possibly_unsatisfied_predicates,
                 Some(&mut vec![]),
             );
@@ -1222,21 +1223,27 @@ fn pick_method_with_unstable(&mut self, self_ty: Ty<'tcx>) -> Option<PickResult<
             }
         }
 
-        debug!("searching unstable candidates");
-        let res = self.consider_candidates(
-            self_ty,
-            self.inherent_candidates.iter().chain(&self.extension_candidates),
-            &mut possibly_unsatisfied_predicates,
-            None,
-        );
-        if res.is_none() {
-            self.unsatisfied_predicates.extend(possibly_unsatisfied_predicates);
+        for (kind, candidates) in
+            &[("inherent", &self.inherent_candidates), ("extension", &self.extension_candidates)]
+        {
+            debug!("searching unstable {kind} candidates");
+            let res = self.consider_candidates(
+                self_ty,
+                candidates,
+                &mut possibly_unsatisfied_predicates,
+                None,
+            );
+            if res.is_some() {
+                return res;
+            }
         }
-        res
+
+        self.unsatisfied_predicates.borrow_mut().extend(possibly_unsatisfied_predicates);
+        None
     }
 
     fn pick_method(
-        &mut self,
+        &self,
         self_ty: Ty<'tcx>,
         mut unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
     ) -> Option<PickResult<'tcx>> {
@@ -1254,7 +1261,7 @@ fn pick_method(
             debug!("searching {} candidates", kind);
             let res = self.consider_candidates(
                 self_ty,
-                candidates.iter(),
+                candidates,
                 &mut possibly_unsatisfied_predicates,
                 unstable_candidates.as_deref_mut(),
             );
@@ -1266,28 +1273,24 @@ fn pick_method(
         // `pick_method` may be called twice for the same self_ty if no stable methods
         // match. Only extend once.
         if unstable_candidates.is_some() {
-            self.unsatisfied_predicates.extend(possibly_unsatisfied_predicates);
+            self.unsatisfied_predicates.borrow_mut().extend(possibly_unsatisfied_predicates);
         }
         None
     }
 
-    fn consider_candidates<'b, ProbesIter>(
+    fn consider_candidates(
         &self,
         self_ty: Ty<'tcx>,
-        probes: ProbesIter,
+        candidates: &[Candidate<'tcx>],
         possibly_unsatisfied_predicates: &mut Vec<(
             ty::Predicate<'tcx>,
             Option<ty::Predicate<'tcx>>,
             Option<ObligationCause<'tcx>>,
         )>,
         mut unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
-    ) -> Option<PickResult<'tcx>>
-    where
-        ProbesIter: Iterator<Item = &'b Candidate<'tcx>> + Clone,
-        'tcx: 'b,
-    {
-        let mut applicable_candidates: Vec<_> = probes
-            .clone()
+    ) -> Option<PickResult<'tcx>> {
+        let mut applicable_candidates: Vec<_> = candidates
+            .iter()
             .map(|probe| {
                 (probe, self.consider_probe(self_ty, probe, possibly_unsatisfied_predicates))
             })
@@ -1305,11 +1308,11 @@ fn consider_candidates<'b, ProbesIter>(
         }
 
         if let Some(uc) = &mut unstable_candidates {
-            applicable_candidates.retain(|&(p, _)| {
+            applicable_candidates.retain(|&(candidate, _)| {
                 if let stability::EvalResult::Deny { feature, .. } =
-                    self.tcx.eval_stability(p.item.def_id, None, self.span, None)
+                    self.tcx.eval_stability(candidate.item.def_id, None, self.span, None)
                 {
-                    uc.push((p.clone(), feature));
+                    uc.push((candidate.clone(), feature));
                     return false;
                 }
                 true
@@ -1317,7 +1320,7 @@ fn consider_candidates<'b, ProbesIter>(
         }
 
         if applicable_candidates.len() > 1 {
-            let sources = probes.map(|p| self.candidate_source(p, self_ty)).collect();
+            let sources = candidates.iter().map(|p| self.candidate_source(p, self_ty)).collect();
             return Some(Err(MethodError::Ambiguity(sources)));
         }
 
@@ -1701,7 +1704,7 @@ fn probe_for_lev_candidate(&mut self) -> Result<Option<ty::AssocItem>, MethodErr
                 self.mode,
                 self.method_name,
                 self.return_type,
-                self.orig_steps_var_values.clone(),
+                &self.orig_steps_var_values,
                 steps,
                 self.scope_expr_id,
             );
@@ -1763,8 +1766,8 @@ fn has_applicable_self(&self, item: &ty::AssocItem) -> bool {
         // -- but this could be overcome.
     }
 
-    fn record_static_candidate(&mut self, source: CandidateSource) {
-        self.static_candidates.push(source);
+    fn record_static_candidate(&self, source: CandidateSource) {
+        self.static_candidates.borrow_mut().push(source);
     }
 
     #[instrument(level = "debug", skip(self))]
index db93cfab2c0dbd6a45508b9c35607b642cfe6c51..d40a66715a2ea63a0d7d2af6da0b1a41fc5c06ee 100644 (file)
@@ -25,7 +25,7 @@
 use rustc_middle::traits::util::supertraits;
 use rustc_middle::ty::fast_reject::DeepRejectCtxt;
 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
-use rustc_middle::ty::print::with_crate_prefix;
+use rustc_middle::ty::print::{with_crate_prefix, with_forced_trimmed_paths};
 use rustc_middle::ty::{self, DefIdTree, GenericArgKind, Ty, TyCtxt, TypeVisitable};
 use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef};
 use rustc_span::symbol::{kw, sym, Ident};
@@ -270,7 +270,7 @@ pub fn report_method_error(
                 let tcx = self.tcx;
 
                 let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
-                let ty_str = self.ty_to_string(rcvr_ty);
+                let ty_str = with_forced_trimmed_paths!(self.ty_to_string(rcvr_ty));
                 let is_method = mode == Mode::MethodCall;
                 let item_kind = if is_method {
                     "method"
@@ -557,15 +557,16 @@ pub fn report_method_error(
                                         .chain(projection_ty.substs.iter().skip(1)),
                                 );
 
-                                let quiet_projection_ty = ty::ProjectionTy {
-                                    substs: substs_with_infer_self,
-                                    item_def_id: projection_ty.item_def_id,
-                                };
+                                let quiet_projection_ty =
+                                    tcx.mk_alias_ty(projection_ty.def_id, substs_with_infer_self);
 
                                 let term = pred.skip_binder().term;
 
                                 let obligation = format!("{} = {}", projection_ty, term);
-                                let quiet = format!("{} = {}", quiet_projection_ty, term);
+                                let quiet = with_forced_trimmed_paths!(format!(
+                                    "{} = {}",
+                                    quiet_projection_ty, term
+                                ));
 
                                 bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
                                 Some((obligation, projection_ty.self_ty()))
@@ -575,7 +576,7 @@ pub fn report_method_error(
                                 let self_ty = p.self_ty();
                                 let path = p.print_only_trait_path();
                                 let obligation = format!("{}: {}", self_ty, path);
-                                let quiet = format!("_: {}", path);
+                                let quiet = with_forced_trimmed_paths!(format!("_: {}", path));
                                 bound_span_label(self_ty, &obligation, &quiet);
                                 Some((obligation, self_ty))
                             }
@@ -688,6 +689,16 @@ pub fn report_method_error(
                                 let entry = spanned_predicates.entry(spans);
                                 entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
                             }
+                            Some(Node::Item(hir::Item {
+                                kind: hir::ItemKind::Trait(rustc_ast::ast::IsAuto::Yes, ..),
+                                span: item_span,
+                                ..
+                            })) => {
+                                tcx.sess.delay_span_bug(
+                                        *item_span,
+                                        "auto trait is invoked with no method error, but no error reported?",
+                                    );
+                            }
                             Some(_) => unreachable!(),
                             None => (),
                         }
@@ -798,7 +809,8 @@ trait bound{s}",
                                 (None, None)
                             };
                         let primary_message = primary_message.unwrap_or_else(|| format!(
-                            "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
+                            "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, \
+                             but its trait bounds were not satisfied"
                         ));
                         err.set_primary_message(&primary_message);
                         if let Some(label) = label {
@@ -895,7 +907,14 @@ trait bound{s}",
                             }
                         }
                     } else {
-                        err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
+                        let ty_str = if ty_str.len() > 50 {
+                            String::new()
+                        } else {
+                            format!("on `{ty_str}` ")
+                        };
+                        err.span_label(span, format!(
+                            "{item_kind} cannot be called {ty_str}due to unsatisfied trait bounds"
+                        ));
                     }
                 };
 
@@ -1843,7 +1862,7 @@ pub(crate) fn note_unmet_impls_on_type(
         self.suggest_derive(err, &preds);
     }
 
-    fn suggest_derive(
+    pub fn suggest_derive(
         &self,
         err: &mut Diagnostic,
         unsatisfied_predicates: &[(
@@ -1853,7 +1872,7 @@ fn suggest_derive(
         )],
     ) {
         let mut derives = Vec::<(String, Span, Symbol)>::new();
-        let mut traits = Vec::<Span>::new();
+        let mut traits = Vec::new();
         for (pred, _, _) in unsatisfied_predicates {
             let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = pred.kind().skip_binder() else { continue };
             let adt = match trait_pred.self_ty().ty_adt_def() {
@@ -1892,10 +1911,10 @@ fn suggest_derive(
                     }
                     derives.push((self_name, self_span, diagnostic_name));
                 } else {
-                    traits.push(self.tcx.def_span(trait_pred.def_id()));
+                    traits.push(trait_pred.def_id());
                 }
             } else {
-                traits.push(self.tcx.def_span(trait_pred.def_id()));
+                traits.push(trait_pred.def_id());
             }
         }
         traits.sort();
@@ -1918,10 +1937,23 @@ fn suggest_derive(
 
         let len = traits.len();
         if len > 0 {
-            let span: MultiSpan = traits.into();
+            let span =
+                MultiSpan::from_spans(traits.iter().map(|&did| self.tcx.def_span(did)).collect());
+            let mut names = format!("`{}`", self.tcx.def_path_str(traits[0]));
+            for (i, &did) in traits.iter().enumerate().skip(1) {
+                if len > 2 {
+                    names.push_str(", ");
+                }
+                if i == len - 1 {
+                    names.push_str(" and ");
+                }
+                names.push('`');
+                names.push_str(&self.tcx.def_path_str(did));
+                names.push('`');
+            }
             err.span_note(
                 span,
-                &format!("the following trait{} must be implemented", pluralize!(len),),
+                &format!("the trait{} {} must be implemented", pluralize!(len), names),
             );
         }
 
@@ -1969,7 +2001,7 @@ fn check_for_deref_method(
                         | ty::Float(_)
                         | ty::Adt(_, _)
                         | ty::Str
-                        | ty::Projection(_)
+                        | ty::Alias(ty::Projection, _)
                         | ty::Param(_) => format!("{deref_ty}"),
                         // we need to test something like  <&[_]>::len or <(&[u32])>::len
                         // and Vec::function();
@@ -2269,7 +2301,7 @@ fn suggest_traits_to_import(
                             t.def_id() == info.def_id
                         }
                         ty::PredicateKind::Clause(ty::Clause::Projection(p)) => {
-                            p.projection_ty.item_def_id == info.def_id
+                            p.projection_ty.def_id == info.def_id
                         }
                         _ => false,
                     }
index decd317d9fc9b1e3a8943e9419bd0dedbb66e5eb..6810353f9e778bc992e43c6ee94111cdcca39aca 100644 (file)
@@ -386,7 +386,7 @@ fn check_pat_lit(
         // Byte string patterns behave the same way as array patterns
         // They can denote both statically and dynamically-sized byte arrays.
         let mut pat_ty = ty;
-        if let hir::ExprKind::Lit(Spanned { node: ast::LitKind::ByteStr(_), .. }) = lt.kind {
+        if let hir::ExprKind::Lit(Spanned { node: ast::LitKind::ByteStr(..), .. }) = lt.kind {
             let expected = self.structurally_resolved_type(span, expected);
             if let ty::Ref(_, inner_ty, _) = expected.kind()
                 && matches!(inner_ty.kind(), ty::Slice(_))
index 58ced6a1d3b4ffb90308cd91e64d1012b1c245df..bb956ddc780423876eca53ec2fc209aaed365aa8 100644 (file)
@@ -546,7 +546,7 @@ struct RecursionChecker {
             impl<'tcx> ty::TypeVisitor<'tcx> for RecursionChecker {
                 type BreakTy = ();
                 fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
-                    if let ty::Opaque(def_id, _) = *t.kind() {
+                    if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *t.kind() {
                         if def_id == self.def_id.to_def_id() {
                             return ControlFlow::Break(());
                         }
index 69e482ce854c063a2b300c7c7068531c9aca0ff1..b4bf9f4bcc767a3688f7a9b2965cf399c46d718e 100644 (file)
@@ -249,7 +249,7 @@ fn dump_graph(query: &DepGraphQuery) {
         // dump a .txt file with just the edges:
         let txt_path = format!("{}.txt", path);
         let mut file = BufWriter::new(File::create(&txt_path).unwrap());
-        for &(ref source, ref target) in &edges {
+        for (source, target) in &edges {
             write!(file, "{:?} -> {:?}\n", source, target).unwrap();
         }
     }
index a8acaf6597aaba3064b261dc005ac964ee241598..d1d328128bc15a145f7b60835cdfe62f7733beae 100644 (file)
@@ -30,8 +30,6 @@
 use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
-use std::iter::FromIterator;
-use std::vec::Vec;
 
 const LOADED_FROM_DISK: Symbol = sym::loaded_from_disk;
 const EXCEPT: Symbol = sym::except;
index 58d6e6d7efd69c0d757ff903b4356a586904f7d9..1fd2b9b0d7b7b5a58b4d291cf039575a08715e48 100644 (file)
 use rustc_errors::ErrorGuaranteed;
 use rustc_fs_util::{link_or_copy, LinkOrCopy};
 use rustc_session::{Session, StableCrateId};
+use rustc_span::Symbol;
 
 use std::fs as std_fs;
 use std::io::{self, ErrorKind};
-use std::mem;
 use std::path::{Path, PathBuf};
 use std::time::{Duration, SystemTime, UNIX_EPOCH};
 
@@ -202,7 +202,7 @@ pub fn in_incr_comp_dir(incr_comp_session_dir: &Path, file_name: &str) -> PathBu
 /// [`rustc_interface::queries::dep_graph`]: ../../rustc_interface/struct.Queries.html#structfield.dep_graph
 pub fn prepare_session_directory(
     sess: &Session,
-    crate_name: &str,
+    crate_name: Symbol,
     stable_crate_id: StableCrateId,
 ) -> Result<(), ErrorGuaranteed> {
     if sess.opts.incremental.is_none() {
@@ -304,7 +304,7 @@ pub fn prepare_session_directory(
             }
 
             delete_session_dir_lock_file(sess, &lock_file_path);
-            mem::drop(directory_lock);
+            drop(directory_lock);
         }
     }
 }
@@ -657,7 +657,7 @@ fn string_to_timestamp(s: &str) -> Result<SystemTime, ()> {
     Ok(UNIX_EPOCH + duration)
 }
 
-fn crate_path(sess: &Session, crate_name: &str, stable_crate_id: StableCrateId) -> PathBuf {
+fn crate_path(sess: &Session, crate_name: Symbol, stable_crate_id: StableCrateId) -> PathBuf {
     let incr_dir = sess.opts.incremental.as_ref().unwrap().clone();
 
     let stable_crate_id = base_n::encode(stable_crate_id.to_u64() as u128, INT_ENCODE_BASE);
@@ -863,7 +863,7 @@ pub fn garbage_collect_session_directories(sess: &Session) -> io::Result<()> {
 
                     // Let's make it explicit that the file lock is released at this point,
                     // or rather, that we held on to it until here
-                    mem::drop(lock);
+                    drop(lock);
                 }
                 Err(_) => {
                     debug!(
@@ -897,7 +897,7 @@ pub fn garbage_collect_session_directories(sess: &Session) -> io::Result<()> {
 
         // Let's make it explicit that the file lock is released at this point,
         // or rather, that we held on to it until here
-        mem::drop(lock);
+        drop(lock);
     }
 
     Ok(())
index 777112442f0104bcf7eabe5fbfb91854c5891a1a..686cb6dac496224f130d3f08a2f17d685eb30a32 100644 (file)
@@ -209,7 +209,7 @@ pub fn insert_range(&mut self, elems: impl RangeBounds<T>) {
             self.words[start_word_index] |= !(start_mask - 1);
             // And all trailing bits (i.e. from 0..=end) in the end word,
             // including the end.
-            self.words[end_word_index] |= end_mask | end_mask - 1;
+            self.words[end_word_index] |= end_mask | (end_mask - 1);
         } else {
             self.words[start_word_index] |= end_mask | (end_mask - start_mask);
         }
index 39aa27a23c1d2ceeb62825d123893566f57729be..c18a911b2fbcd4db06dfe417f9efbfee8579a4a2 100644 (file)
@@ -4,7 +4,6 @@
 use std::fmt;
 use std::fmt::Debug;
 use std::hash::Hash;
-use std::iter::FromIterator;
 use std::marker::PhantomData;
 use std::ops::{Index, IndexMut, RangeBounds};
 use std::slice;
index 74c4c65cc1729a981db0c42c44e4c57d355cf6cd..c4f11472d55482e979acfdb41894115a7a6a4923 100644 (file)
@@ -517,6 +517,6 @@ pub struct MismatchedStaticLifetime<'a> {
     pub expl: Option<note_and_explain::RegionExplanation<'a>>,
     #[subdiagnostic]
     pub does_not_outlive_static_from_impl: DoesNotOutliveStaticFromImpl,
-    #[subdiagnostic(eager)]
+    #[subdiagnostic]
     pub implicit_static_lifetimes: Vec<ImplicitStaticLifetimeSubdiag>,
 }
index 4429e4f43629a885543c06a5ac61426e96825760..e9186540a7b7c53869366303bba18d2791432f5f 100644 (file)
@@ -411,7 +411,7 @@ fn to_trace(
     }
 }
 
-impl<'tcx> ToTrace<'tcx> for ty::ProjectionTy<'tcx> {
+impl<'tcx> ToTrace<'tcx> for ty::AliasTy<'tcx> {
     fn to_trace(
         tcx: TyCtxt<'tcx>,
         cause: &ObligationCause<'tcx>,
@@ -419,8 +419,8 @@ fn to_trace(
         a: Self,
         b: Self,
     ) -> TypeTrace<'tcx> {
-        let a_ty = tcx.mk_projection(a.item_def_id, a.substs);
-        let b_ty = tcx.mk_projection(b.item_def_id, b.substs);
+        let a_ty = tcx.mk_projection(a.def_id, a.substs);
+        let b_ty = tcx.mk_projection(b.def_id, b.substs);
         TypeTrace {
             cause: cause.clone(),
             values: Terms(ExpectedFound::new(a_is_expected, a_ty.into(), b_ty.into())),
index 3dc0d60b1eb0fab07d2358d1cf9c2c959f5c0cbd..ec5221379d2c9314f93dedab1163b409569203e6 100644 (file)
@@ -453,10 +453,9 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
             | ty::Dynamic(..)
             | ty::Never
             | ty::Tuple(..)
-            | ty::Projection(..)
+            | ty::Alias(..)
             | ty::Foreign(..)
-            | ty::Param(..)
-            | ty::Opaque(..) => {
+            | ty::Param(..) => {
                 if t.flags().intersects(self.needs_canonical_flags) {
                     t.super_fold_with(self)
                 } else {
index cf895ed0d3e598ba23eb5effcb52345e75982045..9a1c49c1aa6af24feb4625f718fc2a29acbdc2aa 100644 (file)
@@ -675,7 +675,7 @@ fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
                 // relatable.
                 Ok(t)
             }
-            ty::Opaque(def_id, substs) => {
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
                 let s = self.relate(substs, substs)?;
                 Ok(if s == substs { t } else { self.infcx.tcx.mk_opaque(def_id, s) })
             }
index 8682f4d3b7aed970783395d50e8ca09a8b648d64..46e7813d99e562cd1cff9b39b0224eaa75048fb1 100644 (file)
@@ -100,11 +100,15 @@ fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
                 self.fields.instantiate(a, RelationDir::EqTo, b_id, self.a_is_expected)?;
             }
 
-            (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => {
+            (
+                &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
+                &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
+            ) if a_def_id == b_def_id => {
                 self.fields.infcx.super_combine_tys(self, a, b)?;
             }
-            (&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..))
-                if self.fields.define_opaque_types && did.is_local() =>
+            (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
+            | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
+                if self.fields.define_opaque_types && def_id.is_local() =>
             {
                 self.fields.obligations.extend(
                     infcx
@@ -178,6 +182,11 @@ fn binders<T>(
     where
         T: Relate<'tcx>,
     {
+        // A binder is equal to itself if it's structually equal to itself
+        if a == b {
+            return Ok(a);
+        }
+
         if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() {
             self.fields.higher_ranked_sub(a, b, self.a_is_expected)?;
             self.fields.higher_ranked_sub(b, a, self.a_is_expected)?;
index 3256ca1fb20fbaff5fd3effea13ae9db8d415082..397fa43175f732b3d87e566678388b0fbcd342d8 100644 (file)
 use crate::traits::error_reporting::report_object_safety_error;
 use crate::traits::{
     IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
-    StatementAsExpression,
 };
 
-use crate::errors::SuggAddLetForLetChains;
-use hir::intravisit::{walk_expr, walk_stmt};
 use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed, IntoDiagnosticArg};
 use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString, MultiSpan};
 use rustc_hir as hir;
-use rustc_hir::def::{CtorKind, DefKind};
+use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::intravisit::Visitor;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::Node;
 use rustc_middle::dep_graph::DepContext;
-use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::relate::{self, RelateResult, TypeRelation};
 use rustc_middle::ty::{
     self, error::TypeError, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
 use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span};
 use rustc_target::spec::abi;
 use std::ops::{ControlFlow, Deref};
+use std::path::PathBuf;
 use std::{cmp, fmt, iter};
 
 mod note;
+mod suggest;
 
 pub(crate) mod need_type_info;
 pub use need_type_info::TypeAnnotationNeeded;
@@ -342,11 +339,13 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>(
 impl<'tcx> InferCtxt<'tcx> {
     pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
         let (def_id, substs) = match *ty.kind() {
-            ty::Opaque(def_id, substs) => (def_id, substs),
-            ty::Projection(data)
-                if self.tcx.def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder =>
+            ty::Alias(_, ty::AliasTy { def_id, substs, .. })
+                if matches!(
+                    self.tcx.def_kind(def_id),
+                    DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder
+                ) =>
             {
-                (data.item_def_id, data.substs)
+                (def_id, substs)
             }
             _ => return None,
         };
@@ -360,7 +359,7 @@ pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
                     .kind()
                     .map_bound(|kind| match kind {
                         ty::PredicateKind::Clause(ty::Clause::Projection(projection_predicate))
-                            if projection_predicate.projection_ty.item_def_id == item_def_id =>
+                            if projection_predicate.projection_ty.def_id == item_def_id =>
                         {
                             projection_predicate.term.ty()
                         }
@@ -806,87 +805,6 @@ fn note_error_origin(
         }
     }
 
-    fn suggest_remove_semi_or_return_binding(
-        &self,
-        err: &mut Diagnostic,
-        first_id: Option<hir::HirId>,
-        first_ty: Ty<'tcx>,
-        first_span: Span,
-        second_id: Option<hir::HirId>,
-        second_ty: Ty<'tcx>,
-        second_span: Span,
-    ) {
-        let remove_semicolon = [
-            (first_id, self.resolve_vars_if_possible(second_ty)),
-            (second_id, self.resolve_vars_if_possible(first_ty)),
-        ]
-        .into_iter()
-        .find_map(|(id, ty)| {
-            let hir::Node::Block(blk) = self.tcx.hir().get(id?) else { return None };
-            self.could_remove_semicolon(blk, ty)
-        });
-        match remove_semicolon {
-            Some((sp, StatementAsExpression::NeedsBoxing)) => {
-                err.multipart_suggestion(
-                    "consider removing this semicolon and boxing the expressions",
-                    vec![
-                        (first_span.shrink_to_lo(), "Box::new(".to_string()),
-                        (first_span.shrink_to_hi(), ")".to_string()),
-                        (second_span.shrink_to_lo(), "Box::new(".to_string()),
-                        (second_span.shrink_to_hi(), ")".to_string()),
-                        (sp, String::new()),
-                    ],
-                    Applicability::MachineApplicable,
-                );
-            }
-            Some((sp, StatementAsExpression::CorrectType)) => {
-                err.span_suggestion_short(
-                    sp,
-                    "consider removing this semicolon",
-                    "",
-                    Applicability::MachineApplicable,
-                );
-            }
-            None => {
-                for (id, ty) in [(first_id, second_ty), (second_id, first_ty)] {
-                    if let Some(id) = id
-                        && let hir::Node::Block(blk) = self.tcx.hir().get(id)
-                        && self.consider_returning_binding(blk, ty, err)
-                    {
-                        break;
-                    }
-                }
-            }
-        }
-    }
-
-    fn suggest_boxing_for_return_impl_trait(
-        &self,
-        err: &mut Diagnostic,
-        return_sp: Span,
-        arm_spans: impl Iterator<Item = Span>,
-    ) {
-        err.multipart_suggestion(
-            "you could change the return type to be a boxed trait object",
-            vec![
-                (return_sp.with_hi(return_sp.lo() + BytePos(4)), "Box<dyn".to_string()),
-                (return_sp.shrink_to_hi(), ">".to_string()),
-            ],
-            Applicability::MaybeIncorrect,
-        );
-        let sugg = arm_spans
-            .flat_map(|sp| {
-                [(sp.shrink_to_lo(), "Box::new(".to_string()), (sp.shrink_to_hi(), ")".to_string())]
-                    .into_iter()
-            })
-            .collect::<Vec<_>>();
-        err.multipart_suggestion(
-            "if you change the return type to expect trait objects, box the returned expressions",
-            sugg,
-            Applicability::MaybeIncorrect,
-        );
-    }
-
     /// Given that `other_ty` is the same as a type argument for `name` in `sub`, populate `value`
     /// highlighting `name` and every type argument that isn't at `pos` (which is `other_ty`), and
     /// populate `other_value` with `other_ty`.
@@ -1352,10 +1270,7 @@ fn lifetime_display(lifetime: Region<'_>) -> String {
                             .map(|(mod_str, _)| mod_str.len() + separator_len)
                             .sum();
 
-                    debug!(
-                        "cmp: separator_len={}, split_idx={}, min_len={}",
-                        separator_len, split_idx, min_len
-                    );
+                    debug!(?separator_len, ?split_idx, ?min_len, "cmp");
 
                     if split_idx >= min_len {
                         // paths are identical, highlight everything
@@ -1366,7 +1281,7 @@ fn lifetime_display(lifetime: Region<'_>) -> String {
                     } else {
                         let (common, uniq1) = t1_str.split_at(split_idx);
                         let (_, uniq2) = t2_str.split_at(split_idx);
-                        debug!("cmp: common={}, uniq1={}, uniq2={}", common, uniq1, uniq2);
+                        debug!(?common, ?uniq1, ?uniq2, "cmp");
 
                         values.0.push_normal(common);
                         values.0.push_highlighted(uniq1);
@@ -1659,17 +1574,14 @@ enum Mismatch<'a> {
                     }
                     ValuePairs::Regions(_) => (false, Mismatch::Fixed("lifetime")),
                 };
-                let vals = match self.values_str(values) {
-                    Some((expected, found)) => Some((expected, found)),
-                    None => {
-                        // Derived error. Cancel the emitter.
-                        // NOTE(eddyb) this was `.cancel()`, but `diag`
-                        // is borrowed, so we can't fully defuse it.
-                        diag.downgrade_to_delayed_bug();
-                        return;
-                    }
+                let Some(vals) = self.values_str(values) else {
+                    // Derived error. Cancel the emitter.
+                    // NOTE(eddyb) this was `.cancel()`, but `diag`
+                    // is borrowed, so we can't fully defuse it.
+                    diag.downgrade_to_delayed_bug();
+                    return;
                 };
-                (vals, exp_found, is_simple_error, Some(values))
+                (Some(vals), exp_found, is_simple_error, Some(values))
             }
         };
 
@@ -1701,7 +1613,7 @@ enum Mismatch<'a> {
             label_or_note(span, &terr.to_string());
         }
 
-        if let Some((expected, found)) = expected_found {
+        if let Some((expected, found, exp_p, found_p)) = expected_found {
             let (expected_label, found_label, exp_found) = match exp_found {
                 Mismatch::Variable(ef) => (
                     ef.expected.prefix_string(self.tcx),
@@ -1818,32 +1730,41 @@ enum Similar<'tcx> {
                 }
                 TypeError::Sorts(values) => {
                     let extra = expected == found;
-                    let sort_string = |ty: Ty<'tcx>| match (extra, ty.kind()) {
-                        (true, ty::Opaque(def_id, _)) => {
-                            let sm = self.tcx.sess.source_map();
-                            let pos = sm.lookup_char_pos(self.tcx.def_span(*def_id).lo());
-                            format!(
-                                " (opaque type at <{}:{}:{}>)",
-                                sm.filename_for_diagnostics(&pos.file.name),
-                                pos.line,
-                                pos.col.to_usize() + 1,
-                            )
-                        }
-                        (true, ty::Projection(proj))
-                            if self.tcx.def_kind(proj.item_def_id)
-                                == DefKind::ImplTraitPlaceholder =>
-                        {
-                            let sm = self.tcx.sess.source_map();
-                            let pos = sm.lookup_char_pos(self.tcx.def_span(proj.item_def_id).lo());
-                            format!(
-                                " (trait associated opaque type at <{}:{}:{}>)",
-                                sm.filename_for_diagnostics(&pos.file.name),
-                                pos.line,
-                                pos.col.to_usize() + 1,
-                            )
+                    let sort_string = |ty: Ty<'tcx>, path: Option<PathBuf>| {
+                        let mut s = match (extra, ty.kind()) {
+                            (true, ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) => {
+                                let sm = self.tcx.sess.source_map();
+                                let pos = sm.lookup_char_pos(self.tcx.def_span(*def_id).lo());
+                                format!(
+                                    " (opaque type at <{}:{}:{}>)",
+                                    sm.filename_for_diagnostics(&pos.file.name),
+                                    pos.line,
+                                    pos.col.to_usize() + 1,
+                                )
+                            }
+                            (true, ty::Alias(ty::Projection, proj))
+                                if self.tcx.def_kind(proj.def_id)
+                                    == DefKind::ImplTraitPlaceholder =>
+                            {
+                                let sm = self.tcx.sess.source_map();
+                                let pos = sm.lookup_char_pos(self.tcx.def_span(proj.def_id).lo());
+                                format!(
+                                    " (trait associated opaque type at <{}:{}:{}>)",
+                                    sm.filename_for_diagnostics(&pos.file.name),
+                                    pos.line,
+                                    pos.col.to_usize() + 1,
+                                )
+                            }
+                            (true, _) => format!(" ({})", ty.sort_string(self.tcx)),
+                            (false, _) => "".to_string(),
+                        };
+                        if let Some(path) = path {
+                            s.push_str(&format!(
+                                "\nthe full type name has been written to '{}'",
+                                path.display(),
+                            ));
                         }
-                        (true, _) => format!(" ({})", ty.sort_string(self.tcx)),
-                        (false, _) => "".to_string(),
+                        s
                     };
                     if !(values.expected.is_simple_text() && values.found.is_simple_text())
                         || (exp_found.map_or(false, |ef| {
@@ -1865,8 +1786,8 @@ enum Similar<'tcx> {
                             expected,
                             &found_label,
                             found,
-                            &sort_string(values.expected),
-                            &sort_string(values.found),
+                            &sort_string(values.expected, exp_p),
+                            &sort_string(values.found, found_p),
                         );
                     }
                 }
@@ -1940,310 +1861,6 @@ enum Similar<'tcx> {
         debug!(?diag);
     }
 
-    fn suggest_tuple_pattern(
-        &self,
-        cause: &ObligationCause<'tcx>,
-        exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
-        diag: &mut Diagnostic,
-    ) {
-        // Heavily inspired by `FnCtxt::suggest_compatible_variants`, with
-        // some modifications due to that being in typeck and this being in infer.
-        if let ObligationCauseCode::Pattern { .. } = cause.code() {
-            if let ty::Adt(expected_adt, substs) = exp_found.expected.kind() {
-                let compatible_variants: Vec<_> = expected_adt
-                    .variants()
-                    .iter()
-                    .filter(|variant| {
-                        variant.fields.len() == 1 && variant.ctor_kind() == Some(CtorKind::Fn)
-                    })
-                    .filter_map(|variant| {
-                        let sole_field = &variant.fields[0];
-                        let sole_field_ty = sole_field.ty(self.tcx, substs);
-                        if self.same_type_modulo_infer(sole_field_ty, exp_found.found) {
-                            let variant_path =
-                                with_no_trimmed_paths!(self.tcx.def_path_str(variant.def_id));
-                            // FIXME #56861: DRYer prelude filtering
-                            if let Some(path) = variant_path.strip_prefix("std::prelude::") {
-                                if let Some((_, path)) = path.split_once("::") {
-                                    return Some(path.to_string());
-                                }
-                            }
-                            Some(variant_path)
-                        } else {
-                            None
-                        }
-                    })
-                    .collect();
-                match &compatible_variants[..] {
-                    [] => {}
-                    [variant] => {
-                        diag.multipart_suggestion_verbose(
-                            &format!("try wrapping the pattern in `{}`", variant),
-                            vec![
-                                (cause.span.shrink_to_lo(), format!("{}(", variant)),
-                                (cause.span.shrink_to_hi(), ")".to_string()),
-                            ],
-                            Applicability::MaybeIncorrect,
-                        );
-                    }
-                    _ => {
-                        // More than one matching variant.
-                        diag.multipart_suggestions(
-                            &format!(
-                                "try wrapping the pattern in a variant of `{}`",
-                                self.tcx.def_path_str(expected_adt.did())
-                            ),
-                            compatible_variants.into_iter().map(|variant| {
-                                vec![
-                                    (cause.span.shrink_to_lo(), format!("{}(", variant)),
-                                    (cause.span.shrink_to_hi(), ")".to_string()),
-                                ]
-                            }),
-                            Applicability::MaybeIncorrect,
-                        );
-                    }
-                }
-            }
-        }
-    }
-
-    /// A possible error is to forget to add `.await` when using futures:
-    ///
-    /// ```compile_fail,E0308
-    /// async fn make_u32() -> u32 {
-    ///     22
-    /// }
-    ///
-    /// fn take_u32(x: u32) {}
-    ///
-    /// async fn foo() {
-    ///     let x = make_u32();
-    ///     take_u32(x);
-    /// }
-    /// ```
-    ///
-    /// This routine checks if the found type `T` implements `Future<Output=U>` where `U` is the
-    /// expected type. If this is the case, and we are inside of an async body, it suggests adding
-    /// `.await` to the tail of the expression.
-    fn suggest_await_on_expect_found(
-        &self,
-        cause: &ObligationCause<'tcx>,
-        exp_span: Span,
-        exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
-        diag: &mut Diagnostic,
-    ) {
-        debug!(
-            "suggest_await_on_expect_found: exp_span={:?}, expected_ty={:?}, found_ty={:?}",
-            exp_span, exp_found.expected, exp_found.found,
-        );
-
-        if let ObligationCauseCode::CompareImplItemObligation { .. } = cause.code() {
-            return;
-        }
-
-        match (
-            self.get_impl_future_output_ty(exp_found.expected),
-            self.get_impl_future_output_ty(exp_found.found),
-        ) {
-            (Some(exp), Some(found)) if self.same_type_modulo_infer(exp, found) => match cause
-                .code()
-            {
-                ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => {
-                    let then_span = self.find_block_span_from_hir_id(*then_id);
-                    diag.multipart_suggestion(
-                        "consider `await`ing on both `Future`s",
-                        vec![
-                            (then_span.shrink_to_hi(), ".await".to_string()),
-                            (exp_span.shrink_to_hi(), ".await".to_string()),
-                        ],
-                        Applicability::MaybeIncorrect,
-                    );
-                }
-                ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
-                    prior_arms,
-                    ..
-                }) => {
-                    if let [.., arm_span] = &prior_arms[..] {
-                        diag.multipart_suggestion(
-                            "consider `await`ing on both `Future`s",
-                            vec![
-                                (arm_span.shrink_to_hi(), ".await".to_string()),
-                                (exp_span.shrink_to_hi(), ".await".to_string()),
-                            ],
-                            Applicability::MaybeIncorrect,
-                        );
-                    } else {
-                        diag.help("consider `await`ing on both `Future`s");
-                    }
-                }
-                _ => {
-                    diag.help("consider `await`ing on both `Future`s");
-                }
-            },
-            (_, Some(ty)) if self.same_type_modulo_infer(exp_found.expected, ty) => {
-                diag.span_suggestion_verbose(
-                    exp_span.shrink_to_hi(),
-                    "consider `await`ing on the `Future`",
-                    ".await",
-                    Applicability::MaybeIncorrect,
-                );
-            }
-            (Some(ty), _) if self.same_type_modulo_infer(ty, exp_found.found) => match cause.code()
-            {
-                ObligationCauseCode::Pattern { span: Some(then_span), .. } => {
-                    diag.span_suggestion_verbose(
-                        then_span.shrink_to_hi(),
-                        "consider `await`ing on the `Future`",
-                        ".await",
-                        Applicability::MaybeIncorrect,
-                    );
-                }
-                ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => {
-                    let then_span = self.find_block_span_from_hir_id(*then_id);
-                    diag.span_suggestion_verbose(
-                        then_span.shrink_to_hi(),
-                        "consider `await`ing on the `Future`",
-                        ".await",
-                        Applicability::MaybeIncorrect,
-                    );
-                }
-                ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
-                    ref prior_arms,
-                    ..
-                }) => {
-                    diag.multipart_suggestion_verbose(
-                        "consider `await`ing on the `Future`",
-                        prior_arms
-                            .iter()
-                            .map(|arm| (arm.shrink_to_hi(), ".await".to_string()))
-                            .collect(),
-                        Applicability::MaybeIncorrect,
-                    );
-                }
-                _ => {}
-            },
-            _ => {}
-        }
-    }
-
-    fn suggest_accessing_field_where_appropriate(
-        &self,
-        cause: &ObligationCause<'tcx>,
-        exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
-        diag: &mut Diagnostic,
-    ) {
-        debug!(
-            "suggest_accessing_field_where_appropriate(cause={:?}, exp_found={:?})",
-            cause, exp_found
-        );
-        if let ty::Adt(expected_def, expected_substs) = exp_found.expected.kind() {
-            if expected_def.is_enum() {
-                return;
-            }
-
-            if let Some((name, ty)) = expected_def
-                .non_enum_variant()
-                .fields
-                .iter()
-                .filter(|field| field.vis.is_accessible_from(field.did, self.tcx))
-                .map(|field| (field.name, field.ty(self.tcx, expected_substs)))
-                .find(|(_, ty)| self.same_type_modulo_infer(*ty, exp_found.found))
-            {
-                if let ObligationCauseCode::Pattern { span: Some(span), .. } = *cause.code() {
-                    if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
-                        let suggestion = if expected_def.is_struct() {
-                            format!("{}.{}", snippet, name)
-                        } else if expected_def.is_union() {
-                            format!("unsafe {{ {}.{} }}", snippet, name)
-                        } else {
-                            return;
-                        };
-                        diag.span_suggestion(
-                            span,
-                            &format!(
-                                "you might have meant to use field `{}` whose type is `{}`",
-                                name, ty
-                            ),
-                            suggestion,
-                            Applicability::MaybeIncorrect,
-                        );
-                    }
-                }
-            }
-        }
-    }
-
-    /// When encountering a case where `.as_ref()` on a `Result` or `Option` would be appropriate,
-    /// suggests it.
-    fn suggest_as_ref_where_appropriate(
-        &self,
-        span: Span,
-        exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
-        diag: &mut Diagnostic,
-    ) {
-        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
-            && let Some(msg) = self.should_suggest_as_ref(exp_found.expected, exp_found.found)
-        {
-            diag.span_suggestion(
-                span,
-                msg,
-                // HACK: fix issue# 100605, suggesting convert from &Option<T> to Option<&T>, remove the extra `&`
-                format!("{}.as_ref()", snippet.trim_start_matches('&')),
-                Applicability::MachineApplicable,
-            );
-        }
-    }
-
-    pub fn should_suggest_as_ref(&self, expected: Ty<'tcx>, found: Ty<'tcx>) -> Option<&str> {
-        if let (ty::Adt(exp_def, exp_substs), ty::Ref(_, found_ty, _)) =
-            (expected.kind(), found.kind())
-        {
-            if let ty::Adt(found_def, found_substs) = *found_ty.kind() {
-                if exp_def == &found_def {
-                    let have_as_ref = &[
-                        (
-                            sym::Option,
-                            "you can convert from `&Option<T>` to `Option<&T>` using \
-                        `.as_ref()`",
-                        ),
-                        (
-                            sym::Result,
-                            "you can convert from `&Result<T, E>` to \
-                        `Result<&T, &E>` using `.as_ref()`",
-                        ),
-                    ];
-                    if let Some(msg) = have_as_ref.iter().find_map(|(name, msg)| {
-                        self.tcx.is_diagnostic_item(*name, exp_def.did()).then_some(msg)
-                    }) {
-                        let mut show_suggestion = true;
-                        for (exp_ty, found_ty) in
-                            iter::zip(exp_substs.types(), found_substs.types())
-                        {
-                            match *exp_ty.kind() {
-                                ty::Ref(_, exp_ty, _) => {
-                                    match (exp_ty.kind(), found_ty.kind()) {
-                                        (_, ty::Param(_))
-                                        | (_, ty::Infer(_))
-                                        | (ty::Param(_), _)
-                                        | (ty::Infer(_), _) => {}
-                                        _ if self.same_type_modulo_infer(exp_ty, found_ty) => {}
-                                        _ => show_suggestion = false,
-                                    };
-                                }
-                                ty::Param(_) | ty::Infer(_) => {}
-                                _ => show_suggestion = false,
-                            }
-                        }
-                        if show_suggestion {
-                            return Some(*msg);
-                        }
-                    }
-                }
-            }
-        }
-        None
-    }
-
     pub fn report_and_explain_type_error(
         &self,
         trace: TypeTrace<'tcx>,
@@ -2339,7 +1956,7 @@ fn escape_literal(s: &str) -> String {
                 let code = trace.cause.code();
                 if let &MatchExpressionArm(box MatchExpressionArmCause { source, .. }) = code
                     && let hir::MatchSource::TryDesugar = source
-                    && let Some((expected_ty, found_ty)) = self.values_str(trace.values)
+                    && let Some((expected_ty, found_ty, _, _)) = self.values_str(trace.values)
                 {
                     err.note(&format!(
                         "`?` operator cannot convert from `{}` to `{}`",
@@ -2357,67 +1974,6 @@ fn escape_literal(s: &str) -> String {
         diag
     }
 
-    /// Try to find code with pattern `if Some(..) = expr`
-    /// use a `visitor` to mark the `if` which its span contains given error span,
-    /// and then try to find a assignment in the `cond` part, which span is equal with error span
-    fn suggest_let_for_letchains(
-        &self,
-        err: &mut Diagnostic,
-        cause: &ObligationCause<'_>,
-        span: Span,
-    ) {
-        let hir = self.tcx.hir();
-        let fn_hir_id = hir.get_parent_node(cause.body_id);
-        if let Some(node) = self.tcx.hir().find(fn_hir_id) &&
-            let hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Fn(_sig, _, body_id), ..
-                }) = node {
-        let body = hir.body(*body_id);
-
-        /// Find the if expression with given span
-        struct IfVisitor {
-            pub result: bool,
-            pub found_if: bool,
-            pub err_span: Span,
-        }
-
-        impl<'v> Visitor<'v> for IfVisitor {
-            fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
-                if self.result { return; }
-                match ex.kind {
-                    hir::ExprKind::If(cond, _, _) => {
-                        self.found_if = true;
-                        walk_expr(self, cond);
-                        self.found_if = false;
-                    }
-                    _ => walk_expr(self, ex),
-                }
-            }
-
-            fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) {
-                if let hir::StmtKind::Local(hir::Local {
-                        span, pat: hir::Pat{..}, ty: None, init: Some(_), ..
-                    }) = &ex.kind
-                    && self.found_if
-                    && span.eq(&self.err_span) {
-                        self.result = true;
-                }
-                walk_stmt(self, ex);
-            }
-
-            fn visit_body(&mut self, body: &'v hir::Body<'v>) {
-                hir::intravisit::walk_body(self, body);
-            }
-        }
-
-        let mut visitor = IfVisitor { err_span: span, found_if: false, result: false };
-        visitor.visit_body(&body);
-        if visitor.result {
-                err.subdiagnostic(SuggAddLetForLetChains{span: span.shrink_to_lo()});
-            }
-        }
-    }
-
     fn emit_tuple_wrap_err(
         &self,
         err: &mut Diagnostic,
@@ -2455,7 +2011,8 @@ fn emit_tuple_wrap_err(
     fn values_str(
         &self,
         values: ValuePairs<'tcx>,
-    ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
+    ) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option<PathBuf>, Option<PathBuf>)>
+    {
         match values {
             infer::Regions(exp_found) => self.expected_found_str(exp_found),
             infer::Terms(exp_found) => self.expected_found_str_term(exp_found),
@@ -2465,7 +2022,7 @@ fn values_str(
                     found: exp_found.found.print_only_trait_path(),
                 };
                 match self.expected_found_str(pretty_exp_found) {
-                    Some((expected, found)) if expected == found => {
+                    Some((expected, found, _, _)) if expected == found => {
                         self.expected_found_str(exp_found)
                     }
                     ret => ret,
@@ -2477,7 +2034,7 @@ fn values_str(
                     found: exp_found.found.print_only_trait_path(),
                 };
                 match self.expected_found_str(pretty_exp_found) {
-                    Some((expected, found)) if expected == found => {
+                    Some((expected, found, _, _)) if expected == found => {
                         self.expected_found_str(exp_found)
                     }
                     ret => ret,
@@ -2489,17 +2046,41 @@ fn values_str(
     fn expected_found_str_term(
         &self,
         exp_found: ty::error::ExpectedFound<ty::Term<'tcx>>,
-    ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
+    ) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option<PathBuf>, Option<PathBuf>)>
+    {
         let exp_found = self.resolve_vars_if_possible(exp_found);
         if exp_found.references_error() {
             return None;
         }
 
         Some(match (exp_found.expected.unpack(), exp_found.found.unpack()) {
-            (ty::TermKind::Ty(expected), ty::TermKind::Ty(found)) => self.cmp(expected, found),
+            (ty::TermKind::Ty(expected), ty::TermKind::Ty(found)) => {
+                let (mut exp, mut fnd) = self.cmp(expected, found);
+                // Use the terminal width as the basis to determine when to compress the printed
+                // out type, but give ourselves some leeway to avoid ending up creating a file for
+                // a type that is somewhat shorter than the path we'd write to.
+                let len = self.tcx.sess().diagnostic_width() + 40;
+                let exp_s = exp.content();
+                let fnd_s = fnd.content();
+                let mut exp_p = None;
+                let mut fnd_p = None;
+                if exp_s.len() > len {
+                    let (exp_s, exp_path) = self.tcx.short_ty_string(expected);
+                    exp = DiagnosticStyledString::highlighted(exp_s);
+                    exp_p = exp_path;
+                }
+                if fnd_s.len() > len {
+                    let (fnd_s, fnd_path) = self.tcx.short_ty_string(found);
+                    fnd = DiagnosticStyledString::highlighted(fnd_s);
+                    fnd_p = fnd_path;
+                }
+                (exp, fnd, exp_p, fnd_p)
+            }
             _ => (
                 DiagnosticStyledString::highlighted(exp_found.expected.to_string()),
                 DiagnosticStyledString::highlighted(exp_found.found.to_string()),
+                None,
+                None,
             ),
         })
     }
@@ -2508,7 +2089,8 @@ fn expected_found_str_term(
     fn expected_found_str<T: fmt::Display + TypeFoldable<'tcx>>(
         &self,
         exp_found: ty::error::ExpectedFound<T>,
-    ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
+    ) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option<PathBuf>, Option<PathBuf>)>
+    {
         let exp_found = self.resolve_vars_if_possible(exp_found);
         if exp_found.references_error() {
             return None;
@@ -2517,6 +2099,8 @@ fn expected_found_str<T: fmt::Display + TypeFoldable<'tcx>>(
         Some((
             DiagnosticStyledString::highlighted(exp_found.expected.to_string()),
             DiagnosticStyledString::highlighted(exp_found.found.to_string()),
+            None,
+            None,
         ))
     }
 
@@ -2801,7 +2385,7 @@ enum SubOrigin<'hir> {
                         // fn get_later<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
                         // suggest:
                         // fn get_later<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
-                        ty::Closure(_, _substs) | ty::Opaque(_, _substs) if return_impl_trait => {
+                        ty::Closure(..) | ty::Alias(ty::Opaque, ..) if return_impl_trait => {
                             new_binding_suggestion(&mut err, type_param_span);
                         }
                         _ => {
@@ -2850,36 +2434,29 @@ fn report_sub_sup_conflict(
         debug!("report_sub_sup_conflict: sup_region={:?}", sup_region);
         debug!("report_sub_sup_conflict: sup_origin={:?}", sup_origin);
 
-        if let (&infer::Subtype(ref sup_trace), &infer::Subtype(ref sub_trace)) =
-            (&sup_origin, &sub_origin)
+        if let infer::Subtype(ref sup_trace) = sup_origin
+            && let infer::Subtype(ref sub_trace) = sub_origin
+            && let Some((sup_expected, sup_found, _, _)) = self.values_str(sup_trace.values)
+            && let Some((sub_expected, sub_found, _, _)) = self.values_str(sub_trace.values)
+            && sub_expected == sup_expected
+            && sub_found == sup_found
         {
-            debug!("report_sub_sup_conflict: sup_trace={:?}", sup_trace);
-            debug!("report_sub_sup_conflict: sub_trace={:?}", sub_trace);
-            debug!("report_sub_sup_conflict: sup_trace.values={:?}", sup_trace.values);
-            debug!("report_sub_sup_conflict: sub_trace.values={:?}", sub_trace.values);
-
-            if let (Some((sup_expected, sup_found)), Some((sub_expected, sub_found))) =
-                (self.values_str(sup_trace.values), self.values_str(sub_trace.values))
-            {
-                if sub_expected == sup_expected && sub_found == sup_found {
-                    note_and_explain_region(
-                        self.tcx,
-                        &mut err,
-                        "...but the lifetime must also be valid for ",
-                        sub_region,
-                        "...",
-                        None,
-                    );
-                    err.span_note(
-                        sup_trace.cause.span,
-                        &format!("...so that the {}", sup_trace.cause.as_requirement_str()),
-                    );
+            note_and_explain_region(
+                self.tcx,
+                &mut err,
+                "...but the lifetime must also be valid for ",
+                sub_region,
+                "...",
+                None,
+            );
+            err.span_note(
+                sup_trace.cause.span,
+                &format!("...so that the {}", sup_trace.cause.as_requirement_str()),
+            );
 
-                    err.note_expected_found(&"", sup_expected, &"", sup_found);
-                    err.emit();
-                    return;
-                }
-            }
+            err.note_expected_found(&"", sup_expected, &"", sup_found);
+            err.emit();
+            return;
         }
 
         self.note_region_origin(&mut err, &sup_origin);
@@ -3190,7 +2767,7 @@ fn descr(&self) -> &'static str {
     pub fn from_ty(tcx: TyCtxt<'_>, ty: Ty<'_>) -> Option<(Self, DefId)> {
         match *ty.kind() {
             ty::Closure(def_id, _) => Some((Self::Closure, def_id)),
-            ty::Opaque(def_id, _) => Some((Self::Opaque, def_id)),
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => Some((Self::Opaque, def_id)),
             ty::Generator(def_id, ..) => {
                 Some((Self::Generator(tcx.generator_kind(def_id).unwrap()), def_id))
             }
@@ -3228,211 +2805,3 @@ pub fn find_block_span_from_hir_id(&self, hir_id: hir::HirId) -> Span {
         }
     }
 }
-
-impl<'tcx> TypeErrCtxt<'_, 'tcx> {
-    /// Be helpful when the user wrote `{... expr; }` and taking the `;` off
-    /// is enough to fix the error.
-    pub fn could_remove_semicolon(
-        &self,
-        blk: &'tcx hir::Block<'tcx>,
-        expected_ty: Ty<'tcx>,
-    ) -> Option<(Span, StatementAsExpression)> {
-        let blk = blk.innermost_block();
-        // Do not suggest if we have a tail expr.
-        if blk.expr.is_some() {
-            return None;
-        }
-        let last_stmt = blk.stmts.last()?;
-        let hir::StmtKind::Semi(ref last_expr) = last_stmt.kind else {
-            return None;
-        };
-        let last_expr_ty = self.typeck_results.as_ref()?.expr_ty_opt(*last_expr)?;
-        let needs_box = match (last_expr_ty.kind(), expected_ty.kind()) {
-            _ if last_expr_ty.references_error() => return None,
-            _ if self.same_type_modulo_infer(last_expr_ty, expected_ty) => {
-                StatementAsExpression::CorrectType
-            }
-            (ty::Opaque(last_def_id, _), ty::Opaque(exp_def_id, _))
-                if last_def_id == exp_def_id =>
-            {
-                StatementAsExpression::CorrectType
-            }
-            (ty::Opaque(last_def_id, last_bounds), ty::Opaque(exp_def_id, exp_bounds)) => {
-                debug!(
-                    "both opaque, likely future {:?} {:?} {:?} {:?}",
-                    last_def_id, last_bounds, exp_def_id, exp_bounds
-                );
-
-                let last_local_id = last_def_id.as_local()?;
-                let exp_local_id = exp_def_id.as_local()?;
-
-                match (
-                    &self.tcx.hir().expect_item(last_local_id).kind,
-                    &self.tcx.hir().expect_item(exp_local_id).kind,
-                ) {
-                    (
-                        hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: last_bounds, .. }),
-                        hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: exp_bounds, .. }),
-                    ) if iter::zip(*last_bounds, *exp_bounds).all(|(left, right)| {
-                        match (left, right) {
-                            (
-                                hir::GenericBound::Trait(tl, ml),
-                                hir::GenericBound::Trait(tr, mr),
-                            ) if tl.trait_ref.trait_def_id() == tr.trait_ref.trait_def_id()
-                                && ml == mr =>
-                            {
-                                true
-                            }
-                            (
-                                hir::GenericBound::LangItemTrait(langl, _, _, argsl),
-                                hir::GenericBound::LangItemTrait(langr, _, _, argsr),
-                            ) if langl == langr => {
-                                // FIXME: consider the bounds!
-                                debug!("{:?} {:?}", argsl, argsr);
-                                true
-                            }
-                            _ => false,
-                        }
-                    }) =>
-                    {
-                        StatementAsExpression::NeedsBoxing
-                    }
-                    _ => StatementAsExpression::CorrectType,
-                }
-            }
-            _ => return None,
-        };
-        let span = if last_stmt.span.from_expansion() {
-            let mac_call = rustc_span::source_map::original_sp(last_stmt.span, blk.span);
-            self.tcx.sess.source_map().mac_call_stmt_semi_span(mac_call)?
-        } else {
-            last_stmt.span.with_lo(last_stmt.span.hi() - BytePos(1))
-        };
-        Some((span, needs_box))
-    }
-
-    /// Suggest returning a local binding with a compatible type if the block
-    /// has no return expression.
-    pub fn consider_returning_binding(
-        &self,
-        blk: &'tcx hir::Block<'tcx>,
-        expected_ty: Ty<'tcx>,
-        err: &mut Diagnostic,
-    ) -> bool {
-        let blk = blk.innermost_block();
-        // Do not suggest if we have a tail expr.
-        if blk.expr.is_some() {
-            return false;
-        }
-        let mut shadowed = FxIndexSet::default();
-        let mut candidate_idents = vec![];
-        let mut find_compatible_candidates = |pat: &hir::Pat<'_>| {
-            if let hir::PatKind::Binding(_, hir_id, ident, _) = &pat.kind
-                && let Some(pat_ty) = self
-                    .typeck_results
-                    .as_ref()
-                    .and_then(|typeck_results| typeck_results.node_type_opt(*hir_id))
-            {
-                let pat_ty = self.resolve_vars_if_possible(pat_ty);
-                if self.same_type_modulo_infer(pat_ty, expected_ty)
-                    && !(pat_ty, expected_ty).references_error()
-                    && shadowed.insert(ident.name)
-                {
-                    candidate_idents.push((*ident, pat_ty));
-                }
-            }
-            true
-        };
-
-        let hir = self.tcx.hir();
-        for stmt in blk.stmts.iter().rev() {
-            let hir::StmtKind::Local(local) = &stmt.kind else { continue; };
-            local.pat.walk(&mut find_compatible_candidates);
-        }
-        match hir.find(hir.get_parent_node(blk.hir_id)) {
-            Some(hir::Node::Expr(hir::Expr { hir_id, .. })) => {
-                match hir.find(hir.get_parent_node(*hir_id)) {
-                    Some(hir::Node::Arm(hir::Arm { pat, .. })) => {
-                        pat.walk(&mut find_compatible_candidates);
-                    }
-                    Some(
-                        hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body), .. })
-                        | hir::Node::ImplItem(hir::ImplItem {
-                            kind: hir::ImplItemKind::Fn(_, body),
-                            ..
-                        })
-                        | hir::Node::TraitItem(hir::TraitItem {
-                            kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body)),
-                            ..
-                        })
-                        | hir::Node::Expr(hir::Expr {
-                            kind: hir::ExprKind::Closure(hir::Closure { body, .. }),
-                            ..
-                        }),
-                    ) => {
-                        for param in hir.body(*body).params {
-                            param.pat.walk(&mut find_compatible_candidates);
-                        }
-                    }
-                    Some(hir::Node::Expr(hir::Expr {
-                        kind:
-                            hir::ExprKind::If(
-                                hir::Expr { kind: hir::ExprKind::Let(let_), .. },
-                                then_block,
-                                _,
-                            ),
-                        ..
-                    })) if then_block.hir_id == *hir_id => {
-                        let_.pat.walk(&mut find_compatible_candidates);
-                    }
-                    _ => {}
-                }
-            }
-            _ => {}
-        }
-
-        match &candidate_idents[..] {
-            [(ident, _ty)] => {
-                let sm = self.tcx.sess.source_map();
-                if let Some(stmt) = blk.stmts.last() {
-                    let stmt_span = sm.stmt_span(stmt.span, blk.span);
-                    let sugg = if sm.is_multiline(blk.span)
-                        && let Some(spacing) = sm.indentation_before(stmt_span)
-                    {
-                        format!("\n{spacing}{ident}")
-                    } else {
-                        format!(" {ident}")
-                    };
-                    err.span_suggestion_verbose(
-                        stmt_span.shrink_to_hi(),
-                        format!("consider returning the local binding `{ident}`"),
-                        sugg,
-                        Applicability::MaybeIncorrect,
-                    );
-                } else {
-                    let sugg = if sm.is_multiline(blk.span)
-                        && let Some(spacing) = sm.indentation_before(blk.span.shrink_to_lo())
-                    {
-                        format!("\n{spacing}    {ident}\n{spacing}")
-                    } else {
-                        format!(" {ident} ")
-                    };
-                    let left_span = sm.span_through_char(blk.span, '{').shrink_to_hi();
-                    err.span_suggestion_verbose(
-                        sm.span_extend_while(left_span, |c| c.is_whitespace()).unwrap_or(left_span),
-                        format!("consider returning the local binding `{ident}`"),
-                        sugg,
-                        Applicability::MaybeIncorrect,
-                    );
-                }
-                true
-            }
-            values if (1..3).contains(&values.len()) => {
-                let spans = values.iter().map(|(ident, _)| ident.span).collect::<Vec<_>>();
-                err.span_note(spans, "consider returning one of these bindings");
-                true
-            }
-            _ => false,
-        }
-    }
-}
index 8ff1639a3a24b489e1f8ffc1d039e77a298fda4f..a4c36b4c9cd59db580517b60f8d887ca2bcd40eb 100644 (file)
@@ -20,7 +20,7 @@
 use rustc_middle::ty::{self, DefIdTree, InferConst};
 use rustc_middle::ty::{GenericArg, GenericArgKind, SubstsRef};
 use rustc_middle::ty::{IsSuggestable, Ty, TyCtxt, TypeckResults};
-use rustc_span::symbol::{kw, Ident};
+use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{BytePos, Span};
 use std::borrow::Cow;
 use std::iter;
@@ -79,7 +79,7 @@ fn can_add_more_info(&self) -> bool {
 
     fn where_x_is_kind(&self, in_type: Ty<'_>) -> &'static str {
         if in_type.is_ty_infer() {
-            "empty"
+            ""
         } else if self.name == "_" {
             // FIXME: Consider specializing this message if there is a single `_`
             // in the type.
@@ -183,13 +183,24 @@ fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinte
     printer
 }
 
-fn ty_to_string<'tcx>(infcx: &InferCtxt<'tcx>, ty: Ty<'tcx>) -> String {
+fn ty_to_string<'tcx>(
+    infcx: &InferCtxt<'tcx>,
+    ty: Ty<'tcx>,
+    called_method_def_id: Option<DefId>,
+) -> String {
     let printer = fmt_printer(infcx, Namespace::TypeNS);
     let ty = infcx.resolve_vars_if_possible(ty);
-    match ty.kind() {
+    match (ty.kind(), called_method_def_id) {
         // We don't want the regular output for `fn`s because it includes its path in
         // invalid pseudo-syntax, we want the `fn`-pointer output instead.
-        ty::FnDef(..) => ty.fn_sig(infcx.tcx).print(printer).unwrap().into_buffer(),
+        (ty::FnDef(..), _) => ty.fn_sig(infcx.tcx).print(printer).unwrap().into_buffer(),
+        (_, Some(def_id))
+            if ty.is_ty_infer()
+                && infcx.tcx.get_diagnostic_item(sym::iterator_collect_fn) == Some(def_id) =>
+        {
+            "Vec<_>".to_string()
+        }
+        _ if ty.is_ty_infer() => "/* Type */".to_string(),
         // FIXME: The same thing for closures, but this only works when the closure
         // does not capture anything.
         //
@@ -213,7 +224,7 @@ fn closure_as_fn_str<'tcx>(infcx: &InferCtxt<'tcx>, ty: Ty<'tcx>) -> String {
         .map(|args| {
             args.tuple_fields()
                 .iter()
-                .map(|arg| ty_to_string(infcx, arg))
+                .map(|arg| ty_to_string(infcx, arg, None))
                 .collect::<Vec<_>>()
                 .join(", ")
         })
@@ -221,7 +232,7 @@ fn closure_as_fn_str<'tcx>(infcx: &InferCtxt<'tcx>, ty: Ty<'tcx>) -> String {
     let ret = if fn_sig.output().skip_binder().is_unit() {
         String::new()
     } else {
-        format!(" -> {}", ty_to_string(infcx, fn_sig.output().skip_binder()))
+        format!(" -> {}", ty_to_string(infcx, fn_sig.output().skip_binder(), None))
     };
     format!("fn({}){}", args, ret)
 }
@@ -368,6 +379,7 @@ fn bad_inference_failure_err(
 }
 
 impl<'tcx> TypeErrCtxt<'_, 'tcx> {
+    #[instrument(level = "debug", skip(self, error_code))]
     pub fn emit_inference_failure_err(
         &self,
         body_id: Option<hir::BodyId>,
@@ -406,7 +418,7 @@ pub fn emit_inference_failure_err(
         let mut infer_subdiags = Vec::new();
         let mut multi_suggestions = Vec::new();
         match kind {
-            InferSourceKind::LetBinding { insert_span, pattern_name, ty } => {
+            InferSourceKind::LetBinding { insert_span, pattern_name, ty, def_id } => {
                 infer_subdiags.push(SourceKindSubdiag::LetLike {
                     span: insert_span,
                     name: pattern_name.map(|name| name.to_string()).unwrap_or_else(String::new),
@@ -415,7 +427,7 @@ pub fn emit_inference_failure_err(
                     prefix: arg_data.kind.try_get_prefix().unwrap_or_default(),
                     arg_name: arg_data.name,
                     kind: if pattern_name.is_some() { "with_pattern" } else { "other" },
-                    type_name: ty_to_string(self, ty),
+                    type_name: ty_to_string(self, ty, def_id),
                 });
             }
             InferSourceKind::ClosureArg { insert_span, ty } => {
@@ -427,7 +439,7 @@ pub fn emit_inference_failure_err(
                     prefix: arg_data.kind.try_get_prefix().unwrap_or_default(),
                     arg_name: arg_data.name,
                     kind: "closure",
-                    type_name: ty_to_string(self, ty),
+                    type_name: ty_to_string(self, ty, None),
                 });
             }
             InferSourceKind::GenericArg {
@@ -456,33 +468,39 @@ pub fn emit_inference_failure_err(
                     parent_name,
                 });
 
-                let args = fmt_printer(self, Namespace::TypeNS)
-                    .comma_sep(generic_args.iter().copied().map(|arg| {
-                        if arg.is_suggestable(self.tcx, true) {
-                            return arg;
-                        }
+                let args = if self.infcx.tcx.get_diagnostic_item(sym::iterator_collect_fn)
+                    == Some(generics_def_id)
+                {
+                    "Vec<_>".to_string()
+                } else {
+                    fmt_printer(self, Namespace::TypeNS)
+                        .comma_sep(generic_args.iter().copied().map(|arg| {
+                            if arg.is_suggestable(self.tcx, true) {
+                                return arg;
+                            }
 
-                        match arg.unpack() {
-                            GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
-                            GenericArgKind::Type(_) => self
-                                .next_ty_var(TypeVariableOrigin {
-                                    span: rustc_span::DUMMY_SP,
-                                    kind: TypeVariableOriginKind::MiscVariable,
-                                })
-                                .into(),
-                            GenericArgKind::Const(arg) => self
-                                .next_const_var(
-                                    arg.ty(),
-                                    ConstVariableOrigin {
+                            match arg.unpack() {
+                                GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
+                                GenericArgKind::Type(_) => self
+                                    .next_ty_var(TypeVariableOrigin {
                                         span: rustc_span::DUMMY_SP,
-                                        kind: ConstVariableOriginKind::MiscVariable,
-                                    },
-                                )
-                                .into(),
-                        }
-                    }))
-                    .unwrap()
-                    .into_buffer();
+                                        kind: TypeVariableOriginKind::MiscVariable,
+                                    })
+                                    .into(),
+                                GenericArgKind::Const(arg) => self
+                                    .next_const_var(
+                                        arg.ty(),
+                                        ConstVariableOrigin {
+                                            span: rustc_span::DUMMY_SP,
+                                            kind: ConstVariableOriginKind::MiscVariable,
+                                        },
+                                    )
+                                    .into(),
+                            }
+                        }))
+                        .unwrap()
+                        .into_buffer()
+                };
 
                 if !have_turbofish {
                     infer_subdiags.push(SourceKindSubdiag::GenericSuggestion {
@@ -520,7 +538,7 @@ pub fn emit_inference_failure_err(
                 ));
             }
             InferSourceKind::ClosureReturn { ty, data, should_wrap_expr } => {
-                let ty_info = ty_to_string(self, ty);
+                let ty_info = ty_to_string(self, ty, None);
                 multi_suggestions.push(SourceKindMultiSuggestion::new_closure_return(
                     ty_info,
                     data,
@@ -608,6 +626,7 @@ enum InferSourceKind<'tcx> {
         insert_span: Span,
         pattern_name: Option<Ident>,
         ty: Ty<'tcx>,
+        def_id: Option<DefId>,
     },
     ClosureArg {
         insert_span: Span,
@@ -662,7 +681,7 @@ fn ty_localized_msg(&self, infcx: &InferCtxt<'tcx>) -> (&'static str, String) {
                 if ty.is_closure() {
                     ("closure", closure_as_fn_str(infcx, ty))
                 } else if !ty.is_ty_infer() {
-                    ("normal", ty_to_string(infcx, ty))
+                    ("normal", ty_to_string(infcx, ty, None))
                 } else {
                     ("other", String::new())
                 }
@@ -788,10 +807,18 @@ fn ty_cost(self, ty: Ty<'tcx>) -> usize {
     /// Uses `fn source_cost` to determine whether this inference source is preferable to
     /// previous sources. We generally prefer earlier sources.
     #[instrument(level = "debug", skip(self))]
-    fn update_infer_source(&mut self, new_source: InferSource<'tcx>) {
+    fn update_infer_source(&mut self, mut new_source: InferSource<'tcx>) {
         let cost = self.source_cost(&new_source) + self.attempt;
         debug!(?cost);
         self.attempt += 1;
+        if let Some(InferSource { kind: InferSourceKind::GenericArg { def_id: did, ..}, .. }) = self.infer_source
+            && let InferSourceKind::LetBinding { ref ty, ref mut def_id, ..} = new_source.kind
+            && ty.is_ty_infer()
+        {
+            // Customize the output so we talk about `let x: Vec<_> = iter.collect();` instead of
+            // `let x: _ = iter.collect();`, as this is a very common case.
+            *def_id = Some(did);
+        }
         if cost < self.infer_source_cost {
             self.infer_source_cost = cost;
             self.infer_source = Some(new_source);
@@ -852,7 +879,10 @@ fn generic_arg_contains_target(&self, arg: GenericArg<'tcx>) -> bool {
             match inner.unpack() {
                 GenericArgKind::Lifetime(_) => {}
                 GenericArgKind::Type(ty) => {
-                    if matches!(ty.kind(), ty::Opaque(..) | ty::Closure(..) | ty::Generator(..)) {
+                    if matches!(
+                        ty.kind(),
+                        ty::Alias(ty::Opaque, ..) | ty::Closure(..) | ty::Generator(..)
+                    ) {
                         // Opaque types can't be named by the user right now.
                         //
                         // Both the generic arguments of closures and generators can
@@ -1089,6 +1119,7 @@ fn visit_local(&mut self, local: &'tcx Local<'tcx>) {
                                 insert_span: local.pat.span.shrink_to_hi(),
                                 pattern_name: local.pat.simple_ident(),
                                 ty,
+                                def_id: None,
                             },
                         })
                     }
index 1f554c81eff8e1941453d2f0a544ec245cd16d51..fed9fda74bfb33ec462dfadf8200f54432691762 100644 (file)
@@ -226,13 +226,11 @@ fn report_trait_placeholder_mismatch(
             false
         };
 
-        let expected_trait_ref = self.cx.resolve_vars_if_possible(ty::TraitRef {
-            def_id: trait_def_id,
-            substs: expected_substs,
-        });
-        let actual_trait_ref = self
+        let expected_trait_ref = self
             .cx
-            .resolve_vars_if_possible(ty::TraitRef { def_id: trait_def_id, substs: actual_substs });
+            .resolve_vars_if_possible(self.cx.tcx.mk_trait_ref(trait_def_id, expected_substs));
+        let actual_trait_ref =
+            self.cx.resolve_vars_if_possible(self.cx.tcx.mk_trait_ref(trait_def_id, actual_substs));
 
         // Search the expected and actual trait references to see (a)
         // whether the sub/sup placeholders appear in them (sometimes
index 09f9aa3c84220981537e7c5734dd90c0a4dbb5a8..9bd2202d2601e6f54dcb7a7bac0a5c001e2eb325 100644 (file)
@@ -330,7 +330,7 @@ pub fn suggest_new_region_bound(
                             Applicability::MaybeIncorrect,
                         );
                     }
-                    if let Some((param_span, param_ty)) = param.clone() {
+                    if let Some((param_span, ref param_ty)) = param {
                         err.span_suggestion_verbose(
                             param_span,
                             add_static_bound,
index 41b115f3377ac879d7287aa3910dcdf492221fc7..d2dffa4a0b78e5ef1d75606e165b0a137fbf87e0 100644 (file)
@@ -16,7 +16,7 @@ pub(super) fn note_region_origin(&self, err: &mut Diagnostic, origin: &Subregion
             infer::Subtype(ref trace) => RegionOriginNote::WithRequirement {
                 span: trace.cause.span,
                 requirement: ObligationCauseAsDiagArg(trace.cause.clone()),
-                expected_found: self.values_str(trace.values),
+                expected_found: self.values_str(trace.values).map(|(e, f, _, _)| (e, f)),
             }
             .add_to_diagnostic(err),
             infer::Reborrow(span) => {
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_region.rs b/compiler/rustc_infer/src/infer/error_reporting/note_region.rs
new file mode 100644 (file)
index 0000000..41b115f
--- /dev/null
@@ -0,0 +1,427 @@
+use crate::errors::RegionOriginNote;
+use crate::infer::error_reporting::{note_and_explain_region, TypeErrCtxt};
+use crate::infer::{self, SubregionOrigin};
+use rustc_errors::{
+    fluent, struct_span_err, AddToDiagnostic, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
+};
+use rustc_middle::traits::ObligationCauseCode;
+use rustc_middle::ty::error::TypeError;
+use rustc_middle::ty::{self, Region};
+
+use super::ObligationCauseAsDiagArg;
+
+impl<'tcx> TypeErrCtxt<'_, 'tcx> {
+    pub(super) fn note_region_origin(&self, err: &mut Diagnostic, origin: &SubregionOrigin<'tcx>) {
+        match *origin {
+            infer::Subtype(ref trace) => RegionOriginNote::WithRequirement {
+                span: trace.cause.span,
+                requirement: ObligationCauseAsDiagArg(trace.cause.clone()),
+                expected_found: self.values_str(trace.values),
+            }
+            .add_to_diagnostic(err),
+            infer::Reborrow(span) => {
+                RegionOriginNote::Plain { span, msg: fluent::infer_reborrow }.add_to_diagnostic(err)
+            }
+            infer::ReborrowUpvar(span, ref upvar_id) => {
+                let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
+                RegionOriginNote::WithName {
+                    span,
+                    msg: fluent::infer_reborrow,
+                    name: &var_name.to_string(),
+                    continues: false,
+                }
+                .add_to_diagnostic(err);
+            }
+            infer::RelateObjectBound(span) => {
+                RegionOriginNote::Plain { span, msg: fluent::infer_relate_object_bound }
+                    .add_to_diagnostic(err);
+            }
+            infer::DataBorrowed(ty, span) => {
+                RegionOriginNote::WithName {
+                    span,
+                    msg: fluent::infer_data_borrowed,
+                    name: &self.ty_to_string(ty),
+                    continues: false,
+                }
+                .add_to_diagnostic(err);
+            }
+            infer::ReferenceOutlivesReferent(ty, span) => {
+                RegionOriginNote::WithName {
+                    span,
+                    msg: fluent::infer_reference_outlives_referent,
+                    name: &self.ty_to_string(ty),
+                    continues: false,
+                }
+                .add_to_diagnostic(err);
+            }
+            infer::RelateParamBound(span, ty, opt_span) => {
+                RegionOriginNote::WithName {
+                    span,
+                    msg: fluent::infer_relate_param_bound,
+                    name: &self.ty_to_string(ty),
+                    continues: opt_span.is_some(),
+                }
+                .add_to_diagnostic(err);
+                if let Some(span) = opt_span {
+                    RegionOriginNote::Plain { span, msg: fluent::infer_relate_param_bound_2 }
+                        .add_to_diagnostic(err);
+                }
+            }
+            infer::RelateRegionParamBound(span) => {
+                RegionOriginNote::Plain { span, msg: fluent::infer_relate_region_param_bound }
+                    .add_to_diagnostic(err);
+            }
+            infer::CompareImplItemObligation { span, .. } => {
+                RegionOriginNote::Plain { span, msg: fluent::infer_compare_impl_item_obligation }
+                    .add_to_diagnostic(err);
+            }
+            infer::CheckAssociatedTypeBounds { ref parent, .. } => {
+                self.note_region_origin(err, &parent);
+            }
+            infer::AscribeUserTypeProvePredicate(span) => {
+                RegionOriginNote::Plain {
+                    span,
+                    msg: fluent::infer_ascribe_user_type_prove_predicate,
+                }
+                .add_to_diagnostic(err);
+            }
+        }
+    }
+
+    pub(super) fn report_concrete_failure(
+        &self,
+        origin: SubregionOrigin<'tcx>,
+        sub: Region<'tcx>,
+        sup: Region<'tcx>,
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
+        match origin {
+            infer::Subtype(box trace) => {
+                let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
+                let mut err = self.report_and_explain_type_error(trace, terr);
+                match (*sub, *sup) {
+                    (ty::RePlaceholder(_), ty::RePlaceholder(_)) => {}
+                    (ty::RePlaceholder(_), _) => {
+                        note_and_explain_region(
+                            self.tcx,
+                            &mut err,
+                            "",
+                            sup,
+                            " doesn't meet the lifetime requirements",
+                            None,
+                        );
+                    }
+                    (_, ty::RePlaceholder(_)) => {
+                        note_and_explain_region(
+                            self.tcx,
+                            &mut err,
+                            "the required lifetime does not necessarily outlive ",
+                            sub,
+                            "",
+                            None,
+                        );
+                    }
+                    _ => {
+                        note_and_explain_region(self.tcx, &mut err, "", sup, "...", None);
+                        note_and_explain_region(
+                            self.tcx,
+                            &mut err,
+                            "...does not necessarily outlive ",
+                            sub,
+                            "",
+                            None,
+                        );
+                    }
+                }
+                err
+            }
+            infer::Reborrow(span) => {
+                let mut err = struct_span_err!(
+                    self.tcx.sess,
+                    span,
+                    E0312,
+                    "lifetime of reference outlives lifetime of borrowed content..."
+                );
+                note_and_explain_region(
+                    self.tcx,
+                    &mut err,
+                    "...the reference is valid for ",
+                    sub,
+                    "...",
+                    None,
+                );
+                note_and_explain_region(
+                    self.tcx,
+                    &mut err,
+                    "...but the borrowed content is only valid for ",
+                    sup,
+                    "",
+                    None,
+                );
+                err
+            }
+            infer::ReborrowUpvar(span, ref upvar_id) => {
+                let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
+                let mut err = struct_span_err!(
+                    self.tcx.sess,
+                    span,
+                    E0313,
+                    "lifetime of borrowed pointer outlives lifetime of captured variable `{}`...",
+                    var_name
+                );
+                note_and_explain_region(
+                    self.tcx,
+                    &mut err,
+                    "...the borrowed pointer is valid for ",
+                    sub,
+                    "...",
+                    None,
+                );
+                note_and_explain_region(
+                    self.tcx,
+                    &mut err,
+                    &format!("...but `{}` is only valid for ", var_name),
+                    sup,
+                    "",
+                    None,
+                );
+                err
+            }
+            infer::RelateObjectBound(span) => {
+                let mut err = struct_span_err!(
+                    self.tcx.sess,
+                    span,
+                    E0476,
+                    "lifetime of the source pointer does not outlive lifetime bound of the \
+                     object type"
+                );
+                note_and_explain_region(
+                    self.tcx,
+                    &mut err,
+                    "object type is valid for ",
+                    sub,
+                    "",
+                    None,
+                );
+                note_and_explain_region(
+                    self.tcx,
+                    &mut err,
+                    "source pointer is only valid for ",
+                    sup,
+                    "",
+                    None,
+                );
+                err
+            }
+            infer::RelateParamBound(span, ty, opt_span) => {
+                let mut err = struct_span_err!(
+                    self.tcx.sess,
+                    span,
+                    E0477,
+                    "the type `{}` does not fulfill the required lifetime",
+                    self.ty_to_string(ty)
+                );
+                match *sub {
+                    ty::ReStatic => note_and_explain_region(
+                        self.tcx,
+                        &mut err,
+                        "type must satisfy ",
+                        sub,
+                        if opt_span.is_some() { " as required by this binding" } else { "" },
+                        opt_span,
+                    ),
+                    _ => note_and_explain_region(
+                        self.tcx,
+                        &mut err,
+                        "type must outlive ",
+                        sub,
+                        if opt_span.is_some() { " as required by this binding" } else { "" },
+                        opt_span,
+                    ),
+                }
+                err
+            }
+            infer::RelateRegionParamBound(span) => {
+                let mut err =
+                    struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
+                note_and_explain_region(
+                    self.tcx,
+                    &mut err,
+                    "lifetime parameter instantiated with ",
+                    sup,
+                    "",
+                    None,
+                );
+                note_and_explain_region(
+                    self.tcx,
+                    &mut err,
+                    "but lifetime parameter must outlive ",
+                    sub,
+                    "",
+                    None,
+                );
+                err
+            }
+            infer::DataBorrowed(ty, span) => {
+                let mut err = struct_span_err!(
+                    self.tcx.sess,
+                    span,
+                    E0490,
+                    "a value of type `{}` is borrowed for too long",
+                    self.ty_to_string(ty)
+                );
+                note_and_explain_region(
+                    self.tcx,
+                    &mut err,
+                    "the type is valid for ",
+                    sub,
+                    "",
+                    None,
+                );
+                note_and_explain_region(
+                    self.tcx,
+                    &mut err,
+                    "but the borrow lasts for ",
+                    sup,
+                    "",
+                    None,
+                );
+                err
+            }
+            infer::ReferenceOutlivesReferent(ty, span) => {
+                let mut err = struct_span_err!(
+                    self.tcx.sess,
+                    span,
+                    E0491,
+                    "in type `{}`, reference has a longer lifetime than the data it references",
+                    self.ty_to_string(ty)
+                );
+                note_and_explain_region(
+                    self.tcx,
+                    &mut err,
+                    "the pointer is valid for ",
+                    sub,
+                    "",
+                    None,
+                );
+                note_and_explain_region(
+                    self.tcx,
+                    &mut err,
+                    "but the referenced data is only valid for ",
+                    sup,
+                    "",
+                    None,
+                );
+                err
+            }
+            infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => self
+                .report_extra_impl_obligation(
+                    span,
+                    impl_item_def_id,
+                    trait_item_def_id,
+                    &format!("`{}: {}`", sup, sub),
+                ),
+            infer::CheckAssociatedTypeBounds { impl_item_def_id, trait_item_def_id, parent } => {
+                let mut err = self.report_concrete_failure(*parent, sub, sup);
+
+                let trait_item_span = self.tcx.def_span(trait_item_def_id);
+                let item_name = self.tcx.item_name(impl_item_def_id.to_def_id());
+                err.span_label(
+                    trait_item_span,
+                    format!("definition of `{}` from trait", item_name),
+                );
+
+                let trait_predicates = self.tcx.explicit_predicates_of(trait_item_def_id);
+                let impl_predicates = self.tcx.explicit_predicates_of(impl_item_def_id);
+
+                let impl_predicates: rustc_data_structures::fx::FxHashSet<_> =
+                    impl_predicates.predicates.into_iter().map(|(pred, _)| pred).collect();
+                let clauses: Vec<_> = trait_predicates
+                    .predicates
+                    .into_iter()
+                    .filter(|&(pred, _)| !impl_predicates.contains(pred))
+                    .map(|(pred, _)| format!("{}", pred))
+                    .collect();
+
+                if !clauses.is_empty() {
+                    let generics = self.tcx.hir().get_generics(impl_item_def_id).unwrap();
+                    let where_clause_span = generics.tail_span_for_predicate_suggestion();
+
+                    let suggestion = format!(
+                        "{} {}",
+                        generics.add_where_or_trailing_comma(),
+                        clauses.join(", "),
+                    );
+                    err.span_suggestion(
+                        where_clause_span,
+                        &format!(
+                            "try copying {} from the trait",
+                            if clauses.len() > 1 { "these clauses" } else { "this clause" }
+                        ),
+                        suggestion,
+                        rustc_errors::Applicability::MaybeIncorrect,
+                    );
+                }
+
+                err
+            }
+            infer::AscribeUserTypeProvePredicate(span) => {
+                let mut err =
+                    struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
+                note_and_explain_region(
+                    self.tcx,
+                    &mut err,
+                    "lifetime instantiated with ",
+                    sup,
+                    "",
+                    None,
+                );
+                note_and_explain_region(
+                    self.tcx,
+                    &mut err,
+                    "but lifetime must outlive ",
+                    sub,
+                    "",
+                    None,
+                );
+                err
+            }
+        }
+    }
+
+    pub(super) fn report_placeholder_failure(
+        &self,
+        placeholder_origin: SubregionOrigin<'tcx>,
+        sub: Region<'tcx>,
+        sup: Region<'tcx>,
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
+        // I can't think how to do better than this right now. -nikomatsakis
+        debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure");
+        match placeholder_origin {
+            infer::Subtype(box ref trace)
+                if matches!(
+                    &trace.cause.code().peel_derives(),
+                    ObligationCauseCode::BindingObligation(..)
+                        | ObligationCauseCode::ExprBindingObligation(..)
+                ) =>
+            {
+                // Hack to get around the borrow checker because trace.cause has an `Rc`.
+                if let ObligationCauseCode::BindingObligation(_, span)
+                | ObligationCauseCode::ExprBindingObligation(_, span, ..) =
+                    &trace.cause.code().peel_derives()
+                {
+                    let span = *span;
+                    let mut err = self.report_concrete_failure(placeholder_origin, sub, sup);
+                    err.span_note(span, "the lifetime requirement is introduced here");
+                    err
+                } else {
+                    unreachable!()
+                }
+            }
+            infer::Subtype(box trace) => {
+                let terr = TypeError::RegionsPlaceholderMismatch;
+                return self.report_and_explain_type_error(trace, terr);
+            }
+            _ => return self.report_concrete_failure(placeholder_origin, sub, sup),
+        }
+    }
+}
diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
new file mode 100644 (file)
index 0000000..30ca9f4
--- /dev/null
@@ -0,0 +1,674 @@
+use hir::def::CtorKind;
+use hir::intravisit::{walk_expr, walk_stmt, Visitor};
+use rustc_data_structures::fx::FxIndexSet;
+use rustc_errors::{Applicability, Diagnostic};
+use rustc_hir as hir;
+use rustc_middle::traits::{
+    IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
+    StatementAsExpression,
+};
+use rustc_middle::ty::print::with_no_trimmed_paths;
+use rustc_middle::ty::{self as ty, Ty, TypeVisitable};
+use rustc_span::{sym, BytePos, Span};
+
+use crate::errors::SuggAddLetForLetChains;
+
+use super::TypeErrCtxt;
+
+impl<'tcx> TypeErrCtxt<'_, 'tcx> {
+    pub(super) fn suggest_remove_semi_or_return_binding(
+        &self,
+        err: &mut Diagnostic,
+        first_id: Option<hir::HirId>,
+        first_ty: Ty<'tcx>,
+        first_span: Span,
+        second_id: Option<hir::HirId>,
+        second_ty: Ty<'tcx>,
+        second_span: Span,
+    ) {
+        let remove_semicolon = [
+            (first_id, self.resolve_vars_if_possible(second_ty)),
+            (second_id, self.resolve_vars_if_possible(first_ty)),
+        ]
+        .into_iter()
+        .find_map(|(id, ty)| {
+            let hir::Node::Block(blk) = self.tcx.hir().get(id?) else { return None };
+            self.could_remove_semicolon(blk, ty)
+        });
+        match remove_semicolon {
+            Some((sp, StatementAsExpression::NeedsBoxing)) => {
+                err.multipart_suggestion(
+                    "consider removing this semicolon and boxing the expressions",
+                    vec![
+                        (first_span.shrink_to_lo(), "Box::new(".to_string()),
+                        (first_span.shrink_to_hi(), ")".to_string()),
+                        (second_span.shrink_to_lo(), "Box::new(".to_string()),
+                        (second_span.shrink_to_hi(), ")".to_string()),
+                        (sp, String::new()),
+                    ],
+                    Applicability::MachineApplicable,
+                );
+            }
+            Some((sp, StatementAsExpression::CorrectType)) => {
+                err.span_suggestion_short(
+                    sp,
+                    "consider removing this semicolon",
+                    "",
+                    Applicability::MachineApplicable,
+                );
+            }
+            None => {
+                for (id, ty) in [(first_id, second_ty), (second_id, first_ty)] {
+                    if let Some(id) = id
+                        && let hir::Node::Block(blk) = self.tcx.hir().get(id)
+                        && self.consider_returning_binding(blk, ty, err)
+                    {
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    pub(super) fn suggest_boxing_for_return_impl_trait(
+        &self,
+        err: &mut Diagnostic,
+        return_sp: Span,
+        arm_spans: impl Iterator<Item = Span>,
+    ) {
+        err.multipart_suggestion(
+            "you could change the return type to be a boxed trait object",
+            vec![
+                (return_sp.with_hi(return_sp.lo() + BytePos(4)), "Box<dyn".to_string()),
+                (return_sp.shrink_to_hi(), ">".to_string()),
+            ],
+            Applicability::MaybeIncorrect,
+        );
+        let sugg = arm_spans
+            .flat_map(|sp| {
+                [(sp.shrink_to_lo(), "Box::new(".to_string()), (sp.shrink_to_hi(), ")".to_string())]
+                    .into_iter()
+            })
+            .collect::<Vec<_>>();
+        err.multipart_suggestion(
+            "if you change the return type to expect trait objects, box the returned expressions",
+            sugg,
+            Applicability::MaybeIncorrect,
+        );
+    }
+
+    pub(super) fn suggest_tuple_pattern(
+        &self,
+        cause: &ObligationCause<'tcx>,
+        exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
+        diag: &mut Diagnostic,
+    ) {
+        // Heavily inspired by `FnCtxt::suggest_compatible_variants`, with
+        // some modifications due to that being in typeck and this being in infer.
+        if let ObligationCauseCode::Pattern { .. } = cause.code() {
+            if let ty::Adt(expected_adt, substs) = exp_found.expected.kind() {
+                let compatible_variants: Vec<_> = expected_adt
+                    .variants()
+                    .iter()
+                    .filter(|variant| {
+                        variant.fields.len() == 1 && variant.ctor_kind() == Some(CtorKind::Fn)
+                    })
+                    .filter_map(|variant| {
+                        let sole_field = &variant.fields[0];
+                        let sole_field_ty = sole_field.ty(self.tcx, substs);
+                        if self.same_type_modulo_infer(sole_field_ty, exp_found.found) {
+                            let variant_path =
+                                with_no_trimmed_paths!(self.tcx.def_path_str(variant.def_id));
+                            // FIXME #56861: DRYer prelude filtering
+                            if let Some(path) = variant_path.strip_prefix("std::prelude::") {
+                                if let Some((_, path)) = path.split_once("::") {
+                                    return Some(path.to_string());
+                                }
+                            }
+                            Some(variant_path)
+                        } else {
+                            None
+                        }
+                    })
+                    .collect();
+                match &compatible_variants[..] {
+                    [] => {}
+                    [variant] => {
+                        diag.multipart_suggestion_verbose(
+                            &format!("try wrapping the pattern in `{}`", variant),
+                            vec![
+                                (cause.span.shrink_to_lo(), format!("{}(", variant)),
+                                (cause.span.shrink_to_hi(), ")".to_string()),
+                            ],
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
+                    _ => {
+                        // More than one matching variant.
+                        diag.multipart_suggestions(
+                            &format!(
+                                "try wrapping the pattern in a variant of `{}`",
+                                self.tcx.def_path_str(expected_adt.did())
+                            ),
+                            compatible_variants.into_iter().map(|variant| {
+                                vec![
+                                    (cause.span.shrink_to_lo(), format!("{}(", variant)),
+                                    (cause.span.shrink_to_hi(), ")".to_string()),
+                                ]
+                            }),
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
+                }
+            }
+        }
+    }
+
+    /// A possible error is to forget to add `.await` when using futures:
+    ///
+    /// ```compile_fail,E0308
+    /// async fn make_u32() -> u32 {
+    ///     22
+    /// }
+    ///
+    /// fn take_u32(x: u32) {}
+    ///
+    /// async fn foo() {
+    ///     let x = make_u32();
+    ///     take_u32(x);
+    /// }
+    /// ```
+    ///
+    /// This routine checks if the found type `T` implements `Future<Output=U>` where `U` is the
+    /// expected type. If this is the case, and we are inside of an async body, it suggests adding
+    /// `.await` to the tail of the expression.
+    pub(super) fn suggest_await_on_expect_found(
+        &self,
+        cause: &ObligationCause<'tcx>,
+        exp_span: Span,
+        exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
+        diag: &mut Diagnostic,
+    ) {
+        debug!(
+            "suggest_await_on_expect_found: exp_span={:?}, expected_ty={:?}, found_ty={:?}",
+            exp_span, exp_found.expected, exp_found.found,
+        );
+
+        if let ObligationCauseCode::CompareImplItemObligation { .. } = cause.code() {
+            return;
+        }
+
+        match (
+            self.get_impl_future_output_ty(exp_found.expected),
+            self.get_impl_future_output_ty(exp_found.found),
+        ) {
+            (Some(exp), Some(found)) if self.same_type_modulo_infer(exp, found) => match cause
+                .code()
+            {
+                ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => {
+                    let then_span = self.find_block_span_from_hir_id(*then_id);
+                    diag.multipart_suggestion(
+                        "consider `await`ing on both `Future`s",
+                        vec![
+                            (then_span.shrink_to_hi(), ".await".to_string()),
+                            (exp_span.shrink_to_hi(), ".await".to_string()),
+                        ],
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+                ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
+                    prior_arms,
+                    ..
+                }) => {
+                    if let [.., arm_span] = &prior_arms[..] {
+                        diag.multipart_suggestion(
+                            "consider `await`ing on both `Future`s",
+                            vec![
+                                (arm_span.shrink_to_hi(), ".await".to_string()),
+                                (exp_span.shrink_to_hi(), ".await".to_string()),
+                            ],
+                            Applicability::MaybeIncorrect,
+                        );
+                    } else {
+                        diag.help("consider `await`ing on both `Future`s");
+                    }
+                }
+                _ => {
+                    diag.help("consider `await`ing on both `Future`s");
+                }
+            },
+            (_, Some(ty)) if self.same_type_modulo_infer(exp_found.expected, ty) => {
+                diag.span_suggestion_verbose(
+                    exp_span.shrink_to_hi(),
+                    "consider `await`ing on the `Future`",
+                    ".await",
+                    Applicability::MaybeIncorrect,
+                );
+            }
+            (Some(ty), _) if self.same_type_modulo_infer(ty, exp_found.found) => match cause.code()
+            {
+                ObligationCauseCode::Pattern { span: Some(then_span), .. } => {
+                    diag.span_suggestion_verbose(
+                        then_span.shrink_to_hi(),
+                        "consider `await`ing on the `Future`",
+                        ".await",
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+                ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => {
+                    let then_span = self.find_block_span_from_hir_id(*then_id);
+                    diag.span_suggestion_verbose(
+                        then_span.shrink_to_hi(),
+                        "consider `await`ing on the `Future`",
+                        ".await",
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+                ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
+                    ref prior_arms,
+                    ..
+                }) => {
+                    diag.multipart_suggestion_verbose(
+                        "consider `await`ing on the `Future`",
+                        prior_arms
+                            .iter()
+                            .map(|arm| (arm.shrink_to_hi(), ".await".to_string()))
+                            .collect(),
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+                _ => {}
+            },
+            _ => {}
+        }
+    }
+
+    pub(super) fn suggest_accessing_field_where_appropriate(
+        &self,
+        cause: &ObligationCause<'tcx>,
+        exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
+        diag: &mut Diagnostic,
+    ) {
+        debug!(
+            "suggest_accessing_field_where_appropriate(cause={:?}, exp_found={:?})",
+            cause, exp_found
+        );
+        if let ty::Adt(expected_def, expected_substs) = exp_found.expected.kind() {
+            if expected_def.is_enum() {
+                return;
+            }
+
+            if let Some((name, ty)) = expected_def
+                .non_enum_variant()
+                .fields
+                .iter()
+                .filter(|field| field.vis.is_accessible_from(field.did, self.tcx))
+                .map(|field| (field.name, field.ty(self.tcx, expected_substs)))
+                .find(|(_, ty)| self.same_type_modulo_infer(*ty, exp_found.found))
+            {
+                if let ObligationCauseCode::Pattern { span: Some(span), .. } = *cause.code() {
+                    if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
+                        let suggestion = if expected_def.is_struct() {
+                            format!("{}.{}", snippet, name)
+                        } else if expected_def.is_union() {
+                            format!("unsafe {{ {}.{} }}", snippet, name)
+                        } else {
+                            return;
+                        };
+                        diag.span_suggestion(
+                            span,
+                            &format!(
+                                "you might have meant to use field `{}` whose type is `{}`",
+                                name, ty
+                            ),
+                            suggestion,
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
+                }
+            }
+        }
+    }
+
+    /// When encountering a case where `.as_ref()` on a `Result` or `Option` would be appropriate,
+    /// suggests it.
+    pub(super) fn suggest_as_ref_where_appropriate(
+        &self,
+        span: Span,
+        exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
+        diag: &mut Diagnostic,
+    ) {
+        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
+            && let Some(msg) = self.should_suggest_as_ref(exp_found.expected, exp_found.found)
+        {
+            diag.span_suggestion(
+                span,
+                msg,
+                // HACK: fix issue# 100605, suggesting convert from &Option<T> to Option<&T>, remove the extra `&`
+                format!("{}.as_ref()", snippet.trim_start_matches('&')),
+                Applicability::MachineApplicable,
+            );
+        }
+    }
+
+    pub fn should_suggest_as_ref(&self, expected: Ty<'tcx>, found: Ty<'tcx>) -> Option<&str> {
+        if let (ty::Adt(exp_def, exp_substs), ty::Ref(_, found_ty, _)) =
+            (expected.kind(), found.kind())
+        {
+            if let ty::Adt(found_def, found_substs) = *found_ty.kind() {
+                if exp_def == &found_def {
+                    let have_as_ref = &[
+                        (
+                            sym::Option,
+                            "you can convert from `&Option<T>` to `Option<&T>` using \
+                        `.as_ref()`",
+                        ),
+                        (
+                            sym::Result,
+                            "you can convert from `&Result<T, E>` to \
+                        `Result<&T, &E>` using `.as_ref()`",
+                        ),
+                    ];
+                    if let Some(msg) = have_as_ref.iter().find_map(|(name, msg)| {
+                        self.tcx.is_diagnostic_item(*name, exp_def.did()).then_some(msg)
+                    }) {
+                        let mut show_suggestion = true;
+                        for (exp_ty, found_ty) in
+                            std::iter::zip(exp_substs.types(), found_substs.types())
+                        {
+                            match *exp_ty.kind() {
+                                ty::Ref(_, exp_ty, _) => {
+                                    match (exp_ty.kind(), found_ty.kind()) {
+                                        (_, ty::Param(_))
+                                        | (_, ty::Infer(_))
+                                        | (ty::Param(_), _)
+                                        | (ty::Infer(_), _) => {}
+                                        _ if self.same_type_modulo_infer(exp_ty, found_ty) => {}
+                                        _ => show_suggestion = false,
+                                    };
+                                }
+                                ty::Param(_) | ty::Infer(_) => {}
+                                _ => show_suggestion = false,
+                            }
+                        }
+                        if show_suggestion {
+                            return Some(*msg);
+                        }
+                    }
+                }
+            }
+        }
+        None
+    }
+
+    /// Try to find code with pattern `if Some(..) = expr`
+    /// use a `visitor` to mark the `if` which its span contains given error span,
+    /// and then try to find a assignment in the `cond` part, which span is equal with error span
+    pub(super) fn suggest_let_for_letchains(
+        &self,
+        err: &mut Diagnostic,
+        cause: &ObligationCause<'_>,
+        span: Span,
+    ) {
+        let hir = self.tcx.hir();
+        let fn_hir_id = hir.get_parent_node(cause.body_id);
+        if let Some(node) = self.tcx.hir().find(fn_hir_id) &&
+            let hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Fn(_sig, _, body_id), ..
+                }) = node {
+        let body = hir.body(*body_id);
+
+        /// Find the if expression with given span
+        struct IfVisitor {
+            pub result: bool,
+            pub found_if: bool,
+            pub err_span: Span,
+        }
+
+        impl<'v> Visitor<'v> for IfVisitor {
+            fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
+                if self.result { return; }
+                match ex.kind {
+                    hir::ExprKind::If(cond, _, _) => {
+                        self.found_if = true;
+                        walk_expr(self, cond);
+                        self.found_if = false;
+                    }
+                    _ => walk_expr(self, ex),
+                }
+            }
+
+            fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) {
+                if let hir::StmtKind::Local(hir::Local {
+                        span, pat: hir::Pat{..}, ty: None, init: Some(_), ..
+                    }) = &ex.kind
+                    && self.found_if
+                    && span.eq(&self.err_span) {
+                        self.result = true;
+                }
+                walk_stmt(self, ex);
+            }
+
+            fn visit_body(&mut self, body: &'v hir::Body<'v>) {
+                hir::intravisit::walk_body(self, body);
+            }
+        }
+
+        let mut visitor = IfVisitor { err_span: span, found_if: false, result: false };
+        visitor.visit_body(&body);
+        if visitor.result {
+                err.subdiagnostic(SuggAddLetForLetChains{span: span.shrink_to_lo()});
+            }
+        }
+    }
+}
+
+impl<'tcx> TypeErrCtxt<'_, 'tcx> {
+    /// Be helpful when the user wrote `{... expr; }` and taking the `;` off
+    /// is enough to fix the error.
+    pub fn could_remove_semicolon(
+        &self,
+        blk: &'tcx hir::Block<'tcx>,
+        expected_ty: Ty<'tcx>,
+    ) -> Option<(Span, StatementAsExpression)> {
+        let blk = blk.innermost_block();
+        // Do not suggest if we have a tail expr.
+        if blk.expr.is_some() {
+            return None;
+        }
+        let last_stmt = blk.stmts.last()?;
+        let hir::StmtKind::Semi(ref last_expr) = last_stmt.kind else {
+            return None;
+        };
+        let last_expr_ty = self.typeck_results.as_ref()?.expr_ty_opt(*last_expr)?;
+        let needs_box = match (last_expr_ty.kind(), expected_ty.kind()) {
+            _ if last_expr_ty.references_error() => return None,
+            _ if self.same_type_modulo_infer(last_expr_ty, expected_ty) => {
+                StatementAsExpression::CorrectType
+            }
+            (
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id: last_def_id, .. }),
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id: exp_def_id, .. }),
+            ) if last_def_id == exp_def_id => StatementAsExpression::CorrectType,
+            (
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id: last_def_id, substs: last_bounds, .. }),
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id: exp_def_id, substs: exp_bounds, .. }),
+            ) => {
+                debug!(
+                    "both opaque, likely future {:?} {:?} {:?} {:?}",
+                    last_def_id, last_bounds, exp_def_id, exp_bounds
+                );
+
+                let last_local_id = last_def_id.as_local()?;
+                let exp_local_id = exp_def_id.as_local()?;
+
+                match (
+                    &self.tcx.hir().expect_item(last_local_id).kind,
+                    &self.tcx.hir().expect_item(exp_local_id).kind,
+                ) {
+                    (
+                        hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: last_bounds, .. }),
+                        hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: exp_bounds, .. }),
+                    ) if std::iter::zip(*last_bounds, *exp_bounds).all(|(left, right)| {
+                        match (left, right) {
+                            (
+                                hir::GenericBound::Trait(tl, ml),
+                                hir::GenericBound::Trait(tr, mr),
+                            ) if tl.trait_ref.trait_def_id() == tr.trait_ref.trait_def_id()
+                                && ml == mr =>
+                            {
+                                true
+                            }
+                            (
+                                hir::GenericBound::LangItemTrait(langl, _, _, argsl),
+                                hir::GenericBound::LangItemTrait(langr, _, _, argsr),
+                            ) if langl == langr => {
+                                // FIXME: consider the bounds!
+                                debug!("{:?} {:?}", argsl, argsr);
+                                true
+                            }
+                            _ => false,
+                        }
+                    }) =>
+                    {
+                        StatementAsExpression::NeedsBoxing
+                    }
+                    _ => StatementAsExpression::CorrectType,
+                }
+            }
+            _ => return None,
+        };
+        let span = if last_stmt.span.from_expansion() {
+            let mac_call = rustc_span::source_map::original_sp(last_stmt.span, blk.span);
+            self.tcx.sess.source_map().mac_call_stmt_semi_span(mac_call)?
+        } else {
+            last_stmt.span.with_lo(last_stmt.span.hi() - BytePos(1))
+        };
+        Some((span, needs_box))
+    }
+
+    /// Suggest returning a local binding with a compatible type if the block
+    /// has no return expression.
+    pub fn consider_returning_binding(
+        &self,
+        blk: &'tcx hir::Block<'tcx>,
+        expected_ty: Ty<'tcx>,
+        err: &mut Diagnostic,
+    ) -> bool {
+        let blk = blk.innermost_block();
+        // Do not suggest if we have a tail expr.
+        if blk.expr.is_some() {
+            return false;
+        }
+        let mut shadowed = FxIndexSet::default();
+        let mut candidate_idents = vec![];
+        let mut find_compatible_candidates = |pat: &hir::Pat<'_>| {
+            if let hir::PatKind::Binding(_, hir_id, ident, _) = &pat.kind
+                && let Some(pat_ty) = self
+                    .typeck_results
+                    .as_ref()
+                    .and_then(|typeck_results| typeck_results.node_type_opt(*hir_id))
+            {
+                let pat_ty = self.resolve_vars_if_possible(pat_ty);
+                if self.same_type_modulo_infer(pat_ty, expected_ty)
+                    && !(pat_ty, expected_ty).references_error()
+                    && shadowed.insert(ident.name)
+                {
+                    candidate_idents.push((*ident, pat_ty));
+                }
+            }
+            true
+        };
+
+        let hir = self.tcx.hir();
+        for stmt in blk.stmts.iter().rev() {
+            let hir::StmtKind::Local(local) = &stmt.kind else { continue; };
+            local.pat.walk(&mut find_compatible_candidates);
+        }
+        match hir.find(hir.get_parent_node(blk.hir_id)) {
+            Some(hir::Node::Expr(hir::Expr { hir_id, .. })) => {
+                match hir.find(hir.get_parent_node(*hir_id)) {
+                    Some(hir::Node::Arm(hir::Arm { pat, .. })) => {
+                        pat.walk(&mut find_compatible_candidates);
+                    }
+                    Some(
+                        hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body), .. })
+                        | hir::Node::ImplItem(hir::ImplItem {
+                            kind: hir::ImplItemKind::Fn(_, body),
+                            ..
+                        })
+                        | hir::Node::TraitItem(hir::TraitItem {
+                            kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body)),
+                            ..
+                        })
+                        | hir::Node::Expr(hir::Expr {
+                            kind: hir::ExprKind::Closure(hir::Closure { body, .. }),
+                            ..
+                        }),
+                    ) => {
+                        for param in hir.body(*body).params {
+                            param.pat.walk(&mut find_compatible_candidates);
+                        }
+                    }
+                    Some(hir::Node::Expr(hir::Expr {
+                        kind:
+                            hir::ExprKind::If(
+                                hir::Expr { kind: hir::ExprKind::Let(let_), .. },
+                                then_block,
+                                _,
+                            ),
+                        ..
+                    })) if then_block.hir_id == *hir_id => {
+                        let_.pat.walk(&mut find_compatible_candidates);
+                    }
+                    _ => {}
+                }
+            }
+            _ => {}
+        }
+
+        match &candidate_idents[..] {
+            [(ident, _ty)] => {
+                let sm = self.tcx.sess.source_map();
+                if let Some(stmt) = blk.stmts.last() {
+                    let stmt_span = sm.stmt_span(stmt.span, blk.span);
+                    let sugg = if sm.is_multiline(blk.span)
+                        && let Some(spacing) = sm.indentation_before(stmt_span)
+                    {
+                        format!("\n{spacing}{ident}")
+                    } else {
+                        format!(" {ident}")
+                    };
+                    err.span_suggestion_verbose(
+                        stmt_span.shrink_to_hi(),
+                        format!("consider returning the local binding `{ident}`"),
+                        sugg,
+                        Applicability::MaybeIncorrect,
+                    );
+                } else {
+                    let sugg = if sm.is_multiline(blk.span)
+                        && let Some(spacing) = sm.indentation_before(blk.span.shrink_to_lo())
+                    {
+                        format!("\n{spacing}    {ident}\n{spacing}")
+                    } else {
+                        format!(" {ident} ")
+                    };
+                    let left_span = sm.span_through_char(blk.span, '{').shrink_to_hi();
+                    err.span_suggestion_verbose(
+                        sm.span_extend_while(left_span, |c| c.is_whitespace()).unwrap_or(left_span),
+                        format!("consider returning the local binding `{ident}`"),
+                        sugg,
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+                true
+            }
+            values if (1..3).contains(&values.len()) => {
+                let spans = values.iter().map(|(ident, _)| ident.span).collect::<Vec<_>>();
+                err.span_note(spans, "consider returning one of these bindings");
+                true
+            }
+            _ => false,
+        }
+    }
+}
index f6946929bd23f58dbdd62d37fbbcedb6572f3831..8f53b1ccdf45829c758721072cf55d1063f730ff 100644 (file)
@@ -205,12 +205,11 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
             | ty::Dynamic(..)
             | ty::Never
             | ty::Tuple(..)
-            | ty::Projection(..)
+            | ty::Alias(..)
             | ty::Foreign(..)
             | ty::Param(..)
             | ty::Closure(..)
-            | ty::GeneratorWitness(..)
-            | ty::Opaque(..) => t.super_fold_with(self),
+            | ty::GeneratorWitness(..) => t.super_fold_with(self),
 
             ty::Placeholder(..) | ty::Bound(..) => bug!("unexpected type {:?}", t),
         }
index 7f27b35a54e4f8808c0350a30677abd61d77bed8..21b68ce998997a6826645c6ad0036f2af522bb7d 100644 (file)
@@ -103,6 +103,11 @@ fn binders<T>(
     where
         T: Relate<'tcx>,
     {
+        // GLB of a binder and itself is just itself
+        if a == b {
+            return Ok(a);
+        }
+
         debug!("binders(a={:?}, b={:?})", a, b);
         if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() {
             // When higher-ranked types are involved, computing the GLB is
index eba65361ae6b2b923ec5e8f100b41e4dc904aea1..0ebc6d55bcba952678c86e6ff3c1dba91d8a11bd 100644 (file)
@@ -105,11 +105,13 @@ pub fn super_lattice_tys<'a, 'tcx: 'a, L>(
             Ok(v)
         }
 
-        (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => {
-            infcx.super_combine_tys(this, a, b)
-        }
-        (&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..))
-            if this.define_opaque_types() && did.is_local() =>
+        (
+            &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
+            &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
+        ) if a_def_id == b_def_id => infcx.super_combine_tys(this, a, b),
+        (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
+        | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
+            if this.define_opaque_types() && def_id.is_local() =>
         {
             this.add_obligations(
                 infcx
index 97ed4729bd0d9e67af8250645909cc3ba567950a..c07ac1d3ace92a4375b03797534a725c7b26911e 100644 (file)
@@ -103,6 +103,11 @@ fn binders<T>(
     where
         T: Relate<'tcx>,
     {
+        // LUB of a binder and itself is just itself
+        if a == b {
+            return Ok(a);
+        }
+
         debug!("binders(a={:?}, b={:?})", a, b);
         if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() {
             // When higher-ranked types are involved, computing the LUB is
index 2ce7cd8beba98a5e8cf4f154161e0e325df5f484..268b3bf1dcd4b23c01fe1d69f15e3d1b528a3133 100644 (file)
@@ -1920,7 +1920,7 @@ pub fn poly_trait_refs(
     ) -> TypeTrace<'tcx> {
         TypeTrace {
             cause: cause.clone(),
-            values: PolyTraitRefs(ExpectedFound::new(a_is_expected, a.into(), b.into())),
+            values: PolyTraitRefs(ExpectedFound::new(a_is_expected, a, b)),
         }
     }
 
@@ -2014,31 +2014,54 @@ fn replace_param_and_infer_substs_with_placeholder<'tcx>(
     tcx: TyCtxt<'tcx>,
     substs: SubstsRef<'tcx>,
 ) -> SubstsRef<'tcx> {
-    tcx.mk_substs(substs.iter().enumerate().map(|(idx, arg)| {
-        match arg.unpack() {
-            GenericArgKind::Type(_) if arg.has_non_region_param() || arg.has_non_region_infer() => {
-                tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
+    struct ReplaceParamAndInferWithPlaceholder<'tcx> {
+        tcx: TyCtxt<'tcx>,
+        idx: usize,
+    }
+
+    impl<'tcx> TypeFolder<'tcx> for ReplaceParamAndInferWithPlaceholder<'tcx> {
+        fn tcx(&self) -> TyCtxt<'tcx> {
+            self.tcx
+        }
+
+        fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+            if let ty::Infer(_) = t.kind() {
+                self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
                     universe: ty::UniverseIndex::ROOT,
-                    name: ty::BoundVar::from_usize(idx),
+                    name: ty::BoundVar::from_usize({
+                        let idx = self.idx;
+                        self.idx += 1;
+                        idx
+                    }),
                 }))
-                .into()
+            } else {
+                t.super_fold_with(self)
             }
-            GenericArgKind::Const(ct) if ct.has_non_region_infer() || ct.has_non_region_param() => {
-                let ty = ct.ty();
-                // If the type references param or infer, replace that too...
+        }
+
+        fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
+            if let ty::ConstKind::Infer(_) = c.kind() {
+                let ty = c.ty();
+                // If the type references param or infer then ICE ICE ICE
                 if ty.has_non_region_param() || ty.has_non_region_infer() {
-                    bug!("const `{ct}`'s type should not reference params or types");
+                    bug!("const `{c}`'s type should not reference params or types");
                 }
-                tcx.mk_const(
+                self.tcx.mk_const(
                     ty::PlaceholderConst {
                         universe: ty::UniverseIndex::ROOT,
-                        name: ty::BoundVar::from_usize(idx),
+                        name: ty::BoundVar::from_usize({
+                            let idx = self.idx;
+                            self.idx += 1;
+                            idx
+                        }),
                     },
                     ty,
                 )
-                .into()
+            } else {
+                c.super_fold_with(self)
             }
-            _ => arg,
         }
-    }))
+    }
+
+    substs.fold_with(&mut ReplaceParamAndInferWithPlaceholder { tcx, idx: 0 })
 }
index f6bc4db0d59dfc5466f3927e3a6c10ce55d552c3..1f9d86a78d6e50912f7cc3dba6e0b006391a33aa 100644 (file)
@@ -275,13 +275,13 @@ fn push_outlives(
     ///   `ProjectionEq(projection = ?U)`, `ProjectionEq(other_projection = ?U)`.
     fn relate_projection_ty(
         &mut self,
-        projection_ty: ty::ProjectionTy<'tcx>,
+        projection_ty: ty::AliasTy<'tcx>,
         value_ty: Ty<'tcx>,
     ) -> Ty<'tcx> {
         use rustc_span::DUMMY_SP;
 
         match *value_ty.kind() {
-            ty::Projection(other_projection_ty) => {
+            ty::Alias(ty::Projection, other_projection_ty) => {
                 let var = self.infcx.next_ty_var(TypeVariableOrigin {
                     kind: TypeVariableOriginKind::MiscVariable,
                     span: DUMMY_SP,
@@ -335,7 +335,9 @@ fn relate_ty_var<PAIR: VidValuePair<'tcx>>(
                 return Ok(value_ty);
             }
 
-            ty::Projection(projection_ty) if D::normalization() == NormalizationStrategy::Lazy => {
+            ty::Alias(ty::Projection, projection_ty)
+                if D::normalization() == NormalizationStrategy::Lazy =>
+            {
                 return Ok(self.relate_projection_ty(projection_ty, self.infcx.tcx.mk_ty_var(vid)));
             }
 
@@ -406,8 +408,8 @@ fn relate_opaques(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<
             }
         };
         let (a, b) = match (a.kind(), b.kind()) {
-            (&ty::Opaque(..), _) => (a, generalize(b, false)?),
-            (_, &ty::Opaque(..)) => (generalize(a, true)?, b),
+            (&ty::Alias(ty::Opaque, ..), _) => (a, generalize(b, false)?),
+            (_, &ty::Alias(ty::Opaque, ..)) => (generalize(a, true)?, b),
             _ => unreachable!(),
         };
         let cause = ObligationCause::dummy_with_span(self.delegate.span());
@@ -608,26 +610,30 @@ fn tys(&mut self, a: Ty<'tcx>, mut b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>>
 
             (&ty::Infer(ty::TyVar(vid)), _) => self.relate_ty_var((vid, b)),
 
-            (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => {
-                infcx.super_combine_tys(self, a, b).or_else(|err| {
-                    self.tcx().sess.delay_span_bug(
-                        self.delegate.span(),
-                        "failure to relate an opaque to itself should result in an error later on",
-                    );
-                    if a_def_id.is_local() { self.relate_opaques(a, b) } else { Err(err) }
-                })
-            }
-            (&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..)) if did.is_local() => {
+            (
+                &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
+                &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
+            ) if a_def_id == b_def_id => infcx.super_combine_tys(self, a, b).or_else(|err| {
+                self.tcx().sess.delay_span_bug(
+                    self.delegate.span(),
+                    "failure to relate an opaque to itself should result in an error later on",
+                );
+                if a_def_id.is_local() { self.relate_opaques(a, b) } else { Err(err) }
+            }),
+            (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
+            | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
+                if def_id.is_local() =>
+            {
                 self.relate_opaques(a, b)
             }
 
-            (&ty::Projection(projection_ty), _)
+            (&ty::Alias(ty::Projection, projection_ty), _)
                 if D::normalization() == NormalizationStrategy::Lazy =>
             {
                 Ok(self.relate_projection_ty(projection_ty, b))
             }
 
-            (_, &ty::Projection(projection_ty))
+            (_, &ty::Alias(ty::Projection, projection_ty))
                 if D::normalization() == NormalizationStrategy::Lazy =>
             {
                 Ok(self.relate_projection_ty(projection_ty, a))
diff --git a/compiler/rustc_infer/src/infer/note.rs b/compiler/rustc_infer/src/infer/note.rs
new file mode 100644 (file)
index 0000000..2ccbd16
--- /dev/null
@@ -0,0 +1,203 @@
+impl<'tcx> TypeErrCtxt<'_, 'tcx> {
+    fn note_error_origin(
+        &self,
+        err: &mut Diagnostic,
+        cause: &ObligationCause<'tcx>,
+        exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>,
+        terr: TypeError<'tcx>,
+    ) {
+        match *cause.code() {
+            ObligationCauseCode::Pattern { origin_expr: true, span: Some(span), root_ty } => {
+                let ty = self.resolve_vars_if_possible(root_ty);
+                if !matches!(ty.kind(), ty::Infer(ty::InferTy::TyVar(_) | ty::InferTy::FreshTy(_)))
+                {
+                    // don't show type `_`
+                    if span.desugaring_kind() == Some(DesugaringKind::ForLoop)
+                        && let ty::Adt(def, substs) = ty.kind()
+                        && Some(def.did()) == self.tcx.get_diagnostic_item(sym::Option)
+                    {
+                        err.span_label(span, format!("this is an iterator with items of type `{}`", substs.type_at(0)));
+                    } else {
+                    err.span_label(span, format!("this expression has type `{}`", ty));
+                }
+                }
+                if let Some(ty::error::ExpectedFound { found, .. }) = exp_found
+                    && ty.is_box() && ty.boxed_ty() == found
+                    && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
+                {
+                    err.span_suggestion(
+                        span,
+                        "consider dereferencing the boxed value",
+                        format!("*{}", snippet),
+                        Applicability::MachineApplicable,
+                    );
+                }
+            }
+            ObligationCauseCode::Pattern { origin_expr: false, span: Some(span), .. } => {
+                err.span_label(span, "expected due to this");
+            }
+            ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
+                arm_block_id,
+                arm_span,
+                arm_ty,
+                prior_arm_block_id,
+                prior_arm_span,
+                prior_arm_ty,
+                source,
+                ref prior_arms,
+                scrut_hir_id,
+                opt_suggest_box_span,
+                scrut_span,
+                ..
+            }) => match source {
+                hir::MatchSource::TryDesugar => {
+                    if let Some(ty::error::ExpectedFound { expected, .. }) = exp_found {
+                        let scrut_expr = self.tcx.hir().expect_expr(scrut_hir_id);
+                        let scrut_ty = if let hir::ExprKind::Call(_, args) = &scrut_expr.kind {
+                            let arg_expr = args.first().expect("try desugaring call w/out arg");
+                            self.typeck_results.as_ref().and_then(|typeck_results| {
+                                typeck_results.expr_ty_opt(arg_expr)
+                            })
+                        } else {
+                            bug!("try desugaring w/out call expr as scrutinee");
+                        };
+
+                        match scrut_ty {
+                            Some(ty) if expected == ty => {
+                                let source_map = self.tcx.sess.source_map();
+                                err.span_suggestion(
+                                    source_map.end_point(cause.span),
+                                    "try removing this `?`",
+                                    "",
+                                    Applicability::MachineApplicable,
+                                );
+                            }
+                            _ => {}
+                        }
+                    }
+                }
+                _ => {
+                    // `prior_arm_ty` can be `!`, `expected` will have better info when present.
+                    let t = self.resolve_vars_if_possible(match exp_found {
+                        Some(ty::error::ExpectedFound { expected, .. }) => expected,
+                        _ => prior_arm_ty,
+                    });
+                    let source_map = self.tcx.sess.source_map();
+                    let mut any_multiline_arm = source_map.is_multiline(arm_span);
+                    if prior_arms.len() <= 4 {
+                        for sp in prior_arms {
+                            any_multiline_arm |= source_map.is_multiline(*sp);
+                            err.span_label(*sp, format!("this is found to be of type `{}`", t));
+                        }
+                    } else if let Some(sp) = prior_arms.last() {
+                        any_multiline_arm |= source_map.is_multiline(*sp);
+                        err.span_label(
+                            *sp,
+                            format!("this and all prior arms are found to be of type `{}`", t),
+                        );
+                    }
+                    let outer_error_span = if any_multiline_arm {
+                        // Cover just `match` and the scrutinee expression, not
+                        // the entire match body, to reduce diagram noise.
+                        cause.span.shrink_to_lo().to(scrut_span)
+                    } else {
+                        cause.span
+                    };
+                    let msg = "`match` arms have incompatible types";
+                    err.span_label(outer_error_span, msg);
+                    self.suggest_remove_semi_or_return_binding(
+                        err,
+                        prior_arm_block_id,
+                        prior_arm_ty,
+                        prior_arm_span,
+                        arm_block_id,
+                        arm_ty,
+                        arm_span,
+                    );
+                    if let Some(ret_sp) = opt_suggest_box_span {
+                        // Get return type span and point to it.
+                        self.suggest_boxing_for_return_impl_trait(
+                            err,
+                            ret_sp,
+                            prior_arms.iter().chain(std::iter::once(&arm_span)).map(|s| *s),
+                        );
+                    }
+                }
+            },
+            ObligationCauseCode::IfExpression(box IfExpressionCause {
+                then_id,
+                else_id,
+                then_ty,
+                else_ty,
+                outer_span,
+                opt_suggest_box_span,
+            }) => {
+                let then_span = self.find_block_span_from_hir_id(then_id);
+                let else_span = self.find_block_span_from_hir_id(else_id);
+                err.span_label(then_span, "expected because of this");
+                if let Some(sp) = outer_span {
+                    err.span_label(sp, "`if` and `else` have incompatible types");
+                }
+                self.suggest_remove_semi_or_return_binding(
+                    err,
+                    Some(then_id),
+                    then_ty,
+                    then_span,
+                    Some(else_id),
+                    else_ty,
+                    else_span,
+                );
+                if let Some(ret_sp) = opt_suggest_box_span {
+                    self.suggest_boxing_for_return_impl_trait(
+                        err,
+                        ret_sp,
+                        [then_span, else_span].into_iter(),
+                    );
+                }
+            }
+            ObligationCauseCode::LetElse => {
+                err.help("try adding a diverging expression, such as `return` or `panic!(..)`");
+                err.help("...or use `match` instead of `let...else`");
+            }
+            _ => {
+                if let ObligationCauseCode::BindingObligation(_, span)
+                | ObligationCauseCode::ExprBindingObligation(_, span, ..)
+                = cause.code().peel_derives()
+                    && let TypeError::RegionsPlaceholderMismatch = terr
+                {
+                    err.span_note( * span,
+                    "the lifetime requirement is introduced here");
+                }
+            }
+        }
+    }
+}
+
+impl<'tcx> InferCtxt<'tcx> {
+    /// Given a [`hir::Block`], get the span of its last expression or
+    /// statement, peeling off any inner blocks.
+    pub fn find_block_span(&self, block: &'tcx hir::Block<'tcx>) -> Span {
+        let block = block.innermost_block();
+        if let Some(expr) = &block.expr {
+            expr.span
+        } else if let Some(stmt) = block.stmts.last() {
+            // possibly incorrect trailing `;` in the else arm
+            stmt.span
+        } else {
+            // empty block; point at its entirety
+            block.span
+        }
+    }
+
+    /// Given a [`hir::HirId`] for a block, get the span of its last expression
+    /// or statement, peeling off any inner blocks.
+    pub fn find_block_span_from_hir_id(&self, hir_id: hir::HirId) -> Span {
+        match self.tcx.hir().get(hir_id) {
+            hir::Node::Block(blk) => self.find_block_span(blk),
+            // The parser was in a weird state if either of these happen, but
+            // it's better not to panic.
+            hir::Node::Expr(e) => e.span,
+            _ => rustc_span::DUMMY_SP,
+        }
+    }
+}
index 524f7a39ebbfb8f72077340dd534b13d8aafa330..a130fde47ed5c4d7c0ccdae1536387b649f7cc1b 100644 (file)
@@ -66,7 +66,9 @@ pub fn replace_opaque_types_with_inference_vars<T: TypeFoldable<'tcx>>(
             lt_op: |lt| lt,
             ct_op: |ct| ct,
             ty_op: |ty| match *ty.kind() {
-                ty::Opaque(def_id, _substs) if replace_opaque_type(def_id) => {
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })
+                    if replace_opaque_type(def_id) =>
+                {
                     let def_span = self.tcx.def_span(def_id);
                     let span = if span.contains(def_span) { def_span } else { span };
                     let code = traits::ObligationCauseCode::OpaqueReturnType(None);
@@ -104,7 +106,7 @@ pub fn handle_opaque_type(
         }
         let (a, b) = if a_is_expected { (a, b) } else { (b, a) };
         let process = |a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected| match *a.kind() {
-            ty::Opaque(def_id, substs) if def_id.is_local() => {
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) if def_id.is_local() => {
                 let def_id = def_id.expect_local();
                 let origin = match self.defining_use_anchor {
                     DefiningAnchor::Bind(_) => {
@@ -147,18 +149,19 @@ pub fn handle_opaque_type(
                     DefiningAnchor::Bubble => self.opaque_ty_origin_unchecked(def_id, cause.span),
                     DefiningAnchor::Error => return None,
                 };
-                if let ty::Opaque(did2, _) = *b.kind() {
+                if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }) = *b.kind() {
                     // We could accept this, but there are various ways to handle this situation, and we don't
                     // want to make a decision on it right now. Likely this case is so super rare anyway, that
                     // no one encounters it in practice.
                     // It does occur however in `fn fut() -> impl Future<Output = i32> { async { 42 } }`,
                     // where it is of no concern, so we only check for TAITs.
-                    if let Some(OpaqueTyOrigin::TyAlias) =
-                        did2.as_local().and_then(|did2| self.opaque_type_origin(did2, cause.span))
+                    if let Some(OpaqueTyOrigin::TyAlias) = b_def_id
+                        .as_local()
+                        .and_then(|b_def_id| self.opaque_type_origin(b_def_id, cause.span))
                     {
                         self.tcx.sess.emit_err(OpaqueHiddenTypeDiag {
                             span: cause.span,
-                            hidden_type: self.tcx.def_span(did2),
+                            hidden_type: self.tcx.def_span(b_def_id),
                             opaque_type: self.tcx.def_span(def_id),
                         });
                     }
@@ -475,7 +478,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
                 substs.as_generator().resume_ty().visit_with(self);
             }
 
-            ty::Opaque(def_id, ref substs) => {
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, ref substs, .. }) => {
                 // Skip lifetime paramters that are not captures.
                 let variances = self.tcx.variances_of(*def_id);
 
@@ -486,11 +489,11 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
                 }
             }
 
-            ty::Projection(proj)
-                if self.tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder =>
+            ty::Alias(ty::Projection, proj)
+                if self.tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder =>
             {
                 // Skip lifetime paramters that are not captures.
-                let variances = self.tcx.variances_of(proj.item_def_id);
+                let variances = self.tcx.variances_of(proj.def_id);
 
                 for (v, s) in std::iter::zip(variances, proj.substs.iter()) {
                     if *v != ty::Variance::Bivariant {
@@ -563,9 +566,9 @@ fn register_hidden_type(
                     // We can't normalize associated types from `rustc_infer`,
                     // but we can eagerly register inference variables for them.
                     // FIXME(RPITIT): Don't replace RPITITs with inference vars.
-                    ty::Projection(projection_ty)
+                    ty::Alias(ty::Projection, projection_ty)
                         if !projection_ty.has_escaping_bound_vars()
-                            && tcx.def_kind(projection_ty.item_def_id)
+                            && tcx.def_kind(projection_ty.def_id)
                                 != DefKind::ImplTraitPlaceholder =>
                     {
                         self.infer_projection(
@@ -578,17 +581,16 @@ fn register_hidden_type(
                     }
                     // Replace all other mentions of the same opaque type with the hidden type,
                     // as the bounds must hold on the hidden type after all.
-                    ty::Opaque(def_id2, substs2)
+                    ty::Alias(ty::Opaque, ty::AliasTy { def_id: def_id2, substs: substs2, .. })
                         if def_id.to_def_id() == def_id2 && substs == substs2 =>
                     {
                         hidden_ty
                     }
                     // FIXME(RPITIT): This can go away when we move to associated types
-                    ty::Projection(proj)
-                        if def_id.to_def_id() == proj.item_def_id && substs == proj.substs =>
-                    {
-                        hidden_ty
-                    }
+                    ty::Alias(
+                        ty::Projection,
+                        ty::AliasTy { def_id: def_id2, substs: substs2, .. },
+                    ) if def_id.to_def_id() == def_id2 && substs == substs2 => hidden_ty,
                     _ => ty,
                 },
                 lt_op: |lt| lt,
index 14ee9f05190102b8f7067bf28a1f56a7b332b9b5..aa2b5d067d266d8742c322ea147ffe5bc4905442 100644 (file)
@@ -23,7 +23,7 @@ pub enum Component<'tcx> {
     // is not in a position to judge which is the best technique, so
     // we just product the projection as a component and leave it to
     // the consumer to decide (but see `EscapingProjection` below).
-    Projection(ty::ProjectionTy<'tcx>),
+    Projection(ty::AliasTy<'tcx>),
 
     // In the case where a projection has escaping regions -- meaning
     // regions bound within the type itself -- we always use
@@ -130,7 +130,7 @@ fn compute_components<'tcx>(
             // outlives any other lifetime, which is unsound.
             // See https://github.com/rust-lang/rust/issues/84305 for
             // more details.
-            ty::Opaque(def_id, substs) => {
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
                 out.push(Component::Opaque(def_id, substs));
             },
 
@@ -142,7 +142,7 @@ fn compute_components<'tcx>(
             // trait-ref. Therefore, if we see any higher-ranked regions,
             // we simply fallback to the most restrictive rule, which
             // requires that `Pi: 'a` for all `i`.
-            ty::Projection(ref data) => {
+            ty::Alias(ty::Projection, ref data) => {
                 if !data.has_escaping_bound_vars() {
                     // best case: no escaping regions, so push the
                     // projection and skip the subtree (thus generating no
index 6ca884799aa6fb3b77b5891c6ff20175f9aab922..ccae7165d80d2fac9d859c26b64031742bcbd244 100644 (file)
@@ -338,7 +338,7 @@ fn opaque_must_outlive(
             substs,
             true,
             |ty| match *ty.kind() {
-                ty::Opaque(def_id, substs) => (def_id, substs),
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => (def_id, substs),
                 _ => bug!("expected only projection types from env, not {:?}", ty),
             },
         );
@@ -349,17 +349,19 @@ fn projection_must_outlive(
         &mut self,
         origin: infer::SubregionOrigin<'tcx>,
         region: ty::Region<'tcx>,
-        projection_ty: ty::ProjectionTy<'tcx>,
+        projection_ty: ty::AliasTy<'tcx>,
     ) {
         self.generic_must_outlive(
             origin,
             region,
             GenericKind::Projection(projection_ty),
-            projection_ty.item_def_id,
+            projection_ty.def_id,
             projection_ty.substs,
             false,
             |ty| match ty.kind() {
-                ty::Projection(projection_ty) => (projection_ty.item_def_id, projection_ty.substs),
+                ty::Alias(ty::Projection, projection_ty) => {
+                    (projection_ty.def_id, projection_ty.substs)
+                }
                 _ => bug!("expected only projection types from env, not {:?}", ty),
             },
         );
index f470b2eb8c1939a4acef1abd6f12e7b4c6a35b97..136da4a3cb12a110eaaffd96606370628219f855 100644 (file)
@@ -178,7 +178,7 @@ fn bound_from_single_component(
             ),
             Component::Projection(projection_ty) => self.projection_opaque_bounds(
                 GenericKind::Projection(projection_ty),
-                projection_ty.item_def_id,
+                projection_ty.def_id,
                 projection_ty.substs,
                 visited,
             ),
index eb6deee291cf7ab1b236be9e1c9283348538ee82..4667d99ff00080daacd1ad224218c596b48fb987 100644 (file)
@@ -16,12 +16,12 @@ impl<'tcx> InferCtxt<'tcx> {
     pub fn infer_projection(
         &self,
         param_env: ty::ParamEnv<'tcx>,
-        projection_ty: ty::ProjectionTy<'tcx>,
+        projection_ty: ty::AliasTy<'tcx>,
         cause: ObligationCause<'tcx>,
         recursion_depth: usize,
         obligations: &mut Vec<PredicateObligation<'tcx>>,
     ) -> Ty<'tcx> {
-        let def_id = projection_ty.item_def_id;
+        let def_id = projection_ty.def_id;
         let ty_var = self.next_ty_var(TypeVariableOrigin {
             kind: TypeVariableOriginKind::NormalizeProjectionType,
             span: self.tcx.def_span(def_id),
index 985c5d360db8e814b4a7b9b7e69924e2ae9fabcc..9a427ceacd0a7c63737805a2cb370adfa6788d7c 100644 (file)
@@ -169,7 +169,7 @@ pub struct Verify<'tcx> {
 #[derive(Copy, Clone, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)]
 pub enum GenericKind<'tcx> {
     Param(ty::ParamTy),
-    Projection(ty::ProjectionTy<'tcx>),
+    Projection(ty::AliasTy<'tcx>),
     Opaque(DefId, SubstsRef<'tcx>),
 }
 
@@ -773,7 +773,7 @@ impl<'tcx> GenericKind<'tcx> {
     pub fn to_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
         match *self {
             GenericKind::Param(ref p) => p.to_ty(tcx),
-            GenericKind::Projection(ref p) => tcx.mk_projection(p.item_def_id, p.substs),
+            GenericKind::Projection(ref p) => tcx.mk_projection(p.def_id, p.substs),
             GenericKind::Opaque(def_id, substs) => tcx.mk_opaque(def_id, substs),
         }
     }
index 2c6987cc3f45670d5290b6ba8d04ecc9d3d0aae2..bd38b52ba34a7eab0fbcbae019d94d58dd0d2c40 100644 (file)
@@ -130,12 +130,16 @@ fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
                 Ok(self.tcx().ty_error_with_guaranteed(e))
             }
 
-            (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => {
+            (
+                &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
+                &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
+            ) if a_def_id == b_def_id => {
                 self.fields.infcx.super_combine_tys(self, a, b)?;
                 Ok(a)
             }
-            (&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..))
-                if self.fields.define_opaque_types && did.is_local() =>
+            (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
+            | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
+                if self.fields.define_opaque_types && def_id.is_local() =>
             {
                 self.fields.obligations.extend(
                     infcx
@@ -213,6 +217,11 @@ fn binders<T>(
     where
         T: Relate<'tcx>,
     {
+        // A binder is always a subtype of itself if it's structually equal to itself
+        if a == b {
+            return Ok(a);
+        }
+
         self.fields.higher_ranked_sub(a, b, self.a_is_expected)?;
         Ok(a)
     }
index 5d22f9f972e10626b34adecb59283ba04905db0e..ac455055b430375ce8aa245d092498ed9a67e199 100644 (file)
@@ -77,11 +77,11 @@ pub struct ProjectionCacheStorage<'tcx> {
 
 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
 pub struct ProjectionCacheKey<'tcx> {
-    ty: ty::ProjectionTy<'tcx>,
+    ty: ty::AliasTy<'tcx>,
 }
 
 impl<'tcx> ProjectionCacheKey<'tcx> {
-    pub fn new(ty: ty::ProjectionTy<'tcx>) -> Self {
+    pub fn new(ty: ty::AliasTy<'tcx>) -> Self {
         Self { ty }
     }
 }
@@ -200,7 +200,7 @@ pub fn insert_term(
     pub fn complete(&mut self, key: ProjectionCacheKey<'tcx>, result: EvaluationResult) {
         let mut map = self.map();
         match map.get(&key) {
-            Some(&ProjectionCacheEntry::NormalizedTy { ref ty, complete: _ }) => {
+            Some(ProjectionCacheEntry::NormalizedTy { ty, complete: _ }) => {
                 info!("ProjectionCacheEntry::complete({:?}) - completing {:?}", key, ty);
                 let mut ty = ty.clone();
                 if result.must_apply_considering_regions() {
index 512e6079f43a02fa7ada619ec45164ccce254748..8f0bd3a9abe5e29ac32a3a754f3516790bd9a4c6 100644 (file)
@@ -259,8 +259,7 @@ fn elaborate(&mut self, obligation: &PredicateObligation<'tcx>) {
                             Component::Projection(projection) => {
                                 // We might end up here if we have `Foo<<Bar as Baz>::Assoc>: 'a`.
                                 // With this, we can deduce that `<Bar as Baz>::Assoc: 'a`.
-                                let ty =
-                                    tcx.mk_projection(projection.item_def_id, projection.substs);
+                                let ty = tcx.mk_projection(projection.def_id, projection.substs);
                                 Some(ty::PredicateKind::Clause(ty::Clause::TypeOutlives(
                                     ty::OutlivesPredicate(ty, r_min),
                                 )))
index f75c8669fa1e1efb1ec7c6cbe6990cc10fe4412f..89d9450cf4e89a0b6335647b5bf5f2446f7207bd 100644 (file)
@@ -158,7 +158,7 @@ pub fn create_resolver(
     sess: Lrc<Session>,
     metadata_loader: Box<MetadataLoaderDyn>,
     krate: &ast::Crate,
-    crate_name: &str,
+    crate_name: Symbol,
 ) -> BoxedResolver {
     trace!("create_resolver");
     BoxedResolver::new(sess, move |sess, resolver_arenas| {
@@ -171,7 +171,7 @@ pub fn register_plugins<'a>(
     metadata_loader: &'a dyn MetadataLoader,
     register_lints: impl Fn(&Session, &mut LintStore),
     mut krate: ast::Crate,
-    crate_name: &str,
+    crate_name: Symbol,
 ) -> Result<(ast::Crate, LintStore)> {
     krate = sess.time("attributes_injection", || {
         rustc_builtin_macros::cmdline_attrs::inject(
@@ -228,19 +228,21 @@ fn pre_expansion_lint<'a>(
     lint_store: &LintStore,
     registered_tools: &RegisteredTools,
     check_node: impl EarlyCheckNode<'a>,
-    node_name: &str,
+    node_name: Symbol,
 ) {
-    sess.prof.generic_activity_with_arg("pre_AST_expansion_lint_checks", node_name).run(|| {
-        rustc_lint::check_ast_node(
-            sess,
-            true,
-            lint_store,
-            registered_tools,
-            None,
-            rustc_lint::BuiltinCombinedPreExpansionLintPass::new(),
-            check_node,
-        );
-    });
+    sess.prof.generic_activity_with_arg("pre_AST_expansion_lint_checks", node_name.as_str()).run(
+        || {
+            rustc_lint::check_ast_node(
+                sess,
+                true,
+                lint_store,
+                registered_tools,
+                None,
+                rustc_lint::BuiltinCombinedPreExpansionLintPass::new(),
+                check_node,
+            );
+        },
+    );
 }
 
 // Cannot implement directly for `LintStore` due to trait coherence.
@@ -254,7 +256,7 @@ fn pre_expansion_lint(
         node_id: ast::NodeId,
         attrs: &[ast::Attribute],
         items: &[rustc_ast::ptr::P<ast::Item>],
-        name: &str,
+        name: Symbol,
     ) {
         pre_expansion_lint(sess, self.0, registered_tools, (node_id, attrs, items), name);
     }
@@ -268,7 +270,7 @@ pub fn configure_and_expand(
     sess: &Session,
     lint_store: &LintStore,
     mut krate: ast::Crate,
-    crate_name: &str,
+    crate_name: Symbol,
     resolver: &mut Resolver<'_>,
 ) -> Result<ast::Crate> {
     trace!("configure_and_expand");
@@ -462,7 +464,7 @@ fn generated_output_paths(
     sess: &Session,
     outputs: &OutputFilenames,
     exact_name: bool,
-    crate_name: &str,
+    crate_name: Symbol,
 ) -> Vec<PathBuf> {
     let mut out_filenames = Vec::new();
     for output_type in sess.opts.output_types.keys() {
@@ -661,7 +663,7 @@ pub fn prepare_outputs(
     compiler: &Compiler,
     krate: &ast::Crate,
     boxed_resolver: &RefCell<BoxedResolver>,
-    crate_name: &str,
+    crate_name: Symbol,
 ) -> Result<OutputFilenames> {
     let _timer = sess.timer("prepare_outputs");
 
@@ -771,7 +773,7 @@ pub fn create_global_ctxt<'tcx>(
     dep_graph: DepGraph,
     resolver: Rc<RefCell<BoxedResolver>>,
     outputs: OutputFilenames,
-    crate_name: &str,
+    crate_name: Symbol,
     queries: &'tcx OnceCell<TcxQueries<'tcx>>,
     global_ctxt: &'tcx OnceCell<GlobalCtxt<'tcx>>,
     arena: &'tcx WorkerLocal<Arena<'tcx>>,
@@ -803,9 +805,9 @@ pub fn create_global_ctxt<'tcx>(
     });
 
     let ty::ResolverOutputs {
-        definitions,
         global_ctxt: untracked_resolutions,
         ast_lowering: untracked_resolver_for_lowering,
+        untracked,
     } = resolver_outputs;
 
     let gcx = sess.time("setup_global_ctxt", || {
@@ -815,8 +817,8 @@ pub fn create_global_ctxt<'tcx>(
                 lint_store,
                 arena,
                 hir_arena,
-                definitions,
                 untracked_resolutions,
+                untracked,
                 krate,
                 dep_graph,
                 queries.on_disk_cache.as_ref().map(OnDiskCache::as_dyn),
index f5ddd647b2435f157d4645fcf4107c11cd639f93..39e1f2204b002010176277dadfb531098f096730 100644 (file)
@@ -17,6 +17,7 @@
 use rustc_session::config::{self, OutputFilenames, OutputType};
 use rustc_session::{output::find_crate_name, Session};
 use rustc_span::symbol::sym;
+use rustc_span::Symbol;
 use std::any::Any;
 use std::cell::{Ref, RefCell, RefMut};
 use std::rc::Rc;
@@ -74,7 +75,7 @@ pub struct Queries<'tcx> {
 
     dep_graph_future: Query<Option<DepGraphFuture>>,
     parse: Query<ast::Crate>,
-    crate_name: Query<String>,
+    crate_name: Query<Symbol>,
     register_plugins: Query<(ast::Crate, Lrc<LintStore>)>,
     expansion: Query<(Lrc<ast::Crate>, Rc<RefCell<BoxedResolver>>, Lrc<LintStore>)>,
     dep_graph: Query<DepGraph>,
@@ -135,7 +136,7 @@ pub fn register_plugins(&self) -> Result<&Query<(ast::Crate, Lrc<LintStore>)>> {
                 &*self.codegen_backend().metadata_loader(),
                 self.compiler.register_lints.as_deref().unwrap_or_else(|| empty),
                 krate,
-                &crate_name,
+                crate_name,
             )?;
 
             // Compute the dependency graph (in the background). We want to do
@@ -149,7 +150,7 @@ pub fn register_plugins(&self) -> Result<&Query<(ast::Crate, Lrc<LintStore>)>> {
         })
     }
 
-    pub fn crate_name(&self) -> Result<&Query<String>> {
+    pub fn crate_name(&self) -> Result<&Query<Symbol>> {
         self.crate_name.compute(|| {
             Ok({
                 let parse_result = self.parse()?;
@@ -165,7 +166,7 @@ pub fn expansion(
     ) -> Result<&Query<(Lrc<ast::Crate>, Rc<RefCell<BoxedResolver>>, Lrc<LintStore>)>> {
         trace!("expansion");
         self.expansion.compute(|| {
-            let crate_name = self.crate_name()?.peek().clone();
+            let crate_name = *self.crate_name()?.peek();
             let (krate, lint_store) = self.register_plugins()?.take();
             let _timer = self.session().timer("configure_and_expand");
             let sess = self.session();
@@ -173,10 +174,10 @@ pub fn expansion(
                 sess.clone(),
                 self.codegen_backend().metadata_loader(),
                 &krate,
-                &crate_name,
+                crate_name,
             );
             let krate = resolver.access(|resolver| {
-                passes::configure_and_expand(sess, &lint_store, krate, &crate_name, resolver)
+                passes::configure_and_expand(sess, &lint_store, krate, crate_name, resolver)
             })?;
             Ok((Lrc::new(krate), Rc::new(RefCell::new(resolver)), lint_store))
         })
@@ -201,20 +202,20 @@ fn dep_graph(&self) -> Result<&Query<DepGraph>> {
     pub fn prepare_outputs(&self) -> Result<&Query<OutputFilenames>> {
         self.prepare_outputs.compute(|| {
             let (krate, boxed_resolver, _) = &*self.expansion()?.peek();
-            let crate_name = self.crate_name()?.peek();
+            let crate_name = *self.crate_name()?.peek();
             passes::prepare_outputs(
                 self.session(),
                 self.compiler,
                 krate,
                 &*boxed_resolver,
-                &crate_name,
+                crate_name,
             )
         })
     }
 
     pub fn global_ctxt(&'tcx self) -> Result<&Query<QueryContext<'tcx>>> {
         self.global_ctxt.compute(|| {
-            let crate_name = self.crate_name()?.peek().clone();
+            let crate_name = *self.crate_name()?.peek();
             let outputs = self.prepare_outputs()?.take();
             let dep_graph = self.dep_graph()?.peek().clone();
             let (krate, resolver, lint_store) = self.expansion()?.take();
@@ -225,7 +226,7 @@ pub fn global_ctxt(&'tcx self) -> Result<&Query<QueryContext<'tcx>>> {
                 dep_graph,
                 resolver,
                 outputs,
-                &crate_name,
+                crate_name,
                 &self.queries,
                 &self.gcx,
                 &self.arena,
index 2b8f6557c829b32042879be2c525ed09e4fbef8f..e903cb86dd20438a9264fcdf67bfedf6f3783cb4 100644 (file)
@@ -25,7 +25,6 @@
 use rustc_target::spec::{RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel};
 
 use std::collections::{BTreeMap, BTreeSet};
-use std::iter::FromIterator;
 use std::num::NonZeroUsize;
 use std::path::{Path, PathBuf};
 
index 3fbabbc6344a7f3518b10e11b1869bb78d9fd948..50d6d5b9bab91a0bc08807c708ad7f02858d2842 100644 (file)
@@ -34,7 +34,6 @@
 use self::LiteralKind::*;
 use self::TokenKind::*;
 use crate::cursor::EOF_CHAR;
-use std::convert::TryFrom;
 
 /// Parsed token.
 /// It doesn't contain information about data that has been parsed,
index e405013dcabf83047cb34a88c635e6d4d7ec8a28..87c44638a8de1918883375cd0d6357dfebd8a16b 100644 (file)
@@ -204,14 +204,13 @@ fn scan_escape(chars: &mut Chars<'_>, is_byte: bool) -> Result<char, EscapeError
                         })?;
                     }
                     Some(c) => {
-                        let digit =
+                        let digit: u32 =
                             c.to_digit(16).ok_or(EscapeError::InvalidCharInUnicodeEscape)?;
                         n_digits += 1;
                         if n_digits > 6 {
                             // Stop updating value since we're sure that it's incorrect already.
                             continue;
                         }
-                        let digit = digit as u32;
                         value = value * 16 + digit;
                     }
                 };
index 825093384fba7f4688948e4f1eb963decf7fc9e3..43862570e80954aa8c11dbd80e4aa4e060e66ed9 100644 (file)
@@ -53,7 +53,8 @@
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{BytePos, InnerSpan, Span};
 use rustc_target::abi::{Abi, VariantIdx};
-use rustc_trait_selection::traits::{self, misc::can_type_implement_copy};
+use rustc_trait_selection::infer::{InferCtxtExt, TyCtxtInferExt};
+use rustc_trait_selection::traits::{self, misc::can_type_implement_copy, EvaluationResult};
 
 use crate::nonstandard_style::{method_context, MethodLateContext};
 
@@ -96,6 +97,7 @@ fn pierce_parens(mut expr: &ast::Expr) -> &ast::Expr {
 }
 
 impl EarlyLintPass for WhileTrue {
+    #[inline]
     fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
         if let ast::ExprKind::While(cond, _, label) = &e.kind
             && let cond = pierce_parens(cond)
@@ -259,7 +261,7 @@ fn check_pat(&mut self, cx: &LateContext<'_>, pat: &hir::Pat<'_>) {
                 }
                 if let PatKind::Binding(binding_annot, _, ident, None) = fieldpat.pat.kind {
                     if cx.tcx.find_field_index(ident, &variant)
-                        == Some(cx.tcx.field_index(fieldpat.hir_id, cx.typeck_results()))
+                        == Some(cx.typeck_results().field_index(fieldpat.hir_id))
                     {
                         cx.struct_span_lint(
                             NON_SHORTHAND_FIELD_PATTERNS,
@@ -360,6 +362,7 @@ fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) {
         }
     }
 
+    #[inline]
     fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
         if let ast::ExprKind::Block(ref blk, _) = e.kind {
             // Don't warn about generated blocks; that'll just pollute the output.
@@ -582,6 +585,7 @@ fn check_missing_docs_attrs(
 }
 
 impl<'tcx> LateLintPass<'tcx> for MissingDoc {
+    #[inline]
     fn enter_lint_attrs(&mut self, _cx: &LateContext<'_>, attrs: &[ast::Attribute]) {
         let doc_hidden = self.doc_hidden()
             || attrs.iter().any(|attr| {
@@ -750,10 +754,39 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
         if def.has_dtor(cx.tcx) {
             return;
         }
+
+        // If the type contains a raw pointer, it may represent something like a handle,
+        // and recommending Copy might be a bad idea.
+        for field in def.all_fields() {
+            let did = field.did;
+            if cx.tcx.type_of(did).is_unsafe_ptr() {
+                return;
+            }
+        }
         let param_env = ty::ParamEnv::empty();
         if ty.is_copy_modulo_regions(cx.tcx, param_env) {
             return;
         }
+
+        // We shouldn't recommend implementing `Copy` on stateful things,
+        // such as iterators.
+        if let Some(iter_trait) = cx.tcx.get_diagnostic_item(sym::Iterator) {
+            if cx.tcx.infer_ctxt().build().type_implements_trait(iter_trait, [ty], param_env)
+                == EvaluationResult::EvaluatedToOk
+            {
+                return;
+            }
+        }
+
+        // Default value of clippy::trivially_copy_pass_by_ref
+        const MAX_SIZE: u64 = 256;
+
+        if let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes()) {
+            if size > MAX_SIZE {
+                return;
+            }
+        }
+
         if can_type_implement_copy(
             cx.tcx,
             param_env,
@@ -2983,8 +3016,8 @@ fn structurally_same_type_impl<'tcx>(
                         | (Closure(..), Closure(..))
                         | (Generator(..), Generator(..))
                         | (GeneratorWitness(..), GeneratorWitness(..))
-                        | (Projection(..), Projection(..))
-                        | (Opaque(..), Opaque(..)) => false,
+                        | (Alias(ty::Projection, ..), Alias(ty::Projection, ..))
+                        | (Alias(ty::Opaque, ..), Alias(ty::Opaque, ..)) => false,
 
                         // These definitely should have been caught above.
                         (Bool, Bool) | (Char, Char) | (Never, Never) | (Str, Str) => unreachable!(),
index e6a0d7e60ca772b10cd67b0630dbdc50724a4907..0417f375588cc8a0500e17307b1878efa69ff603 100644 (file)
@@ -438,18 +438,18 @@ pub fn check_lint_name(
                         return CheckLintNameResult::Tool(Ok(&lint_ids));
                     }
                 },
-                Some(&Id(ref id)) => return CheckLintNameResult::Tool(Ok(slice::from_ref(id))),
+                Some(Id(id)) => return CheckLintNameResult::Tool(Ok(slice::from_ref(id))),
                 // If the lint was registered as removed or renamed by the lint tool, we don't need
                 // to treat tool_lints and rustc lints different and can use the code below.
                 _ => {}
             }
         }
         match self.by_name.get(&complete_name) {
-            Some(&Renamed(ref new_name, _)) => CheckLintNameResult::Warning(
+            Some(Renamed(new_name, _)) => CheckLintNameResult::Warning(
                 format!("lint `{}` has been renamed to `{}`", complete_name, new_name),
                 Some(new_name.to_owned()),
             ),
-            Some(&Removed(ref reason)) => CheckLintNameResult::Warning(
+            Some(Removed(reason)) => CheckLintNameResult::Warning(
                 format!("lint `{}` has been removed: {}", complete_name, reason),
                 None,
             ),
@@ -470,7 +470,7 @@ pub fn check_lint_name(
                     CheckLintNameResult::Ok(&lint_ids)
                 }
             },
-            Some(&Id(ref id)) => CheckLintNameResult::Ok(slice::from_ref(id)),
+            Some(Id(id)) => CheckLintNameResult::Ok(slice::from_ref(id)),
             Some(&Ignored) => CheckLintNameResult::Ok(&[]),
         }
     }
@@ -513,7 +513,7 @@ fn check_tool_name_for_backwards_compat(
                     CheckLintNameResult::Tool(Err((Some(&lint_ids), complete_name)))
                 }
             },
-            Some(&Id(ref id)) => {
+            Some(Id(id)) => {
                 CheckLintNameResult::Tool(Err((Some(slice::from_ref(id)), complete_name)))
             }
             Some(other) => {
@@ -1258,7 +1258,7 @@ pub fn get_associated_type(
         tcx.associated_items(trait_id)
             .find_by_name_and_kind(tcx, Ident::from_str(name), ty::AssocKind::Type, trait_id)
             .and_then(|assoc| {
-                let proj = tcx.mk_projection(assoc.def_id, tcx.mk_substs_trait(self_ty, []));
+                let proj = tcx.mk_projection(assoc.def_id, [self_ty]);
                 tcx.try_normalize_erasing_regions(self.param_env, proj).ok()
             })
     }
index 52363b0be2db90fc51eb062847498a0ce8745be9..5f84d5c8b949575394d401a287bbe1b025563376 100644 (file)
 use rustc_ast::visit::{self as ast_visit, Visitor};
 use rustc_ast::{self as ast, walk_list, HasAttrs};
 use rustc_middle::ty::RegisteredTools;
-use rustc_session::lint::{BufferedEarlyLint, LintBuffer};
+use rustc_session::lint::{BufferedEarlyLint, LintBuffer, LintPass};
 use rustc_session::Session;
 use rustc_span::symbol::Ident;
 use rustc_span::Span;
 
-macro_rules! run_early_passes { ($cx:expr, $f:ident, $($args:expr),*) => ({
-    for pass in $cx.passes.iter_mut() {
-        pass.$f(&$cx.context, $($args),*);
-    }
+macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({
+    $cx.pass.$f(&$cx.context, $($args),*);
 }) }
 
-pub struct EarlyContextAndPasses<'a> {
+/// Implements the AST traversal for early lint passes. `T` provides the the
+/// `check_*` methods.
+pub struct EarlyContextAndPass<'a, T: EarlyLintPass> {
     context: EarlyContext<'a>,
-    passes: Vec<EarlyLintPassObject>,
+    pass: T,
 }
 
-impl<'a> EarlyContextAndPasses<'a> {
-    fn check_id(&mut self, id: ast::NodeId) {
+impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> {
+    // This always-inlined function is for the hot call site.
+    #[inline(always)]
+    fn inlined_check_id(&mut self, id: ast::NodeId) {
         for early_lint in self.context.buffered.take(id) {
             let BufferedEarlyLint { span, msg, node_id: _, lint_id, diagnostic } = early_lint;
             self.context.lookup_with_diagnostics(
@@ -50,6 +52,11 @@ fn check_id(&mut self, id: ast::NodeId) {
         }
     }
 
+    // This non-inlined function is for the cold call sites.
+    fn check_id(&mut self, id: ast::NodeId) {
+        self.inlined_check_id(id)
+    }
+
     /// Merge the lints specified by any lint attributes into the
     /// current lint context, call the provided function, then reset the
     /// lints in effect to their previous state.
@@ -61,29 +68,29 @@ fn with_lint_attrs<F>(&mut self, id: ast::NodeId, attrs: &'a [ast::Attribute], f
         debug!(?id);
         let push = self.context.builder.push(attrs, is_crate_node, None);
 
-        self.check_id(id);
+        self.inlined_check_id(id);
         debug!("early context: enter_attrs({:?})", attrs);
-        run_early_passes!(self, enter_lint_attrs, attrs);
+        lint_callback!(self, enter_lint_attrs, attrs);
         f(self);
         debug!("early context: exit_attrs({:?})", attrs);
-        run_early_passes!(self, exit_lint_attrs, attrs);
+        lint_callback!(self, exit_lint_attrs, attrs);
         self.context.builder.pop(push);
     }
 }
 
-impl<'a> ast_visit::Visitor<'a> for EarlyContextAndPasses<'a> {
+impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> {
     fn visit_param(&mut self, param: &'a ast::Param) {
         self.with_lint_attrs(param.id, &param.attrs, |cx| {
-            run_early_passes!(cx, check_param, param);
+            lint_callback!(cx, check_param, param);
             ast_visit::walk_param(cx, param);
         });
     }
 
     fn visit_item(&mut self, it: &'a ast::Item) {
         self.with_lint_attrs(it.id, &it.attrs, |cx| {
-            run_early_passes!(cx, check_item, it);
+            lint_callback!(cx, check_item, it);
             ast_visit::walk_item(cx, it);
-            run_early_passes!(cx, check_item_post, it);
+            lint_callback!(cx, check_item_post, it);
         })
     }
 
@@ -94,10 +101,10 @@ fn visit_foreign_item(&mut self, it: &'a ast::ForeignItem) {
     }
 
     fn visit_pat(&mut self, p: &'a ast::Pat) {
-        run_early_passes!(self, check_pat, p);
+        lint_callback!(self, check_pat, p);
         self.check_id(p.id);
         ast_visit::walk_pat(self, p);
-        run_early_passes!(self, check_pat_post, p);
+        lint_callback!(self, check_pat_post, p);
     }
 
     fn visit_pat_field(&mut self, field: &'a ast::PatField) {
@@ -113,7 +120,7 @@ fn visit_anon_const(&mut self, c: &'a ast::AnonConst) {
 
     fn visit_expr(&mut self, e: &'a ast::Expr) {
         self.with_lint_attrs(e.id, &e.attrs, |cx| {
-            run_early_passes!(cx, check_expr, e);
+            lint_callback!(cx, check_expr, e);
             ast_visit::walk_expr(cx, e);
         })
     }
@@ -134,7 +141,7 @@ fn visit_stmt(&mut self, s: &'a ast::Stmt) {
         // Note that statements get their attributes from
         // the AST struct that they wrap (e.g. an item)
         self.with_lint_attrs(s.id, s.attrs(), |cx| {
-            run_early_passes!(cx, check_stmt, s);
+            lint_callback!(cx, check_stmt, s);
             cx.check_id(s.id);
         });
         // The visitor for the AST struct wrapped
@@ -145,7 +152,7 @@ fn visit_stmt(&mut self, s: &'a ast::Stmt) {
     }
 
     fn visit_fn(&mut self, fk: ast_visit::FnKind<'a>, span: Span, id: ast::NodeId) {
-        run_early_passes!(self, check_fn, fk, span, id);
+        lint_callback!(self, check_fn, fk, span, id);
         self.check_id(id);
         ast_visit::walk_fn(self, fk);
 
@@ -173,37 +180,37 @@ fn visit_field_def(&mut self, s: &'a ast::FieldDef) {
 
     fn visit_variant(&mut self, v: &'a ast::Variant) {
         self.with_lint_attrs(v.id, &v.attrs, |cx| {
-            run_early_passes!(cx, check_variant, v);
+            lint_callback!(cx, check_variant, v);
             ast_visit::walk_variant(cx, v);
         })
     }
 
     fn visit_ty(&mut self, t: &'a ast::Ty) {
-        run_early_passes!(self, check_ty, t);
+        lint_callback!(self, check_ty, t);
         self.check_id(t.id);
         ast_visit::walk_ty(self, t);
     }
 
     fn visit_ident(&mut self, ident: Ident) {
-        run_early_passes!(self, check_ident, ident);
+        lint_callback!(self, check_ident, ident);
     }
 
     fn visit_local(&mut self, l: &'a ast::Local) {
         self.with_lint_attrs(l.id, &l.attrs, |cx| {
-            run_early_passes!(cx, check_local, l);
+            lint_callback!(cx, check_local, l);
             ast_visit::walk_local(cx, l);
         })
     }
 
     fn visit_block(&mut self, b: &'a ast::Block) {
-        run_early_passes!(self, check_block, b);
+        lint_callback!(self, check_block, b);
         self.check_id(b.id);
         ast_visit::walk_block(self, b);
     }
 
     fn visit_arm(&mut self, a: &'a ast::Arm) {
         self.with_lint_attrs(a.id, &a.attrs, |cx| {
-            run_early_passes!(cx, check_arm, a);
+            lint_callback!(cx, check_arm, a);
             ast_visit::walk_arm(cx, a);
         })
     }
@@ -222,19 +229,19 @@ fn visit_expr_post(&mut self, e: &'a ast::Expr) {
     }
 
     fn visit_generic_arg(&mut self, arg: &'a ast::GenericArg) {
-        run_early_passes!(self, check_generic_arg, arg);
+        lint_callback!(self, check_generic_arg, arg);
         ast_visit::walk_generic_arg(self, arg);
     }
 
     fn visit_generic_param(&mut self, param: &'a ast::GenericParam) {
         self.with_lint_attrs(param.id, &param.attrs, |cx| {
-            run_early_passes!(cx, check_generic_param, param);
+            lint_callback!(cx, check_generic_param, param);
             ast_visit::walk_generic_param(cx, param);
         });
     }
 
     fn visit_generics(&mut self, g: &'a ast::Generics) {
-        run_early_passes!(self, check_generics, g);
+        lint_callback!(self, check_generics, g);
         ast_visit::walk_generics(self, g);
     }
 
@@ -243,18 +250,18 @@ fn visit_where_predicate(&mut self, p: &'a ast::WherePredicate) {
     }
 
     fn visit_poly_trait_ref(&mut self, t: &'a ast::PolyTraitRef) {
-        run_early_passes!(self, check_poly_trait_ref, t);
+        lint_callback!(self, check_poly_trait_ref, t);
         ast_visit::walk_poly_trait_ref(self, t);
     }
 
     fn visit_assoc_item(&mut self, item: &'a ast::AssocItem, ctxt: ast_visit::AssocCtxt) {
         self.with_lint_attrs(item.id, &item.attrs, |cx| match ctxt {
             ast_visit::AssocCtxt::Trait => {
-                run_early_passes!(cx, check_trait_item, item);
+                lint_callback!(cx, check_trait_item, item);
                 ast_visit::walk_assoc_item(cx, item, ctxt);
             }
             ast_visit::AssocCtxt::Impl => {
-                run_early_passes!(cx, check_impl_item, item);
+                lint_callback!(cx, check_impl_item, item);
                 ast_visit::walk_assoc_item(cx, item, ctxt);
             }
         });
@@ -275,20 +282,49 @@ fn visit_path_segment(&mut self, s: &'a ast::PathSegment) {
     }
 
     fn visit_attribute(&mut self, attr: &'a ast::Attribute) {
-        run_early_passes!(self, check_attribute, attr);
+        lint_callback!(self, check_attribute, attr);
     }
 
     fn visit_mac_def(&mut self, mac: &'a ast::MacroDef, id: ast::NodeId) {
-        run_early_passes!(self, check_mac_def, mac);
+        lint_callback!(self, check_mac_def, mac);
         self.check_id(id);
     }
 
     fn visit_mac_call(&mut self, mac: &'a ast::MacCall) {
-        run_early_passes!(self, check_mac, mac);
+        lint_callback!(self, check_mac, mac);
         ast_visit::walk_mac(self, mac);
     }
 }
 
+// Combines multiple lint passes into a single pass, at runtime. Each
+// `check_foo` method in `$methods` within this pass simply calls `check_foo`
+// once per `$pass`. Compare with `declare_combined_early_lint_pass`, which is
+// similar, but combines lint passes at compile time.
+struct RuntimeCombinedEarlyLintPass<'a> {
+    passes: &'a mut [EarlyLintPassObject],
+}
+
+#[allow(rustc::lint_pass_impl_without_macro)]
+impl LintPass for RuntimeCombinedEarlyLintPass<'_> {
+    fn name(&self) -> &'static str {
+        panic!()
+    }
+}
+
+macro_rules! impl_early_lint_pass {
+    ([], [$($(#[$attr:meta])* fn $f:ident($($param:ident: $arg:ty),*);)*]) => (
+        impl EarlyLintPass for RuntimeCombinedEarlyLintPass<'_> {
+            $(fn $f(&mut self, context: &EarlyContext<'_>, $($param: $arg),*) {
+                for pass in self.passes.iter_mut() {
+                    pass.$f(context, $($param),*);
+                }
+            })*
+        }
+    )
+}
+
+crate::early_lint_methods!(impl_early_lint_pass, []);
+
 /// Early lints work on different nodes - either on the crate root, or on freshly loaded modules.
 /// This trait generalizes over those nodes.
 pub trait EarlyCheckNode<'a>: Copy {
@@ -296,7 +332,7 @@ pub trait EarlyCheckNode<'a>: Copy {
     fn attrs<'b>(self) -> &'b [ast::Attribute]
     where
         'a: 'b;
-    fn check<'b>(self, cx: &mut EarlyContextAndPasses<'b>)
+    fn check<'b, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'b, T>)
     where
         'a: 'b;
 }
@@ -311,13 +347,13 @@ fn attrs<'b>(self) -> &'b [ast::Attribute]
     {
         &self.attrs
     }
-    fn check<'b>(self, cx: &mut EarlyContextAndPasses<'b>)
+    fn check<'b, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'b, T>)
     where
         'a: 'b,
     {
-        run_early_passes!(cx, check_crate, self);
+        lint_callback!(cx, check_crate, self);
         ast_visit::walk_crate(cx, self);
-        run_early_passes!(cx, check_crate_post, self);
+        lint_callback!(cx, check_crate_post, self);
     }
 }
 
@@ -331,7 +367,7 @@ fn attrs<'b>(self) -> &'b [ast::Attribute]
     {
         self.1
     }
-    fn check<'b>(self, cx: &mut EarlyContextAndPasses<'b>)
+    fn check<'b, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'b, T>)
     where
         'a: 'b,
     {
@@ -349,21 +385,37 @@ pub fn check_ast_node<'a>(
     builtin_lints: impl EarlyLintPass + 'static,
     check_node: impl EarlyCheckNode<'a>,
 ) {
+    let context = EarlyContext::new(
+        sess,
+        !pre_expansion,
+        lint_store,
+        registered_tools,
+        lint_buffer.unwrap_or_default(),
+    );
+
+    // Note: `passes` is often empty. In that case, it's faster to run
+    // `builtin_lints` directly rather than bundling it up into the
+    // `RuntimeCombinedEarlyLintPass`.
     let passes =
         if pre_expansion { &lint_store.pre_expansion_passes } else { &lint_store.early_passes };
-    let mut passes: Vec<EarlyLintPassObject> = passes.iter().map(|p| (p)()).collect();
-    passes.push(Box::new(builtin_lints));
-
-    let mut cx = EarlyContextAndPasses {
-        context: EarlyContext::new(
-            sess,
-            !pre_expansion,
-            lint_store,
-            registered_tools,
-            lint_buffer.unwrap_or_default(),
-        ),
-        passes,
-    };
+    if passes.is_empty() {
+        check_ast_node_inner(sess, check_node, context, builtin_lints);
+    } else {
+        let mut passes: Vec<_> = passes.iter().map(|mk_pass| (mk_pass)()).collect();
+        passes.push(Box::new(builtin_lints));
+        let pass = RuntimeCombinedEarlyLintPass { passes: &mut passes[..] };
+        check_ast_node_inner(sess, check_node, context, pass);
+    }
+}
+
+pub fn check_ast_node_inner<'a, T: EarlyLintPass>(
+    sess: &Session,
+    check_node: impl EarlyCheckNode<'a>,
+    context: EarlyContext<'_>,
+    pass: T,
+) {
+    let mut cx = EarlyContextAndPass { context, pass };
+
     cx.with_lint_attrs(check_node.id(), check_node.attrs(), |cx| check_node.check(cx));
 
     // All of the buffered lints should have been emitted at this point.
index 7106e75dba290ebcac26a9deac25964eff0afaec..dc2f5c0e2967e86e45c838e288272132b5eb4bf4 100644 (file)
@@ -121,6 +121,7 @@ fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) {
         }
     }
 
+    #[inline]
     fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
         // byte strings are already handled well enough by `EscapeError::NonAsciiCharInByteString`
         match &expr.kind {
index 8a50cb1f19ef5821b843911f5d1b65d06a152344..e2876938d70566477329cc94541c81478a3894f1 100644 (file)
@@ -23,6 +23,7 @@
 use rustc_hir::intravisit::Visitor;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{self, TyCtxt};
+use rustc_session::lint::LintPass;
 use rustc_span::Span;
 
 use std::any::Any;
@@ -36,17 +37,17 @@ pub fn unerased_lint_store(tcx: TyCtxt<'_>) -> &LintStore {
 }
 
 macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({
-    for pass in $cx.passes.iter_mut() {
-        pass.$f(&$cx.context, $($args),*);
-    }
+    $cx.pass.$f(&$cx.context, $($args),*);
 }) }
 
-struct LateContextAndPasses<'tcx> {
+/// Implements the AST traversal for late lint passes. `T` provides the the
+/// `check_*` methods.
+pub struct LateContextAndPass<'tcx, T: LateLintPass<'tcx>> {
     context: LateContext<'tcx>,
-    passes: Vec<LateLintPassObject<'tcx>>,
+    pass: T,
 }
 
-impl<'tcx> LateContextAndPasses<'tcx> {
+impl<'tcx, T: LateLintPass<'tcx>> LateContextAndPass<'tcx, T> {
     /// Merge the lints specified by any lint attributes into the
     /// current lint context, call the provided function, then reset the
     /// lints in effect to their previous state.
@@ -82,7 +83,7 @@ fn process_mod(&mut self, m: &'tcx hir::Mod<'tcx>, n: hir::HirId) {
     }
 }
 
-impl<'tcx> hir_visit::Visitor<'tcx> for LateContextAndPasses<'tcx> {
+impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPass<'tcx, T> {
     type NestedFilter = nested_filter::All;
 
     /// Because lints are scoped lexically, we want to walk nested
@@ -302,6 +303,35 @@ fn visit_attribute(&mut self, attr: &'tcx ast::Attribute) {
     }
 }
 
+// Combines multiple lint passes into a single pass, at runtime. Each
+// `check_foo` method in `$methods` within this pass simply calls `check_foo`
+// once per `$pass`. Compare with `declare_combined_late_lint_pass`, which is
+// similar, but combines lint passes at compile time.
+struct RuntimeCombinedLateLintPass<'a, 'tcx> {
+    passes: &'a mut [LateLintPassObject<'tcx>],
+}
+
+#[allow(rustc::lint_pass_impl_without_macro)]
+impl LintPass for RuntimeCombinedLateLintPass<'_, '_> {
+    fn name(&self) -> &'static str {
+        panic!()
+    }
+}
+
+macro_rules! impl_late_lint_pass {
+    ([], [$($(#[$attr:meta])* fn $f:ident($($param:ident: $arg:ty),*);)*]) => {
+        impl<'tcx> LateLintPass<'tcx> for RuntimeCombinedLateLintPass<'_, 'tcx> {
+            $(fn $f(&mut self, context: &LateContext<'tcx>, $($param: $arg),*) {
+                for pass in self.passes.iter_mut() {
+                    pass.$f(context, $($param),*);
+                }
+            })*
+        }
+    };
+}
+
+crate::late_lint_methods!(impl_late_lint_pass, []);
+
 pub(super) fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>(
     tcx: TyCtxt<'tcx>,
     module_def_id: LocalDefId,
@@ -319,11 +349,27 @@ pub(super) fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>(
         only_module: true,
     };
 
+    // Note: `passes` is often empty. In that case, it's faster to run
+    // `builtin_lints` directly rather than bundling it up into the
+    // `RuntimeCombinedLateLintPass`.
     let mut passes: Vec<_> =
-        unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)(tcx)).collect();
-    passes.push(Box::new(builtin_lints));
+        unerased_lint_store(tcx).late_module_passes.iter().map(|mk_pass| (mk_pass)(tcx)).collect();
+    if passes.is_empty() {
+        late_lint_mod_inner(tcx, module_def_id, context, builtin_lints);
+    } else {
+        passes.push(Box::new(builtin_lints));
+        let pass = RuntimeCombinedLateLintPass { passes: &mut passes[..] };
+        late_lint_mod_inner(tcx, module_def_id, context, pass);
+    }
+}
 
-    let mut cx = LateContextAndPasses { context, passes };
+fn late_lint_mod_inner<'tcx, T: LateLintPass<'tcx>>(
+    tcx: TyCtxt<'tcx>,
+    module_def_id: LocalDefId,
+    context: LateContext<'tcx>,
+    pass: T,
+) {
+    let mut cx = LateContextAndPass { context, pass };
 
     let (module, _span, hir_id) = tcx.hir().get_module(module_def_id);
     cx.process_mod(module, hir_id);
@@ -349,11 +395,26 @@ fn late_lint_crate<'tcx, T: LateLintPass<'tcx> + 'tcx>(tcx: TyCtxt<'tcx>, builti
         only_module: false,
     };
 
-    let mut passes =
-        unerased_lint_store(tcx).late_passes.iter().map(|p| (p)(tcx)).collect::<Vec<_>>();
-    passes.push(Box::new(builtin_lints));
+    // Note: `passes` is often empty. In that case, it's faster to run
+    // `builtin_lints` directly rather than bundling it up into the
+    // `RuntimeCombinedLateLintPass`.
+    let mut passes: Vec<_> =
+        unerased_lint_store(tcx).late_passes.iter().map(|mk_pass| (mk_pass)(tcx)).collect();
+    if passes.is_empty() {
+        late_lint_crate_inner(tcx, context, builtin_lints);
+    } else {
+        passes.push(Box::new(builtin_lints));
+        let pass = RuntimeCombinedLateLintPass { passes: &mut passes[..] };
+        late_lint_crate_inner(tcx, context, pass);
+    }
+}
 
-    let mut cx = LateContextAndPasses { context, passes };
+fn late_lint_crate_inner<'tcx, T: LateLintPass<'tcx>>(
+    tcx: TyCtxt<'tcx>,
+    context: LateContext<'tcx>,
+    pass: T,
+) {
+    let mut cx = LateContextAndPass { context, pass };
 
     // Visit the whole crate.
     cx.with_lint_attrs(hir::CRATE_HIR_ID, |cx| {
index 10bae36e0fd3c3b4eb0d1c53daa1d7934236e15c..11022eb80ea5ff04bd713ee1ba29c27af2d5cc55 100644 (file)
@@ -162,7 +162,8 @@ fn lint_mod(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
     ]
 );
 
-// FIXME: Make a separate lint type which do not require typeck tables
+// FIXME: Make a separate lint type which does not require typeck tables.
+
 late_lint_methods!(
     declare_combined_late_lint_pass,
     [
@@ -179,8 +180,7 @@ fn lint_mod(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
             // Keeps a global list of foreign declarations.
             ClashingExternDeclarations: ClashingExternDeclarations::new(),
         ]
-    ],
-    ['tcx]
+    ]
 );
 
 late_lint_methods!(
@@ -229,8 +229,7 @@ fn lint_mod(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
             NamedAsmLabels: NamedAsmLabels,
             OpaqueHiddenInferredBound: OpaqueHiddenInferredBound,
         ]
-    ],
-    ['tcx]
+    ]
 );
 
 pub fn new_lint_store(internal_lints: bool) -> LintStore {
index 7e50801f80c7bbbf6797b8aa84224ff84dc61b18..91fcd6d690ee7a52c819546eccc065dca1baf64c 100644 (file)
@@ -175,13 +175,23 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) {
             return;
         }
 
-        match it.kind {
+        match &it.kind {
             ast::ItemKind::TyAlias(..)
             | ast::ItemKind::Enum(..)
             | ast::ItemKind::Struct(..)
             | ast::ItemKind::Union(..) => self.check_case(cx, "type", &it.ident),
             ast::ItemKind::Trait(..) => self.check_case(cx, "trait", &it.ident),
             ast::ItemKind::TraitAlias(..) => self.check_case(cx, "trait alias", &it.ident),
+
+            // N.B. This check is only for inherent associated types, so that we don't lint against
+            // trait impls where we should have warned for the trait definition already.
+            ast::ItemKind::Impl(box ast::Impl { of_trait: None, items, .. }) => {
+                for it in items {
+                    if let ast::AssocItemKind::Type(..) = it.kind {
+                        self.check_case(cx, "associated type", &it.ident);
+                    }
+                }
+            }
             _ => (),
         }
     }
index 03d6f4fd92687f192ac40cbf540209b057bdfeae..42442cfb1904d4ddfdd621d53b156e62ec1186f2 100644 (file)
@@ -82,7 +82,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
             let Some(proj_term) = proj.term.ty() else { continue };
 
             let proj_ty =
-                cx.tcx.mk_projection(proj.projection_ty.item_def_id, proj.projection_ty.substs);
+                cx.tcx.mk_projection(proj.projection_ty.def_id, proj.projection_ty.substs);
             // For every instance of the projection type in the bounds,
             // replace them with the term we're assigning to the associated
             // type in our opaque type.
@@ -97,7 +97,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
             // with `impl Send: OtherTrait`.
             for (assoc_pred, assoc_pred_span) in cx
                 .tcx
-                .bound_explicit_item_bounds(proj.projection_ty.item_def_id)
+                .bound_explicit_item_bounds(proj.projection_ty.def_id)
                 .subst_iter_copied(cx.tcx, &proj.projection_ty.substs)
             {
                 let assoc_pred = assoc_pred.fold_with(proj_replacer);
@@ -117,7 +117,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
                     // then we can emit a suggestion to add the bound.
                     let add_bound = match (proj_term.kind(), assoc_pred.kind().skip_binder()) {
                         (
-                            ty::Opaque(def_id, _),
+                            ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }),
                             ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)),
                         ) => Some(AddBound {
                             suggest_span: cx.tcx.def_span(*def_id).shrink_to_hi(),
index 2f53986139e05cc55500a7b87e112913caf3d357..5558156a4b9ef040a07ff54271328b64f31e2ba4 100644 (file)
@@ -9,49 +9,49 @@
 
 #[macro_export]
 macro_rules! late_lint_methods {
-    ($macro:path, $args:tt, [$hir:tt]) => (
-        $macro!($args, [$hir], [
-            fn check_body(a: &$hir hir::Body<$hir>);
-            fn check_body_post(a: &$hir hir::Body<$hir>);
+    ($macro:path, $args:tt) => (
+        $macro!($args, [
+            fn check_body(a: &'tcx hir::Body<'tcx>);
+            fn check_body_post(a: &'tcx hir::Body<'tcx>);
             fn check_crate();
             fn check_crate_post();
-            fn check_mod(a: &$hir hir::Mod<$hir>, b: hir::HirId);
-            fn check_foreign_item(a: &$hir hir::ForeignItem<$hir>);
-            fn check_item(a: &$hir hir::Item<$hir>);
-            fn check_item_post(a: &$hir hir::Item<$hir>);
-            fn check_local(a: &$hir hir::Local<$hir>);
-            fn check_block(a: &$hir hir::Block<$hir>);
-            fn check_block_post(a: &$hir hir::Block<$hir>);
-            fn check_stmt(a: &$hir hir::Stmt<$hir>);
-            fn check_arm(a: &$hir hir::Arm<$hir>);
-            fn check_pat(a: &$hir hir::Pat<$hir>);
-            fn check_expr(a: &$hir hir::Expr<$hir>);
-            fn check_expr_post(a: &$hir hir::Expr<$hir>);
-            fn check_ty(a: &$hir hir::Ty<$hir>);
-            fn check_generic_param(a: &$hir hir::GenericParam<$hir>);
-            fn check_generics(a: &$hir hir::Generics<$hir>);
-            fn check_poly_trait_ref(a: &$hir hir::PolyTraitRef<$hir>);
+            fn check_mod(a: &'tcx hir::Mod<'tcx>, b: hir::HirId);
+            fn check_foreign_item(a: &'tcx hir::ForeignItem<'tcx>);
+            fn check_item(a: &'tcx hir::Item<'tcx>);
+            fn check_item_post(a: &'tcx hir::Item<'tcx>);
+            fn check_local(a: &'tcx hir::Local<'tcx>);
+            fn check_block(a: &'tcx hir::Block<'tcx>);
+            fn check_block_post(a: &'tcx hir::Block<'tcx>);
+            fn check_stmt(a: &'tcx hir::Stmt<'tcx>);
+            fn check_arm(a: &'tcx hir::Arm<'tcx>);
+            fn check_pat(a: &'tcx hir::Pat<'tcx>);
+            fn check_expr(a: &'tcx hir::Expr<'tcx>);
+            fn check_expr_post(a: &'tcx hir::Expr<'tcx>);
+            fn check_ty(a: &'tcx hir::Ty<'tcx>);
+            fn check_generic_param(a: &'tcx hir::GenericParam<'tcx>);
+            fn check_generics(a: &'tcx hir::Generics<'tcx>);
+            fn check_poly_trait_ref(a: &'tcx hir::PolyTraitRef<'tcx>);
             fn check_fn(
-                a: rustc_hir::intravisit::FnKind<$hir>,
-                b: &$hir hir::FnDecl<$hir>,
-                c: &$hir hir::Body<$hir>,
+                a: rustc_hir::intravisit::FnKind<'tcx>,
+                b: &'tcx hir::FnDecl<'tcx>,
+                c: &'tcx hir::Body<'tcx>,
                 d: Span,
                 e: hir::HirId);
-            fn check_trait_item(a: &$hir hir::TraitItem<$hir>);
-            fn check_impl_item(a: &$hir hir::ImplItem<$hir>);
-            fn check_impl_item_post(a: &$hir hir::ImplItem<$hir>);
-            fn check_struct_def(a: &$hir hir::VariantData<$hir>);
-            fn check_field_def(a: &$hir hir::FieldDef<$hir>);
-            fn check_variant(a: &$hir hir::Variant<$hir>);
-            fn check_path(a: &hir::Path<$hir>, b: hir::HirId);
-            fn check_attribute(a: &$hir ast::Attribute);
+            fn check_trait_item(a: &'tcx hir::TraitItem<'tcx>);
+            fn check_impl_item(a: &'tcx hir::ImplItem<'tcx>);
+            fn check_impl_item_post(a: &'tcx hir::ImplItem<'tcx>);
+            fn check_struct_def(a: &'tcx hir::VariantData<'tcx>);
+            fn check_field_def(a: &'tcx hir::FieldDef<'tcx>);
+            fn check_variant(a: &'tcx hir::Variant<'tcx>);
+            fn check_path(a: &hir::Path<'tcx>, b: hir::HirId);
+            fn check_attribute(a: &'tcx ast::Attribute);
 
             /// Called when entering a syntax node that can have lint attributes such
             /// as `#[allow(...)]`. Called with *all* the attributes of that node.
-            fn enter_lint_attrs(a: &$hir [ast::Attribute]);
+            fn enter_lint_attrs(a: &'tcx [ast::Attribute]);
 
             /// Counterpart to `enter_lint_attrs`.
-            fn exit_lint_attrs(a: &$hir [ast::Attribute]);
+            fn exit_lint_attrs(a: &'tcx [ast::Attribute]);
         ]);
     )
 }
@@ -66,21 +66,23 @@ fn check_fn(
 // contains a few lint-specific methods with no equivalent in `Visitor`.
 
 macro_rules! declare_late_lint_pass {
-    ([], [$hir:tt], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
-        pub trait LateLintPass<$hir>: LintPass {
-            $(#[inline(always)] fn $name(&mut self, _: &LateContext<$hir>, $(_: $arg),*) {})*
+    ([], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
+        pub trait LateLintPass<'tcx>: LintPass {
+            $(#[inline(always)] fn $name(&mut self, _: &LateContext<'tcx>, $(_: $arg),*) {})*
         }
     )
 }
 
-late_lint_methods!(declare_late_lint_pass, [], ['tcx]);
+// Declare the `LateLintPass` trait, which contains empty default definitions
+// for all the `check_*` methods.
+late_lint_methods!(declare_late_lint_pass, []);
 
 impl LateLintPass<'_> for HardwiredLints {}
 
 #[macro_export]
 macro_rules! expand_combined_late_lint_pass_method {
-    ([$($passes:ident),*], $self: ident, $name: ident, $params:tt) => ({
-        $($self.$passes.$name $params;)*
+    ([$($pass:ident),*], $self: ident, $name: ident, $params:tt) => ({
+        $($self.$pass.$name $params;)*
     })
 }
 
@@ -93,30 +95,35 @@ macro_rules! expand_combined_late_lint_pass_methods {
     )
 }
 
+/// Combines multiple lints passes into a single lint pass, at compile time,
+/// for maximum speed. Each `check_foo` method in `$methods` within this pass
+/// simply calls `check_foo` once per `$pass`. Compare with
+/// `LateLintPassObjects`, which is similar, but combines lint passes at
+/// runtime.
 #[macro_export]
 macro_rules! declare_combined_late_lint_pass {
-    ([$v:vis $name:ident, [$($passes:ident: $constructor:expr,)*]], [$hir:tt], $methods:tt) => (
+    ([$v:vis $name:ident, [$($pass:ident: $constructor:expr,)*]], $methods:tt) => (
         #[allow(non_snake_case)]
         $v struct $name {
-            $($passes: $passes,)*
+            $($pass: $pass,)*
         }
 
         impl $name {
             $v fn new() -> Self {
                 Self {
-                    $($passes: $constructor,)*
+                    $($pass: $constructor,)*
                 }
             }
 
             $v fn get_lints() -> LintArray {
                 let mut lints = Vec::new();
-                $(lints.extend_from_slice(&$passes::get_lints());)*
+                $(lints.extend_from_slice(&$pass::get_lints());)*
                 lints
             }
         }
 
         impl<'tcx> LateLintPass<'tcx> for $name {
-            expand_combined_late_lint_pass_methods!([$($passes),*], $methods);
+            expand_combined_late_lint_pass_methods!([$($pass),*], $methods);
         }
 
         #[allow(rustc::lint_pass_impl_without_macro)]
@@ -176,12 +183,14 @@ pub trait EarlyLintPass: LintPass {
     )
 }
 
+// Declare the `EarlyLintPass` trait, which contains empty default definitions
+// for all the `check_*` methods.
 early_lint_methods!(declare_early_lint_pass, []);
 
 #[macro_export]
 macro_rules! expand_combined_early_lint_pass_method {
-    ([$($passes:ident),*], $self: ident, $name: ident, $params:tt) => ({
-        $($self.$passes.$name $params;)*
+    ([$($pass:ident),*], $self: ident, $name: ident, $params:tt) => ({
+        $($self.$pass.$name $params;)*
     })
 }
 
@@ -194,30 +203,35 @@ macro_rules! expand_combined_early_lint_pass_methods {
     )
 }
 
+/// Combines multiple lints passes into a single lint pass, at compile time,
+/// for maximum speed. Each `check_foo` method in `$methods` within this pass
+/// simply calls `check_foo` once per `$pass`. Compare with
+/// `EarlyLintPassObjects`, which is similar, but combines lint passes at
+/// runtime.
 #[macro_export]
 macro_rules! declare_combined_early_lint_pass {
-    ([$v:vis $name:ident, [$($passes:ident: $constructor:expr,)*]], $methods:tt) => (
+    ([$v:vis $name:ident, [$($pass:ident: $constructor:expr,)*]], $methods:tt) => (
         #[allow(non_snake_case)]
         $v struct $name {
-            $($passes: $passes,)*
+            $($pass: $pass,)*
         }
 
         impl $name {
             $v fn new() -> Self {
                 Self {
-                    $($passes: $constructor,)*
+                    $($pass: $constructor,)*
                 }
             }
 
             $v fn get_lints() -> LintArray {
                 let mut lints = Vec::new();
-                $(lints.extend_from_slice(&$passes::get_lints());)*
+                $(lints.extend_from_slice(&$pass::get_lints());)*
                 lints
             }
         }
 
         impl EarlyLintPass for $name {
-            expand_combined_early_lint_pass_methods!([$($passes),*], $methods);
+            expand_combined_early_lint_pass_methods!([$($pass),*], $methods);
         }
 
         #[allow(rustc::lint_pass_impl_without_macro)]
index 297b509d4023d40138c47233316a38c2e41270e6..8e27bc03c489aeedf8ab0b5d2cd15776c8cff157 100644 (file)
@@ -16,7 +16,6 @@
 use rustc_target::abi::{Integer, TagEncoding, Variants};
 use rustc_target::spec::abi::Abi as SpecAbi;
 
-use std::cmp;
 use std::iter;
 use std::ops::ControlFlow;
 
@@ -531,7 +530,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx hir::Expr<'tcx>) {
             _ => {}
         };
 
-        fn is_valid<T: cmp::PartialOrd>(binop: hir::BinOp, v: T, min: T, max: T) -> bool {
+        fn is_valid<T: PartialOrd>(binop: hir::BinOp, v: T, min: T, max: T) -> bool {
             match binop.node {
                 hir::BinOpKind::Lt => v > min && v <= max,
                 hir::BinOpKind::Le => v >= min && v < max,
@@ -1140,18 +1139,20 @@ fn check_type_for_ffi(&self, cache: &mut FxHashSet<Ty<'tcx>>, ty: Ty<'tcx>) -> F
 
             // While opaque types are checked for earlier, if a projection in a struct field
             // normalizes to an opaque type, then it will reach this branch.
-            ty::Opaque(..) => {
+            ty::Alias(ty::Opaque, ..) => {
                 FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_opaque, help: None }
             }
 
             // `extern "C" fn` functions can have type parameters, which may or may not be FFI-safe,
             //  so they are currently ignored for the purposes of this lint.
-            ty::Param(..) | ty::Projection(..) if matches!(self.mode, CItemKind::Definition) => {
+            ty::Param(..) | ty::Alias(ty::Projection, ..)
+                if matches!(self.mode, CItemKind::Definition) =>
+            {
                 FfiSafe
             }
 
             ty::Param(..)
-            | ty::Projection(..)
+            | ty::Alias(ty::Projection, ..)
             | ty::Infer(..)
             | ty::Bound(..)
             | ty::Error(_)
@@ -1206,7 +1207,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
                     return ControlFlow::CONTINUE;
                 }
 
-                if let ty::Opaque(..) = ty.kind() {
+                if let ty::Alias(ty::Opaque, ..) = ty.kind() {
                     ControlFlow::Break(ty)
                 } else {
                     ty.super_visit_with(self)
index b5db94f8c0684b3235fa92972c5f453df2c71c6f..3b8df61a0eab771a704f9ed9006bbd1807b612fa 100644 (file)
@@ -96,7 +96,7 @@ fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) {
 
         if let hir::ExprKind::Match(await_expr, _arms, hir::MatchSource::AwaitDesugar) = expr.kind
             && let ty = cx.typeck_results().expr_ty(&await_expr)
-            && let ty::Opaque(future_def_id, _) = ty.kind()
+            && let ty::Alias(ty::Opaque, ty::AliasTy { def_id: future_def_id, .. }) = ty.kind()
             && cx.tcx.ty_is_opaque_future(ty)
             // FIXME: This also includes non-async fns that return `impl Future`.
             && let async_fn_def_id = cx.tcx.parent(*future_def_id)
@@ -251,7 +251,7 @@ fn is_ty_must_use<'tcx>(
                         .map(|inner| MustUsePath::Boxed(Box::new(inner)))
                 }
                 ty::Adt(def, _) => is_def_must_use(cx, def.did(), span),
-                ty::Opaque(def, _) => {
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
                     elaborate_predicates_with_span(
                         cx.tcx,
                         cx.tcx.explicit_item_bounds(def).iter().cloned(),
@@ -617,7 +617,10 @@ fn is_expr_delims_necessary(
         lhs_needs_parens
             || (followed_by_block
                 && match &inner.kind {
-                    ExprKind::Ret(_) | ExprKind::Break(..) | ExprKind::Yield(..) => true,
+                    ExprKind::Ret(_)
+                    | ExprKind::Break(..)
+                    | ExprKind::Yield(..)
+                    | ExprKind::Yeet(..) => true,
                     ExprKind::Range(_lhs, Some(rhs), _limits) => {
                         matches!(rhs.kind, ExprKind::Block(..))
                     }
@@ -946,6 +949,7 @@ fn check_unused_parens_pat(
 }
 
 impl EarlyLintPass for UnusedParens {
+    #[inline]
     fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
         match e.kind {
             ExprKind::Let(ref pat, _, _) | ExprKind::ForLoop(ref pat, ..) => {
@@ -1164,6 +1168,7 @@ fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
         <Self as UnusedDelimLint>::check_stmt(self, cx, s)
     }
 
+    #[inline]
     fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
         <Self as UnusedDelimLint>::check_expr(self, cx, e);
 
@@ -1274,7 +1279,7 @@ impl UnusedImportBraces {
     fn check_use_tree(&self, cx: &EarlyContext<'_>, use_tree: &ast::UseTree, item: &ast::Item) {
         if let ast::UseTreeKind::Nested(ref items) = use_tree.kind {
             // Recursively check nested UseTrees
-            for &(ref tree, _) in items {
+            for (tree, _) in items {
                 self.check_use_tree(cx, tree, item);
             }
 
index df0e17dea3c051495593062c68485307b168bf01..33cb35e60ebb6cfc1edf37d68a4262b57956e19b 100644 (file)
 
 declare_lint! {
     /// The `trivial_casts` lint detects trivial casts which could be replaced
-    /// with coercion, which may require [type ascription] or a temporary
-    /// variable.
+    /// with coercion, which may require a temporary variable.
     ///
     /// ### Example
     ///
     /// with FFI interfaces or complex type aliases, where it triggers
     /// incorrectly, or in situations where it will be more difficult to
     /// clearly express the intent. It may be possible that this will become a
-    /// warning in the future, possibly with [type ascription] providing a
-    /// convenient way to work around the current issues. See [RFC 401] for
-    /// historical context.
-    ///
-    /// [type ascription]: https://github.com/rust-lang/rust/issues/23416
-    /// [RFC 401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
+    /// warning in the future, possibly with an explicit syntax for coercions
+    /// providing a convenient way to work around the current issues.
+    /// See [RFC 401 (coercions)][rfc-401], [RFC 803 (type ascription)][rfc-803] and
+    /// [RFC 3307 (remove type ascription)][rfc-3307] for historical context.
+    ///
+    /// [rfc-401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
+    /// [rfc-803]: https://github.com/rust-lang/rfcs/blob/master/text/0803-type-ascription.md
+    /// [rfc-3307]: https://github.com/rust-lang/rfcs/blob/master/text/3307-de-rfc-type-ascription.md
     pub TRIVIAL_CASTS,
     Allow,
     "detects trivial casts which could be removed"
     /// with FFI interfaces or complex type aliases, where it triggers
     /// incorrectly, or in situations where it will be more difficult to
     /// clearly express the intent. It may be possible that this will become a
-    /// warning in the future, possibly with [type ascription] providing a
-    /// convenient way to work around the current issues. See [RFC 401] for
-    /// historical context.
-    ///
-    /// [type ascription]: https://github.com/rust-lang/rust/issues/23416
-    /// [RFC 401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
+    /// warning in the future, possibly with an explicit syntax for coercions
+    /// providing a convenient way to work around the current issues.
+    /// See [RFC 401 (coercions)][rfc-401], [RFC 803 (type ascription)][rfc-803] and
+    /// [RFC 3307 (remove type ascription)][rfc-3307] for historical context.
+    ///
+    /// [rfc-401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
+    /// [rfc-803]: https://github.com/rust-lang/rfcs/blob/master/text/0803-type-ascription.md
+    /// [rfc-3307]: https://github.com/rust-lang/rfcs/blob/master/text/3307-de-rfc-type-ascription.md
     pub TRIVIAL_NUMERIC_CASTS,
     Allow,
     "detects trivial casts of numeric types which could be removed"
     };
 }
 
+declare_lint! {
+    /// The `invalid_alignment` lint detects dereferences of misaligned pointers during
+    /// constant evluation.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,compile_fail
+    /// #![feature(const_ptr_read)]
+    /// const FOO: () = unsafe {
+    ///     let x = &[0_u8; 4];
+    ///     let y = x.as_ptr().cast::<u32>();
+    ///     y.read(); // the address of a `u8` array is unknown and thus we don't know if
+    ///     // it is aligned enough for reading a `u32`.
+    /// };
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// The compiler allowed dereferencing raw pointers irrespective of alignment
+    /// during const eval due to the const evaluator at the time not making it easy
+    /// or cheap to check. Now that it is both, this is not accepted anymore.
+    ///
+    /// Since it was undefined behaviour to begin with, this breakage does not violate
+    /// Rust's stability guarantees. Using undefined behaviour can cause arbitrary
+    /// behaviour, including failure to build.
+    ///
+    /// [future-incompatible]: ../index.md#future-incompatible-lints
+    pub INVALID_ALIGNMENT,
+    Deny,
+    "raw pointers must be aligned before dereferencing",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #68585 <https://github.com/rust-lang/rust/issues/104616>",
+        reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow,
+    };
+}
+
 declare_lint! {
     /// The `exported_private_dependencies` lint detects private dependencies
     /// that are exposed in a public interface.
index 79f06ac146c77953267734d0d37022d3abfa9853..0b3c057345a67d9a532e4b15e041f353b88f1743 100644 (file)
@@ -238,18 +238,20 @@ fn main() {
 
     if !is_crossed {
         cmd.arg("--system-libs");
-    } else if target.contains("windows-gnu") {
-        println!("cargo:rustc-link-lib=shell32");
-        println!("cargo:rustc-link-lib=uuid");
-    } else if target.contains("netbsd") || target.contains("haiku") || target.contains("darwin") {
-        println!("cargo:rustc-link-lib=z");
-    } else if target.starts_with("arm")
+    }
+
+    if (target.starts_with("arm") && !target.contains("freebsd"))
         || target.starts_with("mips-")
         || target.starts_with("mipsel-")
         || target.starts_with("powerpc-")
     {
         // 32-bit targets need to link libatomic.
         println!("cargo:rustc-link-lib=atomic");
+    } else if target.contains("windows-gnu") {
+        println!("cargo:rustc-link-lib=shell32");
+        println!("cargo:rustc-link-lib=uuid");
+    } else if target.contains("netbsd") || target.contains("haiku") || target.contains("darwin") {
+        println!("cargo:rustc-link-lib=z");
     }
     cmd.args(&components);
 
index 1a3d458c30067cfce22e11625a5c9e5fa9ccaf53..2865ea8927336143490193bddbeaec125dda6789 100644 (file)
@@ -223,7 +223,11 @@ fromRust(LLVMRustCodeModel Model) {
   case LLVMRustCodeModel::Large:
     return CodeModel::Large;
   case LLVMRustCodeModel::None:
+#if LLVM_VERSION_LT(16, 0)
     return None;
+#else
+    return std::nullopt;
+#endif
   default:
     report_fatal_error("Bad CodeModel.");
   }
index 3a748f38995bbc77bf8102379e227ab4a922d2f4..279b699185421982026fad27f12804d00a8e7d8d 100644 (file)
@@ -322,7 +322,13 @@ extern "C" LLVMAttributeRef LLVMRustCreateUWTableAttr(LLVMContextRef C, bool Asy
 }
 
 extern "C" LLVMAttributeRef LLVMRustCreateAllocSizeAttr(LLVMContextRef C, uint32_t ElementSizeArg) {
-  return wrap(Attribute::getWithAllocSizeArgs(*unwrap(C), ElementSizeArg, None));
+  return wrap(Attribute::getWithAllocSizeArgs(*unwrap(C), ElementSizeArg,
+#if LLVM_VERSION_LT(16, 0)
+                                              None
+#else
+                                              std::nullopt
+#endif
+                                              ));
 }
 
 #if LLVM_VERSION_GE(15, 0)
@@ -717,7 +723,11 @@ static std::optional<DIFile::ChecksumKind> fromRust(LLVMRustChecksumKind Kind) {
 #endif
   switch (Kind) {
   case LLVMRustChecksumKind::None:
+#if LLVM_VERSION_LT(16, 0)
     return None;
+#else
+    return std::nullopt;
+#endif
   case LLVMRustChecksumKind::MD5:
     return DIFile::ChecksumKind::CSK_MD5;
   case LLVMRustChecksumKind::SHA1:
@@ -1476,13 +1486,13 @@ extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) {
 
 extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
                                           LLVMValueRef *Args, unsigned NumArgs,
-                                          OperandBundleDef *Bundle) {
+                                          OperandBundleDef **OpBundles,
+                                          unsigned NumOpBundles) {
   Value *Callee = unwrap(Fn);
   FunctionType *FTy = unwrap<FunctionType>(Ty);
-  unsigned Len = Bundle ? 1 : 0;
-  ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
   return wrap(unwrap(B)->CreateCall(
-      FTy, Callee, makeArrayRef(unwrap(Args), NumArgs), Bundles));
+      FTy, Callee, makeArrayRef(unwrap(Args), NumArgs),
+      makeArrayRef(*OpBundles, NumOpBundles)));
 }
 
 extern "C" LLVMValueRef LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) {
@@ -1522,14 +1532,14 @@ extern "C" LLVMValueRef
 LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
                     LLVMValueRef *Args, unsigned NumArgs,
                     LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
-                    OperandBundleDef *Bundle, const char *Name) {
+                    OperandBundleDef **OpBundles, unsigned NumOpBundles,
+                    const char *Name) {
   Value *Callee = unwrap(Fn);
   FunctionType *FTy = unwrap<FunctionType>(Ty);
-  unsigned Len = Bundle ? 1 : 0;
-  ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
   return wrap(unwrap(B)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch),
                                       makeArrayRef(unwrap(Args), NumArgs),
-                                      Bundles, Name));
+                                      makeArrayRef(*OpBundles, NumOpBundles),
+                                      Name));
 }
 
 extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B,
index 684835d8c5c86b88e60713d8639ab1962a4eb0da..13f06fe747349d8084b9b53d1a303c75f9b0278b 100644 (file)
@@ -192,7 +192,7 @@ fn check(slug: &syn::Path) -> Option<Mismatch> {
         let crate_name = std::env::var("CARGO_CRATE_NAME").ok()?;
 
         // If we're not in a "rustc_" crate, bail.
-        let Some(("rustc", slug_prefix)) = crate_name.split_once("_") else { return None };
+        let Some(("rustc", slug_prefix)) = crate_name.split_once('_') else { return None };
 
         let slug_name = slug.segments.first()?.ident.to_string();
         if !slug_name.starts_with(slug_prefix) {
index 9f2ac5112f1cd9d3aa4b78a9cf1deeda1c0ae799..82f6812026a7d73a185a526b7390173f4602f996 100644 (file)
@@ -372,46 +372,21 @@ fn generate_inner_field_code(
                 }
             }
             (Meta::Path(_), "subdiagnostic") => {
-                return Ok(quote! { #diag.subdiagnostic(#binding); });
+                if FieldInnerTy::from_type(&info.binding.ast().ty).will_iterate() {
+                    let DiagnosticDeriveKind::Diagnostic { handler } = &self.parent.kind else {
+                        // No eager translation for lints.
+                        return Ok(quote! { #diag.subdiagnostic(#binding); });
+                    };
+                    return Ok(quote! { #diag.eager_subdiagnostic(#handler, #binding); });
+                } else {
+                    return Ok(quote! { #diag.subdiagnostic(#binding); });
+                }
             }
-            (Meta::NameValue(_), "subdiagnostic") => {
+            (Meta::List(_), "subdiagnostic") => {
                 throw_invalid_attr!(attr, &meta, |diag| {
-                    diag.help("`eager` is the only supported nested attribute for `subdiagnostic`")
+                    diag.help("`subdiagnostic` does not support nested attributes")
                 })
             }
-            (Meta::List(MetaList { ref nested, .. }), "subdiagnostic") => {
-                if nested.len() != 1 {
-                    throw_invalid_attr!(attr, &meta, |diag| {
-                        diag.help(
-                            "`eager` is the only supported nested attribute for `subdiagnostic`",
-                        )
-                    })
-                }
-
-                let handler = match &self.parent.kind {
-                    DiagnosticDeriveKind::Diagnostic { handler } => handler,
-                    DiagnosticDeriveKind::LintDiagnostic => {
-                        throw_invalid_attr!(attr, &meta, |diag| {
-                            diag.help("eager subdiagnostics are not supported on lints")
-                        })
-                    }
-                };
-
-                let nested_attr = nested.first().expect("pop failed for single element list");
-                match nested_attr {
-                    NestedMeta::Meta(meta @ Meta::Path(_))
-                        if meta.path().segments.last().unwrap().ident.to_string().as_str()
-                            == "eager" =>
-                    {
-                        return Ok(quote! { #diag.eager_subdiagnostic(#handler, #binding); });
-                    }
-                    _ => {
-                        throw_invalid_nested_attr!(attr, nested_attr, |diag| {
-                            diag.help("`eager` is the only supported nested attribute for `subdiagnostic`")
-                        })
-                    }
-                }
-            }
             _ => (),
         }
 
index 1a2389c7a8448878b28c406dbe0d247a6b3a1a61..9ce3ff98ba985bac96973926e662e8b693280688 100644 (file)
@@ -1,10 +1,9 @@
 //! Validates all used crates and extern libraries and loads their metadata
 
 use crate::errors::{
-    AllocFuncRequired, ConflictingAllocErrorHandler, ConflictingGlobalAlloc, CrateNotPanicRuntime,
-    GlobalAllocRequired, MissingAllocErrorHandler, NoMultipleAllocErrorHandler,
-    NoMultipleGlobalAlloc, NoPanicStrategy, NoTransitiveNeedsDep, NotProfilerRuntime,
-    ProfilerBuiltinsNeedsCore,
+    ConflictingAllocErrorHandler, ConflictingGlobalAlloc, CrateNotPanicRuntime,
+    GlobalAllocRequired, NoMultipleAllocErrorHandler, NoMultipleGlobalAlloc, NoPanicStrategy,
+    NoTransitiveNeedsDep, NotProfilerRuntime, ProfilerBuiltinsNeedsCore,
 };
 use crate::locator::{CrateError, CrateLocator, CratePaths};
 use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob};
@@ -13,7 +12,7 @@
 use rustc_ast::{self as ast, *};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::svh::Svh;
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{Lrc, ReadGuard};
 use rustc_expand::base::SyntaxExtension;
 use rustc_hir::def_id::{CrateNum, LocalDefId, StableCrateId, LOCAL_CRATE};
 use rustc_hir::definitions::Definitions;
@@ -68,11 +67,12 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 pub struct CrateLoader<'a> {
     // Immutable configuration.
     sess: &'a Session,
-    metadata_loader: Box<MetadataLoaderDyn>,
+    metadata_loader: &'a MetadataLoaderDyn,
+    definitions: ReadGuard<'a, Definitions>,
     local_crate_name: Symbol,
     // Mutable output.
-    cstore: CStore,
-    used_extern_options: FxHashSet<Symbol>,
+    cstore: &'a mut CStore,
+    used_extern_options: &'a mut FxHashSet<Symbol>,
 }
 
 pub enum LoadedMacro {
@@ -239,47 +239,49 @@ pub fn report_unused_deps(&self, tcx: TyCtxt<'_>) {
             );
         }
     }
+
+    pub fn new(sess: &Session) -> CStore {
+        let mut stable_crate_ids = FxHashMap::default();
+        stable_crate_ids.insert(sess.local_stable_crate_id(), LOCAL_CRATE);
+        CStore {
+            // We add an empty entry for LOCAL_CRATE (which maps to zero) in
+            // order to make array indices in `metas` match with the
+            // corresponding `CrateNum`. This first entry will always remain
+            // `None`.
+            metas: IndexVec::from_elem_n(None, 1),
+            injected_panic_runtime: None,
+            allocator_kind: None,
+            alloc_error_handler_kind: None,
+            has_global_allocator: false,
+            has_alloc_error_handler: false,
+            stable_crate_ids,
+            unused_externs: Vec::new(),
+        }
+    }
 }
 
 impl<'a> CrateLoader<'a> {
     pub fn new(
         sess: &'a Session,
-        metadata_loader: Box<MetadataLoaderDyn>,
-        local_crate_name: &str,
+        metadata_loader: &'a MetadataLoaderDyn,
+        local_crate_name: Symbol,
+        cstore: &'a mut CStore,
+        definitions: ReadGuard<'a, Definitions>,
+        used_extern_options: &'a mut FxHashSet<Symbol>,
     ) -> Self {
-        let mut stable_crate_ids = FxHashMap::default();
-        stable_crate_ids.insert(sess.local_stable_crate_id(), LOCAL_CRATE);
-
         CrateLoader {
             sess,
             metadata_loader,
-            local_crate_name: Symbol::intern(local_crate_name),
-            cstore: CStore {
-                // We add an empty entry for LOCAL_CRATE (which maps to zero) in
-                // order to make array indices in `metas` match with the
-                // corresponding `CrateNum`. This first entry will always remain
-                // `None`.
-                metas: IndexVec::from_elem_n(None, 1),
-                injected_panic_runtime: None,
-                allocator_kind: None,
-                alloc_error_handler_kind: None,
-                has_global_allocator: false,
-                has_alloc_error_handler: false,
-                stable_crate_ids,
-                unused_externs: Vec::new(),
-            },
-            used_extern_options: Default::default(),
+            local_crate_name,
+            cstore,
+            used_extern_options,
+            definitions,
         }
     }
-
     pub fn cstore(&self) -> &CStore {
         &self.cstore
     }
 
-    pub fn into_cstore(self) -> CStore {
-        self.cstore
-    }
-
     fn existing_match(&self, name: Symbol, hash: Option<Svh>, kind: PathKind) -> Option<CrateNum> {
         for (cnum, data) in self.cstore.iter_crate_data() {
             if data.name() != name {
@@ -892,10 +894,6 @@ fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
         } else {
             // The alloc crate provides a default allocation error handler if
             // one isn't specified.
-            if !self.sess.features_untracked().default_alloc_error_handler {
-                self.sess.emit_err(AllocFuncRequired);
-                self.sess.emit_note(MissingAllocErrorHandler);
-            }
             self.cstore.alloc_error_handler_kind = Some(AllocatorKind::Default);
         }
     }
@@ -989,7 +987,6 @@ pub fn postprocess(&mut self, krate: &ast::Crate) {
     pub fn process_extern_crate(
         &mut self,
         item: &ast::Item,
-        definitions: &Definitions,
         def_id: LocalDefId,
     ) -> Option<CrateNum> {
         match item.kind {
@@ -1000,7 +997,7 @@ pub fn process_extern_crate(
                 );
                 let name = match orig_name {
                     Some(orig_name) => {
-                        validate_crate_name(self.sess, orig_name.as_str(), Some(item.span));
+                        validate_crate_name(self.sess, orig_name, Some(item.span));
                         orig_name
                     }
                     None => item.ident.name,
@@ -1013,7 +1010,7 @@ pub fn process_extern_crate(
 
                 let cnum = self.resolve_crate(name, item.span, dep_kind)?;
 
-                let path_len = definitions.def_path(def_id).data.len();
+                let path_len = self.definitions.def_path(def_id).data.len();
                 self.update_extern_crate(
                     cnum,
                     ExternCrate {
index 6f7e6e09ca5eddfabcf7ff0c908c7ce2a9de72d9..de2a879f1d73769c59f4dda5661f1abc93e1b5cf 100644 (file)
@@ -371,14 +371,6 @@ pub struct ConflictingAllocErrorHandler {
 #[diag(metadata_global_alloc_required)]
 pub struct GlobalAllocRequired;
 
-#[derive(Diagnostic)]
-#[diag(metadata_alloc_func_required)]
-pub struct AllocFuncRequired;
-
-#[derive(Diagnostic)]
-#[diag(metadata_missing_alloc_error_handler)]
-pub struct MissingAllocErrorHandler;
-
 #[derive(Diagnostic)]
 #[diag(metadata_no_transitive_needs_dep)]
 pub struct NoTransitiveNeedsDep<'a> {
index 4fa440c7ca691128fa8c03012ff8c03efcdc1bab..7601f6bd3221efaae15ef9b76f4c54366cd9628c 100644 (file)
@@ -61,8 +61,7 @@ enum MetadataKind {
         .unwrap_or(MetadataKind::None);
 
     let crate_name = tcx.crate_name(LOCAL_CRATE);
-    let out_filename =
-        filename_for_metadata(tcx.sess, crate_name.as_str(), tcx.output_filenames(()));
+    let out_filename = filename_for_metadata(tcx.sess, crate_name, tcx.output_filenames(()));
     // To avoid races with another rustc process scanning the output directory,
     // we need to write the file somewhere else and atomically move it to its
     // final destination, with an `fs::rename` call. In order for the rename to
index af7b0793a957413b38283188befe5def41f1e234..4370d4bd758d21f3112c664cd7a96f1456585243 100644 (file)
@@ -1527,13 +1527,15 @@ fn filter<'a>(sess: &Session, path: Option<&'a Path>) -> Option<&'a Path> {
                 if let Some(virtual_dir) = &sess.opts.unstable_opts.simulate_remapped_rust_src_base
                 {
                     if let Some(real_dir) = &sess.opts.real_rust_source_base_dir {
-                        if let rustc_span::FileName::Real(ref mut old_name) = name {
-                            if let rustc_span::RealFileName::LocalPath(local) = old_name {
-                                if let Ok(rest) = local.strip_prefix(real_dir) {
-                                    *old_name = rustc_span::RealFileName::Remapped {
-                                        local_path: None,
-                                        virtual_name: virtual_dir.join(rest),
-                                    };
+                        for subdir in ["library", "compiler"] {
+                            if let rustc_span::FileName::Real(ref mut old_name) = name {
+                                if let rustc_span::RealFileName::LocalPath(local) = old_name {
+                                    if let Ok(rest) = local.strip_prefix(real_dir.join(subdir)) {
+                                        *old_name = rustc_span::RealFileName::Remapped {
+                                            local_path: None,
+                                            virtual_name: virtual_dir.join(subdir).join(rest),
+                                        };
+                                    }
                                 }
                             }
                         }
index 33cce0a411e81babf281a72e64061927c0eb1968..9d0ccfeb16898309ae374f4b6b392e032eb4d550 100644 (file)
@@ -629,6 +629,9 @@ impl CrateStore for CStore {
     fn as_any(&self) -> &dyn Any {
         self
     }
+    fn untracked_as_any(&mut self) -> &mut dyn Any {
+        self
+    }
 
     fn crate_name(&self, cnum: CrateNum) -> Symbol {
         self.get_crate_data(cnum).root.name
index 8b4c4bb2675cb62309fe840c2c5efc1303b1ca72..96f15a6f758f2aa9b09fa8a24278429c89a6e1a1 100644 (file)
@@ -1111,8 +1111,8 @@ fn should_encode_trait_impl_trait_tys<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) ->
     // associated types.
     tcx.fn_sig(trait_item_def_id).skip_binder().output().walk().any(|arg| {
         if let ty::GenericArgKind::Type(ty) = arg.unpack()
-            && let ty::Projection(data) = ty.kind()
-            && tcx.def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder
+            && let ty::Alias(ty::Projection, data) = ty.kind()
+            && tcx.def_kind(data.def_id) == DefKind::ImplTraitPlaceholder
         {
             true
         } else {
@@ -1337,24 +1337,16 @@ fn encode_info_for_trait_item(&mut self, def_id: DefId) {
         debug!("EncodeContext::encode_info_for_trait_item({:?})", def_id);
         let tcx = self.tcx;
 
-        let ast_item = tcx.hir().expect_trait_item(def_id.expect_local());
-        self.tables.impl_defaultness.set(def_id.index, ast_item.defaultness);
+        let impl_defaultness = tcx.impl_defaultness(def_id.expect_local());
+        self.tables.impl_defaultness.set(def_id.index, impl_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 => {}
             ty::AssocKind::Fn => {
-                let hir::TraitItemKind::Fn(m_sig, m) = &ast_item.kind else { bug!() };
-                match *m {
-                    hir::TraitFn::Required(ref names) => {
-                        record_array!(self.tables.fn_arg_names[def_id] <- *names)
-                    }
-                    hir::TraitFn::Provided(body) => {
-                        record_array!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body))
-                    }
-                };
-                self.tables.asyncness.set(def_id.index, m_sig.header.asyncness);
+                record_array!(self.tables.fn_arg_names[def_id] <- tcx.fn_arg_names(def_id));
+                self.tables.asyncness.set(def_id.index, tcx.asyncness(def_id));
                 self.tables.constness.set(def_id.index, hir::Constness::NotConst);
             }
             ty::AssocKind::Type => {
@@ -1857,7 +1849,7 @@ fn encode_crate_deps(&mut self) -> LazyArray<CrateDep> {
         // the assumption that they are numbered 1 to n.
         // FIXME (#2166): This is not nearly enough to support correct versioning
         // but is enough to get transitive crate dependencies working.
-        self.lazy_array(deps.iter().map(|&(_, ref dep)| dep))
+        self.lazy_array(deps.iter().map(|(_, dep)| dep))
     }
 
     fn encode_lib_features(&mut self) -> LazyArray<(Symbol, Option<Symbol>)> {
@@ -1994,7 +1986,7 @@ fn encode_exported_symbols(
         self.lazy_array(
             exported_symbols
                 .iter()
-                .filter(|&&(ref exported_symbol, _)| match *exported_symbol {
+                .filter(|&(exported_symbol, _)| match *exported_symbol {
                     ExportedSymbol::NoDefId(symbol_name) => symbol_name != metadata_symbol_name,
                     _ => true,
                 })
index 29fe6110797e3885947169dcbdccaa83432479b7..716655c7f144d7de62e0d5c1bc64ee9a703c5b55 100644 (file)
@@ -7,7 +7,6 @@
 use rustc_serialize::opaque::FileEncoder;
 use rustc_serialize::Encoder as _;
 use rustc_span::hygiene::MacroKind;
-use std::convert::TryInto;
 use std::marker::PhantomData;
 use std::num::NonZeroUsize;
 
index 6de68841fe91f41fa84faa97f77ce3448350d9e9..75282f958b53b3b738c6498f16600f59209f2698 100644 (file)
@@ -93,7 +93,7 @@ macro_rules! arena_types {
             // Interned types
             [] tys: rustc_type_ir::WithCachedTypeInfo<rustc_middle::ty::TyKind<'tcx>>,
             [] predicates: rustc_type_ir::WithCachedTypeInfo<rustc_middle::ty::PredicateKind<'tcx>>,
-            [] consts: rustc_middle::ty::ConstS<'tcx>,
+            [] consts: rustc_middle::ty::ConstData<'tcx>,
 
             // Note that this deliberately duplicates items in the `rustc_hir::arena`,
             // since we need to allocate this type on both the `rustc_hir` arena
index 1bd8f95350879d29e86136f6c5d7c7bd1892bbb7..0450abed51b0652338a9bd7799d0dd2e566c62db 100644 (file)
@@ -14,7 +14,7 @@
 use rustc_middle::hir::nested_filter;
 use rustc_span::def_id::StableCrateId;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::Span;
 use rustc_target::spec::abi::Abi;
 
 #[inline]
@@ -1162,7 +1162,7 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
                 .filter_map(|(def_id, info)| {
                     let _ = info.as_owner()?;
                     let def_path_hash = definitions.def_path_hash(def_id);
-                    let span = resolutions.source_span.get(def_id).unwrap_or(&DUMMY_SP);
+                    let span = tcx.source_span(def_id);
                     debug_assert_eq!(span.parent(), None);
                     Some((def_path_hash, span))
                 })
index 02fd03c02839a69f7eb6e847d14248ebc06470c4..3f6e29ad611c911daf807d72be51dc5eb6e00780 100644 (file)
@@ -141,8 +141,6 @@ pub fn provide(providers: &mut Providers) {
     providers.hir_attrs = |tcx, id| {
         tcx.hir_crate(()).owners[id.def_id].as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs)
     };
-    providers.source_span =
-        |tcx, def_id| tcx.resolutions(()).source_span.get(def_id).copied().unwrap_or(DUMMY_SP);
     providers.def_span = |tcx, def_id| {
         let def_id = def_id.expect_local();
         let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
index 45d33a1659ffa42fbc0ae603025f44c80bdbda4a..bea884c856a95bd616b229e20f9f2984154ab573 100644 (file)
@@ -26,8 +26,10 @@ pub struct CodegenFnAttrs {
     /// The `#[target_feature(enable = "...")]` attribute and the enabled
     /// features (only enabled features are supported right now).
     pub target_features: Vec<Symbol>,
-    /// The `#[linkage = "..."]` attribute and the value we found.
+    /// The `#[linkage = "..."]` attribute on Rust-defined items and the value we found.
     pub linkage: Option<Linkage>,
+    /// The `#[linkage = "..."]` attribute on foreign items and the value we found.
+    pub import_linkage: Option<Linkage>,
     /// The `#[link_section = "..."]` attribute, or what executable section this
     /// should be placed in.
     pub link_section: Option<Symbol>,
@@ -113,6 +115,7 @@ pub const fn new() -> CodegenFnAttrs {
             link_ordinal: None,
             target_features: vec![],
             linkage: None,
+            import_linkage: None,
             link_section: None,
             no_sanitize: SanitizerSet::empty(),
             instruction_set: None,
index efa9464529e71ca14473852c3b6abb4cffdb04db..0b55757eb038298d32ee3598e9a07fe5732e0d15 100644 (file)
@@ -3,7 +3,6 @@
 use rustc_macros::HashStable;
 use rustc_span::Symbol;
 
-use std::cmp::Ord;
 use std::fmt::{self, Debug, Formatter};
 
 rustc_index::newtype_index! {
index d79cd8b7a8a4b075c4bfdcc30a5379141d6bc385..8fe349d9640dafd776814d0feb5f9b8175a7e92f 100644 (file)
@@ -95,7 +95,6 @@ macro_rules! throw_machine_stop {
 mod queries;
 mod value;
 
-use std::convert::TryFrom;
 use std::fmt;
 use std::io;
 use std::io::{Read, Write};
index 9c270ba1ec179939e18834ca0f773c9efbea4836..b0830991076206930b030985cdab10732d551744 100644 (file)
@@ -3,7 +3,6 @@
 use rustc_macros::HashStable;
 use rustc_target::abi::{HasDataLayout, Size};
 
-use std::convert::{TryFrom, TryInto};
 use std::fmt;
 
 ////////////////////////////////////////////////////////////////////////////////
index e6636e50e6e7ab0a1acf50e90cf57ed963c70c6a..88fb14eb359424e468ac55f953092fbc18cae2ee 100644 (file)
@@ -1,4 +1,3 @@
-use std::convert::{TryFrom, TryInto};
 use std::fmt;
 
 use either::{Either, Left, Right};
index a513444e1e08bd91b8f98fe9c428e1406554ffc2..e909b2f74aa16878bd4298bda6a7614c96fdb996 100644 (file)
@@ -36,7 +36,6 @@
 use either::Either;
 
 use std::borrow::Cow;
-use std::convert::TryInto;
 use std::fmt::{self, Debug, Display, Formatter, Write};
 use std::ops::{ControlFlow, Index, IndexMut};
 use std::{iter, mem};
@@ -534,6 +533,11 @@ pub fn should_skip(&self) -> bool {
         };
         injection_phase > self.phase
     }
+
+    #[inline]
+    pub fn is_custom_mir(&self) -> bool {
+        self.injection_phase.is_some()
+    }
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, Debug, TyEncodable, TyDecodable, HashStable)]
@@ -1484,7 +1488,7 @@ pub fn as_assign(&self) -> Option<&(Place<'tcx>, Rvalue<'tcx>)> {
 ///////////////////////////////////////////////////////////////////////////
 // Places
 
-impl<V, T> ProjectionElem<V, T> {
+impl<V, T, U> ProjectionElem<V, T, U> {
     /// Returns `true` if the target of this projection may refer to a different region of memory
     /// than the base.
     fn is_indirect(&self) -> bool {
@@ -1513,7 +1517,7 @@ pub fn is_field_to(&self, f: Field) -> bool {
 
 /// Alias for projections as they appear in `UserTypeProjection`, where we
 /// need neither the `V` parameter for `Index` nor the `T` for `Field`.
-pub type ProjectionKind = ProjectionElem<(), ()>;
+pub type ProjectionKind = ProjectionElem<(), (), ()>;
 
 rustc_index::newtype_index! {
     /// A [newtype'd][wrapper] index type in the MIR [control-flow graph][CFG]
@@ -1848,7 +1852,7 @@ impl<'tcx> Operand<'tcx> {
     pub fn function_handle(
         tcx: TyCtxt<'tcx>,
         def_id: DefId,
-        substs: SubstsRef<'tcx>,
+        substs: impl IntoIterator<Item = GenericArg<'tcx>>,
         span: Span,
     ) -> Self {
         let ty = tcx.mk_fn_def(def_id, substs);
index 15a24aa4ace512f1b453902ddca2e34d2033abab..1e8d5f7eae87a8881edadb729794f43e43fc9a9e 100644 (file)
@@ -200,6 +200,15 @@ pub fn krate(&self) -> CrateNum {
             MonoItem::GlobalAsm(..) => LOCAL_CRATE,
         }
     }
+
+    /// Returns the item's `DefId`
+    pub fn def_id(&self) -> DefId {
+        match *self {
+            MonoItem::Fn(Instance { def, .. }) => def.def_id(),
+            MonoItem::Static(def_id) => def_id,
+            MonoItem::GlobalAsm(item_id) => item_id.owner_id.to_def_id(),
+        }
+    }
 }
 
 impl<'tcx> fmt::Display for MonoItem<'tcx> {
index 7d2a6bda56926cbe8030d3430e35478c30540cb0..a6ca04f5e627ade49119c343de8f3fd405470dc6 100644 (file)
@@ -6,6 +6,7 @@
 use super::{BasicBlock, Constant, Field, Local, SwitchTargets, UserTypeProjection};
 
 use crate::mir::coverage::{CodeRegion, CoverageKind};
+use crate::traits::Reveal;
 use crate::ty::adjustment::PointerCast;
 use crate::ty::subst::SubstsRef;
 use crate::ty::{self, List, Ty};
@@ -100,6 +101,13 @@ pub fn name(&self) -> &'static str {
             MirPhase::Runtime(RuntimePhase::Optimized) => "runtime-optimized",
         }
     }
+
+    pub fn reveal(&self) -> Reveal {
+        match *self {
+            MirPhase::Built | MirPhase::Analysis(_) => Reveal::UserFacing,
+            MirPhase::Runtime(_) => Reveal::All,
+        }
+    }
 }
 
 /// See [`MirPhase::Analysis`].
@@ -400,7 +408,7 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 #[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, Hash, HashStable)]
 #[rustc_pass_by_value]
 pub enum RetagKind {
-    /// The initial retag when entering a function.
+    /// The initial retag of arguments when entering a function.
     FnEntry,
     /// Retag preparing for a two-phase borrow.
     TwoPhase,
@@ -518,12 +526,6 @@ pub enum TerminatorKind<'tcx> {
     SwitchInt {
         /// The discriminant value being tested.
         discr: Operand<'tcx>,
-
-        /// The type of value being tested.
-        /// This is always the same as the type of `discr`.
-        /// FIXME: remove this redundant information. Currently, it is relied on by pretty-printing.
-        switch_ty: Ty<'tcx>,
-
         targets: SwitchTargets,
     },
 
@@ -888,11 +890,18 @@ pub struct Place<'tcx> {
     pub projection: &'tcx List<PlaceElem<'tcx>>,
 }
 
+/// The different kinds of projections that can be used in the projection of a `Place`.
+///
+/// `T1` is the generic type for a field projection. For an actual projection on a `Place`
+/// this parameter will always be `Ty`, but the field type can be unavailable when
+/// building (by using `PlaceBuilder`) places that correspond to upvars.
+/// `T2` is the generic type for an `OpaqueCast` (is generic since it's abstracted over
+/// in dataflow analysis, see `AbstractElem`).
 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
 #[derive(TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
-pub enum ProjectionElem<V, T> {
+pub enum ProjectionElem<V, T1, T2> {
     Deref,
-    Field(Field, T),
+    Field(Field, T1),
     /// Index into a slice/array.
     ///
     /// Note that this does not also dereference, and so it does not exactly correspond to slice
@@ -948,12 +957,36 @@ pub enum ProjectionElem<V, T> {
 
     /// Like an explicit cast from an opaque type to a concrete type, but without
     /// requiring an intermediate variable.
-    OpaqueCast(T),
+    OpaqueCast(T2),
 }
 
 /// Alias for projections as they appear in places, where the base is a place
 /// and the index is a local.
-pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>;
+pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>, Ty<'tcx>>;
+
+/// Alias for projections that appear in `PlaceBuilder::Upvar`, for which
+/// we cannot provide any field types.
+pub type UpvarProjectionElem<'tcx> = ProjectionElem<Local, (), Ty<'tcx>>;
+
+impl<'tcx> From<PlaceElem<'tcx>> for UpvarProjectionElem<'tcx> {
+    fn from(elem: PlaceElem<'tcx>) -> Self {
+        match elem {
+            ProjectionElem::Deref => ProjectionElem::Deref,
+            ProjectionElem::Field(field, _) => ProjectionElem::Field(field, ()),
+            ProjectionElem::Index(v) => ProjectionElem::Index(v),
+            ProjectionElem::ConstantIndex { offset, min_length, from_end } => {
+                ProjectionElem::ConstantIndex { offset, min_length, from_end }
+            }
+            ProjectionElem::Subslice { from, to, from_end } => {
+                ProjectionElem::Subslice { from, to, from_end }
+            }
+            ProjectionElem::Downcast(opt_sym, variant_idx) => {
+                ProjectionElem::Downcast(opt_sym, variant_idx)
+            }
+            ProjectionElem::OpaqueCast(ty) => ProjectionElem::OpaqueCast(ty),
+        }
+    }
+}
 
 ///////////////////////////////////////////////////////////////////////////
 // Operands
index fa3adafd4b85f385c884f5b5c155234dbfce021a..1e289fc4abec3d4817d49f5521690e0792b193be 100644 (file)
@@ -28,8 +28,8 @@ pub fn from_ty(ty: Ty<'tcx>) -> PlaceTy<'tcx> {
     /// `place_ty.field_ty(tcx, f)` computes the type at a given field
     /// of a record or enum-variant. (Most clients of `PlaceTy` can
     /// instead just extract the relevant type directly from their
-    /// `PlaceElem`, but some instances of `ProjectionElem<V, T>` do
-    /// not carry a `Ty` for `T`.)
+    /// `PlaceElem`, but some instances of `ProjectionElem<V, T1, T2>` do
+    /// not carry a `Ty` for `T1` or `T2`.)
     ///
     /// Note that the resulting type has not been normalized.
     pub fn field_ty(self, tcx: TyCtxt<'tcx>, f: Field) -> Ty<'tcx> {
@@ -64,17 +64,18 @@ pub fn projection_ty(self, tcx: TyCtxt<'tcx>, elem: PlaceElem<'tcx>) -> PlaceTy<
     /// `Ty` or downcast variant corresponding to that projection.
     /// The `handle_field` callback must map a `Field` to its `Ty`,
     /// (which should be trivial when `T` = `Ty`).
-    pub fn projection_ty_core<V, T>(
+    pub fn projection_ty_core<V, T1, T2>(
         self,
         tcx: TyCtxt<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
-        elem: &ProjectionElem<V, T>,
-        mut handle_field: impl FnMut(&Self, Field, T) -> Ty<'tcx>,
-        mut handle_opaque_cast: impl FnMut(&Self, T) -> Ty<'tcx>,
+        elem: &ProjectionElem<V, T1, T2>,
+        mut handle_field: impl FnMut(&Self, Field, T1) -> Ty<'tcx>,
+        mut handle_opaque_cast: impl FnMut(&Self, T2) -> Ty<'tcx>,
     ) -> PlaceTy<'tcx>
     where
         V: ::std::fmt::Debug,
-        T: ::std::fmt::Debug + Copy,
+        T1: ::std::fmt::Debug + Copy,
+        T2: ::std::fmt::Debug + Copy,
     {
         if self.variant_index.is_some() && !matches!(elem, ProjectionElem::Field(..)) {
             bug!("cannot use non field projection on downcasted place")
@@ -234,7 +235,7 @@ pub fn ty<D>(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> Ty<'tcx>
     {
         match self {
             &Operand::Copy(ref l) | &Operand::Move(ref l) => l.ty(local_decls, tcx).ty,
-            &Operand::Constant(ref c) => c.literal.ty(),
+            Operand::Constant(c) => c.literal.ty(),
         }
     }
 }
index 4ea333cff7d9db9841502b4a18362a36148dc3b0..013a1bccd3bd1fd85af72a5a31db156e4e0c3416 100644 (file)
@@ -1,6 +1,3 @@
-use crate::mir;
-use crate::mir::interpret::Scalar;
-use crate::ty::{self, Ty, TyCtxt};
 use smallvec::{smallvec, SmallVec};
 
 use super::{BasicBlock, InlineAsmOperand, Operand, SourceInfo, TerminatorKind};
@@ -131,17 +128,8 @@ pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> {
 }
 
 impl<'tcx> TerminatorKind<'tcx> {
-    pub fn if_(
-        tcx: TyCtxt<'tcx>,
-        cond: Operand<'tcx>,
-        t: BasicBlock,
-        f: BasicBlock,
-    ) -> TerminatorKind<'tcx> {
-        TerminatorKind::SwitchInt {
-            discr: cond,
-            switch_ty: tcx.types.bool,
-            targets: SwitchTargets::static_if(0, f, t),
-        }
+    pub fn if_(cond: Operand<'tcx>, t: BasicBlock, f: BasicBlock) -> TerminatorKind<'tcx> {
+        TerminatorKind::SwitchInt { discr: cond, targets: SwitchTargets::static_if(0, f, t) }
     }
 
     pub fn successors(&self) -> Successors<'_> {
@@ -264,11 +252,9 @@ pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> {
         }
     }
 
-    pub fn as_switch(&self) -> Option<(&Operand<'tcx>, Ty<'tcx>, &SwitchTargets)> {
+    pub fn as_switch(&self) -> Option<(&Operand<'tcx>, &SwitchTargets)> {
         match self {
-            TerminatorKind::SwitchInt { discr, switch_ty, targets } => {
-                Some((discr, *switch_ty, targets))
-            }
+            TerminatorKind::SwitchInt { discr, targets } => Some((discr, targets)),
             _ => None,
         }
     }
@@ -403,21 +389,12 @@ pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> {
         match *self {
             Return | Resume | Abort | Unreachable | GeneratorDrop => vec![],
             Goto { .. } => vec!["".into()],
-            SwitchInt { ref targets, switch_ty, .. } => ty::tls::with(|tcx| {
-                let param_env = ty::ParamEnv::empty();
-                let switch_ty = tcx.lift(switch_ty).unwrap();
-                let size = tcx.layout_of(param_env.and(switch_ty)).unwrap().size;
-                targets
-                    .values
-                    .iter()
-                    .map(|&u| {
-                        mir::ConstantKind::from_scalar(tcx, Scalar::from_uint(u, size), switch_ty)
-                            .to_string()
-                            .into()
-                    })
-                    .chain(iter::once("otherwise".into()))
-                    .collect()
-            }),
+            SwitchInt { ref targets, .. } => targets
+                .values
+                .iter()
+                .map(|&u| Cow::Owned(u.to_string()))
+                .chain(iter::once("otherwise".into()))
+                .collect(),
             Call { target: Some(_), cleanup: Some(_), .. } => {
                 vec!["return".into(), "unwind".into()]
             }
index b21f50ae5eaa95a42689ce9ccbf614c65aced654..2ee3f551529f986c44525f9857994b4a29cbafba 100644 (file)
@@ -477,11 +477,9 @@ fn super_terminator(&mut self,
 
                     TerminatorKind::SwitchInt {
                         discr,
-                        switch_ty,
                         targets: _
                     } => {
                         self.visit_operand(discr, location);
-                        self.visit_ty($(& $mutability)? *switch_ty, TyContext::Location(location));
                     }
 
                     TerminatorKind::Drop {
index 880632561b9e8e2ba75ee46aac677f9932f879f2..e4bb3ce3d5a99b32793e8f0a9f1467d5b47f76f7 100644 (file)
 /// The `Key` trait controls what types can legally be used as the key
 /// for a query.
 pub trait Key: Sized {
-    type CacheSelector = DefaultCacheSelector<Self>;
+    // N.B. Most of the keys down below have `type CacheSelector = DefaultCacheSelector<Self>;`,
+    //      it would be reasonable to use associated type defaults, to remove the duplication...
+    //
+    //      ...But r-a doesn't support them yet and using a default here causes r-a to not infer
+    //      return types of queries which is very annoying. Thus, until r-a support associated
+    //      type defaults, plese restrain from using them here <3
+    //
+    //      r-a issue: <https://github.com/rust-lang/rust-analyzer/issues/13693>
+    type CacheSelector;
 
     /// Given an instance of this key, what crate is it referring to?
     /// This is used to find the provider.
@@ -37,6 +45,8 @@ fn ty_adt_id(&self) -> Option<DefId> {
 }
 
 impl Key for () {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
@@ -48,6 +58,8 @@ fn default_span(&self, _: TyCtxt<'_>) -> Span {
 }
 
 impl<'tcx> Key for ty::InstanceDef<'tcx> {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
@@ -59,6 +71,8 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
 }
 
 impl<'tcx> Key for ty::Instance<'tcx> {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
@@ -70,6 +84,8 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
 }
 
 impl<'tcx> Key for mir::interpret::GlobalId<'tcx> {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
@@ -81,6 +97,8 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
 }
 
 impl<'tcx> Key for (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>) {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
@@ -92,6 +110,8 @@ fn default_span(&self, _: TyCtxt<'_>) -> Span {
 }
 
 impl<'tcx> Key for mir::interpret::LitToConstInput<'tcx> {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
@@ -145,6 +165,8 @@ fn key_as_def_id(&self) -> Option<DefId> {
 }
 
 impl Key for DefId {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         self.krate == LOCAL_CRATE
@@ -159,6 +181,8 @@ fn key_as_def_id(&self) -> Option<DefId> {
 }
 
 impl Key for ty::WithOptConstParam<LocalDefId> {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
@@ -169,6 +193,8 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
 }
 
 impl Key for SimplifiedType {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
@@ -179,6 +205,8 @@ fn default_span(&self, _: TyCtxt<'_>) -> Span {
 }
 
 impl Key for (DefId, DefId) {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         self.0.krate == LOCAL_CRATE
@@ -189,6 +217,8 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
 }
 
 impl<'tcx> Key for (ty::Instance<'tcx>, LocalDefId) {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
@@ -199,6 +229,8 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
 }
 
 impl Key for (DefId, LocalDefId) {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         self.0.krate == LOCAL_CRATE
@@ -209,6 +241,8 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
 }
 
 impl Key for (LocalDefId, DefId) {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
@@ -219,6 +253,8 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
 }
 
 impl Key for (LocalDefId, LocalDefId) {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
@@ -229,6 +265,8 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
 }
 
 impl Key for (DefId, Option<Ident>) {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         self.0.krate == LOCAL_CRATE
@@ -243,6 +281,8 @@ fn key_as_def_id(&self) -> Option<DefId> {
 }
 
 impl Key for (DefId, LocalDefId, Ident) {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         self.0.krate == LOCAL_CRATE
@@ -253,6 +293,8 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
 }
 
 impl Key for (CrateNum, DefId) {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         self.0 == LOCAL_CRATE
@@ -263,6 +305,8 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
 }
 
 impl Key for (CrateNum, SimplifiedType) {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         self.0 == LOCAL_CRATE
@@ -273,6 +317,8 @@ fn default_span(&self, _: TyCtxt<'_>) -> Span {
 }
 
 impl Key for (DefId, SimplifiedType) {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         self.0.krate == LOCAL_CRATE
@@ -283,6 +329,8 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
 }
 
 impl<'tcx> Key for SubstsRef<'tcx> {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
@@ -293,6 +341,8 @@ fn default_span(&self, _: TyCtxt<'_>) -> Span {
 }
 
 impl<'tcx> Key for (DefId, SubstsRef<'tcx>) {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         self.0.krate == LOCAL_CRATE
@@ -303,6 +353,8 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
 }
 
 impl<'tcx> Key for (ty::UnevaluatedConst<'tcx>, ty::UnevaluatedConst<'tcx>) {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         (self.0).def.did.krate == LOCAL_CRATE
@@ -313,6 +365,8 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
 }
 
 impl<'tcx> Key for (LocalDefId, DefId, SubstsRef<'tcx>) {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
@@ -323,6 +377,8 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
 }
 
 impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         self.1.def_id().krate == LOCAL_CRATE
@@ -333,6 +389,8 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
 }
 
 impl<'tcx> Key for (ty::Const<'tcx>, mir::Field) {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
@@ -343,6 +401,8 @@ fn default_span(&self, _: TyCtxt<'_>) -> Span {
 }
 
 impl<'tcx> Key for mir::interpret::ConstAlloc<'tcx> {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
@@ -353,6 +413,8 @@ fn default_span(&self, _: TyCtxt<'_>) -> Span {
 }
 
 impl<'tcx> Key for ty::PolyTraitRef<'tcx> {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         self.def_id().krate == LOCAL_CRATE
@@ -363,6 +425,8 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
 }
 
 impl<'tcx> Key for ty::PolyExistentialTraitRef<'tcx> {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         self.def_id().krate == LOCAL_CRATE
@@ -373,6 +437,8 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
 }
 
 impl<'tcx> Key for (ty::PolyTraitRef<'tcx>, ty::PolyTraitRef<'tcx>) {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         self.0.def_id().krate == LOCAL_CRATE
@@ -383,6 +449,8 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
 }
 
 impl<'tcx> Key for GenericArg<'tcx> {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
@@ -393,6 +461,8 @@ fn default_span(&self, _: TyCtxt<'_>) -> Span {
 }
 
 impl<'tcx> Key for mir::ConstantKind<'tcx> {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
@@ -403,6 +473,8 @@ fn default_span(&self, _: TyCtxt<'_>) -> Span {
 }
 
 impl<'tcx> Key for ty::Const<'tcx> {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
@@ -413,6 +485,8 @@ fn default_span(&self, _: TyCtxt<'_>) -> Span {
 }
 
 impl<'tcx> Key for Ty<'tcx> {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
@@ -429,6 +503,8 @@ fn ty_adt_id(&self) -> Option<DefId> {
 }
 
 impl<'tcx> Key for TyAndLayout<'tcx> {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
@@ -439,6 +515,8 @@ fn default_span(&self, _: TyCtxt<'_>) -> Span {
 }
 
 impl<'tcx> Key for (Ty<'tcx>, Ty<'tcx>) {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
@@ -449,6 +527,8 @@ fn default_span(&self, _: TyCtxt<'_>) -> Span {
 }
 
 impl<'tcx> Key for &'tcx ty::List<ty::Predicate<'tcx>> {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
@@ -459,6 +539,8 @@ fn default_span(&self, _: TyCtxt<'_>) -> Span {
 }
 
 impl<'tcx> Key for ty::ParamEnv<'tcx> {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
@@ -469,6 +551,8 @@ fn default_span(&self, _: TyCtxt<'_>) -> Span {
 }
 
 impl<'tcx, T: Key> Key for ty::ParamEnvAnd<'tcx, T> {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         self.value.query_crate_is_local()
@@ -479,6 +563,8 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
 }
 
 impl Key for Symbol {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
@@ -489,6 +575,8 @@ fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
 }
 
 impl Key for Option<Symbol> {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
@@ -501,6 +589,8 @@ fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
 /// Canonical query goals correspond to abstract trait operations that
 /// are not tied to any crate in particular.
 impl<'tcx, T> Key for Canonical<'tcx, T> {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
@@ -512,6 +602,8 @@ fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
 }
 
 impl Key for (Symbol, u32, u32) {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
@@ -523,6 +615,8 @@ fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
 }
 
 impl<'tcx> Key for (DefId, Ty<'tcx>, SubstsRef<'tcx>, ty::ParamEnv<'tcx>) {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
@@ -534,6 +628,8 @@ fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
 }
 
 impl<'tcx> Key for (ty::Predicate<'tcx>, traits::WellFormedLoc) {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
@@ -545,6 +641,8 @@ fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
 }
 
 impl<'tcx> Key for (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>) {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
@@ -556,6 +654,8 @@ fn default_span(&self, _: TyCtxt<'_>) -> Span {
 }
 
 impl<'tcx> Key for (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>) {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
@@ -567,6 +667,8 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
 }
 
 impl<'tcx> Key for (Ty<'tcx>, ty::ValTree<'tcx>) {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
@@ -578,6 +680,8 @@ fn default_span(&self, _: TyCtxt<'_>) -> Span {
 }
 
 impl Key for HirId {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
         true
index f2f2b22f52a37b81834c82f7e06f9a25e36c6c27..ab512804330b9f647ca9bc14edf2e0d698b53b4a 100644 (file)
@@ -43,6 +43,8 @@
     /// This span is meant for dep-tracking rather than diagnostics. It should not be used outside
     /// of rustc_middle::hir::source_map.
     query source_span(key: LocalDefId) -> Span {
+        // Accesses untracked data
+        eval_always
         desc { "getting the source span" }
     }
 
index 143435cb2a1f47bcbf11929aa4aba4a4b6e9b1da..d00b26a5a3d0b42baafca1d795332bbfc0ddbdcc 100644 (file)
@@ -250,7 +250,7 @@ pub enum ObligationCauseCode<'tcx> {
     TupleElem,
 
     /// This is the trait reference from the given projection.
-    ProjectionWf(ty::ProjectionTy<'tcx>),
+    ProjectionWf(ty::AliasTy<'tcx>),
 
     /// Must satisfy all of the where-clause predicates of the
     /// given item.
index fb152b63f63448675059b251cbd6191681df48fa..7380c62a6693a85166a3ed26ef4184b572c6ac39 100644 (file)
@@ -12,7 +12,6 @@
 use crate::ty::{self, Ty, TyCtxt};
 use rustc_hir::def_id::DefId;
 use rustc_span::source_map::Span;
-use std::iter::FromIterator;
 
 pub mod type_op {
     use crate::ty::fold::TypeFoldable;
@@ -77,8 +76,7 @@ pub fn new(value: T) -> Self {
     }
 }
 
-pub type CanonicalProjectionGoal<'tcx> =
-    Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::ProjectionTy<'tcx>>>;
+pub type CanonicalProjectionGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::AliasTy<'tcx>>>;
 
 pub type CanonicalTyGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, Ty<'tcx>>>;
 
@@ -219,6 +217,6 @@ pub struct NormalizationResult<'tcx> {
 pub enum OutlivesBound<'tcx> {
     RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>),
     RegionSubParam(ty::Region<'tcx>, ty::ParamTy),
-    RegionSubProjection(ty::Region<'tcx>, ty::ProjectionTy<'tcx>),
+    RegionSubProjection(ty::Region<'tcx>, ty::AliasTy<'tcx>),
     RegionSubOpaque(ty::Region<'tcx>, DefId, SubstsRef<'tcx>),
 }
index 7036c4a7b27d60b8da7772a1e575c33297736d4d..8ce06404de0811d64a177271ba6d4679278e007f 100644 (file)
@@ -131,7 +131,7 @@ pub fn method_call(&self, tcx: TyCtxt<'tcx>, source: Ty<'tcx>) -> Ty<'tcx> {
             .find(|m| m.kind == ty::AssocKind::Fn)
             .unwrap()
             .def_id;
-        tcx.mk_fn_def(method_def_id, tcx.mk_substs_trait(source, []))
+        tcx.mk_fn_def(method_def_id, [source])
     }
 }
 
index 75f2d45eadb81dbdea74246cedd6188b6002b6eb..8cc8286c1dbe67ea25fba051aab058f27ba18d2b 100644 (file)
@@ -310,7 +310,7 @@ fn decode(decoder: &mut D) -> &'tcx Self {
 
 impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Const<'tcx> {
     fn decode(decoder: &mut D) -> Self {
-        let consts: ty::ConstS<'tcx> = Decodable::decode(decoder);
+        let consts: ty::ConstData<'tcx> = Decodable::decode(decoder);
         decoder.interner().mk_const(consts.kind, consts.ty)
     }
 }
index c2be08e497e5bf85bc9174c7a05daf806eb91b51..e5abc38046ced9003709e43ee04b419ba6f1f63a 100644 (file)
 pub use kind::*;
 pub use valtree::*;
 
-/// Use this rather than `ConstS`, whenever possible.
+/// Use this rather than `ConstData, whenever possible.
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)]
 #[rustc_pass_by_value]
-pub struct Const<'tcx>(pub Interned<'tcx, ConstS<'tcx>>);
+pub struct Const<'tcx>(pub(super) Interned<'tcx, ConstData<'tcx>>);
 
 impl<'tcx> fmt::Debug for Const<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -30,13 +30,13 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 
 /// Typed constant value.
 #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, TyEncodable, TyDecodable)]
-pub struct ConstS<'tcx> {
+pub struct ConstData<'tcx> {
     pub ty: Ty<'tcx>,
     pub kind: ConstKind<'tcx>,
 }
 
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-static_assert_size!(ConstS<'_>, 40);
+static_assert_size!(ConstData<'_>, 40);
 
 impl<'tcx> Const<'tcx> {
     #[inline]
index f3186e1c30c3dc4b4229f8501ac5e91d33131edd..2a8a4d598882d0c0cd1b83abed69dd574fdc866d 100644 (file)
@@ -2,7 +2,6 @@
 use rustc_apfloat::Float;
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use rustc_target::abi::Size;
-use std::convert::{TryFrom, TryInto};
 use std::fmt;
 use std::num::NonZeroU8;
 
index becc2b805dd1ee9ffb3ca9c50eb6b346e697a996..d9721863a58c801fa49c21594cfc26309a2dc47d 100644 (file)
@@ -1,5 +1,3 @@
-use std::convert::TryInto;
-
 use super::Const;
 use crate::mir;
 use crate::mir::interpret::{AllocId, ConstValue, Scalar};
index 82ca1b87535d89780909a8d5c5f95789138c60b7..8f4d56c65b98575a3161cd4ef73f01f56e6c4585 100644 (file)
@@ -4,8 +4,7 @@
 
 use crate::arena::Arena;
 use crate::dep_graph::{DepGraph, DepKindStruct};
-use crate::hir::place::Place as HirPlace;
-use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
+use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
 use crate::lint::struct_lint_level;
 use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
 use crate::middle::resolve_lifetime;
 use crate::traits;
 use crate::ty::query::{self, TyCtxtAt};
 use crate::ty::{
-    self, AdtDef, AdtDefData, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig,
-    ClosureSizeProfileData, Const, ConstS, DefIdTree, FloatTy, FloatVar, FloatVid,
-    GenericParamDefKind, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy,
-    PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, ProjectionTy, Region,
-    RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, UintTy,
+    self, AdtDef, AdtDefData, AdtKind, Binder, Const, ConstData, DefIdTree, FloatTy, FloatVar,
+    FloatVid, GenericParamDefKind, ImplPolarity, InferTy, IntTy, IntVar, IntVid, List, ParamConst,
+    ParamTy, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, Region, RegionKind,
+    ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, TypeckResults, UintTy,
     Visibility,
 };
-use crate::ty::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef, UserSubsts};
+use crate::ty::{GenericArg, InternalSubsts, SubstsRef};
 use rustc_ast as ast;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::steal::Steal;
-use rustc_data_structures::sync::{self, Lock, Lrc, ReadGuard, RwLock, WorkerLocal};
-use rustc_data_structures::unord::UnordSet;
-use rustc_data_structures::vec_map::VecMap;
+use rustc_data_structures::sync::{self, Lock, Lrc, ReadGuard, WorkerLocal};
 use rustc_errors::{
     DecorateLint, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, MultiSpan,
 };
 use rustc_hir as hir;
-use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, LOCAL_CRATE};
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
 use rustc_hir::definitions::Definitions;
-use rustc_hir::hir_id::OwnerId;
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{
-    Constness, ExprKind, HirId, ImplItemKind, ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet,
-    Node, TraitCandidate, TraitItemKind,
+    Constness, ExprKind, HirId, ImplItemKind, ItemKind, Node, TraitCandidate, TraitItemKind,
 };
-use rustc_index::vec::{Idx, IndexVec};
+use rustc_index::vec::IndexVec;
 use rustc_macros::HashStable;
-use rustc_middle::mir::FakeReadCause;
 use rustc_query_system::dep_graph::DepNodeIndex;
 use rustc_query_system::ich::StableHashingContext;
 use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
 use rustc_session::config::{CrateType, OutputFilenames};
-use rustc_session::cstore::CrateStoreDyn;
+use rustc_session::cstore::{CrateStoreDyn, Untracked};
 use rustc_session::lint::Lint;
 use rustc_session::Limit;
 use rustc_session::Session;
@@ -76,7 +69,6 @@
 use std::any::Any;
 use std::borrow::Borrow;
 use std::cmp::Ordering;
-use std::collections::hash_map::{self, Entry};
 use std::fmt;
 use std::hash::{Hash, Hasher};
 use std::iter;
@@ -84,8 +76,6 @@
 use std::ops::{Bound, Deref};
 use std::sync::Arc;
 
-use super::{ImplPolarity, RvalueScopes};
-
 pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync {
     /// Creates a new `OnDiskCache` instance from the serialized data in `data`.
     fn new(sess: &'tcx Session, data: Mmap, start_pos: usize) -> Self
@@ -116,7 +106,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
     type ListBinderExistentialPredicate = &'tcx List<PolyExistentialPredicate<'tcx>>;
     type BinderListTy = Binder<'tcx, &'tcx List<Ty<'tcx>>>;
     type ListTy = &'tcx List<Ty<'tcx>>;
-    type ProjectionTy = ty::ProjectionTy<'tcx>;
+    type AliasTy = ty::AliasTy<'tcx>;
     type ParamTy = ParamTy;
     type BoundTy = ty::BoundTy;
     type PlaceholderType = ty::PlaceholderType;
@@ -150,7 +140,7 @@ pub struct CtxtInterners<'tcx> {
     predicates: InternedSet<'tcx, List<Predicate<'tcx>>>,
     projs: InternedSet<'tcx, List<ProjectionKind>>,
     place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
-    const_: InternedSet<'tcx, ConstS<'tcx>>,
+    const_: InternedSet<'tcx, ConstData<'tcx>>,
     const_allocation: InternedSet<'tcx, Allocation>,
     bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
     layout: InternedSet<'tcx, LayoutS<VariantIdx>>,
@@ -182,20 +172,12 @@ fn new(arena: &'tcx WorkerLocal<Arena<'tcx>>) -> CtxtInterners<'tcx> {
     /// Interns a type.
     #[allow(rustc::usage_of_ty_tykind)]
     #[inline(never)]
-    fn intern_ty(
-        &self,
-        kind: TyKind<'tcx>,
-        sess: &Session,
-        definitions: &rustc_hir::definitions::Definitions,
-        cstore: &CrateStoreDyn,
-        source_span: &IndexVec<LocalDefId, Span>,
-    ) -> Ty<'tcx> {
+    fn intern_ty(&self, kind: TyKind<'tcx>, sess: &Session, untracked: &Untracked) -> Ty<'tcx> {
         Ty(Interned::new_unchecked(
             self.type_
                 .intern(kind, |kind| {
                     let flags = super::flags::FlagComputation::for_kind(&kind);
-                    let stable_hash =
-                        self.stable_hash(&flags, sess, definitions, cstore, source_span, &kind);
+                    let stable_hash = self.stable_hash(&flags, sess, untracked, &kind);
 
                     InternedInSet(self.arena.alloc(WithCachedTypeInfo {
                         internee: kind,
@@ -212,9 +194,7 @@ fn stable_hash<'a, T: HashStable<StableHashingContext<'a>>>(
         &self,
         flags: &ty::flags::FlagComputation,
         sess: &'a Session,
-        definitions: &'a rustc_hir::definitions::Definitions,
-        cstore: &'a CrateStoreDyn,
-        source_span: &'a IndexVec<LocalDefId, Span>,
+        untracked: &'a Untracked,
         val: &T,
     ) -> Fingerprint {
         // It's impossible to hash inference variables (and will ICE), so we don't need to try to cache them.
@@ -223,7 +203,7 @@ fn stable_hash<'a, T: HashStable<StableHashingContext<'a>>>(
             Fingerprint::ZERO
         } else {
             let mut hasher = StableHasher::new();
-            let mut hcx = StableHashingContext::new(sess, definitions, cstore, source_span);
+            let mut hcx = StableHashingContext::new(sess, untracked);
             val.hash_stable(&mut hcx, &mut hasher);
             hasher.finish()
         }
@@ -234,17 +214,14 @@ fn intern_predicate(
         &self,
         kind: Binder<'tcx, PredicateKind<'tcx>>,
         sess: &Session,
-        definitions: &rustc_hir::definitions::Definitions,
-        cstore: &CrateStoreDyn,
-        source_span: &IndexVec<LocalDefId, Span>,
+        untracked: &Untracked,
     ) -> Predicate<'tcx> {
         Predicate(Interned::new_unchecked(
             self.predicate
                 .intern(kind, |kind| {
                     let flags = super::flags::FlagComputation::for_predicate(kind);
 
-                    let stable_hash =
-                        self.stable_hash(&flags, sess, definitions, cstore, source_span, &kind);
+                    let stable_hash = self.stable_hash(&flags, sess, untracked, &kind);
 
                     InternedInSet(self.arena.alloc(WithCachedTypeInfo {
                         internee: kind,
@@ -298,667 +275,13 @@ pub struct CommonConsts<'tcx> {
     pub unit: Const<'tcx>,
 }
 
-pub struct LocalTableInContext<'a, V> {
-    hir_owner: OwnerId,
-    data: &'a ItemLocalMap<V>,
-}
-
-/// Validate that the given HirId (respectively its `local_id` part) can be
-/// safely used as a key in the maps of a TypeckResults. For that to be
-/// the case, the HirId must have the same `owner` as all the other IDs in
-/// this table (signified by `hir_owner`). Otherwise the HirId
-/// would be in a different frame of reference and using its `local_id`
-/// would result in lookup errors, or worse, in silently wrong data being
-/// stored/returned.
-#[inline]
-fn validate_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
-    if hir_id.owner != hir_owner {
-        invalid_hir_id_for_typeck_results(hir_owner, hir_id);
-    }
-}
-
-#[cold]
-#[inline(never)]
-fn invalid_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
-    ty::tls::with(|tcx| {
-        bug!(
-            "node {} with HirId::owner {:?} cannot be placed in TypeckResults with hir_owner {:?}",
-            tcx.hir().node_to_string(hir_id),
-            hir_id.owner,
-            hir_owner
-        )
-    });
-}
-
-impl<'a, V> LocalTableInContext<'a, V> {
-    pub fn contains_key(&self, id: hir::HirId) -> bool {
-        validate_hir_id_for_typeck_results(self.hir_owner, id);
-        self.data.contains_key(&id.local_id)
-    }
-
-    pub fn get(&self, id: hir::HirId) -> Option<&V> {
-        validate_hir_id_for_typeck_results(self.hir_owner, id);
-        self.data.get(&id.local_id)
-    }
-
-    pub fn iter(&self) -> hash_map::Iter<'_, hir::ItemLocalId, V> {
-        self.data.iter()
-    }
-}
-
-impl<'a, V> ::std::ops::Index<hir::HirId> for LocalTableInContext<'a, V> {
-    type Output = V;
-
-    fn index(&self, key: hir::HirId) -> &V {
-        self.get(key).expect("LocalTableInContext: key not found")
-    }
-}
-
-pub struct LocalTableInContextMut<'a, V> {
-    hir_owner: OwnerId,
-    data: &'a mut ItemLocalMap<V>,
-}
-
-impl<'a, V> LocalTableInContextMut<'a, V> {
-    pub fn get_mut(&mut self, id: hir::HirId) -> Option<&mut V> {
-        validate_hir_id_for_typeck_results(self.hir_owner, id);
-        self.data.get_mut(&id.local_id)
-    }
-
-    pub fn entry(&mut self, id: hir::HirId) -> Entry<'_, hir::ItemLocalId, V> {
-        validate_hir_id_for_typeck_results(self.hir_owner, id);
-        self.data.entry(id.local_id)
-    }
-
-    pub fn insert(&mut self, id: hir::HirId, val: V) -> Option<V> {
-        validate_hir_id_for_typeck_results(self.hir_owner, id);
-        self.data.insert(id.local_id, val)
-    }
-
-    pub fn remove(&mut self, id: hir::HirId) -> Option<V> {
-        validate_hir_id_for_typeck_results(self.hir_owner, id);
-        self.data.remove(&id.local_id)
-    }
-}
-
-/// Whenever a value may be live across a generator yield, the type of that value winds up in the
-/// `GeneratorInteriorTypeCause` struct. This struct adds additional information about such
-/// captured types that can be useful for diagnostics. In particular, it stores the span that
-/// caused a given type to be recorded, along with the scope that enclosed the value (which can
-/// be used to find the await that the value is live across).
-///
-/// For example:
-///
-/// ```ignore (pseudo-Rust)
-/// async move {
-///     let x: T = expr;
-///     foo.await
-///     ...
-/// }
-/// ```
-///
-/// Here, we would store the type `T`, the span of the value `x`, the "scope-span" for
-/// the scope that contains `x`, the expr `T` evaluated from, and the span of `foo.await`.
-#[derive(TyEncodable, TyDecodable, Clone, Debug, Eq, Hash, PartialEq, HashStable)]
-#[derive(TypeFoldable, TypeVisitable)]
-pub struct GeneratorInteriorTypeCause<'tcx> {
-    /// Type of the captured binding.
-    pub ty: Ty<'tcx>,
-    /// Span of the binding that was captured.
-    pub span: Span,
-    /// Span of the scope of the captured binding.
-    pub scope_span: Option<Span>,
-    /// Span of `.await` or `yield` expression.
-    pub yield_span: Span,
-    /// Expr which the type evaluated from.
-    pub expr: Option<hir::HirId>,
-}
-
-// This type holds diagnostic information on generators and async functions across crate boundaries
-// and is used to provide better error messages
-#[derive(TyEncodable, TyDecodable, Clone, Debug, HashStable)]
-pub struct GeneratorDiagnosticData<'tcx> {
-    pub generator_interior_types: ty::Binder<'tcx, Vec<GeneratorInteriorTypeCause<'tcx>>>,
-    pub hir_owner: DefId,
-    pub nodes_types: ItemLocalMap<Ty<'tcx>>,
-    pub adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
-}
-
-#[derive(TyEncodable, TyDecodable, Debug, HashStable)]
-pub struct TypeckResults<'tcx> {
-    /// The `HirId::owner` all `ItemLocalId`s in this table are relative to.
-    pub hir_owner: OwnerId,
-
-    /// Resolved definitions for `<T>::X` associated paths and
-    /// method calls, including those of overloaded operators.
-    type_dependent_defs: ItemLocalMap<Result<(DefKind, DefId), ErrorGuaranteed>>,
-
-    /// Resolved field indices for field accesses in expressions (`S { field }`, `obj.field`)
-    /// or patterns (`S { field }`). The index is often useful by itself, but to learn more
-    /// about the field you also need definition of the variant to which the field
-    /// belongs, but it may not exist if it's a tuple field (`tuple.0`).
-    field_indices: ItemLocalMap<usize>,
-
-    /// Stores the types for various nodes in the AST. Note that this table
-    /// is not guaranteed to be populated outside inference. See
-    /// typeck::check::fn_ctxt for details.
-    node_types: ItemLocalMap<Ty<'tcx>>,
-
-    /// Stores the type parameters which were substituted to obtain the type
-    /// of this node. This only applies to nodes that refer to entities
-    /// parameterized by type parameters, such as generic fns, types, or
-    /// other items.
-    node_substs: ItemLocalMap<SubstsRef<'tcx>>,
-
-    /// This will either store the canonicalized types provided by the user
-    /// or the substitutions that the user explicitly gave (if any) attached
-    /// to `id`. These will not include any inferred values. The canonical form
-    /// is used to capture things like `_` or other unspecified values.
-    ///
-    /// For example, if the user wrote `foo.collect::<Vec<_>>()`, then the
-    /// canonical substitutions would include only `for<X> { Vec<X> }`.
-    ///
-    /// See also `AscribeUserType` statement in MIR.
-    user_provided_types: ItemLocalMap<CanonicalUserType<'tcx>>,
-
-    /// Stores the canonicalized types provided by the user. See also
-    /// `AscribeUserType` statement in MIR.
-    pub user_provided_sigs: LocalDefIdMap<CanonicalPolyFnSig<'tcx>>,
-
-    adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
-
-    /// Stores the actual binding mode for all instances of hir::BindingAnnotation.
-    pat_binding_modes: ItemLocalMap<BindingMode>,
-
-    /// Stores the types which were implicitly dereferenced in pattern binding modes
-    /// for later usage in THIR lowering. For example,
-    ///
-    /// ```
-    /// match &&Some(5i32) {
-    ///     Some(n) => {},
-    ///     _ => {},
-    /// }
-    /// ```
-    /// leads to a `vec![&&Option<i32>, &Option<i32>]`. Empty vectors are not stored.
-    ///
-    /// See:
-    /// <https://github.com/rust-lang/rfcs/blob/master/text/2005-match-ergonomics.md#definitions>
-    pat_adjustments: ItemLocalMap<Vec<Ty<'tcx>>>,
-
-    /// Records the reasons that we picked the kind of each closure;
-    /// not all closures are present in the map.
-    closure_kind_origins: ItemLocalMap<(Span, HirPlace<'tcx>)>,
-
-    /// For each fn, records the "liberated" types of its arguments
-    /// and return type. Liberated means that all bound regions
-    /// (including late-bound regions) are replaced with free
-    /// equivalents. This table is not used in codegen (since regions
-    /// are erased there) and hence is not serialized to metadata.
-    ///
-    /// This table also contains the "revealed" values for any `impl Trait`
-    /// that appear in the signature and whose values are being inferred
-    /// by this function.
-    ///
-    /// # Example
-    ///
-    /// ```rust
-    /// # use std::fmt::Debug;
-    /// fn foo(x: &u32) -> impl Debug { *x }
-    /// ```
-    ///
-    /// The function signature here would be:
-    ///
-    /// ```ignore (illustrative)
-    /// for<'a> fn(&'a u32) -> Foo
-    /// ```
-    ///
-    /// where `Foo` is an opaque type created for this function.
-    ///
-    ///
-    /// The *liberated* form of this would be
-    ///
-    /// ```ignore (illustrative)
-    /// fn(&'a u32) -> u32
-    /// ```
-    ///
-    /// Note that `'a` is not bound (it would be an `ReFree`) and
-    /// that the `Foo` opaque type is replaced by its hidden type.
-    liberated_fn_sigs: ItemLocalMap<ty::FnSig<'tcx>>,
-
-    /// For each FRU expression, record the normalized types of the fields
-    /// of the struct - this is needed because it is non-trivial to
-    /// normalize while preserving regions. This table is used only in
-    /// MIR construction and hence is not serialized to metadata.
-    fru_field_types: ItemLocalMap<Vec<Ty<'tcx>>>,
-
-    /// For every coercion cast we add the HIR node ID of the cast
-    /// expression to this set.
-    coercion_casts: ItemLocalSet,
-
-    /// Set of trait imports actually used in the method resolution.
-    /// This is used for warning unused imports. During type
-    /// checking, this `Lrc` should not be cloned: it must have a ref-count
-    /// of 1 so that we can insert things into the set mutably.
-    pub used_trait_imports: Lrc<UnordSet<LocalDefId>>,
-
-    /// If any errors occurred while type-checking this body,
-    /// this field will be set to `Some(ErrorGuaranteed)`.
-    pub tainted_by_errors: Option<ErrorGuaranteed>,
-
-    /// All the opaque types that have hidden types set
-    /// by this function. We also store the
-    /// type here, so that mir-borrowck can use it as a hint for figuring out hidden types,
-    /// even if they are only set in dead code (which doesn't show up in MIR).
-    pub concrete_opaque_types: VecMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
-
-    /// Tracks the minimum captures required for a closure;
-    /// see `MinCaptureInformationMap` for more details.
-    pub closure_min_captures: ty::MinCaptureInformationMap<'tcx>,
-
-    /// Tracks the fake reads required for a closure and the reason for the fake read.
-    /// When performing pattern matching for closures, there are times we don't end up
-    /// reading places that are mentioned in a closure (because of _ patterns). However,
-    /// to ensure the places are initialized, we introduce fake reads.
-    /// Consider these two examples:
-    /// ``` (discriminant matching with only wildcard arm)
-    /// let x: u8;
-    /// let c = || match x { _ => () };
-    /// ```
-    /// In this example, we don't need to actually read/borrow `x` in `c`, and so we don't
-    /// want to capture it. However, we do still want an error here, because `x` should have
-    /// to be initialized at the point where c is created. Therefore, we add a "fake read"
-    /// instead.
-    /// ``` (destructured assignments)
-    /// let c = || {
-    ///     let (t1, t2) = t;
-    /// }
-    /// ```
-    /// In the second example, we capture the disjoint fields of `t` (`t.0` & `t.1`), but
-    /// we never capture `t`. This becomes an issue when we build MIR as we require
-    /// information on `t` in order to create place `t.0` and `t.1`. We can solve this
-    /// issue by fake reading `t`.
-    pub closure_fake_reads: FxHashMap<LocalDefId, Vec<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>>,
-
-    /// Tracks the rvalue scoping rules which defines finer scoping for rvalue expressions
-    /// by applying extended parameter rules.
-    /// Details may be find in `rustc_hir_analysis::check::rvalue_scopes`.
-    pub rvalue_scopes: RvalueScopes,
-
-    /// Stores the type, expression, span and optional scope span of all types
-    /// that are live across the yield of this generator (if a generator).
-    pub generator_interior_types: ty::Binder<'tcx, Vec<GeneratorInteriorTypeCause<'tcx>>>,
-
-    /// We sometimes treat byte string literals (which are of type `&[u8; N]`)
-    /// as `&[u8]`, depending on the pattern  in which they are used.
-    /// This hashset records all instances where we behave
-    /// like this to allow `const_to_pat` to reliably handle this situation.
-    pub treat_byte_string_as_slice: ItemLocalSet,
-
-    /// Contains the data for evaluating the effect of feature `capture_disjoint_fields`
-    /// on closure size.
-    pub closure_size_eval: FxHashMap<LocalDefId, ClosureSizeProfileData<'tcx>>,
-}
-
-impl<'tcx> TypeckResults<'tcx> {
-    pub fn new(hir_owner: OwnerId) -> TypeckResults<'tcx> {
-        TypeckResults {
-            hir_owner,
-            type_dependent_defs: Default::default(),
-            field_indices: Default::default(),
-            user_provided_types: Default::default(),
-            user_provided_sigs: Default::default(),
-            node_types: Default::default(),
-            node_substs: Default::default(),
-            adjustments: Default::default(),
-            pat_binding_modes: Default::default(),
-            pat_adjustments: Default::default(),
-            closure_kind_origins: Default::default(),
-            liberated_fn_sigs: Default::default(),
-            fru_field_types: Default::default(),
-            coercion_casts: Default::default(),
-            used_trait_imports: Lrc::new(Default::default()),
-            tainted_by_errors: None,
-            concrete_opaque_types: Default::default(),
-            closure_min_captures: Default::default(),
-            closure_fake_reads: Default::default(),
-            rvalue_scopes: Default::default(),
-            generator_interior_types: ty::Binder::dummy(Default::default()),
-            treat_byte_string_as_slice: Default::default(),
-            closure_size_eval: Default::default(),
-        }
-    }
-
-    /// Returns the final resolution of a `QPath` in an `Expr` or `Pat` node.
-    pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res {
-        match *qpath {
-            hir::QPath::Resolved(_, ref path) => path.res,
-            hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
-                .type_dependent_def(id)
-                .map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
-        }
-    }
-
-    pub fn type_dependent_defs(
-        &self,
-    ) -> LocalTableInContext<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
-        LocalTableInContext { hir_owner: self.hir_owner, data: &self.type_dependent_defs }
-    }
-
-    pub fn type_dependent_def(&self, id: HirId) -> Option<(DefKind, DefId)> {
-        validate_hir_id_for_typeck_results(self.hir_owner, id);
-        self.type_dependent_defs.get(&id.local_id).cloned().and_then(|r| r.ok())
-    }
-
-    pub fn type_dependent_def_id(&self, id: HirId) -> Option<DefId> {
-        self.type_dependent_def(id).map(|(_, def_id)| def_id)
-    }
-
-    pub fn type_dependent_defs_mut(
-        &mut self,
-    ) -> LocalTableInContextMut<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
-        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.type_dependent_defs }
-    }
-
-    pub fn field_indices(&self) -> LocalTableInContext<'_, usize> {
-        LocalTableInContext { hir_owner: self.hir_owner, data: &self.field_indices }
-    }
-
-    pub fn field_indices_mut(&mut self) -> LocalTableInContextMut<'_, usize> {
-        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.field_indices }
-    }
-
-    pub fn user_provided_types(&self) -> LocalTableInContext<'_, CanonicalUserType<'tcx>> {
-        LocalTableInContext { hir_owner: self.hir_owner, data: &self.user_provided_types }
-    }
-
-    pub fn user_provided_types_mut(
-        &mut self,
-    ) -> LocalTableInContextMut<'_, CanonicalUserType<'tcx>> {
-        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.user_provided_types }
-    }
-
-    pub fn node_types(&self) -> LocalTableInContext<'_, Ty<'tcx>> {
-        LocalTableInContext { hir_owner: self.hir_owner, data: &self.node_types }
-    }
-
-    pub fn node_types_mut(&mut self) -> LocalTableInContextMut<'_, Ty<'tcx>> {
-        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_types }
-    }
-
-    pub fn get_generator_diagnostic_data(&self) -> GeneratorDiagnosticData<'tcx> {
-        let generator_interior_type = self.generator_interior_types.map_bound_ref(|vec| {
-            vec.iter()
-                .map(|item| {
-                    GeneratorInteriorTypeCause {
-                        ty: item.ty,
-                        span: item.span,
-                        scope_span: item.scope_span,
-                        yield_span: item.yield_span,
-                        expr: None, //FIXME: Passing expression over crate boundaries is impossible at the moment
-                    }
-                })
-                .collect::<Vec<_>>()
-        });
-        GeneratorDiagnosticData {
-            generator_interior_types: generator_interior_type,
-            hir_owner: self.hir_owner.to_def_id(),
-            nodes_types: self.node_types.clone(),
-            adjustments: self.adjustments.clone(),
-        }
-    }
-
-    pub fn node_type(&self, id: hir::HirId) -> Ty<'tcx> {
-        self.node_type_opt(id).unwrap_or_else(|| {
-            bug!("node_type: no type for node `{}`", tls::with(|tcx| tcx.hir().node_to_string(id)))
-        })
-    }
-
-    pub fn node_type_opt(&self, id: hir::HirId) -> Option<Ty<'tcx>> {
-        validate_hir_id_for_typeck_results(self.hir_owner, id);
-        self.node_types.get(&id.local_id).cloned()
-    }
-
-    pub fn node_substs_mut(&mut self) -> LocalTableInContextMut<'_, SubstsRef<'tcx>> {
-        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_substs }
-    }
-
-    pub fn node_substs(&self, id: hir::HirId) -> SubstsRef<'tcx> {
-        validate_hir_id_for_typeck_results(self.hir_owner, id);
-        self.node_substs.get(&id.local_id).cloned().unwrap_or_else(|| InternalSubsts::empty())
-    }
-
-    pub fn node_substs_opt(&self, id: hir::HirId) -> Option<SubstsRef<'tcx>> {
-        validate_hir_id_for_typeck_results(self.hir_owner, id);
-        self.node_substs.get(&id.local_id).cloned()
-    }
-
-    /// Returns the type of a pattern as a monotype. Like [`expr_ty`], this function
-    /// doesn't provide type parameter substitutions.
-    ///
-    /// [`expr_ty`]: TypeckResults::expr_ty
-    pub fn pat_ty(&self, pat: &hir::Pat<'_>) -> Ty<'tcx> {
-        self.node_type(pat.hir_id)
-    }
-
-    /// Returns the type of an expression as a monotype.
-    ///
-    /// NB (1): This is the PRE-ADJUSTMENT TYPE for the expression.  That is, in
-    /// some cases, we insert `Adjustment` annotations such as auto-deref or
-    /// auto-ref.  The type returned by this function does not consider such
-    /// adjustments.  See `expr_ty_adjusted()` instead.
-    ///
-    /// NB (2): This type doesn't provide type parameter substitutions; e.g., if you
-    /// ask for the type of `id` in `id(3)`, it will return `fn(&isize) -> isize`
-    /// instead of `fn(ty) -> T with T = isize`.
-    pub fn expr_ty(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
-        self.node_type(expr.hir_id)
-    }
-
-    pub fn expr_ty_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>> {
-        self.node_type_opt(expr.hir_id)
-    }
-
-    pub fn adjustments(&self) -> LocalTableInContext<'_, Vec<ty::adjustment::Adjustment<'tcx>>> {
-        LocalTableInContext { hir_owner: self.hir_owner, data: &self.adjustments }
-    }
-
-    pub fn adjustments_mut(
-        &mut self,
-    ) -> LocalTableInContextMut<'_, Vec<ty::adjustment::Adjustment<'tcx>>> {
-        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.adjustments }
-    }
-
-    pub fn expr_adjustments(&self, expr: &hir::Expr<'_>) -> &[ty::adjustment::Adjustment<'tcx>] {
-        validate_hir_id_for_typeck_results(self.hir_owner, expr.hir_id);
-        self.adjustments.get(&expr.hir_id.local_id).map_or(&[], |a| &a[..])
-    }
-
-    /// Returns the type of `expr`, considering any `Adjustment`
-    /// entry recorded for that expression.
-    pub fn expr_ty_adjusted(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
-        self.expr_adjustments(expr).last().map_or_else(|| self.expr_ty(expr), |adj| adj.target)
-    }
-
-    pub fn expr_ty_adjusted_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>> {
-        self.expr_adjustments(expr).last().map(|adj| adj.target).or_else(|| self.expr_ty_opt(expr))
-    }
-
-    pub fn is_method_call(&self, expr: &hir::Expr<'_>) -> bool {
-        // Only paths and method calls/overloaded operators have
-        // entries in type_dependent_defs, ignore the former here.
-        if let hir::ExprKind::Path(_) = expr.kind {
-            return false;
-        }
-
-        matches!(self.type_dependent_defs().get(expr.hir_id), Some(Ok((DefKind::AssocFn, _))))
-    }
-
-    pub fn extract_binding_mode(&self, s: &Session, id: HirId, sp: Span) -> Option<BindingMode> {
-        self.pat_binding_modes().get(id).copied().or_else(|| {
-            s.delay_span_bug(sp, "missing binding mode");
-            None
-        })
-    }
-
-    pub fn pat_binding_modes(&self) -> LocalTableInContext<'_, BindingMode> {
-        LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_binding_modes }
-    }
-
-    pub fn pat_binding_modes_mut(&mut self) -> LocalTableInContextMut<'_, BindingMode> {
-        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_binding_modes }
-    }
-
-    pub fn pat_adjustments(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
-        LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_adjustments }
-    }
-
-    pub fn pat_adjustments_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
-        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments }
-    }
-
-    /// For a given closure, returns the iterator of `ty::CapturedPlace`s that are captured
-    /// by the closure.
-    pub fn closure_min_captures_flattened(
-        &self,
-        closure_def_id: LocalDefId,
-    ) -> impl Iterator<Item = &ty::CapturedPlace<'tcx>> {
-        self.closure_min_captures
-            .get(&closure_def_id)
-            .map(|closure_min_captures| closure_min_captures.values().flat_map(|v| v.iter()))
-            .into_iter()
-            .flatten()
-    }
-
-    pub fn closure_kind_origins(&self) -> LocalTableInContext<'_, (Span, HirPlace<'tcx>)> {
-        LocalTableInContext { hir_owner: self.hir_owner, data: &self.closure_kind_origins }
-    }
-
-    pub fn closure_kind_origins_mut(
-        &mut self,
-    ) -> LocalTableInContextMut<'_, (Span, HirPlace<'tcx>)> {
-        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.closure_kind_origins }
-    }
-
-    pub fn liberated_fn_sigs(&self) -> LocalTableInContext<'_, ty::FnSig<'tcx>> {
-        LocalTableInContext { hir_owner: self.hir_owner, data: &self.liberated_fn_sigs }
-    }
-
-    pub fn liberated_fn_sigs_mut(&mut self) -> LocalTableInContextMut<'_, ty::FnSig<'tcx>> {
-        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.liberated_fn_sigs }
-    }
-
-    pub fn fru_field_types(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
-        LocalTableInContext { hir_owner: self.hir_owner, data: &self.fru_field_types }
-    }
-
-    pub fn fru_field_types_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
-        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.fru_field_types }
-    }
-
-    pub fn is_coercion_cast(&self, hir_id: hir::HirId) -> bool {
-        validate_hir_id_for_typeck_results(self.hir_owner, hir_id);
-        self.coercion_casts.contains(&hir_id.local_id)
-    }
-
-    pub fn set_coercion_cast(&mut self, id: ItemLocalId) {
-        self.coercion_casts.insert(id);
-    }
-
-    pub fn coercion_casts(&self) -> &ItemLocalSet {
-        &self.coercion_casts
-    }
-}
-
-rustc_index::newtype_index! {
-    pub struct UserTypeAnnotationIndex {
-        derive [HashStable]
-        DEBUG_FORMAT = "UserType({})",
-        const START_INDEX = 0,
-    }
-}
-
-/// Mapping of type annotation indices to canonical user type annotations.
-pub type CanonicalUserTypeAnnotations<'tcx> =
-    IndexVec<UserTypeAnnotationIndex, CanonicalUserTypeAnnotation<'tcx>>;
-
-#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct CanonicalUserTypeAnnotation<'tcx> {
-    pub user_ty: Box<CanonicalUserType<'tcx>>,
-    pub span: Span,
-    pub inferred_ty: Ty<'tcx>,
-}
-
-/// Canonicalized user type annotation.
-pub type CanonicalUserType<'tcx> = Canonical<'tcx, UserType<'tcx>>;
-
-impl<'tcx> CanonicalUserType<'tcx> {
-    /// Returns `true` if this represents a substitution of the form `[?0, ?1, ?2]`,
-    /// i.e., each thing is mapped to a canonical variable with the same index.
-    pub fn is_identity(&self) -> bool {
-        match self.value {
-            UserType::Ty(_) => false,
-            UserType::TypeOf(_, user_substs) => {
-                if user_substs.user_self_ty.is_some() {
-                    return false;
-                }
-
-                iter::zip(user_substs.substs, BoundVar::new(0)..).all(|(kind, cvar)| {
-                    match kind.unpack() {
-                        GenericArgKind::Type(ty) => match ty.kind() {
-                            ty::Bound(debruijn, b) => {
-                                // We only allow a `ty::INNERMOST` index in substitutions.
-                                assert_eq!(*debruijn, ty::INNERMOST);
-                                cvar == b.var
-                            }
-                            _ => false,
-                        },
-
-                        GenericArgKind::Lifetime(r) => match *r {
-                            ty::ReLateBound(debruijn, br) => {
-                                // We only allow a `ty::INNERMOST` index in substitutions.
-                                assert_eq!(debruijn, ty::INNERMOST);
-                                cvar == br.var
-                            }
-                            _ => false,
-                        },
-
-                        GenericArgKind::Const(ct) => match ct.kind() {
-                            ty::ConstKind::Bound(debruijn, b) => {
-                                // We only allow a `ty::INNERMOST` index in substitutions.
-                                assert_eq!(debruijn, ty::INNERMOST);
-                                cvar == b
-                            }
-                            _ => false,
-                        },
-                    }
-                })
-            }
-        }
-    }
-}
-
-/// A user-given type annotation attached to a constant. These arise
-/// from constants that are named via paths, like `Foo::<A>::new` and
-/// so forth.
-#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub enum UserType<'tcx> {
-    Ty(Ty<'tcx>),
-
-    /// The canonical type is the result of `type_of(def_id)` with the
-    /// given substitutions applied.
-    TypeOf(DefId, UserSubsts<'tcx>),
-}
-
 impl<'tcx> CommonTypes<'tcx> {
     fn new(
         interners: &CtxtInterners<'tcx>,
         sess: &Session,
-        definitions: &rustc_hir::definitions::Definitions,
-        cstore: &CrateStoreDyn,
-        source_span: &IndexVec<LocalDefId, Span>,
+        untracked: &Untracked,
     ) -> CommonTypes<'tcx> {
-        let mk = |ty| interners.intern_ty(ty, sess, definitions, cstore, source_span);
+        let mk = |ty| interners.intern_ty(ty, sess, untracked);
 
         CommonTypes {
             unit: mk(Tuple(List::empty())),
@@ -1008,7 +331,7 @@ fn new(interners: &CtxtInterners<'tcx>, types: &CommonTypes<'tcx>) -> CommonCons
         };
 
         CommonConsts {
-            unit: mk_const(ty::ConstS {
+            unit: mk_const(ty::ConstData {
                 kind: ty::ConstKind::Value(ty::ValTree::zst()),
                 ty: types.unit,
             }),
@@ -1104,8 +427,7 @@ pub struct GlobalCtxt<'tcx> {
     /// Common consts, pre-interned for your convenience.
     pub consts: CommonConsts<'tcx>,
 
-    definitions: RwLock<Definitions>,
-
+    untracked: Untracked,
     /// Output of the resolver.
     pub(crate) untracked_resolutions: ty::ResolverGlobalCtxt,
     /// The entire crate as AST. This field serves as the input for the hir_crate query,
@@ -1270,28 +592,21 @@ pub fn create_global_ctxt(
         lint_store: Lrc<dyn Any + sync::Send + sync::Sync>,
         arena: &'tcx WorkerLocal<Arena<'tcx>>,
         hir_arena: &'tcx WorkerLocal<hir::Arena<'tcx>>,
-        definitions: Definitions,
         untracked_resolutions: ty::ResolverGlobalCtxt,
+        untracked: Untracked,
         krate: Lrc<ast::Crate>,
         dep_graph: DepGraph,
         on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>,
         queries: &'tcx dyn query::QueryEngine<'tcx>,
         query_kinds: &'tcx [DepKindStruct<'tcx>],
-        crate_name: &str,
+        crate_name: Symbol,
         output_filenames: OutputFilenames,
     ) -> GlobalCtxt<'tcx> {
         let data_layout = s.target.parse_data_layout().unwrap_or_else(|err| {
             s.emit_fatal(err);
         });
         let interners = CtxtInterners::new(arena);
-        let common_types = CommonTypes::new(
-            &interners,
-            s,
-            &definitions,
-            &*untracked_resolutions.cstore,
-            // This is only used to create a stable hashing context.
-            &untracked_resolutions.source_span,
-        );
+        let common_types = CommonTypes::new(&interners, s, &untracked);
         let common_lifetimes = CommonLifetimes::new(&interners);
         let common_consts = CommonConsts::new(&interners, &common_types);
 
@@ -1302,11 +617,11 @@ pub fn create_global_ctxt(
             hir_arena,
             interners,
             dep_graph,
-            definitions: RwLock::new(definitions),
             prof: s.prof.clone(),
             types: common_types,
             lifetimes: common_lifetimes,
             consts: common_consts,
+            untracked,
             untracked_resolutions,
             untracked_crate: Steal::new(krate),
             on_disk_cache,
@@ -1317,7 +632,7 @@ pub fn create_global_ctxt(
             pred_rcache: Default::default(),
             selection_cache: Default::default(),
             evaluation_cache: Default::default(),
-            crate_name: Symbol::intern(crate_name),
+            crate_name,
             data_layout,
             alloc_map: Lock::new(interpret::AllocMap::new()),
             output_filenames: Arc::new(output_filenames),
@@ -1420,7 +735,7 @@ pub fn def_key(self, id: DefId) -> rustc_hir::definitions::DefKey {
         if let Some(id) = id.as_local() {
             self.definitions_untracked().def_key(id)
         } else {
-            self.untracked_resolutions.cstore.def_key(id)
+            self.untracked.cstore.def_key(id)
         }
     }
 
@@ -1434,7 +749,7 @@ pub fn def_path(self, id: DefId) -> rustc_hir::definitions::DefPath {
         if let Some(id) = id.as_local() {
             self.definitions_untracked().def_path(id)
         } else {
-            self.untracked_resolutions.cstore.def_path(id)
+            self.untracked.cstore.def_path(id)
         }
     }
 
@@ -1444,7 +759,7 @@ pub fn def_path_hash(self, def_id: DefId) -> rustc_hir::definitions::DefPathHash
         if let Some(def_id) = def_id.as_local() {
             self.definitions_untracked().def_path_hash(def_id)
         } else {
-            self.untracked_resolutions.cstore.def_path_hash(def_id)
+            self.untracked.cstore.def_path_hash(def_id)
         }
     }
 
@@ -1453,7 +768,7 @@ pub fn stable_crate_id(self, crate_num: CrateNum) -> StableCrateId {
         if crate_num == LOCAL_CRATE {
             self.sess.local_stable_crate_id()
         } else {
-            self.untracked_resolutions.cstore.stable_crate_id(crate_num)
+            self.untracked.cstore.stable_crate_id(crate_num)
         }
     }
 
@@ -1464,7 +779,7 @@ pub fn stable_crate_id_to_crate_num(self, stable_crate_id: StableCrateId) -> Cra
         if stable_crate_id == self.sess.local_stable_crate_id() {
             LOCAL_CRATE
         } else {
-            self.untracked_resolutions.cstore.stable_crate_id_to_crate_num(stable_crate_id)
+            self.untracked.cstore.stable_crate_id_to_crate_num(stable_crate_id)
         }
     }
 
@@ -1479,11 +794,11 @@ pub fn def_path_hash_to_def_id(self, hash: DefPathHash, err: &mut dyn FnMut() ->
         // If this is a DefPathHash from the local crate, we can look up the
         // DefId in the tcx's `Definitions`.
         if stable_crate_id == self.sess.local_stable_crate_id() {
-            self.definitions.read().local_def_path_hash_to_def_id(hash, err).to_def_id()
+            self.untracked.definitions.read().local_def_path_hash_to_def_id(hash, err).to_def_id()
         } else {
             // If this is a DefPathHash from an upstream crate, let the CrateStore map
             // it to a DefId.
-            let cstore = &*self.untracked_resolutions.cstore;
+            let cstore = &*self.untracked.cstore;
             let cnum = cstore.stable_crate_id_to_crate_num(stable_crate_id);
             cstore.def_path_hash_to_def_id(cnum, hash)
         }
@@ -1497,7 +812,7 @@ pub fn def_path_debug_str(self, def_id: DefId) -> String {
         let (crate_name, stable_crate_id) = if def_id.is_local() {
             (self.crate_name, self.sess.local_stable_crate_id())
         } else {
-            let cstore = &*self.untracked_resolutions.cstore;
+            let cstore = &*self.untracked.cstore;
             (cstore.crate_name(def_id.krate), cstore.stable_crate_id(def_id.krate))
         };
 
@@ -1539,7 +854,7 @@ pub fn create_def(
         // This is fine because:
         // - those queries are `eval_always` so we won't miss their result changing;
         // - this write will have happened before these queries are called.
-        let key = self.definitions.write().create_def(parent, data);
+        let key = self.untracked.definitions.write().create_def(parent, data);
 
         let feed = TyCtxtFeed { tcx: self.tcx, key };
         feed.def_span(self.span);
@@ -1553,7 +868,7 @@ pub fn iter_local_def_id(self) -> impl Iterator<Item = LocalDefId> + 'tcx {
         // definitions change.
         self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
 
-        let definitions = &self.definitions;
+        let definitions = &self.untracked.definitions;
         std::iter::from_generator(|| {
             let mut i = 0;
 
@@ -1577,7 +892,7 @@ pub fn def_path_table(self) -> &'tcx rustc_hir::definitions::DefPathTable {
 
         // Leak a read lock once we start iterating on definitions, to prevent adding new ones
         // while iterating.  If some query needs to add definitions, it should be `ensure`d above.
-        let definitions = self.definitions.leak();
+        let definitions = self.untracked.definitions.leak();
         definitions.def_path_table()
     }
 
@@ -1589,28 +904,28 @@ pub fn def_path_hash_to_def_index_map(
         self.ensure().hir_crate(());
         // Leak a read lock once we start iterating on definitions, to prevent adding new ones
         // while iterating.  If some query needs to add definitions, it should be `ensure`d above.
-        let definitions = self.definitions.leak();
+        let definitions = self.untracked.definitions.leak();
         definitions.def_path_hash_to_def_index_map()
     }
 
     /// Note that this is *untracked* and should only be used within the query
     /// system if the result is otherwise tracked through queries
     pub fn cstore_untracked(self) -> &'tcx CrateStoreDyn {
-        &*self.untracked_resolutions.cstore
+        &*self.untracked.cstore
     }
 
     /// Note that this is *untracked* and should only be used within the query
     /// system if the result is otherwise tracked through queries
     #[inline]
     pub fn definitions_untracked(self) -> ReadGuard<'tcx, Definitions> {
-        self.definitions.read()
+        self.untracked.definitions.read()
     }
 
     /// Note that this is *untracked* and should only be used within the query
     /// system if the result is otherwise tracked through queries
     #[inline]
     pub fn source_span_untracked(self, def_id: LocalDefId) -> Span {
-        self.untracked_resolutions.source_span.get(def_id).copied().unwrap_or(DUMMY_SP)
+        self.untracked.source_span.get(def_id).copied().unwrap_or(DUMMY_SP)
     }
 
     #[inline(always)]
@@ -1618,14 +933,7 @@ pub fn with_stable_hashing_context<R>(
         self,
         f: impl FnOnce(StableHashingContext<'_>) -> R,
     ) -> R {
-        let definitions = self.definitions_untracked();
-        let hcx = StableHashingContext::new(
-            self.sess,
-            &*definitions,
-            &*self.untracked_resolutions.cstore,
-            &self.untracked_resolutions.source_span,
-        );
-        f(hcx)
+        f(StableHashingContext::new(self.sess, &self.untracked))
     }
 
     pub fn serialize_query_result_cache(self, encoder: FileEncoder) -> FileEncodeResult {
@@ -2167,8 +1475,7 @@ fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                     Bound,
                     Param,
                     Infer,
-                    Projection,
-                    Opaque,
+                    Alias,
                     Foreign
                 )?;
 
@@ -2294,7 +1601,7 @@ pub fn $method(self, v: $ty) -> $ret_ty {
 
 direct_interners! {
     region: mk_region(RegionKind<'tcx>): Region -> Region<'tcx>,
-    const_: mk_const_internal(ConstS<'tcx>): Const -> Const<'tcx>,
+    const_: mk_const_internal(ConstData<'tcx>): Const -> Const<'tcx>,
     const_allocation: intern_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
     layout: intern_layout(LayoutS<VariantIdx>): Layout -> Layout<'tcx>,
     adt_def: intern_adt_def(AdtDefData): AdtDef -> AdtDef<'tcx>,
@@ -2345,7 +1652,7 @@ pub fn trait_may_define_assoc_type(self, trait_def_id: DefId, assoc_name: Ident)
 
     /// Given a `ty`, return whether it's an `impl Future<...>`.
     pub fn ty_is_opaque_future(self, ty: Ty<'_>) -> bool {
-        let ty::Opaque(def_id, _) = ty.kind() else { return false };
+        let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = ty.kind() else { return false };
         let future_trait = self.require_lang_item(LangItem::Future, None);
 
         self.explicit_item_bounds(def_id).iter().any(|(predicate, _)| {
@@ -2419,10 +1726,8 @@ pub fn mk_ty(self, st: TyKind<'tcx>) -> Ty<'tcx> {
         self.interners.intern_ty(
             st,
             self.sess,
-            &self.definitions.read(),
-            &*self.untracked_resolutions.cstore,
             // This is only used to create a stable hashing context.
-            &self.untracked_resolutions.source_span,
+            &self.untracked,
         )
     }
 
@@ -2431,10 +1736,8 @@ pub fn mk_predicate(self, binder: Binder<'tcx, PredicateKind<'tcx>>) -> Predicat
         self.interners.intern_predicate(
             binder,
             self.sess,
-            &self.definitions.read(),
-            &*self.untracked_resolutions.cstore,
             // This is only used to create a stable hashing context.
-            &self.untracked_resolutions.source_span,
+            &self.untracked,
         )
     }
 
@@ -2593,15 +1896,35 @@ pub fn mk_diverging_default(self) -> Ty<'tcx> {
     }
 
     #[inline]
-    pub fn mk_fn_def(self, def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
-        debug_assert_eq!(
-            self.generics_of(def_id).count(),
-            substs.len(),
-            "wrong number of generic parameters for {def_id:?}: {substs:?}",
-        );
+    pub fn mk_fn_def(
+        self,
+        def_id: DefId,
+        substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+    ) -> Ty<'tcx> {
+        let substs = self.check_substs(def_id, substs);
         self.mk_ty(FnDef(def_id, substs))
     }
 
+    #[inline(always)]
+    fn check_substs(
+        self,
+        _def_id: DefId,
+        substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+    ) -> SubstsRef<'tcx> {
+        let substs = substs.into_iter().map(Into::into);
+        #[cfg(debug_assertions)]
+        {
+            let n = self.generics_of(_def_id).count();
+            assert_eq!(
+                (n, Some(n)),
+                substs.size_hint(),
+                "wrong number of generic parameters for {_def_id:?}: {:?}",
+                substs.collect::<Vec<_>>(),
+            );
+        }
+        self.mk_substs(substs)
+    }
+
     #[inline]
     pub fn mk_fn_ptr(self, fty: PolyFnSig<'tcx>) -> Ty<'tcx> {
         self.mk_ty(FnPtr(fty))
@@ -2618,13 +1941,12 @@ pub fn mk_dynamic(
     }
 
     #[inline]
-    pub fn mk_projection(self, item_def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
-        debug_assert_eq!(
-            self.generics_of(item_def_id).count(),
-            substs.len(),
-            "wrong number of generic parameters for {item_def_id:?}: {substs:?}",
-        );
-        self.mk_ty(Projection(ProjectionTy { item_def_id, substs }))
+    pub fn mk_projection(
+        self,
+        item_def_id: DefId,
+        substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+    ) -> Ty<'tcx> {
+        self.mk_ty(Alias(ty::Projection, self.mk_alias_ty(item_def_id, substs)))
     }
 
     #[inline]
@@ -2654,7 +1976,7 @@ pub fn mk_ty_var(self, v: TyVid) -> Ty<'tcx> {
 
     #[inline]
     pub fn mk_const(self, kind: impl Into<ty::ConstKind<'tcx>>, ty: Ty<'tcx>) -> Const<'tcx> {
-        self.mk_const_internal(ty::ConstS { kind: kind.into(), ty })
+        self.mk_const_internal(ty::ConstData { kind: kind.into(), ty })
     }
 
     #[inline]
@@ -2694,7 +2016,7 @@ pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> GenericArg<'tcx>
 
     #[inline]
     pub fn mk_opaque(self, def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
-        self.mk_ty(Opaque(def_id, substs))
+        self.mk_ty(Alias(ty::Opaque, self.mk_alias_ty(def_id, substs)))
     }
 
     pub fn mk_place_field(self, place: Place<'tcx>, f: Field, ty: Ty<'tcx>) -> Place<'tcx> {
@@ -2883,16 +2205,17 @@ pub fn mk_trait_ref(
         trait_def_id: DefId,
         substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
     ) -> ty::TraitRef<'tcx> {
-        let substs = substs.into_iter().map(Into::into);
-        let n = self.generics_of(trait_def_id).count();
-        debug_assert_eq!(
-            (n, Some(n)),
-            substs.size_hint(),
-            "wrong number of generic parameters for {trait_def_id:?}: {:?} \nDid you accidentally include the self-type in the params list?",
-            substs.collect::<Vec<_>>(),
-        );
-        let substs = self.mk_substs(substs);
-        ty::TraitRef::new(trait_def_id, substs)
+        let substs = self.check_substs(trait_def_id, substs);
+        ty::TraitRef { def_id: trait_def_id, substs, _use_mk_trait_ref_instead: () }
+    }
+
+    pub fn mk_alias_ty(
+        self,
+        def_id: DefId,
+        substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+    ) -> ty::AliasTy<'tcx> {
+        let substs = self.check_substs(def_id, substs);
+        ty::AliasTy { def_id, substs, _use_mk_alias_ty_instead: () }
     }
 
     pub fn mk_bound_variable_kinds<
@@ -3116,4 +2439,6 @@ pub fn provide(providers: &mut ty::query::Providers) {
         // We want to check if the panic handler was defined in this crate
         tcx.lang_items().panic_impl().map_or(false, |did| did.is_local())
     };
+    providers.source_span =
+        |tcx, def_id| tcx.untracked.source_span.get(def_id).copied().unwrap_or(DUMMY_SP);
 }
index 511d51cd670fb94ff8bf013f3512e545f9ea881e..8c22df7395f1052669ad14f2e36cc7e187bf4b23 100644 (file)
@@ -3,7 +3,7 @@
 use std::ops::ControlFlow;
 
 use crate::ty::{
-    visit::TypeVisitable, Const, ConstKind, DefIdTree, ExistentialPredicate, InferConst, InferTy,
+    visit::TypeVisitable, AliasTy, Const, ConstKind, DefIdTree, InferConst, InferTy, Opaque,
     PolyTraitPredicate, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor,
 };
 
@@ -457,11 +457,11 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
                 return ControlFlow::Break(());
             }
 
-            Opaque(did, _) => {
-                let parent = self.tcx.parent(*did);
+            Alias(Opaque, AliasTy { def_id, .. }) => {
+                let parent = self.tcx.parent(*def_id);
                 if let hir::def::DefKind::TyAlias | hir::def::DefKind::AssocTy = self.tcx.def_kind(parent)
-                    && let Opaque(parent_did, _) = self.tcx.type_of(parent).kind()
-                    && parent_did == did
+                    && let Alias(Opaque, AliasTy { def_id: parent_opaque_def_id, .. }) = self.tcx.type_of(parent).kind()
+                    && parent_opaque_def_id == def_id
                 {
                     // Okay
                 } else {
@@ -469,17 +469,6 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
                 }
             }
 
-            Dynamic(dty, _, _) => {
-                for pred in *dty {
-                    match pred.skip_binder() {
-                        ExistentialPredicate::Trait(_) | ExistentialPredicate::Projection(_) => {
-                            // Okay
-                        }
-                        _ => return ControlFlow::Break(()),
-                    }
-                }
-            }
-
             Param(param) => {
                 // FIXME: It would be nice to make this not use string manipulation,
                 // but it's pretty hard to do this, since `ty::ParamTy` is missing
index d83e17574a09423c249b54034a35339c6f9f1b04..14d07608a780e6c5b33b6dbae204401251b39088 100644 (file)
@@ -1,6 +1,6 @@
 use crate::traits::{ObligationCause, ObligationCauseCode};
 use crate::ty::diagnostics::suggest_constraining_type_param;
-use crate::ty::print::{FmtPrinter, Printer};
+use crate::ty::print::{with_forced_trimmed_paths, FmtPrinter, Printer};
 use crate::ty::{self, BoundRegionKind, Region, Ty, TyCtxt};
 use hir::def::DefKind;
 use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect};
@@ -162,17 +162,29 @@ fn report_maybe_different(
             ),
             RegionsPlaceholderMismatch => write!(f, "one type is more general than the other"),
             ArgumentSorts(values, _) | Sorts(values) => ty::tls::with(|tcx| {
-                report_maybe_different(
-                    f,
-                    &values.expected.sort_string(tcx),
-                    &values.found.sort_string(tcx),
-                )
+                let (mut expected, mut found) = with_forced_trimmed_paths!((
+                    values.expected.sort_string(tcx),
+                    values.found.sort_string(tcx),
+                ));
+                if expected == found {
+                    expected = values.expected.sort_string(tcx);
+                    found = values.found.sort_string(tcx);
+                }
+                report_maybe_different(f, &expected, &found)
             }),
             Traits(values) => ty::tls::with(|tcx| {
+                let (mut expected, mut found) = with_forced_trimmed_paths!((
+                    tcx.def_path_str(values.expected),
+                    tcx.def_path_str(values.found),
+                ));
+                if expected == found {
+                    expected = tcx.def_path_str(values.expected);
+                    found = tcx.def_path_str(values.found);
+                }
                 report_maybe_different(
                     f,
-                    &format!("trait `{}`", tcx.def_path_str(values.expected)),
-                    &format!("trait `{}`", tcx.def_path_str(values.found)),
+                    &format!("trait `{expected}`"),
+                    &format!("trait `{found}`"),
                 )
             }),
             IntMismatch(ref values) => {
@@ -325,9 +337,9 @@ pub fn sort_string(self, tcx: TyCtxt<'_>) -> Cow<'static, str> {
             ty::Infer(ty::FreshTy(_)) => "fresh type".into(),
             ty::Infer(ty::FreshIntTy(_)) => "fresh integral type".into(),
             ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(),
-            ty::Projection(_) => "associated type".into(),
+            ty::Alias(ty::Projection, _) => "associated type".into(),
             ty::Param(p) => format!("type parameter `{}`", p).into(),
-            ty::Opaque(..) => "opaque type".into(),
+            ty::Alias(ty::Opaque, ..) => "opaque type".into(),
             ty::Error(_) => "type error".into(),
         }
     }
@@ -363,9 +375,9 @@ pub fn prefix_string(self, tcx: TyCtxt<'_>) -> Cow<'static, str> {
             ty::Tuple(..) => "tuple".into(),
             ty::Placeholder(..) => "higher-ranked type".into(),
             ty::Bound(..) => "bound type variable".into(),
-            ty::Projection(_) => "associated type".into(),
+            ty::Alias(ty::Projection, _) => "associated type".into(),
             ty::Param(_) => "type parameter".into(),
-            ty::Opaque(..) => "opaque type".into(),
+            ty::Alias(ty::Opaque, ..) => "opaque type".into(),
         }
     }
 }
@@ -388,7 +400,7 @@ pub fn note_and_explain_type_err(
                         diag.note("no two closures, even if identical, have the same type");
                         diag.help("consider boxing your closure and/or using it as a trait object");
                     }
-                    (ty::Opaque(..), ty::Opaque(..)) => {
+                    (ty::Alias(ty::Opaque, ..), ty::Alias(ty::Opaque, ..)) => {
                         // Issue #63167
                         diag.note("distinct uses of `impl Trait` result in different opaque types");
                     }
@@ -427,11 +439,11 @@ pub fn note_and_explain_type_err(
                              #traits-as-parameters",
                         );
                     }
-                    (ty::Projection(_), ty::Projection(_)) => {
+                    (ty::Alias(ty::Projection, _), ty::Alias(ty::Projection, _)) => {
                         diag.note("an associated type was expected, but a different one was found");
                     }
-                    (ty::Param(p), ty::Projection(proj)) | (ty::Projection(proj), ty::Param(p))
-                        if self.def_kind(proj.item_def_id) != DefKind::ImplTraitPlaceholder =>
+                    (ty::Param(p), ty::Alias(ty::Projection, proj)) | (ty::Alias(ty::Projection, proj), ty::Param(p))
+                        if self.def_kind(proj.def_id) != DefKind::ImplTraitPlaceholder =>
                     {
                         let generics = self.generics_of(body_owner_def_id);
                         let p_span = self.def_span(generics.type_param(p, self).def_id);
@@ -454,7 +466,7 @@ pub fn note_and_explain_type_err(
                             let (trait_ref, assoc_substs) = proj.trait_ref_and_own_substs(self);
                             let path =
                                 self.def_path_str_with_substs(trait_ref.def_id, trait_ref.substs);
-                            let item_name = self.item_name(proj.item_def_id);
+                            let item_name = self.item_name(proj.def_id);
                             let item_args = self.format_generic_args(assoc_substs);
 
                             let path = if path.ends_with('>') {
@@ -481,8 +493,8 @@ pub fn note_and_explain_type_err(
                             diag.note("you might be missing a type parameter or trait bound");
                         }
                     }
-                    (ty::Param(p), ty::Dynamic(..) | ty::Opaque(..))
-                    | (ty::Dynamic(..) | ty::Opaque(..), ty::Param(p)) => {
+                    (ty::Param(p), ty::Dynamic(..) | ty::Alias(ty::Opaque, ..))
+                    | (ty::Dynamic(..) | ty::Alias(ty::Opaque, ..), ty::Param(p)) => {
                         let generics = self.generics_of(body_owner_def_id);
                         let p_span = self.def_span(generics.type_param(p, self).def_id);
                         if !sp.contains(p_span) {
@@ -541,7 +553,7 @@ fn foo(&self, x: T) -> T { x }
                             diag.span_label(p_span, "this type parameter");
                         }
                     }
-                    (ty::Projection(proj_ty), _) if self.def_kind(proj_ty.item_def_id) != DefKind::ImplTraitPlaceholder => {
+                    (ty::Alias(ty::Projection, proj_ty), _) if self.def_kind(proj_ty.def_id) != DefKind::ImplTraitPlaceholder => {
                         self.expected_projection(
                             diag,
                             proj_ty,
@@ -550,7 +562,7 @@ fn foo(&self, x: T) -> T { x }
                             cause.code(),
                         );
                     }
-                    (_, ty::Projection(proj_ty)) if self.def_kind(proj_ty.item_def_id) != DefKind::ImplTraitPlaceholder => {
+                    (_, ty::Alias(ty::Projection, proj_ty)) if self.def_kind(proj_ty.def_id) != DefKind::ImplTraitPlaceholder => {
                         let msg = format!(
                             "consider constraining the associated type `{}` to `{}`",
                             values.found, values.expected,
@@ -612,10 +624,10 @@ fn suggest_constraint(
         diag: &mut Diagnostic,
         msg: &str,
         body_owner_def_id: DefId,
-        proj_ty: &ty::ProjectionTy<'tcx>,
+        proj_ty: &ty::AliasTy<'tcx>,
         ty: Ty<'tcx>,
     ) -> bool {
-        let assoc = self.associated_item(proj_ty.item_def_id);
+        let assoc = self.associated_item(proj_ty.def_id);
         let (trait_ref, assoc_substs) = proj_ty.trait_ref_and_own_substs(self);
         if let Some(item) = self.hir().get_if_local(body_owner_def_id) {
             if let Some(hir_generics) = item.generics() {
@@ -668,7 +680,7 @@ fn suggest_constraint(
     fn expected_projection(
         self,
         diag: &mut Diagnostic,
-        proj_ty: &ty::ProjectionTy<'tcx>,
+        proj_ty: &ty::AliasTy<'tcx>,
         values: ExpectedFound<Ty<'tcx>>,
         body_owner_def_id: DefId,
         cause_code: &ObligationCauseCode<'_>,
@@ -691,7 +703,7 @@ fn expected_projection(
         );
         let impl_comparison =
             matches!(cause_code, ObligationCauseCode::CompareImplItemObligation { .. });
-        let assoc = self.associated_item(proj_ty.item_def_id);
+        let assoc = self.associated_item(proj_ty.def_id);
         if !callable_scope || impl_comparison {
             // We do not want to suggest calling functions when the reason of the
             // type error is a comparison of an `impl` with its `trait` or when the
@@ -704,7 +716,7 @@ fn expected_projection(
                 diag,
                 assoc.container_id(self),
                 current_method_ident,
-                proj_ty.item_def_id,
+                proj_ty.def_id,
                 values.expected,
             );
             // Possibly suggest constraining the associated type to conform to the
@@ -763,11 +775,11 @@ fn suggest_constraining_opaque_associated_type(
         self,
         diag: &mut Diagnostic,
         msg: &str,
-        proj_ty: &ty::ProjectionTy<'tcx>,
+        proj_ty: &ty::AliasTy<'tcx>,
         ty: Ty<'tcx>,
     ) -> bool {
-        let assoc = self.associated_item(proj_ty.item_def_id);
-        if let ty::Opaque(def_id, _) = *proj_ty.self_ty().kind() {
+        let assoc = self.associated_item(proj_ty.def_id);
+        if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *proj_ty.self_ty().kind() {
             let opaque_local_def_id = def_id.as_local();
             let opaque_hir_ty = if let Some(opaque_local_def_id) = opaque_local_def_id {
                 match &self.hir().expect_item(opaque_local_def_id).kind {
@@ -816,7 +828,7 @@ fn point_at_methods_that_satisfy_associated_type(
             .filter_map(|(_, item)| {
                 let method = self.fn_sig(item.def_id);
                 match *method.output().skip_binder().kind() {
-                    ty::Projection(ty::ProjectionTy { item_def_id, .. })
+                    ty::Alias(ty::Projection, ty::AliasTy { def_id: item_def_id, .. })
                         if item_def_id == proj_ty_item_def_id =>
                     {
                         Some((
@@ -986,23 +998,34 @@ fn constrain_associated_type_structured_suggestion(
     }
 
     pub fn short_ty_string(self, ty: Ty<'tcx>) -> (String, Option<PathBuf>) {
-        let length_limit = 50;
-        let type_limit = 4;
+        let width = self.sess.diagnostic_width();
+        let length_limit = width.saturating_sub(30);
+        let mut type_limit = 50;
         let regular = FmtPrinter::new(self, hir::def::Namespace::TypeNS)
             .pretty_print_type(ty)
             .expect("could not write to `String`")
             .into_buffer();
-        if regular.len() <= length_limit {
+        if regular.len() <= width {
             return (regular, None);
         }
-        let short = FmtPrinter::new_with_limit(
-            self,
-            hir::def::Namespace::TypeNS,
-            rustc_session::Limit(type_limit),
-        )
-        .pretty_print_type(ty)
-        .expect("could not write to `String`")
-        .into_buffer();
+        let mut short;
+        loop {
+            // Look for the longest properly trimmed path that still fits in length_limit.
+            short = with_forced_trimmed_paths!(
+                FmtPrinter::new_with_limit(
+                    self,
+                    hir::def::Namespace::TypeNS,
+                    rustc_session::Limit(type_limit),
+                )
+                .pretty_print_type(ty)
+                .expect("could not write to `String`")
+                .into_buffer()
+            );
+            if short.len() <= length_limit || type_limit == 0 {
+                break;
+            }
+            type_limit -= 1;
+        }
         if regular == short {
             return (regular, None);
         }
index c9c09c93a3e1c470a9e94b68d6e8d2c7086f575c..f785fb5c4b9be5b5c57f78104e7895b029bcbabf 100644 (file)
@@ -6,28 +6,18 @@
 use std::hash::Hash;
 use std::iter;
 
-use self::SimplifiedTypeGen::*;
+use self::SimplifiedType::*;
 
-pub type SimplifiedType = SimplifiedTypeGen<DefId>;
-
-/// See `simplify_type`
-///
-/// Note that we keep this type generic over the type of identifier it uses
-/// because we sometimes need to use SimplifiedTypeGen values as stable sorting
-/// keys (in which case we use a DefPathHash as id-type) but in the general case
-/// the non-stable but fast to construct DefId-version is the better choice.
+/// See `simplify_type`.
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
-pub enum SimplifiedTypeGen<D>
-where
-    D: Copy + Debug + Eq,
-{
+pub enum SimplifiedType {
     BoolSimplifiedType,
     CharSimplifiedType,
     IntSimplifiedType(ty::IntTy),
     UintSimplifiedType(ty::UintTy),
     FloatSimplifiedType(ty::FloatTy),
-    AdtSimplifiedType(D),
-    ForeignSimplifiedType(D),
+    AdtSimplifiedType(DefId),
+    ForeignSimplifiedType(DefId),
     StrSimplifiedType,
     ArraySimplifiedType,
     SliceSimplifiedType,
@@ -38,9 +28,9 @@ pub enum SimplifiedTypeGen<D>
     /// A trait object, all of whose components are markers
     /// (e.g., `dyn Send + Sync`).
     MarkerTraitObjectSimplifiedType,
-    TraitSimplifiedType(D),
-    ClosureSimplifiedType(D),
-    GeneratorSimplifiedType(D),
+    TraitSimplifiedType(DefId),
+    ClosureSimplifiedType(DefId),
+    GeneratorSimplifiedType(DefId),
     GeneratorWitnessSimplifiedType(usize),
     FunctionSimplifiedType(usize),
     PlaceholderSimplifiedType,
@@ -126,7 +116,7 @@ pub fn simplify_type<'tcx>(
             TreatParams::AsPlaceholder => Some(PlaceholderSimplifiedType),
             TreatParams::AsInfer => None,
         },
-        ty::Opaque(..) | ty::Projection(_) => match treat_params {
+        ty::Alias(..) => match treat_params {
             // When treating `ty::Param` as a placeholder, projections also
             // don't unify with anything else as long as they are fully normalized.
             //
@@ -142,8 +132,8 @@ pub fn simplify_type<'tcx>(
     }
 }
 
-impl<D: Copy + Debug + Eq> SimplifiedTypeGen<D> {
-    pub fn def(self) -> Option<D> {
+impl SimplifiedType {
+    pub fn def(self) -> Option<DefId> {
         match self {
             AdtSimplifiedType(d)
             | ForeignSimplifiedType(d)
@@ -153,36 +143,6 @@ pub fn def(self) -> Option<D> {
             _ => None,
         }
     }
-
-    pub fn map_def<U, F>(self, map: F) -> SimplifiedTypeGen<U>
-    where
-        F: Fn(D) -> U,
-        U: Copy + Debug + Eq,
-    {
-        match self {
-            BoolSimplifiedType => BoolSimplifiedType,
-            CharSimplifiedType => CharSimplifiedType,
-            IntSimplifiedType(t) => IntSimplifiedType(t),
-            UintSimplifiedType(t) => UintSimplifiedType(t),
-            FloatSimplifiedType(t) => FloatSimplifiedType(t),
-            AdtSimplifiedType(d) => AdtSimplifiedType(map(d)),
-            ForeignSimplifiedType(d) => ForeignSimplifiedType(map(d)),
-            StrSimplifiedType => StrSimplifiedType,
-            ArraySimplifiedType => ArraySimplifiedType,
-            SliceSimplifiedType => SliceSimplifiedType,
-            RefSimplifiedType(m) => RefSimplifiedType(m),
-            PtrSimplifiedType(m) => PtrSimplifiedType(m),
-            NeverSimplifiedType => NeverSimplifiedType,
-            MarkerTraitObjectSimplifiedType => MarkerTraitObjectSimplifiedType,
-            TupleSimplifiedType(n) => TupleSimplifiedType(n),
-            TraitSimplifiedType(d) => TraitSimplifiedType(map(d)),
-            ClosureSimplifiedType(d) => ClosureSimplifiedType(map(d)),
-            GeneratorSimplifiedType(d) => GeneratorSimplifiedType(map(d)),
-            GeneratorWitnessSimplifiedType(n) => GeneratorWitnessSimplifiedType(n),
-            FunctionSimplifiedType(n) => FunctionSimplifiedType(n),
-            PlaceholderSimplifiedType => PlaceholderSimplifiedType,
-        }
-    }
 }
 
 /// Given generic arguments from an obligation and an impl,
@@ -225,7 +185,7 @@ pub fn types_may_unify<'tcx>(self, obligation_ty: Ty<'tcx>, impl_ty: Ty<'tcx>) -
         match impl_ty.kind() {
             // Start by checking whether the type in the impl may unify with
             // pretty much everything. Just return `true` in that case.
-            ty::Param(_) | ty::Projection(_) | ty::Error(_) | ty::Opaque(..) => return true,
+            ty::Param(_) | ty::Error(_) | ty::Alias(..) => return true,
             // These types only unify with inference variables or their own
             // variant.
             ty::Bool
@@ -323,8 +283,6 @@ pub fn types_may_unify<'tcx>(self, obligation_ty: Ty<'tcx>, impl_ty: Ty<'tcx>) -
                 _ => false,
             },
 
-            ty::Opaque(..) => true,
-
             // Impls cannot contain these types as these cannot be named directly.
             ty::FnDef(..) | ty::Closure(..) | ty::Generator(..) => false,
 
@@ -344,7 +302,7 @@ pub fn types_may_unify<'tcx>(self, obligation_ty: Ty<'tcx>, impl_ty: Ty<'tcx>) -
             // projections can unify with other stuff.
             //
             // Looking forward to lazy normalization this is the safer strategy anyways.
-            ty::Projection(_) => true,
+            ty::Alias(..) => true,
 
             ty::Error(_) => true,
 
index 046a2660a1f6dd51b45d23616ef786ee69767ca8..042b89bc4b01f6b4a5271e9ec4dc5d51611fabcd 100644 (file)
@@ -95,7 +95,7 @@ fn add_kind(&mut self, kind: &ty::TyKind<'_>) {
                 self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
             }
 
-            &ty::Generator(_, ref substs, _) => {
+            ty::Generator(_, substs, _) => {
                 let substs = substs.as_generator();
                 let should_remove_further_specializable =
                     !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
@@ -155,12 +155,12 @@ fn add_kind(&mut self, kind: &ty::TyKind<'_>) {
                 self.add_substs(substs);
             }
 
-            &ty::Projection(data) => {
+            &ty::Alias(ty::Projection, data) => {
                 self.add_flags(TypeFlags::HAS_TY_PROJECTION);
                 self.add_projection_ty(data);
             }
 
-            &ty::Opaque(_, substs) => {
+            &ty::Alias(ty::Opaque, ty::AliasTy { substs, .. }) => {
                 self.add_flags(TypeFlags::HAS_TY_OPAQUE);
                 self.add_substs(substs);
             }
@@ -186,7 +186,7 @@ fn add_kind(&mut self, kind: &ty::TyKind<'_>) {
 
             &ty::Slice(tt) => self.add_ty(tt),
 
-            &ty::RawPtr(ref m) => {
+            ty::RawPtr(m) => {
                 self.add_ty(m.ty);
             }
 
@@ -345,7 +345,7 @@ fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection<
         }
     }
 
-    fn add_projection_ty(&mut self, projection_ty: ty::ProjectionTy<'_>) {
+    fn add_projection_ty(&mut self, projection_ty: ty::AliasTy<'_>) {
         self.add_substs(projection_ty.substs);
     }
 
index d431d008ddf06ed96489dcea92e5a542aa74e537..09fee0c3f7c30819138b4df81f49295aa0a6d031 100644 (file)
@@ -583,36 +583,6 @@ pub fn erase_late_bound_regions<T>(self, value: Binder<'tcx, T>) -> T
         self.replace_late_bound_regions(value, |_| self.lifetimes.re_erased).0
     }
 
-    /// Rewrite any late-bound regions so that they are anonymous. Region numbers are
-    /// assigned starting at 0 and increasing monotonically in the order traversed
-    /// by the fold operation.
-    ///
-    /// The chief purpose of this function is to canonicalize regions so that two
-    /// `FnSig`s or `TraitRef`s which are equivalent up to region naming will become
-    /// structurally identical. For example, `for<'a, 'b> fn(&'a isize, &'b isize)` and
-    /// `for<'a, 'b> fn(&'b isize, &'a isize)` will become identical after anonymization.
-    pub fn anonymize_late_bound_regions<T>(self, sig: Binder<'tcx, T>) -> Binder<'tcx, T>
-    where
-        T: TypeFoldable<'tcx>,
-    {
-        let mut counter = 0;
-        let inner = self
-            .replace_late_bound_regions(sig, |_| {
-                let br = ty::BoundRegion {
-                    var: ty::BoundVar::from_u32(counter),
-                    kind: ty::BrAnon(counter, None),
-                };
-                let r = self.mk_region(ty::ReLateBound(ty::INNERMOST, br));
-                counter += 1;
-                r
-            })
-            .0;
-        let bound_vars = self.mk_bound_variable_kinds(
-            (0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i, None))),
-        );
-        Binder::bind_with_vars(inner, bound_vars)
-    }
-
     /// Anonymize all bound variables in `value`, this is mostly used to improve caching.
     pub fn anonymize_bound_vars<T>(self, value: Binder<'tcx, T>) -> Binder<'tcx, T>
     where
index 48329da3e63326049a5878ba502c28f0b1c73a19..2e70ac256a71973a768abfcd73cb943e66293cbf 100644 (file)
@@ -234,6 +234,15 @@ pub fn param_at(&'tcx self, param_index: usize, tcx: TyCtxt<'tcx>) -> &'tcx Gene
         }
     }
 
+    pub fn params_to(&'tcx self, param_index: usize, tcx: TyCtxt<'tcx>) -> &'tcx [GenericParamDef] {
+        if let Some(index) = param_index.checked_sub(self.parent_count) {
+            &self.params[..index]
+        } else {
+            tcx.generics_of(self.parent.expect("parent_count > 0 but no parent?"))
+                .params_to(param_index, tcx)
+        }
+    }
+
     /// Returns the `GenericParamDef` associated with this `EarlyBoundRegion`.
     pub fn region_param(
         &'tcx self,
index ace81bc4f8352e155330d5178968f369eed30054..5d5089cec82a696d105c196e45d16808e20569c5 100644 (file)
@@ -112,7 +112,7 @@ pub fn inhabited_predicate(self, tcx: TyCtxt<'tcx>) -> InhabitedPredicate<'tcx>
                 InhabitedPredicate::True
             }
             Never => InhabitedPredicate::False,
-            Param(_) | Projection(_) => InhabitedPredicate::GenericType(self),
+            Param(_) | Alias(ty::Projection, _) => InhabitedPredicate::GenericType(self),
             Tuple(tys) if tys.is_empty() => InhabitedPredicate::True,
             // use a query for more complex cases
             Adt(..) | Array(..) | Tuple(_) => tcx.inhabited_predicate_type(self),
index 586460986dd73cbad18633ee4f318a8be72e3c57..35d369ffc891c859e035e8555a36dec60b29fda8 100644 (file)
@@ -385,6 +385,21 @@ pub fn resolve(
         )
     }
 
+    pub fn expect_resolve(
+        tcx: TyCtxt<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        def_id: DefId,
+        substs: SubstsRef<'tcx>,
+    ) -> Instance<'tcx> {
+        match ty::Instance::resolve(tcx, param_env, def_id, substs) {
+            Ok(Some(instance)) => instance,
+            _ => bug!(
+                "failed to resolve instance for {}",
+                tcx.def_path_str_with_substs(def_id, substs)
+            ),
+        }
+    }
+
     // This should be kept up to date with `resolve`.
     pub fn resolve_opt_const_arg(
         tcx: TyCtxt<'tcx>,
@@ -525,7 +540,7 @@ pub fn resolve_closure(
     pub fn resolve_drop_in_place(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ty::Instance<'tcx> {
         let def_id = tcx.require_lang_item(LangItem::DropInPlace, None);
         let substs = tcx.intern_substs(&[ty.into()]);
-        Instance::resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap().unwrap()
+        Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs)
     }
 
     #[instrument(level = "debug", skip(tcx), ret)]
index 488fd567846a3a850f973c7a7f3328ae21f28694..7f66b993646a32058461edd9b1063ea46a892475 100644 (file)
@@ -271,7 +271,7 @@ pub fn compute(
                 let non_zero = !ty.is_unsafe_ptr();
                 let tail = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
                 match tail.kind() {
-                    ty::Param(_) | ty::Projection(_) => {
+                    ty::Param(_) | ty::Alias(ty::Projection, _) => {
                         debug_assert!(tail.has_non_region_param());
                         Ok(SizeSkeleton::Pointer { non_zero, tail: tcx.erase_regions(tail) })
                     }
@@ -349,7 +349,7 @@ pub fn compute(
                 }
             }
 
-            ty::Projection(_) | ty::Opaque(..) => {
+            ty::Alias(..) => {
                 let normalized = tcx.normalize_erasing_regions(param_env, ty);
                 if ty == normalized {
                     Err(err)
@@ -757,10 +757,9 @@ fn field_ty_or_layout<'tcx>(
                     }
                 }
 
-                ty::Projection(_)
+                ty::Alias(..)
                 | ty::Bound(..)
                 | ty::Placeholder(..)
-                | ty::Opaque(..)
                 | ty::Param(_)
                 | ty::Infer(_)
                 | ty::Error(_) => bug!("TyAndLayout::field: unexpected type `{}`", this.ty),
index cd679ffdfbc67d6f72efadd5a4fb028c2d021e94..a8e1253e67057bdc504be706707f10cc29f119d5 100644 (file)
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, LifetimeRes, Res};
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap};
-use rustc_hir::definitions::Definitions;
 use rustc_hir::Node;
 use rustc_index::vec::IndexVec;
 use rustc_macros::HashStable;
 use rustc_query_system::ich::StableHashingContext;
 use rustc_serialize::{Decodable, Encodable};
-use rustc_session::cstore::CrateStoreDyn;
+use rustc_session::cstore::Untracked;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{ExpnId, Span};
@@ -65,6 +64,7 @@
 use std::{fmt, str};
 
 pub use crate::ty::diagnostics::*;
+pub use rustc_type_ir::AliasKind::*;
 pub use rustc_type_ir::DynKind::*;
 pub use rustc_type_ir::InferTy::*;
 pub use rustc_type_ir::RegionKind::*;
     CAPTURE_STRUCT_LOCAL,
 };
 pub use self::consts::{
-    Const, ConstInt, ConstKind, ConstS, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree,
+    Const, ConstData, ConstInt, ConstKind, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree,
 };
 pub use self::context::{
-    tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
-    CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GeneratorDiagnosticData,
-    GeneratorInteriorTypeCause, GlobalCtxt, Lift, OnDiskCache, TyCtxt, TyCtxtFeed, TypeckResults,
-    UserType, UserTypeAnnotationIndex,
+    tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, OnDiskCache, TyCtxt,
+    TyCtxtFeed,
 };
 pub use self::instance::{Instance, InstanceDef, ShortInstance};
 pub use self::list::List;
 pub use self::rvalue_scopes::RvalueScopes;
 pub use self::sty::BoundRegionKind::*;
 pub use self::sty::{
-    Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar,
+    AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar,
     BoundVariableKind, CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstVid,
     EarlyBoundRegion, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig,
     FreeRegion, GenSig, GeneratorSubsts, GeneratorSubstsParts, InlineConstSubsts,
     InlineConstSubstsParts, ParamConst, ParamTy, PolyExistentialPredicate,
     PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef,
-    ProjectionTy, Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts,
-    VarianceDiagInfo,
+    Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts, VarianceDiagInfo,
 };
 pub use self::trait_def::TraitDef;
+pub use self::typeck_results::{
+    CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
+    GeneratorDiagnosticData, GeneratorInteriorTypeCause, TypeckResults, UserType,
+    UserTypeAnnotationIndex,
+};
 
 pub mod _match;
 pub mod abstract_const;
 mod rvalue_scopes;
 mod structural_impls;
 mod sty;
+mod typeck_results;
 
 // Data types
 
 pub type RegisteredTools = FxHashSet<Ident>;
 
 pub struct ResolverOutputs {
-    pub definitions: Definitions,
     pub global_ctxt: ResolverGlobalCtxt,
     pub ast_lowering: ResolverAstLowering,
+    pub untracked: Untracked,
 }
 
 #[derive(Debug)]
 pub struct ResolverGlobalCtxt {
-    pub cstore: Box<CrateStoreDyn>,
     pub visibilities: FxHashMap<LocalDefId, Visibility>,
     /// This field is used to decide whether we should make `PRIVATE_IN_PUBLIC` a hard error.
     pub has_pub_restricted: bool,
     /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`.
     pub expn_that_defined: FxHashMap<LocalDefId, ExpnId>,
-    /// Reference span for definitions.
-    pub source_span: IndexVec<LocalDefId, Span>,
     pub effective_visibilities: EffectiveVisibilities,
     pub extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
     pub maybe_unused_trait_imports: FxIndexSet<LocalDefId>,
@@ -239,7 +239,7 @@ pub struct ImplHeader<'tcx> {
     pub predicates: Vec<Predicate<'tcx>>,
 }
 
-#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)]
 pub enum ImplSubject<'tcx> {
     Trait(TraitRef<'tcx>),
     Inherent(Ty<'tcx>),
@@ -785,8 +785,8 @@ pub fn remap_constness_diag(&mut self, param_env: ParamEnv<'tcx>) {
         }
     }
 
-    pub fn with_self_type(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
-        Self { trait_ref: self.trait_ref.with_self_type(tcx, self_ty), ..self }
+    pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
+        Self { trait_ref: self.trait_ref.with_self_ty(tcx, self_ty), ..self }
     }
 
     pub fn def_id(self) -> DefId {
@@ -945,7 +945,7 @@ pub fn unpack(self) -> TermKind<'tcx> {
                     &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::TyKind<'tcx>>),
                 ))),
                 CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked(
-                    &*((ptr & !TAG_MASK) as *const ty::ConstS<'tcx>),
+                    &*((ptr & !TAG_MASK) as *const ty::ConstData<'tcx>),
                 ))),
                 _ => core::intrinsics::unreachable(),
             }
@@ -991,7 +991,7 @@ fn pack(self) -> Term<'tcx> {
             TermKind::Const(ct) => {
                 // Ensure we can use the tag bits.
                 assert_eq!(mem::align_of_val(&*ct.0.0) & TAG_MASK, 0);
-                (CONST_TAG, ct.0.0 as *const ty::ConstS<'tcx> as usize)
+                (CONST_TAG, ct.0.0 as *const ty::ConstData<'tcx> as usize)
             }
         };
 
@@ -1014,7 +1014,7 @@ fn pack(self) -> Term<'tcx> {
 #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
 pub struct ProjectionPredicate<'tcx> {
-    pub projection_ty: ProjectionTy<'tcx>,
+    pub projection_ty: AliasTy<'tcx>,
     pub term: Term<'tcx>,
 }
 
@@ -1050,7 +1050,19 @@ pub fn term(&self) -> Binder<'tcx, Term<'tcx>> {
     /// associated type, which is in `tcx.associated_item(projection_def_id()).container`.
     pub fn projection_def_id(&self) -> DefId {
         // Ok to skip binder since trait `DefId` does not care about regions.
-        self.skip_binder().projection_ty.item_def_id
+        self.skip_binder().projection_ty.def_id
+    }
+}
+
+impl<'tcx> ProjectionPredicate<'tcx> {
+    pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
+        Self {
+            projection_ty: tcx.mk_alias_ty(
+                self.projection_ty.def_id,
+                [self_ty.into()].into_iter().chain(self.projection_ty.substs.iter().skip(1)),
+            ),
+            ..self
+        }
     }
 }
 
@@ -2142,10 +2154,6 @@ pub fn opt_associated_item(self, def_id: DefId) -> Option<&'tcx AssocItem> {
         }
     }
 
-    pub fn field_index(self, hir_id: hir::HirId, typeck_results: &TypeckResults<'_>) -> usize {
-        typeck_results.field_indices().get(hir_id).cloned().expect("no index for a field")
-    }
-
     pub fn find_field_index(self, ident: Ident, variant: &VariantDef) -> Option<usize> {
         variant
             .fields
index c7d6c6abd1c22ebe153c37ae240e8f572058eee3..a21e3961cb627341211579f1a8528bb3a39b34c3 100644 (file)
@@ -1,15 +1,10 @@
 use rustc_data_structures::fx::FxHashMap;
-use rustc_hir::def_id::{DefId, DefIndex};
+use rustc_hir::def_id::DefIndex;
 use rustc_index::vec::{Idx, IndexVec};
 
-use crate::middle::exported_symbols::ExportedSymbol;
-use crate::mir::Body;
-use crate::ty::{
-    self, Clause, Const, FnSig, GeneratorDiagnosticData, GenericPredicates, Predicate, TraitRef, Ty,
-};
+use crate::ty;
 
 pub trait ParameterizedOverTcx: 'static {
-    #[allow(unused_lifetimes)]
     type Value<'tcx>;
 }
 
@@ -67,7 +62,7 @@ impl $crate::ty::ParameterizedOverTcx for $ty {
     ty::TraitDef,
     ty::Visibility<DefIndex>,
     ty::adjustment::CoerceUnsizedInfo,
-    ty::fast_reject::SimplifiedTypeGen<DefId>,
+    ty::fast_reject::SimplifiedType,
     rustc_ast::Attribute,
     rustc_ast::DelimArgs,
     rustc_attr::ConstStability,
@@ -100,29 +95,28 @@ impl $crate::ty::ParameterizedOverTcx for $ty {
     rustc_type_ir::Variance,
 }
 
-// HACK(compiler-errors): This macro rule can only take an ident,
-// not a path, due to parsing ambiguity reasons. That means we gotta
-// import all of these types above.
+// HACK(compiler-errors): This macro rule can only take a fake path,
+// not a real, due to parsing ambiguity reasons.
 #[macro_export]
 macro_rules! parameterized_over_tcx {
-    ($($ident:ident),+ $(,)?) => {
+    ($($($fake_path:ident)::+),+ $(,)?) => {
         $(
-            impl $crate::ty::ParameterizedOverTcx for $ident<'static> {
-                type Value<'tcx> = $ident<'tcx>;
+            impl $crate::ty::ParameterizedOverTcx for $($fake_path)::+<'static> {
+                type Value<'tcx> = $($fake_path)::+<'tcx>;
             }
         )*
     }
 }
 
 parameterized_over_tcx! {
-    Ty,
-    FnSig,
-    GenericPredicates,
-    TraitRef,
-    Const,
-    Predicate,
-    Clause,
-    GeneratorDiagnosticData,
-    Body,
-    ExportedSymbol,
+    crate::middle::exported_symbols::ExportedSymbol,
+    crate::mir::Body,
+    ty::Ty,
+    ty::FnSig,
+    ty::GenericPredicates,
+    ty::TraitRef,
+    ty::Const,
+    ty::Predicate,
+    ty::Clause,
+    ty::GeneratorDiagnosticData,
 }
index 667298b9b5b1316ff2738e5c08b1ceab2502be75..29bad33e4bc0f36aa5ef8f955e1ec30da54ef19a 100644 (file)
@@ -169,10 +169,8 @@ fn default_print_def_path(
                 self.path_append(
                     |cx: Self| {
                         if trait_qualify_parent {
-                            let trait_ref = ty::TraitRef::new(
-                                parent_def_id,
-                                cx.tcx().intern_substs(parent_substs),
-                            );
+                            let trait_ref =
+                                cx.tcx().mk_trait_ref(parent_def_id, parent_substs.iter().copied());
                             cx.path_qualified(trait_ref.self_ty(), Some(trait_ref))
                         } else {
                             cx.print_def_path(parent_def_id, parent_substs)
@@ -275,10 +273,9 @@ fn characteristic_def_id_of_type_cached<'a>(
         | ty::Uint(_)
         | ty::Str
         | ty::FnPtr(_)
-        | ty::Projection(_)
+        | ty::Alias(..)
         | ty::Placeholder(..)
         | ty::Param(_)
-        | ty::Opaque(..)
         | ty::Infer(_)
         | ty::Bound(..)
         | ty::Error(_)
index 5303341ba443c6c285fc170b96aa81535641b3ad..a1d53506707c9a2938749623d087c314bad761a6 100644 (file)
 use rustc_hir as hir;
 use rustc_hir::def::{self, CtorKind, DefKind, Namespace};
 use rustc_hir::def_id::{DefId, DefIdSet, CRATE_DEF_ID, LOCAL_CRATE};
-use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData};
+use rustc_hir::definitions::{DefKey, DefPathData, DefPathDataName, DisambiguatedDefPathData};
 use rustc_hir::LangItem;
 use rustc_session::config::TrimmedDefPaths;
 use rustc_session::cstore::{ExternCrate, ExternCrateSource};
 use rustc_session::Limit;
 use rustc_span::symbol::{kw, Ident, Symbol};
+use rustc_span::FileNameDisplayPreference;
 use rustc_target::abi::Size;
 use rustc_target::spec::abi::Abi;
 use smallvec::SmallVec;
@@ -23,7 +24,6 @@
 use std::cell::Cell;
 use std::char;
 use std::collections::BTreeMap;
-use std::convert::TryFrom;
 use std::fmt::{self, Write as _};
 use std::iter;
 use std::ops::{ControlFlow, Deref, DerefMut};
@@ -63,6 +63,7 @@ macro_rules! scoped_cx {
     static FORCE_IMPL_FILENAME_LINE: Cell<bool> = const { Cell::new(false) };
     static SHOULD_PREFIX_WITH_CRATE: Cell<bool> = const { Cell::new(false) };
     static NO_TRIMMED_PATH: Cell<bool> = const { Cell::new(false) };
+    static FORCE_TRIMMED_PATH: Cell<bool> = const { Cell::new(false) };
     static NO_QUERIES: Cell<bool> = const { Cell::new(false) };
     static NO_VISIBLE_PATH: Cell<bool> = const { Cell::new(false) };
 }
@@ -116,6 +117,7 @@ fn drop(&mut self) {
     /// of various rustc types, for example `std::vec::Vec` would be trimmed to `Vec`,
     /// if no other `Vec` is found.
     fn with_no_trimmed_paths(NoTrimmedGuard, NO_TRIMMED_PATH);
+    fn with_forced_trimmed_paths(ForceTrimmedGuard, FORCE_TRIMMED_PATH);
     /// Prevent selection of visible paths. `Display` impl of DefId will prefer
     /// visible (public) reexports of types as paths.
     fn with_no_visible_paths(NoVisibleGuard, NO_VISIBLE_PATH);
@@ -295,11 +297,89 @@ fn try_print_visible_def_path(self, def_id: DefId) -> Result<(Self, bool), Self:
         self.try_print_visible_def_path_recur(def_id, &mut callers)
     }
 
+    // Given a `DefId`, produce a short name. For types and traits, it prints *only* its name,
+    // For associated items on traits it prints out the trait's name and the associated item's name.
+    // For enum variants, if they have an unique name, then we only print the name, otherwise we
+    // print the enum name and the variant name. Otherwise, we do not print anything and let the
+    // caller use the `print_def_path` fallback.
+    fn force_print_trimmed_def_path(
+        mut self,
+        def_id: DefId,
+    ) -> Result<(Self::Path, bool), Self::Error> {
+        let key = self.tcx().def_key(def_id);
+        let visible_parent_map = self.tcx().visible_parent_map(());
+        let kind = self.tcx().def_kind(def_id);
+
+        let get_local_name = |this: &Self, name, def_id, key: DefKey| {
+            if let Some(visible_parent) = visible_parent_map.get(&def_id)
+                && let actual_parent = this.tcx().opt_parent(def_id)
+                && let DefPathData::TypeNs(_) = key.disambiguated_data.data
+                && Some(*visible_parent) != actual_parent
+            {
+                this
+                    .tcx()
+                    .module_children(visible_parent)
+                    .iter()
+                    .filter(|child| child.res.opt_def_id() == Some(def_id))
+                    .find(|child| child.vis.is_public() && child.ident.name != kw::Underscore)
+                    .map(|child| child.ident.name)
+                    .unwrap_or(name)
+            } else {
+                name
+            }
+        };
+        if let DefKind::Variant = kind
+            && let Some(symbol) = self.tcx().trimmed_def_paths(()).get(&def_id)
+        {
+            // If `Assoc` is unique, we don't want to talk about `Trait::Assoc`.
+            self.write_str(get_local_name(&self, *symbol, def_id, key).as_str())?;
+            return Ok((self, true));
+        }
+        if let Some(symbol) = key.get_opt_name() {
+            if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = kind
+                && let Some(parent) = self.tcx().opt_parent(def_id)
+                && let parent_key = self.tcx().def_key(parent)
+                && let Some(symbol) = parent_key.get_opt_name()
+            {
+                // Trait
+                self.write_str(get_local_name(&self, symbol, parent, parent_key).as_str())?;
+                self.write_str("::")?;
+            } else if let DefKind::Variant = kind
+                && let Some(parent) = self.tcx().opt_parent(def_id)
+                && let parent_key = self.tcx().def_key(parent)
+                && let Some(symbol) = parent_key.get_opt_name()
+            {
+                // Enum
+
+                // For associated items and variants, we want the "full" path, namely, include
+                // the parent type in the path. For example, `Iterator::Item`.
+                self.write_str(get_local_name(&self, symbol, parent, parent_key).as_str())?;
+                self.write_str("::")?;
+            } else if let DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::Trait
+                | DefKind::TyAlias | DefKind::Fn | DefKind::Const | DefKind::Static(_) = kind
+            {
+            } else {
+                // If not covered above, like for example items out of `impl` blocks, fallback.
+                return Ok((self, false));
+            }
+            self.write_str(get_local_name(&self, symbol, def_id, key).as_str())?;
+            return Ok((self, true));
+        }
+        Ok((self, false))
+    }
+
     /// Try to see if this path can be trimmed to a unique symbol name.
     fn try_print_trimmed_def_path(
         mut self,
         def_id: DefId,
     ) -> Result<(Self::Path, bool), Self::Error> {
+        if FORCE_TRIMMED_PATH.with(|flag| flag.get()) {
+            let (s, trimmed) = self.force_print_trimmed_def_path(def_id)?;
+            if trimmed {
+                return Ok((s, true));
+            }
+            self = s;
+        }
         if !self.tcx().sess.opts.unstable_opts.trim_diagnostic_paths
             || matches!(self.tcx().sess.opts.trimmed_def_paths, TrimmedDefPaths::Never)
             || NO_TRIMMED_PATH.with(|flag| flag.get())
@@ -639,17 +719,17 @@ fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error>
             ty::Foreign(def_id) => {
                 p!(print_def_path(def_id, &[]));
             }
-            ty::Projection(ref data) => {
+            ty::Alias(ty::Projection, ref data) => {
                 if !(self.should_print_verbose() || NO_QUERIES.with(|q| q.get()))
-                    && self.tcx().def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder
+                    && self.tcx().def_kind(data.def_id) == DefKind::ImplTraitPlaceholder
                 {
-                    return self.pretty_print_opaque_impl_type(data.item_def_id, data.substs);
+                    return self.pretty_print_opaque_impl_type(data.def_id, data.substs);
                 } else {
                     p!(print(data))
                 }
             }
             ty::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)),
-            ty::Opaque(def_id, substs) => {
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
                 // FIXME(eddyb) print this with `print_def_path`.
                 // We use verbose printing in 'NO_QUERIES' mode, to
                 // avoid needing to call `predicates_of`. This should
@@ -664,7 +744,9 @@ fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error>
                 let parent = self.tcx().parent(def_id);
                 match self.tcx().def_kind(parent) {
                     DefKind::TyAlias | DefKind::AssocTy => {
-                        if let ty::Opaque(d, _) = *self.tcx().type_of(parent).kind() {
+                        if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: d, .. }) =
+                            *self.tcx().type_of(parent).kind()
+                        {
                             if d == def_id {
                                 // If the type alias directly starts with the `impl` of the
                                 // opaque type we're printing, then skip the `::{opaque#1}`.
@@ -737,11 +819,16 @@ fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error>
                             p!("@", print_def_path(did.to_def_id(), substs));
                         } else {
                             let span = self.tcx().def_span(did);
+                            let preference = if FORCE_TRIMMED_PATH.with(|flag| flag.get()) {
+                                FileNameDisplayPreference::Short
+                            } else {
+                                FileNameDisplayPreference::Remapped
+                            };
                             p!(write(
                                 "@{}",
                                 // This may end up in stderr diagnostics but it may also be emitted
                                 // into MIR. Hence we use the remapped path if available
-                                self.tcx().sess.source_map().span_to_embeddable_string(span)
+                                self.tcx().sess.source_map().span_to_string(span, preference)
                             ));
                         }
                     } else {
@@ -940,8 +1027,8 @@ fn pretty_print_opaque_impl_type(
                         // Skip printing `<[generator@] as Generator<_>>::Return` from async blocks,
                         // unless we can find out what generator return type it comes from.
                         let term = if let Some(ty) = term.skip_binder().ty()
-                            && let ty::Projection(proj) = ty.kind()
-                            && let Some(assoc) = tcx.opt_associated_item(proj.item_def_id)
+                            && let ty::Alias(ty::Projection, proj) = ty.kind()
+                            && let Some(assoc) = tcx.opt_associated_item(proj.def_id)
                             && assoc.trait_container(tcx) == tcx.lang_items().gen_trait()
                             && assoc.name == rustc_span::sym::Return
                         {
@@ -2574,7 +2661,7 @@ pub struct PrintClosureAsImpl<'tcx> {
     }
 
     ty::ExistentialProjection<'tcx> {
-        let name = cx.tcx().associated_item(self.item_def_id).name;
+        let name = cx.tcx().associated_item(self.def_id).name;
         p!(write("{} = ", name), print(self.term))
     }
 
@@ -2661,8 +2748,8 @@ pub struct PrintClosureAsImpl<'tcx> {
       }
     }
 
-    ty::ProjectionTy<'tcx> {
-        p!(print_def_path(self.item_def_id, self.substs));
+    ty::AliasTy<'tcx> {
+        p!(print_def_path(self.def_id, self.substs));
     }
 
     ty::ClosureKind {
index c759fb6d5e4f4c50c05a7972032f83e6218f10b1..4d34ca3d66b5fd20b86a7b9fbbec7b0e51f60bdd 100644 (file)
@@ -106,7 +106,7 @@ fn binders<T>(
         T: Relate<'tcx>;
 }
 
-pub trait Relate<'tcx>: TypeFoldable<'tcx> + Copy {
+pub trait Relate<'tcx>: TypeFoldable<'tcx> + PartialEq + Copy {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
         a: Self,
@@ -270,21 +270,17 @@ fn relate<R: TypeRelation<'tcx>>(
     }
 }
 
-impl<'tcx> Relate<'tcx> for ty::ProjectionTy<'tcx> {
+impl<'tcx> Relate<'tcx> for ty::AliasTy<'tcx> {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
-        a: ty::ProjectionTy<'tcx>,
-        b: ty::ProjectionTy<'tcx>,
-    ) -> RelateResult<'tcx, ty::ProjectionTy<'tcx>> {
-        if a.item_def_id != b.item_def_id {
-            Err(TypeError::ProjectionMismatched(expected_found(
-                relation,
-                a.item_def_id,
-                b.item_def_id,
-            )))
+        a: ty::AliasTy<'tcx>,
+        b: ty::AliasTy<'tcx>,
+    ) -> RelateResult<'tcx, ty::AliasTy<'tcx>> {
+        if a.def_id != b.def_id {
+            Err(TypeError::ProjectionMismatched(expected_found(relation, a.def_id, b.def_id)))
         } else {
             let substs = relation.relate(a.substs, b.substs)?;
-            Ok(ty::ProjectionTy { item_def_id: a.item_def_id, substs: &substs })
+            Ok(relation.tcx().mk_alias_ty(a.def_id, substs))
         }
     }
 }
@@ -295,12 +291,8 @@ fn relate<R: TypeRelation<'tcx>>(
         a: ty::ExistentialProjection<'tcx>,
         b: ty::ExistentialProjection<'tcx>,
     ) -> RelateResult<'tcx, ty::ExistentialProjection<'tcx>> {
-        if a.item_def_id != b.item_def_id {
-            Err(TypeError::ProjectionMismatched(expected_found(
-                relation,
-                a.item_def_id,
-                b.item_def_id,
-            )))
+        if a.def_id != b.def_id {
+            Err(TypeError::ProjectionMismatched(expected_found(relation, a.def_id, b.def_id)))
         } else {
             let term = relation.relate_with_variance(
                 ty::Invariant,
@@ -314,7 +306,7 @@ fn relate<R: TypeRelation<'tcx>>(
                 a.substs,
                 b.substs,
             )?;
-            Ok(ty::ExistentialProjection { item_def_id: a.item_def_id, substs, term })
+            Ok(ty::ExistentialProjection { def_id: a.def_id, substs, term })
         }
     }
 }
@@ -330,7 +322,7 @@ fn relate<R: TypeRelation<'tcx>>(
             Err(TypeError::Traits(expected_found(relation, a.def_id, b.def_id)))
         } else {
             let substs = relate_substs(relation, a.substs, b.substs)?;
-            Ok(ty::TraitRef { def_id: a.def_id, substs })
+            Ok(relation.tcx().mk_trait_ref(a.def_id, substs))
         }
     }
 }
@@ -351,7 +343,7 @@ fn relate<R: TypeRelation<'tcx>>(
     }
 }
 
-#[derive(Copy, Debug, Clone, TypeFoldable, TypeVisitable)]
+#[derive(PartialEq, Copy, Debug, Clone, TypeFoldable, TypeVisitable)]
 struct GeneratorWitness<'tcx>(&'tcx ty::List<Ty<'tcx>>);
 
 impl<'tcx> Relate<'tcx> for GeneratorWitness<'tcx> {
@@ -436,7 +428,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
             Ok(a)
         }
 
-        (&ty::Param(ref a_p), &ty::Param(ref b_p)) if a_p.index == b_p.index => Ok(a),
+        (ty::Param(a_p), ty::Param(b_p)) if a_p.index == b_p.index => Ok(a),
 
         (ty::Placeholder(p1), ty::Placeholder(p2)) if p1 == p2 => Ok(a),
 
@@ -559,14 +551,15 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
         }
 
         // these two are already handled downstream in case of lazy normalization
-        (&ty::Projection(a_data), &ty::Projection(b_data)) => {
+        (&ty::Alias(ty::Projection, a_data), &ty::Alias(ty::Projection, b_data)) => {
             let projection_ty = relation.relate(a_data, b_data)?;
-            Ok(tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs))
+            Ok(tcx.mk_projection(projection_ty.def_id, projection_ty.substs))
         }
 
-        (&ty::Opaque(a_def_id, a_substs), &ty::Opaque(b_def_id, b_substs))
-            if a_def_id == b_def_id =>
-        {
+        (
+            &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, substs: a_substs, .. }),
+            &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, substs: b_substs, .. }),
+        ) if a_def_id == b_def_id => {
             if relation.intercrate() {
                 // During coherence, opaque types should be treated as equal to each other, even if their generic params
                 // differ, as they could resolve to the same hidden type, even for different generic params.
index 9f70b4f1ffd25291592894531cab301143c473bb..3c6800cf293dee25e44b9b807a7c14550330f8cf 100644 (file)
@@ -651,8 +651,7 @@ fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
             }
             ty::GeneratorWitness(types) => ty::GeneratorWitness(types.try_fold_with(folder)?),
             ty::Closure(did, substs) => ty::Closure(did, substs.try_fold_with(folder)?),
-            ty::Projection(data) => ty::Projection(data.try_fold_with(folder)?),
-            ty::Opaque(did, substs) => ty::Opaque(did, substs.try_fold_with(folder)?),
+            ty::Alias(kind, data) => ty::Alias(kind, data.try_fold_with(folder)?),
 
             ty::Bool
             | ty::Char
@@ -697,8 +696,7 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
             ty::Generator(_did, ref substs, _) => substs.visit_with(visitor),
             ty::GeneratorWitness(ref types) => types.visit_with(visitor),
             ty::Closure(_did, ref substs) => substs.visit_with(visitor),
-            ty::Projection(ref data) => data.visit_with(visitor),
-            ty::Opaque(_, ref substs) => substs.visit_with(visitor),
+            ty::Alias(_, ref data) => data.visit_with(visitor),
 
             ty::Bool
             | ty::Char
index 9cbda95a4df7a7f1e582dadbcf021829f45791a4..66aeebab88ba017d24bfd90895e1d1f7b58d4d94 100644 (file)
@@ -217,7 +217,7 @@ fn article(&self) -> &'static str {
 /// * `GR`: The "return type", which is the type of value returned upon
 ///   completion of the generator.
 /// * `GW`: The "generator witness".
-#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable, Lift)]
 pub struct ClosureSubsts<'tcx> {
     /// Lifetime and type parameters from the enclosing function,
     /// concatenated with a tuple containing the types of the upvars.
@@ -348,7 +348,7 @@ pub fn print_as_impl_trait(self) -> ty::print::PrintClosureAsImpl<'tcx> {
 }
 
 /// Similar to `ClosureSubsts`; see the above documentation for more.
-#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable, Lift)]
 pub struct GeneratorSubsts<'tcx> {
     pub substs: SubstsRef<'tcx>,
 }
@@ -693,7 +693,7 @@ pub fn stable_cmp(&self, tcx: TyCtxt<'tcx>, other: &Self) -> Ordering {
         match (*self, *other) {
             (Trait(_), Trait(_)) => Ordering::Equal,
             (Projection(ref a), Projection(ref b)) => {
-                tcx.def_path_hash(a.item_def_id).cmp(&tcx.def_path_hash(b.item_def_id))
+                tcx.def_path_hash(a.def_id).cmp(&tcx.def_path_hash(b.def_id))
             }
             (AutoTrait(ref a), AutoTrait(ref b)) => {
                 tcx.def_path_hash(*a).cmp(&tcx.def_path_hash(*b))
@@ -816,14 +816,13 @@ pub fn auto_traits<'a>(&'a self) -> impl Iterator<Item = DefId> + Captures<'tcx>
 pub struct TraitRef<'tcx> {
     pub def_id: DefId,
     pub substs: SubstsRef<'tcx>,
+    /// This field exists to prevent the creation of `TraitRef` without
+    /// calling [TyCtxt::mk_trait_ref].
+    pub(super) _use_mk_trait_ref_instead: (),
 }
 
 impl<'tcx> TraitRef<'tcx> {
-    pub fn new(def_id: DefId, substs: SubstsRef<'tcx>) -> TraitRef<'tcx> {
-        TraitRef { def_id, substs }
-    }
-
-    pub fn with_self_type(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
+    pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
         tcx.mk_trait_ref(
             self.def_id,
             [self_ty.into()].into_iter().chain(self.substs.iter().skip(1)),
@@ -833,10 +832,7 @@ pub fn with_self_type(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
     /// Returns a `TraitRef` of the form `P0: Foo<P1..Pn>` where `Pi`
     /// are the parameters defined on trait.
     pub fn identity(tcx: TyCtxt<'tcx>, def_id: DefId) -> Binder<'tcx, TraitRef<'tcx>> {
-        ty::Binder::dummy(TraitRef {
-            def_id,
-            substs: InternalSubsts::identity_for_item(tcx, def_id),
-        })
+        ty::Binder::dummy(tcx.mk_trait_ref(def_id, InternalSubsts::identity_for_item(tcx, def_id)))
     }
 
     #[inline]
@@ -850,7 +846,7 @@ pub fn from_method(
         substs: SubstsRef<'tcx>,
     ) -> ty::TraitRef<'tcx> {
         let defs = tcx.generics_of(trait_id);
-        ty::TraitRef { def_id: trait_id, substs: tcx.intern_substs(&substs[..defs.params.len()]) }
+        tcx.mk_trait_ref(trait_id, tcx.intern_substs(&substs[..defs.params.len()]))
     }
 }
 
@@ -980,8 +976,12 @@ impl<'tcx, T> Binder<'tcx, T>
     /// contain any bound vars that would be bound by the
     /// binder. This is commonly used to 'inject' a value T into a
     /// different binding level.
+    #[track_caller]
     pub fn dummy(value: T) -> Binder<'tcx, T> {
-        assert!(!value.has_escaping_bound_vars());
+        assert!(
+            !value.has_escaping_bound_vars(),
+            "`{value:?}` has escaping bound vars, so it cannot be wrapped in a dummy binder."
+        );
         Binder(value, ty::List::empty())
     }
 
@@ -1128,28 +1128,52 @@ pub fn transpose(self) -> Option<Binder<'tcx, T>> {
     }
 }
 
-/// Represents the projection of an associated type. In explicit UFCS
-/// form this would be written `<T as Trait<..>>::N`.
+impl<'tcx, T: IntoIterator> Binder<'tcx, T> {
+    pub fn iter(self) -> impl Iterator<Item = ty::Binder<'tcx, T::Item>> {
+        let bound_vars = self.1;
+        self.0.into_iter().map(|v| Binder(v, bound_vars))
+    }
+}
+
+/// Represents the projection of an associated type.
+///
+/// For a projection, this would be `<Ty as Trait<...>>::N`.
+///
+/// For an opaque type, there is no explicit syntax.
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct ProjectionTy<'tcx> {
-    /// The parameters of the associated item.
+pub struct AliasTy<'tcx> {
+    /// The parameters of the associated or opaque item.
+    ///
+    /// For a projection, these are the substitutions for the trait and the
+    /// GAT substitutions, if there are any.
+    ///
+    /// For RPIT the substitutions are for the generics of the function,
+    /// while for TAIT it is used for the generic parameters of the alias.
     pub substs: SubstsRef<'tcx>,
 
-    /// The `DefId` of the `TraitItem` for the associated type `N`.
+    /// The `DefId` of the `TraitItem` for the associated type `N` if this is a projection,
+    /// or the `OpaqueType` item if this is an opaque.
     ///
-    /// Note that this is not the `DefId` of the `TraitRef` containing this
-    /// associated type, which is in `tcx.associated_item(item_def_id).container`,
-    /// aka. `tcx.parent(item_def_id).unwrap()`.
-    pub item_def_id: DefId,
+    /// During codegen, `tcx.type_of(def_id)` can be used to get the type of the
+    /// underlying type if the type is an opaque.
+    ///
+    /// Note that if this is an associated type, this is not the `DefId` of the
+    /// `TraitRef` containing this associated type, which is in `tcx.associated_item(def_id).container`,
+    /// aka. `tcx.parent(def_id)`.
+    pub def_id: DefId,
+
+    /// This field exists to prevent the creation of `ProjectionTy` without using
+    /// [TyCtxt::mk_alias_ty].
+    pub(super) _use_mk_alias_ty_instead: (),
 }
 
-impl<'tcx> ProjectionTy<'tcx> {
+impl<'tcx> AliasTy<'tcx> {
     pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId {
-        match tcx.def_kind(self.item_def_id) {
-            DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.item_def_id),
+        match tcx.def_kind(self.def_id) {
+            DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.def_id),
             DefKind::ImplTraitPlaceholder => {
-                tcx.parent(tcx.impl_trait_in_trait_parent(self.item_def_id))
+                tcx.parent(tcx.impl_trait_in_trait_parent(self.def_id))
             }
             kind => bug!("unexpected DefKind in ProjectionTy: {kind:?}"),
         }
@@ -1162,11 +1186,11 @@ pub fn trait_ref_and_own_substs(
         &self,
         tcx: TyCtxt<'tcx>,
     ) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) {
-        let def_id = tcx.parent(self.item_def_id);
-        assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
-        let trait_generics = tcx.generics_of(def_id);
+        debug_assert!(matches!(tcx.def_kind(self.def_id), DefKind::AssocTy | DefKind::AssocConst));
+        let trait_def_id = self.trait_def_id(tcx);
+        let trait_generics = tcx.generics_of(trait_def_id);
         (
-            ty::TraitRef { def_id, substs: self.substs.truncate_to(tcx, trait_generics) },
+            tcx.mk_trait_ref(trait_def_id, self.substs.truncate_to(tcx, trait_generics)),
             &self.substs[trait_generics.count()..],
         )
     }
@@ -1180,7 +1204,7 @@ pub fn trait_ref_and_own_substs(
     /// as well.
     pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> {
         let def_id = self.trait_def_id(tcx);
-        ty::TraitRef { def_id, substs: self.substs.truncate_to(tcx, tcx.generics_of(def_id)) }
+        tcx.mk_trait_ref(def_id, self.substs.truncate_to(tcx, tcx.generics_of(def_id)))
     }
 
     pub fn self_ty(&self) -> Ty<'tcx> {
@@ -1394,7 +1418,7 @@ fn from(var: BoundVar) -> Self {
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
 pub struct ExistentialProjection<'tcx> {
-    pub item_def_id: DefId,
+    pub def_id: DefId,
     pub substs: SubstsRef<'tcx>,
     pub term: Term<'tcx>,
 }
@@ -1407,7 +1431,7 @@ impl<'tcx> ExistentialProjection<'tcx> {
     /// then this function would return an `exists T. T: Iterator` existential trait
     /// reference.
     pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::ExistentialTraitRef<'tcx> {
-        let def_id = tcx.parent(self.item_def_id);
+        let def_id = tcx.parent(self.def_id);
         let subst_count = tcx.generics_of(def_id).count() - 1;
         let substs = tcx.intern_substs(&self.substs[..subst_count]);
         ty::ExistentialTraitRef { def_id, substs }
@@ -1422,10 +1446,8 @@ pub fn with_self_ty(
         debug_assert!(!self_ty.has_escaping_bound_vars());
 
         ty::ProjectionPredicate {
-            projection_ty: ty::ProjectionTy {
-                item_def_id: self.item_def_id,
-                substs: tcx.mk_substs_trait(self_ty, self.substs),
-            },
+            projection_ty: tcx
+                .mk_alias_ty(self.def_id, [self_ty.into()].into_iter().chain(self.substs)),
             term: self.term,
         }
     }
@@ -1438,7 +1460,7 @@ pub fn erase_self_ty(
         projection_predicate.projection_ty.substs.type_at(0);
 
         Self {
-            item_def_id: projection_predicate.projection_ty.item_def_id,
+            def_id: projection_predicate.projection_ty.def_id,
             substs: tcx.intern_substs(&projection_predicate.projection_ty.substs[1..]),
             term: projection_predicate.term,
         }
@@ -1455,7 +1477,7 @@ pub fn with_self_ty(
     }
 
     pub fn item_def_id(&self) -> DefId {
-        self.skip_binder().item_def_id
+        self.skip_binder().def_id
     }
 }
 
@@ -1962,7 +1984,7 @@ pub fn is_fn_ptr(self) -> bool {
 
     #[inline]
     pub fn is_impl_trait(self) -> bool {
-        matches!(self.kind(), Opaque(..))
+        matches!(self.kind(), Alias(ty::Opaque, ..))
     }
 
     #[inline]
@@ -2029,7 +2051,7 @@ pub fn discriminant_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
             ty::Adt(adt, _) if adt.is_enum() => adt.repr().discr_type().to_ty(tcx),
             ty::Generator(_, substs, _) => substs.as_generator().discr_ty(tcx),
 
-            ty::Param(_) | ty::Projection(_) | ty::Opaque(..) | ty::Infer(ty::TyVar(_)) => {
+            ty::Param(_) | ty::Alias(..) | ty::Infer(ty::TyVar(_)) => {
                 let assoc_items = tcx.associated_item_def_ids(
                     tcx.require_lang_item(hir::LangItem::DiscriminantKind, None),
                 );
@@ -2109,7 +2131,7 @@ pub fn ptr_metadata_ty(
 
             // type parameters only have unit metadata if they're sized, so return true
             // to make sure we double check this during confirmation
-            ty::Param(_) |  ty::Projection(_) | ty::Opaque(..) => (tcx.types.unit, true),
+            ty::Param(_) |  ty::Alias(..) => (tcx.types.unit, true),
 
             ty::Infer(ty::TyVar(_))
             | ty::Bound(..)
@@ -2185,7 +2207,7 @@ pub fn is_trivially_sized(self, tcx: TyCtxt<'tcx>) -> bool {
 
             ty::Adt(def, _substs) => def.sized_constraint(tcx).0.is_empty(),
 
-            ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => false,
+            ty::Alias(..) | ty::Param(_) => false,
 
             ty::Infer(ty::TyVar(_)) => false,
 
@@ -2241,9 +2263,12 @@ pub fn is_trivially_pure_clone_copy(self) -> bool {
             ty::Generator(..) | ty::GeneratorWitness(..) => false,
 
             // Might be, but not "trivial" so just giving the safe answer.
-            ty::Adt(..) | ty::Closure(..) | ty::Opaque(..) => false,
+            ty::Adt(..) | ty::Closure(..) => false,
+
+            // Needs normalization or revealing to determine, so no is the safe answer.
+            ty::Alias(..) => false,
 
-            ty::Projection(..) | ty::Param(..) | ty::Infer(..) | ty::Error(..) => false,
+            ty::Param(..) | ty::Infer(..) | ty::Error(..) => false,
 
             ty::Bound(..) | ty::Placeholder(..) => {
                 bug!("`is_trivially_pure_clone_copy` applied to unexpected type: {:?}", self);
index a1b084a5e891eca1bb2bf780597bae2fb06cbb40..a04b15f8cf13c52385a886956a9d07229c31bd02 100644 (file)
@@ -90,7 +90,7 @@ fn pack(self) -> GenericArg<'tcx> {
             GenericArgKind::Const(ct) => {
                 // Ensure we can use the tag bits.
                 assert_eq!(mem::align_of_val(&*ct.0.0) & TAG_MASK, 0);
-                (CONST_TAG, ct.0.0 as *const ty::ConstS<'tcx> as usize)
+                (CONST_TAG, ct.0.0 as *const ty::ConstData<'tcx> as usize)
             }
         };
 
@@ -166,7 +166,7 @@ pub fn unpack(self) -> GenericArgKind<'tcx> {
                     &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::TyKind<'tcx>>),
                 ))),
                 CONST_TAG => GenericArgKind::Const(ty::Const(Interned::new_unchecked(
-                    &*((ptr & !TAG_MASK) as *const ty::ConstS<'tcx>),
+                    &*((ptr & !TAG_MASK) as *const ty::ConstData<'tcx>),
                 ))),
                 _ => intrinsics::unreachable(),
             }
@@ -252,7 +252,7 @@ fn decode(d: &mut D) -> GenericArg<'tcx> {
     }
 }
 
-/// A substitution mapping generic parameters to new values.
+/// List of generic arguments that are gonna be used to substitute generic parameters.
 pub type InternalSubsts<'tcx> = List<GenericArg<'tcx>>;
 
 pub type SubstsRef<'tcx> = &'tcx InternalSubsts<'tcx>;
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
new file mode 100644 (file)
index 0000000..4fe85d4
--- /dev/null
@@ -0,0 +1,689 @@
+use crate::{
+    hir::place::Place as HirPlace,
+    infer::canonical::Canonical,
+    ty::{
+        self, tls, BindingMode, BoundVar, CanonicalPolyFnSig, ClosureSizeProfileData,
+        GenericArgKind, InternalSubsts, SubstsRef, Ty, UserSubsts,
+    },
+};
+use rustc_data_structures::{fx::FxHashMap, sync::Lrc, unord::UnordSet, vec_map::VecMap};
+use rustc_errors::ErrorGuaranteed;
+use rustc_hir as hir;
+use rustc_hir::{
+    def::{DefKind, Res},
+    def_id::{DefId, LocalDefId, LocalDefIdMap},
+    hir_id::OwnerId,
+    HirId, ItemLocalId, ItemLocalMap, ItemLocalSet,
+};
+use rustc_index::vec::{Idx, IndexVec};
+use rustc_macros::HashStable;
+use rustc_middle::mir::FakeReadCause;
+use rustc_session::Session;
+use rustc_span::Span;
+use std::{
+    collections::hash_map::{self, Entry},
+    hash::Hash,
+    iter,
+};
+
+use super::RvalueScopes;
+
+#[derive(TyEncodable, TyDecodable, Debug, HashStable)]
+pub struct TypeckResults<'tcx> {
+    /// The `HirId::owner` all `ItemLocalId`s in this table are relative to.
+    pub hir_owner: OwnerId,
+
+    /// Resolved definitions for `<T>::X` associated paths and
+    /// method calls, including those of overloaded operators.
+    type_dependent_defs: ItemLocalMap<Result<(DefKind, DefId), ErrorGuaranteed>>,
+
+    /// Resolved field indices for field accesses in expressions (`S { field }`, `obj.field`)
+    /// or patterns (`S { field }`). The index is often useful by itself, but to learn more
+    /// about the field you also need definition of the variant to which the field
+    /// belongs, but it may not exist if it's a tuple field (`tuple.0`).
+    field_indices: ItemLocalMap<usize>,
+
+    /// Stores the types for various nodes in the AST. Note that this table
+    /// is not guaranteed to be populated outside inference. See
+    /// typeck::check::fn_ctxt for details.
+    node_types: ItemLocalMap<Ty<'tcx>>,
+
+    /// Stores the type parameters which were substituted to obtain the type
+    /// of this node. This only applies to nodes that refer to entities
+    /// parameterized by type parameters, such as generic fns, types, or
+    /// other items.
+    node_substs: ItemLocalMap<SubstsRef<'tcx>>,
+
+    /// This will either store the canonicalized types provided by the user
+    /// or the substitutions that the user explicitly gave (if any) attached
+    /// to `id`. These will not include any inferred values. The canonical form
+    /// is used to capture things like `_` or other unspecified values.
+    ///
+    /// For example, if the user wrote `foo.collect::<Vec<_>>()`, then the
+    /// canonical substitutions would include only `for<X> { Vec<X> }`.
+    ///
+    /// See also `AscribeUserType` statement in MIR.
+    user_provided_types: ItemLocalMap<CanonicalUserType<'tcx>>,
+
+    /// Stores the canonicalized types provided by the user. See also
+    /// `AscribeUserType` statement in MIR.
+    pub user_provided_sigs: LocalDefIdMap<CanonicalPolyFnSig<'tcx>>,
+
+    adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
+
+    /// Stores the actual binding mode for all instances of hir::BindingAnnotation.
+    pat_binding_modes: ItemLocalMap<BindingMode>,
+
+    /// Stores the types which were implicitly dereferenced in pattern binding modes
+    /// for later usage in THIR lowering. For example,
+    ///
+    /// ```
+    /// match &&Some(5i32) {
+    ///     Some(n) => {},
+    ///     _ => {},
+    /// }
+    /// ```
+    /// leads to a `vec![&&Option<i32>, &Option<i32>]`. Empty vectors are not stored.
+    ///
+    /// See:
+    /// <https://github.com/rust-lang/rfcs/blob/master/text/2005-match-ergonomics.md#definitions>
+    pat_adjustments: ItemLocalMap<Vec<Ty<'tcx>>>,
+
+    /// Records the reasons that we picked the kind of each closure;
+    /// not all closures are present in the map.
+    closure_kind_origins: ItemLocalMap<(Span, HirPlace<'tcx>)>,
+
+    /// For each fn, records the "liberated" types of its arguments
+    /// and return type. Liberated means that all bound regions
+    /// (including late-bound regions) are replaced with free
+    /// equivalents. This table is not used in codegen (since regions
+    /// are erased there) and hence is not serialized to metadata.
+    ///
+    /// This table also contains the "revealed" values for any `impl Trait`
+    /// that appear in the signature and whose values are being inferred
+    /// by this function.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// # use std::fmt::Debug;
+    /// fn foo(x: &u32) -> impl Debug { *x }
+    /// ```
+    ///
+    /// The function signature here would be:
+    ///
+    /// ```ignore (illustrative)
+    /// for<'a> fn(&'a u32) -> Foo
+    /// ```
+    ///
+    /// where `Foo` is an opaque type created for this function.
+    ///
+    ///
+    /// The *liberated* form of this would be
+    ///
+    /// ```ignore (illustrative)
+    /// fn(&'a u32) -> u32
+    /// ```
+    ///
+    /// Note that `'a` is not bound (it would be an `ReFree`) and
+    /// that the `Foo` opaque type is replaced by its hidden type.
+    liberated_fn_sigs: ItemLocalMap<ty::FnSig<'tcx>>,
+
+    /// For each FRU expression, record the normalized types of the fields
+    /// of the struct - this is needed because it is non-trivial to
+    /// normalize while preserving regions. This table is used only in
+    /// MIR construction and hence is not serialized to metadata.
+    fru_field_types: ItemLocalMap<Vec<Ty<'tcx>>>,
+
+    /// For every coercion cast we add the HIR node ID of the cast
+    /// expression to this set.
+    coercion_casts: ItemLocalSet,
+
+    /// Set of trait imports actually used in the method resolution.
+    /// This is used for warning unused imports. During type
+    /// checking, this `Lrc` should not be cloned: it must have a ref-count
+    /// of 1 so that we can insert things into the set mutably.
+    pub used_trait_imports: Lrc<UnordSet<LocalDefId>>,
+
+    /// If any errors occurred while type-checking this body,
+    /// this field will be set to `Some(ErrorGuaranteed)`.
+    pub tainted_by_errors: Option<ErrorGuaranteed>,
+
+    /// All the opaque types that have hidden types set
+    /// by this function. We also store the
+    /// type here, so that mir-borrowck can use it as a hint for figuring out hidden types,
+    /// even if they are only set in dead code (which doesn't show up in MIR).
+    pub concrete_opaque_types: VecMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
+
+    /// Tracks the minimum captures required for a closure;
+    /// see `MinCaptureInformationMap` for more details.
+    pub closure_min_captures: ty::MinCaptureInformationMap<'tcx>,
+
+    /// Tracks the fake reads required for a closure and the reason for the fake read.
+    /// When performing pattern matching for closures, there are times we don't end up
+    /// reading places that are mentioned in a closure (because of _ patterns). However,
+    /// to ensure the places are initialized, we introduce fake reads.
+    /// Consider these two examples:
+    /// ``` (discriminant matching with only wildcard arm)
+    /// let x: u8;
+    /// let c = || match x { _ => () };
+    /// ```
+    /// In this example, we don't need to actually read/borrow `x` in `c`, and so we don't
+    /// want to capture it. However, we do still want an error here, because `x` should have
+    /// to be initialized at the point where c is created. Therefore, we add a "fake read"
+    /// instead.
+    /// ``` (destructured assignments)
+    /// let c = || {
+    ///     let (t1, t2) = t;
+    /// }
+    /// ```
+    /// In the second example, we capture the disjoint fields of `t` (`t.0` & `t.1`), but
+    /// we never capture `t`. This becomes an issue when we build MIR as we require
+    /// information on `t` in order to create place `t.0` and `t.1`. We can solve this
+    /// issue by fake reading `t`.
+    pub closure_fake_reads: FxHashMap<LocalDefId, Vec<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>>,
+
+    /// Tracks the rvalue scoping rules which defines finer scoping for rvalue expressions
+    /// by applying extended parameter rules.
+    /// Details may be find in `rustc_hir_analysis::check::rvalue_scopes`.
+    pub rvalue_scopes: RvalueScopes,
+
+    /// Stores the type, expression, span and optional scope span of all types
+    /// that are live across the yield of this generator (if a generator).
+    pub generator_interior_types: ty::Binder<'tcx, Vec<GeneratorInteriorTypeCause<'tcx>>>,
+
+    /// We sometimes treat byte string literals (which are of type `&[u8; N]`)
+    /// as `&[u8]`, depending on the pattern  in which they are used.
+    /// This hashset records all instances where we behave
+    /// like this to allow `const_to_pat` to reliably handle this situation.
+    pub treat_byte_string_as_slice: ItemLocalSet,
+
+    /// Contains the data for evaluating the effect of feature `capture_disjoint_fields`
+    /// on closure size.
+    pub closure_size_eval: FxHashMap<LocalDefId, ClosureSizeProfileData<'tcx>>,
+}
+
+/// Whenever a value may be live across a generator yield, the type of that value winds up in the
+/// `GeneratorInteriorTypeCause` struct. This struct adds additional information about such
+/// captured types that can be useful for diagnostics. In particular, it stores the span that
+/// caused a given type to be recorded, along with the scope that enclosed the value (which can
+/// be used to find the await that the value is live across).
+///
+/// For example:
+///
+/// ```ignore (pseudo-Rust)
+/// async move {
+///     let x: T = expr;
+///     foo.await
+///     ...
+/// }
+/// ```
+///
+/// Here, we would store the type `T`, the span of the value `x`, the "scope-span" for
+/// the scope that contains `x`, the expr `T` evaluated from, and the span of `foo.await`.
+#[derive(TyEncodable, TyDecodable, Clone, Debug, Eq, Hash, PartialEq, HashStable)]
+#[derive(TypeFoldable, TypeVisitable)]
+pub struct GeneratorInteriorTypeCause<'tcx> {
+    /// Type of the captured binding.
+    pub ty: Ty<'tcx>,
+    /// Span of the binding that was captured.
+    pub span: Span,
+    /// Span of the scope of the captured binding.
+    pub scope_span: Option<Span>,
+    /// Span of `.await` or `yield` expression.
+    pub yield_span: Span,
+    /// Expr which the type evaluated from.
+    pub expr: Option<hir::HirId>,
+}
+
+// This type holds diagnostic information on generators and async functions across crate boundaries
+// and is used to provide better error messages
+#[derive(TyEncodable, TyDecodable, Clone, Debug, HashStable)]
+pub struct GeneratorDiagnosticData<'tcx> {
+    pub generator_interior_types: ty::Binder<'tcx, Vec<GeneratorInteriorTypeCause<'tcx>>>,
+    pub hir_owner: DefId,
+    pub nodes_types: ItemLocalMap<Ty<'tcx>>,
+    pub adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
+}
+
+impl<'tcx> TypeckResults<'tcx> {
+    pub fn new(hir_owner: OwnerId) -> TypeckResults<'tcx> {
+        TypeckResults {
+            hir_owner,
+            type_dependent_defs: Default::default(),
+            field_indices: Default::default(),
+            user_provided_types: Default::default(),
+            user_provided_sigs: Default::default(),
+            node_types: Default::default(),
+            node_substs: Default::default(),
+            adjustments: Default::default(),
+            pat_binding_modes: Default::default(),
+            pat_adjustments: Default::default(),
+            closure_kind_origins: Default::default(),
+            liberated_fn_sigs: Default::default(),
+            fru_field_types: Default::default(),
+            coercion_casts: Default::default(),
+            used_trait_imports: Lrc::new(Default::default()),
+            tainted_by_errors: None,
+            concrete_opaque_types: Default::default(),
+            closure_min_captures: Default::default(),
+            closure_fake_reads: Default::default(),
+            rvalue_scopes: Default::default(),
+            generator_interior_types: ty::Binder::dummy(Default::default()),
+            treat_byte_string_as_slice: Default::default(),
+            closure_size_eval: Default::default(),
+        }
+    }
+
+    /// Returns the final resolution of a `QPath` in an `Expr` or `Pat` node.
+    pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res {
+        match *qpath {
+            hir::QPath::Resolved(_, ref path) => path.res,
+            hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
+                .type_dependent_def(id)
+                .map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
+        }
+    }
+
+    pub fn type_dependent_defs(
+        &self,
+    ) -> LocalTableInContext<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
+        LocalTableInContext { hir_owner: self.hir_owner, data: &self.type_dependent_defs }
+    }
+
+    pub fn type_dependent_def(&self, id: HirId) -> Option<(DefKind, DefId)> {
+        validate_hir_id_for_typeck_results(self.hir_owner, id);
+        self.type_dependent_defs.get(&id.local_id).cloned().and_then(|r| r.ok())
+    }
+
+    pub fn type_dependent_def_id(&self, id: HirId) -> Option<DefId> {
+        self.type_dependent_def(id).map(|(_, def_id)| def_id)
+    }
+
+    pub fn type_dependent_defs_mut(
+        &mut self,
+    ) -> LocalTableInContextMut<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
+        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.type_dependent_defs }
+    }
+
+    pub fn field_indices(&self) -> LocalTableInContext<'_, usize> {
+        LocalTableInContext { hir_owner: self.hir_owner, data: &self.field_indices }
+    }
+
+    pub fn field_indices_mut(&mut self) -> LocalTableInContextMut<'_, usize> {
+        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.field_indices }
+    }
+
+    pub fn field_index(&self, id: hir::HirId) -> usize {
+        self.field_indices().get(id).cloned().expect("no index for a field")
+    }
+
+    pub fn opt_field_index(&self, id: hir::HirId) -> Option<usize> {
+        self.field_indices().get(id).cloned()
+    }
+
+    pub fn user_provided_types(&self) -> LocalTableInContext<'_, CanonicalUserType<'tcx>> {
+        LocalTableInContext { hir_owner: self.hir_owner, data: &self.user_provided_types }
+    }
+
+    pub fn user_provided_types_mut(
+        &mut self,
+    ) -> LocalTableInContextMut<'_, CanonicalUserType<'tcx>> {
+        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.user_provided_types }
+    }
+
+    pub fn node_types(&self) -> LocalTableInContext<'_, Ty<'tcx>> {
+        LocalTableInContext { hir_owner: self.hir_owner, data: &self.node_types }
+    }
+
+    pub fn node_types_mut(&mut self) -> LocalTableInContextMut<'_, Ty<'tcx>> {
+        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_types }
+    }
+
+    pub fn get_generator_diagnostic_data(&self) -> GeneratorDiagnosticData<'tcx> {
+        let generator_interior_type = self.generator_interior_types.map_bound_ref(|vec| {
+            vec.iter()
+                .map(|item| {
+                    GeneratorInteriorTypeCause {
+                        ty: item.ty,
+                        span: item.span,
+                        scope_span: item.scope_span,
+                        yield_span: item.yield_span,
+                        expr: None, //FIXME: Passing expression over crate boundaries is impossible at the moment
+                    }
+                })
+                .collect::<Vec<_>>()
+        });
+        GeneratorDiagnosticData {
+            generator_interior_types: generator_interior_type,
+            hir_owner: self.hir_owner.to_def_id(),
+            nodes_types: self.node_types.clone(),
+            adjustments: self.adjustments.clone(),
+        }
+    }
+
+    pub fn node_type(&self, id: hir::HirId) -> Ty<'tcx> {
+        self.node_type_opt(id).unwrap_or_else(|| {
+            bug!("node_type: no type for node `{}`", tls::with(|tcx| tcx.hir().node_to_string(id)))
+        })
+    }
+
+    pub fn node_type_opt(&self, id: hir::HirId) -> Option<Ty<'tcx>> {
+        validate_hir_id_for_typeck_results(self.hir_owner, id);
+        self.node_types.get(&id.local_id).cloned()
+    }
+
+    pub fn node_substs_mut(&mut self) -> LocalTableInContextMut<'_, SubstsRef<'tcx>> {
+        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_substs }
+    }
+
+    pub fn node_substs(&self, id: hir::HirId) -> SubstsRef<'tcx> {
+        validate_hir_id_for_typeck_results(self.hir_owner, id);
+        self.node_substs.get(&id.local_id).cloned().unwrap_or_else(|| InternalSubsts::empty())
+    }
+
+    pub fn node_substs_opt(&self, id: hir::HirId) -> Option<SubstsRef<'tcx>> {
+        validate_hir_id_for_typeck_results(self.hir_owner, id);
+        self.node_substs.get(&id.local_id).cloned()
+    }
+
+    /// Returns the type of a pattern as a monotype. Like [`expr_ty`], this function
+    /// doesn't provide type parameter substitutions.
+    ///
+    /// [`expr_ty`]: TypeckResults::expr_ty
+    pub fn pat_ty(&self, pat: &hir::Pat<'_>) -> Ty<'tcx> {
+        self.node_type(pat.hir_id)
+    }
+
+    /// Returns the type of an expression as a monotype.
+    ///
+    /// NB (1): This is the PRE-ADJUSTMENT TYPE for the expression.  That is, in
+    /// some cases, we insert `Adjustment` annotations such as auto-deref or
+    /// auto-ref.  The type returned by this function does not consider such
+    /// adjustments.  See `expr_ty_adjusted()` instead.
+    ///
+    /// NB (2): This type doesn't provide type parameter substitutions; e.g., if you
+    /// ask for the type of `id` in `id(3)`, it will return `fn(&isize) -> isize`
+    /// instead of `fn(ty) -> T with T = isize`.
+    pub fn expr_ty(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
+        self.node_type(expr.hir_id)
+    }
+
+    pub fn expr_ty_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>> {
+        self.node_type_opt(expr.hir_id)
+    }
+
+    pub fn adjustments(&self) -> LocalTableInContext<'_, Vec<ty::adjustment::Adjustment<'tcx>>> {
+        LocalTableInContext { hir_owner: self.hir_owner, data: &self.adjustments }
+    }
+
+    pub fn adjustments_mut(
+        &mut self,
+    ) -> LocalTableInContextMut<'_, Vec<ty::adjustment::Adjustment<'tcx>>> {
+        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.adjustments }
+    }
+
+    pub fn expr_adjustments(&self, expr: &hir::Expr<'_>) -> &[ty::adjustment::Adjustment<'tcx>] {
+        validate_hir_id_for_typeck_results(self.hir_owner, expr.hir_id);
+        self.adjustments.get(&expr.hir_id.local_id).map_or(&[], |a| &a[..])
+    }
+
+    /// Returns the type of `expr`, considering any `Adjustment`
+    /// entry recorded for that expression.
+    pub fn expr_ty_adjusted(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
+        self.expr_adjustments(expr).last().map_or_else(|| self.expr_ty(expr), |adj| adj.target)
+    }
+
+    pub fn expr_ty_adjusted_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>> {
+        self.expr_adjustments(expr).last().map(|adj| adj.target).or_else(|| self.expr_ty_opt(expr))
+    }
+
+    pub fn is_method_call(&self, expr: &hir::Expr<'_>) -> bool {
+        // Only paths and method calls/overloaded operators have
+        // entries in type_dependent_defs, ignore the former here.
+        if let hir::ExprKind::Path(_) = expr.kind {
+            return false;
+        }
+
+        matches!(self.type_dependent_defs().get(expr.hir_id), Some(Ok((DefKind::AssocFn, _))))
+    }
+
+    pub fn extract_binding_mode(&self, s: &Session, id: HirId, sp: Span) -> Option<BindingMode> {
+        self.pat_binding_modes().get(id).copied().or_else(|| {
+            s.delay_span_bug(sp, "missing binding mode");
+            None
+        })
+    }
+
+    pub fn pat_binding_modes(&self) -> LocalTableInContext<'_, BindingMode> {
+        LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_binding_modes }
+    }
+
+    pub fn pat_binding_modes_mut(&mut self) -> LocalTableInContextMut<'_, BindingMode> {
+        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_binding_modes }
+    }
+
+    pub fn pat_adjustments(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
+        LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_adjustments }
+    }
+
+    pub fn pat_adjustments_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
+        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments }
+    }
+
+    /// For a given closure, returns the iterator of `ty::CapturedPlace`s that are captured
+    /// by the closure.
+    pub fn closure_min_captures_flattened(
+        &self,
+        closure_def_id: LocalDefId,
+    ) -> impl Iterator<Item = &ty::CapturedPlace<'tcx>> {
+        self.closure_min_captures
+            .get(&closure_def_id)
+            .map(|closure_min_captures| closure_min_captures.values().flat_map(|v| v.iter()))
+            .into_iter()
+            .flatten()
+    }
+
+    pub fn closure_kind_origins(&self) -> LocalTableInContext<'_, (Span, HirPlace<'tcx>)> {
+        LocalTableInContext { hir_owner: self.hir_owner, data: &self.closure_kind_origins }
+    }
+
+    pub fn closure_kind_origins_mut(
+        &mut self,
+    ) -> LocalTableInContextMut<'_, (Span, HirPlace<'tcx>)> {
+        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.closure_kind_origins }
+    }
+
+    pub fn liberated_fn_sigs(&self) -> LocalTableInContext<'_, ty::FnSig<'tcx>> {
+        LocalTableInContext { hir_owner: self.hir_owner, data: &self.liberated_fn_sigs }
+    }
+
+    pub fn liberated_fn_sigs_mut(&mut self) -> LocalTableInContextMut<'_, ty::FnSig<'tcx>> {
+        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.liberated_fn_sigs }
+    }
+
+    pub fn fru_field_types(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
+        LocalTableInContext { hir_owner: self.hir_owner, data: &self.fru_field_types }
+    }
+
+    pub fn fru_field_types_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
+        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.fru_field_types }
+    }
+
+    pub fn is_coercion_cast(&self, hir_id: hir::HirId) -> bool {
+        validate_hir_id_for_typeck_results(self.hir_owner, hir_id);
+        self.coercion_casts.contains(&hir_id.local_id)
+    }
+
+    pub fn set_coercion_cast(&mut self, id: ItemLocalId) {
+        self.coercion_casts.insert(id);
+    }
+
+    pub fn coercion_casts(&self) -> &ItemLocalSet {
+        &self.coercion_casts
+    }
+}
+
+/// Validate that the given HirId (respectively its `local_id` part) can be
+/// safely used as a key in the maps of a TypeckResults. For that to be
+/// the case, the HirId must have the same `owner` as all the other IDs in
+/// this table (signified by `hir_owner`). Otherwise the HirId
+/// would be in a different frame of reference and using its `local_id`
+/// would result in lookup errors, or worse, in silently wrong data being
+/// stored/returned.
+#[inline]
+fn validate_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
+    if hir_id.owner != hir_owner {
+        invalid_hir_id_for_typeck_results(hir_owner, hir_id);
+    }
+}
+
+#[cold]
+#[inline(never)]
+fn invalid_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
+    ty::tls::with(|tcx| {
+        bug!(
+            "node {} with HirId::owner {:?} cannot be placed in TypeckResults with hir_owner {:?}",
+            tcx.hir().node_to_string(hir_id),
+            hir_id.owner,
+            hir_owner
+        )
+    });
+}
+
+pub struct LocalTableInContext<'a, V> {
+    hir_owner: OwnerId,
+    data: &'a ItemLocalMap<V>,
+}
+
+impl<'a, V> LocalTableInContext<'a, V> {
+    pub fn contains_key(&self, id: hir::HirId) -> bool {
+        validate_hir_id_for_typeck_results(self.hir_owner, id);
+        self.data.contains_key(&id.local_id)
+    }
+
+    pub fn get(&self, id: hir::HirId) -> Option<&V> {
+        validate_hir_id_for_typeck_results(self.hir_owner, id);
+        self.data.get(&id.local_id)
+    }
+
+    pub fn iter(&self) -> hash_map::Iter<'_, hir::ItemLocalId, V> {
+        self.data.iter()
+    }
+}
+
+impl<'a, V> ::std::ops::Index<hir::HirId> for LocalTableInContext<'a, V> {
+    type Output = V;
+
+    fn index(&self, key: hir::HirId) -> &V {
+        self.get(key).expect("LocalTableInContext: key not found")
+    }
+}
+
+pub struct LocalTableInContextMut<'a, V> {
+    hir_owner: OwnerId,
+    data: &'a mut ItemLocalMap<V>,
+}
+
+impl<'a, V> LocalTableInContextMut<'a, V> {
+    pub fn get_mut(&mut self, id: hir::HirId) -> Option<&mut V> {
+        validate_hir_id_for_typeck_results(self.hir_owner, id);
+        self.data.get_mut(&id.local_id)
+    }
+
+    pub fn entry(&mut self, id: hir::HirId) -> Entry<'_, hir::ItemLocalId, V> {
+        validate_hir_id_for_typeck_results(self.hir_owner, id);
+        self.data.entry(id.local_id)
+    }
+
+    pub fn insert(&mut self, id: hir::HirId, val: V) -> Option<V> {
+        validate_hir_id_for_typeck_results(self.hir_owner, id);
+        self.data.insert(id.local_id, val)
+    }
+
+    pub fn remove(&mut self, id: hir::HirId) -> Option<V> {
+        validate_hir_id_for_typeck_results(self.hir_owner, id);
+        self.data.remove(&id.local_id)
+    }
+}
+
+rustc_index::newtype_index! {
+    pub struct UserTypeAnnotationIndex {
+        derive [HashStable]
+        DEBUG_FORMAT = "UserType({})",
+        const START_INDEX = 0,
+    }
+}
+
+/// Mapping of type annotation indices to canonical user type annotations.
+pub type CanonicalUserTypeAnnotations<'tcx> =
+    IndexVec<UserTypeAnnotationIndex, CanonicalUserTypeAnnotation<'tcx>>;
+
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable, Lift)]
+pub struct CanonicalUserTypeAnnotation<'tcx> {
+    pub user_ty: Box<CanonicalUserType<'tcx>>,
+    pub span: Span,
+    pub inferred_ty: Ty<'tcx>,
+}
+
+/// Canonicalized user type annotation.
+pub type CanonicalUserType<'tcx> = Canonical<'tcx, UserType<'tcx>>;
+
+impl<'tcx> CanonicalUserType<'tcx> {
+    /// Returns `true` if this represents a substitution of the form `[?0, ?1, ?2]`,
+    /// i.e., each thing is mapped to a canonical variable with the same index.
+    pub fn is_identity(&self) -> bool {
+        match self.value {
+            UserType::Ty(_) => false,
+            UserType::TypeOf(_, user_substs) => {
+                if user_substs.user_self_ty.is_some() {
+                    return false;
+                }
+
+                iter::zip(user_substs.substs, BoundVar::new(0)..).all(|(kind, cvar)| {
+                    match kind.unpack() {
+                        GenericArgKind::Type(ty) => match ty.kind() {
+                            ty::Bound(debruijn, b) => {
+                                // We only allow a `ty::INNERMOST` index in substitutions.
+                                assert_eq!(*debruijn, ty::INNERMOST);
+                                cvar == b.var
+                            }
+                            _ => false,
+                        },
+
+                        GenericArgKind::Lifetime(r) => match *r {
+                            ty::ReLateBound(debruijn, br) => {
+                                // We only allow a `ty::INNERMOST` index in substitutions.
+                                assert_eq!(debruijn, ty::INNERMOST);
+                                cvar == br.var
+                            }
+                            _ => false,
+                        },
+
+                        GenericArgKind::Const(ct) => match ct.kind() {
+                            ty::ConstKind::Bound(debruijn, b) => {
+                                // We only allow a `ty::INNERMOST` index in substitutions.
+                                assert_eq!(debruijn, ty::INNERMOST);
+                                cvar == b
+                            }
+                            _ => false,
+                        },
+                    }
+                })
+            }
+        }
+    }
+}
+
+/// A user-given type annotation attached to a constant. These arise
+/// from constants that are named via paths, like `Foo::<A>::new` and
+/// so forth.
+#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)]
+#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
+pub enum UserType<'tcx> {
+    Ty(Ty<'tcx>),
+
+    /// The canonical type is the result of `type_of(def_id)` with the
+    /// given substitutions applied.
+    TypeOf(DefId, UserSubsts<'tcx>),
+}
index 47c1ce8075674acd461a2cd8d90da3ca73dd76e4..857f52c8a245612ddc9d164207681e8c15a7f4aa 100644 (file)
@@ -1,6 +1,7 @@
 //! Miscellaneous type-system utilities that are too small to deserve their own modules.
 
 use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
+use crate::mir;
 use crate::ty::layout::IntegerExt;
 use crate::ty::{
     self, DefIdTree, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
@@ -15,6 +16,7 @@
 use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_index::bit_set::GrowableBitSet;
+use rustc_index::vec::{Idx, IndexVec};
 use rustc_macros::HashStable;
 use rustc_span::{sym, DUMMY_SP};
 use rustc_target::abi::{Integer, IntegerType, Size, TargetDataLayout};
@@ -257,7 +259,7 @@ pub fn struct_tail_with_normalize(
 
                 ty::Tuple(_) => break,
 
-                ty::Projection(_) | ty::Opaque(..) => {
+                ty::Alias(..) => {
                     let normalized = normalize(ty);
                     if ty == normalized {
                         return ty;
@@ -330,8 +332,7 @@ pub fn struct_lockstep_tails_with_normalize(
                         break;
                     }
                 }
-                (ty::Projection(_) | ty::Opaque(..), _)
-                | (_, ty::Projection(_) | ty::Opaque(..)) => {
+                (ty::Alias(..), _) | (_, ty::Alias(..)) => {
                     // If either side is a projection, attempt to
                     // progress via normalization. (Should be safe to
                     // apply to both sides as normalization is
@@ -692,6 +693,80 @@ pub fn bound_explicit_predicates_of(
     pub fn bound_impl_subject(self, def_id: DefId) -> ty::EarlyBinder<ty::ImplSubject<'tcx>> {
         ty::EarlyBinder(self.impl_subject(def_id))
     }
+
+    /// Returns names of captured upvars for closures and generators.
+    ///
+    /// Here are some examples:
+    ///  - `name__field1__field2` when the upvar is captured by value.
+    ///  - `_ref__name__field` when the upvar is captured by reference.
+    ///
+    /// For generators this only contains upvars that are shared by all states.
+    pub fn closure_saved_names_of_captured_variables(
+        self,
+        def_id: DefId,
+    ) -> SmallVec<[String; 16]> {
+        let body = self.optimized_mir(def_id);
+
+        body.var_debug_info
+            .iter()
+            .filter_map(|var| {
+                let is_ref = match var.value {
+                    mir::VarDebugInfoContents::Place(place)
+                        if place.local == mir::Local::new(1) =>
+                    {
+                        // The projection is either `[.., Field, Deref]` or `[.., Field]`. It
+                        // implies whether the variable is captured by value or by reference.
+                        matches!(place.projection.last().unwrap(), mir::ProjectionElem::Deref)
+                    }
+                    _ => return None,
+                };
+                let prefix = if is_ref { "_ref__" } else { "" };
+                Some(prefix.to_owned() + var.name.as_str())
+            })
+            .collect()
+    }
+
+    // FIXME(eddyb) maybe precompute this? Right now it's computed once
+    // per generator monomorphization, but it doesn't depend on substs.
+    pub fn generator_layout_and_saved_local_names(
+        self,
+        def_id: DefId,
+    ) -> (
+        &'tcx ty::GeneratorLayout<'tcx>,
+        IndexVec<mir::GeneratorSavedLocal, Option<rustc_span::Symbol>>,
+    ) {
+        let tcx = self;
+        let body = tcx.optimized_mir(def_id);
+        let generator_layout = body.generator_layout().unwrap();
+        let mut generator_saved_local_names =
+            IndexVec::from_elem(None, &generator_layout.field_tys);
+
+        let state_arg = mir::Local::new(1);
+        for var in &body.var_debug_info {
+            let mir::VarDebugInfoContents::Place(place) = &var.value else { continue };
+            if place.local != state_arg {
+                continue;
+            }
+            match place.projection[..] {
+                [
+                    // Deref of the `Pin<&mut Self>` state argument.
+                    mir::ProjectionElem::Field(..),
+                    mir::ProjectionElem::Deref,
+                    // Field of a variant of the state.
+                    mir::ProjectionElem::Downcast(_, variant),
+                    mir::ProjectionElem::Field(field, _),
+                ] => {
+                    let name = &mut generator_saved_local_names
+                        [generator_layout.variant_fields[variant][field]];
+                    if name.is_none() {
+                        name.replace(var.name);
+                    }
+                }
+                _ => {}
+            }
+        }
+        (generator_layout, generator_saved_local_names)
+    }
 }
 
 struct OpaqueTypeExpander<'tcx> {
@@ -750,7 +825,7 @@ fn tcx(&self) -> TyCtxt<'tcx> {
     }
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
-        if let ty::Opaque(def_id, substs) = *t.kind() {
+        if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) = *t.kind() {
             self.expand_opaque_ty(def_id, substs).unwrap_or(t)
         } else if t.has_opaque_types() {
             t.super_fold_with(self)
@@ -862,10 +937,9 @@ fn is_trivially_freeze(self) -> bool {
             | ty::Generator(..)
             | ty::GeneratorWitness(_)
             | ty::Infer(_)
-            | ty::Opaque(..)
+            | ty::Alias(..)
             | ty::Param(_)
-            | ty::Placeholder(_)
-            | ty::Projection(_) => false,
+            | ty::Placeholder(_) => false,
         }
     }
 
@@ -902,10 +976,9 @@ fn is_trivially_unpin(self) -> bool {
             | ty::Generator(..)
             | ty::GeneratorWitness(_)
             | ty::Infer(_)
-            | ty::Opaque(..)
+            | ty::Alias(..)
             | ty::Param(_)
-            | ty::Placeholder(_)
-            | ty::Projection(_) => false,
+            | ty::Placeholder(_) => false,
         }
     }
 
@@ -1025,12 +1098,9 @@ pub fn is_structural_eq_shallow(self, tcx: TyCtxt<'tcx>) -> bool {
             //
             // FIXME(ecstaticmorse): Maybe we should `bug` here? This should probably only be
             // called for known, fully-monomorphized types.
-            ty::Projection(_)
-            | ty::Opaque(..)
-            | ty::Param(_)
-            | ty::Bound(..)
-            | ty::Placeholder(_)
-            | ty::Infer(_) => false,
+            ty::Alias(..) | ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) => {
+                false
+            }
 
             ty::Foreign(_) | ty::GeneratorWitness(..) | ty::Error(_) => false,
         }
@@ -1161,11 +1231,10 @@ pub fn needs_drop_components<'tcx>(
 
         // These require checking for `Copy` bounds or `Adt` destructors.
         ty::Adt(..)
-        | ty::Projection(..)
+        | ty::Alias(..)
         | ty::Param(_)
         | ty::Bound(..)
         | ty::Placeholder(..)
-        | ty::Opaque(..)
         | ty::Infer(_)
         | ty::Closure(..)
         | ty::Generator(..) => Ok(smallvec![ty]),
@@ -1189,13 +1258,12 @@ pub fn is_trivially_const_drop<'tcx>(ty: Ty<'tcx>) -> bool {
         | ty::Never
         | ty::Foreign(_) => true,
 
-        ty::Opaque(..)
+        ty::Alias(..)
         | ty::Dynamic(..)
         | ty::Error(_)
         | ty::Bound(..)
         | ty::Param(_)
         | ty::Placeholder(_)
-        | ty::Projection(_)
         | ty::Infer(_) => false,
 
         // Not trivial because they have components, and instead of looking inside,
index 4cdfd9e594042ba3550aa038094c7c707ad836b2..b302572f3cabdf3db89d88a04f8d3ba38e065f2b 100644 (file)
@@ -654,7 +654,7 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
         // ignore the inputs to a projection, as they may not appear
         // in the normalized form
         if self.just_constrained {
-            if let ty::Projection(..) | ty::Opaque(..) = t.kind() {
+            if let ty::Alias(..) = t.kind() {
                 return ControlFlow::CONTINUE;
             }
         }
index 6eae94511e4d63c05f1a508da14027ac07cf0399..f77bd9f0c6ffc320d6222f03130feff9550ab844 100644 (file)
@@ -1,4 +1,3 @@
-use std::convert::TryFrom;
 use std::fmt;
 
 use crate::mir::interpret::{alloc_range, AllocId, Allocation, Pointer, Scalar};
@@ -89,8 +88,8 @@ pub(super) fn vtable_allocation_provider<'tcx>(
                 let fn_ptr = Pointer::from(fn_alloc_id);
                 Scalar::from_pointer(fn_ptr, &tcx)
             }
-            VtblEntry::MetadataSize => Scalar::from_uint(size, ptr_size).into(),
-            VtblEntry::MetadataAlign => Scalar::from_uint(align, ptr_size).into(),
+            VtblEntry::MetadataSize => Scalar::from_uint(size, ptr_size),
+            VtblEntry::MetadataAlign => Scalar::from_uint(align, ptr_size),
             VtblEntry::Vacant => continue,
             VtblEntry::Method(instance) => {
                 // Prepare the fn ptr we write into the vtable.
index 4fab5abe909d40c39042aee829a86bff88e51f7b..34dbb6e9f68ea1cf6fe295448322edf3f532cea9 100644 (file)
@@ -165,7 +165,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
                 stack.push(ty.into());
                 stack.push(lt.into());
             }
-            ty::Projection(data) => {
+            ty::Alias(_, data) => {
                 stack.extend(data.substs.iter().rev());
             }
             ty::Dynamic(obj, lt, _) => {
@@ -188,7 +188,6 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
                 }));
             }
             ty::Adt(_, substs)
-            | ty::Opaque(_, substs)
             | ty::Closure(_, substs)
             | ty::Generator(_, substs, _)
             | ty::FnDef(_, substs) => {
index 2baa3bfcb6401f3570ee79012cab627d0a6b11f9..4ad3343d3031b2fa1e0f23eb2efc03ffd85edad1 100644 (file)
@@ -17,6 +17,7 @@ rustc_index = { path = "../rustc_index" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_infer = { path = "../rustc_infer" }
+rustc_macros = { path = "../rustc_macros" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
index 49d7136a2f1ffd26faff815c99bfbf1467149acd..2643d33cee00abde2688faf2b4f25186ff8ccf6b 100644 (file)
@@ -231,7 +231,7 @@ fn ast_block_stmts(
                                         remainder_span,
                                         pattern,
                                         None,
-                                        Some((None, initializer_span)),
+                                        Some((Some(&destination), initializer_span)),
                                     );
                                     this.visit_primary_bindings(
                                         pattern,
@@ -373,7 +373,9 @@ fn ast_block_stmts(
             // the case of `!`, no return value is required, as the block will never return.
             // Opaque types of empty bodies also need this unit assignment, in order to infer that their
             // type is actually unit. Otherwise there will be no defining use found in the MIR.
-            if destination_ty.is_unit() || matches!(destination_ty.kind(), ty::Opaque(..)) {
+            if destination_ty.is_unit()
+                || matches!(destination_ty.kind(), ty::Alias(ty::Opaque, ..))
+            {
                 // We only want to assign an implicit `()` as the return value of the block if the
                 // block does not diverge. (Otherwise, we may try to assign a unit to a `!`-type.)
                 this.cfg.push_assign_unit(block, source_info, destination, this.tcx);
index eb021f477573c165847eb5159def1aff24535c7c..34fefb99e09c25c1b034a2f431ce38dafbf3e39c 100644 (file)
 use rustc_ast::Attribute;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def_id::DefId;
+use rustc_hir::HirId;
 use rustc_index::vec::IndexVec;
 use rustc_middle::{
     mir::*,
     thir::*,
-    ty::{Ty, TyCtxt},
+    ty::{ParamEnv, Ty, TyCtxt},
 };
 use rustc_span::Span;
 
@@ -33,6 +34,7 @@
 pub(super) fn build_custom_mir<'tcx>(
     tcx: TyCtxt<'tcx>,
     did: DefId,
+    hir_id: HirId,
     thir: &Thir<'tcx>,
     expr: ExprId,
     params: &IndexVec<ParamId, Param<'tcx>>,
@@ -67,12 +69,16 @@ pub(super) fn build_custom_mir<'tcx>(
         parent_scope: None,
         inlined: None,
         inlined_parent_scope: None,
-        local_data: ClearCrossCrate::Clear,
+        local_data: ClearCrossCrate::Set(SourceScopeLocalData {
+            lint_root: hir_id,
+            safety: Safety::Safe,
+        }),
     });
     body.injection_phase = Some(parse_attribute(attr));
 
     let mut pctxt = ParseCtxt {
         tcx,
+        param_env: tcx.param_env(did),
         thir,
         source_scope: OUTERMOST_SOURCE_SCOPE,
         body: &mut body,
@@ -127,6 +133,7 @@ fn parse_attribute(attr: &Attribute) -> MirPhase {
 
 struct ParseCtxt<'tcx, 'body> {
     tcx: TyCtxt<'tcx>,
+    param_env: ParamEnv<'tcx>,
     thir: &'body Thir<'tcx>,
     source_scope: SourceScope,
 
index 03206af33bfb5dc927da6348f64b84f7d4074a08..ecc3e4de8d1da46f035b96b4b0174d127c9e6b68 100644 (file)
@@ -1,5 +1,11 @@
 use rustc_middle::mir::interpret::{ConstValue, Scalar};
+use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::{mir::*, thir::*, ty};
+use rustc_span::Span;
+use rustc_target::abi::VariantIdx;
+
+use crate::build::custom::ParseError;
+use crate::build::expr::as_constant::as_constant_inner;
 
 use super::{parse_by_kind, PResult, ParseCtxt};
 
@@ -12,6 +18,14 @@ pub fn parse_statement(&self, expr_id: ExprId) -> PResult<StatementKind<'tcx>> {
             @call("mir_retag_raw", args) => {
                 Ok(StatementKind::Retag(RetagKind::Raw, Box::new(self.parse_place(args[0])?)))
             },
+            @call("mir_set_discriminant", args) => {
+                let place = self.parse_place(args[0])?;
+                let var = self.parse_integer_literal(args[1])? as u32;
+                Ok(StatementKind::SetDiscriminant {
+                    place: Box::new(place),
+                    variant_index: VariantIdx::from_u32(var),
+                })
+            },
             ExprKind::Assign { lhs, rhs } => {
                 let lhs = self.parse_place(*lhs)?;
                 let rhs = self.parse_rvalue(*rhs)?;
@@ -21,18 +35,109 @@ pub fn parse_statement(&self, expr_id: ExprId) -> PResult<StatementKind<'tcx>> {
     }
 
     pub fn parse_terminator(&self, expr_id: ExprId) -> PResult<TerminatorKind<'tcx>> {
-        parse_by_kind!(self, expr_id, _, "terminator",
+        parse_by_kind!(self, expr_id, expr, "terminator",
             @call("mir_return", _args) => {
                 Ok(TerminatorKind::Return)
             },
             @call("mir_goto", args) => {
                 Ok(TerminatorKind::Goto { target: self.parse_block(args[0])? } )
             },
+            @call("mir_unreachable", _args) => {
+                Ok(TerminatorKind::Unreachable)
+            },
+            @call("mir_drop", args) => {
+                Ok(TerminatorKind::Drop {
+                    place: self.parse_place(args[0])?,
+                    target: self.parse_block(args[1])?,
+                    unwind: None,
+                })
+            },
+            @call("mir_drop_and_replace", args) => {
+                Ok(TerminatorKind::DropAndReplace {
+                    place: self.parse_place(args[0])?,
+                    value: self.parse_operand(args[1])?,
+                    target: self.parse_block(args[2])?,
+                    unwind: None,
+                })
+            },
+            @call("mir_call", args) => {
+                let destination = self.parse_place(args[0])?;
+                let target = self.parse_block(args[1])?;
+                self.parse_call(args[2], destination, target)
+            },
+            ExprKind::Match { scrutinee, arms } => {
+                let discr = self.parse_operand(*scrutinee)?;
+                self.parse_match(arms, expr.span).map(|t| TerminatorKind::SwitchInt { discr, targets: t })
+            },
+        )
+    }
+
+    fn parse_match(&self, arms: &[ArmId], span: Span) -> PResult<SwitchTargets> {
+        let Some((otherwise, rest)) = arms.split_last() else {
+            return Err(ParseError {
+                span,
+                item_description: format!("no arms"),
+                expected: "at least one arm".to_string(),
+            })
+        };
+
+        let otherwise = &self.thir[*otherwise];
+        let PatKind::Wild = otherwise.pattern.kind else {
+            return Err(ParseError {
+                span: otherwise.span,
+                item_description: format!("{:?}", otherwise.pattern.kind),
+                expected: "wildcard pattern".to_string(),
+            })
+        };
+        let otherwise = self.parse_block(otherwise.body)?;
+
+        let mut values = Vec::new();
+        let mut targets = Vec::new();
+        for arm in rest {
+            let arm = &self.thir[*arm];
+            let PatKind::Constant { value } = arm.pattern.kind else {
+                return Err(ParseError {
+                    span: arm.pattern.span,
+                    item_description: format!("{:?}", arm.pattern.kind),
+                    expected: "constant pattern".to_string(),
+                })
+            };
+            values.push(value.eval_bits(self.tcx, self.param_env, arm.pattern.ty));
+            targets.push(self.parse_block(arm.body)?);
+        }
+
+        Ok(SwitchTargets::new(values.into_iter().zip(targets), otherwise))
+    }
+
+    fn parse_call(
+        &self,
+        expr_id: ExprId,
+        destination: Place<'tcx>,
+        target: BasicBlock,
+    ) -> PResult<TerminatorKind<'tcx>> {
+        parse_by_kind!(self, expr_id, _, "function call",
+            ExprKind::Call { fun, args, from_hir_call, fn_span, .. } => {
+                let fun = self.parse_operand(*fun)?;
+                let args = args
+                    .iter()
+                    .map(|arg| self.parse_operand(*arg))
+                    .collect::<PResult<Vec<_>>>()?;
+                Ok(TerminatorKind::Call {
+                    func: fun,
+                    args,
+                    destination,
+                    target: Some(target),
+                    cleanup: None,
+                    from_hir_call: *from_hir_call,
+                    fn_span: *fn_span,
+                })
+            },
         )
     }
 
     fn parse_rvalue(&self, expr_id: ExprId) -> PResult<Rvalue<'tcx>> {
         parse_by_kind!(self, expr_id, _, "rvalue",
+            @call("mir_discriminant", args) => self.parse_place(args[0]).map(Rvalue::Discriminant),
             ExprKind::Borrow { borrow_kind, arg } => Ok(
                 Rvalue::Ref(self.tcx.lifetimes.re_erased, *borrow_kind, self.parse_place(*arg)?)
             ),
@@ -55,7 +160,7 @@ fn parse_operand(&self, expr_id: ExprId) -> PResult<Operand<'tcx>> {
             | ExprKind::ConstParam { .. }
             | ExprKind::ConstBlock { .. } => {
                 Ok(Operand::Constant(Box::new(
-                    crate::build::expr::as_constant::as_constant_inner(expr, |_| None, self.tcx)
+                    as_constant_inner(expr, |_| None, self.tcx)
                 )))
             },
             _ => self.parse_place(expr_id).map(Operand::Copy),
@@ -63,12 +168,42 @@ fn parse_operand(&self, expr_id: ExprId) -> PResult<Operand<'tcx>> {
     }
 
     fn parse_place(&self, expr_id: ExprId) -> PResult<Place<'tcx>> {
-        parse_by_kind!(self, expr_id, _, "place",
-            ExprKind::Deref { arg } => Ok(
-                self.parse_place(*arg)?.project_deeper(&[PlaceElem::Deref], self.tcx)
-            ),
-            _ => self.parse_local(expr_id).map(Place::from),
-        )
+        self.parse_place_inner(expr_id).map(|(x, _)| x)
+    }
+
+    fn parse_place_inner(&self, expr_id: ExprId) -> PResult<(Place<'tcx>, PlaceTy<'tcx>)> {
+        let (parent, proj) = parse_by_kind!(self, expr_id, expr, "place",
+            @call("mir_field", args) => {
+                let (parent, ty) = self.parse_place_inner(args[0])?;
+                let field = Field::from_u32(self.parse_integer_literal(args[1])? as u32);
+                let field_ty = ty.field_ty(self.tcx, field);
+                let proj = PlaceElem::Field(field, field_ty);
+                let place = parent.project_deeper(&[proj], self.tcx);
+                return Ok((place, PlaceTy::from_ty(field_ty)));
+            },
+            @call("mir_variant", args) => {
+                (args[0], PlaceElem::Downcast(
+                    None,
+                    VariantIdx::from_u32(self.parse_integer_literal(args[1])? as u32)
+                ))
+            },
+            ExprKind::Deref { arg } => {
+                parse_by_kind!(self, *arg, _, "does not matter",
+                    @call("mir_make_place", args) => return self.parse_place_inner(args[0]),
+                    _ => (*arg, PlaceElem::Deref),
+                )
+            },
+            ExprKind::Index { lhs, index } => (*lhs, PlaceElem::Index(self.parse_local(*index)?)),
+            ExprKind::Field { lhs, name: field, .. } => (*lhs, PlaceElem::Field(*field, expr.ty)),
+            _ => {
+                let place = self.parse_local(expr_id).map(Place::from)?;
+                return Ok((place, PlaceTy::from_ty(expr.ty)))
+            },
+        );
+        let (parent, ty) = self.parse_place_inner(parent)?;
+        let place = parent.project_deeper(&[proj], self.tcx);
+        let ty = ty.projection_ty(self.tcx, proj);
+        Ok((place, ty))
     }
 
     fn parse_local(&self, expr_id: ExprId) -> PResult<Local> {
@@ -102,4 +237,16 @@ fn parse_static(&self, expr_id: ExprId) -> PResult<Operand<'tcx>> {
             },
         )
     }
+
+    fn parse_integer_literal(&self, expr_id: ExprId) -> PResult<u128> {
+        parse_by_kind!(self, expr_id, expr, "constant",
+            ExprKind::Literal { .. }
+            | ExprKind::NamedConst { .. }
+            | ExprKind::NonHirLiteral { .. }
+            | ExprKind::ConstBlock { .. } => Ok({
+                let value = as_constant_inner(expr, |_| None, self.tcx);
+                value.literal.eval_bits(self.tcx, self.param_env, value.ty())
+            }),
+        )
+    }
 }
index 717c62315745b303ca7cef8e1e4d539c24930b4d..3b7ed818dc9b7eb7cd88630d60e63e0fa86ad22d 100644 (file)
@@ -135,14 +135,14 @@ pub(crate) fn lit_to_mir_constant<'tcx>(
             let allocation = tcx.intern_const_alloc(allocation);
             ConstValue::Slice { data: allocation, start: 0, end: s.len() }
         }
-        (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _))
+        (ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _))
             if matches!(inner_ty.kind(), ty::Slice(_)) =>
         {
             let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8]);
             let allocation = tcx.intern_const_alloc(allocation);
             ConstValue::Slice { data: allocation, start: 0, end: data.len() }
         }
-        (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
+        (ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
             let id = tcx.allocate_bytes(data);
             ConstValue::Scalar(Scalar::from_pointer(id.into(), &tcx))
         }
index edd527286264a135e019394fc9019646d32f3e88..23a4f85386b8d5f29d2c46d8f3b5f70f7e38b583 100644 (file)
@@ -7,6 +7,7 @@
 use rustc_middle::hir::place::Projection as HirProjection;
 use rustc_middle::hir::place::ProjectionKind as HirProjectionKind;
 use rustc_middle::middle::region;
+use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::mir::AssertKind::BoundsCheck;
 use rustc_middle::mir::*;
 use rustc_middle::thir::*;
 use rustc_index::vec::Idx;
 
 use std::assert_matches::assert_matches;
+use std::convert::From;
 use std::iter;
 
-/// The "outermost" place that holds this value.
-#[derive(Copy, Clone, Debug, PartialEq)]
-pub(crate) enum PlaceBase {
+/// `PlaceBuilder` is used to create places during MIR construction. It allows you to "build up" a
+/// place by pushing more and more projections onto the end, and then convert the final set into a
+/// place using the `into_place` method.
+///
+/// This is used internally when building a place for an expression like `a.b.c`. The fields `b`
+/// and `c` can be progressively pushed onto the place builder that is created when converting `a`.
+#[derive(Clone, Debug, PartialEq)]
+pub(in crate::build) enum PlaceBuilder<'tcx> {
     /// Denotes the start of a `Place`.
-    Local(Local),
+    ///
+    /// We use `PlaceElem` since this has all `Field` types available.
+    Local { local: Local, projection: Vec<PlaceElem<'tcx>> },
 
     /// When building place for an expression within a closure, the place might start off a
     /// captured path. When `capture_disjoint_fields` is enabled, we might not know the capture
     /// index (within the desugared closure) of the captured path until most of the projections
-    /// are applied. We use `PlaceBase::Upvar` to keep track of the root variable off of which the
+    /// are applied. We use `PlaceBuilder::Upvar` to keep track of the root variable off of which the
     /// captured path starts, the closure the capture belongs to and the trait the closure
     /// implements.
     ///
-    /// Once we have figured out the capture index, we can convert the place builder to start from
-    /// `PlaceBase::Local`.
+    /// Once we have figured out the capture index, we can convert the place builder to
+    /// `PlaceBuilder::Local`.
     ///
     /// Consider the following example
     /// ```rust
@@ -55,24 +64,16 @@ pub(crate) enum PlaceBase {
     ///
     /// When `capture_disjoint_fields` is enabled, `t.0.0.0` is captured and we won't be able to
     /// figure out that it is captured until all the `Field` projections are applied.
-    Upvar {
-        /// HirId of the upvar
-        var_hir_id: LocalVarId,
-        /// DefId of the closure
-        closure_def_id: LocalDefId,
-    },
+    ///
+    /// Note: in contrast to `PlaceBuilder::Local` we have not yet determined all `Field` types
+    /// and will only do so once converting to `PlaceBuilder::Local`.
+    Upvar { upvar: Upvar, projection: Vec<UpvarProjectionElem<'tcx>> },
 }
 
-/// `PlaceBuilder` is used to create places during MIR construction. It allows you to "build up" a
-/// place by pushing more and more projections onto the end, and then convert the final set into a
-/// place using the `to_place` method.
-///
-/// This is used internally when building a place for an expression like `a.b.c`. The fields `b`
-/// and `c` can be progressively pushed onto the place builder that is created when converting `a`.
-#[derive(Clone, Debug, PartialEq)]
-pub(in crate::build) struct PlaceBuilder<'tcx> {
-    base: PlaceBase,
-    projection: Vec<PlaceElem<'tcx>>,
+#[derive(Copy, Clone, Debug, PartialEq)]
+pub(crate) struct Upvar {
+    var_hir_id: LocalVarId,
+    closure_def_id: LocalDefId,
 }
 
 /// Given a list of MIR projections, convert them to list of HIR ProjectionKind.
@@ -82,7 +83,7 @@ pub(in crate::build) struct PlaceBuilder<'tcx> {
 /// part of a path that is captured by a closure. We stop applying projections once we see the first
 /// projection that isn't captured by a closure.
 fn convert_to_hir_projections_and_truncate_for_capture<'tcx>(
-    mir_projections: &[PlaceElem<'tcx>],
+    mir_projections: &[UpvarProjectionElem<'tcx>],
 ) -> Vec<HirProjectionKind> {
     let mut hir_projections = Vec::new();
     let mut variant = None;
@@ -156,7 +157,7 @@ fn is_ancestor_or_same_capture(
 fn find_capture_matching_projections<'a, 'tcx>(
     upvars: &'a CaptureMap<'tcx>,
     var_hir_id: LocalVarId,
-    projections: &[PlaceElem<'tcx>],
+    projections: &[UpvarProjectionElem<'tcx>],
 ) -> Option<(usize, &'a Capture<'tcx>)> {
     let hir_projections = convert_to_hir_projections_and_truncate_for_capture(projections);
 
@@ -174,7 +175,7 @@ fn to_upvars_resolved_place_builder<'tcx>(
     cx: &Builder<'_, 'tcx>,
     var_hir_id: LocalVarId,
     closure_def_id: LocalDefId,
-    projection: &[PlaceElem<'tcx>],
+    projection: &[UpvarProjectionElem<'tcx>],
 ) -> Option<PlaceBuilder<'tcx>> {
     let Some((capture_index, capture)) =
         find_capture_matching_projections(
@@ -196,23 +197,32 @@ fn to_upvars_resolved_place_builder<'tcx>(
                 var_hir_id, projection,
             );
         }
+
         return None;
     };
 
     // Access the capture by accessing the field within the Closure struct.
     let capture_info = &cx.upvars[capture_index];
 
-    let mut upvar_resolved_place_builder = PlaceBuilder::from(capture_info.use_place);
+    let Place { local: upvar_resolved_local, projection: local_projection } =
+        capture_info.use_place;
 
     // We used some of the projections to build the capture itself,
     // now we apply the remaining to the upvar resolved place.
-    trace!(?capture.captured_place, ?projection);
-    let remaining_projections = strip_prefix(
+    let upvar_projection = strip_prefix(
         capture.captured_place.place.base_ty,
         projection,
         &capture.captured_place.place.projections,
     );
-    upvar_resolved_place_builder.projection.extend(remaining_projections);
+
+    let upvar_resolved_place_builder = PlaceBuilder::construct_local_place_builder(
+        cx,
+        upvar_resolved_local,
+        local_projection.as_slice(),
+        upvar_projection,
+    );
+
+    assert!(matches!(upvar_resolved_place_builder, PlaceBuilder::Local { .. }));
 
     Some(upvar_resolved_place_builder)
 }
@@ -225,15 +235,17 @@ fn to_upvars_resolved_place_builder<'tcx>(
 /// projection kinds are unsupported.
 fn strip_prefix<'a, 'tcx>(
     mut base_ty: Ty<'tcx>,
-    projections: &'a [PlaceElem<'tcx>],
+    projections: &'a [UpvarProjectionElem<'tcx>],
     prefix_projections: &[HirProjection<'tcx>],
-) -> impl Iterator<Item = PlaceElem<'tcx>> + 'a {
+) -> impl Iterator<Item = UpvarProjectionElem<'tcx>> + 'a {
     let mut iter = projections
         .iter()
         .copied()
         // Filter out opaque casts, they are unnecessary in the prefix.
         .filter(|elem| !matches!(elem, ProjectionElem::OpaqueCast(..)));
     for projection in prefix_projections {
+        debug!(?projection, ?projection.ty);
+
         match projection.kind {
             HirProjectionKind::Deref => {
                 assert_matches!(iter.next(), Some(ProjectionElem::Deref));
@@ -248,8 +260,10 @@ fn strip_prefix<'a, 'tcx>(
                 bug!("unexpected projection kind: {:?}", projection);
             }
         }
+
         base_ty = projection.ty;
     }
+
     iter
 }
 
@@ -262,9 +276,9 @@ pub(in crate::build) fn to_place(&self, cx: &Builder<'_, 'tcx>) -> Place<'tcx> {
     pub(in crate::build) fn try_to_place(&self, cx: &Builder<'_, 'tcx>) -> Option<Place<'tcx>> {
         let resolved = self.resolve_upvar(cx);
         let builder = resolved.as_ref().unwrap_or(self);
-        let PlaceBase::Local(local) = builder.base else { return None };
-        let projection = cx.tcx.intern_place_elems(&builder.projection);
-        Some(Place { local, projection })
+        let PlaceBuilder::Local{local, ref projection} = builder else { return None };
+        let projection = cx.tcx.intern_place_elems(projection);
+        Some(Place { local: *local, projection })
     }
 
     /// Attempts to resolve the `PlaceBuilder`.
@@ -281,22 +295,31 @@ pub(in crate::build) fn resolve_upvar(
         &self,
         cx: &Builder<'_, 'tcx>,
     ) -> Option<PlaceBuilder<'tcx>> {
-        let PlaceBase::Upvar { var_hir_id, closure_def_id } = self.base else {
+        let PlaceBuilder::Upvar{ upvar: Upvar {var_hir_id, closure_def_id }, projection} = self else {
             return None;
         };
-        to_upvars_resolved_place_builder(cx, var_hir_id, closure_def_id, &self.projection)
-    }
 
-    pub(crate) fn base(&self) -> PlaceBase {
-        self.base
+        to_upvars_resolved_place_builder(cx, *var_hir_id, *closure_def_id, &projection)
     }
 
-    pub(crate) fn projection(&self) -> &[PlaceElem<'tcx>] {
-        &self.projection
-    }
+    #[instrument(skip(cx), level = "debug")]
+    pub(crate) fn field(self, cx: &Builder<'_, 'tcx>, f: Field) -> Self {
+        match self.clone() {
+            PlaceBuilder::Local { local, projection } => {
+                let base_place = PlaceBuilder::Local { local, projection };
+                let PlaceTy { ty, variant_index } =
+                    base_place.to_place(cx).ty(&cx.local_decls, cx.tcx);
+                let base_ty = cx.tcx.normalize_erasing_regions(cx.param_env, ty);
+
+                let field_ty = PlaceBuilder::compute_field_ty(cx, f, base_ty, variant_index);
 
-    pub(crate) fn field(self, f: Field, ty: Ty<'tcx>) -> Self {
-        self.project(PlaceElem::Field(f, ty))
+                self.project(ProjectionElem::Field(f, field_ty))
+            }
+            PlaceBuilder::Upvar { upvar, mut projection } => {
+                projection.push(ProjectionElem::Field(f, ()));
+                PlaceBuilder::Upvar { upvar, projection }
+            }
+        }
     }
 
     pub(crate) fn deref(self) -> Self {
@@ -311,35 +334,236 @@ fn index(self, index: Local) -> Self {
         self.project(PlaceElem::Index(index))
     }
 
-    pub(crate) fn project(mut self, elem: PlaceElem<'tcx>) -> Self {
-        self.projection.push(elem);
-        self
+    #[instrument(level = "debug")]
+    pub(crate) fn project(self, elem: PlaceElem<'tcx>) -> Self {
+        let result = match self {
+            PlaceBuilder::Local { local, mut projection } => {
+                projection.push(elem);
+                PlaceBuilder::Local { local, projection }
+            }
+            PlaceBuilder::Upvar { upvar, mut projection } => {
+                projection.push(elem.into());
+                PlaceBuilder::Upvar { upvar, projection }
+            }
+        };
+
+        debug!(?result);
+        result
     }
 
     /// Same as `.clone().project(..)` but more efficient
     pub(crate) fn clone_project(&self, elem: PlaceElem<'tcx>) -> Self {
-        Self {
-            base: self.base,
-            projection: Vec::from_iter(self.projection.iter().copied().chain([elem])),
+        match self {
+            PlaceBuilder::Local { local, projection } => PlaceBuilder::Local {
+                local: *local,
+                projection: Vec::from_iter(projection.iter().copied().chain([elem])),
+            },
+            PlaceBuilder::Upvar { upvar, projection } => PlaceBuilder::Upvar {
+                upvar: *upvar,
+                projection: Vec::from_iter(projection.iter().copied().chain([elem.into()])),
+            },
         }
     }
+
+    /// Similar to `Place::ty` but needed during mir building.
+    ///
+    /// Applies the projections in the `PlaceBuilder` to the base
+    /// type.
+    ///
+    /// Fallible as the root of this place may be an upvar for
+    /// which no base type can be determined.
+    #[instrument(skip(cx), level = "debug")]
+    fn compute_field_ty(
+        cx: &Builder<'_, 'tcx>,
+        field: Field,
+        base_ty: Ty<'tcx>,
+        variant_index: Option<VariantIdx>,
+    ) -> Ty<'tcx> {
+        let field_idx = field.as_usize();
+        let field_ty = match base_ty.kind() {
+            ty::Adt(adt_def, substs) if adt_def.is_enum() => {
+                let variant_idx = variant_index.unwrap();
+                adt_def.variant(variant_idx).fields[field_idx].ty(cx.tcx, substs)
+            }
+            ty::Adt(adt_def, substs) => adt_def
+                .all_fields()
+                .nth(field_idx)
+                .unwrap_or_else(|| {
+                    bug!(
+                        "expected to take field with idx {:?} of fields of {:?}",
+                        field_idx,
+                        adt_def
+                    )
+                })
+                .ty(cx.tcx, substs),
+            ty::Tuple(elems) => elems.iter().nth(field_idx).unwrap_or_else(|| {
+                bug!("expected to take field with idx {:?} of {:?}", field_idx, elems)
+            }),
+            ty::Closure(_, substs) => {
+                let substs = substs.as_closure();
+                let Some(f_ty) = substs.upvar_tys().nth(field_idx) else {
+                    bug!("expected to take field with idx {:?} of {:?}", field_idx, substs.upvar_tys().collect::<Vec<_>>());
+                };
+
+                f_ty
+            }
+            &ty::Generator(def_id, substs, _) => {
+                if let Some(var) = variant_index {
+                    let gen_body = cx.tcx.optimized_mir(def_id);
+                    let Some(layout) = gen_body.generator_layout() else {
+                        bug!("No generator layout for {:?}", base_ty);
+                    };
+
+                    let Some(&local) = layout.variant_fields[var].get(field) else {
+                        bug!("expected to take field {:?} of {:?}", field, layout.variant_fields[var]);
+                    };
+
+                    let Some(&f_ty) = layout.field_tys.get(local) else {
+                        bug!("expected to get element for {:?} in {:?}", local, layout.field_tys);
+                    };
+
+                    f_ty
+                } else {
+                    let Some(f_ty) = substs.as_generator().prefix_tys().nth(field.index()) else {
+                        bug!(
+                            "expected to take index {:?} in {:?}",
+                            field.index(),
+                            substs.as_generator().prefix_tys().collect::<Vec<_>>()
+                        );
+                    };
+
+                    f_ty
+                }
+            }
+            _ => bug!("couldn't create field type, unexpected base type: {:?}", base_ty),
+        };
+
+        cx.tcx.normalize_erasing_regions(cx.param_env, field_ty)
+    }
+
+    /// Creates a `PlaceBuilder::Local` from a `PlaceBuilder::Upvar` whose upvars
+    /// are resolved. This function takes two kinds of projections: `local_projection`
+    /// contains the projections of the captured upvar and `upvar_projection` the
+    /// projections that are applied to the captured upvar. The main purpose of this
+    /// function is to figure out the `Ty`s of the field projections in `upvar_projection`.
+    #[instrument(skip(cx, local, upvar_projection))]
+    fn construct_local_place_builder(
+        cx: &Builder<'_, 'tcx>,
+        local: Local,
+        local_projection: &[PlaceElem<'tcx>],
+        upvar_projection: impl Iterator<Item = UpvarProjectionElem<'tcx>>,
+    ) -> Self {
+        // We maintain a `Ty` to which we apply a projection in each iteration over `upvar_projection`.
+        // This `ancestor_ty` let's us infer the field type whenever we encounter a
+        // `ProjectionElem::Field`.
+        let (mut ancestor_ty, mut opt_variant_idx) =
+            local_projections_to_ty(cx, local, local_projection);
+
+        // We add all projection elements we encounter to this `Vec`.
+        let mut local_projection = local_projection.to_vec();
+
+        for (i, proj) in upvar_projection.enumerate() {
+            debug!("i: {:?}, proj: {:?}, local_projection: {:?}", i, proj, local_projection);
+            match proj {
+                ProjectionElem::Field(field, _) => {
+                    let field_ty =
+                        PlaceBuilder::compute_field_ty(cx, field, ancestor_ty, opt_variant_idx);
+                    debug!(?field_ty);
+
+                    local_projection.push(ProjectionElem::Field(field, field_ty));
+                    ancestor_ty = field_ty;
+                    opt_variant_idx = None;
+                }
+                _ => {
+                    let proj = upvar_proj_to_place_elem_no_field_proj(proj);
+                    (ancestor_ty, opt_variant_idx) = project_ty(cx.tcx, ancestor_ty, proj);
+                    local_projection.push(proj);
+                }
+            }
+        }
+
+        PlaceBuilder::Local { local, projection: local_projection }
+    }
 }
 
 impl<'tcx> From<Local> for PlaceBuilder<'tcx> {
     fn from(local: Local) -> Self {
-        Self { base: PlaceBase::Local(local), projection: Vec::new() }
+        Self::Local { local, projection: Vec::new() }
     }
 }
 
-impl<'tcx> From<PlaceBase> for PlaceBuilder<'tcx> {
-    fn from(base: PlaceBase) -> Self {
-        Self { base, projection: Vec::new() }
+impl<'tcx> From<Place<'tcx>> for PlaceBuilder<'tcx> {
+    fn from(p: Place<'tcx>) -> Self {
+        Self::Local { local: p.local, projection: p.projection.to_vec() }
     }
 }
 
-impl<'tcx> From<Place<'tcx>> for PlaceBuilder<'tcx> {
-    fn from(p: Place<'tcx>) -> Self {
-        Self { base: PlaceBase::Local(p.local), projection: p.projection.to_vec() }
+fn project_ty<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    ty: Ty<'tcx>,
+    elem: PlaceElem<'tcx>,
+) -> (Ty<'tcx>, Option<VariantIdx>) {
+    match elem {
+        ProjectionElem::Deref => {
+            let updated_ty = ty
+                .builtin_deref(true)
+                .unwrap_or_else(|| bug!("deref projection of non-dereferenceable ty {:?}", ty))
+                .ty;
+
+            (updated_ty, None)
+        }
+        ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } => {
+            (ty.builtin_index().unwrap(), None)
+        }
+        ProjectionElem::Subslice { from, to, from_end } => {
+            let ty = match ty.kind() {
+                ty::Slice(..) => ty,
+                ty::Array(inner, _) if !from_end => tcx.mk_array(*inner, (to - from) as u64),
+                ty::Array(inner, size) if from_end => {
+                    let size = size.eval_usize(tcx, ty::ParamEnv::empty());
+                    let len = size - (from as u64) - (to as u64);
+                    tcx.mk_array(*inner, len)
+                }
+                _ => bug!("cannot subslice non-array type: `{:?}`", ty),
+            };
+
+            (ty, None)
+        }
+        ProjectionElem::Downcast(_, variant_idx) => (ty, Some(variant_idx)),
+        ProjectionElem::Field(_, ty) => (ty, None),
+        ProjectionElem::OpaqueCast(..) => bug!("didn't expect OpaqueCast"),
+    }
+}
+
+fn local_projections_to_ty<'a, 'tcx>(
+    cx: &'a Builder<'a, 'tcx>,
+    local: Local,
+    projection: &'a [PlaceElem<'tcx>],
+) -> (Ty<'tcx>, Option<VariantIdx>) {
+    let local_ty = cx.local_decls.local_decls()[local].ty;
+    projection.iter().fold((local_ty, None), |ty_variant_idx, elem| {
+        let ty = ty_variant_idx.0;
+        project_ty(cx.tcx, ty, *elem)
+    })
+}
+
+// Converts an `UpvarProjectionElem` to `PlaceElem`, ICE'ing when being passed a
+// field projection.
+fn upvar_proj_to_place_elem_no_field_proj<'tcx>(
+    upvar_proj: UpvarProjectionElem<'tcx>,
+) -> PlaceElem<'tcx> {
+    match upvar_proj {
+        ProjectionElem::Deref => ProjectionElem::Deref,
+        ProjectionElem::Index(i) => ProjectionElem::Index(i),
+        ProjectionElem::ConstantIndex { offset, min_length, from_end } => {
+            ProjectionElem::ConstantIndex { offset, min_length, from_end }
+        }
+        ProjectionElem::Subslice { from, to, from_end } => {
+            ProjectionElem::Subslice { from, to, from_end }
+        }
+        ProjectionElem::Downcast(ty, variant_idx) => ProjectionElem::Downcast(ty, variant_idx),
+        ProjectionElem::OpaqueCast(ty) => ProjectionElem::OpaqueCast(ty),
+        ProjectionElem::Field(..) => bug!("should not be called with `ProjectionElem::Field`"),
     }
 }
 
@@ -403,6 +627,7 @@ fn as_read_only_place_builder(
         self.expr_as_place(block, expr, Mutability::Not, None)
     }
 
+    #[instrument(skip(self, fake_borrow_temps), level = "debug")]
     fn expr_as_place(
         &mut self,
         mut block: BasicBlock,
@@ -410,8 +635,6 @@ fn expr_as_place(
         mutability: Mutability,
         fake_borrow_temps: Option<&mut Vec<Local>>,
     ) -> BlockAnd<PlaceBuilder<'tcx>> {
-        debug!("expr_as_place(block={:?}, expr={:?}, mutability={:?})", block, expr, mutability);
-
         let this = self;
         let expr_span = expr.span;
         let source_info = this.source_info(expr_span);
@@ -425,12 +648,13 @@ fn expr_as_place(
                 let lhs = &this.thir[lhs];
                 let mut place_builder =
                     unpack!(block = this.expr_as_place(block, lhs, mutability, fake_borrow_temps,));
+                debug!(?place_builder);
                 if let ty::Adt(adt_def, _) = lhs.ty.kind() {
                     if adt_def.is_enum() {
                         place_builder = place_builder.downcast(*adt_def, variant_index);
                     }
                 }
-                block.and(place_builder.field(name, expr.ty))
+                block.and(place_builder.field(this, name))
             }
             ExprKind::Deref { arg } => {
                 let place_builder = unpack!(
@@ -572,7 +796,7 @@ fn expr_as_place(
     }
 
     /// Lower a captured upvar. Note we might not know the actual capture index,
-    /// so we create a place starting from `PlaceBase::Upvar`, which will be resolved
+    /// so we create a place starting from `Upvar`, which will be resolved
     /// once all projections that allow us to identify a capture have been applied.
     fn lower_captured_upvar(
         &mut self,
@@ -580,7 +804,10 @@ fn lower_captured_upvar(
         closure_def_id: LocalDefId,
         var_hir_id: LocalVarId,
     ) -> BlockAnd<PlaceBuilder<'tcx>> {
-        block.and(PlaceBuilder::from(PlaceBase::Upvar { var_hir_id, closure_def_id }))
+        block.and(PlaceBuilder::Upvar {
+            upvar: Upvar { var_hir_id, closure_def_id },
+            projection: vec![],
+        })
     }
 
     /// Lower an index expression
@@ -671,8 +898,8 @@ fn add_fake_borrows_of_base(
         source_info: SourceInfo,
     ) {
         let tcx = self.tcx;
-
         let place_ty = base_place.ty(&self.local_decls, tcx);
+
         if let ty::Slice(_) = place_ty.ty.kind() {
             // We need to create fake borrows to ensure that the bounds
             // check that we just did stays valid. Since we can't assign to
index 0814793f27790159dd3aa6400fe3a6e28b6b3b4f..b420e820171482c8813dbf3b6defaeb4ca7079d1 100644 (file)
@@ -4,9 +4,8 @@
 use rustc_middle::ty::util::IntTypeExt;
 use rustc_target::abi::{Abi, Primitive};
 
-use crate::build::expr::as_place::PlaceBase;
 use crate::build::expr::category::{Category, RvalueFunc};
-use crate::build::{BlockAnd, BlockAndExtension, Builder, NeedsTemporary};
+use crate::build::{BlockAnd, BlockAndExtension, Builder, NeedsTemporary, PlaceBuilder};
 use rustc_hir::lang_items::LangItem;
 use rustc_middle::middle::region;
 use rustc_middle::mir::AssertKind;
@@ -142,7 +141,7 @@ pub(crate) fn as_rvalue(
                 let exchange_malloc = Operand::function_handle(
                     tcx,
                     tcx.require_lang_item(LangItem::ExchangeMalloc, Some(expr_span)),
-                    ty::List::empty(),
+                    [],
                     expr_span,
                 );
                 let storage = this.temp(tcx.mk_mut_ptr(tcx.types.u8), expr_span);
@@ -651,15 +650,15 @@ fn limit_capture_mutability(
 
         let arg_place_builder = unpack!(block = this.as_place_builder(block, arg));
 
-        let mutability = match arg_place_builder.base() {
+        let mutability = match arg_place_builder {
             // We are capturing a path that starts off a local variable in the parent.
             // The mutability of the current capture is same as the mutability
             // of the local declaration in the parent.
-            PlaceBase::Local(local) => this.local_decls[local].mutability,
+            PlaceBuilder::Local { local, .. } => this.local_decls[local].mutability,
             // Parent is a closure and we are capturing a path that is captured
             // by the parent itself. The mutability of the current capture
             // is same as that of the capture in the parent closure.
-            PlaceBase::Upvar { .. } => {
+            PlaceBuilder::Upvar { .. } => {
                 let enclosing_upvars_resolved = arg_place_builder.to_place(this);
 
                 match enclosing_upvars_resolved.as_ref() {
index 218a26e62797dc97b0fe5f559ead5374613506de..895051d7590b58a2c1da71d3807ddb091e522b40 100644 (file)
@@ -183,7 +183,7 @@ pub(crate) fn expr_into_dest(
                     LogicalOp::And => (else_block, shortcircuit_block),
                     LogicalOp::Or => (shortcircuit_block, else_block),
                 };
-                let term = TerminatorKind::if_(this.tcx, lhs, blocks.0, blocks.1);
+                let term = TerminatorKind::if_(lhs, blocks.0, blocks.1);
                 this.cfg.terminate(block, source_info, term);
 
                 this.cfg.push_assign_constant(
@@ -355,11 +355,13 @@ pub(crate) fn expr_into_dest(
                     // base-supplied field, generate an operand that
                     // reads it from the base.
                     iter::zip(field_names, &**field_types)
-                        .map(|(n, ty)| match fields_map.get(&n) {
+                        .map(|(n, _ty)| match fields_map.get(&n) {
                             Some(v) => v.clone(),
                             None => {
-                                let place = place_builder.clone_project(PlaceElem::Field(n, *ty));
-                                this.consume_by_copy_or_move(place.to_place(this))
+                                let place_builder = place_builder.clone();
+                                this.consume_by_copy_or_move(
+                                    place_builder.field(this, n).to_place(this),
+                                )
                             }
                         })
                         .collect()
index 00dbcaeb0c96f98866bdfc7a466d90785340d5df..e9f327978aab1f0ac0617bafe6f3d85af4b31251 100644 (file)
@@ -6,10 +6,8 @@
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Builds a block of MIR statements to evaluate the THIR `expr`.
-    /// If the original expression was an AST statement,
-    /// (e.g., `some().code(&here());`) then `opt_stmt_span` is the
-    /// span of that statement (including its semicolon, if any).
-    /// The scope is used if a statement temporary must be dropped.
+    ///
+    /// The `statement_scope` is used if a statement temporary must be dropped.
     pub(crate) fn stmt_expr(
         &mut self,
         mut block: BasicBlock,
index 691cbee2c731911acf2997bea4754b5d54c9ee16..7edcd46a34f293a542e1f2df59bc6f55f07a7bce 100644 (file)
@@ -30,7 +30,6 @@
 mod util;
 
 use std::borrow::Borrow;
-use std::convert::TryFrom;
 use std::mem;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
@@ -95,7 +94,7 @@ pub(crate) fn then_else_break(
 
                 let then_block = this.cfg.start_new_block();
                 let else_block = this.cfg.start_new_block();
-                let term = TerminatorKind::if_(this.tcx, operand, then_block, else_block);
+                let term = TerminatorKind::if_(operand, then_block, else_block);
 
                 let source_info = this.source_info(expr_span);
                 this.cfg.terminate(block, source_info, term);
index f6b1955fdec4d89814844bbedf3845de14616f83..36aa7693e827ff3009026c32fd2b88c3a8c7b2af 100644 (file)
@@ -272,9 +272,9 @@ fn simplify_match_pair<'pat>(
                     || !adt_def.is_variant_list_non_exhaustive());
                 if irrefutable {
                     let place_builder = match_pair.place.downcast(adt_def, variant_index);
-                    candidate
-                        .match_pairs
-                        .extend(self.field_match_pairs(place_builder, subpatterns));
+                    let field_match_pairs =
+                        self.field_match_pairs(place_builder.clone(), subpatterns);
+                    candidate.match_pairs.extend(field_match_pairs);
                     Ok(())
                 } else {
                     Err(match_pair)
index 58513bde2aa2a09fdcff2d16b02ec26bd2af02e4..6c10704c5db51a64d7b73c93a2fcb1e2ca731b52 100644 (file)
@@ -203,7 +203,6 @@ pub(super) fn perform_test(
                     self.source_info(match_start_span),
                     TerminatorKind::SwitchInt {
                         discr: Operand::Move(discr),
-                        switch_ty: discr_ty,
                         targets: switch_targets,
                     },
                 );
@@ -221,7 +220,7 @@ pub(super) fn perform_test(
                         0 => (second_bb, first_bb),
                         v => span_bug!(test.span, "expected boolean value but got {:?}", v),
                     };
-                    TerminatorKind::if_(self.tcx, Operand::Copy(place), true_bb, false_bb)
+                    TerminatorKind::if_(Operand::Copy(place), true_bb, false_bb)
                 } else {
                     // The switch may be inexhaustive so we have a catch all block
                     debug_assert_eq!(options.len() + 1, target_blocks.len());
@@ -232,7 +231,6 @@ pub(super) fn perform_test(
                     );
                     TerminatorKind::SwitchInt {
                         discr: Operand::Copy(place),
-                        switch_ty,
                         targets: switch_targets,
                     }
                 };
@@ -378,7 +376,7 @@ fn compare(
         self.cfg.terminate(
             block,
             source_info,
-            TerminatorKind::if_(self.tcx, Operand::Move(result), success_block, fail_block),
+            TerminatorKind::if_(Operand::Move(result), success_block, fail_block),
         );
     }
 
@@ -482,7 +480,7 @@ fn non_scalar_compare(
         self.cfg.terminate(
             eq_block,
             source_info,
-            TerminatorKind::if_(self.tcx, Operand::Move(eq_result), success_block, fail_block),
+            TerminatorKind::if_(Operand::Move(eq_result), success_block, fail_block),
         );
     }
 
@@ -553,16 +551,15 @@ pub(super) fn sort_candidate<'pat>(
             //
             // FIXME(#29623) we could use PatKind::Range to rule
             // things out here, in some cases.
-            (
-                &TestKind::SwitchInt { switch_ty: _, ref options },
-                &PatKind::Constant { ref value },
-            ) if is_switch_ty(match_pair.pattern.ty) => {
+            (TestKind::SwitchInt { switch_ty: _, options }, PatKind::Constant { value })
+                if is_switch_ty(match_pair.pattern.ty) =>
+            {
                 let index = options.get_index_of(value).unwrap();
                 self.candidate_without_match_pair(match_pair_index, candidate);
                 Some(index)
             }
 
-            (&TestKind::SwitchInt { switch_ty: _, ref options }, &PatKind::Range(ref range)) => {
+            (TestKind::SwitchInt { switch_ty: _, options }, PatKind::Range(range)) => {
                 let not_contained =
                     self.values_not_contained_in_range(&*range, options).unwrap_or(false);
 
@@ -580,7 +577,7 @@ pub(super) fn sort_candidate<'pat>(
 
             (
                 &TestKind::Len { len: test_len, op: BinOp::Eq },
-                &PatKind::Slice { ref prefix, ref slice, ref suffix },
+                PatKind::Slice { prefix, slice, suffix },
             ) => {
                 let pat_len = (prefix.len() + suffix.len()) as u64;
                 match (test_len.cmp(&pat_len), slice) {
@@ -617,7 +614,7 @@ pub(super) fn sort_candidate<'pat>(
 
             (
                 &TestKind::Len { len: test_len, op: BinOp::Ge },
-                &PatKind::Slice { ref prefix, ref slice, ref suffix },
+                PatKind::Slice { prefix, slice, suffix },
             ) => {
                 // the test is `$actual_len >= test_len`
                 let pat_len = (prefix.len() + suffix.len()) as u64;
@@ -653,7 +650,7 @@ pub(super) fn sort_candidate<'pat>(
                 }
             }
 
-            (&TestKind::Range(ref test), &PatKind::Range(ref pat)) => {
+            (TestKind::Range(test), PatKind::Range(pat)) => {
                 use std::cmp::Ordering::*;
 
                 if test == pat {
@@ -680,7 +677,7 @@ pub(super) fn sort_candidate<'pat>(
                 no_overlap
             }
 
-            (&TestKind::Range(ref range), &PatKind::Constant { value }) => {
+            (TestKind::Range(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.
@@ -760,8 +757,7 @@ fn candidate_after_variant_switch<'pat>(
         let downcast_place = match_pair.place.downcast(adt_def, variant_index); // `(x as Variant)`
         let consequent_match_pairs = subpatterns.iter().map(|subpattern| {
             // e.g., `(x as Variant).0`
-            let place = downcast_place
-                .clone_project(PlaceElem::Field(subpattern.field, subpattern.pattern.ty));
+            let place = downcast_place.clone().field(self, subpattern.field);
             // e.g., `(x as Variant).0 @ P1`
             MatchPair::new(place, &subpattern.pattern, self)
         });
@@ -840,8 +836,6 @@ fn trait_method<'tcx>(
     method_name: Symbol,
     substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
 ) -> ConstantKind<'tcx> {
-    let substs = tcx.mk_substs(substs.into_iter().map(Into::into));
-
     // The unhygienic comparison here is acceptable because this is only
     // used on known traits.
     let item = tcx
index bd435f9ab0095a4b86e10703a3127c31bbd068b5..d95dbfca78e847573464af63833f1deb680bce0e 100644 (file)
@@ -1,4 +1,3 @@
-use crate::build::expr::as_place::PlaceBase;
 use crate::build::expr::as_place::PlaceBuilder;
 use crate::build::matches::MatchPair;
 use crate::build::Builder;
@@ -7,7 +6,6 @@
 use rustc_middle::ty;
 use rustc_middle::ty::TypeVisitable;
 use smallvec::SmallVec;
-use std::convert::TryInto;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     pub(crate) fn field_match_pairs<'pat>(
@@ -18,8 +16,8 @@ pub(crate) fn field_match_pairs<'pat>(
         subpatterns
             .iter()
             .map(|fieldpat| {
-                let place =
-                    place.clone_project(PlaceElem::Field(fieldpat.field, fieldpat.pattern.ty));
+                let place = place.clone().field(self, fieldpat.field);
+
                 MatchPair::new(place, &fieldpat.pattern, self)
             })
             .collect()
@@ -108,9 +106,9 @@ pub(in crate::build) fn new(
 
         // Only add the OpaqueCast projection if the given place is an opaque type and the
         // expected type from the pattern is not.
-        let may_need_cast = match place.base() {
-            PlaceBase::Local(local) => {
-                let ty = Place::ty_from(local, place.projection(), &cx.local_decls, cx.tcx).ty;
+        let may_need_cast = match place {
+            PlaceBuilder::Local { local, ref projection } => {
+                let ty = Place::ty_from(local, projection, &cx.local_decls, cx.tcx).ty;
                 ty != pattern.ty && ty.has_opaque_types()
             }
             _ => true,
index 007f3b55ec8bb156b6c53c338fdfbbfacd3641f8..7af89dd472f88e9be4ccf03111f2ad525d870d7c 100644 (file)
@@ -487,6 +487,7 @@ fn construct_fn<'tcx>(
         return custom::build_custom_mir(
             tcx,
             fn_def.did.to_def_id(),
+            fn_id,
             thir,
             expr,
             arguments,
index fb1ea9ed300ad4f8c87a02d6c32718c614ceca21..99e96ff77ced9bff4c0ab710e1db1fafc01ebb66 100644 (file)
@@ -1,7 +1,7 @@
 use crate::build::ExprCategory;
+use crate::errors::*;
 use rustc_middle::thir::visit::{self, Visitor};
 
-use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_middle::mir::BorrowKind;
 use rustc_middle::thir::*;
@@ -12,7 +12,6 @@
 use rustc_span::symbol::Symbol;
 use rustc_span::Span;
 
-use std::borrow::Cow;
 use std::ops::Bound;
 
 struct UnsafetyVisitor<'a, 'tcx> {
@@ -46,7 +45,9 @@ fn in_safety_context(&mut self, safety_context: SafetyContext, f: impl FnOnce(&m
             self.warn_unused_unsafe(
                 hir_id,
                 block_span,
-                Some((self.tcx.sess.source_map().guess_head_span(enclosing_span), "block")),
+                Some(UnusedUnsafeEnclosing::Block {
+                    span: self.tcx.sess.source_map().guess_head_span(enclosing_span),
+                }),
             );
             f(self);
         } else {
@@ -60,7 +61,9 @@ fn in_safety_context(&mut self, safety_context: SafetyContext, f: impl FnOnce(&m
                     hir_id,
                     span,
                     if self.unsafe_op_in_unsafe_fn_allowed() {
-                        self.body_unsafety.unsafe_fn_sig_span().map(|span| (span, "fn"))
+                        self.body_unsafety
+                            .unsafe_fn_sig_span()
+                            .map(|span| UnusedUnsafeEnclosing::Function { span })
                     } else {
                         None
                     },
@@ -83,30 +86,11 @@ fn requires_unsafe(&mut self, span: Span, kind: UnsafeOpKind) {
             }
             SafetyContext::UnsafeFn if unsafe_op_in_unsafe_fn_allowed => {}
             SafetyContext::UnsafeFn => {
-                let (description, note) = kind.description_and_note(self.tcx);
                 // unsafe_op_in_unsafe_fn is disallowed
-                self.tcx.struct_span_lint_hir(
-                    UNSAFE_OP_IN_UNSAFE_FN,
-                    self.hir_context,
-                    span,
-                    format!("{} is unsafe and requires unsafe block (error E0133)", description,),
-                    |lint| lint.span_label(span, kind.simple_description()).note(note),
-                )
+                kind.emit_unsafe_op_in_unsafe_fn_lint(self.tcx, self.hir_context, span);
             }
             SafetyContext::Safe => {
-                let (description, note) = kind.description_and_note(self.tcx);
-                let fn_sugg = if unsafe_op_in_unsafe_fn_allowed { " function or" } else { "" };
-                struct_span_err!(
-                    self.tcx.sess,
-                    span,
-                    E0133,
-                    "{} is unsafe and requires unsafe{} block",
-                    description,
-                    fn_sugg,
-                )
-                .span_label(span, kind.simple_description())
-                .note(note)
-                .emit();
+                kind.emit_requires_unsafe_err(self.tcx, span, unsafe_op_in_unsafe_fn_allowed);
             }
         }
     }
@@ -115,23 +99,33 @@ fn warn_unused_unsafe(
         &self,
         hir_id: hir::HirId,
         block_span: Span,
-        enclosing_unsafe: Option<(Span, &'static str)>,
+        enclosing_unsafe: Option<UnusedUnsafeEnclosing>,
     ) {
         let block_span = self.tcx.sess.source_map().guess_head_span(block_span);
-        let msg = "unnecessary `unsafe` block";
-        self.tcx.struct_span_lint_hir(UNUSED_UNSAFE, hir_id, block_span, msg, |lint| {
-            lint.span_label(block_span, msg);
-            if let Some((span, kind)) = enclosing_unsafe {
-                lint.span_label(span, format!("because it's nested under this `unsafe` {}", kind));
-            }
-            lint
-        });
+        self.tcx.emit_spanned_lint(
+            UNUSED_UNSAFE,
+            hir_id,
+            block_span,
+            UnusedUnsafe { span: block_span, enclosing: enclosing_unsafe },
+        );
     }
 
     /// Whether the `unsafe_op_in_unsafe_fn` lint is `allow`ed at the current HIR node.
     fn unsafe_op_in_unsafe_fn_allowed(&self) -> bool {
         self.tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, self.hir_context).0 == Level::Allow
     }
+
+    /// Handle closures/generators/inline-consts, which is unsafecked with their parent body.
+    fn visit_inner_body(&mut self, def: ty::WithOptConstParam<LocalDefId>) {
+        if let Ok((inner_thir, expr)) = self.tcx.thir_body(def) {
+            let inner_thir = &inner_thir.borrow();
+            let hir_context = self.tcx.hir().local_def_id_to_hir_id(def.did);
+            let mut inner_visitor = UnsafetyVisitor { thir: inner_thir, hir_context, ..*self };
+            inner_visitor.visit_expr(&inner_thir[expr]);
+            // Unsafe blocks can be used in the inner body, make sure to take it into account
+            self.safety_context = inner_visitor.safety_context;
+        }
+    }
 }
 
 // Searches for accesses to layout constrained fields.
@@ -408,16 +402,11 @@ fn visit_expr(&mut self, expr: &Expr<'tcx>) {
                 } else {
                     ty::WithOptConstParam::unknown(closure_id)
                 };
-                let (closure_thir, expr) = self.tcx.thir_body(closure_def).unwrap_or_else(|_| {
-                    (self.tcx.alloc_steal_thir(Thir::new()), ExprId::from_u32(0))
-                });
-                let closure_thir = &closure_thir.borrow();
-                let hir_context = self.tcx.hir().local_def_id_to_hir_id(closure_id);
-                let mut closure_visitor =
-                    UnsafetyVisitor { thir: closure_thir, hir_context, ..*self };
-                closure_visitor.visit_expr(&closure_thir[expr]);
-                // Unsafe blocks can be used in closures, make sure to take it into account
-                self.safety_context = closure_visitor.safety_context;
+                self.visit_inner_body(closure_def);
+            }
+            ExprKind::ConstBlock { did, substs: _ } => {
+                let def_id = did.expect_local();
+                self.visit_inner_body(ty::WithOptConstParam::unknown(def_id));
             }
             ExprKind::Field { lhs, .. } => {
                 let lhs = &self.thir[lhs];
@@ -529,81 +518,189 @@ enum UnsafeOpKind {
 use UnsafeOpKind::*;
 
 impl UnsafeOpKind {
-    pub fn simple_description(&self) -> &'static str {
-        match self {
-            CallToUnsafeFunction(..) => "call to unsafe function",
-            UseOfInlineAssembly => "use of inline assembly",
-            InitializingTypeWith => "initializing type with `rustc_layout_scalar_valid_range` attr",
-            UseOfMutableStatic => "use of mutable static",
-            UseOfExternStatic => "use of extern static",
-            DerefOfRawPointer => "dereference of raw pointer",
-            AccessToUnionField => "access to union field",
-            MutationOfLayoutConstrainedField => "mutation of layout constrained field",
-            BorrowOfLayoutConstrainedField => {
-                "borrow of layout constrained field with interior mutability"
-            }
-            CallToFunctionWith(..) => "call to function with `#[target_feature]`",
-        }
-    }
-
-    pub fn description_and_note(&self, tcx: TyCtxt<'_>) -> (Cow<'static, str>, &'static str) {
+    pub fn emit_unsafe_op_in_unsafe_fn_lint(
+        &self,
+        tcx: TyCtxt<'_>,
+        hir_id: hir::HirId,
+        span: Span,
+    ) {
         match self {
-            CallToUnsafeFunction(did) => (
-                if let Some(did) = did {
-                    Cow::from(format!("call to unsafe function `{}`", tcx.def_path_str(*did)))
-                } else {
-                    Cow::Borrowed(self.simple_description())
+            CallToUnsafeFunction(did) if did.is_some() => tcx.emit_spanned_lint(
+                UNSAFE_OP_IN_UNSAFE_FN,
+                hir_id,
+                span,
+                UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe {
+                    span,
+                    function: &tcx.def_path_str(did.unwrap()),
                 },
-                "consult the function's documentation for information on how to avoid undefined \
-                 behavior",
             ),
-            UseOfInlineAssembly => (
-                Cow::Borrowed(self.simple_description()),
-                "inline assembly is entirely unchecked and can cause undefined behavior",
+            CallToUnsafeFunction(..) => tcx.emit_spanned_lint(
+                UNSAFE_OP_IN_UNSAFE_FN,
+                hir_id,
+                span,
+                UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { span },
             ),
-            InitializingTypeWith => (
-                Cow::Borrowed(self.simple_description()),
-                "initializing a layout restricted type's field with a value outside the valid \
-                 range is undefined behavior",
+            UseOfInlineAssembly => tcx.emit_spanned_lint(
+                UNSAFE_OP_IN_UNSAFE_FN,
+                hir_id,
+                span,
+                UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { span },
             ),
-            UseOfMutableStatic => (
-                Cow::Borrowed(self.simple_description()),
-                "mutable statics can be mutated by multiple threads: aliasing violations or data \
-                 races will cause undefined behavior",
+            InitializingTypeWith => tcx.emit_spanned_lint(
+                UNSAFE_OP_IN_UNSAFE_FN,
+                hir_id,
+                span,
+                UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { span },
             ),
-            UseOfExternStatic => (
-                Cow::Borrowed(self.simple_description()),
-                "extern statics are not controlled by the Rust type system: invalid data, \
-                 aliasing violations or data races will cause undefined behavior",
+            UseOfMutableStatic => tcx.emit_spanned_lint(
+                UNSAFE_OP_IN_UNSAFE_FN,
+                hir_id,
+                span,
+                UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { span },
             ),
-            DerefOfRawPointer => (
-                Cow::Borrowed(self.simple_description()),
-                "raw pointers may be null, dangling or unaligned; they can violate aliasing rules \
-                 and cause data races: all of these are undefined behavior",
+            UseOfExternStatic => tcx.emit_spanned_lint(
+                UNSAFE_OP_IN_UNSAFE_FN,
+                hir_id,
+                span,
+                UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { span },
             ),
-            AccessToUnionField => (
-                Cow::Borrowed(self.simple_description()),
-                "the field may not be properly initialized: using uninitialized data will cause \
-                 undefined behavior",
+            DerefOfRawPointer => tcx.emit_spanned_lint(
+                UNSAFE_OP_IN_UNSAFE_FN,
+                hir_id,
+                span,
+                UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { span },
+            ),
+            AccessToUnionField => tcx.emit_spanned_lint(
+                UNSAFE_OP_IN_UNSAFE_FN,
+                hir_id,
+                span,
+                UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { span },
             ),
-            MutationOfLayoutConstrainedField => (
-                Cow::Borrowed(self.simple_description()),
-                "mutating layout constrained fields cannot statically be checked for valid values",
+            MutationOfLayoutConstrainedField => tcx.emit_spanned_lint(
+                UNSAFE_OP_IN_UNSAFE_FN,
+                hir_id,
+                span,
+                UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { span },
             ),
-            BorrowOfLayoutConstrainedField => (
-                Cow::Borrowed(self.simple_description()),
-                "references to fields of layout constrained fields lose the constraints. Coupled \
-                 with interior mutability, the field can be changed to invalid values",
+            BorrowOfLayoutConstrainedField => tcx.emit_spanned_lint(
+                UNSAFE_OP_IN_UNSAFE_FN,
+                hir_id,
+                span,
+                UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe { span },
             ),
-            CallToFunctionWith(did) => (
-                Cow::from(format!(
-                    "call to function `{}` with `#[target_feature]`",
-                    tcx.def_path_str(*did)
-                )),
-                "can only be called if the required target features are available",
+            CallToFunctionWith(did) => tcx.emit_spanned_lint(
+                UNSAFE_OP_IN_UNSAFE_FN,
+                hir_id,
+                span,
+                UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe {
+                    span,
+                    function: &tcx.def_path_str(*did),
+                },
             ),
         }
     }
+
+    pub fn emit_requires_unsafe_err(
+        &self,
+        tcx: TyCtxt<'_>,
+        span: Span,
+        unsafe_op_in_unsafe_fn_allowed: bool,
+    ) {
+        match self {
+            CallToUnsafeFunction(did) if did.is_some() && unsafe_op_in_unsafe_fn_allowed => {
+                tcx.sess.emit_err(CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
+                    span,
+                    function: &tcx.def_path_str(did.unwrap()),
+                });
+            }
+            CallToUnsafeFunction(did) if did.is_some() => {
+                tcx.sess.emit_err(CallToUnsafeFunctionRequiresUnsafe {
+                    span,
+                    function: &tcx.def_path_str(did.unwrap()),
+                });
+            }
+            CallToUnsafeFunction(..) if unsafe_op_in_unsafe_fn_allowed => {
+                tcx.sess.emit_err(
+                    CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed { span },
+                );
+            }
+            CallToUnsafeFunction(..) => {
+                tcx.sess.emit_err(CallToUnsafeFunctionRequiresUnsafeNameless { span });
+            }
+            UseOfInlineAssembly if unsafe_op_in_unsafe_fn_allowed => {
+                tcx.sess
+                    .emit_err(UseOfInlineAssemblyRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span });
+            }
+            UseOfInlineAssembly => {
+                tcx.sess.emit_err(UseOfInlineAssemblyRequiresUnsafe { span });
+            }
+            InitializingTypeWith if unsafe_op_in_unsafe_fn_allowed => {
+                tcx.sess
+                    .emit_err(InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span });
+            }
+            InitializingTypeWith => {
+                tcx.sess.emit_err(InitializingTypeWithRequiresUnsafe { span });
+            }
+            UseOfMutableStatic if unsafe_op_in_unsafe_fn_allowed => {
+                tcx.sess
+                    .emit_err(UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span });
+            }
+            UseOfMutableStatic => {
+                tcx.sess.emit_err(UseOfMutableStaticRequiresUnsafe { span });
+            }
+            UseOfExternStatic if unsafe_op_in_unsafe_fn_allowed => {
+                tcx.sess
+                    .emit_err(UseOfExternStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span });
+            }
+            UseOfExternStatic => {
+                tcx.sess.emit_err(UseOfExternStaticRequiresUnsafe { span });
+            }
+            DerefOfRawPointer if unsafe_op_in_unsafe_fn_allowed => {
+                tcx.sess
+                    .emit_err(DerefOfRawPointerRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span });
+            }
+            DerefOfRawPointer => {
+                tcx.sess.emit_err(DerefOfRawPointerRequiresUnsafe { span });
+            }
+            AccessToUnionField if unsafe_op_in_unsafe_fn_allowed => {
+                tcx.sess
+                    .emit_err(AccessToUnionFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span });
+            }
+            AccessToUnionField => {
+                tcx.sess.emit_err(AccessToUnionFieldRequiresUnsafe { span });
+            }
+            MutationOfLayoutConstrainedField if unsafe_op_in_unsafe_fn_allowed => {
+                tcx.sess.emit_err(
+                    MutationOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
+                        span,
+                    },
+                );
+            }
+            MutationOfLayoutConstrainedField => {
+                tcx.sess.emit_err(MutationOfLayoutConstrainedFieldRequiresUnsafe { span });
+            }
+            BorrowOfLayoutConstrainedField if unsafe_op_in_unsafe_fn_allowed => {
+                tcx.sess.emit_err(
+                    BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span },
+                );
+            }
+            BorrowOfLayoutConstrainedField => {
+                tcx.sess.emit_err(BorrowOfLayoutConstrainedFieldRequiresUnsafe { span });
+            }
+            CallToFunctionWith(did) if unsafe_op_in_unsafe_fn_allowed => {
+                tcx.sess.emit_err(CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
+                    span,
+                    function: &tcx.def_path_str(*did),
+                });
+            }
+            CallToFunctionWith(did) => {
+                tcx.sess.emit_err(CallToFunctionWithRequiresUnsafe {
+                    span,
+                    function: &tcx.def_path_str(*did),
+                });
+            }
+        }
+    }
 }
 
 pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalDefId>) {
@@ -612,11 +709,8 @@ pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalD
         return;
     }
 
-    // Closures are handled by their owner, if it has a body
-    if tcx.is_closure(def.did.to_def_id()) {
-        let hir = tcx.hir();
-        let owner = hir.enclosing_body_owner(hir.local_def_id_to_hir_id(def.did));
-        tcx.ensure().thir_check_unsafety(owner);
+    // Closures and inline consts are handled by their owner, if it has a body
+    if tcx.is_typeck_child(def.did.to_def_id()) {
         return;
     }
 
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
new file mode 100644 (file)
index 0000000..6817900
--- /dev/null
@@ -0,0 +1,616 @@
+use crate::thir::pattern::MatchCheckCtxt;
+use rustc_errors::Handler;
+use rustc_errors::{
+    error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, MultiSpan,
+};
+use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
+use rustc_middle::ty::{self, Ty};
+use rustc_span::{symbol::Ident, Span};
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_unconditional_recursion)]
+#[help]
+pub struct UnconditionalRecursion {
+    #[label]
+    pub span: Span,
+    #[label(mir_build_unconditional_recursion_call_site_label)]
+    pub call_sites: Vec<Span>,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe)]
+#[note]
+pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe<'a> {
+    #[label]
+    pub span: Span,
+    pub function: &'a str,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe_nameless)]
+#[note]
+pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless {
+    #[label]
+    pub span: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe)]
+#[note]
+pub struct UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe {
+    #[label]
+    pub span: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe)]
+#[note]
+pub struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe {
+    #[label]
+    pub span: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe)]
+#[note]
+pub struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe {
+    #[label]
+    pub span: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_unsafe_op_in_unsafe_fn_extern_static_requires_unsafe)]
+#[note]
+pub struct UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe {
+    #[label]
+    pub span: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_unsafe_op_in_unsafe_fn_deref_raw_pointer_requires_unsafe)]
+#[note]
+pub struct UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe {
+    #[label]
+    pub span: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_unsafe_op_in_unsafe_fn_union_field_requires_unsafe)]
+#[note]
+pub struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe {
+    #[label]
+    pub span: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_unsafe_op_in_unsafe_fn_mutation_of_layout_constrained_field_requires_unsafe)]
+#[note]
+pub struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe {
+    #[label]
+    pub span: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe)]
+pub struct UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe {
+    #[label]
+    pub span: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe)]
+#[note]
+pub struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe<'a> {
+    #[label]
+    pub span: Span,
+    pub function: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_call_to_unsafe_fn_requires_unsafe, code = "E0133")]
+#[note]
+pub struct CallToUnsafeFunctionRequiresUnsafe<'a> {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    pub function: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_call_to_unsafe_fn_requires_unsafe_nameless, code = "E0133")]
+#[note]
+pub struct CallToUnsafeFunctionRequiresUnsafeNameless {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_call_to_unsafe_fn_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
+#[note]
+pub struct CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    pub function: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(
+    mir_build_call_to_unsafe_fn_requires_unsafe_nameless_unsafe_op_in_unsafe_fn_allowed,
+    code = "E0133"
+)]
+#[note]
+pub struct CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_inline_assembly_requires_unsafe, code = "E0133")]
+#[note]
+pub struct UseOfInlineAssemblyRequiresUnsafe {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_inline_assembly_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
+#[note]
+pub struct UseOfInlineAssemblyRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_initializing_type_with_requires_unsafe, code = "E0133")]
+#[note]
+pub struct InitializingTypeWithRequiresUnsafe {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(
+    mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed,
+    code = "E0133"
+)]
+#[note]
+pub struct InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_mutable_static_requires_unsafe, code = "E0133")]
+#[note]
+pub struct UseOfMutableStaticRequiresUnsafe {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_mutable_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
+#[note]
+pub struct UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_extern_static_requires_unsafe, code = "E0133")]
+#[note]
+pub struct UseOfExternStaticRequiresUnsafe {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
+#[note]
+pub struct UseOfExternStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_deref_raw_pointer_requires_unsafe, code = "E0133")]
+#[note]
+pub struct DerefOfRawPointerRequiresUnsafe {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_deref_raw_pointer_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
+#[note]
+pub struct DerefOfRawPointerRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_union_field_requires_unsafe, code = "E0133")]
+#[note]
+pub struct AccessToUnionFieldRequiresUnsafe {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
+#[note]
+pub struct AccessToUnionFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_mutation_of_layout_constrained_field_requires_unsafe, code = "E0133")]
+#[note]
+pub struct MutationOfLayoutConstrainedFieldRequiresUnsafe {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(
+    mir_build_mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed,
+    code = "E0133"
+)]
+#[note]
+pub struct MutationOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_borrow_of_layout_constrained_field_requires_unsafe, code = "E0133")]
+#[note]
+pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafe {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(
+    mir_build_borrow_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed,
+    code = "E0133"
+)]
+#[note]
+pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_call_to_fn_with_requires_unsafe, code = "E0133")]
+#[note]
+pub struct CallToFunctionWithRequiresUnsafe<'a> {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    pub function: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
+#[note]
+pub struct CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    pub function: &'a str,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_unused_unsafe)]
+pub struct UnusedUnsafe {
+    #[label]
+    pub span: Span,
+    #[subdiagnostic]
+    pub enclosing: Option<UnusedUnsafeEnclosing>,
+}
+
+#[derive(Subdiagnostic)]
+pub enum UnusedUnsafeEnclosing {
+    #[label(mir_build_unused_unsafe_enclosing_block_label)]
+    Block {
+        #[primary_span]
+        span: Span,
+    },
+    #[label(mir_build_unused_unsafe_enclosing_fn_label)]
+    Function {
+        #[primary_span]
+        span: Span,
+    },
+}
+
+pub(crate) struct NonExhaustivePatternsTypeNotEmpty<'p, 'tcx, 'm> {
+    pub cx: &'m MatchCheckCtxt<'p, 'tcx>,
+    pub expr_span: Span,
+    pub span: Span,
+    pub ty: Ty<'tcx>,
+}
+
+impl<'a> IntoDiagnostic<'a> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> {
+    fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
+        let mut diag = handler.struct_span_err_with_code(
+            self.span,
+            rustc_errors::fluent::mir_build_non_exhaustive_patterns_type_not_empty,
+            error_code!(E0004),
+        );
+
+        let peeled_ty = self.ty.peel_refs();
+        diag.set_arg("ty", self.ty);
+        diag.set_arg("peeled_ty", peeled_ty);
+
+        if let ty::Adt(def, _) = peeled_ty.kind() {
+            let def_span = self
+                .cx
+                .tcx
+                .hir()
+                .get_if_local(def.did())
+                .and_then(|node| node.ident())
+                .map(|ident| ident.span)
+                .unwrap_or_else(|| self.cx.tcx.def_span(def.did()));
+
+            // workaround to make test pass
+            let mut span: MultiSpan = def_span.into();
+            span.push_span_label(def_span, "");
+
+            diag.span_note(span, rustc_errors::fluent::def_note);
+        }
+
+        let is_variant_list_non_exhaustive = match self.ty.kind() {
+            ty::Adt(def, _) if def.is_variant_list_non_exhaustive() && !def.did().is_local() => {
+                true
+            }
+            _ => false,
+        };
+
+        if is_variant_list_non_exhaustive {
+            diag.note(rustc_errors::fluent::non_exhaustive_type_note);
+        } else {
+            diag.note(rustc_errors::fluent::type_note);
+        }
+
+        if let ty::Ref(_, sub_ty, _) = self.ty.kind() {
+            if !sub_ty.is_inhabited_from(self.cx.tcx, self.cx.module, self.cx.param_env) {
+                diag.note(rustc_errors::fluent::reference_note);
+            }
+        }
+
+        let mut suggestion = None;
+        let sm = self.cx.tcx.sess.source_map();
+        if self.span.eq_ctxt(self.expr_span) {
+            // Get the span for the empty match body `{}`.
+            let (indentation, more) = if let Some(snippet) = sm.indentation_before(self.span) {
+                (format!("\n{}", snippet), "    ")
+            } else {
+                (" ".to_string(), "")
+            };
+            suggestion = Some((
+                self.span.shrink_to_hi().with_hi(self.expr_span.hi()),
+                format!(
+                    " {{{indentation}{more}_ => todo!(),{indentation}}}",
+                    indentation = indentation,
+                    more = more,
+                ),
+            ));
+        }
+
+        if let Some((span, sugg)) = suggestion {
+            diag.span_suggestion_verbose(
+                span,
+                rustc_errors::fluent::suggestion,
+                sugg,
+                Applicability::HasPlaceholders,
+            );
+        } else {
+            diag.help(rustc_errors::fluent::help);
+        }
+
+        diag
+    }
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_static_in_pattern, code = "E0158")]
+pub struct StaticInPattern {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_assoc_const_in_pattern, code = "E0158")]
+pub struct AssocConstInPattern {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_const_param_in_pattern, code = "E0158")]
+pub struct ConstParamInPattern {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_non_const_path, code = "E0080")]
+pub struct NonConstPath {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_unreachable_pattern)]
+pub struct UnreachablePattern {
+    #[label]
+    pub span: Option<Span>,
+    #[label(catchall_label)]
+    pub catchall: Option<Span>,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_const_pattern_depends_on_generic_parameter)]
+pub struct ConstPatternDependsOnGenericParameter {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_could_not_eval_const_pattern)]
+pub struct CouldNotEvalConstPattern {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_lower_range_bound_must_be_less_than_or_equal_to_upper, code = "E0030")]
+pub struct LowerRangeBoundMustBeLessThanOrEqualToUpper {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    #[note(teach_note)]
+    pub teach: Option<()>,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_lower_range_bound_must_be_less_than_upper, code = "E0579")]
+pub struct LowerRangeBoundMustBeLessThanUpper {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_leading_irrefutable_let_patterns)]
+#[note]
+#[help]
+pub struct LeadingIrrefutableLetPatterns {
+    pub count: usize,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_trailing_irrefutable_let_patterns)]
+#[note]
+#[help]
+pub struct TrailingIrrefutableLetPatterns {
+    pub count: usize,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_bindings_with_variant_name, code = "E0170")]
+pub struct BindingsWithVariantName {
+    #[suggestion(code = "{ty_path}::{ident}", applicability = "machine-applicable")]
+    pub suggestion: Option<Span>,
+    pub ty_path: String,
+    pub ident: Ident,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_irrefutable_let_patterns_generic_let)]
+#[note]
+#[help]
+pub struct IrrefutableLetPatternsGenericLet {
+    pub count: usize,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_irrefutable_let_patterns_if_let)]
+#[note]
+#[help]
+pub struct IrrefutableLetPatternsIfLet {
+    pub count: usize,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_irrefutable_let_patterns_if_let_guard)]
+#[note]
+#[help]
+pub struct IrrefutableLetPatternsIfLetGuard {
+    pub count: usize,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_irrefutable_let_patterns_let_else)]
+#[note]
+#[help]
+pub struct IrrefutableLetPatternsLetElse {
+    pub count: usize,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_irrefutable_let_patterns_while_let)]
+#[note]
+#[help]
+pub struct IrrefutableLetPatternsWhileLet {
+    pub count: usize,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_borrow_of_moved_value)]
+pub struct BorrowOfMovedValue<'tcx> {
+    #[primary_span]
+    pub span: Span,
+    #[label]
+    #[label(occurs_because_label)]
+    pub binding_span: Span,
+    #[label(value_borrowed_label)]
+    pub conflicts_ref: Vec<Span>,
+    pub name: Ident,
+    pub ty: Ty<'tcx>,
+    #[suggestion(code = "ref ", applicability = "machine-applicable")]
+    pub suggest_borrowing: Option<Span>,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_multiple_mut_borrows)]
+pub struct MultipleMutBorrows {
+    #[primary_span]
+    pub span: Span,
+    #[label]
+    pub binding_span: Span,
+    #[subdiagnostic]
+    pub occurences: Vec<MultipleMutBorrowOccurence>,
+    pub name: Ident,
+}
+
+#[derive(Subdiagnostic)]
+pub enum MultipleMutBorrowOccurence {
+    #[label(mutable_borrow)]
+    Mutable {
+        #[primary_span]
+        span: Span,
+        name_mut: Ident,
+    },
+    #[label(immutable_borrow)]
+    Immutable {
+        #[primary_span]
+        span: Span,
+        name_immut: Ident,
+    },
+    #[label(moved)]
+    Moved {
+        #[primary_span]
+        span: Span,
+        name_moved: Ident,
+    },
+}
index 8797529459534610bc479c57a9f8dc75cb023059..2b05e92fdcf20c0913e199bf11fdeeb591b73d8d 100644 (file)
@@ -19,6 +19,7 @@
 
 mod build;
 mod check_unsafety;
+mod errors;
 mod lints;
 pub mod thir;
 
index b21f30efce8076dcd993c481dd5f78cbe517e515..8529c64cd5cca64213f3b1efedb38df29c0094b5 100644 (file)
@@ -1,3 +1,4 @@
+use crate::errors::UnconditionalRecursion;
 use rustc_data_structures::graph::iterate::{
     NodeStatus, TriColorDepthFirstSearch, TriColorVisitor,
 };
@@ -36,19 +37,11 @@ pub(crate) fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
 
         let sp = tcx.def_span(def_id);
         let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-        tcx.struct_span_lint_hir(
+        tcx.emit_spanned_lint(
             UNCONDITIONAL_RECURSION,
             hir_id,
             sp,
-            "function cannot return without recursing",
-            |lint| {
-                lint.span_label(sp, "cannot return without recursing");
-                // offer some help to the programmer.
-                for call_span in vis.reachable_recursive_calls {
-                    lint.span_label(call_span, "recursive call site");
-                }
-                lint.help("a `loop` may express intention better if this is on purpose")
-            },
+            UnconditionalRecursion { span: sp, call_sites: vis.reachable_recursive_calls },
         );
     }
 }
index a9ed945d4a15a9b3356653fb623d40ed6b0ed6d5..57ae6a3652df5293116b866a65b79b5d4c1153d8 100644 (file)
@@ -33,13 +33,13 @@ pub(crate) fn lit_to_const<'tcx>(
             let str_bytes = s.as_str().as_bytes();
             ty::ValTree::from_raw_bytes(tcx, str_bytes)
         }
-        (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _))
+        (ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _))
             if matches!(inner_ty.kind(), ty::Slice(_)) =>
         {
             let bytes = data as &[u8];
             ty::ValTree::from_raw_bytes(tcx, bytes)
         }
-        (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
+        (ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
             let bytes = data as &[u8];
             ty::ValTree::from_raw_bytes(tcx, bytes)
         }
index 5fa41ebeb6e5966f9acf748e5ea7aa3ef1588251..261b95ba95b0e36781448e9fdc7be376773f99cb 100644 (file)
@@ -704,7 +704,7 @@ fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx>
             hir::ExprKind::Field(ref source, ..) => ExprKind::Field {
                 lhs: self.mirror_expr(source),
                 variant_index: VariantIdx::new(0),
-                name: Field::new(tcx.field_index(expr.hir_id, self.typeck_results)),
+                name: Field::new(self.typeck_results.field_index(expr.hir_id)),
             },
             hir::ExprKind::Cast(ref source, ref cast_ty) => {
                 // Check for a user-given type annotation on this `cast`
@@ -1079,7 +1079,7 @@ fn field_refs(&mut self, fields: &'tcx [hir::ExprField<'tcx>]) -> Box<[FieldExpr
         fields
             .iter()
             .map(|field| FieldExpr {
-                name: Field::new(self.tcx.field_index(field.hir_id, self.typeck_results)),
+                name: Field::new(self.typeck_results.field_index(field.hir_id)),
                 expr: self.mirror_expr(field.expr),
             })
             .collect()
index e369dba55242c8f1703b38120a99489ca2c80e0f..a94d8d6c6431c81c0d95e2f525d9cff0d8c12d08 100644 (file)
@@ -4,18 +4,22 @@
 };
 use super::{PatCtxt, PatternError};
 
+use crate::errors::*;
+
 use rustc_arena::TypedArena;
 use rustc_ast::Mutability;
 use rustc_errors::{
-    error_code, pluralize, struct_span_err, Applicability, DelayDm, Diagnostic, DiagnosticBuilder,
-    ErrorGuaranteed, MultiSpan,
+    pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
+    MultiSpan,
 };
 use rustc_hir as hir;
 use rustc_hir::def::*;
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{HirId, Pat};
+use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
+
 use rustc_session::lint::builtin::{
     BINDINGS_WITH_VARIANT_NAME, IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS,
 };
@@ -107,28 +111,20 @@ fn report_inlining_errors(&self) {
         for error in &self.errors {
             match *error {
                 PatternError::StaticInPattern(span) => {
-                    self.span_e0158(span, "statics cannot be referenced in patterns")
+                    self.tcx.sess.emit_err(StaticInPattern { span });
                 }
                 PatternError::AssocConstInPattern(span) => {
-                    self.span_e0158(span, "associated consts cannot be referenced in patterns")
+                    self.tcx.sess.emit_err(AssocConstInPattern { span });
                 }
                 PatternError::ConstParamInPattern(span) => {
-                    self.span_e0158(span, "const parameters cannot be referenced in patterns")
+                    self.tcx.sess.emit_err(ConstParamInPattern { span });
                 }
                 PatternError::NonConstPath(span) => {
-                    rustc_middle::mir::interpret::struct_error(
-                        self.tcx.at(span),
-                        "runtime values cannot be referenced in patterns",
-                    )
-                    .emit();
+                    self.tcx.sess.emit_err(NonConstPath { span });
                 }
             }
         }
     }
-
-    fn span_e0158(&self, span: Span, text: &str) {
-        struct_span_err!(self.tcx.sess, span, E0158, "{}", text).emit();
-    }
 }
 
 impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
@@ -345,29 +341,6 @@ fn check_let_chain(&mut self, cx: &mut MatchCheckCtxt<'p, 'tcx>, pat_id: HirId)
             );
             return true;
         }
-        let lint_affix = |affix: &[Option<(Span, bool)>], kind, suggestion| {
-            let span_start = affix[0].unwrap().0;
-            let span_end = affix.last().unwrap().unwrap().0;
-            let span = span_start.to(span_end);
-            let cnt = affix.len();
-            let s = pluralize!(cnt);
-            cx.tcx.struct_span_lint_hir(
-                IRREFUTABLE_LET_PATTERNS,
-                top,
-                span,
-                format!("{kind} irrefutable pattern{s} in let chain"),
-                |lint| {
-                    lint.note(format!(
-                        "{these} pattern{s} will always match",
-                        these = pluralize!("this", cnt),
-                    ))
-                    .help(format!(
-                        "consider moving {} {suggestion}",
-                        if cnt > 1 { "them" } else { "it" }
-                    ))
-                },
-            );
-        };
         if let Some(until) = chain_refutabilities.iter().position(|r| !matches!(*r, Some((_, false)))) && until > 0 {
             // The chain has a non-zero prefix of irrefutable `let` statements.
 
@@ -381,13 +354,21 @@ fn check_let_chain(&mut self, cx: &mut MatchCheckCtxt<'p, 'tcx>, pat_id: HirId)
             if !matches!(let_source, LetSource::WhileLet | LetSource::IfLetGuard) {
                 // Emit the lint
                 let prefix = &chain_refutabilities[..until];
-                lint_affix(prefix, "leading", "outside of the construct");
+                let span_start = prefix[0].unwrap().0;
+                let span_end = prefix.last().unwrap().unwrap().0;
+                let span = span_start.to(span_end);
+                let count = prefix.len();
+                cx.tcx.emit_spanned_lint(IRREFUTABLE_LET_PATTERNS, top, span, LeadingIrrefutableLetPatterns { count });
             }
         }
         if let Some(from) = chain_refutabilities.iter().rposition(|r| !matches!(*r, Some((_, false)))) && from != (chain_refutabilities.len() - 1) {
             // The chain has a non-empty suffix of irrefutable `let` statements
             let suffix = &chain_refutabilities[from + 1..];
-            lint_affix(suffix, "trailing", "into the body");
+            let span_start = suffix[0].unwrap().0;
+            let span_end = suffix.last().unwrap().unwrap().0;
+            let span = span_start.to(span_end);
+            let count = suffix.len();
+            cx.tcx.emit_spanned_lint(IRREFUTABLE_LET_PATTERNS, top, span, TrailingIrrefutableLetPatterns { count });
         }
         true
     }
@@ -568,32 +549,22 @@ fn check_for_bindings_named_same_as_variants(
             })
         {
             let variant_count = edef.variants().len();
-            cx.tcx.struct_span_lint_hir(
+            let ty_path = with_no_trimmed_paths!({
+                cx.tcx.def_path_str(edef.did())
+            });
+            cx.tcx.emit_spanned_lint(
                 BINDINGS_WITH_VARIANT_NAME,
                 p.hir_id,
                 p.span,
-                DelayDm(|| format!(
-                    "pattern binding `{}` is named the same as one \
-                        of the variants of the type `{}`",
-                    ident, cx.tcx.def_path_str(edef.did())
-                )),
-                |lint| {
-                    let ty_path = cx.tcx.def_path_str(edef.did());
-                    lint.code(error_code!(E0170));
-
+                BindingsWithVariantName {
                     // If this is an irrefutable pattern, and there's > 1 variant,
                     // then we can't actually match on this. Applying the below
                     // suggestion would produce code that breaks on `check_irrefutable`.
-                    if rf == Refutable || variant_count == 1 {
-                        lint.span_suggestion(
-                            p.span,
-                            "to match on the variant, qualify the path",
-                            format!("{}::{}", ty_path, ident),
-                            Applicability::MachineApplicable,
-                        );
-                    }
-
-                    lint
+                    suggestion: if rf == Refutable || variant_count == 1 {
+                        Some(p.span)
+                    } else { None },
+                    ty_path,
+                    ident,
                 },
             )
         }
@@ -611,14 +582,12 @@ fn pat_is_catchall(pat: &DeconstructedPat<'_, '_>) -> bool {
 }
 
 fn unreachable_pattern(tcx: TyCtxt<'_>, span: Span, id: HirId, catchall: Option<Span>) {
-    tcx.struct_span_lint_hir(UNREACHABLE_PATTERNS, id, span, "unreachable pattern", |lint| {
-        if let Some(catchall) = catchall {
-            // We had a catchall pattern, hint at that.
-            lint.span_label(span, "unreachable pattern");
-            lint.span_label(catchall, "matches any value");
-        }
-        lint
-    });
+    tcx.emit_spanned_lint(
+        UNREACHABLE_PATTERNS,
+        id,
+        span,
+        UnreachablePattern { span: if catchall.is_some() { Some(span) } else { None }, catchall },
+    );
 }
 
 fn irrefutable_let_pattern(tcx: TyCtxt<'_>, id: HirId, span: Span) {
@@ -634,67 +603,18 @@ fn irrefutable_let_patterns(
     span: Span,
 ) {
     macro_rules! emit_diag {
-        (
-            $lint:expr,
-            $source_name:expr,
-            $note_sufix:expr,
-            $help_sufix:expr
-        ) => {{
-            let s = pluralize!(count);
-            let these = pluralize!("this", count);
-            tcx.struct_span_lint_hir(
-                IRREFUTABLE_LET_PATTERNS,
-                id,
-                span,
-                format!("irrefutable {} pattern{s}", $source_name),
-                |lint| {
-                    lint.note(&format!(
-                        "{these} pattern{s} will always match, so the {}",
-                        $note_sufix
-                    ))
-                    .help(concat!("consider ", $help_sufix))
-                },
-            )
+        ($lint:tt) => {{
+            tcx.emit_spanned_lint(IRREFUTABLE_LET_PATTERNS, id, span, $lint { count });
         }};
     }
 
     match source {
-        LetSource::GenericLet => {
-            emit_diag!(lint, "`let`", "`let` is useless", "removing `let`");
-        }
-        LetSource::IfLet => {
-            emit_diag!(
-                lint,
-                "`if let`",
-                "`if let` is useless",
-                "replacing the `if let` with a `let`"
-            );
-        }
-        LetSource::IfLetGuard => {
-            emit_diag!(
-                lint,
-                "`if let` guard",
-                "guard is useless",
-                "removing the guard and adding a `let` inside the match arm"
-            );
-        }
-        LetSource::LetElse => {
-            emit_diag!(
-                lint,
-                "`let...else`",
-                "`else` clause is useless",
-                "removing the `else` clause"
-            );
-        }
-        LetSource::WhileLet => {
-            emit_diag!(
-                lint,
-                "`while let`",
-                "loop will never exit",
-                "instead using a `loop { ... }` with a `let` inside it"
-            );
-        }
-    };
+        LetSource::GenericLet => emit_diag!(IrrefutableLetPatternsGenericLet),
+        LetSource::IfLet => emit_diag!(IrrefutableLetPatternsIfLet),
+        LetSource::IfLetGuard => emit_diag!(IrrefutableLetPatternsIfLetGuard),
+        LetSource::LetElse => emit_diag!(IrrefutableLetPatternsLetElse),
+        LetSource::WhileLet => emit_diag!(IrrefutableLetPatternsWhileLet),
+    }
 }
 
 fn is_let_irrefutable<'p, 'tcx>(
@@ -760,15 +680,17 @@ fn non_exhaustive_match<'p, 'tcx>(
     // informative.
     let mut err;
     let pattern;
-    let mut patterns_len = 0;
+    let patterns_len;
     if is_empty_match && !non_empty_enum {
-        err = create_e0004(
-            cx.tcx.sess,
-            sp,
-            format!("non-exhaustive patterns: type `{}` is non-empty", scrut_ty),
-        );
-        pattern = "_".to_string();
+        cx.tcx.sess.emit_err(NonExhaustivePatternsTypeNotEmpty {
+            cx,
+            expr_span,
+            span: sp,
+            ty: scrut_ty,
+        });
+        return;
     } else {
+        // FIXME: migration of this diagnostic will require list support
         let joined_patterns = joined_uncovered_patterns(cx, &witnesses);
         err = create_e0004(
             cx.tcx.sess,
@@ -1039,24 +961,17 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pa
                 }
             });
             if !conflicts_ref.is_empty() {
-                let occurs_because = format!(
-                    "move occurs because `{}` has type `{}` which does not implement the `Copy` trait",
+                sess.emit_err(BorrowOfMovedValue {
+                    span: pat.span,
+                    binding_span,
+                    conflicts_ref,
                     name,
-                    typeck_results.node_type(pat.hir_id),
-                );
-                let mut err = sess.struct_span_err(pat.span, "borrow of moved value");
-                err.span_label(binding_span, format!("value moved into `{}` here", name))
-                    .span_label(binding_span, occurs_because)
-                    .span_labels(conflicts_ref, "value borrowed here after move");
-                if pat.span.contains(binding_span) {
-                    err.span_suggestion_verbose(
-                        binding_span.shrink_to_lo(),
-                        "borrow this binding in the pattern to avoid moving the value",
-                        "ref ".to_string(),
-                        Applicability::MachineApplicable,
-                    );
-                }
-                err.emit();
+                    ty: typeck_results.node_type(pat.hir_id),
+                    suggest_borrowing: pat
+                        .span
+                        .contains(binding_span)
+                        .then(|| binding_span.shrink_to_lo()),
+                });
             }
             return;
         }
@@ -1086,19 +1001,18 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pa
     // Report errors if any.
     if !conflicts_mut_mut.is_empty() {
         // Report mutability conflicts for e.g. `ref mut x @ Some(ref mut y)`.
-        let mut err = sess
-            .struct_span_err(pat.span, "cannot borrow value as mutable more than once at a time");
-        err.span_label(binding_span, format!("first mutable borrow, by `{}`, occurs here", name));
-        for (span, name) in conflicts_mut_mut {
-            err.span_label(span, format!("another mutable borrow, by `{}`, occurs here", name));
+        let mut occurences = vec![];
+
+        for (span, name_mut) in conflicts_mut_mut {
+            occurences.push(MultipleMutBorrowOccurence::Mutable { span, name_mut });
         }
-        for (span, name) in conflicts_mut_ref {
-            err.span_label(span, format!("also borrowed as immutable, by `{}`, here", name));
+        for (span, name_immut) in conflicts_mut_ref {
+            occurences.push(MultipleMutBorrowOccurence::Immutable { span, name_immut });
         }
-        for (span, name) in conflicts_move {
-            err.span_label(span, format!("also moved into `{}` here", name));
+        for (span, name_moved) in conflicts_move {
+            occurences.push(MultipleMutBorrowOccurence::Moved { span, name_moved });
         }
-        err.emit();
+        sess.emit_err(MultipleMutBorrows { span: pat.span, binding_span, occurences, name });
     } else if !conflicts_mut_ref.is_empty() {
         // Report mutability conflicts for e.g. `ref x @ Some(ref mut y)` or the converse.
         let (primary, also) = match mut_outer {
index a21f6cd39f01442aa6b45b1d86c528571dd1d113..7e1f708b0d6a1685f01257e69c479cb20097bbc9 100644 (file)
@@ -121,7 +121,7 @@ fn search_for_structural_match_violation(&self, ty: Ty<'tcx>) -> Option<String>
                 ty::Dynamic(..) => {
                     "trait objects cannot be used in patterns".to_string()
                 }
-                ty::Opaque(..) => {
+                ty::Alias(ty::Opaque, ..) => {
                     "opaque types cannot be used in patterns".to_string()
                 }
                 ty::Closure(..) => {
index d60e8722cb61d5c443e20ef22d8c061d100781e0..18e9c69c4870e3b8796c5b01e1e2b73c3c6c0d18 100644 (file)
@@ -45,7 +45,7 @@
 use std::cell::Cell;
 use std::cmp::{self, max, min, Ordering};
 use std::fmt;
-use std::iter::{once, IntoIterator};
+use std::iter::once;
 use std::ops::RangeInclusive;
 
 use smallvec::{smallvec, SmallVec};
index 4c2a80e523f3537593bec024938dc2d35b246f15..2c775b397182b352eea62549c4b7179129e20178 100644 (file)
@@ -6,10 +6,12 @@
 mod usefulness;
 
 pub(crate) use self::check_match::check_match;
+pub(crate) use self::usefulness::MatchCheckCtxt;
 
+use crate::errors::*;
 use crate::thir::util::UserAnnotatedTyHelpers;
 
-use rustc_errors::struct_span_err;
+use rustc_errors::error_code;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::pat_util::EnumerateAndAdjustIterator;
@@ -139,13 +141,7 @@ fn lower_pattern_range(
             }
             // `x..y` where `x >= y`. The range is empty => error.
             (RangeEnd::Excluded, _) => {
-                struct_span_err!(
-                    self.tcx.sess,
-                    span,
-                    E0579,
-                    "lower range bound must be less than upper"
-                )
-                .emit();
+                self.tcx.sess.emit_err(LowerRangeBoundMustBeLessThanUpper { span });
                 PatKind::Wild
             }
             // `x..=y` where `x == y`.
@@ -156,23 +152,10 @@ fn lower_pattern_range(
             }
             // `x..=y` where `x > y` hence the range is empty => error.
             (RangeEnd::Included, _) => {
-                let mut err = struct_span_err!(
-                    self.tcx.sess,
+                self.tcx.sess.emit_err(LowerRangeBoundMustBeLessThanOrEqualToUpper {
                     span,
-                    E0030,
-                    "lower range bound must be less than or equal to upper"
-                );
-                err.span_label(span, "lower bound larger than upper bound");
-                if self.tcx.sess.teach(&err.get_code().unwrap()) {
-                    err.note(
-                        "When matching against a range, the compiler \
-                              verifies that the range is non-empty. Range \
-                              patterns include both end-points, so this is \
-                              equivalent to requiring the start of the range \
-                              to be less than or equal to the end of the range.",
-                    );
-                }
-                err.emit();
+                    teach: if self.tcx.sess.teach(&error_code!(E0030)) { Some(()) } else { None },
+                });
                 PatKind::Wild
             }
         }
@@ -321,7 +304,7 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tc
                 let subpatterns = fields
                     .iter()
                     .map(|field| FieldPat {
-                        field: Field::new(self.tcx.field_index(field.hir_id, self.typeck_results)),
+                        field: Field::new(self.typeck_results.field_index(field.hir_id)),
                         pattern: self.lower_pattern(&field.pat),
                     })
                     .collect();
@@ -501,7 +484,7 @@ fn lower_path(&mut self, qpath: &hir::QPath<'_>, id: hir::HirId, span: Span) ->
             }
 
             Err(_) => {
-                self.tcx.sess.span_err(span, "could not evaluate constant pattern");
+                self.tcx.sess.emit_err(CouldNotEvalConstPattern { span });
                 return pat_from_kind(PatKind::Wild);
             }
         };
@@ -548,11 +531,11 @@ fn lower_path(&mut self, qpath: &hir::QPath<'_>, id: hir::HirId, span: Span) ->
             Err(ErrorHandled::TooGeneric) => {
                 // While `Reported | Linted` cases will have diagnostics emitted already
                 // it is not true for TooGeneric case, so we need to give user more information.
-                self.tcx.sess.span_err(span, "constant pattern depends on a generic parameter");
+                self.tcx.sess.emit_err(ConstPatternDependsOnGenericParameter { span });
                 pat_from_kind(PatKind::Wild)
             }
             Err(_) => {
-                self.tcx.sess.span_err(span, "could not evaluate constant pattern");
+                self.tcx.sess.emit_err(CouldNotEvalConstPattern { span });
                 pat_from_kind(PatKind::Wild)
             }
         }
@@ -584,7 +567,7 @@ fn lower_inline_const(
             mir::ConstantKind::Val(_, _) => self.const_to_pat(value, id, span, false).kind,
             mir::ConstantKind::Unevaluated(..) => {
                 // If we land here it means the const can't be evaluated because it's `TooGeneric`.
-                self.tcx.sess.span_err(span, "constant pattern depends on a generic parameter");
+                self.tcx.sess.emit_err(ConstPatternDependsOnGenericParameter { span });
                 return PatKind::Wild;
             }
         }
index 3e370a053766574d110cefebb855cfed25ff81fc..8f80cb95e58e70ff3512a5c95c93977c3e3490af 100644 (file)
@@ -845,7 +845,7 @@ fn is_useful<'p, 'tcx>(
 
         // Opaque types can't get destructured/split, but the patterns can
         // actually hint at hidden types, so we use the patterns' types instead.
-        if let ty::Opaque(..) = ty.kind() {
+        if let ty::Alias(ty::Opaque, ..) = ty.kind() {
             if let Some(row) = rows.first() {
                 ty = row.head().ty();
             }
index f102872cd2d064abeda1d758bde420d5b25d6c38..3224e13f7af4bfe9da8c9fd3b045edadee2b5496 100644 (file)
@@ -29,56 +29,6 @@ pub fn move_path_children_matching<'tcx, F>(
     None
 }
 
-/// When enumerating the child fragments of a path, don't recurse into
-/// paths (1.) past arrays, slices, and pointers, nor (2.) into a type
-/// that implements `Drop`.
-///
-/// Places behind references or arrays are not tracked by elaboration
-/// and are always assumed to be initialized when accessible. As
-/// references and indexes can be reseated, trying to track them can
-/// only lead to trouble.
-///
-/// Places behind ADT's with a Drop impl are not tracked by
-/// elaboration since they can never have a drop-flag state that
-/// differs from that of the parent with the Drop impl.
-///
-/// In both cases, the contents can only be accessed if and only if
-/// their parents are initialized. This implies for example that there
-/// is no need to maintain separate drop flags to track such state.
-//
-// FIXME: we have to do something for moving slice patterns.
-fn place_contents_drop_state_cannot_differ<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    body: &Body<'tcx>,
-    place: mir::Place<'tcx>,
-) -> bool {
-    let ty = place.ty(body, tcx).ty;
-    match ty.kind() {
-        ty::Array(..) => {
-            debug!(
-                "place_contents_drop_state_cannot_differ place: {:?} ty: {:?} => false",
-                place, ty
-            );
-            false
-        }
-        ty::Slice(..) | ty::Ref(..) | ty::RawPtr(..) => {
-            debug!(
-                "place_contents_drop_state_cannot_differ place: {:?} ty: {:?} refd => true",
-                place, ty
-            );
-            true
-        }
-        ty::Adt(def, _) if (def.has_dtor(tcx) && !def.is_box()) || def.is_union() => {
-            debug!(
-                "place_contents_drop_state_cannot_differ place: {:?} ty: {:?} Drop => true",
-                place, ty
-            );
-            true
-        }
-        _ => false,
-    }
-}
-
 pub fn on_lookup_result_bits<'tcx, F>(
     tcx: TyCtxt<'tcx>,
     body: &Body<'tcx>,
@@ -105,13 +55,58 @@ pub fn on_all_children_bits<'tcx, F>(
 ) where
     F: FnMut(MovePathIndex),
 {
+    #[inline]
     fn is_terminal_path<'tcx>(
         tcx: TyCtxt<'tcx>,
         body: &Body<'tcx>,
         move_data: &MoveData<'tcx>,
         path: MovePathIndex,
     ) -> bool {
-        place_contents_drop_state_cannot_differ(tcx, body, move_data.move_paths[path].place)
+        let place = move_data.move_paths[path].place;
+
+        // When enumerating the child fragments of a path, don't recurse into
+        // paths (1.) past arrays, slices, and pointers, nor (2.) into a type
+        // that implements `Drop`.
+        //
+        // Places behind references or arrays are not tracked by elaboration
+        // and are always assumed to be initialized when accessible. As
+        // references and indexes can be reseated, trying to track them can
+        // only lead to trouble.
+        //
+        // Places behind ADT's with a Drop impl are not tracked by
+        // elaboration since they can never have a drop-flag state that
+        // differs from that of the parent with the Drop impl.
+        //
+        // In both cases, the contents can only be accessed if and only if
+        // their parents are initialized. This implies for example that there
+        // is no need to maintain separate drop flags to track such state.
+        //
+        // FIXME: we have to do something for moving slice patterns.
+        let ty = place.ty(body, tcx).ty;
+        match ty.kind() {
+            ty::Adt(def, _) if (def.has_dtor(tcx) && !def.is_box()) || def.is_union() => {
+                debug!(
+                    "place_contents_drop_state_cannot_differ place: {:?} ty: {:?} Drop => true",
+                    place, ty
+                );
+                true
+            }
+            ty::Array(..) => {
+                debug!(
+                    "place_contents_drop_state_cannot_differ place: {:?} ty: {:?} => false",
+                    place, ty
+                );
+                false
+            }
+            ty::Slice(..) | ty::Ref(..) | ty::RawPtr(..) => {
+                debug!(
+                    "place_contents_drop_state_cannot_differ place: {:?} ty: {:?} refd => true",
+                    place, ty
+                );
+                true
+            }
+            _ => false,
+        }
     }
 
     fn on_all_children_bits<'tcx, F>(
index ce87a1916b4658034ba7941ab6149b7713375ad0..7836ae2e7b76f9959107eceb12875c9da02fdd63 100644 (file)
@@ -596,7 +596,6 @@ fn adt_switch_block(
                 source_info: self.source_info,
                 kind: TerminatorKind::SwitchInt {
                     discr: Operand::Move(discr),
-                    switch_ty: discr_ty,
                     targets: SwitchTargets::new(
                         values.iter().copied().zip(blocks.iter().copied()),
                         *blocks.last().unwrap(),
@@ -615,7 +614,6 @@ fn destructor_call_block(&mut self, (succ, unwind): (BasicBlock, Unwind)) -> Bas
         let drop_trait = tcx.require_lang_item(LangItem::Drop, None);
         let drop_fn = tcx.associated_item_def_ids(drop_trait)[0];
         let ty = self.place_ty(self.place);
-        let substs = tcx.mk_substs_trait(ty, []);
 
         let ref_ty =
             tcx.mk_ref(tcx.lifetimes.re_erased, ty::TypeAndMut { ty, mutbl: hir::Mutability::Mut });
@@ -633,7 +631,12 @@ fn destructor_call_block(&mut self, (succ, unwind): (BasicBlock, Unwind)) -> Bas
             )],
             terminator: Some(Terminator {
                 kind: TerminatorKind::Call {
-                    func: Operand::function_handle(tcx, drop_fn, substs, self.source_info.span),
+                    func: Operand::function_handle(
+                        tcx,
+                        drop_fn,
+                        [ty.into()],
+                        self.source_info.span,
+                    ),
                     args: vec![Operand::Move(Place::from(ref_place))],
                     destination: unit_temp,
                     target: Some(succ),
@@ -716,7 +719,7 @@ fn drop_loop(
             is_cleanup: unwind.is_cleanup(),
             terminator: Some(Terminator {
                 source_info: self.source_info,
-                kind: TerminatorKind::if_(tcx, move_(can_go), succ, drop_block),
+                kind: TerminatorKind::if_(move_(can_go), succ, drop_block),
             }),
         };
         let loop_block = self.elaborator.patch().new_block(loop_block);
@@ -781,7 +784,6 @@ fn open_drop_for_array(&mut self, ety: Ty<'tcx>, opt_size: Option<u64>) -> Basic
                 source_info: self.source_info,
                 kind: TerminatorKind::SwitchInt {
                     discr: move_(elem_size),
-                    switch_ty: tcx.types.usize,
                     targets: SwitchTargets::static_if(
                         0,
                         self.drop_loop_pair(ety, false, len),
@@ -1021,7 +1023,7 @@ fn drop_flag_test_block(
             DropStyle::Static => on_set,
             DropStyle::Conditional | DropStyle::Open => {
                 let flag = self.elaborator.get_drop_flag(self.path).unwrap();
-                let term = TerminatorKind::if_(self.tcx(), flag, on_set, on_unset);
+                let term = TerminatorKind::if_(flag, on_set, on_unset);
                 self.new_block(unwind, term)
             }
         }
index 5c77f3ea395334abc0d5f0c891b11a606ae1bcc1..5ff6b9e7e69b4f8257a49d4190a996da6b75e017 100644 (file)
@@ -261,7 +261,7 @@ fn join_state_into_successors_of<'tcx, A>(
                     propagate(pred, &tmp);
                 }
 
-                mir::TerminatorKind::SwitchInt { targets: _, ref discr, switch_ty: _ } => {
+                mir::TerminatorKind::SwitchInt { targets: _, ref discr } => {
                     let mut applier = BackwardSwitchIntEdgeEffectsApplier {
                         body,
                         pred,
@@ -577,7 +577,7 @@ fn join_state_into_successors_of<'tcx, A>(
                 }
             }
 
-            SwitchInt { ref targets, ref discr, switch_ty: _ } => {
+            SwitchInt { ref targets, ref discr } => {
                 let mut applier = ForwardSwitchIntEdgeEffectsApplier {
                     exit_state,
                     targets,
index f0e75c53ea15c93e9fa6c7fcd46843c25a191f26..8fdac7b2cf501e1540a526392a1cde97c7397216 100644 (file)
@@ -26,7 +26,7 @@
 //! ## `PartialOrd`
 //!
 //! Given that they represent partially ordered sets, you may be surprised that [`JoinSemiLattice`]
-//! and [`MeetSemiLattice`] do not have [`PartialOrd`][std::cmp::PartialOrd] as a supertrait. This
+//! and [`MeetSemiLattice`] do not have [`PartialOrd`] as a supertrait. This
 //! is because most standard library types use lexicographic ordering instead of set inclusion for
 //! their `PartialOrd` impl. Since we do not actually need to compare lattice elements to run a
 //! dataflow analysis, there's no need for a newtype wrapper with a custom `PartialOrd` impl. The
index 18760b6c6fa543328b69ec269cc9c3c4a265afd2..8d379b90a86db28194b2946df68bc564b8e84961 100644 (file)
@@ -3,20 +3,21 @@
 use crate::{CallReturnPlaces, GenKill, Results, ResultsRefCursor};
 use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
+use std::borrow::Cow;
 use std::cell::RefCell;
 
 #[derive(Clone)]
-pub struct MaybeStorageLive {
-    always_live_locals: BitSet<Local>,
+pub struct MaybeStorageLive<'a> {
+    always_live_locals: Cow<'a, BitSet<Local>>,
 }
 
-impl MaybeStorageLive {
-    pub fn new(always_live_locals: BitSet<Local>) -> Self {
+impl<'a> MaybeStorageLive<'a> {
+    pub fn new(always_live_locals: Cow<'a, BitSet<Local>>) -> Self {
         MaybeStorageLive { always_live_locals }
     }
 }
 
-impl<'tcx> crate::AnalysisDomain<'tcx> for MaybeStorageLive {
+impl<'tcx, 'a> crate::AnalysisDomain<'tcx> for MaybeStorageLive<'a> {
     type Domain = BitSet<Local>;
 
     const NAME: &'static str = "maybe_storage_live";
@@ -38,7 +39,7 @@ fn initialize_start_block(&self, body: &mir::Body<'tcx>, on_entry: &mut Self::Do
     }
 }
 
-impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeStorageLive {
+impl<'tcx, 'a> crate::GenKillAnalysis<'tcx> for MaybeStorageLive<'a> {
     type Idx = Local;
 
     fn statement_effect(
index 7806e8f45d3ade55a4f6c907a90e0d515273e88a..5cfbbb1ac01e773980cb20b726038875af7252cf 100644 (file)
@@ -18,7 +18,7 @@
 pub struct AbstractOperand;
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 pub struct AbstractType;
-pub type AbstractElem = ProjectionElem<AbstractOperand, AbstractType>;
+pub type AbstractElem = ProjectionElem<AbstractOperand, AbstractType, AbstractType>;
 
 pub trait Lift {
     type Abstract;
index 7df0114226418c890378eea776e08cc4b6b82973..ab16b60f82df94df027c9b1d36e97f53c4492e1a 100644 (file)
@@ -777,10 +777,10 @@ pub enum TrackElem {
     Field(Field),
 }
 
-impl<V, T> TryFrom<ProjectionElem<V, T>> for TrackElem {
+impl<V, T1, T2> TryFrom<ProjectionElem<V, T1, T2>> for TrackElem {
     type Error = ();
 
-    fn try_from(value: ProjectionElem<V, T>) -> Result<Self, Self::Error> {
+    fn try_from(value: ProjectionElem<V, T1, T2>) -> Result<Self, Self::Error> {
         match value {
             ProjectionElem::Field(field, _) => Ok(TrackElem::Field(field)),
             _ => Err(()),
index 036b5589849a274542145f19e7876cc252fd6cf1..3d22035f0785ed57509c86c251355156d92d3665 100644 (file)
 
 pub struct AddRetag;
 
-/// Determines whether this place is "stable": Whether, if we evaluate it again
-/// after the assignment, we can be sure to obtain the same place value.
-/// (Concurrent accesses by other threads are no problem as these are anyway non-atomic
-/// copies.  Data races are UB.)
-fn is_stable(place: PlaceRef<'_>) -> bool {
-    // Which place this evaluates to can change with any memory write,
-    // so cannot assume deref to be stable.
-    !place.has_deref()
-}
-
 /// Determine whether this type may contain a reference (or box), and thus needs retagging.
 /// We will only recurse `depth` times into Tuples/ADTs to bound the cost of this.
 fn may_contain_reference<'tcx>(ty: Ty<'tcx>, depth: u32, tcx: TyCtxt<'tcx>) -> bool {
@@ -69,22 +59,10 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         let basic_blocks = body.basic_blocks.as_mut();
         let local_decls = &body.local_decls;
         let needs_retag = |place: &Place<'tcx>| {
-            // FIXME: Instead of giving up for unstable places, we should introduce
-            // a temporary and retag on that.
-            is_stable(place.as_ref())
+            !place.has_deref() // we're not eally interested in stores to "outside" locations, they are hard to keep track of anyway
                 && may_contain_reference(place.ty(&*local_decls, tcx).ty, /*depth*/ 3, tcx)
                 && !local_decls[place.local].is_deref_temp()
         };
-        let place_base_raw = |place: &Place<'tcx>| {
-            // If this is a `Deref`, get the type of what we are deref'ing.
-            if place.has_deref() {
-                let ty = &local_decls[place.local].ty;
-                ty.is_unsafe_ptr()
-            } else {
-                // Not a deref, and thus not raw.
-                false
-            }
-        };
 
         // PART 1
         // Retag arguments at the beginning of the start block.
@@ -108,7 +86,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         }
 
         // PART 2
-        // Retag return values of functions.  Also escape-to-raw the argument of `drop`.
+        // Retag return values of functions.
         // We collect the return destinations because we cannot mutate while iterating.
         let returns = basic_blocks
             .iter_mut()
@@ -140,30 +118,25 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         }
 
         // PART 3
-        // Add retag after assignment.
+        // Add retag after assignments where data "enters" this function: the RHS is behind a deref and the LHS is not.
         for block_data in basic_blocks {
             // We want to insert statements as we iterate.  To this end, we
             // iterate backwards using indices.
             for i in (0..block_data.statements.len()).rev() {
                 let (retag_kind, place) = match block_data.statements[i].kind {
-                    // Retag-as-raw after escaping to a raw pointer, if the referent
-                    // is not already a raw pointer.
-                    StatementKind::Assign(box (lplace, Rvalue::AddressOf(_, ref rplace)))
-                        if !place_base_raw(rplace) =>
-                    {
-                        (RetagKind::Raw, lplace)
-                    }
                     // Retag after assignments of reference type.
                     StatementKind::Assign(box (ref place, ref rvalue)) if needs_retag(place) => {
-                        let kind = match rvalue {
-                            Rvalue::Ref(_, borrow_kind, _)
-                                if borrow_kind.allows_two_phase_borrow() =>
-                            {
-                                RetagKind::TwoPhase
-                            }
-                            _ => RetagKind::Default,
+                        let add_retag = match rvalue {
+                            // Ptr-creating operations already do their own internal retagging, no
+                            // need to also add a retag statement.
+                            Rvalue::Ref(..) | Rvalue::AddressOf(..) => false,
+                            _ => true,
                         };
-                        (kind, *place)
+                        if add_retag {
+                            (RetagKind::Default, *place)
+                        } else {
+                            continue;
+                        }
                     }
                     // Do nothing for the rest
                     _ => continue,
index e783d189137749cabfc28a12872bf7ff4ad64006..9c22b5df73ce85ea2423352c4c8d55ed0ea20abe 100644 (file)
@@ -1,6 +1,7 @@
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
+use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::hir_id::HirId;
 use rustc_hir::intravisit;
@@ -134,6 +135,28 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
         self.super_rvalue(rvalue, location);
     }
 
+    fn visit_operand(&mut self, op: &Operand<'tcx>, location: Location) {
+        if let Operand::Constant(constant) = op {
+            let maybe_uneval = match constant.literal {
+                ConstantKind::Val(..) | ConstantKind::Ty(_) => None,
+                ConstantKind::Unevaluated(uv, _) => Some(uv),
+            };
+
+            if let Some(uv) = maybe_uneval {
+                if uv.promoted.is_none() {
+                    let def_id = uv.def.def_id_for_type_of();
+                    if self.tcx.def_kind(def_id) == DefKind::InlineConst {
+                        let local_def_id = def_id.expect_local();
+                        let UnsafetyCheckResult { violations, used_unsafe_blocks, .. } =
+                            self.tcx.unsafety_check_result(local_def_id);
+                        self.register_violations(violations, used_unsafe_blocks.iter().copied());
+                    }
+                }
+            }
+        }
+        self.super_operand(op, location);
+    }
+
     fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) {
         // On types with `scalar_valid_range`, prevent
         // * `&mut x.field`
@@ -410,6 +433,12 @@ fn visit_block(&mut self, block: &'tcx hir::Block<'tcx>) {
         intravisit::walk_block(self, block);
     }
 
+    fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
+        if matches!(self.tcx.def_kind(c.def_id), DefKind::InlineConst) {
+            self.visit_body(self.tcx.hir().body(c.body))
+        }
+    }
+
     fn visit_fn(
         &mut self,
         fk: intravisit::FnKind<'tcx>,
@@ -471,7 +500,7 @@ fn unsafety_check_result<'tcx>(
     // `mir_built` force this.
     let body = &tcx.mir_built(def).borrow();
 
-    if body.should_skip() {
+    if body.is_custom_mir() {
         return tcx.arena.alloc(UnsafetyCheckResult {
             violations: Vec::new(),
             used_unsafe_blocks: FxHashSet::default(),
@@ -484,7 +513,7 @@ fn unsafety_check_result<'tcx>(
     let mut checker = UnsafetyChecker::new(body, def.did, tcx, param_env);
     checker.visit_body(&body);
 
-    let unused_unsafes = (!tcx.is_closure(def.did.to_def_id()))
+    let unused_unsafes = (!tcx.is_typeck_child(def.did.to_def_id()))
         .then(|| check_unused_unsafe(tcx, def.did, &checker.used_unsafe_blocks));
 
     tcx.arena.alloc(UnsafetyCheckResult {
@@ -516,8 +545,8 @@ fn report_unused_unsafe(tcx: TyCtxt<'_>, kind: UnusedUnsafe, id: HirId) {
 pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     debug!("check_unsafety({:?})", def_id);
 
-    // closures are handled by their parent fn.
-    if tcx.is_closure(def_id.to_def_id()) {
+    // closures and inline consts are handled by their parent fn.
+    if tcx.is_typeck_child(def_id.to_def_id()) {
         return;
     }
 
index 0a305a402095d758aecbe4ca5287f357f3c1a61e..40eefda4f076326002a270044b1526f9988110c3 100644 (file)
@@ -82,8 +82,9 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
                 }
 
                 let target_bb_terminator = target_bb.terminator();
-                let (discr, switch_ty, targets) = target_bb_terminator.kind.as_switch()?;
+                let (discr, targets) = target_bb_terminator.kind.as_switch()?;
                 if discr.place() == Some(*place) {
+                    let switch_ty = place.ty(self.body.local_decls(), self.tcx).ty;
                     // We now know that the Switch matches on the const place, and it is statementless
                     // Now find which value in the Switch matches the const value.
                     let const_value =
index b0514e033566c9a65ebe8f5484a41d74ddb39898..e384cfe165990c47940bde2566b8da034d49fe33 100644 (file)
@@ -6,6 +6,7 @@
 use either::Right;
 
 use rustc_ast::Mutability;
+use rustc_const_eval::const_eval::CheckAlignment;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def::DefKind;
 use rustc_index::bit_set::BitSet;
@@ -22,7 +23,7 @@
 use rustc_middle::ty::InternalSubsts;
 use rustc_middle::ty::{self, ConstKind, Instance, ParamEnv, Ty, TyCtxt, TypeVisitable};
 use rustc_span::{def_id::DefId, Span};
-use rustc_target::abi::{self, HasDataLayout, Size, TargetDataLayout};
+use rustc_target::abi::{self, Align, HasDataLayout, Size, TargetDataLayout};
 use rustc_target::spec::abi::Abi as CallAbi;
 use rustc_trait_selection::traits;
 
@@ -186,16 +187,27 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
     type MemoryKind = !;
 
     #[inline(always)]
-    fn enforce_alignment(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
+    fn enforce_alignment(_ecx: &InterpCx<'mir, 'tcx, Self>) -> CheckAlignment {
         // We do not check for alignment to avoid having to carry an `Align`
         // in `ConstValue::ByRef`.
-        false
+        CheckAlignment::No
     }
 
     #[inline(always)]
     fn enforce_validity(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
         false // for now, we don't enforce validity
     }
+    fn alignment_check_failed(
+        ecx: &InterpCx<'mir, 'tcx, Self>,
+        _has: Align,
+        _required: Align,
+        _check: CheckAlignment,
+    ) -> InterpResult<'tcx, ()> {
+        span_bug!(
+            ecx.cur_span(),
+            "`alignment_check_failed` called when no alignment check requested"
+        )
+    }
 
     fn load_mir(
         _ecx: &InterpCx<'mir, 'tcx, Self>,
@@ -689,8 +701,8 @@ fn eval_rvalue_with_identities(
                     BinOp::Mul if const_arg.layout.ty.is_integral() && arg_value == 0 => {
                         if let Rvalue::CheckedBinaryOp(_, _) = rvalue {
                             let val = Immediate::ScalarPair(
-                                const_arg.to_scalar().into(),
-                                Scalar::from_bool(false).into(),
+                                const_arg.to_scalar(),
+                                Scalar::from_bool(false),
                             );
                             this.ecx.write_immediate(val, &dest)
                         } else {
index 9c9ed5fa5105eda71866b54d8dd8b24f99abcda3..eba6a2b34e47ddb11379dc589c7090db1611b18d 100644 (file)
@@ -37,7 +37,7 @@
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_middle::mir::coverage::CoverageKind;
 use rustc_middle::mir::*;
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty;
 use rustc_span::{self, BytePos, Pos, Span, DUMMY_SP};
 
 // All `TEMP_BLOCK` targets should be replaced before calling `to_body() -> mir::Body`.
@@ -47,7 +47,6 @@ struct MockBlocks<'tcx> {
     blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
     dummy_place: Place<'tcx>,
     next_local: usize,
-    bool_ty: Ty<'tcx>,
 }
 
 impl<'tcx> MockBlocks<'tcx> {
@@ -56,7 +55,6 @@ fn new() -> Self {
             blocks: IndexVec::new(),
             dummy_place: Place { local: RETURN_PLACE, projection: ty::List::empty() },
             next_local: 0,
-            bool_ty: TyCtxt::BOOL_TY_FOR_UNIT_TESTING,
         }
     }
 
@@ -157,7 +155,6 @@ fn goto(&mut self, some_from_block: Option<BasicBlock>) -> BasicBlock {
     fn switchint(&mut self, some_from_block: Option<BasicBlock>) -> BasicBlock {
         let switchint_kind = TerminatorKind::SwitchInt {
             discr: Operand::Move(Place::from(self.new_temp())),
-            switch_ty: self.bool_ty, // just a dummy value
             targets: SwitchTargets::static_if(0, TEMP_BLOCK, TEMP_BLOCK),
         };
         self.add_block_from(some_from_block, switchint_kind)
index e9027387413cfe1e97425a7992e74e33384fbfb3..c75fe2327de3eb0b52e35f0cbebfe02fc9282838 100644 (file)
@@ -2,6 +2,7 @@
 //!
 //! Currently, this pass only propagates scalar values.
 
+use rustc_const_eval::const_eval::CheckAlignment;
 use rustc_const_eval::interpret::{ConstValue, ImmTy, Immediate, InterpCx, Scalar};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::mir::visit::{MutVisitor, Visitor};
@@ -10,6 +11,7 @@
 use rustc_mir_dataflow::value_analysis::{Map, State, TrackElem, ValueAnalysis, ValueOrPlace};
 use rustc_mir_dataflow::{lattice::FlatSet, Analysis, ResultsVisitor, SwitchIntEdgeEffects};
 use rustc_span::DUMMY_SP;
+use rustc_target::abi::Align;
 
 use crate::MirPass;
 
@@ -448,13 +450,21 @@ impl<'mir, 'tcx> rustc_const_eval::interpret::Machine<'mir, 'tcx> for DummyMachi
     type MemoryKind = !;
     const PANIC_ON_ALLOC_FAIL: bool = true;
 
-    fn enforce_alignment(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
+    fn enforce_alignment(_ecx: &InterpCx<'mir, 'tcx, Self>) -> CheckAlignment {
         unimplemented!()
     }
 
     fn enforce_validity(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
         unimplemented!()
     }
+    fn alignment_check_failed(
+        _ecx: &InterpCx<'mir, 'tcx, Self>,
+        _has: Align,
+        _required: Align,
+        _check: CheckAlignment,
+    ) -> interpret::InterpResult<'tcx, ()> {
+        unimplemented!()
+    }
 
     fn find_mir_or_eval_fn(
         _ecx: &mut InterpCx<'mir, 'tcx, Self>,
index 97485c4f57b12ea872de807daf68c6ca9fe7ec8a..74d8337653f034f968ea516556563ebd1dc068c1 100644 (file)
 
 use std::collections::hash_map::{Entry, OccupiedEntry};
 
+use crate::simplify::remove_dead_blocks;
 use crate::MirPass;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_index::bit_set::BitSet;
+use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
 use rustc_middle::mir::{dump_mir, PassWhere};
 use rustc_middle::mir::{
     traversal, BasicBlock, Body, InlineAsmOperand, Local, LocalKind, Location, Operand, Place,
     Rvalue, Statement, StatementKind, TerminatorKind,
 };
-use rustc_middle::mir::{
-    visit::{MutVisitor, PlaceContext, Visitor},
-    ProjectionElem,
-};
 use rustc_middle::ty::TyCtxt;
 use rustc_mir_dataflow::impls::MaybeLiveLocals;
 use rustc_mir_dataflow::{Analysis, ResultsCursor};
@@ -238,6 +236,12 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             apply_merges(body, tcx, &merges, &merged_locals);
         }
 
+        if round_count != 0 {
+            // Merging can introduce overlap between moved arguments and/or call destination in an
+            // unreachable code, which validator considers to be ill-formed.
+            remove_dead_blocks(tcx, body);
+        }
+
         trace!(round_count);
     }
 }
@@ -359,40 +363,45 @@ struct FilterInformation<'a, 'body, 'alloc, 'tcx> {
 // through these methods, and not directly.
 impl<'alloc> Candidates<'alloc> {
     /// Just `Vec::retain`, but the condition is inverted and we add debugging output
-    fn vec_remove_debug(
+    fn vec_filter_candidates(
         src: Local,
         v: &mut Vec<Local>,
-        mut f: impl FnMut(Local) -> bool,
+        mut f: impl FnMut(Local) -> CandidateFilter,
         at: Location,
     ) {
         v.retain(|dest| {
             let remove = f(*dest);
-            if remove {
+            if remove == CandidateFilter::Remove {
                 trace!("eliminating {:?} => {:?} due to conflict at {:?}", src, dest, at);
             }
-            !remove
+            remove == CandidateFilter::Keep
         });
     }
 
-    /// `vec_remove_debug` but for an `Entry`
-    fn entry_remove(
+    /// `vec_filter_candidates` but for an `Entry`
+    fn entry_filter_candidates(
         mut entry: OccupiedEntry<'_, Local, Vec<Local>>,
         p: Local,
-        f: impl FnMut(Local) -> bool,
+        f: impl FnMut(Local) -> CandidateFilter,
         at: Location,
     ) {
         let candidates = entry.get_mut();
-        Self::vec_remove_debug(p, candidates, f, at);
+        Self::vec_filter_candidates(p, candidates, f, at);
         if candidates.len() == 0 {
             entry.remove();
         }
     }
 
-    /// Removes all candidates `(p, q)` or `(q, p)` where `p` is the indicated local and `f(q)` is true.
-    fn remove_candidates_if(&mut self, p: Local, mut f: impl FnMut(Local) -> bool, at: Location) {
+    /// For all candidates `(p, q)` or `(q, p)` removes the candidate if `f(q)` says to do so
+    fn filter_candidates_by(
+        &mut self,
+        p: Local,
+        mut f: impl FnMut(Local) -> CandidateFilter,
+        at: Location,
+    ) {
         // Cover the cases where `p` appears as a `src`
         if let Entry::Occupied(entry) = self.c.entry(p) {
-            Self::entry_remove(entry, p, &mut f, at);
+            Self::entry_filter_candidates(entry, p, &mut f, at);
         }
         // And the cases where `p` appears as a `dest`
         let Some(srcs) = self.reverse.get_mut(&p) else {
@@ -401,18 +410,31 @@ fn remove_candidates_if(&mut self, p: Local, mut f: impl FnMut(Local) -> bool, a
         // We use `retain` here to remove the elements from the reverse set if we've removed the
         // matching candidate in the forward set.
         srcs.retain(|src| {
-            if !f(*src) {
+            if f(*src) == CandidateFilter::Keep {
                 return true;
             }
             let Entry::Occupied(entry) = self.c.entry(*src) else {
                 return false;
             };
-            Self::entry_remove(entry, *src, |dest| dest == p, at);
+            Self::entry_filter_candidates(
+                entry,
+                *src,
+                |dest| {
+                    if dest == p { CandidateFilter::Remove } else { CandidateFilter::Keep }
+                },
+                at,
+            );
             false
         });
     }
 }
 
+#[derive(Copy, Clone, PartialEq, Eq)]
+enum CandidateFilter {
+    Keep,
+    Remove,
+}
+
 impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> {
     /// Filters the set of candidates to remove those that conflict.
     ///
@@ -460,7 +482,7 @@ fn internal_filter_liveness(&mut self) {
             for (i, statement) in data.statements.iter().enumerate().rev() {
                 self.at = Location { block, statement_index: i };
                 self.live.seek_after_primary_effect(self.at);
-                self.get_statement_write_info(&statement.kind);
+                self.write_info.for_statement(&statement.kind, self.body);
                 self.apply_conflicts();
             }
         }
@@ -469,80 +491,59 @@ fn internal_filter_liveness(&mut self) {
     fn apply_conflicts(&mut self) {
         let writes = &self.write_info.writes;
         for p in writes {
-            self.candidates.remove_candidates_if(
+            let other_skip = self.write_info.skip_pair.and_then(|(a, b)| {
+                if a == *p {
+                    Some(b)
+                } else if b == *p {
+                    Some(a)
+                } else {
+                    None
+                }
+            });
+            self.candidates.filter_candidates_by(
                 *p,
-                // It is possible that a local may be live for less than the
-                // duration of a statement This happens in the case of function
-                // calls or inline asm. Because of this, we also mark locals as
-                // conflicting when both of them are written to in the same
-                // statement.
-                |q| self.live.contains(q) || writes.contains(&q),
+                |q| {
+                    if Some(q) == other_skip {
+                        return CandidateFilter::Keep;
+                    }
+                    // It is possible that a local may be live for less than the
+                    // duration of a statement This happens in the case of function
+                    // calls or inline asm. Because of this, we also mark locals as
+                    // conflicting when both of them are written to in the same
+                    // statement.
+                    if self.live.contains(q) || writes.contains(&q) {
+                        CandidateFilter::Remove
+                    } else {
+                        CandidateFilter::Keep
+                    }
+                },
                 self.at,
             );
         }
     }
-
-    /// Gets the write info for the `statement`.
-    fn get_statement_write_info(&mut self, statement: &StatementKind<'tcx>) {
-        self.write_info.writes.clear();
-        match statement {
-            StatementKind::Assign(box (lhs, rhs)) => match rhs {
-                Rvalue::Use(op) => {
-                    if !lhs.is_indirect() {
-                        self.get_assign_use_write_info(*lhs, op);
-                        return;
-                    }
-                }
-                _ => (),
-            },
-            _ => (),
-        }
-
-        self.write_info.for_statement(statement);
-    }
-
-    fn get_assign_use_write_info(&mut self, lhs: Place<'tcx>, rhs: &Operand<'tcx>) {
-        // We register the writes for the operand unconditionally
-        self.write_info.add_operand(rhs);
-        // However, we cannot do the same thing for the `lhs` as that would always block the
-        // optimization. Instead, we consider removing candidates manually.
-        let Some(rhs) = rhs.place() else {
-            self.write_info.add_place(lhs);
-            return;
-        };
-        // Find out which candidate pair we should skip, if any
-        let Some((src, dest)) = places_to_candidate_pair(lhs, rhs, self.body) else {
-            self.write_info.add_place(lhs);
-            return;
-        };
-        self.candidates.remove_candidates_if(
-            lhs.local,
-            |other| {
-                // Check if this is the candidate pair that should not be removed
-                if (lhs.local == src && other == dest) || (lhs.local == dest && other == src) {
-                    return false;
-                }
-                // Otherwise, do the "standard" thing
-                self.live.contains(other)
-            },
-            self.at,
-        )
-    }
 }
 
 /// Describes where a statement/terminator writes to
 #[derive(Default, Debug)]
 struct WriteInfo {
     writes: Vec<Local>,
+    /// If this pair of locals is a candidate pair, completely skip processing it during this
+    /// statement. All other candidates are unaffected.
+    skip_pair: Option<(Local, Local)>,
 }
 
 impl WriteInfo {
-    fn for_statement<'tcx>(&mut self, statement: &StatementKind<'tcx>) {
+    fn for_statement<'tcx>(&mut self, statement: &StatementKind<'tcx>, body: &Body<'tcx>) {
+        self.reset();
         match statement {
             StatementKind::Assign(box (lhs, rhs)) => {
                 self.add_place(*lhs);
                 match rhs {
-                    Rvalue::Use(op) | Rvalue::Repeat(op, _) => {
+                    Rvalue::Use(op) => {
+                        self.add_operand(op);
+                        self.consider_skipping_for_assign_use(*lhs, op, body);
+                    }
+                    Rvalue::Repeat(op, _) => {
                         self.add_operand(op);
                     }
                     Rvalue::Cast(_, op, _)
@@ -586,8 +587,22 @@ fn for_statement<'tcx>(&mut self, statement: &StatementKind<'tcx>) {
         }
     }
 
+    fn consider_skipping_for_assign_use<'tcx>(
+        &mut self,
+        lhs: Place<'tcx>,
+        rhs: &Operand<'tcx>,
+        body: &Body<'tcx>,
+    ) {
+        let Some(rhs) = rhs.place() else {
+            return
+        };
+        if let Some(pair) = places_to_candidate_pair(lhs, rhs, body) {
+            self.skip_pair = Some(pair);
+        }
+    }
+
     fn for_terminator<'tcx>(&mut self, terminator: &TerminatorKind<'tcx>) {
-        self.writes.clear();
+        self.reset();
         match terminator {
             TerminatorKind::SwitchInt { discr: op, .. }
             | TerminatorKind::Assert { cond: op, .. } => {
@@ -657,15 +672,16 @@ fn add_operand<'tcx>(&mut self, op: &Operand<'tcx>) {
             Operand::Copy(_) | Operand::Constant(_) => (),
         }
     }
+
+    fn reset(&mut self) {
+        self.writes.clear();
+        self.skip_pair = None;
+    }
 }
 
 /////////////////////////////////////////////////////
 // Candidate accumulation
 
-fn is_constant<'tcx>(place: Place<'tcx>) -> bool {
-    place.projection.iter().all(|p| !matches!(p, ProjectionElem::Deref | ProjectionElem::Index(_)))
-}
-
 /// If the pair of places is being considered for merging, returns the candidate which would be
 /// merged in order to accomplish this.
 ///
@@ -741,10 +757,6 @@ fn visit_statement(&mut self, statement: &Statement<'tcx>, _: Location) {
             Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs)),
         )) = &statement.kind
         {
-            if !is_constant(*lhs) || !is_constant(*rhs) {
-                return;
-            }
-
             let Some((src, dest)) = places_to_candidate_pair(*lhs, *rhs, self.body) else {
                 return;
             };
index 32e738bbcea44b108c47e2dd948cef4f242dbbdb..8a7b027ddda7eb91316f612be8995748d6729fdf 100644 (file)
@@ -121,7 +121,6 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
 
             let TerminatorKind::SwitchInt {
                 discr: parent_op,
-                switch_ty: parent_ty,
                 targets: parent_targets
             } = &bbs[parent].terminator().kind else {
                 unreachable!()
@@ -132,6 +131,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
                 Operand::Copy(x) => Operand::Copy(*x),
                 Operand::Constant(x) => Operand::Constant(x.clone()),
             };
+            let parent_ty = parent_op.ty(body.local_decls(), tcx);
             let statements_before = bbs[parent].statements.len();
             let parent_end = Location { block: parent, statement_index: statements_before };
 
@@ -153,7 +153,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             // create temp to store inequality comparison between the two discriminants, `_t` in
             // example above
             let nequal = BinOp::Ne;
-            let comp_res_type = nequal.ty(tcx, *parent_ty, opt_data.child_ty);
+            let comp_res_type = nequal.ty(tcx, parent_ty, opt_data.child_ty);
             let comp_temp = patch.new_temp(comp_res_type, opt_data.child_source.span);
             patch.add_statement(parent_end, StatementKind::StorageLive(comp_temp));
 
@@ -181,7 +181,6 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
                 kind: TerminatorKind::SwitchInt {
                     // switch on the first discriminant, so we can mark the second one as dead
                     discr: parent_op,
-                    switch_ty: opt_data.child_ty,
                     targets: eq_targets,
                 },
             }));
@@ -193,12 +192,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             let false_case = eq_bb;
             patch.patch_terminator(
                 parent,
-                TerminatorKind::if_(
-                    tcx,
-                    Operand::Move(Place::from(comp_temp)),
-                    true_case,
-                    false_case,
-                ),
+                TerminatorKind::if_(Operand::Move(Place::from(comp_temp)), true_case, false_case),
             );
 
             // generate StorageDead for the second_discriminant_temp not in use anymore
@@ -319,11 +313,11 @@ fn evaluate_candidate<'tcx>(
     let bbs = &body.basic_blocks;
     let TerminatorKind::SwitchInt {
         targets,
-        switch_ty: parent_ty,
-        ..
+        discr: parent_discr,
     } = &bbs[parent].terminator().kind else {
         return None
     };
+    let parent_ty = parent_discr.ty(body.local_decls(), tcx);
     let parent_dest = {
         let poss = targets.otherwise();
         // If the fallthrough on the parent is trivially unreachable, we can let the
@@ -339,12 +333,12 @@ fn evaluate_candidate<'tcx>(
     let (_, child) = targets.iter().next()?;
     let child_terminator = &bbs[child].terminator();
     let TerminatorKind::SwitchInt {
-        switch_ty: child_ty,
         targets: child_targets,
-        ..
+        discr: child_discr,
     } = &child_terminator.kind else {
         return None
     };
+    let child_ty = child_discr.ty(body.local_decls(), tcx);
     if child_ty != parent_ty {
         return None;
     }
@@ -372,7 +366,7 @@ fn evaluate_candidate<'tcx>(
     Some(OptimizationData {
         destination,
         child_place: *child_place,
-        child_ty: *child_ty,
+        child_ty,
         child_source: child_terminator.source_info,
     })
 }
index 8922298ecafcb3fa35dbb9cee7a818aebb2e9240..c097af6161159a7fcec85b6b0bb69a3605fcb8e9 100644 (file)
@@ -490,7 +490,7 @@ fn locals_live_across_suspend_points<'tcx>(
 
     // Calculate when MIR locals have live storage. This gives us an upper bound of their
     // lifetimes.
-    let mut storage_live = MaybeStorageLive::new(always_live_locals.clone())
+    let mut storage_live = MaybeStorageLive::new(std::borrow::Cow::Borrowed(always_live_locals))
         .into_engine(tcx, body_ref)
         .iterate_to_fixpoint()
         .into_results_cursor(body_ref);
@@ -877,11 +877,7 @@ fn insert_switch<'tcx>(
     let (assign, discr) = transform.get_discr(body);
     let switch_targets =
         SwitchTargets::new(cases.iter().map(|(i, bb)| ((*i) as u128, *bb)), default_block);
-    let switch = TerminatorKind::SwitchInt {
-        discr: Operand::Move(discr),
-        switch_ty: transform.discr_ty,
-        targets: switch_targets,
-    };
+    let switch = TerminatorKind::SwitchInt { discr: Operand::Move(discr), targets: switch_targets };
 
     let source_info = SourceInfo::outermost(body.span);
     body.basic_blocks_mut().raw.insert(
@@ -985,16 +981,6 @@ fn create_generator_drop_shim<'tcx>(
         tcx.mk_ptr(ty::TypeAndMut { ty: gen_ty, mutbl: hir::Mutability::Mut }),
         source_info,
     );
-    if tcx.sess.opts.unstable_opts.mir_emit_retag {
-        // Alias tracking must know we changed the type
-        body.basic_blocks_mut()[START_BLOCK].statements.insert(
-            0,
-            Statement {
-                source_info,
-                kind: StatementKind::Retag(RetagKind::Raw, Box::new(Place::from(SELF_ARG))),
-            },
-        )
-    }
 
     // Make sure we remove dead blocks to remove
     // unrelated code from the resume part of the function
index 220cf7df9c6c7e99cd35d103fa959988f9b1db34..9d560f5c837e2d75e75f6899d65199bdef8fe710 100644 (file)
@@ -849,7 +849,7 @@ fn visit_projection_elem(
             };
 
             let kind = match parent_ty.ty.kind() {
-                &ty::Opaque(def_id, substs) => {
+                &ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
                     self.tcx.bound_type_of(def_id).subst(self.tcx, substs).kind()
                 }
                 kind => kind,
index a0ba69c89b048491f9840a9cd6806f91bf2fd46f..ce05db5b762ac9a48d3b2d15f6b3be72a3a5d526 100644 (file)
@@ -55,10 +55,9 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
                 continue;
             }
 
-            let (discr, val, switch_ty, first, second) = match bbs[bb_idx].terminator().kind {
+            let (discr, val, first, second) = match bbs[bb_idx].terminator().kind {
                 TerminatorKind::SwitchInt {
                     discr: ref discr @ (Operand::Copy(_) | Operand::Move(_)),
-                    switch_ty,
                     ref targets,
                     ..
                 } if targets.iter().len() == 1 => {
@@ -66,7 +65,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
                     if target == targets.otherwise() {
                         continue;
                     }
-                    (discr, value, switch_ty, target, targets.otherwise())
+                    (discr, value, target, targets.otherwise())
                 }
                 // Only optimize switch int statements
                 _ => continue,
@@ -105,10 +104,11 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             }
             // Take ownership of items now that we know we can optimize.
             let discr = discr.clone();
+            let discr_ty = discr.ty(&body.local_decls, tcx);
 
             // Introduce a temporary for the discriminant value.
             let source_info = bbs[bb_idx].terminator().source_info;
-            let discr_local = body.local_decls.push(LocalDecl::new(switch_ty, source_info.span));
+            let discr_local = body.local_decls.push(LocalDecl::new(discr_ty, source_info.span));
 
             // We already checked that first and second are different blocks,
             // and bb_idx has a different terminator from both of them.
@@ -130,10 +130,10 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
                             (*f).clone()
                         } else {
                             // Different value between blocks. Make value conditional on switch condition.
-                            let size = tcx.layout_of(param_env.and(switch_ty)).unwrap().size;
+                            let size = tcx.layout_of(param_env.and(discr_ty)).unwrap().size;
                             let const_cmp = Operand::const_from_scalar(
                                 tcx,
-                                switch_ty,
+                                discr_ty,
                                 rustc_const_eval::interpret::Scalar::from_uint(val, size),
                                 rustc_span::DUMMY_SP,
                             );
index 569e783fee847b17a561293e001783627773ab9e..6cabef92d8c2190e7f31514eb319eee727dcc9c2 100644 (file)
@@ -52,7 +52,11 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
 fn maybe_zst(ty: Ty<'_>) -> bool {
     match ty.kind() {
         // maybe ZST (could be more precise)
-        ty::Adt(..) | ty::Array(..) | ty::Closure(..) | ty::Tuple(..) | ty::Opaque(..) => true,
+        ty::Adt(..)
+        | ty::Array(..)
+        | ty::Closure(..)
+        | ty::Tuple(..)
+        | ty::Alias(ty::Opaque, ..) => true,
         // definitely ZST
         ty::FnDef(..) | ty::Never => true,
         // unreachable or can't be ZST
index a115bb2831a4b2c1c1ec7dc04d4015495200a30e..f8b55c862875e06796968c7cc1bbc0d9de190570 100644 (file)
@@ -177,16 +177,6 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
     if ty.is_some() {
         // The first argument (index 0), but add 1 for the return value.
         let dropee_ptr = Place::from(Local::new(1 + 0));
-        if tcx.sess.opts.unstable_opts.mir_emit_retag {
-            // Function arguments should be retagged, and we make this one raw.
-            body.basic_blocks_mut()[START_BLOCK].statements.insert(
-                0,
-                Statement {
-                    source_info,
-                    kind: StatementKind::Retag(RetagKind::Raw, Box::new(dropee_ptr)),
-                },
-            );
-        }
         let patch = {
             let param_env = tcx.param_env_reveal_all_normalized(def_id);
             let mut elaborator =
@@ -346,8 +336,7 @@ fn new(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Self {
         // we must subst the self_ty because it's
         // otherwise going to be TySelf and we can't index
         // or access fields of a Place of type TySelf.
-        let substs = tcx.mk_substs_trait(self_ty, []);
-        let sig = tcx.bound_fn_sig(def_id).subst(tcx, substs);
+        let sig = tcx.bound_fn_sig(def_id).subst(tcx, &[self_ty.into()]);
         let sig = tcx.erase_late_bound_regions(sig);
         let span = tcx.def_span(def_id);
 
@@ -427,10 +416,8 @@ fn make_clone_call(
     ) {
         let tcx = self.tcx;
 
-        let substs = tcx.mk_substs_trait(ty, []);
-
         // `func == Clone::clone(&ty) -> ty`
-        let func_ty = tcx.mk_fn_def(self.def_id, substs);
+        let func_ty = tcx.mk_fn_def(self.def_id, [ty]);
         let func = Operand::Constant(Box::new(Constant {
             span: self.span,
             user_ty: None,
@@ -558,7 +545,6 @@ fn generator_shim(
                 statements.push(statement);
                 *kind = TerminatorKind::SwitchInt {
                     discr: Operand::Move(temp),
-                    switch_ty: discr_ty,
                     targets: SwitchTargets::new(cases.into_iter(), unreachable),
                 };
             }
@@ -586,9 +572,8 @@ fn build_call_shim<'tcx>(
 
         // Create substitutions for the `Self` and `Args` generic parameters of the shim body.
         let arg_tup = tcx.mk_tup(untuple_args.iter());
-        let sig_substs = tcx.mk_substs_trait(ty, [ty::subst::GenericArg::from(arg_tup)]);
 
-        (Some(sig_substs), Some(untuple_args))
+        (Some([ty.into(), arg_tup.into()]), Some(untuple_args))
     } else {
         (None, None)
     };
@@ -599,7 +584,7 @@ fn build_call_shim<'tcx>(
 
     assert_eq!(sig_substs.is_some(), !instance.has_polymorphic_mir_body());
     let mut sig =
-        if let Some(sig_substs) = sig_substs { sig.subst(tcx, sig_substs) } else { sig.0 };
+        if let Some(sig_substs) = sig_substs { sig.subst(tcx, &sig_substs) } else { sig.0 };
 
     if let CallKind::Indirect(fnty) = call_kind {
         // `sig` determines our local decls, and thus the callee type in the `Call` terminator. This
index 475e2ec9a1dea713881123d96bc84a941bb95272..8212a7b523bbc98d5d1e4d8d76e57864432d61df 100644 (file)
@@ -35,7 +35,6 @@
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 use smallvec::SmallVec;
-use std::convert::TryInto;
 
 pub struct SimplifyCfg {
     label: String,
index 405ebce4d2227f7bdfac152ac51725783ac59886..8164b3052786aa1ea07d979f6607ca8988f6b9ef 100644 (file)
@@ -24,12 +24,9 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             let terminator = block.terminator_mut();
             terminator.kind = match terminator.kind {
                 TerminatorKind::SwitchInt {
-                    discr: Operand::Constant(ref c),
-                    switch_ty,
-                    ref targets,
-                    ..
+                    discr: Operand::Constant(ref c), ref targets, ..
                 } => {
-                    let constant = c.literal.try_eval_bits(tcx, param_env, switch_ty);
+                    let constant = c.literal.try_eval_bits(tcx, param_env, c.ty());
                     if let Some(constant) = constant {
                         let target = targets.target_for_value(constant);
                         TerminatorKind::Goto { target }
index 321d8c63b6e028c3d7c9b68d5dd0991c1db4879d..dcad1518eb63eb0d853037b109b9b7d800b727c8 100644 (file)
@@ -127,11 +127,8 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             let targets = SwitchTargets::new(iter::once((new_value, bb_cond)), bb_otherwise);
 
             let terminator = bb.terminator_mut();
-            terminator.kind = TerminatorKind::SwitchInt {
-                discr: Operand::Move(opt.to_switch_on),
-                switch_ty: opt.branch_value_ty,
-                targets,
-            };
+            terminator.kind =
+                TerminatorKind::SwitchInt { discr: Operand::Move(opt.to_switch_on), targets };
         }
 
         for (idx, bb_idx) in storage_deads_to_remove {
index 95fda2eafe8a1799df333461355abe2eb2fc770f..06deca2fffb4889cc447878136b545a0243de852 100644 (file)
@@ -76,7 +76,7 @@ fn remove_successors<'tcx, F>(
     let terminator = match terminator_kind {
         // This will unconditionally run into an unreachable and is therefore unreachable as well.
         TerminatorKind::Goto { target } if is_unreachable(*target) => TerminatorKind::Unreachable,
-        TerminatorKind::SwitchInt { targets, discr, switch_ty } => {
+        TerminatorKind::SwitchInt { targets, discr } => {
             let otherwise = targets.otherwise();
 
             // If all targets are unreachable, we can be unreachable as well.
@@ -110,11 +110,7 @@ fn remove_successors<'tcx, F>(
                     return None;
                 }
 
-                TerminatorKind::SwitchInt {
-                    discr: discr.clone(),
-                    switch_ty: *switch_ty,
-                    targets: new_targets,
-                }
+                TerminatorKind::SwitchInt { discr: discr.clone(), targets: new_targets }
             } else {
                 // If the otherwise branch is reachable, we don't want to delete any unreachable branches.
                 return None;
index cf7226a129ce7fb42aee119c6efccbe7104325eb..10ea4d29cfe4e3317df1500b046cb1ec2d32c67c 100644 (file)
@@ -931,10 +931,13 @@ fn visit_fn_use<'tcx>(
 ) {
     if let ty::FnDef(def_id, substs) = *ty.kind() {
         let instance = if is_direct_call {
-            ty::Instance::resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap().unwrap()
+            ty::Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs)
         } else {
-            ty::Instance::resolve_for_fn_ptr(tcx, ty::ParamEnv::reveal_all(), def_id, substs)
-                .unwrap()
+            match ty::Instance::resolve_for_fn_ptr(tcx, ty::ParamEnv::reveal_all(), def_id, substs)
+            {
+                Some(instance) => instance,
+                _ => bug!("failed to resolve instance for {ty}"),
+            }
         };
         visit_instance_use(tcx, instance, is_direct_call, source, output);
     }
@@ -1369,9 +1372,8 @@ fn create_mono_items_for_default_impls<'tcx>(
                                 trait_ref.substs[param.index as usize]
                             }
                         });
-                    let instance = ty::Instance::resolve(tcx, param_env, method.def_id, substs)
-                        .unwrap()
-                        .unwrap();
+                    let instance =
+                        ty::Instance::expect_resolve(tcx, param_env, method.def_id, substs);
 
                     let mono_item = create_fn_mono_item(tcx, instance, DUMMY_SP);
                     if mono_item.node.is_instantiable(tcx) && should_codegen_locally(tcx, &instance)
index f1ca72de8dbe47d934cc8b8c197c5ed4b4d11ff7..f15cf54718e2b7221bbb70fb9261f36af32fd525 100644 (file)
@@ -77,3 +77,9 @@ pub struct SymbolAlreadyDefined {
     pub span: Option<Span>,
     pub symbol: String,
 }
+
+#[derive(Diagnostic)]
+#[diag(monomorphize_couldnt_dump_mono_stats)]
+pub struct CouldntDumpMonoStats {
+    pub error: String,
+}
index 932edc6675f5900cb6dd04d9678d7847345f0f9b..38e1d98e44e13f0d72af80666004b666fb21835c 100644 (file)
 mod default;
 mod merging;
 
+use std::cmp;
+use std::fs::{self, File};
+use std::io::{BufWriter, Write};
+use std::path::{Path, PathBuf};
+
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync;
 use rustc_hir::def_id::DefIdSet;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::TyCtxt;
+use rustc_session::config::SwitchWithOptPath;
 use rustc_span::symbol::Symbol;
 
 use crate::collector::InliningMap;
 use crate::collector::{self, MonoItemCollectionMode};
-use crate::errors::{SymbolAlreadyDefined, UnknownPartitionStrategy};
+use crate::errors::{CouldntDumpMonoStats, SymbolAlreadyDefined, UnknownPartitionStrategy};
 
 pub struct PartitioningCx<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
@@ -411,6 +417,15 @@ fn collect_and_partition_mono_items<'tcx>(
         })
         .collect();
 
+    // Output monomorphization stats per def_id
+    if let SwitchWithOptPath::Enabled(ref path) = tcx.sess.opts.unstable_opts.dump_mono_stats {
+        if let Err(err) =
+            dump_mono_items_stats(tcx, &codegen_units, path, tcx.sess.opts.crate_name.as_deref())
+        {
+            tcx.sess.emit_fatal(CouldntDumpMonoStats { error: err.to_string() });
+        }
+    }
+
     if tcx.sess.opts.unstable_opts.print_mono_items.is_some() {
         let mut item_to_cgus: FxHashMap<_, Vec<_>> = Default::default();
 
@@ -465,6 +480,67 @@ fn collect_and_partition_mono_items<'tcx>(
     (tcx.arena.alloc(mono_items), codegen_units)
 }
 
+/// Outputs stats about instantation counts and estimated size, per `MonoItem`'s
+/// def, to a file in the given output directory.
+fn dump_mono_items_stats<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    codegen_units: &[CodegenUnit<'tcx>],
+    output_directory: &Option<PathBuf>,
+    crate_name: Option<&str>,
+) -> Result<(), Box<dyn std::error::Error>> {
+    let output_directory = if let Some(ref directory) = output_directory {
+        fs::create_dir_all(directory)?;
+        directory
+    } else {
+        Path::new(".")
+    };
+
+    let filename = format!("{}.mono_items.md", crate_name.unwrap_or("unknown-crate"));
+    let output_path = output_directory.join(&filename);
+    let file = File::create(output_path)?;
+    let mut file = BufWriter::new(file);
+
+    // Gather instantiated mono items grouped by def_id
+    let mut items_per_def_id: FxHashMap<_, Vec<_>> = Default::default();
+    for cgu in codegen_units {
+        for (&mono_item, _) in cgu.items() {
+            // Avoid variable-sized compiler-generated shims
+            if mono_item.is_user_defined() {
+                items_per_def_id.entry(mono_item.def_id()).or_default().push(mono_item);
+            }
+        }
+    }
+
+    // Output stats sorted by total instantiated size, from heaviest to lightest
+    let mut stats: Vec<_> = items_per_def_id
+        .into_iter()
+        .map(|(def_id, items)| {
+            let instantiation_count = items.len();
+            let size_estimate = items[0].size_estimate(tcx);
+            let total_estimate = instantiation_count * size_estimate;
+            (def_id, instantiation_count, size_estimate, total_estimate)
+        })
+        .collect();
+    stats.sort_unstable_by_key(|(_, _, _, total_estimate)| cmp::Reverse(*total_estimate));
+
+    if !stats.is_empty() {
+        writeln!(
+            file,
+            "| Item | Instantiation count | Estimated Cost Per Instantiation | Total Estimated Cost |"
+        )?;
+        writeln!(file, "| --- | ---: | ---: | ---: |")?;
+        for (def_id, instantiation_count, size_estimate, total_estimate) in stats {
+            let item = with_no_trimmed_paths!(tcx.def_path_str(def_id));
+            writeln!(
+                file,
+                "| {item} | {instantiation_count} | {size_estimate} | {total_estimate} |"
+            )?;
+        }
+    }
+
+    Ok(())
+}
+
 fn codegened_and_inlined_items<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> &'tcx DefIdSet {
     let (items, cgus) = tcx.collect_and_partition_mono_items(());
     let mut visited = DefIdSet::default();
index 650076c2213a35f1231e6c1bbb72b01f5ed902df..703ed09a254a96899d2019a1d29afba864a4bb97 100644 (file)
@@ -20,7 +20,6 @@
     Const, Ty, TyCtxt,
 };
 use rustc_span::symbol::sym;
-use std::convert::TryInto;
 use std::ops::ControlFlow;
 
 use crate::errors::UnusedGenericParams;
index 9875cde4a05ebe9354ef1ed5b83b6ba59e29aa5d..18a0bee9c2e5ee83ba98e4543fdc54b2befb3d8d 100644 (file)
@@ -1221,3 +1221,11 @@ pub(crate) struct UnexpectedIfWithIf(
     #[suggestion(applicability = "machine-applicable", code = " ", style = "verbose")]
     pub Span,
 );
+
+#[derive(Diagnostic)]
+#[diag(parse_maybe_fn_typo_with_impl)]
+pub(crate) struct FnTypoWithImpl {
+    #[primary_span]
+    #[suggestion(applicability = "maybe-incorrect", code = "impl", style = "verbose")]
+    pub fn_span: Span,
+}
index c7d239b647f35b2bc273fdc0185a5cf224f13ac9..686454a8f18117f1323fa6dcea384719770e604f 100644 (file)
@@ -6,7 +6,6 @@
 use rustc_ast::token::{self, Delimiter, Nonterminal};
 use rustc_errors::{error_code, fluent, Diagnostic, IntoDiagnostic, PResult};
 use rustc_span::{sym, BytePos, Span};
-use std::convert::TryInto;
 
 // Public for rustfmt usage
 #[derive(Debug)]
index a084a7010885927344a3e24e834cd27e03e00fcb..b97f22417cb7bdcc82482abf2a6314d4ff664c03 100644 (file)
@@ -8,7 +8,6 @@
 use rustc_session::parse::ParseSess;
 use rustc_span::{sym, Span, DUMMY_SP};
 
-use std::convert::TryInto;
 use std::ops::Range;
 
 /// A wrapper type to ensure that the parser handles outer attributes correctly.
index c316a4dd6b41ad346527e1ff0b31512d06434a0f..0191ab730c812e89e55099c5896dc4be68284e38 100644 (file)
@@ -159,8 +159,6 @@ enum IsStandalone {
     Standalone,
     /// It's a subexpression, i.e., *not* standalone.
     Subexpr,
-    /// It's maybe standalone; we're not sure.
-    Maybe,
 }
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
@@ -213,14 +211,8 @@ fn emit(self, err: &mut Diagnostic) {
         err.multipart_suggestion(&self.msg, self.patches, self.applicability);
     }
 
-    /// Overrides individual messages and applicabilities.
-    fn emit_many(
-        err: &mut Diagnostic,
-        msg: &str,
-        applicability: Applicability,
-        suggestions: impl Iterator<Item = Self>,
-    ) {
-        err.multipart_suggestions(msg, suggestions.map(|s| s.patches), applicability);
+    fn emit_verbose(self, err: &mut Diagnostic) {
+        err.multipart_suggestion_verbose(&self.msg, self.patches, self.applicability);
     }
 }
 
@@ -1267,12 +1259,10 @@ pub(super) fn recover_from_prefix_increment(
         &mut self,
         operand_expr: P<Expr>,
         op_span: Span,
-        prev_is_semi: bool,
+        start_stmt: bool,
     ) -> PResult<'a, P<Expr>> {
-        let standalone =
-            if prev_is_semi { IsStandalone::Standalone } else { IsStandalone::Subexpr };
+        let standalone = if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr };
         let kind = IncDecRecovery { standalone, op: IncOrDec::Inc, fixity: UnaryFixity::Pre };
-
         self.recover_from_inc_dec(operand_expr, kind, op_span)
     }
 
@@ -1280,13 +1270,13 @@ pub(super) fn recover_from_postfix_increment(
         &mut self,
         operand_expr: P<Expr>,
         op_span: Span,
+        start_stmt: bool,
     ) -> PResult<'a, P<Expr>> {
         let kind = IncDecRecovery {
-            standalone: IsStandalone::Maybe,
+            standalone: if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr },
             op: IncOrDec::Inc,
             fixity: UnaryFixity::Post,
         };
-
         self.recover_from_inc_dec(operand_expr, kind, op_span)
     }
 
@@ -1315,34 +1305,25 @@ fn recover_from_inc_dec(
         };
 
         match kind.standalone {
-            IsStandalone::Standalone => self.inc_dec_standalone_suggest(kind, spans).emit(&mut err),
+            IsStandalone::Standalone => {
+                self.inc_dec_standalone_suggest(kind, spans).emit_verbose(&mut err)
+            }
             IsStandalone::Subexpr => {
                 let Ok(base_src) = self.span_to_snippet(base.span)
-                    else { return help_base_case(err, base) };
+                else { return help_base_case(err, base) };
                 match kind.fixity {
                     UnaryFixity::Pre => {
                         self.prefix_inc_dec_suggest(base_src, kind, spans).emit(&mut err)
                     }
                     UnaryFixity::Post => {
-                        self.postfix_inc_dec_suggest(base_src, kind, spans).emit(&mut err)
+                        // won't suggest since we can not handle the precedences
+                        // for example: `a + b++` has been parsed (a + b)++ and we can not suggest here
+                        if !matches!(base.kind, ExprKind::Binary(_, _, _)) {
+                            self.postfix_inc_dec_suggest(base_src, kind, spans).emit(&mut err)
+                        }
                     }
                 }
             }
-            IsStandalone::Maybe => {
-                let Ok(base_src) = self.span_to_snippet(base.span)
-                    else { return help_base_case(err, base) };
-                let sugg1 = match kind.fixity {
-                    UnaryFixity::Pre => self.prefix_inc_dec_suggest(base_src, kind, spans),
-                    UnaryFixity::Post => self.postfix_inc_dec_suggest(base_src, kind, spans),
-                };
-                let sugg2 = self.inc_dec_standalone_suggest(kind, spans);
-                MultiSugg::emit_many(
-                    &mut err,
-                    "use `+= 1` instead",
-                    Applicability::Unspecified,
-                    [sugg1, sugg2].into_iter(),
-                )
-            }
         }
         Err(err)
     }
@@ -1392,7 +1373,6 @@ fn inc_dec_standalone_suggest(
         }
 
         patches.push((post_span, format!(" {}= 1", kind.op.chr())));
-
         MultiSugg {
             msg: format!("use `{}= 1` instead", kind.op.chr()),
             patches,
index f6a6ed379a2b595de95d36534b1e234187e6a40d..c0ed450b98508e07beed81f05c23030695d232c5 100644 (file)
@@ -83,7 +83,7 @@ macro_rules! maybe_whole_expr {
 pub(super) enum LhsExpr {
     NotYetParsed,
     AttributesParsed(AttrWrapper),
-    AlreadyParsed(P<Expr>),
+    AlreadyParsed(P<Expr>, bool), // (expr, starts_statement)
 }
 
 impl From<Option<AttrWrapper>> for LhsExpr {
@@ -101,7 +101,7 @@ impl From<P<Expr>> for LhsExpr {
     ///
     /// This conversion does not allocate.
     fn from(expr: P<Expr>) -> Self {
-        LhsExpr::AlreadyParsed(expr)
+        LhsExpr::AlreadyParsed(expr, false)
     }
 }
 
@@ -173,7 +173,9 @@ pub(super) fn parse_assoc_expr_with(
         min_prec: usize,
         lhs: LhsExpr,
     ) -> PResult<'a, P<Expr>> {
-        let mut lhs = if let LhsExpr::AlreadyParsed(expr) = lhs {
+        let mut starts_stmt = false;
+        let mut lhs = if let LhsExpr::AlreadyParsed(expr, starts_statement) = lhs {
+            starts_stmt = starts_statement;
             expr
         } else {
             let attrs = match lhs {
@@ -292,7 +294,7 @@ pub(super) fn parse_assoc_expr_with(
                 let op_span = self.prev_token.span.to(self.token.span);
                 // Eat the second `+`
                 self.bump();
-                lhs = self.recover_from_postfix_increment(lhs, op_span)?;
+                lhs = self.recover_from_postfix_increment(lhs, op_span, starts_stmt)?;
                 continue;
             }
 
@@ -590,14 +592,15 @@ macro_rules! make_it {
             token::BinOp(token::Plus)
                 if this.look_ahead(1, |t| *t == token::BinOp(token::Plus)) =>
             {
-                let prev_is_semi = this.prev_token == token::Semi;
+                let starts_stmt = this.prev_token == token::Semi
+                    || this.prev_token == token::CloseDelim(Delimiter::Brace);
                 let pre_span = this.token.span.to(this.look_ahead(1, |t| t.span));
                 // Eat both `+`s.
                 this.bump();
                 this.bump();
 
                 let operand_expr = this.parse_dot_or_call_expr(Default::default())?;
-                this.recover_from_prefix_increment(operand_expr, pre_span, prev_is_semi)
+                this.recover_from_prefix_increment(operand_expr, pre_span, starts_stmt)
             }
             token::Ident(..) if this.token.is_keyword(kw::Box) => {
                 make_it!(this, attrs, |this, _| this.parse_box_expr(lo))
@@ -1534,15 +1537,16 @@ fn parse_labeled_expr(
             && (matches!(self.token.kind, token::CloseDelim(_) | token::Comma)
                 || self.token.is_op())
         {
-            let lit = self.recover_unclosed_char(label_.ident, |self_| {
-                self_.sess.create_err(UnexpectedTokenAfterLabel {
-                    span: self_.token.span,
-                    remove_label: None,
-                    enclose_in_block: None,
-                })
-            });
+            let (lit, _) =
+                self.recover_unclosed_char(label_.ident, Parser::mk_token_lit_char, |self_| {
+                    self_.sess.create_err(UnexpectedTokenAfterLabel {
+                        span: self_.token.span,
+                        remove_label: None,
+                        enclose_in_block: None,
+                    })
+                });
             consume_colon = false;
-            Ok(self.mk_expr(lo, ExprKind::Lit(lit.token_lit)))
+            Ok(self.mk_expr(lo, ExprKind::Lit(lit)))
         } else if !ate_colon
             && (self.check_noexpect(&TokenKind::Comma) || self.check_noexpect(&TokenKind::Gt))
         {
@@ -1617,12 +1621,13 @@ fn visit_expr_post(&mut self, ex: &'ast Expr) {
         Ok(expr)
     }
 
-    /// Emit an error when a char is parsed as a lifetime because of a missing quote
-    pub(super) fn recover_unclosed_char(
+    /// Emit an error when a char is parsed as a lifetime because of a missing quote.
+    pub(super) fn recover_unclosed_char<L>(
         &self,
         lifetime: Ident,
+        mk_lit_char: impl FnOnce(Symbol, Span) -> L,
         err: impl FnOnce(&Self) -> DiagnosticBuilder<'a, ErrorGuaranteed>,
-    ) -> ast::MetaItemLit {
+    ) -> L {
         if let Some(mut diag) =
             self.sess.span_diagnostic.steal_diagnostic(lifetime.span, StashKey::LifetimeIsChar)
         {
@@ -1644,11 +1649,7 @@ pub(super) fn recover_unclosed_char(
                 .emit();
         }
         let name = lifetime.without_first_quote().name;
-        ast::MetaItemLit {
-            token_lit: token::Lit::new(token::LitKind::Char, name, None),
-            kind: ast::LitKind::Char(name.as_str().chars().next().unwrap_or('_')),
-            span: lifetime.span,
-        }
+        mk_lit_char(name, lifetime.span)
     }
 
     /// Recover on the syntax `do catch { ... }` suggesting `try { ... }` instead.
@@ -1764,8 +1765,8 @@ pub fn parse_str_lit(&mut self) -> Result<ast::StrLit, Option<MetaItemLit>> {
             Some(lit) => match lit.kind {
                 ast::LitKind::Str(symbol_unescaped, style) => Ok(ast::StrLit {
                     style,
-                    symbol: lit.token_lit.symbol,
-                    suffix: lit.token_lit.suffix,
+                    symbol: lit.symbol,
+                    suffix: lit.suffix,
                     span: lit.span,
                     symbol_unescaped,
                 }),
@@ -1775,7 +1776,23 @@ pub fn parse_str_lit(&mut self) -> Result<ast::StrLit, Option<MetaItemLit>> {
         }
     }
 
-    fn handle_missing_lit(&mut self) -> PResult<'a, MetaItemLit> {
+    pub(crate) fn mk_token_lit_char(name: Symbol, span: Span) -> (token::Lit, Span) {
+        (token::Lit { symbol: name, suffix: None, kind: token::Char }, span)
+    }
+
+    fn mk_meta_item_lit_char(name: Symbol, span: Span) -> MetaItemLit {
+        ast::MetaItemLit {
+            symbol: name,
+            suffix: None,
+            kind: ast::LitKind::Char(name.as_str().chars().next().unwrap_or('_')),
+            span,
+        }
+    }
+
+    fn handle_missing_lit<L>(
+        &mut self,
+        mk_lit_char: impl FnOnce(Symbol, Span) -> L,
+    ) -> PResult<'a, L> {
         if let token::Interpolated(inner) = &self.token.kind {
             let expr = match inner.as_ref() {
                 token::NtExpr(expr) => Some(expr),
@@ -1799,7 +1816,7 @@ fn handle_missing_lit(&mut self) -> PResult<'a, MetaItemLit> {
         // On an error path, eagerly consider a lifetime to be an unclosed character lit
         if self.token.is_lifetime() {
             let lt = self.expect_lifetime();
-            Ok(self.recover_unclosed_char(lt.ident, err))
+            Ok(self.recover_unclosed_char(lt.ident, mk_lit_char, err))
         } else {
             Err(err(self))
         }
@@ -1808,11 +1825,13 @@ fn handle_missing_lit(&mut self) -> PResult<'a, MetaItemLit> {
     pub(super) fn parse_token_lit(&mut self) -> PResult<'a, (token::Lit, Span)> {
         self.parse_opt_token_lit()
             .ok_or(())
-            .or_else(|()| self.handle_missing_lit().map(|lit| (lit.token_lit, lit.span)))
+            .or_else(|()| self.handle_missing_lit(Parser::mk_token_lit_char))
     }
 
     pub(super) fn parse_meta_item_lit(&mut self) -> PResult<'a, MetaItemLit> {
-        self.parse_opt_meta_item_lit().ok_or(()).or_else(|()| self.handle_missing_lit())
+        self.parse_opt_meta_item_lit()
+            .ok_or(())
+            .or_else(|()| self.handle_missing_lit(Parser::mk_meta_item_lit_char))
     }
 
     fn recover_after_dot(&mut self) -> Option<Token> {
index 03f25392a7c1f90094ccf4fb2ce067a598f8210b..7c2d01509de417b100c281abf1a6863106d05ee0 100644 (file)
@@ -3,6 +3,7 @@
 use super::diagnostics::{dummy_arg, ConsumeClosingDelim};
 use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
 use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, TrailingToken};
+use crate::errors::FnTypoWithImpl;
 use rustc_ast::ast::*;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter, TokenKind};
@@ -21,7 +22,6 @@
 use rustc_span::source_map::{self, Span};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::DUMMY_SP;
-use std::convert::TryFrom;
 use std::mem;
 use thin_vec::ThinVec;
 use tracing::debug;
@@ -707,9 +707,9 @@ fn parse_item_list<T>(
             }
             match parse_item(self) {
                 Ok(None) => {
-                    let is_unnecessary_semicolon = !items.is_empty()
+                    let mut is_unnecessary_semicolon = !items.is_empty()
                         // When the close delim is `)` in a case like the following, `token.kind` is expected to be `token::CloseDelim(Delimiter::Parenthesis)`,
-                        // but the actual `token.kind` is `token::CloseDelim(Delimiter::Bracket)`.
+                        // but the actual `token.kind` is `token::CloseDelim(Delimiter::Brace)`.
                         // This is because the `token.kind` of the close delim is treated as the same as
                         // that of the open delim in `TokenTreesReader::parse_token_tree`, even if the delimiters of them are different.
                         // Therefore, `token.kind` should not be compared here.
@@ -728,7 +728,13 @@ fn parse_item_list<T>(
                             .span_to_snippet(self.prev_token.span)
                             .map_or(false, |snippet| snippet == "}")
                         && self.token.kind == token::Semi;
-                    let semicolon_span = self.token.span;
+                    let mut semicolon_span = self.token.span;
+                    if !is_unnecessary_semicolon {
+                        // #105369, Detect spurious `;` before assoc fn body
+                        is_unnecessary_semicolon = self.token == token::OpenDelim(Delimiter::Brace)
+                            && self.prev_token.kind == token::Semi;
+                        semicolon_span = self.prev_token.span;
+                    }
                     // We have to bail or we'll potentially never make progress.
                     let non_item_span = self.token.span;
                     let is_let = self.token.is_keyword(kw::Let);
@@ -2126,11 +2132,26 @@ fn parse_fn(
         vis: &Visibility,
         case: Case,
     ) -> PResult<'a, (Ident, FnSig, Generics, Option<P<Block>>)> {
+        let fn_span = self.token.span;
         let header = self.parse_fn_front_matter(vis, case)?; // `const ... fn`
         let ident = self.parse_ident()?; // `foo`
         let mut generics = self.parse_generics()?; // `<'a, T, ...>`
-        let decl =
-            self.parse_fn_decl(fn_parse_mode.req_name, AllowPlus::Yes, RecoverReturnSign::Yes)?; // `(p: u8, ...)`
+        let decl = match self.parse_fn_decl(
+            fn_parse_mode.req_name,
+            AllowPlus::Yes,
+            RecoverReturnSign::Yes,
+        ) {
+            Ok(decl) => decl,
+            Err(old_err) => {
+                // If we see `for Ty ...` then user probably meant `impl` item.
+                if self.token.is_keyword(kw::For) {
+                    old_err.cancel();
+                    return Err(self.sess.create_err(FnTypoWithImpl { fn_span }));
+                } else {
+                    return Err(old_err);
+                }
+            }
+        };
         generics.where_clause = self.parse_where_clause()?; // `where T: Ord`
 
         let mut sig_hi = self.prev_token.span;
index bebb012660a16ae140a780bb5da5049761bc0faa..40b88788caa6743c66a5e7f9c0e6dba47fd6cb9a 100644 (file)
@@ -25,7 +25,7 @@
 use rustc_ast::util::case::Case;
 use rustc_ast::AttrId;
 use rustc_ast::DUMMY_NODE_ID;
-use rustc_ast::{self as ast, AnonConst, AttrStyle, AttrVec, Const, DelimArgs, Extern};
+use rustc_ast::{self as ast, AnonConst, AttrStyle, Const, DelimArgs, Extern};
 use rustc_ast::{Async, AttrArgs, AttrArgsEq, Expr, ExprKind, MacDelimiter, Mutability, StrLit};
 use rustc_ast::{HasAttrs, HasTokens, Unsafe, Visibility, VisibilityKind};
 use rustc_ast_pretty::pprust;
@@ -1217,11 +1217,7 @@ fn parse_const_block(&mut self, span: Span, pat: bool) -> PResult<'a, P<Expr>> {
             value: self.mk_expr(blk.span, ExprKind::Block(blk, None)),
         };
         let blk_span = anon_const.value.span;
-        Ok(self.mk_expr_with_attrs(
-            span.to(blk_span),
-            ExprKind::ConstBlock(anon_const),
-            AttrVec::from(attrs),
-        ))
+        Ok(self.mk_expr_with_attrs(span.to(blk_span), ExprKind::ConstBlock(anon_const), attrs))
     }
 
     /// Parses mutability (`mut` or nothing).
index cbeec951e2dfe8dd0c037ae7f44a966ce11905d7..a1981e11477753b4506a5f2770e71570e1eb2c57 100644 (file)
@@ -411,16 +411,20 @@ fn parse_pat_with_range_pat(
         {
             // Recover a `'a` as a `'a'` literal
             let lt = self.expect_lifetime();
-            let lit = self.recover_unclosed_char(lt.ident, |self_| {
-                let expected = expected.unwrap_or("pattern");
-                let msg =
-                    format!("expected {}, found {}", expected, super::token_descr(&self_.token));
+            let (lit, _) =
+                self.recover_unclosed_char(lt.ident, Parser::mk_token_lit_char, |self_| {
+                    let expected = expected.unwrap_or("pattern");
+                    let msg = format!(
+                        "expected {}, found {}",
+                        expected,
+                        super::token_descr(&self_.token)
+                    );
 
-                let mut err = self_.struct_span_err(self_.token.span, &msg);
-                err.span_label(self_.token.span, format!("expected {}", expected));
-                err
-            });
-            PatKind::Lit(self.mk_expr(lo, ExprKind::Lit(lit.token_lit)))
+                    let mut err = self_.struct_span_err(self_.token.span, &msg);
+                    err.span_label(self_.token.span, format!("expected {}", expected));
+                    err
+                });
+            PatKind::Lit(self.mk_expr(lo, ExprKind::Lit(lit)))
         } else {
             // Try to parse everything else as literal with optional minus
             match self.parse_literal_maybe_minus() {
index 42197e6379749a264c325dbb332a41926754b515..bae7f2670cb11689866e837b411160d0cebe7552 100644 (file)
@@ -164,7 +164,7 @@ fn parse_stmt_path_start(&mut self, lo: Span, attrs: AttrWrapper) -> PResult<'a,
             // Perform this outside of the `collect_tokens_trailing_token` closure,
             // since our outer attributes do not apply to this part of the expression
             let expr = self.with_res(Restrictions::STMT_EXPR, |this| {
-                this.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(expr))
+                this.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(expr, true))
             })?;
             Ok(self.mk_stmt(lo.to(self.prev_token.span), StmtKind::Expr(expr)))
         } else {
@@ -198,7 +198,7 @@ fn parse_stmt_mac(&mut self, lo: Span, attrs: AttrVec, path: ast::Path) -> PResu
             let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac));
             let e = self.maybe_recover_from_bad_qpath(e)?;
             let e = self.parse_dot_or_call_expr_with(e, lo, attrs)?;
-            let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;
+            let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e, false))?;
             StmtKind::Expr(e)
         };
         Ok(self.mk_stmt(lo.to(hi), kind))
index fcc68b3a219cc93bea57983cbe980b31a8b220c8..72da398d3fc1984282fd422763c3fb0a73fe7da5 100644 (file)
@@ -5,3 +5,4 @@ edition = "2021"
 
 [dependencies]
 rustc_lexer = { path = "../rustc_lexer" }
+rustc_data_structures = { path = "../rustc_data_structures" }
index 0113eb4e3d1029911abf26519c4b742b2e62630e..9cbe04c1288effe53ad31e764541f49ef032a23a 100644 (file)
@@ -58,13 +58,13 @@ fn to(self, end: InnerOffset) -> InnerSpan {
 
 /// A piece is a portion of the format string which represents the next part
 /// to emit. These are emitted as a stream by the `Parser` class.
-#[derive(Copy, Clone, Debug, PartialEq)]
+#[derive(Clone, Debug, PartialEq)]
 pub enum Piece<'a> {
     /// A literal string which should directly be emitted
     String(&'a str),
     /// This describes that formatting should process the next argument (as
     /// specified inside) for emission.
-    NextArgument(Argument<'a>),
+    NextArgument(Box<Argument<'a>>),
 }
 
 /// Representation of an argument specification.
@@ -244,7 +244,7 @@ fn next(&mut self) -> Option<Piece<'a>> {
                         } else {
                             self.suggest_positional_arg_instead_of_captured_arg(arg);
                         }
-                        Some(NextArgument(arg))
+                        Some(NextArgument(Box::new(arg)))
                     }
                 }
                 '}' => {
@@ -908,5 +908,9 @@ fn find_skips_from_snippet(
     (skips, true)
 }
 
+// Assert a reasonable size for `Piece`
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+rustc_data_structures::static_assert_size!(Piece<'_>, 16);
+
 #[cfg(test)]
 mod tests;
index 3f9cb149b53eb402fec088035257425eca1c36e9..2992ba845ab16aab0b3da5da04096c2978ce9900 100644 (file)
@@ -76,51 +76,51 @@ fn invalid_precision() {
 fn format_nothing() {
     same(
         "{}",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentImplicitlyIs(0),
             position_span: InnerSpan { start: 2, end: 2 },
             format: fmtdflt(),
-        })],
+        }))],
     );
 }
 #[test]
 fn format_position() {
     same(
         "{3}",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentIs(3),
             position_span: InnerSpan { start: 2, end: 3 },
             format: fmtdflt(),
-        })],
+        }))],
     );
 }
 #[test]
 fn format_position_nothing_else() {
     same(
         "{3:}",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentIs(3),
             position_span: InnerSpan { start: 2, end: 3 },
             format: fmtdflt(),
-        })],
+        }))],
     );
 }
 #[test]
 fn format_named() {
     same(
         "{name}",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentNamed("name"),
             position_span: InnerSpan { start: 2, end: 6 },
             format: fmtdflt(),
-        })],
+        }))],
     )
 }
 #[test]
 fn format_type() {
     same(
         "{3:x}",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentIs(3),
             position_span: InnerSpan { start: 2, end: 3 },
             format: FormatSpec {
@@ -134,14 +134,14 @@ fn format_type() {
                 ty: "x",
                 ty_span: None,
             },
-        })],
+        }))],
     );
 }
 #[test]
 fn format_align_fill() {
     same(
         "{3:>}",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentIs(3),
             position_span: InnerSpan { start: 2, end: 3 },
             format: FormatSpec {
@@ -155,11 +155,11 @@ fn format_align_fill() {
                 ty: "",
                 ty_span: None,
             },
-        })],
+        }))],
     );
     same(
         "{3:0<}",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentIs(3),
             position_span: InnerSpan { start: 2, end: 3 },
             format: FormatSpec {
@@ -173,11 +173,11 @@ fn format_align_fill() {
                 ty: "",
                 ty_span: None,
             },
-        })],
+        }))],
     );
     same(
         "{3:*<abcd}",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentIs(3),
             position_span: InnerSpan { start: 2, end: 3 },
             format: FormatSpec {
@@ -191,14 +191,14 @@ fn format_align_fill() {
                 ty: "abcd",
                 ty_span: Some(InnerSpan::new(6, 10)),
             },
-        })],
+        }))],
     );
 }
 #[test]
 fn format_counts() {
     same(
         "{:10x}",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentImplicitlyIs(0),
             position_span: InnerSpan { start: 2, end: 2 },
             format: FormatSpec {
@@ -212,11 +212,11 @@ fn format_counts() {
                 ty: "x",
                 ty_span: None,
             },
-        })],
+        }))],
     );
     same(
         "{:10$.10x}",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentImplicitlyIs(0),
             position_span: InnerSpan { start: 2, end: 2 },
             format: FormatSpec {
@@ -230,11 +230,11 @@ fn format_counts() {
                 ty: "x",
                 ty_span: None,
             },
-        })],
+        }))],
     );
     same(
         "{1:0$.10x}",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentIs(1),
             position_span: InnerSpan { start: 2, end: 3 },
             format: FormatSpec {
@@ -248,11 +248,11 @@ fn format_counts() {
                 ty: "x",
                 ty_span: None,
             },
-        })],
+        }))],
     );
     same(
         "{:.*x}",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentImplicitlyIs(1),
             position_span: InnerSpan { start: 2, end: 2 },
             format: FormatSpec {
@@ -266,11 +266,11 @@ fn format_counts() {
                 ty: "x",
                 ty_span: None,
             },
-        })],
+        }))],
     );
     same(
         "{:.10$x}",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentImplicitlyIs(0),
             position_span: InnerSpan { start: 2, end: 2 },
             format: FormatSpec {
@@ -284,11 +284,11 @@ fn format_counts() {
                 ty: "x",
                 ty_span: None,
             },
-        })],
+        }))],
     );
     same(
         "{:a$.b$?}",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentImplicitlyIs(0),
             position_span: InnerSpan { start: 2, end: 2 },
             format: FormatSpec {
@@ -302,11 +302,11 @@ fn format_counts() {
                 ty: "?",
                 ty_span: None,
             },
-        })],
+        }))],
     );
     same(
         "{:.4}",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentImplicitlyIs(0),
             position_span: InnerSpan { start: 2, end: 2 },
             format: FormatSpec {
@@ -320,14 +320,14 @@ fn format_counts() {
                 ty: "",
                 ty_span: None,
             },
-        })],
+        }))],
     )
 }
 #[test]
 fn format_flags() {
     same(
         "{:-}",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentImplicitlyIs(0),
             position_span: InnerSpan { start: 2, end: 2 },
             format: FormatSpec {
@@ -341,11 +341,11 @@ fn format_flags() {
                 ty: "",
                 ty_span: None,
             },
-        })],
+        }))],
     );
     same(
         "{:+#}",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentImplicitlyIs(0),
             position_span: InnerSpan { start: 2, end: 2 },
             format: FormatSpec {
@@ -359,7 +359,7 @@ fn format_flags() {
                 ty: "",
                 ty_span: None,
             },
-        })],
+        }))],
     );
 }
 #[test]
@@ -368,7 +368,7 @@ fn format_mixture() {
         "abcd {3:x} efg",
         &[
             String("abcd "),
-            NextArgument(Argument {
+            NextArgument(Box::new(Argument {
                 position: ArgumentIs(3),
                 position_span: InnerSpan { start: 7, end: 8 },
                 format: FormatSpec {
@@ -382,7 +382,7 @@ fn format_mixture() {
                     ty: "x",
                     ty_span: None,
                 },
-            }),
+            })),
             String(" efg"),
         ],
     );
@@ -391,18 +391,18 @@ fn format_mixture() {
 fn format_whitespace() {
     same(
         "{ }",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentImplicitlyIs(0),
             position_span: InnerSpan { start: 2, end: 3 },
             format: fmtdflt(),
-        })],
+        }))],
     );
     same(
         "{  }",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentImplicitlyIs(0),
             position_span: InnerSpan { start: 2, end: 4 },
             format: fmtdflt(),
-        })],
+        }))],
     );
 }
index da023fcf4c3b5c23405cacb7bca785998dd95c94..a71ae717a508d37ee42db75d1a5add8a994fac0b 100644 (file)
@@ -124,7 +124,7 @@ fn lookup_and_handle_method(&mut self, id: hir::HirId) {
     fn handle_field_access(&mut self, lhs: &hir::Expr<'_>, hir_id: hir::HirId) {
         match self.typeck_results().expr_ty_adjusted(lhs).kind() {
             ty::Adt(def, _) => {
-                let index = self.tcx.field_index(hir_id, self.typeck_results());
+                let index = self.typeck_results().field_index(hir_id);
                 self.insert_def_id(def.non_enum_variant().fields[index].did);
             }
             ty::Tuple(..) => {}
@@ -208,7 +208,7 @@ fn handle_field_pattern_match(
             if let PatKind::Wild = pat.pat.kind {
                 continue;
             }
-            let index = self.tcx.field_index(pat.hir_id, self.typeck_results());
+            let index = self.typeck_results().field_index(pat.hir_id);
             self.insert_def_id(variant.fields[index].did);
         }
     }
@@ -341,7 +341,7 @@ fn visit_node(&mut self, node: Node<'tcx>) {
     fn mark_as_used_if_union(&mut self, adt: ty::AdtDef<'tcx>, fields: &[hir::ExprField<'_>]) {
         if adt.is_union() && adt.non_enum_variant().fields.len() > 1 && adt.did().is_local() {
             for field in fields {
-                let index = self.tcx.field_index(field.hir_id, self.typeck_results());
+                let index = self.typeck_results().field_index(field.hir_id);
                 self.insert_def_id(adt.non_enum_variant().fields[index].did);
             }
         }
index a7854cd49988f721806864a33570b646bc5379d2..272386f313e8d0736aecdd274652c4374e1fca6e 100644 (file)
@@ -121,7 +121,7 @@ fn record_inner<T>(
 
     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);
+        nodes.sort_by_key(|(_, node)| node.stats.count * node.stats.size);
 
         let total_size = nodes.iter().map(|(_, node)| node.stats.count * node.stats.size).sum();
 
@@ -147,7 +147,7 @@ fn print(&self, title: &str, prefix: &str) {
             );
             if !node.subnodes.is_empty() {
                 let mut subnodes: Vec<_> = node.subnodes.iter().collect();
-                subnodes.sort_by_key(|&(_, ref subnode)| subnode.count * subnode.size);
+                subnodes.sort_by_key(|(_, subnode)| subnode.count * subnode.size);
 
                 for (label, subnode) in subnodes {
                     let size = subnode.count * subnode.size;
index 99efed0b7fb46be15f9d92585c159c7ccf05b7fa..9a40b847d8552ebd9800fa42f6a6791b17562f73 100644 (file)
@@ -83,7 +83,6 @@ fn collect_item(&mut self, lang_item: LangItem, item_def_id: DefId) {
                         .map(|p| p.display().to_string())
                         .collect::<Vec<_>>()
                         .join(", ")
-                        .into()
                 };
                 let first_defined_span = self.tcx.hir().span_if_local(original_def_id);
                 let mut orig_crate_name = Empty;
@@ -98,7 +97,6 @@ fn collect_item(&mut self, lang_item: LangItem, item_def_id: DefId) {
                         .map(|p| p.display().to_string())
                         .collect::<Vec<_>>()
                         .join(", ")
-                        .into()
                 };
                 if first_defined_span.is_none() {
                     orig_crate_name = self.tcx.crate_name(original_def_id.krate);
index f2177a7c28332432c41eae1ce32fd81409a454f8..72d38aeac7a0c0647f176fe451143d3cc1611354 100644 (file)
@@ -88,10 +88,7 @@ fn visit(&mut self, ty_fragment: impl TypeVisitable<'tcx>) -> ControlFlow<Self::
     fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow<Self::BreakTy> {
         self.skeleton().visit_trait(trait_ref)
     }
-    fn visit_projection_ty(
-        &mut self,
-        projection: ty::ProjectionTy<'tcx>,
-    ) -> ControlFlow<Self::BreakTy> {
+    fn visit_projection_ty(&mut self, projection: ty::AliasTy<'tcx>) -> ControlFlow<Self::BreakTy> {
         self.skeleton().visit_projection_ty(projection)
     }
     fn visit_predicates(
@@ -113,29 +110,25 @@ impl<'tcx, V> DefIdVisitorSkeleton<'_, 'tcx, V>
     V: DefIdVisitor<'tcx> + ?Sized,
 {
     fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow<V::BreakTy> {
-        let TraitRef { def_id, substs } = trait_ref;
+        let TraitRef { def_id, substs, .. } = trait_ref;
         self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref.print_only_trait_path())?;
         if self.def_id_visitor.shallow() { ControlFlow::CONTINUE } else { substs.visit_with(self) }
     }
 
-    fn visit_projection_ty(
-        &mut self,
-        projection: ty::ProjectionTy<'tcx>,
-    ) -> ControlFlow<V::BreakTy> {
+    fn visit_projection_ty(&mut self, projection: ty::AliasTy<'tcx>) -> ControlFlow<V::BreakTy> {
         let tcx = self.def_id_visitor.tcx();
-        let (trait_ref, assoc_substs) = if tcx.def_kind(projection.item_def_id)
-            != DefKind::ImplTraitPlaceholder
-        {
-            projection.trait_ref_and_own_substs(tcx)
-        } else {
-            // HACK(RPITIT): Remove this when RPITITs are lowered to regular assoc tys
-            let def_id = tcx.impl_trait_in_trait_parent(projection.item_def_id);
-            let trait_generics = tcx.generics_of(def_id);
-            (
-                ty::TraitRef { def_id, substs: projection.substs.truncate_to(tcx, trait_generics) },
-                &projection.substs[trait_generics.count()..],
-            )
-        };
+        let (trait_ref, assoc_substs) =
+            if tcx.def_kind(projection.def_id) != DefKind::ImplTraitPlaceholder {
+                projection.trait_ref_and_own_substs(tcx)
+            } else {
+                // HACK(RPITIT): Remove this when RPITITs are lowered to regular assoc tys
+                let def_id = tcx.impl_trait_in_trait_parent(projection.def_id);
+                let trait_generics = tcx.generics_of(def_id);
+                (
+                    tcx.mk_trait_ref(def_id, projection.substs.truncate_to(tcx, trait_generics)),
+                    &projection.substs[trait_generics.count()..],
+                )
+            };
         self.visit_trait(trait_ref)?;
         if self.def_id_visitor.shallow() {
             ControlFlow::CONTINUE
@@ -214,7 +207,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<V::BreakTy> {
                     }
                 }
             }
-            ty::Projection(proj) => {
+            ty::Alias(ty::Projection, proj) => {
                 if self.def_id_visitor.skip_assoc_tys() {
                     // Visitors searching for minimal visibility/reachability want to
                     // conservatively approximate associated types like `<Type as Trait>::Alias`
@@ -241,7 +234,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<V::BreakTy> {
                     self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref)?;
                 }
             }
-            ty::Opaque(def_id, ..) => {
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
                 // Skip repeated `Opaque`s to avoid infinite recursion.
                 if self.visited_opaque_tys.insert(def_id) {
                     // The intent is to treat `impl Trait1 + Trait2` identically to
@@ -1065,9 +1058,9 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
                 // are checked for privacy (RFC 736). Rather than computing the set of
                 // unmentioned fields, just check them all.
                 for (vf_index, variant_field) in variant.fields.iter().enumerate() {
-                    let field = fields.iter().find(|f| {
-                        self.tcx.field_index(f.hir_id, self.typeck_results()) == vf_index
-                    });
+                    let field = fields
+                        .iter()
+                        .find(|f| self.typeck_results().field_index(f.hir_id) == vf_index);
                     let (use_ctxt, span) = match field {
                         Some(field) => (field.ident.span, field.span),
                         None => (base.span, base.span),
@@ -1077,7 +1070,7 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
             } else {
                 for field in fields {
                     let use_ctxt = field.ident.span;
-                    let index = self.tcx.field_index(field.hir_id, self.typeck_results());
+                    let index = self.typeck_results().field_index(field.hir_id);
                     self.check_field(use_ctxt, field.span, adt, &variant.fields[index], false);
                 }
             }
@@ -1093,7 +1086,7 @@ fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) {
             let variant = adt.variant_of_res(res);
             for field in fields {
                 let use_ctxt = field.ident.span;
-                let index = self.tcx.field_index(field.hir_id, self.typeck_results());
+                let index = self.typeck_results().field_index(field.hir_id);
                 self.check_field(use_ctxt, field.span, adt, &variant.fields[index], false);
             }
         }
@@ -1308,15 +1301,15 @@ fn visit_qpath(&mut self, qpath: &'tcx hir::QPath<'tcx>, id: hir::HirId, span: S
             let is_local_static =
                 if let DefKind::Static(_) = kind { def_id.is_local() } else { false };
             if !self.item_is_accessible(def_id) && !is_local_static {
-                let sess = self.tcx.sess;
-                let sm = sess.source_map();
-                let name = match qpath {
-                    hir::QPath::Resolved(..) | hir::QPath::LangItem(..) => {
-                        sm.span_to_snippet(qpath.span()).ok()
+                let name = match *qpath {
+                    hir::QPath::LangItem(it, ..) => {
+                        self.tcx.lang_items().get(it).map(|did| self.tcx.def_path_str(did))
                     }
+                    hir::QPath::Resolved(_, path) => Some(self.tcx.def_path_str(path.res.def_id())),
                     hir::QPath::TypeRelative(_, segment) => Some(segment.ident.to_string()),
                 };
                 let kind = kind.descr(def_id);
+                let sess = self.tcx.sess;
                 let _ = match name {
                     Some(name) => {
                         sess.emit_err(ItemIsPrivate { span, kind, descr: (&name).into() })
index 38c7c6cce67650680b967749481eee26dcbd1b9a..0e7d628c1eb630c030946079bfaa9259a3785c01 100644 (file)
@@ -46,7 +46,7 @@ impl DepNodeIndex {
     pub const FOREVER_RED_NODE: DepNodeIndex = DepNodeIndex::from_u32(1);
 }
 
-impl std::convert::From<DepNodeIndex> for QueryInvocationId {
+impl From<DepNodeIndex> for QueryInvocationId {
     #[inline]
     fn from(dep_node_index: DepNodeIndex) -> Self {
         QueryInvocationId(dep_node_index.as_u32())
index 3b20ec70d73cb3d5dc45a48f893af8ced9e07149..d292f4beef2ebccc33f0bebfa0894a7d756e5a1a 100644 (file)
@@ -22,7 +22,6 @@
 use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder};
 use rustc_serialize::{Decodable, Decoder, Encodable};
 use smallvec::SmallVec;
-use std::convert::TryInto;
 
 // The maximum value of `SerializedDepNodeIndex` leaves the upper two bits
 // unused so that we can store multiple index types in `CompressedHybridIndex`,
index 7a20eaceba0247682a7ae74451ddcbf3eeeb7772..cf2f04c7486b846c0609109998fc8daedc75b8db 100644 (file)
@@ -49,7 +49,7 @@ pub struct Cycle {
     #[primary_span]
     pub span: Span,
     pub stack_bottom: String,
-    #[subdiagnostic(eager)]
+    #[subdiagnostic]
     pub cycle_stack: Vec<CycleStack>,
     #[subdiagnostic]
     pub stack_count: StackCount,
index 6378ec10875d038e087236d195810b573ff6c48b..163da59edd5c7378fe43f9f8c565ae1237d72693 100644 (file)
@@ -6,9 +6,8 @@
 use rustc_data_structures::sync::Lrc;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::definitions::{DefPathHash, Definitions};
-use rustc_index::vec::IndexVec;
-use rustc_session::cstore::CrateStore;
+use rustc_hir::definitions::DefPathHash;
+use rustc_session::cstore::Untracked;
 use rustc_session::Session;
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::Symbol;
@@ -20,9 +19,7 @@
 /// things (e.g., each `DefId`/`DefPath` is only hashed once).
 #[derive(Clone)]
 pub struct StableHashingContext<'a> {
-    definitions: &'a Definitions,
-    cstore: &'a dyn CrateStore,
-    source_span: &'a IndexVec<LocalDefId, Span>,
+    untracked: &'a Untracked,
     // The value of `-Z incremental-ignore-spans`.
     // This field should only be used by `unstable_opts_incremental_ignore_span`
     incremental_ignore_spans: bool,
@@ -49,19 +46,12 @@ pub(super) enum BodyResolver<'tcx> {
 
 impl<'a> StableHashingContext<'a> {
     #[inline]
-    pub fn new(
-        sess: &'a Session,
-        definitions: &'a Definitions,
-        cstore: &'a dyn CrateStore,
-        source_span: &'a IndexVec<LocalDefId, Span>,
-    ) -> Self {
+    pub fn new(sess: &'a Session, untracked: &'a Untracked) -> Self {
         let hash_spans_initial = !sess.opts.unstable_opts.incremental_ignore_spans;
 
         StableHashingContext {
             body_resolver: BodyResolver::Forbidden,
-            definitions,
-            cstore,
-            source_span,
+            untracked,
             incremental_ignore_spans: sess.opts.unstable_opts.incremental_ignore_spans,
             caching_source_map: None,
             raw_source_map: sess.source_map(),
@@ -100,13 +90,13 @@ pub fn def_path_hash(&self, def_id: DefId) -> DefPathHash {
         if let Some(def_id) = def_id.as_local() {
             self.local_def_path_hash(def_id)
         } else {
-            self.cstore.def_path_hash(def_id)
+            self.untracked.cstore.def_path_hash(def_id)
         }
     }
 
     #[inline]
     pub fn local_def_path_hash(&self, def_id: LocalDefId) -> DefPathHash {
-        self.definitions.def_path_hash(def_id)
+        self.untracked.definitions.read().def_path_hash(def_id)
     }
 
     #[inline]
@@ -156,7 +146,7 @@ fn def_path_hash(&self, def_id: DefId) -> DefPathHash {
 
     #[inline]
     fn def_span(&self, def_id: LocalDefId) -> Span {
-        *self.source_span.get(def_id).unwrap_or(&DUMMY_SP)
+        *self.untracked.source_span.get(def_id).unwrap_or(&DUMMY_SP)
     }
 
     #[inline]
index 4c4680b5d8ea89b7d241e548a0e386da06e998df..f65846fc77f6e5114bfd384ce37c013c61e10e62 100644 (file)
@@ -9,7 +9,6 @@
 use rustc_data_structures::sync::Lock;
 use rustc_data_structures::sync::WorkerLocal;
 use rustc_index::vec::{Idx, IndexVec};
-use std::default::Default;
 use std::fmt::Debug;
 use std::hash::Hash;
 use std::marker::PhantomData;
index 49bbcf57804596623ed30642d0d837d5ba1ca8af..701bbde6ad23f92d89169ce3aa3e3c7bc278685c 100644 (file)
@@ -22,8 +22,8 @@
     rustc_data_structures::{jobserver, OnDrop},
     rustc_rayon_core as rayon_core,
     rustc_span::DUMMY_SP,
-    std::iter::{self, FromIterator},
-    std::{mem, process},
+    std::iter,
+    std::process,
 };
 
 /// Represents a span and a query key.
@@ -247,7 +247,7 @@ fn wait_on_inner(&self, waiter: &Lrc<QueryWaiter>) {
             jobserver::release_thread();
             waiter.condvar.wait(&mut info);
             // Release the lock before we potentially block in `acquire_thread`
-            mem::drop(info);
+            drop(info);
             jobserver::acquire_thread();
         }
     }
index 9c90d67aadf7194c4a79108ac0c35f041716030e..cf63599626866203f41feeaca0bf156bd9d0ce75 100644 (file)
@@ -576,7 +576,7 @@ fn build_reduced_graph_for_use_tree(
                 // Ensure there is at most one `self` in the list
                 let self_spans = items
                     .iter()
-                    .filter_map(|&(ref use_tree, _)| {
+                    .filter_map(|(use_tree, _)| {
                         if let ast::UseTreeKind::Simple(..) = use_tree.kind {
                             if use_tree.ident().name == kw::SelfLower {
                                 return Some(use_tree.span);
@@ -836,12 +836,11 @@ fn build_reduced_graph_for_extern_crate(
         } else if orig_name == Some(kw::SelfLower) {
             Some(self.r.graph_root)
         } else {
-            self.r.crate_loader.process_extern_crate(item, &self.r.definitions, local_def_id).map(
-                |crate_id| {
-                    self.r.extern_crate_map.insert(local_def_id, crate_id);
-                    self.r.expect_module(crate_id.as_def_id())
-                },
-            )
+            let crate_id = self.r.crate_loader().process_extern_crate(item, local_def_id);
+            crate_id.map(|crate_id| {
+                self.r.extern_crate_map.insert(local_def_id, crate_id);
+                self.r.expect_module(crate_id.as_def_id())
+            })
         }
         .map(|module| {
             let used = self.process_macro_use_imports(item, module);
index f6b6cf3a94c18e93f3075ae246db451067694c35..37771693417b35a8c60d0e571ed98f7dab77a718 100644 (file)
@@ -153,7 +153,7 @@ fn report_with_use_injections(&mut self, krate: &Crate) {
             if !candidates.is_empty() {
                 show_candidates(
                     &self.session,
-                    &self.source_span,
+                    &self.untracked.source_span,
                     &mut err,
                     span,
                     &candidates,
@@ -682,7 +682,7 @@ pub(crate) fn into_struct_error(
                     }
                     show_candidates(
                         &self.session,
-                        &self.source_span,
+                        &self.untracked.source_span,
                         &mut err,
                         Some(span),
                         &import_suggestions,
@@ -1298,7 +1298,8 @@ pub(crate) fn lookup_import_candidates<FilterFn>(
                     // otherwise cause duplicate suggestions.
                     continue;
                 }
-                if let Some(crate_id) = self.crate_loader.maybe_process_path_extern(ident.name) {
+                let crate_id = self.crate_loader().maybe_process_path_extern(ident.name);
+                if let Some(crate_id) = crate_id {
                     let crate_root = self.expect_module(crate_id.as_def_id());
                     suggestions.extend(self.lookup_import_candidates_from_module(
                         lookup_ident,
@@ -1335,7 +1336,7 @@ pub(crate) fn unresolved_macro_suggestions(
             self.lookup_import_candidates(ident, Namespace::MacroNS, parent_scope, is_expected);
         show_candidates(
             &self.session,
-            &self.source_span,
+            &self.untracked.source_span,
             err,
             None,
             &import_suggestions,
index 85399385d1fd4fb2bd66a9b1244a869011aae057..b8efa3f8b2743336dc894dcbac137b8a0047da94 100644 (file)
@@ -107,7 +107,7 @@ pub fn compute_effective_visibilities<'c>(r: &'r mut Resolver<'a>, krate: &'c Cr
                 r.effective_visibilities.update_eff_vis(
                     r.local_def_id(node_id),
                     eff_vis,
-                    ResolverTree(&r.definitions, &r.crate_loader),
+                    ResolverTree(&r.untracked),
                 )
             }
         }
index b100a8c17cf398ba08c82d0fc8a226e93c82dd85..4d896b055268e975ab284861e93a8c85a4e70cda 100644 (file)
@@ -541,7 +541,7 @@ fn throw_unresolved_import_error(&self, errors: Vec<(String, UnresolvedImportErr
             if let Some(candidate) = &err.candidate {
                 import_candidates(
                     self.r.session,
-                    &self.r.source_span,
+                    &self.r.untracked.source_span,
                     &mut diag,
                     Some(err.span),
                     &candidate,
index cf3e5946053fe514f5b9195784e93e37d63e053f..5b7a00101e9b75b53cd635ec29c1d90da6a9a5be 100644 (file)
@@ -566,6 +566,9 @@ struct LateResolutionVisitor<'a, 'b, 'ast> {
     /// FIXME #4948: Reuse ribs to avoid allocation.
     ribs: PerNS<Vec<Rib<'a>>>,
 
+    /// Previous poped `rib`, only used for diagnostic.
+    last_block_rib: Option<Rib<'a>>,
+
     /// The current set of local scopes, for labels.
     label_ribs: Vec<Rib<'a, NodeId>>,
 
@@ -873,6 +876,8 @@ fn visit_fn(&mut self, fn_kind: FnKind<'ast>, sp: Span, fn_id: NodeId) {
                             // Ignore errors in function bodies if this is rustdoc
                             // Be sure not to set this until the function signature has been resolved.
                             let previous_state = replace(&mut this.in_func_body, true);
+                            // We only care block in the same function
+                            this.last_block_rib = None;
                             // Resolve the function body, potentially inside the body of an async closure
                             this.with_lifetime_rib(
                                 LifetimeRibKind::Elided(LifetimeRes::Infer),
@@ -1168,6 +1173,7 @@ fn new(resolver: &'b mut Resolver<'a>) -> LateResolutionVisitor<'a, 'b, 'ast> {
                 type_ns: vec![Rib::new(start_rib_kind)],
                 macro_ns: vec![Rib::new(start_rib_kind)],
             },
+            last_block_rib: None,
             label_ribs: Vec::new(),
             lifetime_ribs: Vec::new(),
             lifetime_elision_candidates: None,
@@ -3769,7 +3775,7 @@ fn resolve_block(&mut self, block: &'ast Block) {
             self.ribs[ValueNS].pop();
             self.label_ribs.pop();
         }
-        self.ribs[ValueNS].pop();
+        self.last_block_rib = self.ribs[ValueNS].pop();
         if anonymous_module.is_some() {
             self.ribs[TypeNS].pop();
         }
index df59a350ea7c9cfbd19dc89d3ab8556717e21d7e..49bbe37ee4328ad5dadd9ae79c87a7ded364dcd0 100644 (file)
@@ -623,6 +623,22 @@ fn try_lookup_name_relaxed(
                 return (true, candidates);
             }
         }
+
+        // Try to find in last block rib
+        if let Some(rib) = &self.last_block_rib && let RibKind::NormalRibKind = rib.kind {
+            for (ident, &res) in &rib.bindings {
+                if let Res::Local(_) = res && path.len() == 1 &&
+                    ident.span.eq_ctxt(path[0].ident.span) &&
+                    ident.name == path[0].ident.name {
+                    err.span_help(
+                        ident.span,
+                        &format!("the binding `{}` is available in a different scope in the same function", path_str),
+                    );
+                    return (true, candidates);
+                }
+            }
+        }
+
         return (false, candidates);
     }
 
@@ -1663,8 +1679,10 @@ fn lookup_typo_candidate(
                         if !module.no_implicit_prelude {
                             let extern_prelude = self.r.extern_prelude.clone();
                             names.extend(extern_prelude.iter().flat_map(|(ident, _)| {
-                                self.r.crate_loader.maybe_process_path_extern(ident.name).and_then(
-                                    |crate_id| {
+                                self.r
+                                    .crate_loader()
+                                    .maybe_process_path_extern(ident.name)
+                                    .and_then(|crate_id| {
                                         let crate_mod =
                                             Res::Def(DefKind::Mod, crate_id.as_def_id());
 
@@ -1673,8 +1691,7 @@ fn lookup_typo_candidate(
                                         } else {
                                             None
                                         }
-                                    },
-                                )
+                                    })
                             }));
 
                             if let Some(prelude) = self.r.prelude {
index 4ef89cfb2554fdbc13f0dde06cbb2582a81eeb30..24e4b5bdd3f50d8f84e8d3f435062eb401e9de07 100644 (file)
@@ -29,7 +29,7 @@
 use rustc_ast::{AngleBracketedArg, Crate, Expr, ExprKind, GenericArg, GenericArgs, LitKind, Path};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_data_structures::intern::Interned;
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{Lrc, RwLock};
 use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed};
 use rustc_expand::base::{DeriveResolutions, SyntaxExtension, SyntaxExtensionKind};
 use rustc_hir::def::Namespace::*;
@@ -46,7 +46,7 @@
 use rustc_middle::ty::{self, DefIdTree, MainDefinition, RegisteredTools};
 use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs};
 use rustc_query_system::ich::StableHashingContext;
-use rustc_session::cstore::{CrateStore, MetadataLoaderDyn};
+use rustc_session::cstore::{CrateStore, MetadataLoaderDyn, Untracked};
 use rustc_session::lint::LintBuffer;
 use rustc_session::Session;
 use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency};
@@ -866,11 +866,8 @@ struct MacroData {
 pub struct Resolver<'a> {
     session: &'a Session,
 
-    definitions: Definitions,
     /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`.
     expn_that_defined: FxHashMap<LocalDefId, ExpnId>,
-    /// Reference span for definitions.
-    source_span: IndexVec<LocalDefId, Span>,
 
     graph_root: Module<'a>,
 
@@ -954,7 +951,10 @@ pub struct Resolver<'a> {
     arenas: &'a ResolverArenas<'a>,
     dummy_binding: &'a NameBinding<'a>,
 
-    crate_loader: CrateLoader<'a>,
+    local_crate_name: Symbol,
+    metadata_loader: Box<MetadataLoaderDyn>,
+    untracked: Untracked,
+    used_extern_options: FxHashSet<Symbol>,
     macro_names: FxHashSet<Ident>,
     builtin_macros: FxHashMap<Symbol, BuiltinMacroState>,
     /// A small map keeping true kinds of built-in macros that appear to be fn-like on
@@ -1112,15 +1112,15 @@ fn as_mut(&mut self) -> &mut Resolver<'a> {
 /// A minimal subset of resolver that can implemenent `DefIdTree`, sometimes
 /// required to satisfy borrow checker by avoiding borrowing the whole resolver.
 #[derive(Clone, Copy)]
-struct ResolverTree<'a, 'b>(&'a Definitions, &'a CrateLoader<'b>);
+struct ResolverTree<'a>(&'a Untracked);
 
-impl DefIdTree for ResolverTree<'_, '_> {
+impl DefIdTree for ResolverTree<'_> {
     #[inline]
     fn opt_parent(self, id: DefId) -> Option<DefId> {
-        let ResolverTree(definitions, crate_loader) = self;
+        let ResolverTree(Untracked { definitions, cstore, .. }) = self;
         match id.as_local() {
-            Some(id) => definitions.def_key(id).parent,
-            None => crate_loader.cstore().def_key(id).parent,
+            Some(id) => definitions.read().def_key(id).parent,
+            None => cstore.as_any().downcast_ref::<CStore>().unwrap().def_key(id).parent,
         }
         .map(|index| DefId { index, ..id })
     }
@@ -1129,7 +1129,7 @@ fn opt_parent(self, id: DefId) -> Option<DefId> {
 impl<'a, 'b> DefIdTree for &'a Resolver<'b> {
     #[inline]
     fn opt_parent(self, id: DefId) -> Option<DefId> {
-        ResolverTree(&self.definitions, &self.crate_loader).opt_parent(id)
+        ResolverTree(&self.untracked).opt_parent(id)
     }
 }
 
@@ -1156,10 +1156,10 @@ fn create_def(
             "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}",
             node_id,
             data,
-            self.definitions.def_key(self.node_id_to_def_id[&node_id]),
+            self.untracked.definitions.read().def_key(self.node_id_to_def_id[&node_id]),
         );
 
-        let def_id = self.definitions.create_def(parent, data);
+        let def_id = self.untracked.definitions.write().create_def(parent, data);
 
         // Create the definition.
         if expn_id != ExpnId::root() {
@@ -1168,7 +1168,7 @@ fn create_def(
 
         // A relative span's parent must be an absolute span.
         debug_assert_eq!(span.data_untracked().parent, None);
-        let _id = self.source_span.push(span);
+        let _id = self.untracked.source_span.push(span);
         debug_assert_eq!(_id, def_id);
 
         // Some things for which we allocate `LocalDefId`s don't correspond to
@@ -1196,7 +1196,7 @@ impl<'a> Resolver<'a> {
     pub fn new(
         session: &'a Session,
         krate: &Crate,
-        crate_name: &str,
+        crate_name: Symbol,
         metadata_loader: Box<MetadataLoaderDyn>,
         arenas: &'a ResolverArenas<'a>,
     ) -> Resolver<'a> {
@@ -1258,9 +1258,7 @@ pub fn new(
         let mut resolver = Resolver {
             session,
 
-            definitions,
             expn_that_defined: Default::default(),
-            source_span,
 
             // The outermost module has def ID 0; this is not reflected in the
             // AST.
@@ -1311,7 +1309,14 @@ pub fn new(
                 vis: ty::Visibility::Public,
             }),
 
-            crate_loader: CrateLoader::new(session, metadata_loader, crate_name),
+            metadata_loader,
+            local_crate_name: crate_name,
+            used_extern_options: Default::default(),
+            untracked: Untracked {
+                cstore: Box::new(CStore::new(session)),
+                source_span,
+                definitions: RwLock::new(definitions),
+            },
             macro_names: FxHashSet::default(),
             builtin_macros: Default::default(),
             builtin_macro_kinds: Default::default(),
@@ -1402,9 +1407,6 @@ pub fn arenas() -> ResolverArenas<'a> {
 
     pub fn into_outputs(self) -> ResolverOutputs {
         let proc_macros = self.proc_macros.iter().map(|id| self.local_def_id(*id)).collect();
-        let definitions = self.definitions;
-        let cstore = Box::new(self.crate_loader.into_cstore());
-        let source_span = self.source_span;
         let expn_that_defined = self.expn_that_defined;
         let visibilities = self.visibilities;
         let has_pub_restricted = self.has_pub_restricted;
@@ -1416,9 +1418,8 @@ pub fn into_outputs(self) -> ResolverOutputs {
         let main_def = self.main_def;
         let confused_type_with_std_module = self.confused_type_with_std_module;
         let effective_visibilities = self.effective_visibilities;
+        let untracked = self.untracked;
         let global_ctxt = ResolverGlobalCtxt {
-            cstore,
-            source_span,
             expn_that_defined,
             visibilities,
             has_pub_restricted,
@@ -1453,16 +1454,16 @@ pub fn into_outputs(self) -> ResolverOutputs {
             builtin_macro_kinds: self.builtin_macro_kinds,
             lifetime_elision_allowed: self.lifetime_elision_allowed,
         };
-        ResolverOutputs { definitions, global_ctxt, ast_lowering }
+        ResolverOutputs { global_ctxt, ast_lowering, untracked }
     }
 
     pub fn clone_outputs(&self) -> ResolverOutputs {
         let proc_macros = self.proc_macros.iter().map(|id| self.local_def_id(*id)).collect();
-        let definitions = self.definitions.clone();
+        let definitions = self.untracked.definitions.clone();
         let cstore = Box::new(self.cstore().clone());
+        let untracked =
+            Untracked { cstore, source_span: self.untracked.source_span.clone(), definitions };
         let global_ctxt = ResolverGlobalCtxt {
-            cstore,
-            source_span: self.source_span.clone(),
             expn_that_defined: self.expn_that_defined.clone(),
             visibilities: self.visibilities.clone(),
             has_pub_restricted: self.has_pub_restricted,
@@ -1497,20 +1498,26 @@ pub fn clone_outputs(&self) -> ResolverOutputs {
             builtin_macro_kinds: self.builtin_macro_kinds.clone(),
             lifetime_elision_allowed: self.lifetime_elision_allowed.clone(),
         };
-        ResolverOutputs { definitions, global_ctxt, ast_lowering }
+        ResolverOutputs { global_ctxt, ast_lowering, untracked }
     }
 
     fn create_stable_hashing_context(&self) -> StableHashingContext<'_> {
-        StableHashingContext::new(
-            self.session,
-            &self.definitions,
-            self.crate_loader.cstore(),
-            &self.source_span,
+        StableHashingContext::new(self.session, &self.untracked)
+    }
+
+    pub fn crate_loader(&mut self) -> CrateLoader<'_> {
+        CrateLoader::new(
+            &self.session,
+            &*self.metadata_loader,
+            self.local_crate_name,
+            &mut *self.untracked.cstore.untracked_as_any().downcast_mut().unwrap(),
+            self.untracked.definitions.read(),
+            &mut self.used_extern_options,
         )
     }
 
     pub fn cstore(&self) -> &CStore {
-        self.crate_loader.cstore()
+        self.untracked.cstore.as_any().downcast_ref().unwrap()
     }
 
     fn dummy_ext(&self, macro_kind: MacroKind) -> Lrc<SyntaxExtension> {
@@ -1553,7 +1560,7 @@ pub fn resolve_crate(&mut self, krate: &Crate) {
             self.session.time("resolve_main", || self.resolve_main());
             self.session.time("resolve_check_unused", || self.check_unused(krate));
             self.session.time("resolve_report_errors", || self.report_errors(krate));
-            self.session.time("resolve_postprocess", || self.crate_loader.postprocess(krate));
+            self.session.time("resolve_postprocess", || self.crate_loader().postprocess(krate));
         });
     }
 
@@ -1871,10 +1878,10 @@ fn extern_prelude_get(&mut self, ident: Ident, finalize: bool) -> Option<&'a Nam
             } else {
                 let crate_id = if finalize {
                     let Some(crate_id) =
-                        self.crate_loader.process_path_extern(ident.name, ident.span) else { return Some(self.dummy_binding); };
+                        self.crate_loader().process_path_extern(ident.name, ident.span) else { return Some(self.dummy_binding); };
                     crate_id
                 } else {
-                    self.crate_loader.maybe_process_path_extern(ident.name)?
+                    self.crate_loader().maybe_process_path_extern(ident.name)?
                 };
                 let crate_root = self.expect_module(crate_id.as_def_id());
                 let vis = ty::Visibility::<LocalDefId>::Public;
@@ -1946,14 +1953,14 @@ pub fn get_partial_res(&self, node_id: NodeId) -> Option<PartialRes> {
     /// Retrieves the span of the given `DefId` if `DefId` is in the local crate.
     #[inline]
     pub fn opt_span(&self, def_id: DefId) -> Option<Span> {
-        def_id.as_local().map(|def_id| self.source_span[def_id])
+        def_id.as_local().map(|def_id| self.untracked.source_span[def_id])
     }
 
     /// Retrieves the name of the given `DefId`.
     #[inline]
     pub fn opt_name(&self, def_id: DefId) -> Option<Symbol> {
         let def_key = match def_id.as_local() {
-            Some(def_id) => self.definitions.def_key(def_id),
+            Some(def_id) => self.untracked.definitions.read().def_key(def_id),
             None => self.cstore().def_key(def_id),
         };
         def_key.get_opt_name()
index 8c7972f8eebb92f09698ad625382f0a49f4bfd91..b5b1602c5e0d38ad3971cb62c3c19524412063a9 100644 (file)
@@ -455,7 +455,7 @@ fn cfg_accessible(
     }
 
     fn get_proc_macro_quoted_span(&self, krate: CrateNum, id: usize) -> Span {
-        self.crate_loader.cstore().get_proc_macro_quoted_span_untracked(krate, id, self.session)
+        self.cstore().get_proc_macro_quoted_span_untracked(krate, id, self.session)
     }
 
     fn declare_proc_macro(&mut self, id: NodeId) {
index b45288538256f84e9c10b8a80409cd9a773c9bfc..9ae07cb005bd41b0db70ee91e528cf9db13bd741 100644 (file)
@@ -111,7 +111,7 @@ fn lookup_def_id(&self, ref_id: hir::HirId) -> Option<DefId> {
         self.save_ctxt.lookup_def_id(ref_id)
     }
 
-    pub fn dump_crate_info(&mut self, name: &str) {
+    pub fn dump_crate_info(&mut self, name: Symbol) {
         let source_file = self.tcx.sess.local_crate_source_file.as_ref();
         let crate_root = source_file.map(|source_file| {
             let source_file = Path::new(source_file);
@@ -124,7 +124,7 @@ pub fn dump_crate_info(&mut self, name: &str) {
 
         let data = CratePreludeData {
             crate_id: GlobalCrateId {
-                name: name.into(),
+                name: name.to_string(),
                 disambiguator: (self.tcx.sess.local_stable_crate_id().to_u64(), 0),
             },
             crate_root: crate_root.unwrap_or_else(|| "<no source>".to_owned()),
@@ -135,7 +135,7 @@ pub fn dump_crate_info(&mut self, name: &str) {
         self.dumper.crate_prelude(data);
     }
 
-    pub fn dump_compilation_options(&mut self, input: &Input, crate_name: &str) {
+    pub fn dump_compilation_options(&mut self, input: &Input, crate_name: Symbol) {
         // Apply possible `remap-path-prefix` remapping to the input source file
         // (and don't include remapping args anymore)
         let (program, arguments) = {
index f05eb2b7432b5cabd3c8eb1b0839acf7e5a1788e..6c310abf10ac537f78b66ef160e7acd5466eb19a 100644 (file)
@@ -36,7 +36,6 @@
 use rustc_span::*;
 
 use std::cell::Cell;
-use std::default::Default;
 use std::env;
 use std::fs::File;
 use std::io::BufWriter;
@@ -95,7 +94,7 @@ fn span_from_span(&self, span: Span) -> SpanData {
     }
 
     /// Returns path to the compilation output (e.g., libfoo-12345678.rmeta)
-    pub fn compilation_output(&self, crate_name: &str) -> PathBuf {
+    pub fn compilation_output(&self, crate_name: Symbol) -> PathBuf {
         let sess = &self.tcx.sess;
         // Save-analysis is emitted per whole session, not per each crate type
         let crate_type = sess.crate_types()[0];
@@ -894,8 +893,8 @@ pub struct DumpHandler<'a> {
 }
 
 impl<'a> DumpHandler<'a> {
-    pub fn new(odir: Option<&'a Path>, cratename: &str) -> DumpHandler<'a> {
-        DumpHandler { odir, cratename: cratename.to_owned() }
+    pub fn new(odir: Option<&'a Path>, cratename: Symbol) -> DumpHandler<'a> {
+        DumpHandler { odir, cratename: cratename.to_string() }
     }
 
     fn output_file(&self, ctx: &SaveContext<'_>) -> (BufWriter<File>, PathBuf) {
@@ -960,7 +959,7 @@ fn save(&mut self, _: &SaveContext<'_>, analysis: &Analysis) {
 
 pub fn process_crate<'l, 'tcx, H: SaveHandler>(
     tcx: TyCtxt<'tcx>,
-    cratename: &str,
+    cratename: Symbol,
     input: &'l Input,
     config: Option<Config>,
     mut handler: H,
index 0afeb86fceb241611867c67ee4820f4e810507ac..0e0ebc79eb2e3dfdb7c65855491987d8724ee200 100644 (file)
@@ -1,6 +1,5 @@
 use crate::leb128::{self, largest_max_leb128_len};
 use crate::serialize::{Decodable, Decoder, Encodable, Encoder};
-use std::convert::TryInto;
 use std::fs::File;
 use std::io::{self, Write};
 use std::mem::MaybeUninit;
index a052f29334169ebd5d6478caf780b41fb8e4df0d..d8db86c5f6216e1643d7b1e33d881135cf096fb1 100644 (file)
@@ -13,11 +13,13 @@ rustc_hir = { path = "../rustc_hir" }
 rustc_target = { path = "../rustc_target" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_data_structures = { path = "../rustc_data_structures" }
+rustc_index = { path = "../rustc_index" }
 rustc_span = { path = "../rustc_span" }
 rustc_fs_util = { path = "../rustc_fs_util" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_lint_defs = { path = "../rustc_lint_defs" }
 smallvec = "1.8.1"
+termize = "0.1.1"
 
 [target.'cfg(unix)'.dependencies]
 libc = "0.2"
index eede4d16ea378b268a91e6d8e8f50c09ac1026d8..1085bce44758fe7235929e8c7ca2b703f23cbae3 100644 (file)
@@ -19,7 +19,7 @@ pub enum SizeKind {
     Min,
 }
 
-#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 pub struct FieldInfo {
     pub name: Symbol,
     pub offset: u64,
@@ -33,6 +33,7 @@ pub enum DataTypeKind {
     Union,
     Enum,
     Closure,
+    Generator,
 }
 
 #[derive(PartialEq, Eq, Hash, Debug)]
@@ -114,7 +115,7 @@ pub fn print_type_sizes(&self) {
 
             let struct_like = match kind {
                 DataTypeKind::Struct | DataTypeKind::Closure => true,
-                DataTypeKind::Enum | DataTypeKind::Union => false,
+                DataTypeKind::Enum | DataTypeKind::Union | DataTypeKind::Generator => false,
             };
             for (i, variant_info) in variants.into_iter().enumerate() {
                 let VariantInfo { ref name, kind: _, align: _, size, ref fields } = *variant_info;
index 7a20100fd313368ebe24f86e539789af442ed514..3bafd3730bd79d2db4cb31d95bda50d7e756a492 100644 (file)
@@ -32,7 +32,7 @@
 use std::collections::{BTreeMap, BTreeSet};
 use std::fmt;
 use std::hash::Hash;
-use std::iter::{self, FromIterator};
+use std::iter;
 use std::path::{Path, PathBuf};
 use std::str::{self, FromStr};
 
@@ -875,18 +875,12 @@ pub struct PacRet {
     pub key: PAuthKey,
 }
 
-#[derive(Clone, Copy, Hash, Debug, PartialEq)]
+#[derive(Clone, Copy, Hash, Debug, PartialEq, Default)]
 pub struct BranchProtection {
     pub bti: bool,
     pub pac_ret: Option<PacRet>,
 }
 
-impl Default for BranchProtection {
-    fn default() -> Self {
-        BranchProtection { bti: false, pac_ret: None }
-    }
-}
-
 pub const fn default_lib_output() -> CrateType {
     CrateType::Rlib
 }
@@ -1875,7 +1869,7 @@ fn parse_opt_level(
         .into_iter()
         .flat_map(|(i, s)| {
             // NB: This can match a string without `=`.
-            if let Some("opt-level") = s.splitn(2, '=').next() { Some(i) } else { None }
+            if let Some("opt-level") = s.split('=').next() { Some(i) } else { None }
         })
         .max();
     if max_o > max_c {
@@ -1912,7 +1906,7 @@ fn select_debuginfo(
         .into_iter()
         .flat_map(|(i, s)| {
             // NB: This can match a string without `=`.
-            if let Some("debuginfo") = s.splitn(2, '=').next() { Some(i) } else { None }
+            if let Some("debuginfo") = s.split('=').next() { Some(i) } else { None }
         })
         .max();
     if max_g > max_c {
index 7d4a1e212a41749c9606750faf6347358f43a1c4..7f926f7d8bc4a2cb2cd25871384eff142e0324a8 100644 (file)
@@ -6,9 +6,10 @@
 use crate::utils::NativeLibKind;
 use crate::Session;
 use rustc_ast as ast;
-use rustc_data_structures::sync::{self, MetadataRef};
-use rustc_hir::def_id::{CrateNum, DefId, StableCrateId, LOCAL_CRATE};
-use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
+use rustc_data_structures::sync::{self, MetadataRef, RwLock};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, StableCrateId, LOCAL_CRATE};
+use rustc_hir::definitions::{DefKey, DefPath, DefPathHash, Definitions};
+use rustc_index::vec::IndexVec;
 use rustc_span::hygiene::{ExpnHash, ExpnId};
 use rustc_span::symbol::Symbol;
 use rustc_span::Span;
@@ -217,6 +218,7 @@ pub trait MetadataLoader {
 /// during resolve)
 pub trait CrateStore: std::fmt::Debug {
     fn as_any(&self) -> &dyn Any;
+    fn untracked_as_any(&mut self) -> &mut dyn Any;
 
     // Foreign definitions.
     // This information is safe to access, since it's hashed as part of the DefPathHash, which incr.
@@ -249,3 +251,11 @@ fn expn_hash_to_expn_id(
 }
 
 pub type CrateStoreDyn = dyn CrateStore + sync::Sync;
+
+#[derive(Debug)]
+pub struct Untracked {
+    pub cstore: Box<CrateStoreDyn>,
+    /// Reference span for definitions.
+    pub source_span: IndexVec<LocalDefId, Span>,
+    pub definitions: RwLock<Definitions>,
+}
index 8cb9e1a6f1ae81462eb65293fb736409083ddef2..e72b76cfee9e9660a427746e2cadd14cb0ef711c 100644 (file)
@@ -115,6 +115,10 @@ pub struct StackProtectorNotSupportedForTarget<'a> {
     pub target_triple: &'a TargetTriple,
 }
 
+#[derive(Diagnostic)]
+#[diag(session_branch_protection_requires_aarch64)]
+pub(crate) struct BranchProtectionRequiresAArch64;
+
 #[derive(Diagnostic)]
 #[diag(session_split_debuginfo_unstable_platform)]
 pub struct SplitDebugInfoUnstablePlatform {
@@ -129,10 +133,10 @@ pub struct FileIsNotWriteable<'a> {
 
 #[derive(Diagnostic)]
 #[diag(session_crate_name_does_not_match)]
-pub struct CrateNameDoesNotMatch<'a> {
+pub struct CrateNameDoesNotMatch {
     #[primary_span]
     pub span: Span,
-    pub s: &'a str,
+    pub s: Symbol,
     pub name: Symbol,
 }
 
@@ -151,11 +155,11 @@ pub struct CrateNameEmpty {
 
 #[derive(Diagnostic)]
 #[diag(session_invalid_character_in_create_name)]
-pub struct InvalidCharacterInCrateName<'a> {
+pub struct InvalidCharacterInCrateName {
     #[primary_span]
     pub span: Option<Span>,
     pub character: char,
-    pub crate_name: &'a str,
+    pub crate_name: Symbol,
 }
 
 #[derive(Subdiagnostic)]
@@ -176,7 +180,7 @@ pub fn surrounding(s: Span) -> Self {
 #[derive(Diagnostic)]
 #[diag(session_skipping_const_checks)]
 pub struct SkippingConstChecks {
-    #[subdiagnostic(eager)]
+    #[subdiagnostic]
     pub unleashed_features: Vec<UnleashedFeatureHelp>,
 }
 
@@ -291,20 +295,33 @@ fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool {
         s.len() > 1 && s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit())
     }
 
-    // Try to lowercase the prefix if it's a valid base prefix.
-    fn fix_base_capitalisation(s: &str) -> Option<String> {
-        if let Some(stripped) = s.strip_prefix('B') {
-            Some(format!("0b{stripped}"))
-        } else if let Some(stripped) = s.strip_prefix('O') {
-            Some(format!("0o{stripped}"))
-        } else if let Some(stripped) = s.strip_prefix('X') {
-            Some(format!("0x{stripped}"))
+    // Try to lowercase the prefix if the prefix and suffix are valid.
+    fn fix_base_capitalisation(prefix: &str, suffix: &str) -> Option<String> {
+        let mut chars = suffix.chars();
+
+        let base_char = chars.next().unwrap();
+        let base = match base_char {
+            'B' => 2,
+            'O' => 8,
+            'X' => 16,
+            _ => return None,
+        };
+
+        // check that the suffix contains only base-appropriate characters
+        let valid = prefix == "0"
+            && chars
+                .filter(|c| *c != '_')
+                .take_while(|c| *c != 'i' && *c != 'u')
+                .all(|c| c.to_digit(base).is_some());
+
+        if valid {
+            Some(format!("0{}{}", base_char.to_ascii_lowercase(), &suffix[1..]))
         } else {
             None
         }
     }
 
-    let token::Lit { kind, suffix, .. } = lit;
+    let token::Lit { kind, symbol, suffix, .. } = lit;
     match err {
         // `LexerError` is an error, but it was already reported
         // by lexer, so here we don't report it the second time.
@@ -320,7 +337,7 @@ fn fix_base_capitalisation(s: &str) -> Option<String> {
             if looks_like_width_suffix(&['i', 'u'], suf) {
                 // If it looks like a width, try to be helpful.
                 sess.emit_err(InvalidIntLiteralWidth { span, width: suf[1..].into() });
-            } else if let Some(fixed) = fix_base_capitalisation(suf) {
+            } else if let Some(fixed) = fix_base_capitalisation(symbol.as_str(), suf) {
                 sess.emit_err(InvalidNumLiteralBasePrefix { span, fixed });
             } else {
                 sess.emit_err(InvalidNumLiteralSuffix { span, suffix: suf.to_string() });
index 1b66773be6f0804a02627989199547c8c6616769..1855a49c1ecdf36b331a92e362feaa3f54eec1d5 100644 (file)
@@ -3,7 +3,6 @@
 use smallvec::{smallvec, SmallVec};
 use std::env;
 use std::fs;
-use std::iter::FromIterator;
 use std::path::{Path, PathBuf};
 
 use crate::search_paths::{PathKind, SearchPath};
index 8e9198b79dff7cb39284333ad0f1fe6f53e27d78..9e130287104f9b1edd38a3d47e3dc11701c14e7f 100644 (file)
@@ -368,7 +368,7 @@ mod desc {
     pub const parse_opt_panic_strategy: &str = parse_panic_strategy;
     pub const parse_oom_strategy: &str = "either `panic` or `abort`";
     pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`";
-    pub const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `hwaddress`, `leak`, `memory`, `memtag`, `shadow-call-stack`, or `thread`";
+    pub const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `hwaddress`, `kcfi`, `leak`, `memory`, `memtag`, `shadow-call-stack`, or `thread`";
     pub const parse_sanitizer_memory_track_origins: &str = "0, 1, or 2";
     pub const parse_cfguard: &str =
         "either a boolean (`yes`, `no`, `on`, `off`, etc), `checks`, or `nochecks`";
@@ -675,6 +675,7 @@ pub(crate) fn parse_sanitizers(slot: &mut SanitizerSet, v: Option<&str>) -> bool
                 *slot |= match s {
                     "address" => SanitizerSet::ADDRESS,
                     "cfi" => SanitizerSet::CFI,
+                    "kcfi" => SanitizerSet::KCFI,
                     "leak" => SanitizerSet::LEAK,
                     "memory" => SanitizerSet::MEMORY,
                     "memtag" => SanitizerSet::MEMTAG,
@@ -1293,6 +1294,9 @@ pub(crate) fn parse_proc_macro_execution_strategy(
         computed `block` spans (one span encompassing a block's terminator and \
         all statements). If `-Z instrument-coverage` is also enabled, create \
         an additional `.html` file showing the computed coverage spans."),
+    dump_mono_stats: SwitchWithOptPath = (SwitchWithOptPath::Disabled,
+        parse_switch_with_opt_path, [UNTRACKED],
+        "output statistics about monomorphization collection (format: markdown)"),
     dwarf_version: Option<u32> = (None, parse_opt_number, [TRACKED],
         "version of DWARF debug information to emit (default: 2 or 4, depending on platform)"),
     dylib_lto: bool = (false, parse_bool, [UNTRACKED],
index 2511bee46afebef62d59842f74d192194346a3af..8ee3057de625ef3b08c9faad46c824ae9c685130 100644 (file)
@@ -7,14 +7,14 @@
 use crate::Session;
 use rustc_ast as ast;
 use rustc_span::symbol::sym;
-use rustc_span::Span;
+use rustc_span::{Span, Symbol};
 use std::path::{Path, PathBuf};
 
 pub fn out_filename(
     sess: &Session,
     crate_type: CrateType,
     outputs: &OutputFilenames,
-    crate_name: &str,
+    crate_name: Symbol,
 ) -> PathBuf {
     let default_filename = filename_for_input(sess, crate_type, crate_name, outputs);
     let out_filename = outputs
@@ -45,9 +45,9 @@ fn is_writeable(p: &Path) -> bool {
     }
 }
 
-pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute], input: &Input) -> String {
-    let validate = |s: String, span: Option<Span>| {
-        validate_crate_name(sess, &s, span);
+pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute], input: &Input) -> Symbol {
+    let validate = |s: Symbol, span: Option<Span>| {
+        validate_crate_name(sess, s, span);
         s
     };
 
@@ -59,38 +59,39 @@ pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute], input: &Input)
         sess.find_by_name(attrs, sym::crate_name).and_then(|at| at.value_str().map(|s| (at, s)));
 
     if let Some(ref s) = sess.opts.crate_name {
+        let s = Symbol::intern(s);
         if let Some((attr, name)) = attr_crate_name {
-            if name.as_str() != s {
+            if name != s {
                 sess.emit_err(CrateNameDoesNotMatch { span: attr.span, s, name });
             }
         }
-        return validate(s.clone(), None);
+        return validate(s, None);
     }
 
     if let Some((attr, s)) = attr_crate_name {
-        return validate(s.to_string(), Some(attr.span));
+        return validate(s, Some(attr.span));
     }
     if let Input::File(ref path) = *input {
         if let Some(s) = path.file_stem().and_then(|s| s.to_str()) {
             if s.starts_with('-') {
                 sess.emit_err(CrateNameInvalid { s });
             } else {
-                return validate(s.replace('-', "_"), None);
+                return validate(Symbol::intern(&s.replace('-', "_")), None);
             }
         }
     }
 
-    "rust_out".to_string()
+    Symbol::intern("rust_out")
 }
 
-pub fn validate_crate_name(sess: &Session, s: &str, sp: Option<Span>) {
+pub fn validate_crate_name(sess: &Session, s: Symbol, sp: Option<Span>) {
     let mut err_count = 0;
     {
         if s.is_empty() {
             err_count += 1;
             sess.emit_err(CrateNameEmpty { span: sp });
         }
-        for c in s.chars() {
+        for c in s.as_str().chars() {
             if c.is_alphanumeric() {
                 continue;
             }
@@ -109,7 +110,7 @@ pub fn validate_crate_name(sess: &Session, s: &str, sp: Option<Span>) {
 
 pub fn filename_for_metadata(
     sess: &Session,
-    crate_name: &str,
+    crate_name: Symbol,
     outputs: &OutputFilenames,
 ) -> PathBuf {
     // If the command-line specified the path, use that directly.
@@ -132,7 +133,7 @@ pub fn filename_for_metadata(
 pub fn filename_for_input(
     sess: &Session,
     crate_type: CrateType,
-    crate_name: &str,
+    crate_name: Symbol,
     outputs: &OutputFilenames,
 ) -> PathBuf {
     let libname = format!("{}{}", crate_name, sess.opts.cg.extra_filename);
index e99e460913ef0f8799cd5d9412b59e11b8619ff6..01a9b1000882bd5c77a20b64a697a57ea409d260 100644 (file)
@@ -3,10 +3,10 @@
 pub use crate::code_stats::{DataTypeKind, FieldInfo, SizeKind, VariantInfo};
 use crate::config::{self, CrateType, InstrumentCoverage, OptLevel, OutputType, SwitchWithOptPath};
 use crate::errors::{
-    CannotEnableCrtStaticLinux, CannotMixAndMatchSanitizers, LinkerPluginToWindowsNotSupported,
-    NotCircumventFeature, ProfileSampleUseFileDoesNotExist, ProfileUseFileDoesNotExist,
-    SanitizerCfiEnabled, SanitizerNotSupported, SanitizersNotSupported, SkippingConstChecks,
-    SplitDebugInfoUnstablePlatform, StackProtectorNotSupportedForTarget,
+    BranchProtectionRequiresAArch64, CannotEnableCrtStaticLinux, CannotMixAndMatchSanitizers,
+    LinkerPluginToWindowsNotSupported, NotCircumventFeature, ProfileSampleUseFileDoesNotExist,
+    ProfileUseFileDoesNotExist, SanitizerCfiEnabled, SanitizerNotSupported, SanitizersNotSupported,
+    SkippingConstChecks, SplitDebugInfoUnstablePlatform, StackProtectorNotSupportedForTarget,
     TargetRequiresUnwindTables, UnleashedFeatureHelp, UnstableVirtualFunctionElimination,
     UnsupportedDwarfVersion,
 };
@@ -686,6 +686,10 @@ pub fn is_sanitizer_cfi_enabled(&self) -> bool {
         self.opts.unstable_opts.sanitizer.contains(SanitizerSet::CFI)
     }
 
+    pub fn is_sanitizer_kcfi_enabled(&self) -> bool {
+        self.opts.unstable_opts.sanitizer.contains(SanitizerSet::KCFI)
+    }
+
     /// Check whether this compile session and crate type use static crt.
     pub fn crt_static(&self, crate_type: Option<CrateType>) -> bool {
         if !self.target.crt_static_respected {
@@ -952,6 +956,17 @@ pub fn first_attr_value_str_by_name(
     ) -> Option<Symbol> {
         attrs.iter().find(|at| at.has_name(name)).and_then(|at| at.value_str())
     }
+
+    pub fn diagnostic_width(&self) -> usize {
+        let default_column_width = 140;
+        if let Some(width) = self.opts.diagnostic_width {
+            width
+        } else if self.opts.unstable_opts.ui_testing {
+            default_column_width
+        } else {
+            termize::dimensions().map_or(default_column_width, |(w, _)| w)
+        }
+    }
 }
 
 // JUSTIFICATION: defn of the suggested wrapper fns
@@ -1308,7 +1323,7 @@ pub fn build_session(
     let warnings_allow = sopts
         .lint_opts
         .iter()
-        .rfind(|&&(ref key, _)| *key == "warnings")
+        .rfind(|&(key, _)| *key == "warnings")
         .map_or(false, |&(_, level)| level == lint::Allow);
     let cap_lints_allow = sopts.lint_cap.map_or(false, |cap| cap == lint::Allow);
     let can_emit_warnings = !(warnings_allow || cap_lints_allow);
@@ -1533,6 +1548,14 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
         }
     }
 
+    // LLVM CFI and KCFI are mutually exclusive
+    if sess.is_sanitizer_cfi_enabled() && sess.is_sanitizer_kcfi_enabled() {
+        sess.emit_err(CannotMixAndMatchSanitizers {
+            first: "cfi".to_string(),
+            second: "kcfi".to_string(),
+        });
+    }
+
     if sess.opts.unstable_opts.stack_protector != StackProtector::None {
         if !sess.target.options.supports_stack_protector {
             sess.emit_warning(StackProtectorNotSupportedForTarget {
@@ -1542,6 +1565,10 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
         }
     }
 
+    if sess.opts.unstable_opts.branch_protection.is_some() && sess.target.arch != "aarch64" {
+        sess.emit_err(BranchProtectionRequiresAArch64);
+    }
+
     if let Some(dwarf_version) = sess.opts.unstable_opts.dwarf_version {
         if dwarf_version > 5 {
             sess.emit_err(UnsupportedDwarfVersion { dwarf_version });
index d3c2c5113bcdec663f1b00fb9d873d316d7bccae..26cd54210d0bbb9c33134c7876269f4f7a336006 100644 (file)
@@ -175,7 +175,7 @@ unsafe fn analyze_source_file_sse2(src: &str,
             // There might still be a tail left to analyze
             let tail_start = chunk_count * CHUNK_SIZE + intra_chunk_offset;
             if tail_start < src.len() {
-                analyze_source_file_generic(&src[tail_start as usize ..],
+                analyze_source_file_generic(&src[tail_start ..],
                                         src.len() - tail_start,
                                         output_offset + BytePos::from_usize(tail_start),
                                         lines,
@@ -219,7 +219,7 @@ fn analyze_source_file_generic(
     while i < scan_len {
         let byte = unsafe {
             // We verified that i < scan_len <= src.len()
-            *src_bytes.get_unchecked(i as usize)
+            *src_bytes.get_unchecked(i)
         };
 
         // How much to advance in order to get to the next UTF-8 char in the
index 0ad1f1a0da72fb63441861d253f918f7a51987f6..e62ce2c266aa04ca507edd377ab92672d193a336 100644 (file)
@@ -1,4 +1,4 @@
-use crate::HashStableContext;
+use crate::{HashStableContext, Symbol};
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
 use rustc_data_structures::AtomicRef;
@@ -149,9 +149,11 @@ pub fn to_u64(self) -> u64 {
 
     /// Computes the stable ID for a crate with the given name and
     /// `-Cmetadata` arguments.
-    pub fn new(crate_name: &str, is_exe: bool, mut metadata: Vec<String>) -> StableCrateId {
+    pub fn new(crate_name: Symbol, is_exe: bool, mut metadata: Vec<String>) -> StableCrateId {
         let mut hasher = StableHasher::new();
-        crate_name.hash(&mut hasher);
+        // We must hash the string text of the crate name, not the id, as the id is not stable
+        // across builds.
+        crate_name.as_str().hash(&mut hasher);
 
         // We don't want the stable crate ID to depend on the order of
         // -C metadata arguments, so sort them:
index cef4c6f79cefd9d813824284f5d2886d973f0b86..2181c090027b535819aec1eb8afeb1851c0f4841 100644 (file)
@@ -259,6 +259,10 @@ pub fn to_string_lossy(&self, display_pref: FileNameDisplayPreference) -> Cow<'_
             FileNameDisplayPreference::Remapped => {
                 self.remapped_path_if_available().to_string_lossy()
             }
+            FileNameDisplayPreference::Short => self
+                .local_path_if_available()
+                .file_name()
+                .map_or_else(|| "".into(), |f| f.to_string_lossy()),
         }
     }
 }
@@ -302,6 +306,9 @@ pub enum FileNameDisplayPreference {
     /// Display the path before the application of rewrite rules provided via `--remap-path-prefix`.
     /// This is appropriate for use in user-facing output (such as diagnostics).
     Local,
+    /// Display only the filename, as a way to reduce the verbosity of the output.
+    /// This is appropriate for use in user-facing output (such as diagnostics).
+    Short,
 }
 
 pub struct FileNameDisplay<'a> {
@@ -491,6 +498,10 @@ pub fn with_parent(&self, parent: Option<LocalDefId>) -> Span {
     pub fn is_dummy(self) -> bool {
         self.lo.0 == 0 && self.hi.0 == 0
     }
+    #[inline]
+    pub fn is_visible(self, sm: &SourceMap) -> bool {
+        !self.is_dummy() && sm.is_span_accessible(self.span())
+    }
     /// Returns `true` if `self` fully encloses `other`.
     pub fn contains(self, other: Self) -> bool {
         self.lo <= other.lo && other.hi <= self.hi
@@ -556,6 +567,11 @@ pub fn is_dummy(self) -> bool {
         self.data_untracked().is_dummy()
     }
 
+    #[inline]
+    pub fn is_visible(self, sm: &SourceMap) -> bool {
+        self.data_untracked().is_visible(sm)
+    }
+
     /// Returns `true` if this span comes from any kind of macro, desugaring or inlining.
     #[inline]
     pub fn from_expansion(self) -> bool {
@@ -1372,7 +1388,7 @@ fn encode(&self, s: &mut S) {
                     4 => {
                         raw_diffs = Vec::with_capacity(bytes_per_diff * num_diffs);
                         for diff in diff_iter {
-                            raw_diffs.extend_from_slice(&(diff.0 as u32).to_le_bytes());
+                            raw_diffs.extend_from_slice(&(diff.0).to_le_bytes());
                         }
                     }
                     _ => unreachable!(),
index 2ae57d9e56d7c5ce3ec0ff45c06bb8986fe231c2..d9c87ac0ba82bfb6ecb0c9b3991dc6dee752ea44 100644 (file)
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::StableHasher;
 use rustc_data_structures::sync::{AtomicU32, Lrc, MappedReadGuard, ReadGuard, RwLock};
+use std::cmp;
 use std::hash::Hash;
 use std::path::{Path, PathBuf};
 use std::sync::atomic::Ordering;
-use std::{clone::Clone, cmp};
-use std::{convert::TryFrom, unreachable};
 
 use std::fs;
 use std::io;
@@ -439,7 +438,11 @@ pub fn lookup_line(&self, pos: BytePos) -> Result<SourceFileAndLine, Lrc<SourceF
         }
     }
 
-    fn span_to_string(&self, sp: Span, filename_display_pref: FileNameDisplayPreference) -> String {
+    pub fn span_to_string(
+        &self,
+        sp: Span,
+        filename_display_pref: FileNameDisplayPreference,
+    ) -> String {
         if self.files.borrow().source_files.is_empty() || sp.is_dummy() {
             return "no-location".to_string();
         }
@@ -447,12 +450,15 @@ fn span_to_string(&self, sp: Span, filename_display_pref: FileNameDisplayPrefere
         let lo = self.lookup_char_pos(sp.lo());
         let hi = self.lookup_char_pos(sp.hi());
         format!(
-            "{}:{}:{}: {}:{}",
+            "{}:{}:{}{}",
             lo.file.name.display(filename_display_pref),
             lo.line,
             lo.col.to_usize() + 1,
-            hi.line,
-            hi.col.to_usize() + 1,
+            if let FileNameDisplayPreference::Short = filename_display_pref {
+                String::new()
+            } else {
+                format!(": {}:{}", hi.line, hi.col.to_usize() + 1)
+            }
         )
     }
 
@@ -942,7 +948,7 @@ pub fn next_point(&self, sp: Span) -> Span {
     /// Otherwise, the span reached to limit is returned.
     pub fn span_look_ahead(&self, span: Span, expect: Option<&str>, limit: Option<usize>) -> Span {
         let mut sp = span;
-        for _ in 0..limit.unwrap_or(100 as usize) {
+        for _ in 0..limit.unwrap_or(100_usize) {
             sp = self.next_point(sp);
             if let Ok(ref snippet) = self.span_to_snippet(sp) {
                 if expect.map_or(false, |es| snippet == es) {
@@ -1151,7 +1157,7 @@ fn remap_path_prefix(mapping: &[(PathBuf, PathBuf)], path: PathBuf) -> (PathBuf,
             // NOTE: We are iterating over the mapping entries from last to first
             //       because entries specified later on the command line should
             //       take precedence.
-            for &(ref from, ref to) in mapping.iter().rev() {
+            for (from, to) in mapping.iter().rev() {
                 debug!("Trying to apply {from:?} => {to:?}");
 
                 if let Ok(rest) = path.strip_prefix(from) {
index 61253845497238c664ac8116ae14f4b29be7f12f..ace095736c92fd8a1a2e2b39c91b4c08b1ed6115 100644 (file)
@@ -9,7 +9,6 @@
 use rustc_macros::HashStable_Generic;
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 
-use std::cmp::{Ord, PartialEq, PartialOrd};
 use std::fmt;
 use std::hash::{Hash, Hasher};
 use std::str;
         item_like_imports,
         iter,
         iter_repeat,
+        iterator_collect_fn,
+        kcfi,
         keyword,
         kind,
         kreg,
@@ -1710,7 +1711,8 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
-/// This is the most general way to print identifiers.
+/// The most general type to print identifiers.
+///
 /// AST pretty-printer is used as a fallback for turning AST structures into token streams for
 /// proc macros. Additionally, proc macros may stringify their input and expect it survive the
 /// stringification (especially true for proc macro derives written between Rust 1.15 and 1.30).
@@ -1973,7 +1975,6 @@ pub mod kw {
 /// For example `sym::rustfmt` or `sym::u8`.
 pub mod sym {
     use super::Symbol;
-    use std::convert::TryInto;
 
     #[doc(inline)]
     pub use super::sym_generated::*;
index 2a29ad6a9e56b9b288de35f41a85bdf7f06d847b..4e447eab02e7c9d7e9dd581355282fa6a52de6c9 100644 (file)
@@ -10,6 +10,7 @@ bitflags = "1.2.1"
 tracing = "0.1"
 punycode = "0.4.0"
 rustc-demangle = "0.1.21"
+twox-hash = "1.6.3"
 
 rustc_span = { path = "../rustc_span" }
 rustc_middle = { path = "../rustc_middle" }
index c60a2f4671d6c4d841565f9aaba8bb6f67279fa7..a59c9011ab21a4116e4452b206392781e0ab0e25 100644 (file)
@@ -216,8 +216,7 @@ fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
         match *ty.kind() {
             // Print all nominal types as paths (unlike `pretty_print_type`).
             ty::FnDef(def_id, substs)
-            | ty::Opaque(def_id, substs)
-            | ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs })
+            | ty::Alias(_, ty::AliasTy { def_id, substs, .. })
             | ty::Closure(def_id, substs)
             | ty::Generator(def_id, substs, _) => self.print_def_path(def_id, substs),
 
@@ -287,11 +286,7 @@ fn path_qualified(
         // Similar to `pretty_path_qualified`, but for the other
         // types that are printed as paths (see `print_type` above).
         match self_ty.kind() {
-            ty::FnDef(..)
-            | ty::Opaque(..)
-            | ty::Projection(_)
-            | ty::Closure(..)
-            | ty::Generator(..)
+            ty::FnDef(..) | ty::Alias(..) | ty::Closure(..) | ty::Generator(..)
                 if trait_ref.is_none() =>
             {
                 self.print_type(self_ty)
index 9228bea43f9327319d92c5c32b1360d815c92365..53983bed718922b3521462a88794d327bd5eceae 100644 (file)
@@ -3,6 +3,8 @@
 
 use rustc_middle::ty::{FnSig, Ty, TyCtxt};
 use rustc_target::abi::call::FnAbi;
+use std::hash::Hasher;
+use twox_hash::XxHash64;
 
 mod typeid_itanium_cxx_abi;
 use typeid_itanium_cxx_abi::TypeIdOptions;
@@ -16,3 +18,25 @@ pub fn typeid_for_fnabi<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>)
 pub fn typeid_for_fnsig<'tcx>(tcx: TyCtxt<'tcx>, fn_sig: &FnSig<'tcx>) -> String {
     typeid_itanium_cxx_abi::typeid_for_fnsig(tcx, fn_sig, TypeIdOptions::NO_OPTIONS)
 }
+
+/// Returns an LLVM KCFI type metadata identifier for the specified FnAbi.
+pub fn kcfi_typeid_for_fnabi<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> u32 {
+    // An LLVM KCFI type metadata identifier is a 32-bit constant produced by taking the lower half
+    // of the xxHash64 of the type metadata identifier. (See llvm/llvm-project@cff5bef.)
+    let mut hash: XxHash64 = Default::default();
+    hash.write(
+        typeid_itanium_cxx_abi::typeid_for_fnabi(tcx, fn_abi, TypeIdOptions::NO_OPTIONS).as_bytes(),
+    );
+    hash.finish() as u32
+}
+
+/// Returns an LLVM KCFI type metadata identifier for the specified FnSig.
+pub fn kcfi_typeid_for_fnsig<'tcx>(tcx: TyCtxt<'tcx>, fn_sig: &FnSig<'tcx>) -> u32 {
+    // An LLVM KCFI type metadata identifier is a 32-bit constant produced by taking the lower half
+    // of the xxHash64 of the type metadata identifier. (See llvm/llvm-project@cff5bef.)
+    let mut hash: XxHash64 = Default::default();
+    hash.write(
+        typeid_itanium_cxx_abi::typeid_for_fnsig(tcx, fn_sig, TypeIdOptions::NO_OPTIONS).as_bytes(),
+    );
+    hash.finish() as u32
+}
index 87128e0f893a263edb6a8b9a6877f697338d1da7..c9ddb084d63a12d2f5198bae6c2f19ec3493a12b 100644 (file)
@@ -240,7 +240,7 @@ fn encode_predicate<'tcx>(
             s.push_str(&encode_substs(tcx, trait_ref.substs, dict, options));
         }
         ty::ExistentialPredicate::Projection(projection) => {
-            let name = encode_ty_name(tcx, projection.item_def_id);
+            let name = encode_ty_name(tcx, projection.def_id);
             let _ = write!(s, "u{}{}", name.len(), &name);
             s.push_str(&encode_substs(tcx, projection.substs, dict, options));
             match projection.term.unpack() {
@@ -646,10 +646,9 @@ fn encode_ty<'tcx>(
         | ty::Error(..)
         | ty::GeneratorWitness(..)
         | ty::Infer(..)
-        | ty::Opaque(..)
+        | ty::Alias(..)
         | ty::Param(..)
-        | ty::Placeholder(..)
-        | ty::Projection(..) => {
+        | ty::Placeholder(..) => {
             bug!("encode_ty: unexpected `{:?}`", ty.kind());
         }
     };
@@ -799,10 +798,9 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
         | ty::Error(..)
         | ty::GeneratorWitness(..)
         | ty::Infer(..)
-        | ty::Opaque(..)
+        | ty::Alias(..)
         | ty::Param(..)
-        | ty::Placeholder(..)
-        | ty::Projection(..) => {
+        | ty::Placeholder(..) => {
             bug!("transform_ty: unexpected `{:?}`", ty.kind());
         }
     }
index 2cca480f271c73331046c25302e291f9e26e58ad..4285aa62cb96307991169be15b067839e36c2686 100644 (file)
@@ -439,8 +439,7 @@ fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
             // Mangle all nominal types as paths.
             ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did: def_id, .. }, _)), substs)
             | ty::FnDef(def_id, substs)
-            | ty::Opaque(def_id, substs)
-            | ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs })
+            | ty::Alias(_, ty::AliasTy { def_id, substs, .. })
             | ty::Closure(def_id, substs)
             | ty::Generator(def_id, substs, _) => {
                 self = self.print_def_path(def_id, substs)?;
@@ -544,7 +543,7 @@ fn print_dyn_existential(
                         cx = cx.print_def_path(trait_ref.def_id, trait_ref.substs)?;
                     }
                     ty::ExistentialPredicate::Projection(projection) => {
-                        let name = cx.tcx.associated_item(projection.item_def_id).name;
+                        let name = cx.tcx.associated_item(projection.def_id).name;
                         cx.push("p");
                         cx.push_ident(name.as_str());
                         cx = match projection.term.unpack() {
index b69a0a645a415913909e0dd127bff1485cfbb770..dc2cc23ffb1e40c61448af0651d18615c59eb8c9 100644 (file)
@@ -18,7 +18,6 @@
 #![deny(rustc::untranslatable_diagnostic)]
 #![deny(rustc::diagnostic_outside_of_impl)]
 
-use std::iter::FromIterator;
 use std::path::{Path, PathBuf};
 
 #[macro_use]
index 4ae6d4120c9958978820a67141fdf7ef8edfd923..aca52e1478eb8ac44fd5294ac34a65422d27ec73 100644 (file)
@@ -6,13 +6,16 @@
 //
 // For example, `-C target-cpu=cortex-a53`.
 
-use super::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
+use super::{
+    Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, SanitizerSet, Target, TargetOptions,
+};
 
 pub fn target() -> Target {
     let opts = TargetOptions {
         linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
         linker: Some("rust-lld".into()),
         features: "+strict-align,+neon,+fp-armv8".into(),
+        supported_sanitizers: SanitizerSet::KCFI,
         relocation_model: RelocModel::Static,
         disable_redzone: true,
         max_atomic_width: Some(128),
index 7f8160b5dec62d7ce4ed0b5a4ff5113cfb4da9ac..44644c4733e8726b33c886394631744352af4a04 100644 (file)
@@ -81,7 +81,7 @@ fn pre_link_args(os: &'static str, arch: Arch, abi: &'static str) -> LinkArgs {
         _ => os.into(),
     };
 
-    let platform_version: StaticCow<str> = match os.as_ref() {
+    let platform_version: StaticCow<str> = match os {
         "ios" => ios_lld_platform_version(),
         "tvos" => tvos_lld_platform_version(),
         "watchos" => watchos_lld_platform_version(),
@@ -204,7 +204,7 @@ pub fn macos_llvm_target(arch: Arch) -> String {
 fn link_env_remove(arch: Arch, os: &'static str) -> StaticCow<[StaticCow<str>]> {
     // Apple platforms only officially support macOS as a host for any compilation.
     //
-    // If building for macOS, we go ahead and remove any erronous environment state
+    // If building for macOS, we go ahead and remove any erroneous environment state
     // that's only applicable to cross-OS compilation. Always leave anything for the
     // host OS alone though.
     if os == "macos" {
index d05b8aa420067a9b4f8d1a66aa1650ce924f0216..be994eda14c004aecca3d9e0c7e3e5bf7d8f5eb0 100644 (file)
@@ -45,9 +45,7 @@
 use serde_json::Value;
 use std::borrow::Cow;
 use std::collections::BTreeMap;
-use std::convert::TryFrom;
 use std::hash::{Hash, Hasher};
-use std::iter::FromIterator;
 use std::ops::{Deref, DerefMut};
 use std::path::{Path, PathBuf};
 use std::str::FromStr;
@@ -804,7 +802,7 @@ fn to_json(&self) -> Json {
 
 bitflags::bitflags! {
     #[derive(Default, Encodable, Decodable)]
-    pub struct SanitizerSet: u8 {
+    pub struct SanitizerSet: u16 {
         const ADDRESS = 1 << 0;
         const LEAK    = 1 << 1;
         const MEMORY  = 1 << 2;
@@ -813,6 +811,7 @@ pub struct SanitizerSet: u8 {
         const CFI     = 1 << 5;
         const MEMTAG  = 1 << 6;
         const SHADOWCALLSTACK = 1 << 7;
+        const KCFI    = 1 << 8;
     }
 }
 
@@ -824,6 +823,7 @@ pub fn as_str(self) -> Option<&'static str> {
         Some(match self {
             SanitizerSet::ADDRESS => "address",
             SanitizerSet::CFI => "cfi",
+            SanitizerSet::KCFI => "kcfi",
             SanitizerSet::LEAK => "leak",
             SanitizerSet::MEMORY => "memory",
             SanitizerSet::MEMTAG => "memtag",
@@ -859,6 +859,7 @@ fn into_iter(self) -> Self::IntoIter {
         [
             SanitizerSet::ADDRESS,
             SanitizerSet::CFI,
+            SanitizerSet::KCFI,
             SanitizerSet::LEAK,
             SanitizerSet::MEMORY,
             SanitizerSet::MEMTAG,
@@ -2327,6 +2328,7 @@ macro_rules! key {
                             base.$key_name |= match s.as_str() {
                                 Some("address") => SanitizerSet::ADDRESS,
                                 Some("cfi") => SanitizerSet::CFI,
+                                Some("kcfi") => SanitizerSet::KCFI,
                                 Some("leak") => SanitizerSet::LEAK,
                                 Some("memory") => SanitizerSet::MEMORY,
                                 Some("memtag") => SanitizerSet::MEMTAG,
index e3eb9bccd5ed78d5001471c83cec143a3586d02c..34934379c7e84a468abfe4995612c6bbb80aa579 100644 (file)
@@ -5,12 +5,7 @@ pub fn target() -> Target {
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(
         LinkerFlavor::Unix(Cc::No),
-        &[
-            "-b64".into(),
-            "-bpT:0x100000000".into(),
-            "-bpD:0x110000000".into(),
-            "-bcdtors:all:0:s".into(),
-        ],
+        &["-b64", "-bpT:0x100000000", "-bpD:0x110000000", "-bcdtors:all:0:s"],
     );
 
     Target {
index 8dad941b534b6a00125de8e30e7a5ad8b01fd753..06529c2e4039d768b198ecac3558adaf95cda447 100644 (file)
@@ -33,12 +33,6 @@ pub fn target() -> Target {
             // For now this target just never has an entry symbol no matter the output
             // type, so unconditionally pass this.
             "--no-entry",
-            // Rust really needs a way for users to specify exports and imports in
-            // the source code. --export-dynamic isn't the right tool for this job,
-            // however it does have the side effect of automatically exporting a lot
-            // of symbols, which approximates what people want when compiling for
-            // wasm32-unknown-unknown expect, so use it for now.
-            "--export-dynamic",
         ],
     );
     options.add_pre_link_args(
@@ -48,7 +42,6 @@ pub fn target() -> Target {
             // otherwise
             "--target=wasm32-unknown-unknown",
             "-Wl,--no-entry",
-            "-Wl,--export-dynamic",
         ],
     );
 
index 6f0bbf0672d449d555a32beae5bad63e1b0bfe96..a0476d542e6424a1fb3ba2593dd88c3fcc406cf4 100644 (file)
@@ -104,6 +104,10 @@ pub fn target() -> Target {
     // `args::args()` makes the WASI API calls itself.
     options.main_needs_argc_argv = false;
 
+    // And, WASI mangles the name of "main" to distinguish between different
+    // signatures.
+    options.entry_name = "__main_void".into();
+
     Target {
         llvm_target: "wasm32-wasi".into(),
         pointer_width: 32,
index e4d33c2b8c62d9fee2f58a716a601d254435d5a6..32060c35c11b835da211d0dee16e652294082cd8 100644 (file)
@@ -5,7 +5,7 @@
 // features.
 
 use super::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy};
-use super::{RelroLevel, StackProbeType, Target, TargetOptions};
+use super::{RelroLevel, SanitizerSet, StackProbeType, Target, TargetOptions};
 
 pub fn target() -> Target {
     let opts = TargetOptions {
@@ -20,6 +20,7 @@ pub fn target() -> Target {
         features:
             "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float"
                 .into(),
+        supported_sanitizers: SanitizerSet::KCFI,
         disable_redzone: true,
         panic_strategy: PanicStrategy::Abort,
         code_model: Some(CodeModel::Kernel),
index 8e04da4f9be2479aa584270611a9607279b495d8..aef2f8ff9911cc90b565bf27c02d946d0ffcd766 100644 (file)
@@ -579,14 +579,14 @@ fn is_param_no_infer(&self, substs: SubstsRef<'_>) -> bool {
     pub fn is_of_param(&self, ty: Ty<'_>) -> bool {
         match ty.kind() {
             ty::Param(_) => true,
-            ty::Projection(p) => self.is_of_param(p.self_ty()),
+            ty::Alias(ty::Projection, p) => self.is_of_param(p.self_ty()),
             _ => false,
         }
     }
 
     fn is_self_referential_projection(&self, p: ty::PolyProjectionPredicate<'_>) -> bool {
         if let Some(ty) = p.term().skip_binder().ty() {
-            matches!(ty.kind(), ty::Projection(proj) if proj == &p.skip_binder().projection_ty)
+            matches!(ty.kind(), ty::Alias(ty::Projection, proj) if proj == &p.skip_binder().projection_ty)
         } else {
             false
         }
diff --git a/compiler/rustc_trait_selection/src/traits/codegen.rs b/compiler/rustc_trait_selection/src/traits/codegen.rs
deleted file mode 100644 (file)
index 0102d26..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-// This file contains various trait resolution methods used by codegen.
-// They all assume regions can be erased and monomorphic types.  It
-// seems likely that they should eventually be merged into more
-// general routines.
-
-use crate::infer::{DefiningAnchor, TyCtxtInferExt};
-use crate::traits::error_reporting::TypeErrCtxtExt;
-use crate::traits::{
-    ImplSource, Obligation, ObligationCause, SelectionContext, TraitEngine, TraitEngineExt,
-    Unimplemented,
-};
-use rustc_infer::traits::FulfillmentErrorCode;
-use rustc_middle::traits::CodegenObligationError;
-use rustc_middle::ty::{self, TyCtxt};
-
-/// Attempts to resolve an obligation to an `ImplSource`. The result is
-/// a shallow `ImplSource` resolution, meaning that we do not
-/// (necessarily) resolve all nested obligations on the impl. Note
-/// that type check should guarantee to us that all nested
-/// obligations *could be* resolved if we wanted to.
-///
-/// This also expects that `trait_ref` is fully normalized.
-pub fn codegen_select_candidate<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    (param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>),
-) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> {
-    // We expect the input to be fully normalized.
-    debug_assert_eq!(trait_ref, tcx.normalize_erasing_regions(param_env, trait_ref));
-
-    // Do the initial selection for the obligation. This yields the
-    // shallow result we are looking for -- that is, what specific impl.
-    let infcx = tcx
-        .infer_ctxt()
-        .ignoring_regions()
-        .with_opaque_type_inference(DefiningAnchor::Bubble)
-        .build();
-    //~^ HACK `Bubble` is required for
-    // this test to pass: type-alias-impl-trait/assoc-projection-ice.rs
-    let mut selcx = SelectionContext::new(&infcx);
-
-    let obligation_cause = ObligationCause::dummy();
-    let obligation = Obligation::new(tcx, obligation_cause, param_env, trait_ref);
-
-    let selection = match selcx.select(&obligation) {
-        Ok(Some(selection)) => selection,
-        Ok(None) => return Err(CodegenObligationError::Ambiguity),
-        Err(Unimplemented) => return Err(CodegenObligationError::Unimplemented),
-        Err(e) => {
-            bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref)
-        }
-    };
-
-    debug!(?selection);
-
-    // Currently, we use a fulfillment context to completely resolve
-    // all nested obligations. This is because they can inform the
-    // inference of the impl's type parameters.
-    let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(tcx);
-    let impl_source = selection.map(|predicate| {
-        fulfill_cx.register_predicate_obligation(&infcx, predicate);
-    });
-
-    // In principle, we only need to do this so long as `impl_source`
-    // contains unbound type parameters. It could be a slight
-    // optimization to stop iterating early.
-    let errors = fulfill_cx.select_all_or_error(&infcx);
-    if !errors.is_empty() {
-        // `rustc_monomorphize::collector` assumes there are no type errors.
-        // Cycle errors are the only post-monomorphization errors possible; emit them now so
-        // `rustc_ty_utils::resolve_associated_item` doesn't return `None` post-monomorphization.
-        for err in errors {
-            if let FulfillmentErrorCode::CodeCycle(cycle) = err.code {
-                infcx.err_ctxt().report_overflow_obligation_cycle(&cycle);
-            }
-        }
-        return Err(CodegenObligationError::FulfillmentError);
-    }
-
-    let impl_source = infcx.resolve_vars_if_possible(impl_source);
-    let impl_source = infcx.tcx.erase_regions(impl_source);
-
-    // Opaque types may have gotten their hidden types constrained, but we can ignore them safely
-    // as they will get constrained elsewhere, too.
-    // (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();
-
-    Ok(&*tcx.arena.alloc(impl_source))
-}
index 899e30275a05296eb2de1958b29b41286f3f51d0..7c569621cfeb85ab3b64cd2c2bc05c3b045180f5 100644 (file)
@@ -659,7 +659,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
             | ty::RawPtr(..)
             | ty::Never
             | ty::Tuple(..)
-            | ty::Projection(..) => self.found_non_local_ty(ty),
+            | ty::Alias(ty::Projection, ..) => self.found_non_local_ty(ty),
 
             ty::Param(..) => self.found_param_ty(ty),
 
@@ -704,7 +704,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
                 );
                 ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty))
             }
-            ty::Opaque(..) => {
+            ty::Alias(ty::Opaque, ..) => {
                 // This merits some explanation.
                 // Normally, opaque types are not involved when performing
                 // coherence checking, since it is illegal to directly
index 7cc0999478a3eddf3aeff66d0c868647ba38cf9d..7c9fde27420bc2b12ba79a6d08083b507dc2b8ec 100644 (file)
@@ -30,7 +30,7 @@ pub fn is_const_evaluatable<'tcx>(
     span: Span,
 ) -> Result<(), NotConstEvaluatable> {
     let tcx = infcx.tcx;
-    match unexpanded_ct.kind() {
+    match tcx.expand_abstract_consts(unexpanded_ct).kind() {
         ty::ConstKind::Unevaluated(_) | ty::ConstKind::Expr(_) => (),
         ty::ConstKind::Param(_)
         | ty::ConstKind::Bound(_, _)
index 752b53fbc3f9a2011c5cfa90afc2e32d2fbfb8b0..0c1717cff332c40e79bede7a633994be3c054155 100644 (file)
 use rustc_hir::def_id::DefId;
-use rustc_infer::infer::InferCtxt;
+use rustc_infer::infer::{InferCtxt, LateBoundRegionConversionTime};
+use rustc_infer::traits::util::elaborate_predicates_with_span;
 use rustc_infer::traits::{Obligation, ObligationCause, TraitObligation};
-use rustc_span::DUMMY_SP;
+use rustc_middle::ty;
+use rustc_span::{Span, DUMMY_SP};
 
 use crate::traits::ObligationCtxt;
 
+pub enum Ambiguity {
+    DefId(DefId),
+    ParamEnv(Span),
+}
+
 pub fn recompute_applicable_impls<'tcx>(
     infcx: &InferCtxt<'tcx>,
     obligation: &TraitObligation<'tcx>,
-) -> Vec<DefId> {
+) -> Vec<Ambiguity> {
     let tcx = infcx.tcx;
     let param_env = obligation.param_env;
-    let dummy_cause = ObligationCause::dummy();
+
     let impl_may_apply = |impl_def_id| {
         let ocx = ObligationCtxt::new_in_snapshot(infcx);
         let placeholder_obligation =
             infcx.replace_bound_vars_with_placeholders(obligation.predicate);
         let obligation_trait_ref =
-            ocx.normalize(&dummy_cause, param_env, placeholder_obligation.trait_ref);
+            ocx.normalize(&ObligationCause::dummy(), param_env, placeholder_obligation.trait_ref);
 
         let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
         let impl_trait_ref = tcx.bound_impl_trait_ref(impl_def_id).unwrap().subst(tcx, impl_substs);
         let impl_trait_ref = ocx.normalize(&ObligationCause::dummy(), param_env, impl_trait_ref);
 
-        if let Err(_) = ocx.eq(&dummy_cause, param_env, obligation_trait_ref, impl_trait_ref) {
+        if let Err(_) =
+            ocx.eq(&ObligationCause::dummy(), param_env, obligation_trait_ref, impl_trait_ref)
+        {
             return false;
         }
 
         let impl_predicates = tcx.predicates_of(impl_def_id).instantiate(tcx, impl_substs);
-        ocx.register_obligations(
-            impl_predicates
-                .predicates
-                .iter()
-                .map(|&predicate| Obligation::new(tcx, dummy_cause.clone(), param_env, predicate)),
+        ocx.register_obligations(impl_predicates.predicates.iter().map(|&predicate| {
+            Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate)
+        }));
+
+        ocx.select_where_possible().is_empty()
+    };
+
+    let param_env_candidate_may_apply = |poly_trait_predicate: ty::PolyTraitPredicate<'tcx>| {
+        let ocx = ObligationCtxt::new_in_snapshot(infcx);
+        let placeholder_obligation =
+            infcx.replace_bound_vars_with_placeholders(obligation.predicate);
+        let obligation_trait_ref =
+            ocx.normalize(&ObligationCause::dummy(), param_env, placeholder_obligation.trait_ref);
+
+        let param_env_predicate = infcx.replace_bound_vars_with_fresh_vars(
+            DUMMY_SP,
+            LateBoundRegionConversionTime::HigherRankedType,
+            poly_trait_predicate,
         );
+        let param_env_trait_ref =
+            ocx.normalize(&ObligationCause::dummy(), param_env, param_env_predicate.trait_ref);
+
+        if let Err(_) =
+            ocx.eq(&ObligationCause::dummy(), param_env, obligation_trait_ref, param_env_trait_ref)
+        {
+            return false;
+        }
 
         ocx.select_where_possible().is_empty()
     };
 
-    let mut impls = Vec::new();
+    let mut ambiguities = Vec::new();
+
     tcx.for_each_relevant_impl(
         obligation.predicate.def_id(),
         obligation.predicate.skip_binder().trait_ref.self_ty(),
         |impl_def_id| {
-            if infcx.probe(move |_snapshot| impl_may_apply(impl_def_id)) {
-                impls.push(impl_def_id)
+            if infcx.probe(|_| impl_may_apply(impl_def_id)) {
+                ambiguities.push(Ambiguity::DefId(impl_def_id))
             }
         },
     );
-    impls
+
+    let predicates =
+        tcx.predicates_of(obligation.cause.body_id.owner.to_def_id()).instantiate_identity(tcx);
+    for obligation in
+        elaborate_predicates_with_span(tcx, std::iter::zip(predicates.predicates, predicates.spans))
+    {
+        let kind = obligation.predicate.kind();
+        if let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = kind.skip_binder()
+            && param_env_candidate_may_apply(kind.rebind(trait_pred))
+        {
+            if kind.rebind(trait_pred.trait_ref) == ty::TraitRef::identity(tcx, trait_pred.def_id()) {
+                ambiguities.push(Ambiguity::ParamEnv(tcx.def_span(trait_pred.def_id())))
+            } else {
+                ambiguities.push(Ambiguity::ParamEnv(obligation.cause.span))
+            }
+        }
+    }
+
+    ambiguities
 }
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs
new file mode 100644 (file)
index 0000000..cb373d6
--- /dev/null
@@ -0,0 +1,74 @@
+use crate::infer::InferCtxt;
+
+use rustc_middle::ty::error::TypeError;
+use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
+use rustc_middle::ty::{self, Ty, TyCtxt};
+
+pub struct CollectAllMismatches<'a, 'tcx> {
+    pub infcx: &'a InferCtxt<'tcx>,
+    pub param_env: ty::ParamEnv<'tcx>,
+    pub errors: Vec<TypeError<'tcx>>,
+}
+
+impl<'a, 'tcx> TypeRelation<'tcx> for CollectAllMismatches<'a, 'tcx> {
+    fn tag(&self) -> &'static str {
+        "CollectAllMismatches"
+    }
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.infcx.tcx
+    }
+    fn intercrate(&self) -> bool {
+        false
+    }
+    fn param_env(&self) -> ty::ParamEnv<'tcx> {
+        self.param_env
+    }
+    fn a_is_expected(&self) -> bool {
+        true
+    } // irrelevant
+    fn mark_ambiguous(&mut self) {
+        bug!()
+    }
+    fn relate_with_variance<T: Relate<'tcx>>(
+        &mut self,
+        _: ty::Variance,
+        _: ty::VarianceDiagInfo<'tcx>,
+        a: T,
+        b: T,
+    ) -> RelateResult<'tcx, T> {
+        self.relate(a, b)
+    }
+    fn regions(
+        &mut self,
+        a: ty::Region<'tcx>,
+        _b: ty::Region<'tcx>,
+    ) -> RelateResult<'tcx, ty::Region<'tcx>> {
+        Ok(a)
+    }
+    fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
+        if a == b || matches!(a.kind(), ty::Infer(_)) || matches!(b.kind(), ty::Infer(_)) {
+            return Ok(a);
+        }
+        relate::super_relate_tys(self, a, b).or_else(|e| {
+            self.errors.push(e);
+            Ok(a)
+        })
+    }
+    fn consts(
+        &mut self,
+        a: ty::Const<'tcx>,
+        b: ty::Const<'tcx>,
+    ) -> RelateResult<'tcx, ty::Const<'tcx>> {
+        if a == b {
+            return Ok(a);
+        }
+        relate::super_relate_consts(self, a, b) // could do something similar here for constants!
+    }
+    fn binders<T: Relate<'tcx>>(
+        &mut self,
+        a: ty::Binder<'tcx, T>,
+        b: ty::Binder<'tcx, T>,
+    ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> {
+        Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?))
+    }
+}
index dda7b2b2fa5b0b392ce3d19f080c236152a8284e..b89f489a641ed175de351255e21fc1d1e1a8d8e9 100644 (file)
@@ -1,4 +1,5 @@
 mod ambiguity;
+pub mod method_chain;
 pub mod on_unimplemented;
 pub mod suggestions;
 
 use rustc_middle::ty::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::error::ExpectedFound;
 use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
-use rustc_middle::ty::print::{FmtPrinter, Print};
+use rustc_middle::ty::print::{with_forced_trimmed_paths, FmtPrinter, Print};
 use rustc_middle::ty::{
     self, SubtypePredicate, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable,
     TypeVisitable,
 };
 use rustc_session::Limit;
 use rustc_span::def_id::LOCAL_CRATE;
-use rustc_span::symbol::{kw, sym};
+use rustc_span::symbol::sym;
 use rustc_span::{ExpnKind, Span, DUMMY_SP};
 use std::fmt;
 use std::iter;
@@ -225,7 +226,7 @@ fn report_arg_count_mismatch(
             let arg_length = arguments.len();
             let distinct = matches!(other, &[ArgKind::Tuple(..)]);
             match (arg_length, arguments.get(0)) {
-                (1, Some(&ArgKind::Tuple(_, ref fields))) => {
+                (1, Some(ArgKind::Tuple(_, fields))) => {
                     format!("a single {}-tuple as argument", fields.len())
                 }
                 _ => format!(
@@ -536,7 +537,7 @@ fn report_overflow_obligation<T>(
             |err| {
                 self.note_obligation_cause_code(
                     err,
-                    &predicate,
+                    predicate,
                     obligation.param_env,
                     obligation.cause.code(),
                     &mut vec![],
@@ -597,6 +598,7 @@ fn report_selection_error(
                 // can get a better error message by performing HIR-based well-formedness checking.
                 if let ObligationCauseCode::WellFormed(Some(wf_loc)) =
                     root_obligation.cause.code().peel_derives()
+                    && !obligation.predicate.has_non_region_infer()
                 {
                     if let Some(cause) = self
                         .tcx
@@ -978,6 +980,7 @@ fn report_selection_error(
                                 trait_ref,
                                 obligation.cause.body_id,
                                 &mut err,
+                                true,
                             ) {
                                 // This is *almost* equivalent to
                                 // `obligation.cause.code().peel_derives()`, but it gives us the
@@ -1013,6 +1016,7 @@ fn report_selection_error(
                                         trait_ref,
                                         obligation.cause.body_id,
                                         &mut err,
+                                        true,
                                     );
                                 }
                             }
@@ -1032,7 +1036,7 @@ fn report_selection_error(
                             && self.fallback_has_occurred
                         {
                             let predicate = trait_predicate.map_bound(|trait_pred| {
-                                trait_pred.with_self_type(self.tcx, self.tcx.mk_unit())
+                                trait_pred.with_self_ty(self.tcx, self.tcx.mk_unit())
                             });
                             let unit_obligation = obligation.with(tcx, predicate);
                             if self.predicate_may_hold(&unit_obligation) {
@@ -1232,6 +1236,7 @@ fn report_selection_error(
                     _ => None,
                 };
 
+                let found_node = found_did.and_then(|did| self.tcx.hir().get_if_local(did));
                 let found_span = found_did.and_then(|did| self.tcx.hir().span_if_local(did));
 
                 if self.reported_closure_mismatch.borrow().contains(&(span, found_span)) {
@@ -1285,6 +1290,7 @@ fn report_selection_error(
                         found_trait_ref,
                         expected_trait_ref,
                         obligation.cause.code(),
+                        found_node,
                     )
                 } else {
                     let (closure_span, closure_arg_span, found) = found_did
@@ -1430,6 +1436,7 @@ fn report_similar_impl_candidates(
         trait_ref: ty::PolyTraitRef<'tcx>,
         body_id: hir::HirId,
         err: &mut Diagnostic,
+        other: bool,
     ) -> bool;
 
     /// Gets the parent trait chain start
@@ -1480,7 +1487,7 @@ fn suggest_unsized_bound_if_applicable(
     fn annotate_source_of_ambiguity(
         &self,
         err: &mut Diagnostic,
-        impls: &[DefId],
+        impls: &[ambiguity::Ambiguity],
         predicate: ty::Predicate<'tcx>,
     );
 
@@ -1586,7 +1593,7 @@ fn report_fulfillment_error(
                 {
                     self.note_obligation_cause_code(
                         &mut diag,
-                        &error.obligation.predicate,
+                        error.obligation.predicate,
                         error.obligation.param_env,
                         code,
                         &mut vec![],
@@ -1629,18 +1636,30 @@ fn report_projection_error(
                     infer::LateBoundRegionConversionTime::HigherRankedType,
                     bound_predicate.rebind(data),
                 );
-                let normalized_ty = ocx.normalize(
-                    &obligation.cause,
-                    obligation.param_env,
-                    self.tcx
-                        .mk_projection(data.projection_ty.item_def_id, data.projection_ty.substs),
-                );
+                let unnormalized_term = match data.term.unpack() {
+                    ty::TermKind::Ty(_) => self
+                        .tcx
+                        .mk_projection(data.projection_ty.def_id, data.projection_ty.substs)
+                        .into(),
+                    ty::TermKind::Const(ct) => self
+                        .tcx
+                        .mk_const(
+                            ty::UnevaluatedConst {
+                                def: ty::WithOptConstParam::unknown(data.projection_ty.def_id),
+                                substs: data.projection_ty.substs,
+                            },
+                            ct.ty(),
+                        )
+                        .into(),
+                };
+                let normalized_term =
+                    ocx.normalize(&obligation.cause, obligation.param_env, unnormalized_term);
 
                 debug!(?obligation.cause, ?obligation.param_env);
 
-                debug!(?normalized_ty, data.ty = ?data.term);
+                debug!(?normalized_term, data.ty = ?data.term);
 
-                let is_normalized_ty_expected = !matches!(
+                let is_normalized_term_expected = !matches!(
                     obligation.cause.code().peel_derives(),
                     ObligationCauseCode::ItemObligation(_)
                         | ObligationCauseCode::BindingObligation(_, _)
@@ -1649,7 +1668,6 @@ fn report_projection_error(
                         | ObligationCauseCode::ObjectCastObligation(..)
                         | ObligationCauseCode::OpaqueType
                 );
-                let expected_ty = data.term.ty().unwrap_or_else(|| self.tcx.ty_error());
 
                 // constrain inference variables a bit more to nested obligations from normalize so
                 // we can have more helpful errors.
@@ -1658,11 +1676,11 @@ fn report_projection_error(
                 if let Err(new_err) = ocx.eq_exp(
                     &obligation.cause,
                     obligation.param_env,
-                    is_normalized_ty_expected,
-                    normalized_ty,
-                    expected_ty,
+                    is_normalized_term_expected,
+                    normalized_term,
+                    data.term,
                 ) {
-                    (Some((data, is_normalized_ty_expected, normalized_ty, expected_ty)), new_err)
+                    (Some((data, is_normalized_term_expected, normalized_term, data.term)), new_err)
                 } else {
                     (None, error.err)
                 }
@@ -1671,12 +1689,8 @@ fn report_projection_error(
             };
 
             let msg = values
-                .and_then(|(predicate, _, normalized_ty, expected_ty)| {
-                    self.maybe_detailed_projection_msg(
-                        predicate,
-                        normalized_ty.into(),
-                        expected_ty.into(),
-                    )
+                .and_then(|(predicate, _, normalized_term, expected_term)| {
+                    self.maybe_detailed_projection_msg(predicate, normalized_term, expected_term)
                 })
                 .unwrap_or_else(|| format!("type mismatch resolving `{}`", predicate));
             let mut diag = struct_span_err!(self.tcx.sess, obligation.cause.span, E0271, "{msg}");
@@ -1684,10 +1698,10 @@ fn report_projection_error(
             let secondary_span = match predicate.kind().skip_binder() {
                 ty::PredicateKind::Clause(ty::Clause::Projection(proj)) => self
                     .tcx
-                    .opt_associated_item(proj.projection_ty.item_def_id)
+                    .opt_associated_item(proj.projection_ty.def_id)
                     .and_then(|trait_assoc_item| {
                         self.tcx
-                            .trait_of_item(proj.projection_ty.item_def_id)
+                            .trait_of_item(proj.projection_ty.def_id)
                             .map(|id| (trait_assoc_item, id))
                     })
                     .and_then(|(trait_assoc_item, id)| {
@@ -1721,8 +1735,8 @@ fn report_projection_error(
                 values.map(|(_, is_normalized_ty_expected, normalized_ty, expected_ty)| {
                     infer::ValuePairs::Terms(ExpectedFound::new(
                         is_normalized_ty_expected,
-                        normalized_ty.into(),
-                        expected_ty.into(),
+                        normalized_ty,
+                        expected_ty,
                     ))
                 }),
                 err,
@@ -1743,21 +1757,26 @@ fn maybe_detailed_projection_msg(
         let trait_def_id = pred.projection_ty.trait_def_id(self.tcx);
         let self_ty = pred.projection_ty.self_ty();
 
-        if Some(pred.projection_ty.item_def_id) == self.tcx.lang_items().fn_once_output() {
-            Some(format!(
-                "expected `{self_ty}` to be a {fn_kind} that returns `{expected_ty}`, but it returns `{normalized_ty}`",
-                fn_kind = self_ty.prefix_string(self.tcx)
-            ))
-        } else if Some(trait_def_id) == self.tcx.lang_items().future_trait() {
-            Some(format!(
-                "expected `{self_ty}` to be a future that resolves to `{expected_ty}`, but it resolves to `{normalized_ty}`"
-            ))
-        } else if Some(trait_def_id) == self.tcx.get_diagnostic_item(sym::Iterator) {
-            Some(format!(
-                "expected `{self_ty}` to be an iterator that yields `{expected_ty}`, but it yields `{normalized_ty}`"
-            ))
-        } else {
-            None
+        with_forced_trimmed_paths! {
+            if Some(pred.projection_ty.def_id) == self.tcx.lang_items().fn_once_output() {
+                Some(format!(
+                    "expected `{self_ty}` to be a {fn_kind} that returns `{expected_ty}`, but it \
+                     returns `{normalized_ty}`",
+                    fn_kind = self_ty.prefix_string(self.tcx)
+                ))
+            } else if Some(trait_def_id) == self.tcx.lang_items().future_trait() {
+                Some(format!(
+                    "expected `{self_ty}` to be a future that resolves to `{expected_ty}`, but it \
+                     resolves to `{normalized_ty}`"
+                ))
+            } else if Some(trait_def_id) == self.tcx.get_diagnostic_item(sym::Iterator) {
+                Some(format!(
+                    "expected `{self_ty}` to be an iterator that yields `{expected_ty}`, but it \
+                     yields `{normalized_ty}`"
+                ))
+            } else {
+                None
+            }
         }
     }
 
@@ -1786,8 +1805,8 @@ fn type_category(tcx: TyCtxt<'_>, t: Ty<'_>) -> Option<u32> {
                 ty::Closure(..) => Some(9),
                 ty::Tuple(..) => Some(10),
                 ty::Param(..) => Some(11),
-                ty::Projection(..) => Some(12),
-                ty::Opaque(..) => Some(13),
+                ty::Alias(ty::Projection, ..) => Some(12),
+                ty::Alias(ty::Opaque, ..) => Some(13),
                 ty::Never => Some(14),
                 ty::Adt(..) => Some(15),
                 ty::Generator(..) => Some(16),
@@ -1885,7 +1904,9 @@ fn report_similar_impl_candidates(
         trait_ref: ty::PolyTraitRef<'tcx>,
         body_id: hir::HirId,
         err: &mut Diagnostic,
+        other: bool,
     ) -> bool {
+        let other = if other { "other " } else { "" };
         let report = |mut candidates: Vec<TraitRef<'tcx>>, err: &mut Diagnostic| {
             candidates.sort();
             candidates.dedup();
@@ -1936,7 +1957,7 @@ fn report_similar_impl_candidates(
             candidates.dedup();
             let end = if candidates.len() <= 9 { candidates.len() } else { 8 };
             err.help(&format!(
-                "the following other types implement trait `{}`:{}{}",
+                "the following {other}types implement trait `{}`:{}{}",
                 trait_ref.print_only_trait_path(),
                 candidates[..end].join(""),
                 if len > 9 { format!("\nand {} others", len - 8) } else { String::new() }
@@ -2077,8 +2098,8 @@ fn mk_trait_obligation_with_new_self_ty(
         param_env: ty::ParamEnv<'tcx>,
         trait_ref_and_ty: ty::Binder<'tcx, (ty::TraitPredicate<'tcx>, Ty<'tcx>)>,
     ) -> PredicateObligation<'tcx> {
-        let trait_pred = trait_ref_and_ty
-            .map_bound(|(tr, new_self_ty)| tr.with_self_type(self.tcx, new_self_ty));
+        let trait_pred =
+            trait_ref_and_ty.map_bound(|(tr, new_self_ty)| tr.with_self_ty(self.tcx, new_self_ty));
 
         Obligation::new(self.tcx, ObligationCause::dummy(), param_env, trait_pred)
     }
@@ -2172,19 +2193,40 @@ fn maybe_report_ambiguity(
                 let mut selcx = SelectionContext::new(&self);
                 match selcx.select_from_obligation(&obligation) {
                     Ok(None) => {
-                        let impls = ambiguity::recompute_applicable_impls(self.infcx, &obligation);
+                        let ambiguities =
+                            ambiguity::recompute_applicable_impls(self.infcx, &obligation);
                         let has_non_region_infer =
                             trait_ref.skip_binder().substs.types().any(|t| !t.is_ty_infer());
                         // It doesn't make sense to talk about applicable impls if there are more
                         // than a handful of them.
-                        if impls.len() > 1 && impls.len() < 5 && has_non_region_infer {
-                            self.annotate_source_of_ambiguity(&mut err, &impls, predicate);
+                        if ambiguities.len() > 1 && ambiguities.len() < 10 && has_non_region_infer {
+                            if self.tainted_by_errors().is_some() && subst.is_none() {
+                                // If `subst.is_none()`, then this is probably two param-env
+                                // candidates or impl candidates that are equal modulo lifetimes.
+                                // Therefore, if we've already emitted an error, just skip this
+                                // one, since it's not particularly actionable.
+                                err.cancel();
+                                return;
+                            }
+                            self.annotate_source_of_ambiguity(&mut err, &ambiguities, predicate);
                         } else {
                             if self.tainted_by_errors().is_some() {
                                 err.cancel();
                                 return;
                             }
                             err.note(&format!("cannot satisfy `{}`", predicate));
+                            let impl_candidates = self.find_similar_impl_candidates(
+                                predicate.to_opt_poly_trait_pred().unwrap(),
+                            );
+                            if impl_candidates.len() < 10 {
+                                self.report_similar_impl_candidates(
+                                    impl_candidates,
+                                    trait_ref,
+                                    body_id.map(|id| id.hir_id).unwrap_or(obligation.cause.body_id),
+                                    &mut err,
+                                    false,
+                                );
+                            }
                         }
                     }
                     _ => {
@@ -2196,60 +2238,10 @@ fn maybe_report_ambiguity(
                     }
                 }
 
-                if let ObligationCauseCode::ItemObligation(def_id) | ObligationCauseCode::ExprItemObligation(def_id, ..) = *obligation.cause.code() {
-                    self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
-                } else if let Ok(snippet) = &self.tcx.sess.source_map().span_to_snippet(span)
-                    && let ObligationCauseCode::BindingObligation(def_id, _) | ObligationCauseCode::ExprBindingObligation(def_id, ..)
-                        = *obligation.cause.code()
+                if let ObligationCauseCode::ItemObligation(def_id)
+                | ObligationCauseCode::ExprItemObligation(def_id, ..) = *obligation.cause.code()
                 {
-                    let generics = self.tcx.generics_of(def_id);
-                    if generics.params.iter().any(|p| p.name != kw::SelfUpper)
-                        && !snippet.ends_with('>')
-                        && !generics.has_impl_trait()
-                        && !self.tcx.is_fn_trait(def_id)
-                    {
-                        // FIXME: To avoid spurious suggestions in functions where type arguments
-                        // where already supplied, we check the snippet to make sure it doesn't
-                        // end with a turbofish. Ideally we would have access to a `PathSegment`
-                        // instead. Otherwise we would produce the following output:
-                        //
-                        // error[E0283]: type annotations needed
-                        //   --> $DIR/issue-54954.rs:3:24
-                        //    |
-                        // LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>();
-                        //    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^
-                        //    |                        |
-                        //    |                        cannot infer type
-                        //    |                        help: consider specifying the type argument
-                        //    |                        in the function call:
-                        //    |                        `Tt::const_val::<[i8; 123]>::<T>`
-                        // ...
-                        // LL |     const fn const_val<T: Sized>() -> usize {
-                        //    |                        - required by this bound in `Tt::const_val`
-                        //    |
-                        //    = note: cannot satisfy `_: Tt`
-
-                        // Clear any more general suggestions in favor of our specific one
-                        err.clear_suggestions();
-
-                        err.span_suggestion_verbose(
-                            span.shrink_to_hi(),
-                            &format!(
-                                "consider specifying the type argument{} in the function call",
-                                pluralize!(generics.params.len()),
-                            ),
-                            format!(
-                                "::<{}>",
-                                generics
-                                    .params
-                                    .iter()
-                                    .map(|p| p.name.to_string())
-                                    .collect::<Vec<String>>()
-                                    .join(", ")
-                            ),
-                            Applicability::HasPlaceholders,
-                        );
-                    }
+                    self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
                 }
 
                 if let (Some(body_id), Some(ty::subst::GenericArgKind::Type(_))) =
@@ -2320,18 +2312,19 @@ fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
                         let trait_impls = self.tcx.trait_impls_of(data.trait_ref.def_id);
 
                         if trait_impls.blanket_impls().is_empty()
-                            && let Some((impl_ty, _)) = trait_impls.non_blanket_impls().iter().next()
-                            && let Some(impl_def_id) = impl_ty.def() {
-                            let message = if trait_impls.non_blanket_impls().len() == 1 {
+                            && let Some(impl_def_id) = trait_impls.non_blanket_impls().values().flatten().next()
+                        {
+                            let non_blanket_impl_count = trait_impls.non_blanket_impls().values().flatten().count();
+                            let message = if non_blanket_impl_count == 1 {
                                 "use the fully-qualified path to the only available implementation".to_string()
                             } else {
                                 format!(
                                     "use a fully-qualified path to a specific available implementation ({} found)",
-                                    trait_impls.non_blanket_impls().len()
+                                    non_blanket_impl_count
                                 )
                             };
                             let mut suggestions = vec![(
-                                trait_path_segment.ident.span.shrink_to_lo(),
+                                path.span.shrink_to_lo(),
                                 format!("<{} as ", self.tcx.type_of(impl_def_id))
                             )];
                             if let Some(generic_arg) = trait_path_segment.args {
@@ -2464,21 +2457,30 @@ fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
     fn annotate_source_of_ambiguity(
         &self,
         err: &mut Diagnostic,
-        impls: &[DefId],
+        ambiguities: &[ambiguity::Ambiguity],
         predicate: ty::Predicate<'tcx>,
     ) {
         let mut spans = vec![];
         let mut crates = vec![];
         let mut post = vec![];
-        for def_id in impls {
-            match self.tcx.span_of_impl(*def_id) {
-                Ok(span) => spans.push(span),
-                Err(name) => {
-                    crates.push(name);
-                    if let Some(header) = to_pretty_impl_header(self.tcx, *def_id) {
-                        post.push(header);
+        let mut has_param_env = false;
+        for ambiguity in ambiguities {
+            match ambiguity {
+                ambiguity::Ambiguity::DefId(impl_def_id) => {
+                    match self.tcx.span_of_impl(*impl_def_id) {
+                        Ok(span) => spans.push(span),
+                        Err(name) => {
+                            crates.push(name);
+                            if let Some(header) = to_pretty_impl_header(self.tcx, *impl_def_id) {
+                                post.push(header);
+                            }
+                        }
                     }
                 }
+                ambiguity::Ambiguity::ParamEnv(span) => {
+                    has_param_env = true;
+                    spans.push(*span);
+                }
             }
         }
         let mut crate_names: Vec<_> = crates.iter().map(|n| format!("`{}`", n)).collect();
@@ -2502,7 +2504,11 @@ fn annotate_source_of_ambiguity(
             return;
         }
 
-        let msg = format!("multiple `impl`s satisfying `{}` found", predicate);
+        let msg = format!(
+            "multiple `impl`s{} satisfying `{}` found",
+            if has_param_env { " or `where` clauses" } else { "" },
+            predicate
+        );
         let post = if post.len() > 1 || (post.len() == 1 && post[0].contains('\n')) {
             format!(":\n{}", post.iter().map(|p| format!("- {}", p)).collect::<Vec<_>>().join("\n"),)
         } else if post.len() == 1 {
@@ -2601,7 +2607,7 @@ fn note_obligation_cause(&self, err: &mut Diagnostic, obligation: &PredicateObli
         if !self.maybe_note_obligation_cause_for_async_await(err, obligation) {
             self.note_obligation_cause_code(
                 err,
-                &obligation.predicate,
+                obligation.predicate,
                 obligation.param_env,
                 obligation.cause.code(),
                 &mut vec![],
index 6ea54b625bbc0f8e533de1fabf88c6ad5f9dcdbc..d47a5ea3e3706fa68ddcda5e27f80186ab6ca550 100644 (file)
@@ -1,8 +1,10 @@
+// ignore-tidy-filelength
+
 use super::{DefIdOrName, Obligation, ObligationCause, ObligationCauseCode, PredicateObligation};
 
 use crate::autoderef::Autoderef;
 use crate::infer::InferCtxt;
-use crate::traits::NormalizeExt;
+use crate::traits::{NormalizeExt, ObligationCtxt};
 
 use hir::def::CtorOf;
 use hir::HirId;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::{InferOk, LateBoundRegionConversionTime};
 use rustc_middle::hir::map;
+use rustc_middle::ty::error::TypeError::{self, Sorts};
+use rustc_middle::ty::relate::TypeRelation;
 use rustc_middle::ty::{
     self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, DefIdTree,
-    GeneratorDiagnosticData, GeneratorInteriorTypeCause, Infer, InferTy, IsSuggestable,
-    ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable,
+    GeneratorDiagnosticData, GeneratorInteriorTypeCause, Infer, InferTy, InternalSubsts,
+    IsSuggestable, ToPredicate, Ty, TyCtxt, TypeAndMut, TypeFoldable, TypeFolder,
+    TypeSuperFoldable, TypeVisitable, TypeckResults,
 };
-use rustc_middle::ty::{TypeAndMut, TypeckResults};
 use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::{BytePos, DesugaringKind, ExpnKind, Span, DUMMY_SP};
 use rustc_target::spec::abi;
-use std::fmt;
+use std::ops::Deref;
 
+use super::method_chain::CollectAllMismatches;
 use super::InferCtxtPrivExt;
 use crate::infer::InferCtxtExt as _;
 use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
-use rustc_middle::ty::print::with_no_trimmed_paths;
+use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths};
 
 #[derive(Debug)]
 pub enum GeneratorInteriorOrUpvar {
@@ -254,6 +259,7 @@ fn report_closure_arg_mismatch(
         found: ty::PolyTraitRef<'tcx>,
         expected: ty::PolyTraitRef<'tcx>,
         cause: &ObligationCauseCode<'tcx>,
+        found_node: Option<Node<'_>>,
     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
 
     fn note_conflicting_closure_bounds(
@@ -292,13 +298,13 @@ fn note_obligation_cause_for_async_await(
     fn note_obligation_cause_code<T>(
         &self,
         err: &mut Diagnostic,
-        predicate: &T,
+        predicate: T,
         param_env: ty::ParamEnv<'tcx>,
         cause_code: &ObligationCauseCode<'tcx>,
         obligated_types: &mut Vec<Ty<'tcx>>,
         seen_requirements: &mut FxHashSet<DefId>,
     ) where
-        T: fmt::Display + ToPredicate<'tcx>;
+        T: ToPredicate<'tcx>;
 
     /// Suggest to await before try: future? => future.await?
     fn suggest_await_before_try(
@@ -329,6 +335,31 @@ fn suggest_dereferencing_index(
         err: &mut Diagnostic,
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     );
+    fn function_argument_obligation(
+        &self,
+        arg_hir_id: HirId,
+        err: &mut Diagnostic,
+        parent_code: &ObligationCauseCode<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        predicate: ty::Predicate<'tcx>,
+        call_hir_id: HirId,
+    );
+    fn point_at_chain(
+        &self,
+        expr: &hir::Expr<'_>,
+        typeck_results: &TypeckResults<'tcx>,
+        type_diffs: Vec<TypeError<'tcx>>,
+        param_env: ty::ParamEnv<'tcx>,
+        err: &mut Diagnostic,
+    );
+    fn probe_assoc_types_at_expr(
+        &self,
+        type_diffs: &[TypeError<'tcx>],
+        span: Span,
+        prev_ty: Ty<'tcx>,
+        body_id: hir::HirId,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> Vec<Option<(Span, (DefId, Ty<'tcx>))>>;
 }
 
 fn predicate_constraint(generics: &hir::Generics<'_>, pred: ty::Predicate<'_>) -> (Span, String) {
@@ -348,7 +379,7 @@ fn suggest_restriction<'tcx>(
     msg: &str,
     err: &mut Diagnostic,
     fn_sig: Option<&hir::FnSig<'_>>,
-    projection: Option<&ty::ProjectionTy<'_>>,
+    projection: Option<&ty::AliasTy<'_>>,
     trait_pred: ty::PolyTraitPredicate<'tcx>,
     // When we are dealing with a trait, `super_traits` will be `Some`:
     // Given `trait T: A + B + C {}`
@@ -474,7 +505,7 @@ fn suggest_restricting_param_bound(
         let self_ty = trait_pred.skip_binder().self_ty();
         let (param_ty, projection) = match self_ty.kind() {
             ty::Param(_) => (true, None),
-            ty::Projection(projection) => (false, Some(projection)),
+            ty::Alias(ty::Projection, projection) => (false, Some(projection)),
             _ => (false, None),
         };
 
@@ -673,7 +704,7 @@ fn suggest_dereferences(
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) -> bool {
         // It only make sense when suggesting dereferences for arguments
-        let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = obligation.cause.code()
+        let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, call_hir_id, .. } = obligation.cause.code()
             else { return false; };
         let Some(typeck_results) = &self.typeck_results
             else { return false; };
@@ -752,12 +783,33 @@ fn suggest_dereferences(
                         real_trait_pred_and_base_ty,
                     );
                     if self.predicate_may_hold(&obligation) {
-                        err.span_suggestion_verbose(
-                            span.shrink_to_lo(),
-                            "consider dereferencing here",
-                            "*",
-                            Applicability::MachineApplicable,
+                        let call_node = self.tcx.hir().get(*call_hir_id);
+                        let msg = "consider dereferencing here";
+                        let is_receiver = matches!(
+                            call_node,
+                            Node::Expr(hir::Expr {
+                                kind: hir::ExprKind::MethodCall(_, receiver_expr, ..),
+                                ..
+                            })
+                            if receiver_expr.hir_id == *arg_hir_id
                         );
+                        if is_receiver {
+                            err.multipart_suggestion_verbose(
+                                msg,
+                                vec![
+                                    (span.shrink_to_lo(), "(*".to_string()),
+                                    (span.shrink_to_hi(), ")".to_string()),
+                                ],
+                                Applicability::MachineApplicable,
+                            )
+                        } else {
+                            err.span_suggestion_verbose(
+                                span.shrink_to_lo(),
+                                msg,
+                                '*',
+                                Applicability::MachineApplicable,
+                            )
+                        };
                         return true;
                     }
                 }
@@ -834,10 +886,10 @@ fn suggest_fn_call(
                     fn_sig.inputs().map_bound(|inputs| &inputs[1..]),
                 ))
             }
-            ty::Opaque(def_id, substs) => {
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
                 self.tcx.bound_item_bounds(def_id).subst(self.tcx, substs).iter().find_map(|pred| {
                     if let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) = pred.kind().skip_binder()
-                    && Some(proj.projection_ty.item_def_id) == self.tcx.lang_items().fn_once_output()
+                    && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output()
                     // args tuple will always be substs[1]
                     && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind()
                     {
@@ -854,7 +906,7 @@ fn suggest_fn_call(
             ty::Dynamic(data, _, ty::Dyn) => {
                 data.iter().find_map(|pred| {
                     if let ty::ExistentialPredicate::Projection(proj) = pred.skip_binder()
-                    && Some(proj.item_def_id) == self.tcx.lang_items().fn_once_output()
+                    && Some(proj.def_id) == self.tcx.lang_items().fn_once_output()
                     // for existential projection, substs are shifted over by 1
                     && let ty::Tuple(args) = proj.substs.type_at(0).kind()
                     {
@@ -871,7 +923,7 @@ fn suggest_fn_call(
             ty::Param(_) => {
                 obligation.param_env.caller_bounds().iter().find_map(|pred| {
                     if let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) = pred.kind().skip_binder()
-                    && Some(proj.projection_ty.item_def_id) == self.tcx.lang_items().fn_once_output()
+                    && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output()
                     && proj.projection_ty.self_ty() == found
                     // args tuple will always be substs[1]
                     && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind()
@@ -1574,7 +1626,7 @@ fn suggest_impl_trait(
         let trait_obj = if has_dyn { &snippet[4..] } else { &snippet };
         if only_never_return {
             // No return paths, probably using `panic!()` or similar.
-            // Suggest `-> T`, `-> impl Trait`, and if `Trait` is object safe, `-> Box<dyn Trait>`.
+            // Suggest `-> impl Trait`, and if `Trait` is object safe, `-> Box<dyn Trait>`.
             suggest_trait_object_return_type_alternatives(
                 err,
                 ret_ty.span,
@@ -1674,6 +1726,7 @@ fn report_closure_arg_mismatch(
         found: ty::PolyTraitRef<'tcx>,
         expected: ty::PolyTraitRef<'tcx>,
         cause: &ObligationCauseCode<'tcx>,
+        found_node: Option<Node<'_>>,
     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
         pub(crate) fn build_fn_sig_ty<'tcx>(
             infcx: &InferCtxt<'tcx>,
@@ -1735,6 +1788,10 @@ pub(crate) fn build_fn_sig_ty<'tcx>(
 
         self.note_conflicting_closure_bounds(cause, &mut err);
 
+        if let Some(found_node) = found_node {
+            hint_missing_borrow(span, found_span, found, expected, found_node, &mut err);
+        }
+
         err
     }
 
@@ -1755,10 +1812,10 @@ fn note_conflicting_closure_bounds(
             && self.tcx.is_fn_trait(trait_pred.def_id())
         {
             let expected_self =
-                self.tcx.anonymize_late_bound_regions(pred.kind().rebind(trait_pred.self_ty()));
+                self.tcx.anonymize_bound_vars(pred.kind().rebind(trait_pred.self_ty()));
             let expected_substs = self
                 .tcx
-                .anonymize_late_bound_regions(pred.kind().rebind(trait_pred.trait_ref.substs));
+                .anonymize_bound_vars(pred.kind().rebind(trait_pred.trait_ref.substs));
 
             // Find another predicate whose self-type is equal to the expected self type,
             // but whose substs don't match.
@@ -1771,12 +1828,12 @@ fn note_conflicting_closure_bounds(
                             // Make sure that the self type matches
                             // (i.e. constraining this closure)
                             && expected_self
-                                == self.tcx.anonymize_late_bound_regions(
+                                == self.tcx.anonymize_bound_vars(
                                     pred.kind().rebind(trait_pred.self_ty()),
                                 )
                             // But the substs don't match (i.e. incompatible args)
                             && expected_substs
-                                != self.tcx.anonymize_late_bound_regions(
+                                != self.tcx.anonymize_bound_vars(
                                     pred.kind().rebind(trait_pred.trait_ref.substs),
                                 ) =>
                     {
@@ -2158,15 +2215,15 @@ fn note_obligation_cause_for_async_await(
             format!("does not implement `{}`", trait_pred.print_modifiers_and_trait_path())
         };
 
-        let mut explain_yield = |interior_span: Span,
-                                 yield_span: Span,
-                                 scope_span: Option<Span>| {
-            let mut span = MultiSpan::from_span(yield_span);
-            if let Ok(snippet) = source_map.span_to_snippet(interior_span) {
-                // #70935: If snippet contains newlines, display "the value" instead
-                // so that we do not emit complex diagnostics.
-                let snippet = &format!("`{}`", snippet);
-                let snippet = if snippet.contains('\n') { "the value" } else { snippet };
+        let mut explain_yield =
+            |interior_span: Span, yield_span: Span, scope_span: Option<Span>| {
+                let mut span = MultiSpan::from_span(yield_span);
+                let snippet = match source_map.span_to_snippet(interior_span) {
+                    // #70935: If snippet contains newlines, display "the value" instead
+                    // so that we do not emit complex diagnostics.
+                    Ok(snippet) if !snippet.contains('\n') => format!("`{}`", snippet),
+                    _ => "the value".to_string(),
+                };
                 // note: future is not `Send` as this value is used across an await
                 //   --> $DIR/issue-70935-complex-spans.rs:13:9
                 //    |
@@ -2191,17 +2248,11 @@ fn note_obligation_cause_for_async_await(
                     interior_span,
                     format!("has type `{}` which {}", target_ty, trait_explanation),
                 );
-                // If available, use the scope span to annotate the drop location.
-                let mut scope_note = None;
                 if let Some(scope_span) = scope_span {
                     let scope_span = source_map.end_point(scope_span);
 
                     let msg = format!("{} is later dropped here", snippet);
-                    if source_map.is_multiline(yield_span.between(scope_span)) {
-                        span.push_span_label(scope_span, msg);
-                    } else {
-                        scope_note = Some((scope_span, msg));
-                    }
+                    span.push_span_label(scope_span, msg);
                 }
                 err.span_note(
                     span,
@@ -2210,11 +2261,7 @@ fn note_obligation_cause_for_async_await(
                         future_or_generator, trait_explanation, an_await_or_yield
                     ),
                 );
-                if let Some((span, msg)) = scope_note {
-                    err.span_note(span, &msg);
-                }
-            }
-        };
+            };
         match interior_or_upvar_span {
             GeneratorInteriorOrUpvar::Interior(interior_span, interior_extra_info) => {
                 if let Some((scope_span, yield_span, expr, from_awaited_ty)) = interior_extra_info {
@@ -2336,7 +2383,7 @@ fn note_obligation_cause_for_async_await(
         debug!(?next_code);
         self.note_obligation_cause_code(
             err,
-            &obligation.predicate,
+            obligation.predicate,
             obligation.param_env,
             next_code.unwrap(),
             &mut Vec::new(),
@@ -2347,15 +2394,16 @@ fn note_obligation_cause_for_async_await(
     fn note_obligation_cause_code<T>(
         &self,
         err: &mut Diagnostic,
-        predicate: &T,
+        predicate: T,
         param_env: ty::ParamEnv<'tcx>,
         cause_code: &ObligationCauseCode<'tcx>,
         obligated_types: &mut Vec<Ty<'tcx>>,
         seen_requirements: &mut FxHashSet<DefId>,
     ) where
-        T: fmt::Display + ToPredicate<'tcx>,
+        T: ToPredicate<'tcx>,
     {
         let tcx = self.tcx;
+        let predicate = predicate.to_predicate(tcx);
         match *cause_code {
             ObligationCauseCode::ExprAssignable
             | ObligationCauseCode::MatchExpressionArm { .. }
@@ -2390,12 +2438,11 @@ fn note_obligation_cause_code<T>(
                 err.note("only the last element of a tuple may have a dynamically sized type");
             }
             ObligationCauseCode::ProjectionWf(data) => {
-                err.note(&format!("required so that the projection `{}` is well-formed", data,));
+                err.note(&format!("required so that the projection `{data}` is well-formed"));
             }
             ObligationCauseCode::ReferenceOutlivesReferent(ref_ty) => {
                 err.note(&format!(
-                    "required so that reference `{}` does not outlive its referent",
-                    ref_ty,
+                    "required so that reference `{ref_ty}` does not outlive its referent"
                 ));
             }
             ObligationCauseCode::ObjectTypeBound(object_ty, region) => {
@@ -2412,21 +2459,22 @@ fn note_obligation_cause_code<T>(
             ObligationCauseCode::BindingObligation(item_def_id, span)
             | ObligationCauseCode::ExprBindingObligation(item_def_id, span, ..) => {
                 let item_name = tcx.def_path_str(item_def_id);
+                let short_item_name = with_forced_trimmed_paths!(tcx.def_path_str(item_def_id));
                 let mut multispan = MultiSpan::from(span);
+                let sm = tcx.sess.source_map();
                 if let Some(ident) = tcx.opt_item_ident(item_def_id) {
-                    let sm = tcx.sess.source_map();
                     let same_line =
                         match (sm.lookup_line(ident.span.hi()), sm.lookup_line(span.lo())) {
                             (Ok(l), Ok(r)) => l.line == r.line,
                             _ => true,
                         };
-                    if !ident.span.is_dummy() && !ident.span.overlaps(span) && !same_line {
+                    if ident.span.is_visible(sm) && !ident.span.overlaps(span) && !same_line {
                         multispan.push_span_label(ident.span, "required by a bound in this");
                     }
                 }
-                let descr = format!("required by a bound in `{}`", item_name);
-                if !span.is_dummy() {
-                    let msg = format!("required by this bound in `{}`", item_name);
+                let descr = format!("required by a bound in `{item_name}`");
+                if span.is_visible(sm) {
+                    let msg = format!("required by this bound in `{short_item_name}`");
                     multispan.push_span_label(span, msg);
                     err.span_note(multispan, &descr);
                 } else {
@@ -2500,6 +2548,25 @@ fn note_obligation_cause_code<T>(
             }
             ObligationCauseCode::SizedArgumentType(sp) => {
                 if let Some(span) = sp {
+                    if let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder()
+                        && let ty::Clause::Trait(trait_pred) = clause
+                        && let ty::Dynamic(..) = trait_pred.self_ty().kind()
+                    {
+                        let span = if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
+                            && snippet.starts_with("dyn ")
+                        {
+                            let pos = snippet.len() - snippet[3..].trim_start().len();
+                            span.with_hi(span.lo() + BytePos(pos as u32))
+                        } else {
+                            span.shrink_to_lo()
+                        };
+                        err.span_suggestion_verbose(
+                            span,
+                            "you can use `impl Trait` as the argument type",
+                            "impl ".to_string(),
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
                     err.span_suggestion_verbose(
                         span.shrink_to_lo(),
                         "function arguments must have a statically known size, borrowed types \
@@ -2622,7 +2689,7 @@ fn note_obligation_cause_code<T>(
                                 Some(ident) => err.span_note(ident.span, &msg),
                                 None => err.note(&msg),
                             },
-                            ty::Opaque(def_id, _) => {
+                            ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
                                 // Avoid printing the future from `core::future::identity_future`, it's not helpful
                                 if tcx.parent(*def_id) == identity_future {
                                     break 'print;
@@ -2688,7 +2755,7 @@ fn note_obligation_cause_code<T>(
                     ensure_sufficient_stack(|| {
                         self.note_obligation_cause_code(
                             err,
-                            &parent_predicate,
+                            parent_predicate,
                             param_env,
                             &data.parent_code,
                             obligated_types,
@@ -2699,7 +2766,7 @@ fn note_obligation_cause_code<T>(
                     ensure_sufficient_stack(|| {
                         self.note_obligation_cause_code(
                             err,
-                            &parent_predicate,
+                            parent_predicate,
                             param_env,
                             cause_code.peel_derives(),
                             obligated_types,
@@ -2808,7 +2875,7 @@ fn note_obligation_cause_code<T>(
                 ensure_sufficient_stack(|| {
                     self.note_obligation_cause_code(
                         err,
-                        &parent_predicate,
+                        parent_predicate,
                         param_env,
                         &data.parent_code,
                         obligated_types,
@@ -2823,7 +2890,7 @@ fn note_obligation_cause_code<T>(
                 ensure_sufficient_stack(|| {
                     self.note_obligation_cause_code(
                         err,
-                        &parent_predicate,
+                        parent_predicate,
                         param_env,
                         &data.parent_code,
                         obligated_types,
@@ -2835,44 +2902,16 @@ fn note_obligation_cause_code<T>(
                 arg_hir_id,
                 call_hir_id,
                 ref parent_code,
+                ..
             } => {
-                let hir = self.tcx.hir();
-                if let Some(Node::Expr(expr @ hir::Expr { kind: hir::ExprKind::Block(..), .. })) =
-                    hir.find(arg_hir_id)
-                {
-                    let parent_id = hir.get_parent_item(arg_hir_id);
-                    let typeck_results: &TypeckResults<'tcx> = match &self.typeck_results {
-                        Some(t) if t.hir_owner == parent_id => t,
-                        _ => self.tcx.typeck(parent_id.def_id),
-                    };
-                    let expr = expr.peel_blocks();
-                    let ty = typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error());
-                    let span = expr.span;
-                    if Some(span) != err.span.primary_span() {
-                        err.span_label(
-                            span,
-                            if ty.references_error() {
-                                String::new()
-                            } else {
-                                format!("this tail expression is of type `{:?}`", ty)
-                            },
-                        );
-                    }
-                }
-                if let Some(Node::Expr(hir::Expr {
-                    kind:
-                        hir::ExprKind::Call(hir::Expr { span, .. }, _)
-                        | hir::ExprKind::MethodCall(
-                            hir::PathSegment { ident: Ident { span, .. }, .. },
-                            ..,
-                        ),
-                    ..
-                })) = hir.find(call_hir_id)
-                {
-                    if Some(*span) != err.span.primary_span() {
-                        err.span_label(*span, "required by a bound introduced by this call");
-                    }
-                }
+                self.function_argument_obligation(
+                    arg_hir_id,
+                    err,
+                    parent_code,
+                    param_env,
+                    predicate,
+                    call_hir_id,
+                );
                 ensure_sufficient_stack(|| {
                     self.note_obligation_cause_code(
                         err,
@@ -2887,9 +2926,8 @@ fn note_obligation_cause_code<T>(
             ObligationCauseCode::CompareImplItemObligation { trait_item_def_id, kind, .. } => {
                 let item_name = self.tcx.item_name(trait_item_def_id);
                 let msg = format!(
-                    "the requirement `{}` appears on the `impl`'s {kind} `{}` but not on the \
-                     corresponding trait's {kind}",
-                    predicate, item_name,
+                    "the requirement `{predicate}` appears on the `impl`'s {kind} \
+                     `{item_name}` but not on the corresponding trait's {kind}",
                 );
                 let sp = self
                     .tcx
@@ -2899,7 +2937,7 @@ fn note_obligation_cause_code<T>(
                 let mut assoc_span: MultiSpan = sp.into();
                 assoc_span.push_span_label(
                     sp,
-                    format!("this trait's {kind} doesn't have the requirement `{}`", predicate),
+                    format!("this trait's {kind} doesn't have the requirement `{predicate}`"),
                 );
                 if let Some(ident) = self
                     .tcx
@@ -2918,7 +2956,7 @@ fn note_obligation_cause_code<T>(
             }
             ObligationCauseCode::OpaqueReturnType(expr_info) => {
                 if let Some((expr_ty, expr_span)) = expr_info {
-                    let expr_ty = self.resolve_vars_if_possible(expr_ty);
+                    let expr_ty = with_forced_trimmed_paths!(self.ty_to_string(expr_ty));
                     err.span_label(
                         expr_span,
                         format!("return type was inferred to be `{expr_ty}` here"),
@@ -2964,7 +3002,7 @@ fn suggest_await_before_try(
                     self.tcx.mk_projection(
                         item_def_id,
                         // Future::Output has no substs
-                        self.tcx.mk_substs_trait(trait_pred.self_ty(), []),
+                        [trait_pred.self_ty()],
                     )
                 });
                 let InferOk { value: projection_ty, .. } =
@@ -3098,6 +3136,392 @@ fn suggest_dereferencing_index(
             );
         }
     }
+    fn function_argument_obligation(
+        &self,
+        arg_hir_id: HirId,
+        err: &mut Diagnostic,
+        parent_code: &ObligationCauseCode<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        predicate: ty::Predicate<'tcx>,
+        call_hir_id: HirId,
+    ) {
+        let tcx = self.tcx;
+        let hir = tcx.hir();
+        if let Some(Node::Expr(expr)) = hir.find(arg_hir_id) {
+            let parent_id = hir.get_parent_item(arg_hir_id);
+            let typeck_results: &TypeckResults<'tcx> = match &self.typeck_results {
+                Some(t) if t.hir_owner == parent_id => t,
+                _ => self.tcx.typeck(parent_id.def_id),
+            };
+            if let hir::Expr { kind: hir::ExprKind::Block(..), .. } = expr {
+                let expr = expr.peel_blocks();
+                let ty = typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error());
+                let span = expr.span;
+                if Some(span) != err.span.primary_span() {
+                    err.span_label(
+                        span,
+                        if ty.references_error() {
+                            String::new()
+                        } else {
+                            let ty = with_forced_trimmed_paths!(self.ty_to_string(ty));
+                            format!("this tail expression is of type `{ty}`")
+                        },
+                    );
+                }
+            }
+
+            // FIXME: visit the ty to see if there's any closure involved, and if there is,
+            // check whether its evaluated return type is the same as the one corresponding
+            // to an associated type (as seen from `trait_pred`) in the predicate. Like in
+            // trait_pred `S: Sum<<Self as Iterator>::Item>` and predicate `i32: Sum<&()>`
+            let mut type_diffs = vec![];
+
+            if let ObligationCauseCode::ExprBindingObligation(def_id, _, _, idx) = parent_code.deref()
+                && let predicates = self.tcx.predicates_of(def_id).instantiate_identity(self.tcx)
+                && let Some(pred) = predicates.predicates.get(*idx)
+            {
+                if let Ok(trait_pred) = pred.kind().try_map_bound(|pred| match pred {
+                    ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => Ok(trait_pred),
+                    _ => Err(()),
+                })
+                    && let Ok(trait_predicate) = predicate.kind().try_map_bound(|pred| match pred {
+                        ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => Ok(trait_pred),
+                        _ => Err(()),
+                    })
+                {
+                    let mut c = CollectAllMismatches {
+                        infcx: self.infcx,
+                        param_env,
+                        errors: vec![],
+                    };
+                    if let Ok(_) = c.relate(trait_pred, trait_predicate) {
+                        type_diffs = c.errors;
+                    }
+                } else if let ty::PredicateKind::Clause(
+                    ty::Clause::Projection(proj)
+                ) = pred.kind().skip_binder()
+                    && let ty::PredicateKind::Clause(
+                        ty::Clause::Projection(projection)
+                    ) = predicate.kind().skip_binder()
+                {
+                    type_diffs = vec![
+                        Sorts(ty::error::ExpectedFound {
+                            expected: self.tcx.mk_ty(ty::Alias(ty::Projection, proj.projection_ty)),
+                            found: projection.term.ty().unwrap(),
+                        }),
+                    ];
+                }
+            }
+            if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
+                && let hir::Path { res: hir::def::Res::Local(hir_id), .. } = path
+                && let Some(hir::Node::Pat(binding)) = self.tcx.hir().find(*hir_id)
+                && let parent_hir_id = self.tcx.hir().get_parent_node(binding.hir_id)
+                && let Some(hir::Node::Local(local)) = self.tcx.hir().find(parent_hir_id)
+                && let Some(binding_expr) = local.init
+            {
+                // If the expression we're calling on is a binding, we want to point at the
+                // `let` when talking about the type. Otherwise we'll point at every part
+                // of the method chain with the type.
+                self.point_at_chain(binding_expr, typeck_results, type_diffs, param_env, err);
+            } else {
+                self.point_at_chain(expr, typeck_results, type_diffs, param_env, err);
+            }
+        }
+        let call_node = hir.find(call_hir_id);
+        if let Some(Node::Expr(hir::Expr {
+            kind: hir::ExprKind::MethodCall(path, rcvr, ..), ..
+        })) = call_node
+        {
+            if Some(rcvr.span) == err.span.primary_span() {
+                err.replace_span_with(path.ident.span);
+            }
+        }
+        if let Some(Node::Expr(hir::Expr {
+            kind:
+                hir::ExprKind::Call(hir::Expr { span, .. }, _)
+                | hir::ExprKind::MethodCall(hir::PathSegment { ident: Ident { span, .. }, .. }, ..),
+            ..
+        })) = hir.find(call_hir_id)
+        {
+            if Some(*span) != err.span.primary_span() {
+                err.span_label(*span, "required by a bound introduced by this call");
+            }
+        }
+    }
+
+    fn point_at_chain(
+        &self,
+        expr: &hir::Expr<'_>,
+        typeck_results: &TypeckResults<'tcx>,
+        type_diffs: Vec<TypeError<'tcx>>,
+        param_env: ty::ParamEnv<'tcx>,
+        err: &mut Diagnostic,
+    ) {
+        let mut primary_spans = vec![];
+        let mut span_labels = vec![];
+
+        let tcx = self.tcx;
+
+        let mut print_root_expr = true;
+        let mut assocs = vec![];
+        let mut expr = expr;
+        let mut prev_ty = self.resolve_vars_if_possible(
+            typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()),
+        );
+        while let hir::ExprKind::MethodCall(_path_segment, rcvr_expr, _args, span) = expr.kind {
+            // Point at every method call in the chain with the resulting type.
+            // vec![1, 2, 3].iter().map(mapper).sum<i32>()
+            //               ^^^^^^ ^^^^^^^^^^^
+            expr = rcvr_expr;
+            let assocs_in_this_method =
+                self.probe_assoc_types_at_expr(&type_diffs, span, prev_ty, expr.hir_id, param_env);
+            assocs.push(assocs_in_this_method);
+            prev_ty = self.resolve_vars_if_possible(
+                typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()),
+            );
+
+            if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
+                && let hir::Path { res: hir::def::Res::Local(hir_id), .. } = path
+                && let Some(hir::Node::Pat(binding)) = self.tcx.hir().find(*hir_id)
+                && let parent_hir_id = self.tcx.hir().get_parent_node(binding.hir_id)
+                && let Some(parent) = self.tcx.hir().find(parent_hir_id)
+            {
+                // We've reached the root of the method call chain...
+                if let hir::Node::Local(local) = parent
+                    && let Some(binding_expr) = local.init
+                {
+                    // ...and it is a binding. Get the binding creation and continue the chain.
+                    expr = binding_expr;
+                }
+                if let hir::Node::Param(param) = parent {
+                    // ...and it is a an fn argument.
+                    let prev_ty = self.resolve_vars_if_possible(
+                        typeck_results.node_type_opt(param.hir_id).unwrap_or(tcx.ty_error()),
+                    );
+                    let assocs_in_this_method = self.probe_assoc_types_at_expr(&type_diffs, param.ty_span, prev_ty, param.hir_id, param_env);
+                    if assocs_in_this_method.iter().any(|a| a.is_some()) {
+                        assocs.push(assocs_in_this_method);
+                        print_root_expr = false;
+                    }
+                    break;
+                }
+            }
+        }
+        // We want the type before deref coercions, otherwise we talk about `&[_]`
+        // instead of `Vec<_>`.
+        if let Some(ty) = typeck_results.expr_ty_opt(expr) && print_root_expr {
+            let ty = with_forced_trimmed_paths!(self.ty_to_string(ty));
+            // Point at the root expression
+            // vec![1, 2, 3].iter().map(mapper).sum<i32>()
+            // ^^^^^^^^^^^^^
+            span_labels.push((expr.span, format!("this expression has type `{ty}`")));
+        };
+        // Only show this if it is not a "trivial" expression (not a method
+        // chain) and there are associated types to talk about.
+        let mut assocs = assocs.into_iter().peekable();
+        while let Some(assocs_in_method) = assocs.next() {
+            let Some(prev_assoc_in_method) = assocs.peek() else {
+                for entry in assocs_in_method {
+                    let Some((span, (assoc, ty))) = entry else { continue; };
+                    if primary_spans.is_empty() || type_diffs.iter().any(|diff| {
+                        let Sorts(expected_found) = diff else { return false; };
+                        self.can_eq(param_env, expected_found.found, ty).is_ok()
+                    }) {
+                        // FIXME: this doesn't quite work for `Iterator::collect`
+                        // because we have `Vec<i32>` and `()`, but we'd want `i32`
+                        // to point at the `.into_iter()` call, but as long as we
+                        // still point at the other method calls that might have
+                        // introduced the issue, this is fine for now.
+                        primary_spans.push(span);
+                    }
+                    span_labels.push((
+                        span,
+                        with_forced_trimmed_paths!(format!(
+                            "`{}` is `{ty}` here",
+                            self.tcx.def_path_str(assoc),
+                        )),
+                    ));
+                }
+                break;
+            };
+            for (entry, prev_entry) in
+                assocs_in_method.into_iter().zip(prev_assoc_in_method.into_iter())
+            {
+                match (entry, prev_entry) {
+                    (Some((span, (assoc, ty))), Some((_, (_, prev_ty)))) => {
+                        let ty_str = with_forced_trimmed_paths!(self.ty_to_string(ty));
+
+                        let assoc = with_forced_trimmed_paths!(self.tcx.def_path_str(assoc));
+                        if self.can_eq(param_env, ty, *prev_ty).is_err() {
+                            if type_diffs.iter().any(|diff| {
+                                let Sorts(expected_found) = diff else { return false; };
+                                self.can_eq(param_env, expected_found.found, ty).is_ok()
+                            }) {
+                                primary_spans.push(span);
+                            }
+                            span_labels
+                                .push((span, format!("`{assoc}` changed to `{ty_str}` here")));
+                        } else {
+                            span_labels.push((span, format!("`{assoc}` remains `{ty_str}` here")));
+                        }
+                    }
+                    (Some((span, (assoc, ty))), None) => {
+                        span_labels.push((
+                            span,
+                            with_forced_trimmed_paths!(format!(
+                                "`{}` is `{}` here",
+                                self.tcx.def_path_str(assoc),
+                                self.ty_to_string(ty),
+                            )),
+                        ));
+                    }
+                    (None, Some(_)) | (None, None) => {}
+                }
+            }
+        }
+        if !primary_spans.is_empty() {
+            let mut multi_span: MultiSpan = primary_spans.into();
+            for (span, label) in span_labels {
+                multi_span.push_span_label(span, label);
+            }
+            err.span_note(
+                multi_span,
+                format!("the method call chain might not have had the expected associated types"),
+            );
+        }
+    }
+
+    fn probe_assoc_types_at_expr(
+        &self,
+        type_diffs: &[TypeError<'tcx>],
+        span: Span,
+        prev_ty: Ty<'tcx>,
+        body_id: hir::HirId,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> Vec<Option<(Span, (DefId, Ty<'tcx>))>> {
+        let ocx = ObligationCtxt::new_in_snapshot(self.infcx);
+        let mut assocs_in_this_method = Vec::with_capacity(type_diffs.len());
+        for diff in type_diffs {
+            let Sorts(expected_found) = diff else { continue; };
+            let ty::Alias(ty::Projection, proj) = expected_found.expected.kind() else { continue; };
+
+            let origin = TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span };
+            let trait_def_id = proj.trait_def_id(self.tcx);
+            // Make `Self` be equivalent to the type of the call chain
+            // expression we're looking at now, so that we can tell what
+            // for example `Iterator::Item` is at this point in the chain.
+            let substs = InternalSubsts::for_item(self.tcx, trait_def_id, |param, _| {
+                match param.kind {
+                    ty::GenericParamDefKind::Type { .. } => {
+                        if param.index == 0 {
+                            return prev_ty.into();
+                        }
+                    }
+                    ty::GenericParamDefKind::Lifetime | ty::GenericParamDefKind::Const { .. } => {}
+                }
+                self.var_for_def(span, param)
+            });
+            // This will hold the resolved type of the associated type, if the
+            // current expression implements the trait that associated type is
+            // in. For example, this would be what `Iterator::Item` is here.
+            let ty_var = self.infcx.next_ty_var(origin);
+            // This corresponds to `<ExprTy as Iterator>::Item = _`.
+            let projection = ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::Projection(
+                ty::ProjectionPredicate {
+                    projection_ty: self.tcx.mk_alias_ty(proj.def_id, substs),
+                    term: ty_var.into(),
+                },
+            )));
+            // Add `<ExprTy as Iterator>::Item = _` obligation.
+            ocx.register_obligation(Obligation::misc(
+                self.tcx, span, body_id, param_env, projection,
+            ));
+            if ocx.select_where_possible().is_empty() {
+                // `ty_var` now holds the type that `Item` is for `ExprTy`.
+                let ty_var = self.resolve_vars_if_possible(ty_var);
+                assocs_in_this_method.push(Some((span, (proj.def_id, ty_var))));
+            } else {
+                // `<ExprTy as Iterator>` didn't select, so likely we've
+                // reached the end of the iterator chain, like the originating
+                // `Vec<_>`.
+                // Keep the space consistent for later zipping.
+                assocs_in_this_method.push(None);
+            }
+        }
+        assocs_in_this_method
+    }
+}
+
+/// Add a hint to add a missing borrow or remove an unnecessary one.
+fn hint_missing_borrow<'tcx>(
+    span: Span,
+    found_span: Span,
+    found: Ty<'tcx>,
+    expected: Ty<'tcx>,
+    found_node: Node<'_>,
+    err: &mut Diagnostic,
+) {
+    let found_args = match found.kind() {
+        ty::FnPtr(f) => f.inputs().skip_binder().iter(),
+        kind => {
+            span_bug!(span, "found was converted to a FnPtr above but is now {:?}", kind)
+        }
+    };
+    let expected_args = match expected.kind() {
+        ty::FnPtr(f) => f.inputs().skip_binder().iter(),
+        kind => {
+            span_bug!(span, "expected was converted to a FnPtr above but is now {:?}", kind)
+        }
+    };
+
+    let fn_decl = found_node
+        .fn_decl()
+        .unwrap_or_else(|| span_bug!(found_span, "found node must be a function"));
+
+    let arg_spans = fn_decl.inputs.iter().map(|ty| ty.span);
+
+    fn get_deref_type_and_refs<'tcx>(mut ty: Ty<'tcx>) -> (Ty<'tcx>, usize) {
+        let mut refs = 0;
+
+        while let ty::Ref(_, new_ty, _) = ty.kind() {
+            ty = *new_ty;
+            refs += 1;
+        }
+
+        (ty, refs)
+    }
+
+    let mut to_borrow = Vec::new();
+    let mut remove_borrow = Vec::new();
+
+    for ((found_arg, expected_arg), arg_span) in found_args.zip(expected_args).zip(arg_spans) {
+        let (found_ty, found_refs) = get_deref_type_and_refs(*found_arg);
+        let (expected_ty, expected_refs) = get_deref_type_and_refs(*expected_arg);
+
+        if found_ty == expected_ty {
+            if found_refs < expected_refs {
+                to_borrow.push((arg_span, expected_arg.to_string()));
+            } else if found_refs > expected_refs {
+                remove_borrow.push((arg_span, expected_arg.to_string()));
+            }
+        }
+    }
+
+    if !to_borrow.is_empty() {
+        err.multipart_suggestion(
+            "consider borrowing the argument",
+            to_borrow,
+            Applicability::MaybeIncorrect,
+        );
+    }
+
+    if !remove_borrow.is_empty() {
+        err.multipart_suggestion(
+            "do not borrow the argument",
+            remove_borrow,
+            Applicability::MaybeIncorrect,
+        );
+    }
 }
 
 /// Collect all the returned expressions within the input expression.
@@ -3205,13 +3629,6 @@ fn suggest_trait_object_return_type_alternatives(
     trait_obj: &str,
     is_object_safe: bool,
 ) {
-    err.span_suggestion(
-        ret_ty,
-        "use some type `T` that is `T: Sized` as the return type if all return paths have the \
-            same type",
-        "T",
-        Applicability::MaybeIncorrect,
-    );
     err.span_suggestion(
         ret_ty,
         &format!(
index d3cfd61e1956d7d82fd433772f0dd2275995a6b2..2566d793d78daa53e4a5b5be00e880ad0dd96b02 100644 (file)
@@ -4,7 +4,6 @@
 
 pub mod auto_trait;
 mod chalk_fulfill;
-pub mod codegen;
 mod coherence;
 pub mod const_evaluatable;
 mod engine;
@@ -20,9 +19,9 @@
 mod specialize;
 mod structural_match;
 mod util;
+mod vtable;
 pub mod wf;
 
-use crate::errors::DumpVTableEntries;
 use crate::infer::outlives::env::OutlivesEnvironment;
 use crate::infer::{InferCtxt, TyCtxtInferExt};
 use crate::traits::error_reporting::TypeErrCtxtExt as _;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
-use rustc_hir::lang_items::LangItem;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::visit::TypeVisitable;
-use rustc_middle::ty::{
-    self, DefIdTree, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeSuperVisitable, VtblEntry,
-};
+use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeSuperVisitable};
 use rustc_middle::ty::{InternalSubsts, SubstsRef};
-use rustc_span::{sym, Span};
-use smallvec::SmallVec;
+use rustc_span::Span;
 
 use std::fmt::Debug;
 use std::ops::ControlFlow;
@@ -430,13 +425,8 @@ pub fn fully_solve_bound<'tcx>(
     bound: DefId,
 ) -> Vec<FulfillmentError<'tcx>> {
     let tcx = infcx.tcx;
-    let trait_ref = ty::TraitRef { def_id: bound, substs: tcx.mk_substs_trait(ty, []) };
-    let obligation = Obligation {
-        cause,
-        recursion_depth: 0,
-        param_env,
-        predicate: ty::Binder::dummy(trait_ref).without_const().to_predicate(tcx),
-    };
+    let trait_ref = tcx.mk_trait_ref(bound, [ty]);
+    let obligation = Obligation::new(tcx, cause, param_env, ty::Binder::dummy(trait_ref));
 
     fully_solve_obligation(infcx, obligation)
 }
@@ -567,369 +557,12 @@ fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
     false
 }
 
-#[derive(Clone, Debug)]
-enum VtblSegment<'tcx> {
-    MetadataDSA,
-    TraitOwnEntries { trait_ref: ty::PolyTraitRef<'tcx>, emit_vptr: bool },
-}
-
-/// Prepare the segments for a vtable
-fn prepare_vtable_segments<'tcx, T>(
-    tcx: TyCtxt<'tcx>,
-    trait_ref: ty::PolyTraitRef<'tcx>,
-    mut segment_visitor: impl FnMut(VtblSegment<'tcx>) -> ControlFlow<T>,
-) -> Option<T> {
-    // The following constraints holds for the final arrangement.
-    // 1. The whole virtual table of the first direct super trait is included as the
-    //    the prefix. If this trait doesn't have any super traits, then this step
-    //    consists of the dsa metadata.
-    // 2. Then comes the proper pointer metadata(vptr) and all own methods for all
-    //    other super traits except those already included as part of the first
-    //    direct super trait virtual table.
-    // 3. finally, the own methods of this trait.
-
-    // This has the advantage that trait upcasting to the first direct super trait on each level
-    // is zero cost, and to another trait includes only replacing the pointer with one level indirection,
-    // while not using too much extra memory.
-
-    // For a single inheritance relationship like this,
-    //   D --> C --> B --> A
-    // The resulting vtable will consists of these segments:
-    //  DSA, A, B, C, D
-
-    // For a multiple inheritance relationship like this,
-    //   D --> C --> A
-    //           \-> B
-    // The resulting vtable will consists of these segments:
-    //  DSA, A, B, B-vptr, C, D
-
-    // For a diamond inheritance relationship like this,
-    //   D --> B --> A
-    //     \-> C -/
-    // The resulting vtable will consists of these segments:
-    //  DSA, A, B, C, C-vptr, D
-
-    // For a more complex inheritance relationship like this:
-    //   O --> G --> C --> A
-    //     \     \     \-> B
-    //     |     |-> F --> D
-    //     |           \-> E
-    //     |-> N --> J --> H
-    //           \     \-> I
-    //           |-> M --> K
-    //                 \-> L
-    // The resulting vtable will consists of these segments:
-    //  DSA, A, B, B-vptr, C, D, D-vptr, E, E-vptr, F, F-vptr, G,
-    //  H, H-vptr, I, I-vptr, J, J-vptr, K, K-vptr, L, L-vptr, M, M-vptr,
-    //  N, N-vptr, O
-
-    // emit dsa segment first.
-    if let ControlFlow::Break(v) = (segment_visitor)(VtblSegment::MetadataDSA) {
-        return Some(v);
-    }
-
-    let mut emit_vptr_on_new_entry = false;
-    let mut visited = util::PredicateSet::new(tcx);
-    let predicate = trait_ref.without_const().to_predicate(tcx);
-    let mut stack: SmallVec<[(ty::PolyTraitRef<'tcx>, _, _); 5]> =
-        smallvec![(trait_ref, emit_vptr_on_new_entry, None)];
-    visited.insert(predicate);
-
-    // the main traversal loop:
-    // basically we want to cut the inheritance directed graph into a few non-overlapping slices of nodes
-    // that each node is emitted after all its descendents have been emitted.
-    // so we convert the directed graph into a tree by skipping all previously visited nodes using a visited set.
-    // this is done on the fly.
-    // Each loop run emits a slice - it starts by find a "childless" unvisited node, backtracking upwards, and it
-    // stops after it finds a node that has a next-sibling node.
-    // This next-sibling node will used as the starting point of next slice.
-
-    // Example:
-    // For a diamond inheritance relationship like this,
-    //   D#1 --> B#0 --> A#0
-    //     \-> C#1 -/
-
-    // Starting point 0 stack [D]
-    // Loop run #0: Stack after diving in is [D B A], A is "childless"
-    // after this point, all newly visited nodes won't have a vtable that equals to a prefix of this one.
-    // Loop run #0: Emitting the slice [B A] (in reverse order), B has a next-sibling node, so this slice stops here.
-    // Loop run #0: Stack after exiting out is [D C], C is the next starting point.
-    // Loop run #1: Stack after diving in is [D C], C is "childless", since its child A is skipped(already emitted).
-    // Loop run #1: Emitting the slice [D C] (in reverse order). No one has a next-sibling node.
-    // Loop run #1: Stack after exiting out is []. Now the function exits.
-
-    loop {
-        // dive deeper into the stack, recording the path
-        'diving_in: loop {
-            if let Some((inner_most_trait_ref, _, _)) = stack.last() {
-                let inner_most_trait_ref = *inner_most_trait_ref;
-                let mut direct_super_traits_iter = tcx
-                    .super_predicates_of(inner_most_trait_ref.def_id())
-                    .predicates
-                    .into_iter()
-                    .filter_map(move |(pred, _)| {
-                        pred.subst_supertrait(tcx, &inner_most_trait_ref).to_opt_poly_trait_pred()
-                    });
-
-                'diving_in_skip_visited_traits: loop {
-                    if let Some(next_super_trait) = direct_super_traits_iter.next() {
-                        if visited.insert(next_super_trait.to_predicate(tcx)) {
-                            // We're throwing away potential constness of super traits here.
-                            // FIXME: handle ~const super traits
-                            let next_super_trait = next_super_trait.map_bound(|t| t.trait_ref);
-                            stack.push((
-                                next_super_trait,
-                                emit_vptr_on_new_entry,
-                                Some(direct_super_traits_iter),
-                            ));
-                            break 'diving_in_skip_visited_traits;
-                        } else {
-                            continue 'diving_in_skip_visited_traits;
-                        }
-                    } else {
-                        break 'diving_in;
-                    }
-                }
-            }
-        }
-
-        // Other than the left-most path, vptr should be emitted for each trait.
-        emit_vptr_on_new_entry = true;
-
-        // emit innermost item, move to next sibling and stop there if possible, otherwise jump to outer level.
-        'exiting_out: loop {
-            if let Some((inner_most_trait_ref, emit_vptr, siblings_opt)) = stack.last_mut() {
-                if let ControlFlow::Break(v) = (segment_visitor)(VtblSegment::TraitOwnEntries {
-                    trait_ref: *inner_most_trait_ref,
-                    emit_vptr: *emit_vptr,
-                }) {
-                    return Some(v);
-                }
-
-                'exiting_out_skip_visited_traits: loop {
-                    if let Some(siblings) = siblings_opt {
-                        if let Some(next_inner_most_trait_ref) = siblings.next() {
-                            if visited.insert(next_inner_most_trait_ref.to_predicate(tcx)) {
-                                // We're throwing away potential constness of super traits here.
-                                // FIXME: handle ~const super traits
-                                let next_inner_most_trait_ref =
-                                    next_inner_most_trait_ref.map_bound(|t| t.trait_ref);
-                                *inner_most_trait_ref = next_inner_most_trait_ref;
-                                *emit_vptr = emit_vptr_on_new_entry;
-                                break 'exiting_out;
-                            } else {
-                                continue 'exiting_out_skip_visited_traits;
-                            }
-                        }
-                    }
-                    stack.pop();
-                    continue 'exiting_out;
-                }
-            }
-            // all done
-            return None;
-        }
-    }
-}
-
-fn dump_vtable_entries<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    sp: Span,
-    trait_ref: ty::PolyTraitRef<'tcx>,
-    entries: &[VtblEntry<'tcx>],
-) {
-    tcx.sess.emit_err(DumpVTableEntries {
-        span: sp,
-        trait_ref,
-        entries: format!("{:#?}", entries),
-    });
-}
-
-fn own_existential_vtable_entries<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId) -> &'tcx [DefId] {
-    let trait_methods = tcx
-        .associated_items(trait_def_id)
-        .in_definition_order()
-        .filter(|item| item.kind == ty::AssocKind::Fn);
-    // Now list each method's DefId (for within its trait).
-    let own_entries = trait_methods.filter_map(move |trait_method| {
-        debug!("own_existential_vtable_entry: trait_method={:?}", trait_method);
-        let def_id = trait_method.def_id;
-
-        // Some methods cannot be called on an object; skip those.
-        if !is_vtable_safe_method(tcx, trait_def_id, &trait_method) {
-            debug!("own_existential_vtable_entry: not vtable safe");
-            return None;
-        }
-
-        Some(def_id)
-    });
-
-    tcx.arena.alloc_from_iter(own_entries.into_iter())
-}
-
-/// Given a trait `trait_ref`, iterates the vtable entries
-/// that come from `trait_ref`, including its supertraits.
-fn vtable_entries<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    trait_ref: ty::PolyTraitRef<'tcx>,
-) -> &'tcx [VtblEntry<'tcx>] {
-    debug!("vtable_entries({:?})", trait_ref);
-
-    let mut entries = vec![];
-
-    let vtable_segment_callback = |segment| -> ControlFlow<()> {
-        match segment {
-            VtblSegment::MetadataDSA => {
-                entries.extend(TyCtxt::COMMON_VTABLE_ENTRIES);
-            }
-            VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
-                let existential_trait_ref = trait_ref
-                    .map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref));
-
-                // Lookup the shape of vtable for the trait.
-                let own_existential_entries =
-                    tcx.own_existential_vtable_entries(existential_trait_ref.def_id());
-
-                let own_entries = own_existential_entries.iter().copied().map(|def_id| {
-                    debug!("vtable_entries: trait_method={:?}", def_id);
-
-                    // The method may have some early-bound lifetimes; add regions for those.
-                    let substs = trait_ref.map_bound(|trait_ref| {
-                        InternalSubsts::for_item(tcx, def_id, |param, _| match param.kind {
-                            GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
-                            GenericParamDefKind::Type { .. }
-                            | GenericParamDefKind::Const { .. } => {
-                                trait_ref.substs[param.index as usize]
-                            }
-                        })
-                    });
-
-                    // The trait type may have higher-ranked lifetimes in it;
-                    // erase them if they appear, so that we get the type
-                    // at some particular call site.
-                    let substs = tcx
-                        .normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), substs);
-
-                    // It's possible that the method relies on where-clauses that
-                    // do not hold for this particular set of type parameters.
-                    // Note that this method could then never be called, so we
-                    // do not want to try and codegen it, in that case (see #23435).
-                    let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs);
-                    if impossible_predicates(tcx, predicates.predicates) {
-                        debug!("vtable_entries: predicates do not hold");
-                        return VtblEntry::Vacant;
-                    }
-
-                    let instance = ty::Instance::resolve_for_vtable(
-                        tcx,
-                        ty::ParamEnv::reveal_all(),
-                        def_id,
-                        substs,
-                    )
-                    .expect("resolution failed during building vtable representation");
-                    VtblEntry::Method(instance)
-                });
-
-                entries.extend(own_entries);
-
-                if emit_vptr {
-                    entries.push(VtblEntry::TraitVPtr(trait_ref));
-                }
-            }
-        }
-
-        ControlFlow::Continue(())
-    };
-
-    let _ = prepare_vtable_segments(tcx, trait_ref, vtable_segment_callback);
-
-    if tcx.has_attr(trait_ref.def_id(), sym::rustc_dump_vtable) {
-        let sp = tcx.def_span(trait_ref.def_id());
-        dump_vtable_entries(tcx, sp, trait_ref, &entries);
-    }
-
-    tcx.arena.alloc_from_iter(entries.into_iter())
-}
-
-/// Find slot base for trait methods within vtable entries of another trait
-fn vtable_trait_first_method_offset<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    key: (
-        ty::PolyTraitRef<'tcx>, // trait_to_be_found
-        ty::PolyTraitRef<'tcx>, // trait_owning_vtable
-    ),
-) -> usize {
-    let (trait_to_be_found, trait_owning_vtable) = key;
-
-    // #90177
-    let trait_to_be_found_erased = tcx.erase_regions(trait_to_be_found);
-
-    let vtable_segment_callback = {
-        let mut vtable_base = 0;
-
-        move |segment| {
-            match segment {
-                VtblSegment::MetadataDSA => {
-                    vtable_base += TyCtxt::COMMON_VTABLE_ENTRIES.len();
-                }
-                VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
-                    if tcx.erase_regions(trait_ref) == trait_to_be_found_erased {
-                        return ControlFlow::Break(vtable_base);
-                    }
-                    vtable_base += util::count_own_vtable_entries(tcx, trait_ref);
-                    if emit_vptr {
-                        vtable_base += 1;
-                    }
-                }
-            }
-            ControlFlow::Continue(())
-        }
-    };
-
-    if let Some(vtable_base) =
-        prepare_vtable_segments(tcx, trait_owning_vtable, vtable_segment_callback)
-    {
-        vtable_base
-    } else {
-        bug!("Failed to find info for expected trait in vtable");
-    }
-}
-
-/// Find slot offset for trait vptr within vtable entries of another trait
-pub fn vtable_trait_upcasting_coercion_new_vptr_slot<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    key: (
-        Ty<'tcx>, // trait object type whose trait owning vtable
-        Ty<'tcx>, // trait object for supertrait
-    ),
-) -> Option<usize> {
-    let (source, target) = key;
-    assert!(matches!(&source.kind(), &ty::Dynamic(..)) && !source.needs_infer());
-    assert!(matches!(&target.kind(), &ty::Dynamic(..)) && !target.needs_infer());
-
-    // this has been typecked-before, so diagnostics is not really needed.
-    let unsize_trait_did = tcx.require_lang_item(LangItem::Unsize, None);
-
-    let trait_ref = tcx.mk_trait_ref(unsize_trait_did, [source, target]);
-
-    match tcx.codegen_select_candidate((ty::ParamEnv::reveal_all(), ty::Binder::dummy(trait_ref))) {
-        Ok(ImplSource::TraitUpcasting(implsrc_traitcasting)) => {
-            implsrc_traitcasting.vtable_vptr_slot
-        }
-        otherwise => bug!("expected TraitUpcasting candidate, got {otherwise:?}"),
-    }
-}
-
 pub fn provide(providers: &mut ty::query::Providers) {
     object_safety::provide(providers);
-    structural_match::provide(providers);
+    vtable::provide(providers);
     *providers = ty::query::Providers {
         specialization_graph_of: specialize::specialization_graph_provider,
         specializes: specialize::specializes,
-        codegen_select_candidate: codegen::codegen_select_candidate,
-        own_existential_vtable_entries,
-        vtable_entries,
-        vtable_trait_upcasting_coercion_new_vptr_slot,
         subst_and_check_impossible_predicates,
         is_impossible_method,
         ..*providers
index a45749fe48cd48a5d625deb3d7e146ec942984e8..8b1ced78f4e8a06fe4a69ed1d0a4f49c8e043935 100644 (file)
@@ -589,7 +589,7 @@ fn object_ty_for_trait<'tcx>(
             let pred = obligation.predicate.to_opt_poly_projection_pred()?;
             Some(pred.map_bound(|p| {
                 ty::ExistentialPredicate::Projection(ty::ExistentialProjection {
-                    item_def_id: p.projection_ty.item_def_id,
+                    def_id: p.projection_ty.def_id,
                     substs: p.projection_ty.substs,
                     term: p.term,
                 })
@@ -694,18 +694,12 @@ fn receiver_is_dispatchable<'tcx>(
 
         // U: Trait<Arg1, ..., ArgN>
         let trait_predicate = {
-            let substs =
-                InternalSubsts::for_item(tcx, method.trait_container(tcx).unwrap(), |param, _| {
-                    if param.index == 0 {
-                        unsized_self_ty.into()
-                    } else {
-                        tcx.mk_param_from_def(param)
-                    }
-                });
+            let trait_def_id = method.trait_container(tcx).unwrap();
+            let substs = InternalSubsts::for_item(tcx, trait_def_id, |param, _| {
+                if param.index == 0 { unsized_self_ty.into() } else { tcx.mk_param_from_def(param) }
+            });
 
-            ty::Binder::dummy(ty::TraitRef { def_id: unsize_did, substs })
-                .without_const()
-                .to_predicate(tcx)
+            ty::Binder::dummy(tcx.mk_trait_ref(trait_def_id, substs)).to_predicate(tcx)
         };
 
         let caller_bounds: Vec<Predicate<'tcx>> =
@@ -794,13 +788,13 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
                         ControlFlow::CONTINUE
                     }
                 }
-                ty::Projection(ref data)
-                    if self.tcx.def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder =>
+                ty::Alias(ty::Projection, ref data)
+                    if self.tcx.def_kind(data.def_id) == DefKind::ImplTraitPlaceholder =>
                 {
                     // We'll deny these later in their own pass
                     ControlFlow::CONTINUE
                 }
-                ty::Projection(ref data) => {
+                ty::Alias(ty::Projection, ref data) => {
                     // This is a projected type `<Foo as SomeTrait>::X`.
 
                     // Compute supertraits of current trait lazily.
@@ -861,10 +855,10 @@ pub fn contains_illegal_impl_trait_in_trait<'tcx>(
     // FIXME(RPITIT): Perhaps we should use a visitor here?
     ty.skip_binder().walk().find_map(|arg| {
         if let ty::GenericArgKind::Type(ty) = arg.unpack()
-            && let ty::Projection(proj) = ty.kind()
-            && tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder
+            && let ty::Alias(ty::Projection, proj) = ty.kind()
+            && tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder
         {
-            Some(MethodViolationCode::ReferencesImplTraitInTrait(tcx.def_span(proj.item_def_id)))
+            Some(MethodViolationCode::ReferencesImplTraitInTrait(tcx.def_span(proj.def_id)))
         } else {
             None
         }
index 5789754e4fcefd6f19fa458f1f80cd5e4d7e5445..84d7244c1db786a6144c32e6fdf6be92e2e1c3c2 100644 (file)
@@ -45,7 +45,7 @@
 
 pub type ProjectionObligation<'tcx> = Obligation<'tcx, ty::ProjectionPredicate<'tcx>>;
 
-pub type ProjectionTyObligation<'tcx> = Obligation<'tcx, ty::ProjectionTy<'tcx>>;
+pub type ProjectionTyObligation<'tcx> = Obligation<'tcx, ty::AliasTy<'tcx>>;
 
 pub(super) struct InProgress;
 
@@ -496,7 +496,9 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
             // This is really important. While we *can* handle this, this has
             // severe performance implications for large opaque types with
             // late-bound regions. See `issue-88862` benchmark.
-            ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. })
+                if !substs.has_escaping_bound_vars() =>
+            {
                 // Only normalize `impl Trait` outside of type inference, usually in codegen.
                 match self.param_env.reveal() {
                     Reveal::UserFacing => ty.super_fold_with(self),
@@ -523,7 +525,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 }
             }
 
-            ty::Projection(data) if !data.has_escaping_bound_vars() => {
+            ty::Alias(ty::Projection, data) if !data.has_escaping_bound_vars() => {
                 // This branch is *mostly* just an optimization: when we don't
                 // have escaping bound vars, we don't need to replace them with
                 // placeholders (see branch below). *Also*, we know that we can
@@ -562,7 +564,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 normalized_ty.ty().unwrap()
             }
 
-            ty::Projection(data) => {
+            ty::Alias(ty::Projection, data) => {
                 // If there are escaping bound vars, we temporarily replace the
                 // bound vars with placeholders. Note though, that in the case
                 // that we still can't project for whatever reason (e.g. self
@@ -957,7 +959,7 @@ fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
 pub fn normalize_projection_type<'a, 'b, 'tcx>(
     selcx: &'a mut SelectionContext<'b, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    projection_ty: ty::ProjectionTy<'tcx>,
+    projection_ty: ty::AliasTy<'tcx>,
     cause: ObligationCause<'tcx>,
     depth: usize,
     obligations: &mut Vec<PredicateObligation<'tcx>>,
@@ -995,7 +997,7 @@ pub fn normalize_projection_type<'a, 'b, 'tcx>(
 fn opt_normalize_projection_type<'a, 'b, 'tcx>(
     selcx: &'a mut SelectionContext<'b, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    projection_ty: ty::ProjectionTy<'tcx>,
+    projection_ty: ty::AliasTy<'tcx>,
     cause: ObligationCause<'tcx>,
     depth: usize,
     obligations: &mut Vec<PredicateObligation<'tcx>>,
@@ -1177,7 +1179,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
 fn normalize_to_error<'a, 'tcx>(
     selcx: &mut SelectionContext<'a, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    projection_ty: ty::ProjectionTy<'tcx>,
+    projection_ty: ty::AliasTy<'tcx>,
     cause: ObligationCause<'tcx>,
     depth: usize,
 ) -> NormalizedTy<'tcx> {
@@ -1189,10 +1191,9 @@ fn normalize_to_error<'a, 'tcx>(
         predicate: trait_ref.without_const().to_predicate(selcx.tcx()),
     };
     let tcx = selcx.infcx.tcx;
-    let def_id = projection_ty.item_def_id;
     let new_value = selcx.infcx.next_ty_var(TypeVariableOrigin {
         kind: TypeVariableOriginKind::NormalizeProjectionType,
-        span: tcx.def_span(def_id),
+        span: tcx.def_span(projection_ty.def_id),
     });
     Normalized { value: new_value, obligations: vec![trait_obligation] }
 }
@@ -1270,7 +1271,7 @@ fn project<'cx, 'tcx>(
             // need to investigate whether or not this is fine.
             selcx
                 .tcx()
-                .mk_projection(obligation.predicate.item_def_id, obligation.predicate.substs)
+                .mk_projection(obligation.predicate.def_id, obligation.predicate.substs)
                 .into(),
         )),
         // Error occurred while trying to processing impls.
@@ -1290,13 +1291,12 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
     candidate_set: &mut ProjectionCandidateSet<'tcx>,
 ) {
     let tcx = selcx.tcx();
-    if tcx.def_kind(obligation.predicate.item_def_id) == DefKind::ImplTraitPlaceholder {
-        let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.item_def_id);
+    if tcx.def_kind(obligation.predicate.def_id) == DefKind::ImplTraitPlaceholder {
+        let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.def_id);
         // If we are trying to project an RPITIT with trait's default `Self` parameter,
         // then we must be within a default trait body.
         if obligation.predicate.self_ty()
-            == ty::InternalSubsts::identity_for_item(tcx, obligation.predicate.item_def_id)
-                .type_at(0)
+            == ty::InternalSubsts::identity_for_item(tcx, obligation.predicate.def_id).type_at(0)
             && tcx.associated_item(trait_fn_def_id).defaultness(tcx).has_value()
         {
             candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(
@@ -1309,8 +1309,7 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
         let trait_substs =
             obligation.predicate.substs.truncate_to(tcx, tcx.generics_of(trait_def_id));
         // FIXME(named-returns): Binders
-        let trait_predicate =
-            ty::Binder::dummy(ty::TraitRef { def_id: trait_def_id, substs: trait_substs });
+        let trait_predicate = ty::Binder::dummy(tcx.mk_trait_ref(trait_def_id, trait_substs));
 
         let _ = selcx.infcx.commit_if_ok(|_| {
             match selcx.select(&obligation.with(tcx, trait_predicate)) {
@@ -1377,8 +1376,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
     // Check whether the self-type is itself a projection.
     // If so, extract what we know from the trait and try to come up with a good answer.
     let bounds = match *obligation.predicate.self_ty().kind() {
-        ty::Projection(ref data) => tcx.bound_item_bounds(data.item_def_id).subst(tcx, data.substs),
-        ty::Opaque(def_id, substs) => tcx.bound_item_bounds(def_id).subst(tcx, substs),
+        ty::Alias(_, ref data) => tcx.bound_item_bounds(data.def_id).subst(tcx, data.substs),
         ty::Infer(ty::TyVar(_)) => {
             // If the self-type is an inference variable, then it MAY wind up
             // being a projected type, so induce an ambiguity.
@@ -1430,7 +1428,7 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>(
     };
     let env_predicates = data
         .projection_bounds()
-        .filter(|bound| bound.item_def_id() == obligation.predicate.item_def_id)
+        .filter(|bound| bound.item_def_id() == obligation.predicate.def_id)
         .map(|p| p.with_self_ty(tcx, object_ty).to_predicate(tcx));
 
     assemble_candidates_from_predicates(
@@ -1462,7 +1460,7 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>(
             predicate.kind().skip_binder()
         {
             let data = bound_predicate.rebind(data);
-            if data.projection_def_id() != obligation.predicate.item_def_id {
+            if data.projection_def_id() != obligation.predicate.def_id {
                 continue;
             }
 
@@ -1503,7 +1501,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
     candidate_set: &mut ProjectionCandidateSet<'tcx>,
 ) {
     // Can't assemble candidate from impl for RPITIT
-    if selcx.tcx().def_kind(obligation.predicate.item_def_id) == DefKind::ImplTraitPlaceholder {
+    if selcx.tcx().def_kind(obligation.predicate.def_id) == DefKind::ImplTraitPlaceholder {
         return;
     }
 
@@ -1555,7 +1553,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                 // NOTE: This should be kept in sync with the similar code in
                 // `rustc_ty_utils::instance::resolve_associated_item()`.
                 let node_item =
-                    assoc_def(selcx, impl_data.impl_def_id, obligation.predicate.item_def_id)
+                    assoc_def(selcx, impl_data.impl_def_id, obligation.predicate.def_id)
                         .map_err(|ErrorGuaranteed { .. }| ())?;
 
                 if node_item.is_final() {
@@ -1616,8 +1614,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                          // type parameters, opaques, and unnormalized projections have pointer
                         // metadata if they're known (e.g. by the param_env) to be sized
                         ty::Param(_)
-                        | ty::Projection(..)
-                        | ty::Opaque(..)
+                        | ty::Alias(..)
                         | ty::Bound(..)
                         | ty::Placeholder(..)
                         | ty::Infer(..)
@@ -1671,7 +1668,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
 
                         // type parameters, opaques, and unnormalized projections have pointer
                         // metadata if they're known (e.g. by the param_env) to be sized
-                        ty::Param(_) | ty::Projection(..) | ty::Opaque(..)
+                        ty::Param(_) | ty::Alias(..)
                             if selcx.infcx.predicate_must_hold_modulo_regions(
                                 &obligation.with(
                                     selcx.tcx(),
@@ -1687,8 +1684,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
 
                         // FIXME(compiler-errors): are Bound and Placeholder types ever known sized?
                         ty::Param(_)
-                        | ty::Projection(..)
-                        | ty::Opaque(..)
+                        | ty::Alias(..)
                         | ty::Bound(..)
                         | ty::Placeholder(..)
                         | ty::Infer(..)
@@ -1788,7 +1784,7 @@ fn confirm_candidate<'cx, 'tcx>(
         ProjectionCandidate::ImplTraitInTrait(ImplTraitInTraitCandidate::Trait) => Progress {
             term: selcx
                 .tcx()
-                .mk_opaque(obligation.predicate.item_def_id, obligation.predicate.substs)
+                .mk_opaque(obligation.predicate.def_id, obligation.predicate.substs)
                 .into(),
             obligations: vec![],
         },
@@ -1860,7 +1856,7 @@ fn confirm_generator_candidate<'cx, 'tcx>(
         gen_sig,
     )
     .map_bound(|(trait_ref, yield_ty, return_ty)| {
-        let name = tcx.associated_item(obligation.predicate.item_def_id).name;
+        let name = tcx.associated_item(obligation.predicate.def_id).name;
         let ty = if name == sym::Return {
             return_ty
         } else if name == sym::Yield {
@@ -1870,10 +1866,7 @@ fn confirm_generator_candidate<'cx, 'tcx>(
         };
 
         ty::ProjectionPredicate {
-            projection_ty: ty::ProjectionTy {
-                substs: trait_ref.substs,
-                item_def_id: obligation.predicate.item_def_id,
-            },
+            projection_ty: tcx.mk_alias_ty(obligation.predicate.def_id, trait_ref.substs),
             term: ty.into(),
         }
     });
@@ -1909,13 +1902,10 @@ fn confirm_future_candidate<'cx, 'tcx>(
         gen_sig,
     )
     .map_bound(|(trait_ref, return_ty)| {
-        debug_assert_eq!(tcx.associated_item(obligation.predicate.item_def_id).name, sym::Output);
+        debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name, sym::Output);
 
         ty::ProjectionPredicate {
-            projection_ty: ty::ProjectionTy {
-                substs: trait_ref.substs,
-                item_def_id: obligation.predicate.item_def_id,
-            },
+            projection_ty: tcx.mk_alias_ty(obligation.predicate.def_id, trait_ref.substs),
             term: return_ty.into(),
         }
     });
@@ -1934,7 +1924,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>(
     let self_ty = obligation.predicate.self_ty();
     let substs = tcx.mk_substs([self_ty.into()].iter());
     let lang_items = tcx.lang_items();
-    let item_def_id = obligation.predicate.item_def_id;
+    let item_def_id = obligation.predicate.def_id;
     let trait_def_id = tcx.trait_of_item(item_def_id).unwrap();
     let (term, obligations) = if lang_items.discriminant_kind_trait() == Some(trait_def_id) {
         let discriminant_def_id = tcx.require_lang_item(LangItem::Discriminant, None);
@@ -1969,7 +1959,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>(
     };
 
     let predicate =
-        ty::ProjectionPredicate { projection_ty: ty::ProjectionTy { substs, item_def_id }, term };
+        ty::ProjectionPredicate { projection_ty: tcx.mk_alias_ty(item_def_id, substs), term };
 
     confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false)
         .with_addl_obligations(obligations)
@@ -2038,10 +2028,7 @@ fn confirm_callable_candidate<'cx, 'tcx>(
         flag,
     )
     .map_bound(|(trait_ref, ret_type)| ty::ProjectionPredicate {
-        projection_ty: ty::ProjectionTy {
-            substs: trait_ref.substs,
-            item_def_id: fn_once_output_def_id,
-        },
+        projection_ty: tcx.mk_alias_ty(fn_once_output_def_id, trait_ref.substs),
         term: ret_type.into(),
     });
 
@@ -2122,7 +2109,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
     let tcx = selcx.tcx();
 
     let ImplSourceUserDefinedData { impl_def_id, substs, mut nested } = impl_impl_source;
-    let assoc_item_id = obligation.predicate.item_def_id;
+    let assoc_item_id = obligation.predicate.def_id;
     let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap();
 
     let param_env = obligation.param_env;
@@ -2222,7 +2209,7 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
     let tcx = selcx.tcx();
     let mut obligations = data.nested;
 
-    let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.item_def_id);
+    let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.def_id);
     let Ok(leaf_def) = assoc_def(selcx, data.impl_def_id, trait_fn_def_id) else {
         return Progress { term: tcx.ty_error().into(), obligations };
     };
@@ -2233,9 +2220,7 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
     // Use the default `impl Trait` for the trait, e.g., for a default trait body
     if leaf_def.item.container == ty::AssocItemContainer::TraitContainer {
         return Progress {
-            term: tcx
-                .mk_opaque(obligation.predicate.item_def_id, obligation.predicate.substs)
-                .into(),
+            term: tcx.mk_opaque(obligation.predicate.def_id, obligation.predicate.substs).into(),
             obligations,
         };
     }
@@ -2302,7 +2287,7 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
         obligation.recursion_depth + 1,
         tcx.bound_trait_impl_trait_tys(impl_fn_def_id)
             .map_bound(|tys| {
-                tys.map_or_else(|_| tcx.ty_error(), |tys| tys[&obligation.predicate.item_def_id])
+                tys.map_or_else(|_| tcx.ty_error(), |tys| tys[&obligation.predicate.def_id])
             })
             .subst(tcx, impl_fn_substs),
         &mut obligations,
@@ -2320,7 +2305,7 @@ fn assoc_ty_own_obligations<'cx, 'tcx>(
 ) {
     let tcx = selcx.tcx();
     let own = tcx
-        .predicates_of(obligation.predicate.item_def_id)
+        .predicates_of(obligation.predicate.def_id)
         .instantiate_own(tcx, obligation.predicate.substs);
     for (predicate, span) in std::iter::zip(own.predicates, own.spans) {
         let normalized = normalize_with_depth_to(
@@ -2343,13 +2328,13 @@ fn assoc_ty_own_obligations<'cx, 'tcx>(
             ObligationCause::new(
                 obligation.cause.span,
                 obligation.cause.body_id,
-                super::ItemObligation(obligation.predicate.item_def_id),
+                super::ItemObligation(obligation.predicate.def_id),
             )
         } else {
             ObligationCause::new(
                 obligation.cause.span,
                 obligation.cause.body_id,
-                super::BindingObligation(obligation.predicate.item_def_id, span),
+                super::BindingObligation(obligation.predicate.def_id, span),
             )
         };
         nested.push(Obligation::with_depth(
index aad3c37f84e5a783250e31ad60ad9d512a103c47..0f21813bc40ae1a85dfd1185f7199ecd2eec708a 100644 (file)
@@ -62,9 +62,8 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
 
         // The following *might* require a destructor: needs deeper inspection.
         ty::Dynamic(..)
-        | ty::Projection(..)
+        | ty::Alias(..)
         | ty::Param(_)
-        | ty::Opaque(..)
         | ty::Placeholder(..)
         | ty::Infer(_)
         | ty::Bound(..)
index 7ad532d8a34645544996dd1930fbf45284d9d1b7..c6ef13e185b2d7526e6870397a3932e451e6a49c 100644 (file)
@@ -205,7 +205,9 @@ fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
             // This is really important. While we *can* handle this, this has
             // severe performance implications for large opaque types with
             // late-bound regions. See `issue-88862` benchmark.
-            ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. })
+                if !substs.has_escaping_bound_vars() =>
+            {
                 // Only normalize `impl Trait` outside of type inference, usually in codegen.
                 match self.param_env.reveal() {
                     Reveal::UserFacing => ty.try_super_fold_with(self),
@@ -242,7 +244,7 @@ fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
                 }
             }
 
-            ty::Projection(data) if !data.has_escaping_bound_vars() => {
+            ty::Alias(ty::Projection, data) if !data.has_escaping_bound_vars() => {
                 // This branch is just an optimization: when we don't have escaping bound vars,
                 // we don't need to replace them with placeholders (see branch below).
 
@@ -291,7 +293,7 @@ fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
                 }
             }
 
-            ty::Projection(data) => {
+            ty::Alias(ty::Projection, data) => {
                 // See note in `rustc_trait_selection::traits::project`
 
                 let tcx = self.infcx.tcx;
index bfa318787e546869e2c0efe8ebcbb679579feaf0..34b5fc4891eb36643e65c2412e8ac70330559e55 100644 (file)
@@ -26,7 +26,7 @@ pub(crate) fn update<'tcx, T>(
                 .kind()
                 .rebind(
                     // (*) binder moved here
-                    ty::PredicateKind::Clause(ty::Clause::Trait(tpred.with_self_type(infcx.tcx, new_self_ty)))
+                    ty::PredicateKind::Clause(ty::Clause::Trait(tpred.with_self_ty(infcx.tcx, new_self_ty)))
                 ),
         );
         // Don't report overflow errors. Otherwise equivalent to may_hold.
index e4b70f0d2ffa7afbfc54dbf7fdaa252400ef1226..c54d901e9b10aff43f7e9106632beef59ae3e495 100644 (file)
@@ -138,7 +138,7 @@ fn assemble_candidates_from_projected_tys(
         // Before we go into the whole placeholder thing, just
         // quickly check if the self-type is a projection at all.
         match obligation.predicate.skip_binder().trait_ref.self_ty().kind() {
-            ty::Projection(_) | ty::Opaque(..) => {}
+            ty::Alias(..) => {}
             ty::Infer(ty::TyVar(_)) => {
                 span_bug!(
                     obligation.cause.span,
@@ -394,7 +394,7 @@ fn assemble_candidates_from_auto_impls(
                     // still be provided by a manual implementation for
                     // this trait and type.
                 }
-                ty::Param(..) | ty::Projection(..) => {
+                ty::Param(..) | ty::Alias(ty::Projection, ..) => {
                     // In these cases, we don't know what the actual
                     // type is.  Therefore, we cannot break it down
                     // into its constituent types. So we don't
@@ -536,10 +536,7 @@ fn need_migrate_deref_output_trait_object(
             let ty = traits::normalize_projection_type(
                 self,
                 param_env,
-                ty::ProjectionTy {
-                    item_def_id: tcx.lang_items().deref_target()?,
-                    substs: trait_ref.substs,
-                },
+                tcx.mk_alias_ty(tcx.lang_items().deref_target()?, trait_ref.substs),
                 cause.clone(),
                 0,
                 // We're *intentionally* throwing these away,
@@ -737,13 +734,12 @@ fn assemble_const_destruct_candidates(
 
         let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
         match self_ty.skip_binder().kind() {
-            ty::Opaque(..)
+            ty::Alias(..)
             | ty::Dynamic(..)
             | ty::Error(_)
             | ty::Bound(..)
             | ty::Param(_)
-            | ty::Placeholder(_)
-            | ty::Projection(_) => {
+            | ty::Placeholder(_) => {
                 // We don't know if these are `~const Destruct`, at least
                 // not structurally... so don't push a candidate.
             }
@@ -829,8 +825,7 @@ fn assemble_candidate_for_tuple(
             | ty::Generator(_, _, _)
             | ty::GeneratorWitness(_)
             | ty::Never
-            | ty::Projection(_)
-            | ty::Opaque(_, _)
+            | ty::Alias(..)
             | ty::Param(_)
             | ty::Bound(_, _)
             | ty::Error(_)
index 22cd700dcb5f4747705c2c31185cace511e59529..f6fe71fbd4f889ce18c08f0c08b890b4939363c1 100644 (file)
 
 use crate::traits::project::{normalize_with_depth, normalize_with_depth_to};
 use crate::traits::util::{self, closure_trait_ref_and_return_type, predicate_for_trait_def};
+use crate::traits::vtable::{
+    count_own_vtable_entries, prepare_vtable_segments, vtable_trait_first_method_offset,
+    VtblSegment,
+};
 use crate::traits::{
     BuiltinDerivedObligation, ImplDerivedObligation, ImplDerivedObligationCause, ImplSource,
     ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData,
@@ -26,7 +30,7 @@
     ImplSourceGeneratorData, ImplSourceObjectData, ImplSourceTraitAliasData,
     ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, Normalized, ObjectCastObligation,
     Obligation, ObligationCause, OutputTypeParameterMismatch, PredicateObligation, Selection,
-    SelectionError, TraitNotObjectSafe, TraitObligation, Unimplemented, VtblSegment,
+    SelectionError, TraitNotObjectSafe, TraitObligation, Unimplemented,
 };
 
 use super::BuiltinImplConditions;
@@ -151,8 +155,7 @@ fn confirm_projection_candidate(
         let placeholder_self_ty = placeholder_trait_predicate.self_ty();
         let placeholder_trait_predicate = ty::Binder::dummy(placeholder_trait_predicate);
         let (def_id, substs) = match *placeholder_self_ty.kind() {
-            ty::Projection(proj) => (proj.item_def_id, proj.substs),
-            ty::Opaque(def_id, substs) => (def_id, substs),
+            ty::Alias(_, ty::AliasTy { def_id, substs, .. }) => (def_id, substs),
             _ => bug!("projection candidate for unexpected type: {:?}", placeholder_self_ty),
         };
 
@@ -180,7 +183,7 @@ fn confirm_projection_candidate(
                 .map_err(|_| Unimplemented)
         })?);
 
-        if let ty::Projection(..) = placeholder_self_ty.kind() {
+        if let ty::Alias(ty::Projection, ..) = placeholder_self_ty.kind() {
             let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs).predicates;
             debug!(?predicates, "projection predicates");
             for predicate in predicates {
@@ -583,7 +586,7 @@ fn confirm_object_candidate(
 
         debug!(?nested, "object nested obligations");
 
-        let vtable_base = super::super::vtable_trait_first_method_offset(
+        let vtable_base = vtable_trait_first_method_offset(
             tcx,
             (unnormalized_upcast_trait_ref, ty::Binder::dummy(object_trait_ref)),
         );
@@ -904,7 +907,7 @@ fn confirm_trait_upcasting_unsize_candidate(
                         vptr_offset += TyCtxt::COMMON_VTABLE_ENTRIES.len();
                     }
                     VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
-                        vptr_offset += util::count_own_vtable_entries(tcx, trait_ref);
+                        vptr_offset += count_own_vtable_entries(tcx, trait_ref);
                         if trait_ref == upcast_trait_ref {
                             if emit_vptr {
                                 return ControlFlow::Break(Some(vptr_offset));
@@ -923,8 +926,7 @@ fn confirm_trait_upcasting_unsize_candidate(
         };
 
         let vtable_vptr_slot =
-            super::super::prepare_vtable_segments(tcx, source_trait_ref, vtable_segment_callback)
-                .unwrap();
+            prepare_vtable_segments(tcx, source_trait_ref, vtable_segment_callback).unwrap();
 
         Ok(ImplSourceTraitUpcastingData { upcast_trait_ref, vtable_vptr_slot, nested })
     }
@@ -1276,7 +1278,7 @@ fn confirm_const_destruct_candidate(
 
                 // If we have a projection type, make sure to normalize it so we replace it
                 // with a fresh infer variable
-                ty::Projection(..) => {
+                ty::Alias(ty::Projection, ..) => {
                     let predicate = normalize_with_depth_to(
                         self,
                         obligation.param_env,
index 035deb61639817c57d897a9ffdcb75db304aacaa..792933096b15c61a731b3a2e1cee0d87c1347926 100644 (file)
@@ -1595,8 +1595,7 @@ fn match_projection_obligation_against_definition_bounds(
 
         let tcx = self.infcx.tcx;
         let (def_id, substs) = match *placeholder_trait_predicate.trait_ref.self_ty().kind() {
-            ty::Projection(ref data) => (data.item_def_id, data.substs),
-            ty::Opaque(def_id, substs) => (def_id, substs),
+            ty::Alias(_, ty::AliasTy { def_id, substs, .. }) => (def_id, substs),
             _ => {
                 span_bug!(
                     obligation.cause.span,
@@ -1745,7 +1744,7 @@ pub(super) fn match_projection_projections(
             });
 
         if is_match {
-            let generics = self.tcx().generics_of(obligation.predicate.item_def_id);
+            let generics = self.tcx().generics_of(obligation.predicate.def_id);
             // FIXME(generic-associated-types): Addresses aggressive inference in #92917.
             // If this type is a GAT, and of the GAT substs resolve to something new,
             // that means that we must have newly inferred something about the GAT.
@@ -2067,7 +2066,7 @@ fn sized_conditions(
                 }))
             }
 
-            ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => None,
+            ty::Alias(..) | ty::Param(_) => None,
             ty::Infer(ty::TyVar(_)) => Ambiguous,
 
             ty::Placeholder(..)
@@ -2167,7 +2166,7 @@ fn copy_clone_conditions(
                 }
             }
 
-            ty::Adt(..) | ty::Projection(..) | ty::Param(..) | ty::Opaque(..) => {
+            ty::Adt(..) | ty::Alias(..) | ty::Param(..) => {
                 // Fallback to whatever user-defined impls exist in this case.
                 None
             }
@@ -2220,7 +2219,7 @@ fn constituent_types_for_ty(
             | ty::Dynamic(..)
             | ty::Param(..)
             | ty::Foreign(..)
-            | ty::Projection(..)
+            | ty::Alias(ty::Projection, ..)
             | ty::Bound(..)
             | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
                 bug!("asked to assemble constituent types of unexpected type: {:?}", t);
@@ -2260,7 +2259,7 @@ fn constituent_types_for_ty(
                 t.rebind(def.all_fields().map(|f| f.ty(self.tcx(), substs)).collect())
             }
 
-            ty::Opaque(def_id, substs) => {
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
                 // We can resolve the `impl Trait` to its concrete type,
                 // which enforces a DAG between the functions requiring
                 // the auto trait bounds in question.
index 40dbe0b3ff063d927dc78c3de0e2eefb1ab3b113..892a7afd799c73c64ff0a5c6ba5bbf156b68fa9e 100644 (file)
@@ -1,10 +1,5 @@
-use crate::infer::{InferCtxt, TyCtxtInferExt};
-use crate::traits::{ObligationCause, ObligationCtxt};
-
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
-use rustc_hir::lang_items::LangItem;
-use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
 use rustc_span::Span;
 use std::ops::ControlFlow;
@@ -59,41 +54,6 @@ pub fn search_for_adt_const_param_violation<'tcx>(
         .break_value()
 }
 
-/// This method returns true if and only if `adt_ty` itself has been marked as
-/// eligible for structural-match: namely, if it implements both
-/// `StructuralPartialEq` and `StructuralEq` (which are respectively injected by
-/// `#[derive(PartialEq)]` and `#[derive(Eq)]`).
-///
-/// Note that this does *not* recursively check if the substructure of `adt_ty`
-/// implements the traits.
-fn type_marked_structural<'tcx>(
-    infcx: &InferCtxt<'tcx>,
-    adt_ty: Ty<'tcx>,
-    cause: ObligationCause<'tcx>,
-) -> bool {
-    let ocx = ObligationCtxt::new(infcx);
-    // require `#[derive(PartialEq)]`
-    let structural_peq_def_id =
-        infcx.tcx.require_lang_item(LangItem::StructuralPeq, Some(cause.span));
-    ocx.register_bound(cause.clone(), ty::ParamEnv::empty(), adt_ty, structural_peq_def_id);
-    // for now, require `#[derive(Eq)]`. (Doing so is a hack to work around
-    // the type `for<'a> fn(&'a ())` failing to implement `Eq` itself.)
-    let structural_teq_def_id =
-        infcx.tcx.require_lang_item(LangItem::StructuralTeq, Some(cause.span));
-    ocx.register_bound(cause, ty::ParamEnv::empty(), adt_ty, structural_teq_def_id);
-
-    // We deliberately skip *reporting* fulfillment errors (via
-    // `report_fulfillment_errors`), for two reasons:
-    //
-    // 1. The error messages would mention `std::marker::StructuralPartialEq`
-    //    (a trait which is solely meant as an implementation detail
-    //    for now), and
-    //
-    // 2. We are sometimes doing future-incompatibility lints for
-    //    now, so we do not want unconditional errors here.
-    ocx.select_all_or_error().is_empty()
-}
-
 /// This implements the traversal over the structure of a given type to try to
 /// find instances of ADTs (specifically structs or enums) that do not implement
 /// the structural-match traits (`StructuralPartialEq` and `StructuralEq`).
@@ -135,10 +95,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
             ty::Foreign(_) => {
                 return ControlFlow::Break(ty);
             }
-            ty::Opaque(..) => {
-                return ControlFlow::Break(ty);
-            }
-            ty::Projection(..) => {
+            ty::Alias(..) => {
                 return ControlFlow::Break(ty);
             }
             ty::Closure(..) => {
@@ -249,11 +206,3 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
         })
     }
 }
-
-pub fn provide(providers: &mut Providers) {
-    providers.has_structural_eq_impls = |tcx, ty| {
-        let infcx = tcx.infer_ctxt().build();
-        let cause = ObligationCause::dummy();
-        type_marked_structural(&infcx, ty, cause)
-    };
-}
index 51968c2d7a191fccc2bd21e17ff26b6a0ec343f1..f3ca6a6c779a06b9ca34b584dde18fe5775f0516 100644 (file)
@@ -261,16 +261,6 @@ pub fn upcast_choices<'tcx>(
     supertraits(tcx, source_trait_ref).filter(|r| r.def_id() == target_trait_def_id).collect()
 }
 
-/// Given a trait `trait_ref`, returns the number of vtable entries
-/// that come from `trait_ref`, excluding its supertraits. Used in
-/// computing the vtable base for an upcast trait of a trait object.
-pub fn count_own_vtable_entries<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    trait_ref: ty::PolyTraitRef<'tcx>,
-) -> usize {
-    tcx.own_existential_vtable_entries(trait_ref.def_id()).len()
-}
-
 /// Given an upcast trait object described by `object`, returns the
 /// index of the method `method_def_id` (which should be part of
 /// `object.upcast_trait_ref`) within the vtable for `object`.
diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs
new file mode 100644 (file)
index 0000000..41ce6cd
--- /dev/null
@@ -0,0 +1,386 @@
+use crate::errors::DumpVTableEntries;
+use crate::traits::{impossible_predicates, is_vtable_safe_method};
+use rustc_hir::def_id::DefId;
+use rustc_hir::lang_items::LangItem;
+use rustc_infer::traits::util::PredicateSet;
+use rustc_infer::traits::ImplSource;
+use rustc_middle::ty::visit::TypeVisitable;
+use rustc_middle::ty::InternalSubsts;
+use rustc_middle::ty::{self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, VtblEntry};
+use rustc_span::{sym, Span};
+use smallvec::SmallVec;
+
+use std::fmt::Debug;
+use std::ops::ControlFlow;
+
+#[derive(Clone, Debug)]
+pub(super) enum VtblSegment<'tcx> {
+    MetadataDSA,
+    TraitOwnEntries { trait_ref: ty::PolyTraitRef<'tcx>, emit_vptr: bool },
+}
+
+/// Prepare the segments for a vtable
+pub(super) fn prepare_vtable_segments<'tcx, T>(
+    tcx: TyCtxt<'tcx>,
+    trait_ref: ty::PolyTraitRef<'tcx>,
+    mut segment_visitor: impl FnMut(VtblSegment<'tcx>) -> ControlFlow<T>,
+) -> Option<T> {
+    // The following constraints holds for the final arrangement.
+    // 1. The whole virtual table of the first direct super trait is included as the
+    //    the prefix. If this trait doesn't have any super traits, then this step
+    //    consists of the dsa metadata.
+    // 2. Then comes the proper pointer metadata(vptr) and all own methods for all
+    //    other super traits except those already included as part of the first
+    //    direct super trait virtual table.
+    // 3. finally, the own methods of this trait.
+
+    // This has the advantage that trait upcasting to the first direct super trait on each level
+    // is zero cost, and to another trait includes only replacing the pointer with one level indirection,
+    // while not using too much extra memory.
+
+    // For a single inheritance relationship like this,
+    //   D --> C --> B --> A
+    // The resulting vtable will consists of these segments:
+    //  DSA, A, B, C, D
+
+    // For a multiple inheritance relationship like this,
+    //   D --> C --> A
+    //           \-> B
+    // The resulting vtable will consists of these segments:
+    //  DSA, A, B, B-vptr, C, D
+
+    // For a diamond inheritance relationship like this,
+    //   D --> B --> A
+    //     \-> C -/
+    // The resulting vtable will consists of these segments:
+    //  DSA, A, B, C, C-vptr, D
+
+    // For a more complex inheritance relationship like this:
+    //   O --> G --> C --> A
+    //     \     \     \-> B
+    //     |     |-> F --> D
+    //     |           \-> E
+    //     |-> N --> J --> H
+    //           \     \-> I
+    //           |-> M --> K
+    //                 \-> L
+    // The resulting vtable will consists of these segments:
+    //  DSA, A, B, B-vptr, C, D, D-vptr, E, E-vptr, F, F-vptr, G,
+    //  H, H-vptr, I, I-vptr, J, J-vptr, K, K-vptr, L, L-vptr, M, M-vptr,
+    //  N, N-vptr, O
+
+    // emit dsa segment first.
+    if let ControlFlow::Break(v) = (segment_visitor)(VtblSegment::MetadataDSA) {
+        return Some(v);
+    }
+
+    let mut emit_vptr_on_new_entry = false;
+    let mut visited = PredicateSet::new(tcx);
+    let predicate = trait_ref.without_const().to_predicate(tcx);
+    let mut stack: SmallVec<[(ty::PolyTraitRef<'tcx>, _, _); 5]> =
+        smallvec![(trait_ref, emit_vptr_on_new_entry, None)];
+    visited.insert(predicate);
+
+    // the main traversal loop:
+    // basically we want to cut the inheritance directed graph into a few non-overlapping slices of nodes
+    // that each node is emitted after all its descendents have been emitted.
+    // so we convert the directed graph into a tree by skipping all previously visited nodes using a visited set.
+    // this is done on the fly.
+    // Each loop run emits a slice - it starts by find a "childless" unvisited node, backtracking upwards, and it
+    // stops after it finds a node that has a next-sibling node.
+    // This next-sibling node will used as the starting point of next slice.
+
+    // Example:
+    // For a diamond inheritance relationship like this,
+    //   D#1 --> B#0 --> A#0
+    //     \-> C#1 -/
+
+    // Starting point 0 stack [D]
+    // Loop run #0: Stack after diving in is [D B A], A is "childless"
+    // after this point, all newly visited nodes won't have a vtable that equals to a prefix of this one.
+    // Loop run #0: Emitting the slice [B A] (in reverse order), B has a next-sibling node, so this slice stops here.
+    // Loop run #0: Stack after exiting out is [D C], C is the next starting point.
+    // Loop run #1: Stack after diving in is [D C], C is "childless", since its child A is skipped(already emitted).
+    // Loop run #1: Emitting the slice [D C] (in reverse order). No one has a next-sibling node.
+    // Loop run #1: Stack after exiting out is []. Now the function exits.
+
+    loop {
+        // dive deeper into the stack, recording the path
+        'diving_in: loop {
+            if let Some((inner_most_trait_ref, _, _)) = stack.last() {
+                let inner_most_trait_ref = *inner_most_trait_ref;
+                let mut direct_super_traits_iter = tcx
+                    .super_predicates_of(inner_most_trait_ref.def_id())
+                    .predicates
+                    .into_iter()
+                    .filter_map(move |(pred, _)| {
+                        pred.subst_supertrait(tcx, &inner_most_trait_ref).to_opt_poly_trait_pred()
+                    });
+
+                'diving_in_skip_visited_traits: loop {
+                    if let Some(next_super_trait) = direct_super_traits_iter.next() {
+                        if visited.insert(next_super_trait.to_predicate(tcx)) {
+                            // We're throwing away potential constness of super traits here.
+                            // FIXME: handle ~const super traits
+                            let next_super_trait = next_super_trait.map_bound(|t| t.trait_ref);
+                            stack.push((
+                                next_super_trait,
+                                emit_vptr_on_new_entry,
+                                Some(direct_super_traits_iter),
+                            ));
+                            break 'diving_in_skip_visited_traits;
+                        } else {
+                            continue 'diving_in_skip_visited_traits;
+                        }
+                    } else {
+                        break 'diving_in;
+                    }
+                }
+            }
+        }
+
+        // Other than the left-most path, vptr should be emitted for each trait.
+        emit_vptr_on_new_entry = true;
+
+        // emit innermost item, move to next sibling and stop there if possible, otherwise jump to outer level.
+        'exiting_out: loop {
+            if let Some((inner_most_trait_ref, emit_vptr, siblings_opt)) = stack.last_mut() {
+                if let ControlFlow::Break(v) = (segment_visitor)(VtblSegment::TraitOwnEntries {
+                    trait_ref: *inner_most_trait_ref,
+                    emit_vptr: *emit_vptr,
+                }) {
+                    return Some(v);
+                }
+
+                'exiting_out_skip_visited_traits: loop {
+                    if let Some(siblings) = siblings_opt {
+                        if let Some(next_inner_most_trait_ref) = siblings.next() {
+                            if visited.insert(next_inner_most_trait_ref.to_predicate(tcx)) {
+                                // We're throwing away potential constness of super traits here.
+                                // FIXME: handle ~const super traits
+                                let next_inner_most_trait_ref =
+                                    next_inner_most_trait_ref.map_bound(|t| t.trait_ref);
+                                *inner_most_trait_ref = next_inner_most_trait_ref;
+                                *emit_vptr = emit_vptr_on_new_entry;
+                                break 'exiting_out;
+                            } else {
+                                continue 'exiting_out_skip_visited_traits;
+                            }
+                        }
+                    }
+                    stack.pop();
+                    continue 'exiting_out;
+                }
+            }
+            // all done
+            return None;
+        }
+    }
+}
+
+fn dump_vtable_entries<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    sp: Span,
+    trait_ref: ty::PolyTraitRef<'tcx>,
+    entries: &[VtblEntry<'tcx>],
+) {
+    tcx.sess.emit_err(DumpVTableEntries {
+        span: sp,
+        trait_ref,
+        entries: format!("{:#?}", entries),
+    });
+}
+
+fn own_existential_vtable_entries<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId) -> &'tcx [DefId] {
+    let trait_methods = tcx
+        .associated_items(trait_def_id)
+        .in_definition_order()
+        .filter(|item| item.kind == ty::AssocKind::Fn);
+    // Now list each method's DefId (for within its trait).
+    let own_entries = trait_methods.filter_map(move |trait_method| {
+        debug!("own_existential_vtable_entry: trait_method={:?}", trait_method);
+        let def_id = trait_method.def_id;
+
+        // Some methods cannot be called on an object; skip those.
+        if !is_vtable_safe_method(tcx, trait_def_id, &trait_method) {
+            debug!("own_existential_vtable_entry: not vtable safe");
+            return None;
+        }
+
+        Some(def_id)
+    });
+
+    tcx.arena.alloc_from_iter(own_entries.into_iter())
+}
+
+/// Given a trait `trait_ref`, iterates the vtable entries
+/// that come from `trait_ref`, including its supertraits.
+fn vtable_entries<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_ref: ty::PolyTraitRef<'tcx>,
+) -> &'tcx [VtblEntry<'tcx>] {
+    debug!("vtable_entries({:?})", trait_ref);
+
+    let mut entries = vec![];
+
+    let vtable_segment_callback = |segment| -> ControlFlow<()> {
+        match segment {
+            VtblSegment::MetadataDSA => {
+                entries.extend(TyCtxt::COMMON_VTABLE_ENTRIES);
+            }
+            VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
+                let existential_trait_ref = trait_ref
+                    .map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref));
+
+                // Lookup the shape of vtable for the trait.
+                let own_existential_entries =
+                    tcx.own_existential_vtable_entries(existential_trait_ref.def_id());
+
+                let own_entries = own_existential_entries.iter().copied().map(|def_id| {
+                    debug!("vtable_entries: trait_method={:?}", def_id);
+
+                    // The method may have some early-bound lifetimes; add regions for those.
+                    let substs = trait_ref.map_bound(|trait_ref| {
+                        InternalSubsts::for_item(tcx, def_id, |param, _| match param.kind {
+                            GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
+                            GenericParamDefKind::Type { .. }
+                            | GenericParamDefKind::Const { .. } => {
+                                trait_ref.substs[param.index as usize]
+                            }
+                        })
+                    });
+
+                    // The trait type may have higher-ranked lifetimes in it;
+                    // erase them if they appear, so that we get the type
+                    // at some particular call site.
+                    let substs = tcx
+                        .normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), substs);
+
+                    // It's possible that the method relies on where-clauses that
+                    // do not hold for this particular set of type parameters.
+                    // Note that this method could then never be called, so we
+                    // do not want to try and codegen it, in that case (see #23435).
+                    let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs);
+                    if impossible_predicates(tcx, predicates.predicates) {
+                        debug!("vtable_entries: predicates do not hold");
+                        return VtblEntry::Vacant;
+                    }
+
+                    let instance = ty::Instance::resolve_for_vtable(
+                        tcx,
+                        ty::ParamEnv::reveal_all(),
+                        def_id,
+                        substs,
+                    )
+                    .expect("resolution failed during building vtable representation");
+                    VtblEntry::Method(instance)
+                });
+
+                entries.extend(own_entries);
+
+                if emit_vptr {
+                    entries.push(VtblEntry::TraitVPtr(trait_ref));
+                }
+            }
+        }
+
+        ControlFlow::Continue(())
+    };
+
+    let _ = prepare_vtable_segments(tcx, trait_ref, vtable_segment_callback);
+
+    if tcx.has_attr(trait_ref.def_id(), sym::rustc_dump_vtable) {
+        let sp = tcx.def_span(trait_ref.def_id());
+        dump_vtable_entries(tcx, sp, trait_ref, &entries);
+    }
+
+    tcx.arena.alloc_from_iter(entries.into_iter())
+}
+
+/// Find slot base for trait methods within vtable entries of another trait
+pub(super) fn vtable_trait_first_method_offset<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    key: (
+        ty::PolyTraitRef<'tcx>, // trait_to_be_found
+        ty::PolyTraitRef<'tcx>, // trait_owning_vtable
+    ),
+) -> usize {
+    let (trait_to_be_found, trait_owning_vtable) = key;
+
+    // #90177
+    let trait_to_be_found_erased = tcx.erase_regions(trait_to_be_found);
+
+    let vtable_segment_callback = {
+        let mut vtable_base = 0;
+
+        move |segment| {
+            match segment {
+                VtblSegment::MetadataDSA => {
+                    vtable_base += TyCtxt::COMMON_VTABLE_ENTRIES.len();
+                }
+                VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
+                    if tcx.erase_regions(trait_ref) == trait_to_be_found_erased {
+                        return ControlFlow::Break(vtable_base);
+                    }
+                    vtable_base += count_own_vtable_entries(tcx, trait_ref);
+                    if emit_vptr {
+                        vtable_base += 1;
+                    }
+                }
+            }
+            ControlFlow::Continue(())
+        }
+    };
+
+    if let Some(vtable_base) =
+        prepare_vtable_segments(tcx, trait_owning_vtable, vtable_segment_callback)
+    {
+        vtable_base
+    } else {
+        bug!("Failed to find info for expected trait in vtable");
+    }
+}
+
+/// Find slot offset for trait vptr within vtable entries of another trait
+pub(crate) fn vtable_trait_upcasting_coercion_new_vptr_slot<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    key: (
+        Ty<'tcx>, // trait object type whose trait owning vtable
+        Ty<'tcx>, // trait object for supertrait
+    ),
+) -> Option<usize> {
+    let (source, target) = key;
+    assert!(matches!(&source.kind(), &ty::Dynamic(..)) && !source.needs_infer());
+    assert!(matches!(&target.kind(), &ty::Dynamic(..)) && !target.needs_infer());
+
+    // this has been typecked-before, so diagnostics is not really needed.
+    let unsize_trait_did = tcx.require_lang_item(LangItem::Unsize, None);
+
+    let trait_ref = tcx.mk_trait_ref(unsize_trait_did, [source, target]);
+
+    match tcx.codegen_select_candidate((ty::ParamEnv::reveal_all(), ty::Binder::dummy(trait_ref))) {
+        Ok(ImplSource::TraitUpcasting(implsrc_traitcasting)) => {
+            implsrc_traitcasting.vtable_vptr_slot
+        }
+        otherwise => bug!("expected TraitUpcasting candidate, got {otherwise:?}"),
+    }
+}
+
+/// Given a trait `trait_ref`, returns the number of vtable entries
+/// that come from `trait_ref`, excluding its supertraits. Used in
+/// computing the vtable base for an upcast trait of a trait object.
+pub(crate) fn count_own_vtable_entries<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_ref: ty::PolyTraitRef<'tcx>,
+) -> usize {
+    tcx.own_existential_vtable_entries(trait_ref.def_id()).len()
+}
+
+pub(super) fn provide(providers: &mut ty::query::Providers) {
+    *providers = ty::query::Providers {
+        own_existential_vtable_entries,
+        vtable_entries,
+        vtable_trait_upcasting_coercion_new_vptr_slot,
+        ..*providers
+    };
+}
index e47ba64245f50732f0b95a7eddf143b5341bc555..0e0a883d9f5908ffcf0dfe5c41a34daa5c1639e2 100644 (file)
@@ -234,9 +234,9 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
             // projection coming from another associated type. See
             // `src/test/ui/associated-types/point-at-type-on-obligation-failure.rs` and
             // `traits-assoc-type-in-supertrait-bad.rs`.
-            if let Some(ty::Projection(projection_ty)) = proj.term.ty().map(|ty| ty.kind())
+            if let Some(ty::Alias(ty::Projection, projection_ty)) = proj.term.ty().map(|ty| ty.kind())
                 && let Some(&impl_item_id) =
-                    tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.item_def_id)
+                    tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.def_id)
                 && let Some(impl_item_span) = items
                     .iter()
                     .find(|item| item.id.owner_id.to_def_id() == impl_item_id)
@@ -249,9 +249,9 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
             // An associated item obligation born out of the `trait` failed to be met. An example
             // can be seen in `ui/associated-types/point-at-type-on-obligation-failure-2.rs`.
             debug!("extended_cause_with_original_assoc_item_obligation trait proj {:?}", pred);
-            if let ty::Projection(ty::ProjectionTy { item_def_id, .. }) = *pred.self_ty().kind()
+            if let ty::Alias(ty::Projection, ty::AliasTy { def_id, .. }) = *pred.self_ty().kind()
                 && let Some(&impl_item_id) =
-                    tcx.impl_item_implementor_ids(impl_def_id).get(&item_def_id)
+                    tcx.impl_item_implementor_ids(impl_def_id).get(&def_id)
                 && let Some(impl_item_span) = items
                     .iter()
                     .find(|item| item.id.owner_id.to_def_id() == impl_item_id)
@@ -369,7 +369,7 @@ fn compute_trait_pred(&mut self, trait_pred: &ty::TraitPredicate<'tcx>, elaborat
 
     /// Pushes the obligations required for `trait_ref::Item` to be WF
     /// into `self.out`.
-    fn compute_projection(&mut self, data: ty::ProjectionTy<'tcx>) {
+    fn compute_projection(&mut self, data: ty::AliasTy<'tcx>) {
         // A projection is well-formed if
         //
         // (a) its predicates hold (*)
@@ -392,7 +392,7 @@ fn compute_projection(&mut self, data: ty::ProjectionTy<'tcx>) {
         //     `i32: Copy`
         // ]
         // Projection types do not require const predicates.
-        let obligations = self.nominal_obligations_without_const(data.item_def_id, data.substs);
+        let obligations = self.nominal_obligations_without_const(data.def_id, data.substs);
         self.out.extend(obligations);
 
         let tcx = self.tcx();
@@ -451,19 +451,21 @@ fn compute(&mut self, arg: GenericArg<'tcx>) {
                 GenericArgKind::Const(ct) => {
                     match ct.kind() {
                         ty::ConstKind::Unevaluated(uv) => {
-                            let obligations = self.nominal_obligations(uv.def.did, uv.substs);
-                            self.out.extend(obligations);
-
-                            let predicate =
-                                ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct));
-                            let cause = self.cause(traits::WellFormed(None));
-                            self.out.push(traits::Obligation::with_depth(
-                                self.tcx(),
-                                cause,
-                                self.recursion_depth,
-                                self.param_env,
-                                predicate,
-                            ));
+                            if !ct.has_escaping_bound_vars() {
+                                let obligations = self.nominal_obligations(uv.def.did, uv.substs);
+                                self.out.extend(obligations);
+
+                                let predicate =
+                                    ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct));
+                                let cause = self.cause(traits::WellFormed(None));
+                                self.out.push(traits::Obligation::with_depth(
+                                    self.tcx(),
+                                    cause,
+                                    self.recursion_depth,
+                                    self.param_env,
+                                    predicate,
+                                ));
+                            }
                         }
                         ty::ConstKind::Infer(_) => {
                             let cause = self.cause(traits::WellFormed(None));
@@ -556,7 +558,7 @@ fn compute(&mut self, arg: GenericArg<'tcx>) {
                     // Simple cases that are WF if their type args are WF.
                 }
 
-                ty::Projection(data) => {
+                ty::Alias(ty::Projection, data) => {
                     walker.skip_current_subtree(); // Subtree handled by compute_projection.
                     self.compute_projection(data);
                 }
@@ -648,12 +650,12 @@ fn compute(&mut self, arg: GenericArg<'tcx>) {
                     // types appearing in the fn signature
                 }
 
-                ty::Opaque(did, substs) => {
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
                     // All of the requirements on type parameters
                     // have already been checked for `impl Trait` in
                     // return position. We do need to check type-alias-impl-trait though.
-                    if ty::is_impl_trait_defn(self.tcx, did).is_none() {
-                        let obligations = self.nominal_obligations(did, substs);
+                    if ty::is_impl_trait_defn(self.tcx, def_id).is_none() {
+                        let obligations = self.nominal_obligations(def_id, substs);
                         self.out.extend(obligations);
                     }
                 }
index 344c8b93c170489dfb726ff7b12eabc1cb47025b..bc4a52c5040d1fa5f2647d6acd6c7105a814009c 100644 (file)
@@ -432,7 +432,10 @@ fn impl_provided_for(
                         (ast::Mutability::Not, chalk_ir::Mutability::Not) => true,
                     }
                 }
-                (&ty::Opaque(def_id, ..), OpaqueType(opaque_ty_id, ..)) => def_id == opaque_ty_id.0,
+                (
+                    &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }),
+                    OpaqueType(opaque_ty_id, ..),
+                ) => def_id == opaque_ty_id.0,
                 (&ty::FnDef(def_id, ..), FnDef(fn_def_id, ..)) => def_id == fn_def_id.0,
                 (&ty::Str, Str) => true,
                 (&ty::Never, Never) => true,
@@ -786,7 +789,7 @@ fn fold_binder<T: TypeFoldable<'tcx>>(
     }
 
     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        if let ty::Opaque(def_id, substs) = *ty.kind() {
+        if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) = *ty.kind() {
             if def_id == self.opaque_ty_id.0 && substs == self.identity_substs {
                 return self.tcx.mk_ty(ty::Bound(
                     self.binder_index,
index c4ab86e9e9bab343d8b96b27cc0901ffbd52a607..9712abb708f2762c61c6c2b0b922e642c681fb83 100644 (file)
@@ -66,15 +66,6 @@ fn lower_into(self, interner: RustInterner<'tcx>) -> SubstsRef<'tcx> {
     }
 }
 
-impl<'tcx> LowerInto<'tcx, chalk_ir::AliasTy<RustInterner<'tcx>>> for ty::ProjectionTy<'tcx> {
-    fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::AliasTy<RustInterner<'tcx>> {
-        chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy {
-            associated_ty_id: chalk_ir::AssocTypeId(self.item_def_id),
-            substitution: self.substs.lower_into(interner),
-        })
-    }
-}
-
 impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment<chalk_ir::Goal<RustInterner<'tcx>>>>
     for ChalkEnvironmentAndGoal<'tcx>
 {
@@ -255,7 +246,10 @@ fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::AliasEq<RustInter
         // FIXME(associated_const_equality): teach chalk about terms for alias eq.
         chalk_ir::AliasEq {
             ty: self.term.ty().unwrap().lower_into(interner),
-            alias: self.projection_ty.lower_into(interner),
+            alias: chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy {
+                associated_ty_id: chalk_ir::AssocTypeId(self.projection_ty.def_id),
+                substitution: self.projection_ty.substs.lower_into(interner),
+            }),
         }
     }
 }
@@ -353,8 +347,13 @@ fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::Ty<RustInterner<'
             ty::Tuple(types) => {
                 chalk_ir::TyKind::Tuple(types.len(), types.as_substs().lower_into(interner))
             }
-            ty::Projection(proj) => chalk_ir::TyKind::Alias(proj.lower_into(interner)),
-            ty::Opaque(def_id, substs) => {
+            ty::Alias(ty::Projection, ty::AliasTy { def_id, substs, .. }) => {
+                chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy {
+                    associated_ty_id: chalk_ir::AssocTypeId(def_id),
+                    substitution: substs.lower_into(interner),
+                }))
+            }
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
                 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy {
                     opaque_ty_id: chalk_ir::OpaqueTyId(def_id),
                     substitution: substs.lower_into(interner),
@@ -442,13 +441,14 @@ fn lower_into(self, interner: RustInterner<'tcx>) -> Ty<'tcx> {
                 mutbl.lower_into(interner),
             ),
             TyKind::Str => ty::Str,
-            TyKind::OpaqueType(opaque_ty, substitution) => {
-                ty::Opaque(opaque_ty.0, substitution.lower_into(interner))
-            }
-            TyKind::AssociatedType(assoc_ty, substitution) => ty::Projection(ty::ProjectionTy {
-                substs: substitution.lower_into(interner),
-                item_def_id: assoc_ty.0,
-            }),
+            TyKind::OpaqueType(opaque_ty, substitution) => ty::Alias(
+                ty::Opaque,
+                interner.tcx.mk_alias_ty(opaque_ty.0, substitution.lower_into(interner)),
+            ),
+            TyKind::AssociatedType(assoc_ty, substitution) => ty::Alias(
+                ty::Projection,
+                interner.tcx.mk_alias_ty(assoc_ty.0, substitution.lower_into(interner)),
+            ),
             TyKind::Foreign(def_id) => ty::Foreign(def_id.0),
             TyKind::Error => return interner.tcx.ty_error(),
             TyKind::Placeholder(placeholder) => ty::Placeholder(ty::Placeholder {
@@ -456,13 +456,20 @@ fn lower_into(self, interner: RustInterner<'tcx>) -> Ty<'tcx> {
                 name: ty::BoundVar::from_usize(placeholder.idx),
             }),
             TyKind::Alias(alias_ty) => match alias_ty {
-                chalk_ir::AliasTy::Projection(projection) => ty::Projection(ty::ProjectionTy {
-                    item_def_id: projection.associated_ty_id.0,
-                    substs: projection.substitution.lower_into(interner),
-                }),
-                chalk_ir::AliasTy::Opaque(opaque) => {
-                    ty::Opaque(opaque.opaque_ty_id.0, opaque.substitution.lower_into(interner))
-                }
+                chalk_ir::AliasTy::Projection(projection) => ty::Alias(
+                    ty::Projection,
+                    interner.tcx.mk_alias_ty(
+                        projection.associated_ty_id.0,
+                        projection.substitution.lower_into(interner),
+                    ),
+                ),
+                chalk_ir::AliasTy::Opaque(opaque) => ty::Alias(
+                    ty::Opaque,
+                    interner.tcx.mk_alias_ty(
+                        opaque.opaque_ty_id.0,
+                        opaque.substitution.lower_into(interner),
+                    ),
+                ),
             },
             TyKind::Function(_quantified_ty) => unimplemented!(),
             TyKind::BoundVar(_bound) => ty::Bound(
@@ -688,7 +695,7 @@ fn lower_into(
                     binders.clone(),
                     chalk_ir::WhereClause::AliasEq(chalk_ir::AliasEq {
                         alias: chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy {
-                            associated_ty_id: chalk_ir::AssocTypeId(predicate.item_def_id),
+                            associated_ty_id: chalk_ir::AssocTypeId(predicate.def_id),
                             substitution: interner
                                 .tcx
                                 .mk_substs_trait(self_ty, predicate.substs)
@@ -844,7 +851,7 @@ fn lower_into(
         let (trait_ref, own_substs) = self.projection_ty.trait_ref_and_own_substs(interner.tcx);
         chalk_solve::rust_ir::AliasEqBound {
             trait_bound: trait_ref.lower_into(interner),
-            associated_ty_id: chalk_ir::AssocTypeId(self.projection_ty.item_def_id),
+            associated_ty_id: chalk_ir::AssocTypeId(self.projection_ty.def_id),
             parameters: own_substs.iter().map(|arg| arg.lower_into(interner)).collect(),
             value: self.term.ty().unwrap().lower_into(interner),
         }
diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs
new file mode 100644 (file)
index 0000000..f8f74b7
--- /dev/null
@@ -0,0 +1,88 @@
+// This file contains various trait resolution methods used by codegen.
+// They all assume regions can be erased and monomorphic types.  It
+// seems likely that they should eventually be merged into more
+// general routines.
+
+use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
+use rustc_infer::traits::FulfillmentErrorCode;
+use rustc_middle::traits::CodegenObligationError;
+use rustc_middle::ty::{self, TyCtxt};
+use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
+use rustc_trait_selection::traits::{
+    ImplSource, Obligation, ObligationCause, SelectionContext, TraitEngine, TraitEngineExt,
+    Unimplemented,
+};
+
+/// Attempts to resolve an obligation to an `ImplSource`. The result is
+/// a shallow `ImplSource` resolution, meaning that we do not
+/// (necessarily) resolve all nested obligations on the impl. Note
+/// that type check should guarantee to us that all nested
+/// obligations *could be* resolved if we wanted to.
+///
+/// This also expects that `trait_ref` is fully normalized.
+pub fn codegen_select_candidate<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    (param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>),
+) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> {
+    // We expect the input to be fully normalized.
+    debug_assert_eq!(trait_ref, tcx.normalize_erasing_regions(param_env, trait_ref));
+
+    // Do the initial selection for the obligation. This yields the
+    // shallow result we are looking for -- that is, what specific impl.
+    let infcx = tcx
+        .infer_ctxt()
+        .ignoring_regions()
+        .with_opaque_type_inference(DefiningAnchor::Bubble)
+        .build();
+    //~^ HACK `Bubble` is required for
+    // this test to pass: type-alias-impl-trait/assoc-projection-ice.rs
+    let mut selcx = SelectionContext::new(&infcx);
+
+    let obligation_cause = ObligationCause::dummy();
+    let obligation = Obligation::new(tcx, obligation_cause, param_env, trait_ref);
+
+    let selection = match selcx.select(&obligation) {
+        Ok(Some(selection)) => selection,
+        Ok(None) => return Err(CodegenObligationError::Ambiguity),
+        Err(Unimplemented) => return Err(CodegenObligationError::Unimplemented),
+        Err(e) => {
+            bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref)
+        }
+    };
+
+    debug!(?selection);
+
+    // Currently, we use a fulfillment context to completely resolve
+    // all nested obligations. This is because they can inform the
+    // inference of the impl's type parameters.
+    let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(tcx);
+    let impl_source = selection.map(|predicate| {
+        fulfill_cx.register_predicate_obligation(&infcx, predicate);
+    });
+
+    // In principle, we only need to do this so long as `impl_source`
+    // contains unbound type parameters. It could be a slight
+    // optimization to stop iterating early.
+    let errors = fulfill_cx.select_all_or_error(&infcx);
+    if !errors.is_empty() {
+        // `rustc_monomorphize::collector` assumes there are no type errors.
+        // Cycle errors are the only post-monomorphization errors possible; emit them now so
+        // `rustc_ty_utils::resolve_associated_item` doesn't return `None` post-monomorphization.
+        for err in errors {
+            if let FulfillmentErrorCode::CodeCycle(cycle) = err.code {
+                infcx.err_ctxt().report_overflow_obligation_cycle(&cycle);
+            }
+        }
+        return Err(CodegenObligationError::FulfillmentError);
+    }
+
+    let impl_source = infcx.resolve_vars_if_possible(impl_source);
+    let impl_source = infcx.tcx.erase_regions(impl_source);
+
+    // Opaque types may have gotten their hidden types constrained, but we can ignore them safely
+    // as they will get constrained elsewhere, too.
+    // (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();
+
+    Ok(&*tcx.arena.alloc(impl_source))
+}
index 66ab742f15782ae6689314daebb663653635eb41..3f661ce69235caaf0cb69c8df90277e9fdbfb0be 100644 (file)
@@ -112,7 +112,7 @@ fn dropck_outlives<'tcx>(
 
                     // A projection that we couldn't resolve - it
                     // might have a destructor.
-                    ty::Projection(..) | ty::Opaque(..) => {
+                    ty::Alias(..) => {
                         result.kinds.push(ty.into());
                     }
 
@@ -268,7 +268,7 @@ fn dtorck_constraint_for_ty<'tcx>(
         }
 
         // Types that can't be resolved. Pass them forward.
-        ty::Projection(..) | ty::Opaque(..) | ty::Param(..) => {
+        ty::Alias(..) | ty::Param(..) => {
             constraints.dtorck_types.push(ty);
         }
 
index 0ffa92f1ad55d960310e1625e13f53c362ea0e09..9aa26667e7bf461ef3059ade70551ccff81ee75e 100644 (file)
@@ -12,6 +12,7 @@
 extern crate rustc_middle;
 
 mod chalk;
+mod codegen;
 mod dropck_outlives;
 mod evaluate_obligation;
 mod implied_outlives_bounds;
@@ -31,4 +32,5 @@ pub fn provide(p: &mut Providers) {
     normalize_projection_ty::provide(p);
     normalize_erasing_regions::provide(p);
     type_op::provide(p);
+    p.codegen_select_candidate = codegen::codegen_select_candidate;
 }
index 73c7eb6992f075610dd2cac96d23c64c564a1e7a..d644cbccea11b2df6c5080a2191ad3c1c8b8f4f1 100644 (file)
@@ -85,7 +85,7 @@ fn fn_sig_for_fn_abi<'tcx>(
                 bound_vars,
             )
         }
-        ty::Generator(_, substs, _) => {
+        ty::Generator(did, substs, _) => {
             let sig = substs.as_generator().poly_sig();
 
             let bound_vars = tcx.mk_bound_variable_kinds(
@@ -104,10 +104,22 @@ fn fn_sig_for_fn_abi<'tcx>(
             let env_ty = tcx.mk_adt(pin_adt_ref, pin_substs);
 
             let sig = sig.skip_binder();
-            let state_did = tcx.require_lang_item(LangItem::GeneratorState, None);
-            let state_adt_ref = tcx.adt_def(state_did);
-            let state_substs = tcx.intern_substs(&[sig.yield_ty.into(), sig.return_ty.into()]);
-            let ret_ty = tcx.mk_adt(state_adt_ref, state_substs);
+            // The `FnSig` and the `ret_ty` here is for a generators main
+            // `Generator::resume(...) -> GeneratorState` function in case we
+            // have an ordinary generator, or the `Future::poll(...) -> Poll`
+            // function in case this is a special generator backing an async construct.
+            let ret_ty = if tcx.generator_is_async(did) {
+                let state_did = tcx.require_lang_item(LangItem::Poll, None);
+                let state_adt_ref = tcx.adt_def(state_did);
+                let state_substs = tcx.intern_substs(&[sig.return_ty.into()]);
+                tcx.mk_adt(state_adt_ref, state_substs)
+            } else {
+                let state_did = tcx.require_lang_item(LangItem::GeneratorState, None);
+                let state_adt_ref = tcx.adt_def(state_did);
+                let state_substs = tcx.intern_substs(&[sig.yield_ty.into(), sig.return_ty.into()]);
+                tcx.mk_adt(state_adt_ref, state_substs)
+            };
+
             ty::Binder::bind_with_vars(
                 tcx.mk_fn_sig(
                     [env_ty, sig.resume_ty].iter(),
index c6f2b16ca210226db5b9482d7233e87676418292..2da98d3342984bb7231514d46caeec899e442075 100644 (file)
@@ -44,7 +44,13 @@ fn inner_resolve_instance<'tcx>(
 
     let result = if let Some(trait_def_id) = tcx.trait_of_item(def.did) {
         debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env);
-        resolve_associated_item(tcx, def.did, param_env, trait_def_id, substs)
+        resolve_associated_item(
+            tcx,
+            def.did,
+            param_env,
+            trait_def_id,
+            tcx.normalize_erasing_regions(param_env, substs),
+        )
     } else {
         let ty = tcx.type_of(def.def_id_for_type_of());
         let item_type = tcx.subst_and_normalize_erasing_regions(substs, param_env, ty);
index fbc055b5d238f8690555df090b99c3e267f4b126..c761a4dbe4500bfbc78b9576bbfabb873a4de662 100644 (file)
@@ -1,3 +1,4 @@
+use hir::def_id::DefId;
 use rustc_hir as hir;
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::{Idx, IndexVec};
@@ -6,7 +7,7 @@
     IntegerExt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, MAX_SIMD_LANES,
 };
 use rustc_middle::ty::{
-    self, subst::SubstsRef, EarlyBinder, ReprOptions, Ty, TyCtxt, TypeVisitable,
+    self, subst::SubstsRef, AdtDef, EarlyBinder, ReprOptions, Ty, TyCtxt, TypeVisitable,
 };
 use rustc_session::{DataTypeKind, FieldInfo, SizeKind, VariantInfo};
 use rustc_span::symbol::Symbol;
@@ -443,7 +444,7 @@ fn layout_of_uncached<'tcx>(
         }
 
         // Types with no meaningful known layout.
-        ty::Projection(_) | ty::Opaque(..) => {
+        ty::Alias(..) => {
             // NOTE(eddyb) `layout_of` query should've normalized these away,
             // if that was possible, so there's no reason to try again here.
             return Err(LayoutError::Unknown(ty));
@@ -814,27 +815,39 @@ fn record_layout_for_printing_outlined<'tcx>(
         );
     };
 
-    let adt_def = match *layout.ty.kind() {
-        ty::Adt(ref adt_def, _) => {
+    match *layout.ty.kind() {
+        ty::Adt(adt_def, _) => {
             debug!("print-type-size t: `{:?}` process adt", layout.ty);
-            adt_def
+            let adt_kind = adt_def.adt_kind();
+            let adt_packed = adt_def.repr().pack.is_some();
+            let (variant_infos, opt_discr_size) = variant_info_for_adt(cx, layout, adt_def);
+            record(adt_kind.into(), adt_packed, opt_discr_size, variant_infos);
+        }
+
+        ty::Generator(def_id, substs, _) => {
+            debug!("print-type-size t: `{:?}` record generator", layout.ty);
+            // Generators always have a begin/poisoned/end state with additional suspend points
+            let (variant_infos, opt_discr_size) =
+                variant_info_for_generator(cx, layout, def_id, substs);
+            record(DataTypeKind::Generator, false, opt_discr_size, variant_infos);
         }
 
         ty::Closure(..) => {
             debug!("print-type-size t: `{:?}` record closure", layout.ty);
             record(DataTypeKind::Closure, false, None, vec![]);
-            return;
         }
 
         _ => {
             debug!("print-type-size t: `{:?}` skip non-nominal", layout.ty);
-            return;
         }
     };
+}
 
-    let adt_kind = adt_def.adt_kind();
-    let adt_packed = adt_def.repr().pack.is_some();
-
+fn variant_info_for_adt<'tcx>(
+    cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
+    layout: TyAndLayout<'tcx>,
+    adt_def: AdtDef<'tcx>,
+) -> (Vec<VariantInfo>, Option<Size>) {
     let build_variant_info = |n: Option<Symbol>, flds: &[Symbol], layout: TyAndLayout<'tcx>| {
         let mut min_size = Size::ZERO;
         let field_info: Vec<_> = flds
@@ -843,10 +856,7 @@ fn record_layout_for_printing_outlined<'tcx>(
             .map(|(i, &name)| {
                 let field_layout = layout.field(cx, i);
                 let offset = layout.fields.offset(i);
-                let field_end = offset + field_layout.size;
-                if min_size < field_end {
-                    min_size = field_end;
-                }
+                min_size = min_size.max(offset + field_layout.size);
                 FieldInfo {
                     name,
                     offset: offset.bytes(),
@@ -871,16 +881,9 @@ fn record_layout_for_printing_outlined<'tcx>(
                 debug!("print-type-size `{:#?}` variant {}", layout, adt_def.variant(index).name);
                 let variant_def = &adt_def.variant(index);
                 let fields: Vec<_> = variant_def.fields.iter().map(|f| f.name).collect();
-                record(
-                    adt_kind.into(),
-                    adt_packed,
-                    None,
-                    vec![build_variant_info(Some(variant_def.name), &fields, layout)],
-                );
+                (vec![build_variant_info(Some(variant_def.name), &fields, layout)], None)
             } else {
-                // (This case arises for *empty* enums; so give it
-                // zero variants.)
-                record(adt_kind.into(), adt_packed, None, vec![]);
+                (vec![], None)
             }
         }
 
@@ -898,15 +901,117 @@ fn record_layout_for_printing_outlined<'tcx>(
                     build_variant_info(Some(variant_def.name), &fields, layout.for_variant(cx, i))
                 })
                 .collect();
-            record(
-                adt_kind.into(),
-                adt_packed,
+
+            (
+                variant_infos,
                 match tag_encoding {
                     TagEncoding::Direct => Some(tag.size(cx)),
                     _ => None,
                 },
-                variant_infos,
-            );
+            )
         }
     }
 }
+
+fn variant_info_for_generator<'tcx>(
+    cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
+    layout: TyAndLayout<'tcx>,
+    def_id: DefId,
+    substs: ty::SubstsRef<'tcx>,
+) -> (Vec<VariantInfo>, Option<Size>) {
+    let Variants::Multiple { tag, ref tag_encoding, tag_field, .. } = layout.variants else {
+        return (vec![], None);
+    };
+
+    let (generator, state_specific_names) = cx.tcx.generator_layout_and_saved_local_names(def_id);
+    let upvar_names = cx.tcx.closure_saved_names_of_captured_variables(def_id);
+
+    let mut upvars_size = Size::ZERO;
+    let upvar_fields: Vec<_> = substs
+        .as_generator()
+        .upvar_tys()
+        .zip(upvar_names)
+        .enumerate()
+        .map(|(field_idx, (_, name))| {
+            let field_layout = layout.field(cx, field_idx);
+            let offset = layout.fields.offset(field_idx);
+            upvars_size = upvars_size.max(offset + field_layout.size);
+            FieldInfo {
+                name: Symbol::intern(&name),
+                offset: offset.bytes(),
+                size: field_layout.size.bytes(),
+                align: field_layout.align.abi.bytes(),
+            }
+        })
+        .collect();
+
+    let variant_infos: Vec<_> = generator
+        .variant_fields
+        .iter_enumerated()
+        .map(|(variant_idx, variant_def)| {
+            let variant_layout = layout.for_variant(cx, variant_idx);
+            let mut variant_size = Size::ZERO;
+            let fields = variant_def
+                .iter()
+                .enumerate()
+                .map(|(field_idx, local)| {
+                    let field_layout = variant_layout.field(cx, field_idx);
+                    let offset = variant_layout.fields.offset(field_idx);
+                    // The struct is as large as the last field's end
+                    variant_size = variant_size.max(offset + field_layout.size);
+                    FieldInfo {
+                        name: state_specific_names.get(*local).copied().flatten().unwrap_or(
+                            Symbol::intern(&format!(".generator_field{}", local.as_usize())),
+                        ),
+                        offset: offset.bytes(),
+                        size: field_layout.size.bytes(),
+                        align: field_layout.align.abi.bytes(),
+                    }
+                })
+                .chain(upvar_fields.iter().copied())
+                .collect();
+
+            // If the variant has no state-specific fields, then it's the size of the upvars.
+            if variant_size == Size::ZERO {
+                variant_size = upvars_size;
+            }
+
+            // This `if` deserves some explanation.
+            //
+            // The layout code has a choice of where to place the discriminant of this generator.
+            // If the discriminant of the generator is placed early in the layout (before the
+            // variant's own fields), then it'll implicitly be counted towards the size of the
+            // variant, since we use the maximum offset to calculate size.
+            //    (side-note: I know this is a bit problematic given upvars placement, etc).
+            //
+            // This is important, since the layout printing code always subtracts this discriminant
+            // size from the variant size if the struct is "enum"-like, so failing to account for it
+            // will either lead to numerical underflow, or an underreported variant size...
+            //
+            // However, if the discriminant is placed past the end of the variant, then we need
+            // to factor in the size of the discriminant manually. This really should be refactored
+            // better, but this "works" for now.
+            if layout.fields.offset(tag_field) >= variant_size {
+                variant_size += match tag_encoding {
+                    TagEncoding::Direct => tag.size(cx),
+                    _ => Size::ZERO,
+                };
+            }
+
+            VariantInfo {
+                name: Some(Symbol::intern(&ty::GeneratorSubsts::variant_name(variant_idx))),
+                kind: SizeKind::Exact,
+                size: variant_size.bytes(),
+                align: variant_layout.align.abi.bytes(),
+                fields,
+            }
+        })
+        .collect();
+    (
+        variant_infos,
+        match tag_encoding {
+            TagEncoding::Direct => Some(tag.size(cx)),
+            _ => None,
+        },
+    )
+}
index cce5a79ddc855cbcc5970c55855cb94edafb0fdb..7ad5cbc01ccf25293c116f05025bca179b33d0e3 100644 (file)
@@ -29,6 +29,7 @@
 mod layout_sanity_check;
 mod needs_drop;
 pub mod representability;
+mod structural_match;
 mod ty;
 
 pub fn provide(providers: &mut Providers) {
@@ -42,4 +43,5 @@ pub fn provide(providers: &mut Providers) {
     representability::provide(providers);
     ty::provide(providers);
     instance::provide(providers);
+    structural_match::provide(providers);
 }
index 024dcd591bd77d68d321bb27a7016ee9b1b544e7..0df060fc5fb71eae719d70216303c22e90f8af17 100644 (file)
@@ -152,7 +152,7 @@ fn next(&mut self) -> Option<NeedsDropResult<Ty<'tcx>>> {
                             queue_type(self, required);
                         }
                     }
-                    ty::Array(..) | ty::Opaque(..) | ty::Projection(..) | ty::Param(_) => {
+                    ty::Array(..) | ty::Alias(..) | ty::Param(_) => {
                         if ty == component {
                             // Return the type to the caller: they may be able
                             // to normalize further than we can.
diff --git a/compiler/rustc_ty_utils/src/structural_match.rs b/compiler/rustc_ty_utils/src/structural_match.rs
new file mode 100644 (file)
index 0000000..a55bb7e
--- /dev/null
@@ -0,0 +1,44 @@
+use rustc_hir::lang_items::LangItem;
+use rustc_middle::ty::query::Providers;
+use rustc_middle::ty::{self, Ty, TyCtxt};
+
+use rustc_infer::infer::TyCtxtInferExt;
+use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
+
+/// This method returns true if and only if `adt_ty` itself has been marked as
+/// eligible for structural-match: namely, if it implements both
+/// `StructuralPartialEq` and `StructuralEq` (which are respectively injected by
+/// `#[derive(PartialEq)]` and `#[derive(Eq)]`).
+///
+/// Note that this does *not* recursively check if the substructure of `adt_ty`
+/// implements the traits.
+fn has_structural_eq_impls<'tcx>(tcx: TyCtxt<'tcx>, adt_ty: Ty<'tcx>) -> bool {
+    let ref infcx = tcx.infer_ctxt().build();
+    let cause = ObligationCause::dummy();
+
+    let ocx = ObligationCtxt::new(infcx);
+    // require `#[derive(PartialEq)]`
+    let structural_peq_def_id =
+        infcx.tcx.require_lang_item(LangItem::StructuralPeq, Some(cause.span));
+    ocx.register_bound(cause.clone(), ty::ParamEnv::empty(), adt_ty, structural_peq_def_id);
+    // for now, require `#[derive(Eq)]`. (Doing so is a hack to work around
+    // the type `for<'a> fn(&'a ())` failing to implement `Eq` itself.)
+    let structural_teq_def_id =
+        infcx.tcx.require_lang_item(LangItem::StructuralTeq, Some(cause.span));
+    ocx.register_bound(cause, ty::ParamEnv::empty(), adt_ty, structural_teq_def_id);
+
+    // We deliberately skip *reporting* fulfillment errors (via
+    // `report_fulfillment_errors`), for two reasons:
+    //
+    // 1. The error messages would mention `std::marker::StructuralPartialEq`
+    //    (a trait which is solely meant as an implementation detail
+    //    for now), and
+    //
+    // 2. We are sometimes doing future-incompatibility lints for
+    //    now, so we do not want unconditional errors here.
+    ocx.select_all_or_error().is_empty()
+}
+
+pub fn provide(providers: &mut Providers) {
+    providers.has_structural_eq_impls = has_structural_eq_impls;
+}
index 5fc9bcac1b19e35bcb55098d7eb06c273dd44dc4..5279fc69a31b3cb6a72b1cd2e665efff89fbd316 100644 (file)
@@ -37,7 +37,7 @@ fn sized_constraint_for_ty<'tcx>(
                 .collect()
         }
 
-        Projection(..) | Opaque(..) => {
+        Alias(..) => {
             // must calculate explicitly.
             // FIXME: consider special-casing always-Sized projections
             vec![ty]
index e3f7a1bd033cea39b7ed706a45ed49ce7e8474e6..c992dbccd62d5656439cc6ca72578f8656200075 100644 (file)
@@ -42,7 +42,7 @@ pub trait Interner {
     type ListBinderExistentialPredicate: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
     type BinderListTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
     type ListTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
-    type ProjectionTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
+    type AliasTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
     type ParamTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
     type BoundTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
     type PlaceholderType: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
index 3ed616d709b1edf4e1b38933c8002417eea0fb67..f30ae82d7cdd2b4fd4d596c0e207f016efa4aada 100644 (file)
@@ -1,6 +1,6 @@
 #![allow(rustc::usage_of_ty_tykind)]
 
-use std::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
+use std::cmp::Ordering;
 use std::{fmt, hash};
 
 use crate::DebruijnIndex;
 use rustc_serialize::{Decodable, Decoder, Encodable};
 
 /// Specifies how a trait object is represented.
-#[derive(
-    Clone,
-    Copy,
-    PartialEq,
-    Eq,
-    PartialOrd,
-    Ord,
-    Hash,
-    Debug,
-    Encodable,
-    Decodable,
-    HashStable_Generic
-)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[derive(Encodable, Decodable, HashStable_Generic)]
 pub enum DynKind {
     /// An unsized `dyn Trait` object
     Dyn,
@@ -46,6 +35,13 @@ pub enum DynKind {
     DynStar,
 }
 
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[derive(Encodable, Decodable, HashStable_Generic)]
+pub enum AliasKind {
+    Projection,
+    Opaque,
+}
+
 /// Defines the kinds of types used by the type system.
 ///
 /// Types written by the user start out as `hir::TyKind` and get
@@ -170,21 +166,8 @@ pub enum TyKind<I: Interner> {
     /// A tuple type. For example, `(i32, bool)`.
     Tuple(I::ListTy),
 
-    /// The projection of an associated type. For example,
-    /// `<T as Trait<..>>::N`.
-    Projection(I::ProjectionTy),
-
-    /// Opaque (`impl Trait`) type found in a return type.
-    ///
-    /// The `DefId` comes either from
-    /// * the `impl Trait` ast::Ty node,
-    /// * or the `type Foo = impl Trait` declaration
-    ///
-    /// For RPIT the substitutions are for the generics of the function,
-    /// while for TAIT it is used for the generic parameters of the alias.
-    ///
-    /// During codegen, `tcx.type_of(def_id)` can be used to get the underlying type.
-    Opaque(I::DefId, I::SubstsRef),
+    /// A projection or opaque type. Both of these types
+    Alias(AliasKind, I::AliasTy),
 
     /// A type parameter; for example, `T` in `fn f<T>(x: T) {}`.
     Param(I::ParamTy),
@@ -252,13 +235,12 @@ const fn tykind_discriminant<I: Interner>(value: &TyKind<I>) -> usize {
         GeneratorWitness(_) => 17,
         Never => 18,
         Tuple(_) => 19,
-        Projection(_) => 20,
-        Opaque(_, _) => 21,
-        Param(_) => 22,
-        Bound(_, _) => 23,
-        Placeholder(_) => 24,
-        Infer(_) => 25,
-        Error(_) => 26,
+        Alias(_, _) => 20,
+        Param(_) => 21,
+        Bound(_, _) => 22,
+        Placeholder(_) => 23,
+        Infer(_) => 24,
+        Error(_) => 25,
     }
 }
 
@@ -268,9 +250,9 @@ fn clone(&self) -> Self {
         match self {
             Bool => Bool,
             Char => Char,
-            Int(i) => Int(i.clone()),
-            Uint(u) => Uint(u.clone()),
-            Float(f) => Float(f.clone()),
+            Int(i) => Int(*i),
+            Uint(u) => Uint(*u),
+            Float(f) => Float(*f),
             Adt(d, s) => Adt(d.clone(), s.clone()),
             Foreign(d) => Foreign(d.clone()),
             Str => Str,
@@ -280,16 +262,15 @@ fn clone(&self) -> Self {
             Ref(r, t, m) => Ref(r.clone(), t.clone(), m.clone()),
             FnDef(d, s) => FnDef(d.clone(), s.clone()),
             FnPtr(s) => FnPtr(s.clone()),
-            Dynamic(p, r, repr) => Dynamic(p.clone(), r.clone(), repr.clone()),
+            Dynamic(p, r, repr) => Dynamic(p.clone(), r.clone(), *repr),
             Closure(d, s) => Closure(d.clone(), s.clone()),
             Generator(d, s, m) => Generator(d.clone(), s.clone(), m.clone()),
             GeneratorWitness(g) => GeneratorWitness(g.clone()),
             Never => Never,
             Tuple(t) => Tuple(t.clone()),
-            Projection(p) => Projection(p.clone()),
-            Opaque(d, s) => Opaque(d.clone(), s.clone()),
+            Alias(k, p) => Alias(*k, p.clone()),
             Param(p) => Param(p.clone()),
-            Bound(d, b) => Bound(d.clone(), b.clone()),
+            Bound(d, b) => Bound(*d, b.clone()),
             Placeholder(p) => Placeholder(p.clone()),
             Infer(t) => Infer(t.clone()),
             Error(e) => Error(e.clone()),
@@ -323,8 +304,7 @@ fn eq(&self, other: &TyKind<I>) -> bool {
                 }
                 (GeneratorWitness(a_g), GeneratorWitness(b_g)) => a_g == b_g,
                 (Tuple(a_t), Tuple(b_t)) => a_t == b_t,
-                (Projection(a_p), Projection(b_p)) => a_p == b_p,
-                (Opaque(a_d, a_s), Opaque(b_d, b_s)) => a_d == b_d && a_s == b_s,
+                (Alias(a_i, a_p), Alias(b_i, b_p)) => a_i == b_i && a_p == b_p,
                 (Param(a_p), Param(b_p)) => a_p == b_p,
                 (Bound(a_d, a_b), Bound(b_d, b_b)) => a_d == b_d && a_b == b_b,
                 (Placeholder(a_p), Placeholder(b_p)) => a_p == b_p,
@@ -381,8 +361,7 @@ fn cmp(&self, other: &TyKind<I>) -> Ordering {
                 }
                 (GeneratorWitness(a_g), GeneratorWitness(b_g)) => a_g.cmp(b_g),
                 (Tuple(a_t), Tuple(b_t)) => a_t.cmp(b_t),
-                (Projection(a_p), Projection(b_p)) => a_p.cmp(b_p),
-                (Opaque(a_d, a_s), Opaque(b_d, b_s)) => a_d.cmp(b_d).then_with(|| a_s.cmp(b_s)),
+                (Alias(a_i, a_p), Alias(b_i, b_p)) => a_i.cmp(b_i).then_with(|| a_p.cmp(b_p)),
                 (Param(a_p), Param(b_p)) => a_p.cmp(b_p),
                 (Bound(a_d, a_b), Bound(b_d, b_b)) => a_d.cmp(b_d).then_with(|| a_b.cmp(b_b)),
                 (Placeholder(a_p), Placeholder(b_p)) => a_p.cmp(b_p),
@@ -443,10 +422,9 @@ fn hash<__H: hash::Hasher>(&self, state: &mut __H) -> () {
             }
             GeneratorWitness(g) => g.hash(state),
             Tuple(t) => t.hash(state),
-            Projection(p) => p.hash(state),
-            Opaque(d, s) => {
-                d.hash(state);
-                s.hash(state)
+            Alias(i, p) => {
+                i.hash(state);
+                p.hash(state);
             }
             Param(p) => p.hash(state),
             Bound(d, b) => {
@@ -485,8 +463,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             GeneratorWitness(g) => f.debug_tuple_field1_finish("GeneratorWitness", g),
             Never => f.write_str("Never"),
             Tuple(t) => f.debug_tuple_field1_finish("Tuple", t),
-            Projection(p) => f.debug_tuple_field1_finish("Projection", p),
-            Opaque(d, s) => f.debug_tuple_field2_finish("Opaque", d, s),
+            Alias(i, a) => f.debug_tuple_field2_finish("Alias", i, a),
             Param(p) => f.debug_tuple_field1_finish("Param", p),
             Bound(d, b) => f.debug_tuple_field2_finish("Bound", d, b),
             Placeholder(p) => f.debug_tuple_field1_finish("Placeholder", p),
@@ -513,7 +490,7 @@ impl<I: Interner, E: TyEncoder> Encodable<E> for TyKind<I>
     I::ListBinderExistentialPredicate: Encodable<E>,
     I::BinderListTy: Encodable<E>,
     I::ListTy: Encodable<E>,
-    I::ProjectionTy: Encodable<E>,
+    I::AliasTy: Encodable<E>,
     I::ParamTy: Encodable<E>,
     I::BoundTy: Encodable<E>,
     I::PlaceholderType: Encodable<E>,
@@ -586,13 +563,10 @@ fn encode(&self, e: &mut E) {
             Tuple(substs) => e.emit_enum_variant(disc, |e| {
                 substs.encode(e);
             }),
-            Projection(p) => e.emit_enum_variant(disc, |e| {
+            Alias(k, p) => e.emit_enum_variant(disc, |e| {
+                k.encode(e);
                 p.encode(e);
             }),
-            Opaque(def_id, substs) => e.emit_enum_variant(disc, |e| {
-                def_id.encode(e);
-                substs.encode(e);
-            }),
             Param(p) => e.emit_enum_variant(disc, |e| {
                 p.encode(e);
             }),
@@ -630,8 +604,9 @@ impl<I: Interner, D: TyDecoder<I = I>> Decodable<D> for TyKind<I>
     I::ListBinderExistentialPredicate: Decodable<D>,
     I::BinderListTy: Decodable<D>,
     I::ListTy: Decodable<D>,
-    I::ProjectionTy: Decodable<D>,
+    I::AliasTy: Decodable<D>,
     I::ParamTy: Decodable<D>,
+    I::AliasTy: Decodable<D>,
     I::BoundTy: Decodable<D>,
     I::PlaceholderType: Decodable<D>,
     I::InferTy: Decodable<D>,
@@ -660,13 +635,12 @@ fn decode(d: &mut D) -> Self {
             17 => GeneratorWitness(Decodable::decode(d)),
             18 => Never,
             19 => Tuple(Decodable::decode(d)),
-            20 => Projection(Decodable::decode(d)),
-            21 => Opaque(Decodable::decode(d), Decodable::decode(d)),
-            22 => Param(Decodable::decode(d)),
-            23 => Bound(Decodable::decode(d), Decodable::decode(d)),
-            24 => Placeholder(Decodable::decode(d)),
-            25 => Infer(Decodable::decode(d)),
-            26 => Error(Decodable::decode(d)),
+            20 => Alias(Decodable::decode(d), Decodable::decode(d)),
+            21 => Param(Decodable::decode(d)),
+            22 => Bound(Decodable::decode(d), Decodable::decode(d)),
+            23 => Placeholder(Decodable::decode(d)),
+            24 => Infer(Decodable::decode(d)),
+            25 => Error(Decodable::decode(d)),
             _ => panic!(
                 "{}",
                 format!(
@@ -695,7 +669,7 @@ impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for TyKind<I>
     I::Mutability: HashStable<CTX>,
     I::BinderListTy: HashStable<CTX>,
     I::ListTy: HashStable<CTX>,
-    I::ProjectionTy: HashStable<CTX>,
+    I::AliasTy: HashStable<CTX>,
     I::BoundTy: HashStable<CTX>,
     I::ParamTy: HashStable<CTX>,
     I::PlaceholderType: HashStable<CTX>,
@@ -772,13 +746,10 @@ fn hash_stable(
             Tuple(substs) => {
                 substs.hash_stable(__hcx, __hasher);
             }
-            Projection(p) => {
+            Alias(k, p) => {
+                k.hash_stable(__hcx, __hasher);
                 p.hash_stable(__hcx, __hasher);
             }
-            Opaque(def_id, substs) => {
-                def_id.hash_stable(__hcx, __hasher);
-                substs.hash_stable(__hcx, __hasher);
-            }
             Param(p) => {
                 p.hash_stable(__hcx, __hasher);
             }
@@ -965,7 +936,7 @@ impl<I: Interner> Clone for RegionKind<I> {
     fn clone(&self) -> Self {
         match self {
             ReEarlyBound(r) => ReEarlyBound(r.clone()),
-            ReLateBound(d, r) => ReLateBound(d.clone(), r.clone()),
+            ReLateBound(d, r) => ReLateBound(*d, r.clone()),
             ReFree(r) => ReFree(r.clone()),
             ReStatic => ReStatic,
             ReVar(r) => ReVar(r.clone()),
index ca54cbd2d68dc213051f86673ddf3e7fa965cba7..5e1d2f2e314ff904173d04c224797cd2b017b5f2 100644 (file)
@@ -35,9 +35,6 @@ changelog-seen = 2
 # Unless you're developing for a target where Rust CI doesn't build a compiler
 # toolchain or changing LLVM locally, you probably want to set this to true.
 #
-# This is false by default so that distributions don't unexpectedly download
-# LLVM from the internet.
-#
 # All tier 1 targets are currently supported; set this to `"if-available"` if
 # you are not sure whether you're on a tier 1 target.
 #
@@ -45,7 +42,9 @@ changelog-seen = 2
 #
 # Note that many of the LLVM options are not currently supported for
 # downloading. Currently only the "assertions" option can be toggled.
-#download-ci-llvm = false
+#
+# Defaults to "if-available" when `channel = "dev"` and "false" otherwise.
+#download-ci-llvm = "if-available"
 
 # Indicates whether LLVM rebuild should be skipped when running bootstrap. If
 # this is `false` then the compiler's LLVM will be rebuilt whenever the built
index 55f6138cd0f31407217fd4ef17fb391a5f55c80d..e54880e8652305b7f173d08f48aae0b18276212d 100644 (file)
@@ -25,6 +25,10 @@ impl<T, A: Allocator> IntoIter<T, A> {
     pub(super) fn new(inner: VecDeque<T, A>) -> Self {
         IntoIter { inner }
     }
+
+    pub(super) fn into_vecdeque(self) -> VecDeque<T, A> {
+        self.inner
+    }
 }
 
 #[stable(feature = "collection_debug", since = "1.17.0")]
index 4866c53e7d521c64d5870b2e8be8553d86e24bc7..be615b70ced9cfffd9f0ffd2c61752a61410538a 100644 (file)
 
 mod spec_extend;
 
+use self::spec_from_iter::SpecFromIter;
+
+mod spec_from_iter;
+
 #[cfg(test)]
 mod tests;
 
@@ -586,6 +590,38 @@ pub fn with_capacity_in(capacity: usize, alloc: A) -> VecDeque<T, A> {
         VecDeque { head: 0, len: 0, buf: RawVec::with_capacity_in(capacity, alloc) }
     }
 
+    /// Creates a `VecDeque` from a raw allocation, when the initialized
+    /// part of that allocation forms a *contiguous* subslice thereof.
+    ///
+    /// For use by `vec::IntoIter::into_vecdeque`
+    ///
+    /// # Safety
+    ///
+    /// All the usual requirements on the allocated memory like in
+    /// `Vec::from_raw_parts_in`, but takes a *range* of elements that are
+    /// initialized rather than only supporting `0..len`.  Requires that
+    /// `initialized.start` ≤ `initialized.end` ≤ `capacity`.
+    #[inline]
+    pub(crate) unsafe fn from_contiguous_raw_parts_in(
+        ptr: *mut T,
+        initialized: Range<usize>,
+        capacity: usize,
+        alloc: A,
+    ) -> Self {
+        debug_assert!(initialized.start <= initialized.end);
+        debug_assert!(initialized.end <= capacity);
+
+        // SAFETY: Our safety precondition guarantees the range length won't wrap,
+        // and that the allocation is valid for use in `RawVec`.
+        unsafe {
+            VecDeque {
+                head: initialized.start,
+                len: initialized.end.unchecked_sub(initialized.start),
+                buf: RawVec::from_raw_parts_in(ptr, capacity, alloc),
+            }
+        }
+    }
+
     /// Provides a reference to the element at the given index.
     ///
     /// Element at index 0 is the front of the queue.
@@ -2505,7 +2541,7 @@ pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, mut f: F) -> Result<usize
     /// The deque is assumed to be partitioned according to the given predicate.
     /// This means that all elements for which the predicate returns true are at the start of the deque
     /// and all elements for which the predicate returns false are at the end.
-    /// For example, [7, 15, 3, 5, 4, 12, 6] is a partitioned under the predicate x % 2 != 0
+    /// For example, `[7, 15, 3, 5, 4, 12, 6]` is partitioned under the predicate `x % 2 != 0`
     /// (all odd numbers are at the start, all even at the end).
     ///
     /// If the deque is not partitioned, the returned result is unspecified and meaningless,
@@ -2699,18 +2735,8 @@ fn index_mut(&mut self, index: usize) -> &mut T {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> FromIterator<T> for VecDeque<T> {
-    #[inline]
     fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> VecDeque<T> {
-        // Since converting is O(1) now, might as well re-use that logic
-        // (including things like the `vec::IntoIter`→`Vec` specialization)
-        // especially as that could save us some monomorphiziation work
-        // if one uses the same iterators (like slice ones) with both.
-        return from_iter_via_vec(iter.into_iter());
-
-        #[inline]
-        fn from_iter_via_vec<U>(iter: impl Iterator<Item = U>) -> VecDeque<U> {
-            Vec::from_iter(iter).into()
-        }
+        SpecFromIter::spec_from_iter(iter.into_iter())
     }
 }
 
diff --git a/library/alloc/src/collections/vec_deque/spec_from_iter.rs b/library/alloc/src/collections/vec_deque/spec_from_iter.rs
new file mode 100644 (file)
index 0000000..7650492
--- /dev/null
@@ -0,0 +1,33 @@
+use super::{IntoIter, VecDeque};
+
+/// Specialization trait used for `VecDeque::from_iter`
+pub(super) trait SpecFromIter<T, I> {
+    fn spec_from_iter(iter: I) -> Self;
+}
+
+impl<T, I> SpecFromIter<T, I> for VecDeque<T>
+where
+    I: Iterator<Item = T>,
+{
+    default fn spec_from_iter(iterator: I) -> Self {
+        // Since converting is O(1) now, just re-use the `Vec` logic for
+        // anything where we can't do something extra-special for `VecDeque`,
+        // especially as that could save us some monomorphiziation work
+        // if one uses the same iterators (like slice ones) with both.
+        crate::vec::Vec::from_iter(iterator).into()
+    }
+}
+
+impl<T> SpecFromIter<T, crate::vec::IntoIter<T>> for VecDeque<T> {
+    #[inline]
+    fn spec_from_iter(iterator: crate::vec::IntoIter<T>) -> Self {
+        iterator.into_vecdeque()
+    }
+}
+
+impl<T> SpecFromIter<T, IntoIter<T>> for VecDeque<T> {
+    #[inline]
+    fn spec_from_iter(iterator: IntoIter<T>) -> Self {
+        iterator.into_vecdeque()
+    }
+}
index 799ce9d5daa888573c48100239baa23df32300d6..eadb35cb96d422cfcdc84250b820b7cef65ea54c 100644 (file)
 //!         // documentation for details, and the function `pad` can be used
 //!         // to pad strings.
 //!         let decimals = f.precision().unwrap_or(3);
-//!         let string = format!("{:.*}", decimals, magnitude);
+//!         let string = format!("{magnitude:.decimals$}");
 //!         f.pad_integral(true, "", &string)
 //!     }
 //! }
 //! write!(&mut some_writer, "{}", format_args!("print with a {}", "macro"));
 //!
 //! fn my_fmt_fn(args: fmt::Arguments) {
-//!     write!(&mut io::stdout(), "{}", args);
+//!     write!(&mut io::stdout(), "{args}");
 //! }
 //! my_fmt_fn(format_args!(", or a {} too", "function"));
 //! ```
index 02cc7691a82db6af72b99fd9c735e17656ea048b..6bcde6d899ce81776fe8dc55c20d528daec84472 100644 (file)
@@ -1,6 +1,8 @@
 #[cfg(not(no_global_oom_handling))]
 use super::AsVecIntoIter;
 use crate::alloc::{Allocator, Global};
+#[cfg(not(no_global_oom_handling))]
+use crate::collections::VecDeque;
 use crate::raw_vec::RawVec;
 use core::array;
 use core::fmt;
@@ -132,6 +134,33 @@ pub(super) fn forget_allocation_drop_remaining(&mut self) {
     pub(crate) fn forget_remaining_elements(&mut self) {
         self.ptr = self.end;
     }
+
+    #[cfg(not(no_global_oom_handling))]
+    #[inline]
+    pub(crate) fn into_vecdeque(self) -> VecDeque<T, A> {
+        // Keep our `Drop` impl from dropping the elements and the allocator
+        let mut this = ManuallyDrop::new(self);
+
+        // SAFETY: This allocation originally came from a `Vec`, so it passes
+        // all those checks.  We have `this.buf` ≤ `this.ptr` ≤ `this.end`,
+        // so the `sub_ptr`s below cannot wrap, and will produce a well-formed
+        // range.  `end` ≤ `buf + cap`, so the range will be in-bounds.
+        // Taking `alloc` is ok because nothing else is going to look at it,
+        // since our `Drop` impl isn't going to run so there's no more code.
+        unsafe {
+            let buf = this.buf.as_ptr();
+            let initialized = if T::IS_ZST {
+                // All the pointers are the same for ZSTs, so it's fine to
+                // say that they're all at the beginning of the "allocation".
+                0..this.len()
+            } else {
+                this.ptr.sub_ptr(buf)..this.end.sub_ptr(buf)
+            };
+            let cap = this.cap;
+            let alloc = ManuallyDrop::take(&mut this.alloc);
+            VecDeque::from_contiguous_raw_parts_in(buf, initialized, cap, alloc)
+        }
+    }
 }
 
 #[stable(feature = "vec_intoiter_as_ref", since = "1.46.0")]
index d04de5a074b7fafa3d186d6762a336141c133b2b..0b8f5281b785cab4af103238d5125bc1660f358c 100644 (file)
@@ -1736,3 +1736,39 @@ fn test_resize_keeps_reserved_space_from_item() {
     d.resize(1, v);
     assert_eq!(d[0].capacity(), 1234);
 }
+
+#[test]
+fn test_collect_from_into_iter_keeps_allocation() {
+    let mut v = Vec::with_capacity(13);
+    v.extend(0..7);
+    check(v.as_ptr(), v.last().unwrap(), v.into_iter());
+
+    let mut v = VecDeque::with_capacity(13);
+    v.extend(0..7);
+    check(&v[0], &v[v.len() - 1], v.into_iter());
+
+    fn check(buf: *const i32, last: *const i32, mut it: impl Iterator<Item = i32>) {
+        assert_eq!(it.next(), Some(0));
+        assert_eq!(it.next(), Some(1));
+
+        let mut v: VecDeque<i32> = it.collect();
+        assert_eq!(v.capacity(), 13);
+        assert_eq!(v.as_slices().0.as_ptr(), buf.wrapping_add(2));
+        assert_eq!(&v[v.len() - 1] as *const _, last);
+
+        assert_eq!(v.as_slices(), ([2, 3, 4, 5, 6].as_slice(), [].as_slice()));
+        v.push_front(7);
+        assert_eq!(v.as_slices(), ([7, 2, 3, 4, 5, 6].as_slice(), [].as_slice()));
+        v.push_front(8);
+        assert_eq!(v.as_slices(), ([8, 7, 2, 3, 4, 5, 6].as_slice(), [].as_slice()));
+
+        // Now that we've adding thing in place of the two that we removed from
+        // the front of the iterator, we're back to matching the buffer pointer.
+        assert_eq!(v.as_slices().0.as_ptr(), buf);
+        assert_eq!(&v[v.len() - 1] as *const _, last);
+
+        v.push_front(9);
+        assert_eq!(v.as_slices(), ([9].as_slice(), [8, 7, 2, 3, 4, 5, 6].as_slice()));
+        assert_eq!(v.capacity(), 13);
+    }
+}
index 94a1a1d32bcd66d7327c2a2a1142774cdcd33973..2825e0bbb438593a9217c8a490fd6161f5f2bcd0 100644 (file)
@@ -69,7 +69,7 @@
 /// if any element creation was unsuccessful.
 ///
 /// The return type of this function depends on the return type of the closure.
-/// If you return `Result<T, E>` from the closure, you'll get a `Result<[T; N]; E>`.
+/// If you return `Result<T, E>` from the closure, you'll get a `Result<[T; N], E>`.
 /// If you return `Option<T>` from the closure, you'll get an `Option<[T; N]>`.
 ///
 /// # Arguments
@@ -522,7 +522,7 @@ macro_rules! array_impl_default {
     /// return an array the same size as `self` or the first error encountered.
     ///
     /// The return type of this function depends on the return type of the closure.
-    /// If you return `Result<T, E>` from the closure, you'll get a `Result<[T; N]; E>`.
+    /// If you return `Result<T, E>` from the closure, you'll get a `Result<[T; N], E>`.
     /// If you return `Option<T>` from the closure, you'll get an `Option<[T; N]>`.
     ///
     /// # Examples
index fdd56cb4eaa8e462dab96f6816813b9812df2f81..4a8302ee404c109117d56b4e43ee7c7b8ad4f73c 100644 (file)
@@ -26,7 +26,7 @@
 /// to be modified, it can additionally implement [`BorrowMut<T>`].
 ///
 /// Further, when providing implementations for additional traits, it needs
-/// to be considered whether they should behave identical to those of the
+/// to be considered whether they should behave identically to those of the
 /// underlying type as a consequence of acting as a representation of that
 /// underlying type. Generic code typically uses `Borrow<T>` when it relies
 /// on the identical behavior of these additional trait implementations.
index 06dca7e59a2a696088e76775aa814bd14299b9c6..398437d9a023dcb7e386d669e30615f88d869cd7 100644 (file)
@@ -176,7 +176,6 @@ pub struct AssertParamIsCopy<T: Copy + ?Sized> {
 /// are implemented in `traits::SelectionContext::copy_clone_conditions()`
 /// in `rustc_trait_selection`.
 mod impls {
-
     use super::Clone;
 
     macro_rules! impl_clone {
@@ -185,7 +184,7 @@ macro_rules! impl_clone {
                 #[stable(feature = "rust1", since = "1.0.0")]
                 #[rustc_const_unstable(feature = "const_clone", issue = "91805")]
                 impl const Clone for $t {
-                    #[inline]
+                    #[inline(always)]
                     fn clone(&self) -> Self {
                         *self
                     }
@@ -213,7 +212,7 @@ fn clone(&self) -> Self {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_clone", issue = "91805")]
     impl<T: ?Sized> const Clone for *const T {
-        #[inline]
+        #[inline(always)]
         fn clone(&self) -> Self {
             *self
         }
@@ -222,7 +221,7 @@ fn clone(&self) -> Self {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_clone", issue = "91805")]
     impl<T: ?Sized> const Clone for *mut T {
-        #[inline]
+        #[inline(always)]
         fn clone(&self) -> Self {
             *self
         }
@@ -232,7 +231,7 @@ fn clone(&self) -> Self {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_clone", issue = "91805")]
     impl<T: ?Sized> const Clone for &T {
-        #[inline]
+        #[inline(always)]
         #[rustc_diagnostic_item = "noop_method_clone"]
         fn clone(&self) -> Self {
             *self
index 33493964bad2ed8dfb30402444ac8a56041778c8..f95b880df34d37b3b3fc2a8b920bcde4bf6186c5 100644 (file)
@@ -99,7 +99,7 @@
 /// ```
 #[stable(feature = "convert_id", since = "1.33.0")]
 #[rustc_const_stable(feature = "const_identity", since = "1.33.0")]
-#[inline]
+#[inline(always)]
 pub const fn identity<T>(x: T) -> T {
     x
 }
@@ -789,6 +789,7 @@ fn try_from(value: U) -> Result<Self, Self::Error> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> AsRef<[T]> for [T] {
+    #[inline(always)]
     fn as_ref(&self) -> &[T] {
         self
     }
@@ -796,6 +797,7 @@ fn as_ref(&self) -> &[T] {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> AsMut<[T]> for [T] {
+    #[inline(always)]
     fn as_mut(&mut self) -> &mut [T] {
         self
     }
@@ -803,7 +805,7 @@ fn as_mut(&mut self) -> &mut [T] {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl AsRef<str> for str {
-    #[inline]
+    #[inline(always)]
     fn as_ref(&self) -> &str {
         self
     }
@@ -811,7 +813,7 @@ fn as_ref(&self) -> &str {
 
 #[stable(feature = "as_mut_str_for_str", since = "1.51.0")]
 impl AsMut<str> for str {
-    #[inline]
+    #[inline(always)]
     fn as_mut(&mut self) -> &mut str {
         self
     }
index 48b6177434bcbea9d6b7f20f24f70b4809b025e5..122da675f7e439463feed95d44c92de422341100 100644 (file)
@@ -405,7 +405,7 @@ pub const fn new_v1(pieces: &'a [&'static str], args: &'a [ArgumentV1<'a>]) -> A
     /// 1. The `pieces` slice must be at least as long as `fmt`.
     /// 2. Every [`rt::v1::Argument::position`] value within `fmt` must be a
     ///    valid index of `args`.
-    /// 3. Every [`Count::Param`] within `fmt` must contain a valid index of
+    /// 3. Every [`rt::v1::Count::Param`] within `fmt` must contain a valid index of
     ///    `args`.
     #[doc(hidden)]
     #[inline]
index c53175ba4f3f0f7bb23c701eda24d79abfae5926..e8d724ab1ef4eed662ac5ab2810878e6ee8e2904 100644 (file)
 /// ```
 ///
 /// [`thread::yield_now`]: ../../std/thread/fn.yield_now.html
-#[inline]
+#[inline(always)]
 #[stable(feature = "renamed_spin_loop", since = "1.49.0")]
 pub fn spin_loop() {
     #[cfg(target_arch = "x86")]
@@ -345,6 +345,7 @@ pub const fn black_box<T>(dummy: T) -> T {
 #[unstable(feature = "hint_must_use", issue = "94745")]
 #[rustc_const_unstable(feature = "hint_must_use", issue = "94745")]
 #[must_use] // <-- :)
+#[inline(always)]
 pub const fn must_use<T>(value: T) -> T {
     value
 }
index 8ba1c122884ca431173cc28a77d33b6282e7169d..e08a15571fcbed0f74ccc42144202c8addfac029 100644 (file)
 //! #[custom_mir(dialect = "built")]
 //! pub fn simple(x: i32) -> i32 {
 //!     mir!(
-//!         let temp1: i32;
-//!         let temp2: _;
+//!         let temp2: i32;
 //!
 //!         {
-//!             temp1 = x;
-//!             Goto(exit)
+//!             let temp1 = x;
+//!             Goto(my_second_block)
 //!         }
 //!
-//!         exit = {
+//!         my_second_block = {
 //!             temp2 = Move(temp1);
 //!             RET = temp2;
 //!             Return()
 //! }
 //! ```
 //!
-//! Hopefully most of this is fairly self-explanatory. Expanding on some notable details:
+//! The `custom_mir` attribute tells the compiler to treat the function as being custom MIR. This
+//! attribute only works on functions - there is no way to insert custom MIR into the middle of
+//! another function. The `dialect` and `phase` parameters indicate which [version of MIR][dialect
+//! docs] you are inserting here. Generally you'll want to use `#![custom_mir(dialect = "built")]`
+//! if you want your MIR to be modified by the full MIR pipeline, or `#![custom_mir(dialect =
+//! "runtime", phase = "optimized")] if you don't.
 //!
-//!  - The `custom_mir` attribute tells the compiler to treat the function as being custom MIR. This
-//!    attribute only works on functions - there is no way to insert custom MIR into the middle of
-//!    another function.
-//!  - The `dialect` and `phase` parameters indicate which version of MIR you are inserting here.
-//!    This will normally be the phase that corresponds to the thing you are trying to test. The
-//!    phase can be omitted for dialects that have just one.
-//!  - You should define your function signature like you normally would. Externally, this function
-//!    can be called like any other function.
-//!  - Type inference works - you don't have to spell out the type of all of your locals.
+//! [dialect docs]:
+//!     https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.MirPhase.html
 //!
-//! For now, all statements and terminators are parsed from nested invocations of the special
-//! functions provided in this module. We additionally want to (but do not yet) support more
-//! "normal" Rust syntax in places where it makes sense. Also, most kinds of instructions are not
-//! supported yet.
+//! The input to the [`mir!`] macro is:
+//!
+//!  - A possibly empty list of local declarations. Locals can also be declared inline on
+//!    assignments via `let`. Type inference generally works. Shadowing does not.
+//!  - A list of basic blocks. The first of these is the start block and is where execution begins.
+//!    All blocks other than the start block need to be given a name, so that they can be referred
+//!    to later.
+//!     - Each block is a list of semicolon terminated statements, followed by a terminator. The
+//!       syntax for the various statements and terminators is designed to be as similar as possible
+//!       to the syntax for analogous concepts in native Rust. See below for a list.
+//!
+//! # Examples
+//!
+//! ```rust
+//! #![feature(core_intrinsics, custom_mir)]
+//!
+//! extern crate core;
+//! use core::intrinsics::mir::*;
+//!
+//! #[custom_mir(dialect = "built")]
+//! pub fn choose_load(a: &i32, b: &i32, c: bool) -> i32 {
+//!     mir!(
+//!         {
+//!             match c {
+//!                 true => t,
+//!                 _ => f,
+//!             }
+//!         }
+//!
+//!         t = {
+//!             let temp = a;
+//!             Goto(load_and_exit)
+//!         }
+//!
+//!         f = {
+//!             temp = b;
+//!             Goto(load_and_exit)
+//!         }
+//!
+//!         load_and_exit = {
+//!             RET = *temp;
+//!             Return()
+//!         }
+//!     )
+//! }
+//!
+//! #[custom_mir(dialect = "built")]
+//! fn unwrap_unchecked<T>(opt: Option<T>) -> T {
+//!     mir!({
+//!         RET = Move(Field(Variant(opt, 1), 0));
+//!         Return()
+//!     })
+//! }
+//!
+//! #[custom_mir(dialect = "runtime", phase = "optimized")]
+//! fn push_and_pop<T>(v: &mut Vec<T>, value: T) {
+//!     mir!(
+//!         let unused;
+//!         let popped;
+//!
+//!         {
+//!             Call(unused, pop, Vec::push(v, value))
+//!         }
+//!
+//!         pop = {
+//!             Call(popped, drop, Vec::pop(v))
+//!         }
+//!
+//!         drop = {
+//!             Drop(popped, ret)
+//!         }
+//!
+//!         ret = {
+//!             Return()
+//!         }
+//!     )
+//! }
+//! ```
+//!
+//! We can also set off compilation failures that happen in sufficiently late stages of the
+//! compiler:
+//!
+//! ```rust,compile_fail
+//! #![feature(core_intrinsics, custom_mir)]
+//!
+//! extern crate core;
+//! use core::intrinsics::mir::*;
+//!
+//! #[custom_mir(dialect = "built")]
+//! fn borrow_error(should_init: bool) -> i32 {
+//!     mir!(
+//!         let temp: i32;
+//!
+//!         {
+//!             match should_init {
+//!                 true => init,
+//!                 _ => use_temp,
+//!             }
+//!         }
+//!
+//!         init = {
+//!             temp = 0;
+//!             Goto(use_temp)
+//!         }
+//!
+//!         use_temp = {
+//!             RET = temp;
+//!             Return()
+//!         }
+//!     )
+//! }
+//! ```
+//!
+//! ```text
+//! error[E0381]: used binding is possibly-uninitialized
+//!   --> test.rs:24:13
+//!    |
+//! 8  | /     mir!(
+//! 9  | |         let temp: i32;
+//! 10 | |
+//! 11 | |         {
+//! ...  |
+//! 19 | |             temp = 0;
+//!    | |             -------- binding initialized here in some conditions
+//! ...  |
+//! 24 | |             RET = temp;
+//!    | |             ^^^^^^^^^^ value used here but it is possibly-uninitialized
+//! 25 | |             Return()
+//! 26 | |         }
+//! 27 | |     )
+//!    | |_____- binding declared here but left uninitialized
+//!
+//! error: aborting due to previous error
+//!
+//! For more information about this error, try `rustc --explain E0381`.
+//! ```
+//!
+//! # Syntax
+//!
+//! The lists below are an exhaustive description of how various MIR constructs can be created.
+//! Anything missing from the list should be assumed to not be supported, PRs welcome.
+//!
+//! #### Locals
+//!
+//!  - The `_0` return local can always be accessed via `RET`.
+//!  - Arguments can be accessed via their regular name.
+//!  - All other locals need to be declared with `let` somewhere and then can be accessed by name.
+//!
+//! #### Places
+//!  - Locals implicit convert to places.
+//!  - Field accesses, derefs, and indexing work normally.
+//!  - Fields in variants can be accessed via the [`Variant`] and [`Field`] associated functions,
+//!    see their documentation for details.
+//!
+//! #### Operands
+//!  - Places implicitly convert to `Copy` operands.
+//!  - `Move` operands can be created via [`Move`].
+//!  - Const blocks, literals, named constants, and const params all just work.
+//!  - [`Static`] and [`StaticMut`] can be used to create `&T` and `*mut T`s to statics. These are
+//!    constants in MIR and the only way to access statics.
+//!
+//! #### Statements
+//!  - Assign statements work via normal Rust assignment.
+//!  - [`Retag`] statements have an associated function.
+//!
+//! #### Rvalues
+//!
+//!  - Operands implicitly convert to `Use` rvalues.
+//!  - `&`, `&mut`, `addr_of!`, and `addr_of_mut!` all work to create their associated rvalue.
+//!  - [`Discriminant`] has an associated function.
+//!
+//! #### Terminators
+//!
+//! Custom MIR does not currently support cleanup blocks or non-trivial unwind paths. As such, there
+//! are no resume and abort terminators, and terminators that might unwind do not have any way to
+//! indicate the unwind block.
+//!
+//!  - [`Goto`], [`Return`], [`Unreachable`], [`Drop`](Drop()), and [`DropAndReplace`] have associated functions.
+//!  - `match some_int_operand` becomes a `SwitchInt`. Each arm should be `literal => basic_block`
+//!     - The exception is the last arm, which must be `_ => basic_block` and corresponds to the
+//!       otherwise branch.
+//!  - [`Call`] has an associated function as well. The third argument of this function is a normal
+//!    function call expresion, for example `my_other_function(a, 5)`.
 //!
 
 #![unstable(
 pub struct BasicBlock;
 
 macro_rules! define {
-    ($name:literal, $($sig:tt)*) => {
+    ($name:literal, $( #[ $meta:meta ] )* fn $($sig:tt)*) => {
         #[rustc_diagnostic_item = $name]
-        pub $($sig)* { panic!() }
+        $( #[ $meta ] )*
+        pub fn $($sig)* { panic!() }
     }
 }
 
 define!("mir_return", fn Return() -> BasicBlock);
 define!("mir_goto", fn Goto(destination: BasicBlock) -> BasicBlock);
+define!("mir_unreachable", fn Unreachable() -> BasicBlock);
+define!("mir_drop", fn Drop<T>(place: T, goto: BasicBlock));
+define!("mir_drop_and_replace", fn DropAndReplace<T>(place: T, value: T, goto: BasicBlock));
+define!("mir_call", fn Call<T>(place: T, goto: BasicBlock, call: T));
 define!("mir_retag", fn Retag<T>(place: T));
 define!("mir_retag_raw", fn RetagRaw<T>(place: T));
 define!("mir_move", fn Move<T>(place: T) -> T);
 define!("mir_static", fn Static<T>(s: T) -> &'static T);
 define!("mir_static_mut", fn StaticMut<T>(s: T) -> *mut T);
+define!(
+    "mir_discriminant",
+    /// Gets the discriminant of a place.
+    fn Discriminant<T>(place: T) -> <T as ::core::marker::DiscriminantKind>::Discriminant
+);
+define!("mir_set_discriminant", fn SetDiscriminant<T>(place: T, index: u32));
+define!(
+    "mir_field",
+    /// Access the field with the given index of some place.
+    ///
+    /// This only makes sense to use in conjunction with [`Variant`]. If the type you are looking to
+    /// access the field of does not have variants, you can use normal field projection syntax.
+    ///
+    /// There is no proper way to do a place projection to a variant in Rust, and so these two
+    /// functions are a workaround. You can access a field of a variant via `Field(Variant(place,
+    /// var_idx), field_idx)`, where `var_idx` and `field_idx` are appropriate literals. Some
+    /// caveats:
+    ///
+    ///  - The return type of `Variant` is always `()`. Don't worry about that, the correct MIR will
+    ///    still be generated.
+    ///  - In some situations, the return type of `Field` cannot be inferred. You may need to
+    ///    annotate it on the function in these cases.
+    ///  - Since `Field` is a function call which is not a place expression, using this on the left
+    ///    hand side of an expression is rejected by the compiler. [`place!`] is a macro provided to
+    ///    work around that issue. Wrap the left hand side of an assignment in the macro to convince
+    ///    the compiler that it's ok.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// #![feature(custom_mir, core_intrinsics)]
+    ///
+    /// extern crate core;
+    /// use core::intrinsics::mir::*;
+    ///
+    /// #[custom_mir(dialect = "built")]
+    /// fn unwrap_deref(opt: Option<&i32>) -> i32 {
+    ///     mir!({
+    ///         RET = *Field::<&i32>(Variant(opt, 1), 0);
+    ///         Return()
+    ///     })
+    /// }
+    ///
+    /// #[custom_mir(dialect = "built")]
+    /// fn set(opt: &mut Option<i32>) {
+    ///     mir!({
+    ///         place!(Field(Variant(*opt, 1), 0)) = 5;
+    ///         Return()
+    ///     })
+    /// }
+    /// ```
+    fn Field<F>(place: (), field: u32) -> F
+);
+define!(
+    "mir_variant",
+    /// Adds a variant projection with the given index to the place.
+    ///
+    /// See [`Field`] for documentation.
+    fn Variant<T>(place: T, index: u32) -> ()
+);
+define!(
+    "mir_make_place",
+    #[doc(hidden)]
+    fn __internal_make_place<T>(place: T) -> *mut T
+);
 
-/// Convenience macro for generating custom MIR.
+/// Macro for generating custom MIR.
 ///
 /// See the module documentation for syntax details. This macro is not magic - it only transforms
 /// your MIR into something that is easier to parse in the compiler.
@@ -139,6 +385,13 @@ macro_rules! define {
     }}
 }
 
+/// Helper macro that allows you to treat a value expression like a place expression.
+///
+/// See the documentation on [`Variant`] for why this is necessary and how to use it.
+pub macro place($e:expr) {
+    (*::core::intrinsics::mir::__internal_make_place($e))
+}
+
 /// Helper macro that extracts the `let` declarations out of a bunch of statements.
 ///
 /// This macro is written using the "statement muncher" strategy. Each invocation parses the first
index 84d83ee39699fe1841149b00e0c929389a1a7bc3..e31669b3924202db05ee2cceb8289ceae1075105 100644 (file)
 /// [`sum()`]: Iterator::sum
 /// [`FromIterator`]: iter::FromIterator
 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
+#[rustc_on_unimplemented(
+    message = "a value of type `{Self}` cannot be made by summing an iterator over elements of type `{A}`",
+    label = "value of type `{Self}` cannot be made by summing a `std::iter::Iterator<Item={A}>`"
+)]
 pub trait Sum<A = Self>: Sized {
     /// Method which takes an iterator and generates `Self` from the elements by
     /// "summing up" the items.
@@ -27,6 +31,10 @@ pub trait Sum<A = Self>: Sized {
 /// [`product()`]: Iterator::product
 /// [`FromIterator`]: iter::FromIterator
 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
+#[rustc_on_unimplemented(
+    message = "a value of type `{Self}` cannot be made by multiplying all elements of type `{A}` from an iterator",
+    label = "value of type `{Self}` cannot be made by multiplying all elements from a `std::iter::Iterator<Item={A}>`"
+)]
 pub trait Product<A = Self>: Sized {
     /// Method which takes an iterator and generates `Self` from the elements by
     /// multiplying the items.
index 83c7e8977e9f3e22e842bef6a0581afe7be174a9..bac836292f8fa836c163823280463423b12b6700 100644 (file)
@@ -1829,6 +1829,7 @@ fn by_ref(&mut self) -> &mut Self
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead"]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "iterator_collect_fn")]
     fn collect<B: FromIterator<Self::Item>>(self) -> B
     where
         Self: Sized,
@@ -2733,7 +2734,7 @@ fn check<T, B>(mut f: impl FnMut(T) -> Option<B>) -> impl FnMut((), T) -> Contro
     /// the first true result or the first error.
     ///
     /// The return type of this method depends on the return type of the closure.
-    /// If you return `Result<bool, E>` from the closure, you'll get a `Result<Option<Self::Item>; E>`.
+    /// If you return `Result<bool, E>` from the closure, you'll get a `Result<Option<Self::Item>, E>`.
     /// If you return `Option<bool>` from the closure, you'll get an `Option<Option<Self::Item>>`.
     ///
     /// # Examples
index b2328b001de904368ad0adb8ef7ee8a98a080d67..ac7f579ebb5aa8bc8cd059b40d8dfab09de89dfb 100644 (file)
@@ -4,12 +4,14 @@
 
 use crate::ascii;
 use crate::convert::TryInto;
-use crate::error::Error;
 use crate::intrinsics;
 use crate::mem;
 use crate::ops::{Add, Mul, Sub};
 use crate::str::FromStr;
 
+#[cfg(not(no_fp_fmt_parse))]
+use crate::error::Error;
+
 // Used because the `?` operator is not allowed in a const context.
 macro_rules! try_opt {
     ($e:expr) => {
index a5e5b13b33674ca1eaad2375281e9a74dfe5e048..eb2a92f4644d11e8bc903cceb47ac527afbde4eb 100644 (file)
 //! should have some resemblance to multiplication (and share expected
 //! properties like associativity).
 //!
-//! Note that the `&&` and `||` operators short-circuit, i.e., they only
-//! evaluate their second operand if it contributes to the result. Since this
-//! behavior is not enforceable by traits, `&&` and `||` are not supported as
-//! overloadable operators.
+//! Note that the `&&` and `||` operators are currently not supported for
+//! overloading. Due to their short circuiting nature, they require a different
+//! design from traits for other operators like [`BitAnd`]. Designs for them are
+//! under discussion.
 //!
 //! Many of the operators take their operands by value. In non-generic
 //! contexts involving built-in types, this is usually not a problem.
index 505d964e518d7d7ffc1fd9fc66d673588a715429..39462dca4ff3ea46b1f7c8ecf7216eb9b34b624a 100644 (file)
 //! }
 //! ```
 //!
+//! # The question mark operator, `?`
+//!
+//! Similar to the [`Result`] type, when writing code that calls many functions that return the
+//! [`Option`] type, handling `Some`/`None` can be tedious. The question mark
+//! operator, [`?`], hides some of the boilerplate of propagating values
+//! up the call stack.
+//!
+//! It replaces this:
+//!
+//! ```
+//! # #![allow(dead_code)]
+//! fn add_last_numbers(stack: &mut Vec<i32>) -> Option<i32> {
+//!     let a = stack.pop();
+//!     let b = stack.pop();
+//!
+//!     match (a, b) {
+//!         (Some(x), Some(y)) => Some(x + y),
+//!         _ => None,
+//!     }
+//! }
+//!
+//! ```
+//!
+//! With this:
+//!
+//! ```
+//! # #![allow(dead_code)]
+//! fn add_last_numbers(stack: &mut Vec<i32>) -> Option<i32> {
+//!     Some(stack.pop()? + stack.pop()?)
+//! }
+//! ```
+//!
+//! *It's much nicer!*
+//!
+//! Ending the expression with [`?`] will result in the [`Some`]'s unwrapped value, unless the
+//! result is [`None`], in which case [`None`] is returned early from the enclosing function.
+//!
+//! [`?`] can be used in functions that return [`Option`] because of the
+//! early return of [`None`] that it provides.
+//!
+//! [`?`]: crate::ops::Try
+//! [`Some`]: Some
+//! [`None`]: None
+//!
 //! # Representation
 //!
 //! Rust guarantees to optimize the following types `T` such that
index 76603e1018d19409951e6603d8c8e12fff6ed591..b6373beac5f76e651d2572ea12333b9c538abe79 100644 (file)
@@ -45,7 +45,7 @@ pub const fn is_null(self) -> bool {
     /// Casts to a pointer of another type.
     #[stable(feature = "ptr_cast", since = "1.38.0")]
     #[rustc_const_stable(feature = "const_ptr_cast", since = "1.38.0")]
-    #[inline]
+    #[inline(always)]
     pub const fn cast<U>(self) -> *const U {
         self as _
     }
@@ -95,6 +95,7 @@ pub const fn with_metadata_of<U>(self, meta: *const U) -> *const U
     /// refactored.
     #[stable(feature = "ptr_const_cast", since = "1.65.0")]
     #[rustc_const_stable(feature = "ptr_const_cast", since = "1.65.0")]
+    #[inline(always)]
     pub const fn cast_mut(self) -> *mut T {
         self as _
     }
@@ -126,6 +127,7 @@ pub const fn cast_mut(self) -> *mut T {
         note = "replaced by the `exposed_addr` method, or update your code \
             to follow the strict provenance rules using its APIs"
     )]
+    #[inline(always)]
     pub fn to_bits(self) -> usize
     where
         T: Sized,
@@ -155,6 +157,7 @@ pub fn to_bits(self) -> usize
             your code to follow the strict provenance rules using its APIs"
     )]
     #[allow(fuzzy_provenance_casts)] // this is an unstable and semi-deprecated cast function
+    #[inline(always)]
     pub fn from_bits(bits: usize) -> Self
     where
         T: Sized,
@@ -186,7 +189,7 @@ pub fn from_bits(bits: usize) -> Self
     /// might change in the future (including possibly weakening this so it becomes wholly
     /// equivalent to `self as usize`). See the [module documentation][crate::ptr] for details.
     #[must_use]
-    #[inline]
+    #[inline(always)]
     #[unstable(feature = "strict_provenance", issue = "95228")]
     pub fn addr(self) -> usize
     where
@@ -223,7 +226,7 @@ pub fn addr(self) -> usize
     ///
     /// [`from_exposed_addr`]: from_exposed_addr
     #[must_use]
-    #[inline]
+    #[inline(always)]
     #[unstable(feature = "strict_provenance", issue = "95228")]
     pub fn expose_addr(self) -> usize
     where
@@ -1005,7 +1008,7 @@ pub const fn guaranteed_ne(self, other: *const T) -> Option<bool>
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
     #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
-    #[inline]
+    #[inline(always)]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn sub(self, count: usize) -> Self
     where
@@ -1170,7 +1173,7 @@ pub const fn wrapping_byte_add(self, count: usize) -> Self {
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
     #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
-    #[inline]
+    #[inline(always)]
     pub const fn wrapping_sub(self, count: usize) -> Self
     where
         T: Sized,
index 89b11637ecabefc0405209cfe16c11b6accc1912..48b2e88da28413d0e96c45f7ed9f9e974f046076 100644 (file)
@@ -613,7 +613,7 @@ pub const fn invalid_mut<T>(addr: usize) -> *mut T {
 /// This API and its claimed semantics are part of the Strict Provenance experiment, see the
 /// [module documentation][crate::ptr] for details.
 #[must_use]
-#[inline]
+#[inline(always)]
 #[unstable(feature = "strict_provenance", issue = "95228")]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 #[allow(fuzzy_provenance_casts)] // this *is* the strict provenance API one should use instead
@@ -651,7 +651,7 @@ pub fn from_exposed_addr<T>(addr: usize) -> *const T
 /// This API and its claimed semantics are part of the Strict Provenance experiment, see the
 /// [module documentation][crate::ptr] for details.
 #[must_use]
-#[inline]
+#[inline(always)]
 #[unstable(feature = "strict_provenance", issue = "95228")]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 #[allow(fuzzy_provenance_casts)] // this *is* the strict provenance API one should use instead
@@ -1769,7 +1769,7 @@ pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
 /// (which is what the `PartialEq for &T` implementation does).
 ///
 /// When comparing wide pointers, both the address and the metadata are tested for equality.
-/// However, note that comparing trait object pointers (`*const dyn Trait`) is unrealiable: pointers
+/// However, note that comparing trait object pointers (`*const dyn Trait`) is unreliable: pointers
 /// to values of the same underlying type can compare inequal (because vtables are duplicated in
 /// multiple codegen units), and pointers to values of *different* underlying type can compare equal
 /// (since identical vtables can be deduplicated within a codegen unit).
@@ -1801,7 +1801,7 @@ pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
 /// assert!(!std::ptr::eq(&a[0..2], &a[1..3]));
 /// ```
 #[stable(feature = "ptr_eq", since = "1.17.0")]
-#[inline]
+#[inline(always)]
 pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {
     a == b
 }
index b03cad18e4aedf81e89d19f8edd1329d0f5b4097..7a5d9a7059459986cda025f9caa317e0ae951d1b 100644 (file)
@@ -100,6 +100,7 @@ pub const fn with_metadata_of<U>(self, meta: *const U) -> *mut U
     /// [`cast_mut`]: #method.cast_mut
     #[stable(feature = "ptr_const_cast", since = "1.65.0")]
     #[rustc_const_stable(feature = "ptr_const_cast", since = "1.65.0")]
+    #[inline(always)]
     pub const fn cast_const(self) -> *const T {
         self as _
     }
@@ -132,6 +133,7 @@ pub const fn cast_const(self) -> *const T {
         note = "replaced by the `exposed_addr` method, or update your code \
             to follow the strict provenance rules using its APIs"
     )]
+    #[inline(always)]
     pub fn to_bits(self) -> usize
     where
         T: Sized,
@@ -161,6 +163,7 @@ pub fn to_bits(self) -> usize
             update your code to follow the strict provenance rules using its APIs"
     )]
     #[allow(fuzzy_provenance_casts)] // this is an unstable and semi-deprecated cast function
+    #[inline(always)]
     pub fn from_bits(bits: usize) -> Self
     where
         T: Sized,
@@ -192,7 +195,7 @@ pub fn from_bits(bits: usize) -> Self
     /// might change in the future (including possibly weakening this so it becomes wholly
     /// equivalent to `self as usize`). See the [module documentation][crate::ptr] for details.
     #[must_use]
-    #[inline]
+    #[inline(always)]
     #[unstable(feature = "strict_provenance", issue = "95228")]
     pub fn addr(self) -> usize
     where
@@ -229,7 +232,7 @@ pub fn addr(self) -> usize
     ///
     /// [`from_exposed_addr_mut`]: from_exposed_addr_mut
     #[must_use]
-    #[inline]
+    #[inline(always)]
     #[unstable(feature = "strict_provenance", issue = "95228")]
     pub fn expose_addr(self) -> usize
     where
@@ -1107,7 +1110,7 @@ pub const fn guaranteed_ne(self, other: *mut T) -> Option<bool>
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
     #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
-    #[inline]
+    #[inline(always)]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn sub(self, count: usize) -> Self
     where
@@ -1272,7 +1275,7 @@ pub const fn wrapping_byte_add(self, count: usize) -> Self {
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
     #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
-    #[inline]
+    #[inline(always)]
     pub const fn wrapping_sub(self, count: usize) -> Self
     where
         T: Sized,
index c18264d13ebac78993f8cbc9ab9090ed521fe0be..c4348169c78c7e391e975f6d67cd9415264e8aa9 100644 (file)
@@ -330,7 +330,7 @@ pub fn map_addr(self, f: impl FnOnce(NonZeroUsize) -> NonZeroUsize) -> Self
     #[stable(feature = "nonnull", since = "1.25.0")]
     #[rustc_const_stable(feature = "const_nonnull_as_ptr", since = "1.32.0")]
     #[must_use]
-    #[inline]
+    #[inline(always)]
     pub const fn as_ptr(self) -> *mut T {
         self.pointer as *mut T
     }
@@ -378,7 +378,7 @@ pub const fn as_ptr(self) -> *mut T {
     #[stable(feature = "nonnull", since = "1.25.0")]
     #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
     #[must_use]
-    #[inline]
+    #[inline(always)]
     pub const unsafe fn as_ref<'a>(&self) -> &'a T {
         // SAFETY: the caller must guarantee that `self` meets all the
         // requirements for a reference.
@@ -429,7 +429,7 @@ pub const fn as_ptr(self) -> *mut T {
     #[stable(feature = "nonnull", since = "1.25.0")]
     #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
     #[must_use]
-    #[inline]
+    #[inline(always)]
     pub const unsafe fn as_mut<'a>(&mut self) -> &'a mut T {
         // SAFETY: the caller must guarantee that `self` meets all the
         // requirements for a mutable reference.
@@ -703,7 +703,7 @@ pub const fn as_mut_ptr(self) -> *mut T {
 #[stable(feature = "nonnull", since = "1.25.0")]
 #[rustc_const_unstable(feature = "const_clone", issue = "91805")]
 impl<T: ?Sized> const Clone for NonNull<T> {
-    #[inline]
+    #[inline(always)]
     fn clone(&self) -> Self {
         *self
     }
index 3f33c5fd6ca36fd7d78d04536cfe47c49cf9e0a1..f00c40f35d584765176c7c46a708d993bb240326 100644 (file)
 //!
 //! *It's much nicer!*
 //!
-//! Ending the expression with [`?`] will result in the unwrapped
-//! success ([`Ok`]) value, unless the result is [`Err`], in which case
-//! [`Err`] is returned early from the enclosing function.
+//! Ending the expression with [`?`] will result in the [`Ok`]'s unwrapped value, unless the result
+//! is [`Err`], in which case [`Err`] is returned early from the enclosing function.
 //!
-//! [`?`] can only be used in functions that return [`Result`] because of the
+//! [`?`] can be used in functions that return [`Result`] because of the
 //! early return of [`Err`] that it provides.
 //!
 //! [`expect`]: Result::expect
index 04486ed2d14e31a3c9c977ec9978e692b98b2a52..2c469f61854f3cb2acff0185738b73b8d7228bc6 100644 (file)
@@ -465,7 +465,7 @@ pub const fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output>
     /// [`as_mut_ptr`]: slice::as_mut_ptr
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "const_slice_as_ptr", since = "1.32.0")]
-    #[inline]
+    #[inline(always)]
     #[must_use]
     pub const fn as_ptr(&self) -> *const T {
         self as *const [T] as *const T
@@ -495,7 +495,7 @@ pub const fn as_ptr(&self) -> *const T {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
     #[rustc_allow_const_fn_unstable(const_mut_refs)]
-    #[inline]
+    #[inline(always)]
     #[must_use]
     pub const fn as_mut_ptr(&mut self) -> *mut T {
         self as *mut [T] as *mut T
@@ -1002,6 +1002,17 @@ pub fn chunks_exact_mut(&mut self, chunk_size: usize) -> ChunksExactMut<'_, T> {
     /// assert_eq!(chunks, &[['l', 'o'], ['r', 'e']]);
     /// assert_eq!(remainder, &['m']);
     /// ```
+    ///
+    /// If you expect the slice to be an exact multiple, you can combine
+    /// `let`-`else` with an empty slice pattern:
+    /// ```
+    /// #![feature(slice_as_chunks)]
+    /// let slice = ['R', 'u', 's', 't'];
+    /// let (chunks, []) = slice.as_chunks::<2>() else {
+    ///     panic!("slice didn't have even length")
+    /// };
+    /// assert_eq!(chunks, &[['R', 'u'], ['s', 't']]);
+    /// ```
     #[unstable(feature = "slice_as_chunks", issue = "74985")]
     #[inline]
     #[must_use]
@@ -3468,10 +3479,11 @@ fn gcd(a: usize, b: usize) -> usize {
     /// maintained.
     ///
     /// This method splits the slice into three distinct slices: prefix, correctly aligned middle
-    /// slice of a new type, and the suffix slice. The method may make the middle slice the greatest
-    /// length possible for a given type and input slice, but only your algorithm's performance
-    /// should depend on that, not its correctness. It is permissible for all of the input data to
-    /// be returned as the prefix or suffix slice.
+    /// slice of a new type, and the suffix slice. How exactly the slice is split up is not
+    /// specified; the middle part may be smaller than necessary. However, if this fails to return a
+    /// maximal middle part, that is because code is running in a context where performance does not
+    /// matter, such as a sanitizer attempting to find alignment bugs. Regular code running
+    /// in a default (debug or release) execution *will* return a maximal middle part.
     ///
     /// This method has no purpose when either input element `T` or output element `U` are
     /// zero-sized and will return the original slice without splitting anything.
@@ -3529,10 +3541,11 @@ pub unsafe fn align_to<U>(&self) -> (&[T], &[U], &[T]) {
     /// types is maintained.
     ///
     /// This method splits the slice into three distinct slices: prefix, correctly aligned middle
-    /// slice of a new type, and the suffix slice. The method may make the middle slice the greatest
-    /// length possible for a given type and input slice, but only your algorithm's performance
-    /// should depend on that, not its correctness. It is permissible for all of the input data to
-    /// be returned as the prefix or suffix slice.
+    /// slice of a new type, and the suffix slice. How exactly the slice is split up is not
+    /// specified; the middle part may be smaller than necessary. However, if this fails to return a
+    /// maximal middle part, that is because code is running in a context where performance does not
+    /// matter, such as a sanitizer attempting to find alignment bugs. Regular code running
+    /// in a default (debug or release) execution *will* return a maximal middle part.
     ///
     /// This method has no purpose when either input element `T` or output element `U` are
     /// zero-sized and will return the original slice without splitting anything.
@@ -3793,7 +3806,7 @@ pub fn is_sorted_by_key<'a, F, K>(&'a self, f: F) -> bool
     /// The slice is assumed to be partitioned according to the given predicate.
     /// This means that all elements for which the predicate returns true are at the start of the slice
     /// and all elements for which the predicate returns false are at the end.
-    /// For example, [7, 15, 3, 5, 4, 12, 6] is a partitioned under the predicate x % 2 != 0
+    /// For example, `[7, 15, 3, 5, 4, 12, 6]` is partitioned under the predicate `x % 2 != 0`
     /// (all odd numbers are at the start, all even at the end).
     ///
     /// If this slice is not partitioned, the returned result is unspecified and meaningless,
index c0167388713388d7f1e4adbd00c54962eb5a7958..45fd2caae52f4f27efe70ac4054c9660fc3bec99 100644 (file)
@@ -396,7 +396,7 @@ pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "rustc_str_as_ptr", since = "1.32.0")]
     #[must_use]
-    #[inline]
+    #[inline(always)]
     pub const fn as_ptr(&self) -> *const u8 {
         self as *const str as *const u8
     }
@@ -411,7 +411,7 @@ pub const fn as_ptr(&self) -> *const u8 {
     /// modified in a way that it remains valid UTF-8.
     #[stable(feature = "str_as_mut_ptr", since = "1.36.0")]
     #[must_use]
-    #[inline]
+    #[inline(always)]
     pub fn as_mut_ptr(&mut self) -> *mut u8 {
         self as *mut str as *mut u8
     }
index c65c275000ce82bdf56d7e103a9b08aa0e9604d3..301ad41c96634407ff2c6e3791542f69a7743bab 100644 (file)
@@ -138,7 +138,7 @@ pub const fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> {
         unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner) }
     }
 
-    /// Build a _mutable_ references to an `Exclusive<T>` from
+    /// Build a _mutable_ reference to an `Exclusive<T>` from
     /// a _mutable_ reference to a `T`. This allows you to skip
     /// building an `Exclusive` with [`Exclusive::new`].
     #[unstable(feature = "exclusive_wrapper", issue = "98407")]
@@ -149,7 +149,7 @@ pub const fn from_mut(r: &'_ mut T) -> &'_ mut Exclusive<T> {
         unsafe { &mut *(r as *mut T as *mut Exclusive<T>) }
     }
 
-    /// Build a _pinned mutable_ references to an `Exclusive<T>` from
+    /// Build a _pinned mutable_ reference to an `Exclusive<T>` from
     /// a _pinned mutable_ reference to a `T`. This allows you to skip
     /// building an `Exclusive` with [`Exclusive::new`].
     #[unstable(feature = "exclusive_wrapper", issue = "98407")]
index 0d3fc2c5244e03fe20af3b33a2814f4c020640db..f0e4f5d8a8013d613098c4ecd0a2dfee921ac24a 100644 (file)
@@ -1493,7 +1493,7 @@ pub mod tracked_env {
     use std::ffi::OsStr;
 
     /// Retrieve an environment variable and add it to build dependency info.
-    /// Build system executing the compiler will know that the variable was accessed during
+    /// The build system executing the compiler will know that the variable was accessed during
     /// compilation, and will be able to rerun the build when the value of that variable changes.
     /// Besides the dependency tracking this function should be equivalent to `env::var` from the
     /// standard library, except that the argument must be UTF-8.
index a7aefc26b97c7e0ac8008303e3e92b674a55e2cc..29b5a468bf4c502d582e0d369067b8c50af5eaea 100644 (file)
@@ -16,7 +16,7 @@ panic_unwind = { path = "../panic_unwind", optional = true }
 panic_abort = { path = "../panic_abort" }
 core = { path = "../core" }
 libc = { version = "0.2.138", default-features = false, features = ['rustc-dep-of-std'] }
-compiler_builtins = { version = "0.1.82" }
+compiler_builtins = { version = "0.1.85" }
 profiler_builtins = { path = "../profiler_builtins", optional = true }
 unwind = { path = "../unwind" }
 hashbrown = { version = "0.12", default-features = false, features = ['rustc-dep-of-std'] }
index 6eb7cbea6269d7c92531fe00f1cb6a7edccb7f26..183f9ab3b08f632a2a945bd905be038571a125a9 100644 (file)
@@ -570,6 +570,13 @@ fn description(&self) -> &str {
 ///
 /// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-getuserprofiledirectorya
 ///
+/// # Deprecation
+///
+/// This function is deprecated because the behaviour on Windows is not correct.
+/// The 'HOME' environment variable is not standard on Windows, and may not produce
+/// desired results; for instance, under Cygwin or Mingw it will return `/home/you`
+/// when it should return `C:\Users\you`.
+///
 /// # Examples
 ///
 /// ```
@@ -582,7 +589,7 @@ fn description(&self) -> &str {
 /// ```
 #[deprecated(
     since = "1.29.0",
-    note = "This function's behavior is unexpected and probably not what you want. \
+    note = "This function's behavior may be unexpected on Windows. \
             Consider using a crate from crates.io instead."
 )]
 #[must_use]
index b8959316de170e568de3fc7a366ed478158855dc..b385ebde439794e9fc1b3fa0e526aec447a15031 100644 (file)
@@ -1551,3 +1551,47 @@ fn hiberfil_sys() {
     fs::metadata(hiberfil).unwrap();
     assert_eq!(true, hiberfil.exists());
 }
+
+/// Test that two different ways of obtaining the FileType give the same result.
+/// Cf. https://github.com/rust-lang/rust/issues/104900
+#[test]
+fn test_eq_direntry_metadata() {
+    let tmpdir = tmpdir();
+    let file_path = tmpdir.join("file");
+    File::create(file_path).unwrap();
+    for e in fs::read_dir(tmpdir.path()).unwrap() {
+        let e = e.unwrap();
+        let p = e.path();
+        let ft1 = e.file_type().unwrap();
+        let ft2 = p.metadata().unwrap().file_type();
+        assert_eq!(ft1, ft2);
+    }
+}
+
+/// Regression test for https://github.com/rust-lang/rust/issues/50619.
+#[test]
+#[cfg(target_os = "linux")]
+fn test_read_dir_infinite_loop() {
+    use crate::io::ErrorKind;
+    use crate::process::Command;
+
+    // Create a zombie child process
+    let Ok(mut child) = Command::new("echo").spawn() else { return };
+
+    // Make sure the process is (un)dead
+    match child.kill() {
+        // InvalidInput means the child already exited
+        Err(e) if e.kind() != ErrorKind::InvalidInput => return,
+        _ => {}
+    }
+
+    // open() on this path will succeed, but readdir() will fail
+    let id = child.id();
+    let path = format!("/proc/{id}/net");
+
+    // Skip the test if we can't open the directory in the first place
+    let Ok(dir) = fs::read_dir(path) else { return };
+
+    // Check for duplicate errors
+    assert!(dir.filter(|e| e.is_err()).take(2).count() < 2);
+}
index 6c957c2fa90eb517088f085687474dbc3b6d702a..a835b855dddf47e81095ad0c349b7f0502197c62 100644 (file)
@@ -1748,6 +1748,14 @@ fn deref(&self) -> &Path {
     }
 }
 
+#[stable(feature = "path_buf_deref_mut", since = "CURRENT_RUSTC_VERSION")]
+impl ops::DerefMut for PathBuf {
+    #[inline]
+    fn deref_mut(&mut self) -> &mut Path {
+        Path::from_inner_mut(&mut self.inner)
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Borrow<Path> for PathBuf {
     #[inline]
@@ -2000,6 +2008,12 @@ pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &Path {
         unsafe { &*(s.as_ref() as *const OsStr as *const Path) }
     }
 
+    fn from_inner_mut(inner: &mut OsStr) -> &mut Path {
+        // SAFETY: Path is just a wrapper around OsStr,
+        // therefore converting &mut OsStr to &mut Path is safe.
+        unsafe { &mut *(inner as *mut OsStr as *mut Path) }
+    }
+
     /// Yields the underlying [`OsStr`] slice.
     ///
     /// # Examples
index 400d25beb26f3d521387b5933e8a30ab6d1507b2..17aff342c1599455b2160b43b456bdb8f752246e 100644 (file)
@@ -362,6 +362,10 @@ fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
     fn is_read_vectored(&self) -> bool {
         self.inner.is_read_vectored()
     }
+
+    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
+        self.inner.read_to_end(buf)
+    }
 }
 
 impl AsInner<AnonPipe> for ChildStdout {
@@ -907,10 +911,8 @@ pub fn spawn(&mut self) -> io::Result<Child> {
     /// ```
     #[stable(feature = "process", since = "1.0.0")]
     pub fn output(&mut self) -> io::Result<Output> {
-        self.inner
-            .spawn(imp::Stdio::MakePipe, false)
-            .map(Child::from_inner)
-            .and_then(|p| p.wait_with_output())
+        let (status, stdout, stderr) = self.inner.output()?;
+        Ok(Output { status: ExitStatus(status), stdout, stderr })
     }
 
     /// Executes a command as a child process, waiting for it to finish and
index f70aa434e48348b3b5289a52cdbc632d2f625b2e..7a47cc6696a34908a0bea6f832dbf14e8b68087d 100644 (file)
@@ -71,7 +71,7 @@ pub unsafe fn wait(&self, mutex: &Mutex) {
             }
         }
 
-        unsafe { mutex.lock() };
+        mutex.lock();
     }
 
     pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
@@ -109,7 +109,7 @@ pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
         // we woke up because of `notify_*`.
         let success = self.waiters.with_locked(|waiters| unsafe { !waiters.remove(waiter) });
 
-        unsafe { mutex.lock() };
+        mutex.lock();
         success
     }
 }
index f2eed8e771c40ece6fd04b090ae918c3843f694b..1f6cc41947602be1a7f81d443972de6e26b78d69 100644 (file)
@@ -72,7 +72,7 @@ fn drop(&mut self) {
 impl<'a> MutexGuard<'a> {
     #[inline]
     pub(super) fn lock(x: &'a Mutex) -> Self {
-        unsafe { x.lock() };
+        x.lock();
         Self(x)
     }
 }
index d28f57f33be20566de33bd7a79389a85067105a6..c2b3668087225cdc884a28d3a15660974c16b98d 100644 (file)
     ffi::CStr,
     hint, io,
     mem::ManuallyDrop,
+    ptr::NonNull,
     sync::atomic::{AtomicUsize, Ordering},
     sys::thread_local_dtor::run_dtors,
     time::Duration,
 };
 
 pub struct Thread {
-    inner: ManuallyDrop<Box<ThreadInner>>,
+    p_inner: NonNull<ThreadInner>,
 
     /// The ID of the underlying task.
     task: abi::ID,
 }
 
+// Safety: There's nothing in `Thread` that ties it to the original creator. It
+//         can be dropped by any threads.
+unsafe impl Send for Thread {}
+// Safety: `Thread` provides no methods that take `&self`.
+unsafe impl Sync for Thread {}
+
 /// State data shared between a parent thread and child thread. It's dropped on
 /// a transition to one of the final states.
 struct ThreadInner {
@@ -90,8 +97,9 @@ pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
         });
 
         unsafe extern "C" fn trampoline(exinf: isize) {
+            let p_inner: *mut ThreadInner = crate::ptr::from_exposed_addr_mut(exinf as usize);
             // Safety: `ThreadInner` is alive at this point
-            let inner = unsafe { &*(exinf as *const ThreadInner) };
+            let inner = unsafe { &*p_inner };
 
             // Safety: Since `trampoline` is called only once for each
             //         `ThreadInner` and only `trampoline` touches `start`,
@@ -119,13 +127,13 @@ pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
                     // No one will ever join, so we'll ask the collector task to
                     // delete the task.
 
-                    // In this case, `inner`'s ownership has been moved to us,
-                    // And we are responsible for dropping it. The acquire
+                    // In this case, `*p_inner`'s ownership has been moved to
+                    // us, and we are responsible for dropping it. The acquire
                     // ordering is not necessary because the parent thread made
                     // no memory access needing synchronization since the call
                     // to `acre_tsk`.
                     // Safety: See above.
-                    let _ = unsafe { Box::from_raw(inner as *const _ as *mut ThreadInner) };
+                    let _ = unsafe { Box::from_raw(p_inner) };
 
                     // Safety: There are no pinned references to the stack
                     unsafe { terminate_and_delete_current_task() };
@@ -162,13 +170,14 @@ pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
             }
         }
 
-        let inner_ptr = (&*inner) as *const ThreadInner;
+        // Safety: `Box::into_raw` returns a non-null pointer
+        let p_inner = unsafe { NonNull::new_unchecked(Box::into_raw(inner)) };
 
         let new_task = ItronError::err_if_negative(unsafe {
             abi::acre_tsk(&abi::T_CTSK {
                 // Activate this task immediately
                 tskatr: abi::TA_ACT,
-                exinf: inner_ptr as abi::EXINF,
+                exinf: p_inner.as_ptr().expose_addr() as abi::EXINF,
                 // The entry point
                 task: Some(trampoline),
                 // Inherit the calling task's base priority
@@ -180,7 +189,7 @@ pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
         })
         .map_err(|e| e.as_io_error())?;
 
-        Ok(Self { inner: ManuallyDrop::new(inner), task: new_task })
+        Ok(Self { p_inner, task: new_task })
     }
 
     pub fn yield_now() {
@@ -197,8 +206,9 @@ pub fn sleep(dur: Duration) {
         }
     }
 
-    pub fn join(mut self) {
-        let inner = &*self.inner;
+    pub fn join(self) {
+        // Safety: `ThreadInner` is alive at this point
+        let inner = unsafe { self.p_inner.as_ref() };
         // Get the current task ID. Panicking here would cause a resource leak,
         // so just abort on failure.
         let current_task = task::current_task_id_aborting();
@@ -243,8 +253,8 @@ pub fn join(mut self) {
         unsafe { terminate_and_delete_task(self.task) };
 
         // In either case, we are responsible for dropping `inner`.
-        // Safety: The contents of `self.inner` will not be accessed hereafter
-        let _inner = unsafe { ManuallyDrop::take(&mut self.inner) };
+        // Safety: The contents of `*p_inner` will not be accessed hereafter
+        let _inner = unsafe { Box::from_raw(self.p_inner.as_ptr()) };
 
         // Skip the destructor (because it would attempt to detach the thread)
         crate::mem::forget(self);
@@ -253,13 +263,16 @@ pub fn join(mut self) {
 
 impl Drop for Thread {
     fn drop(&mut self) {
+        // Safety: `ThreadInner` is alive at this point
+        let inner = unsafe { self.p_inner.as_ref() };
+
         // Detach the thread.
-        match self.inner.lifecycle.swap(LIFECYCLE_DETACHED_OR_JOINED, Ordering::Acquire) {
+        match inner.lifecycle.swap(LIFECYCLE_DETACHED_OR_JOINED, Ordering::Acquire) {
             LIFECYCLE_INIT => {
                 // [INIT → DETACHED]
                 // When the time comes, the child will figure out that no
                 // one will ever join it.
-                // The ownership of `self.inner` is moved to the child thread.
+                // The ownership of `*p_inner` is moved to the child thread.
                 // However, the release ordering is not necessary because we
                 // made no memory access needing synchronization since the call
                 // to `acre_tsk`.
@@ -278,10 +291,9 @@ fn drop(&mut self) {
                 //         delete by entering the `FINISHED` state.
                 unsafe { terminate_and_delete_task(self.task) };
 
-                // Wwe are responsible for dropping `inner`.
-                // Safety: The contents of `self.inner` will not be accessed
-                //         hereafter
-                unsafe { ManuallyDrop::drop(&mut self.inner) };
+                // Wwe are responsible for dropping `*p_inner`.
+                // Safety: The contents of `*p_inner` will not be accessed hereafter
+                let _ = unsafe { Box::from_raw(self.p_inner.as_ptr()) };
             }
             _ => unsafe { hint::unreachable_unchecked() },
         }
index 01e4ffe3dfc8a04394145b67726b934d780b58d8..63e070207cd707cca701b47e7db0ca5e05b6b4eb 100644 (file)
@@ -34,6 +34,7 @@
 pub mod stdio;
 pub mod thread;
 pub mod thread_local_key;
+pub mod thread_parker;
 pub mod time;
 
 mod condvar;
index d745a619614041dc7e9eb9335f4f3bb48ee97d50..579f758c6cc339fe10f5eb65192851c5e48bf15c 100644 (file)
@@ -65,39 +65,36 @@ pub(super) fn lock() -> MutexGuard<'static, Vec<Task>> {
 /// execution. The signal is sent once all TLS destructors have finished at
 /// which point no new thread locals should be created.
 pub mod wait_notify {
-    use super::super::waitqueue::{SpinMutex, WaitQueue, WaitVariable};
+    use super::super::thread_parker::Parker;
+    use crate::pin::Pin;
     use crate::sync::Arc;
 
-    pub struct Notifier(Arc<SpinMutex<WaitVariable<bool>>>);
+    pub struct Notifier(Arc<Parker>);
 
     impl Notifier {
         /// Notify the waiter. The waiter is either notified right away (if
         /// currently blocked in `Waiter::wait()`) or later when it calls the
         /// `Waiter::wait()` method.
         pub fn notify(self) {
-            let mut guard = self.0.lock();
-            *guard.lock_var_mut() = true;
-            let _ = WaitQueue::notify_one(guard);
+            Pin::new(&*self.0).unpark()
         }
     }
 
-    pub struct Waiter(Arc<SpinMutex<WaitVariable<bool>>>);
+    pub struct Waiter(Arc<Parker>);
 
     impl Waiter {
         /// Wait for a notification. If `Notifier::notify()` has already been
         /// called, this will return immediately, otherwise the current thread
         /// is blocked until notified.
         pub fn wait(self) {
-            let guard = self.0.lock();
-            if *guard.lock_var() {
-                return;
-            }
-            WaitQueue::wait(guard, || {});
+            // This is not actually `unsafe`, but it uses the `Parker` API,
+            // which needs `unsafe` on some platforms.
+            unsafe { Pin::new(&*self.0).park() }
         }
     }
 
     pub fn new() -> (Notifier, Waiter) {
-        let inner = Arc::new(SpinMutex::new(WaitVariable::new(false)));
+        let inner = Arc::new(Parker::new_internal());
         (Notifier(inner.clone()), Waiter(inner))
     }
 }
diff --git a/library/std/src/sys/sgx/thread_parker.rs b/library/std/src/sys/sgx/thread_parker.rs
new file mode 100644 (file)
index 0000000..1c55bcf
--- /dev/null
@@ -0,0 +1,107 @@
+//! Thread parking based on SGX events.
+
+use super::abi::{thread, usercalls};
+use crate::io::ErrorKind;
+use crate::pin::Pin;
+use crate::ptr::{self, NonNull};
+use crate::sync::atomic::AtomicPtr;
+use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
+use crate::time::Duration;
+use fortanix_sgx_abi::{EV_UNPARK, WAIT_INDEFINITE};
+
+// The TCS structure must be page-aligned (this is checked by EENTER), so these cannot
+// be valid pointers
+const EMPTY: *mut u8 = ptr::invalid_mut(1);
+const NOTIFIED: *mut u8 = ptr::invalid_mut(2);
+
+pub struct Parker {
+    /// The park state. One of EMPTY, NOTIFIED or a TCS address.
+    /// A state change to NOTIFIED must be done with release ordering
+    /// and be observed with acquire ordering so that operations after
+    /// `thread::park` returns will not occur before the unpark message
+    /// was sent.
+    state: AtomicPtr<u8>,
+}
+
+impl Parker {
+    /// Construct the thread parker. The UNIX parker implementation
+    /// requires this to happen in-place.
+    pub unsafe fn new(parker: *mut Parker) {
+        unsafe { parker.write(Parker::new_internal()) }
+    }
+
+    pub(super) fn new_internal() -> Parker {
+        Parker { state: AtomicPtr::new(EMPTY) }
+    }
+
+    // This implementation doesn't require `unsafe` and `Pin`, but other implementations do.
+    pub unsafe fn park(self: Pin<&Self>) {
+        if self.state.load(Acquire) != NOTIFIED {
+            let mut prev = EMPTY;
+            loop {
+                // Guard against changing TCS addresses by always setting the state to
+                // the current value.
+                let tcs = thread::current().as_ptr();
+                if self.state.compare_exchange(prev, tcs, Relaxed, Acquire).is_ok() {
+                    let event = usercalls::wait(EV_UNPARK, WAIT_INDEFINITE).unwrap();
+                    assert!(event & EV_UNPARK == EV_UNPARK);
+                    prev = tcs;
+                } else {
+                    // The state was definitely changed by another thread at this point.
+                    // The only time this occurs is when the state is changed to NOTIFIED.
+                    // We observed this change with acquire ordering, so we can simply
+                    // change the state to EMPTY with a relaxed store.
+                    break;
+                }
+            }
+        }
+
+        // At this point, the token was definately read with acquire ordering,
+        // so this can be a relaxed store.
+        self.state.store(EMPTY, Relaxed);
+    }
+
+    // This implementation doesn't require `unsafe` and `Pin`, but other implementations do.
+    pub unsafe fn park_timeout(self: Pin<&Self>, dur: Duration) {
+        let timeout = u128::min(dur.as_nanos(), WAIT_INDEFINITE as u128 - 1) as u64;
+        let tcs = thread::current().as_ptr();
+
+        if self.state.load(Acquire) != NOTIFIED {
+            if self.state.compare_exchange(EMPTY, tcs, Relaxed, Acquire).is_ok() {
+                match usercalls::wait(EV_UNPARK, timeout) {
+                    Ok(event) => assert!(event & EV_UNPARK == EV_UNPARK),
+                    Err(e) => {
+                        assert!(matches!(e.kind(), ErrorKind::TimedOut | ErrorKind::WouldBlock))
+                    }
+                }
+
+                // Swap to provide acquire ordering even if the timeout occurred
+                // before the token was set. This situation can result in spurious
+                // wakeups on the next call to `park_timeout`, but it is better to let
+                // those be handled by the user than do some perhaps unnecessary, but
+                // always expensive guarding.
+                self.state.swap(EMPTY, Acquire);
+                return;
+            }
+        }
+
+        // The token was already read with `acquire` ordering, this can be a store.
+        self.state.store(EMPTY, Relaxed);
+    }
+
+    // This implementation doesn't require `Pin`, but other implementations do.
+    pub fn unpark(self: Pin<&Self>) {
+        let state = self.state.swap(NOTIFIED, Release);
+
+        if !matches!(state, EMPTY | NOTIFIED) {
+            // There is a thread waiting, wake it up.
+            let tcs = NonNull::new(state).unwrap();
+            // This will fail if the thread has already terminated or its TCS is destroyed
+            // by the time the signal is sent, but that is fine. If another thread receives
+            // the same TCS, it will receive this notification as a spurious wakeup, but
+            // all users of `wait` should and (internally) do guard against those where
+            // necessary.
+            let _ = usercalls::send(EV_UNPARK, Some(tcs));
+        }
+    }
+}
index 9eb17a10daa287175a8a3005fc96d274bf666741..a862bb7870264e72ece3f8ee5c6bfc2a9ef0992f 100644 (file)
@@ -75,3 +75,7 @@ pub fn as_mut_slice(&mut self) -> &mut [u8] {
         unsafe { slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len) }
     }
 }
+
+pub fn is_terminal<T>(_: &T) -> bool {
+    false
+}
index 4906c62689d4c27671398aafd86862e7832274bb..6135921f0b5a89a6694d7d151130255981423c73 100644 (file)
@@ -1,7 +1,6 @@
 use super::unsupported;
-use crate::convert::TryFrom;
 use crate::error::Error as StdError;
-use crate::ffi::{CStr, CString, OsStr, OsString};
+use crate::ffi::{CStr, OsStr, OsString};
 use crate::fmt;
 use crate::io;
 use crate::os::{
index 37a49f2d78acdb24179d078f4e84b32ed017a573..d5f50d77911fcafe3ef883f4f85cf3d808d3e223 100644 (file)
@@ -243,17 +243,15 @@ struct InnerReadDir {
 
 pub struct ReadDir {
     inner: Arc<InnerReadDir>,
-    #[cfg(not(any(
-        target_os = "android",
-        target_os = "linux",
-        target_os = "solaris",
-        target_os = "illumos",
-        target_os = "fuchsia",
-        target_os = "redox",
-    )))]
     end_of_stream: bool,
 }
 
+impl ReadDir {
+    fn new(inner: InnerReadDir) -> Self {
+        Self { inner: Arc::new(inner), end_of_stream: false }
+    }
+}
+
 struct Dir(*mut libc::DIR);
 
 unsafe impl Send for Dir {}
@@ -332,11 +330,23 @@ pub struct FileTimes {
     modified: Option<SystemTime>,
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(Copy, Clone, Eq, Debug)]
 pub struct FileType {
     mode: mode_t,
 }
 
+impl PartialEq for FileType {
+    fn eq(&self, other: &Self) -> bool {
+        self.masked() == other.masked()
+    }
+}
+
+impl core::hash::Hash for FileType {
+    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
+        self.masked().hash(state);
+    }
+}
+
 #[derive(Debug)]
 pub struct DirBuilder {
     mode: mode_t,
@@ -548,7 +558,11 @@ pub fn is_symlink(&self) -> bool {
     }
 
     pub fn is(&self, mode: mode_t) -> bool {
-        self.mode & libc::S_IFMT == mode
+        self.masked() == mode
+    }
+
+    fn masked(&self) -> mode_t {
+        self.mode & libc::S_IFMT
     }
 }
 
@@ -578,6 +592,10 @@ impl Iterator for ReadDir {
         target_os = "illumos"
     ))]
     fn next(&mut self) -> Option<io::Result<DirEntry>> {
+        if self.end_of_stream {
+            return None;
+        }
+
         unsafe {
             loop {
                 // As of POSIX.1-2017, readdir() is not required to be thread safe; only
@@ -588,8 +606,12 @@ fn next(&mut self) -> Option<io::Result<DirEntry>> {
                 super::os::set_errno(0);
                 let entry_ptr = readdir64(self.inner.dirp.0);
                 if entry_ptr.is_null() {
-                    // null can mean either the end is reached or an error occurred.
-                    // So we had to clear errno beforehand to check for an error now.
+                    // We either encountered an error, or reached the end.  Either way,
+                    // the next call to next() should return None.
+                    self.end_of_stream = true;
+
+                    // To distinguish between errors and end-of-directory, we had to clear
+                    // errno beforehand to check for an error now.
                     return match super::os::errno() {
                         0 => None,
                         e => Some(Err(Error::from_raw_os_error(e))),
@@ -1347,18 +1369,7 @@ pub fn readdir(path: &Path) -> io::Result<ReadDir> {
     } else {
         let root = path.to_path_buf();
         let inner = InnerReadDir { dirp: Dir(ptr), root };
-        Ok(ReadDir {
-            inner: Arc::new(inner),
-            #[cfg(not(any(
-                target_os = "android",
-                target_os = "linux",
-                target_os = "solaris",
-                target_os = "illumos",
-                target_os = "fuchsia",
-                target_os = "redox",
-            )))]
-            end_of_stream: false,
-        })
+        Ok(ReadDir::new(inner))
     }
 }
 
@@ -1739,12 +1750,16 @@ mod remove_dir_impl {
     use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd};
     use crate::os::unix::prelude::{OwnedFd, RawFd};
     use crate::path::{Path, PathBuf};
-    use crate::sync::Arc;
     use crate::sys::common::small_c_string::run_path_with_cstr;
     use crate::sys::{cvt, cvt_r};
 
-    #[cfg(not(all(target_os = "macos", not(target_arch = "aarch64")),))]
+    #[cfg(not(any(
+        target_os = "linux",
+        all(target_os = "macos", not(target_arch = "aarch64"))
+    )))]
     use libc::{fdopendir, openat, unlinkat};
+    #[cfg(target_os = "linux")]
+    use libc::{fdopendir, openat64 as openat, unlinkat};
     #[cfg(all(target_os = "macos", not(target_arch = "aarch64")))]
     use macos_weak::{fdopendir, openat, unlinkat};
 
@@ -1811,21 +1826,8 @@ fn fdreaddir(dir_fd: OwnedFd) -> io::Result<(ReadDir, RawFd)> {
         // a valid root is not needed because we do not call any functions involving the full path
         // of the DirEntrys.
         let dummy_root = PathBuf::new();
-        Ok((
-            ReadDir {
-                inner: Arc::new(InnerReadDir { dirp, root: dummy_root }),
-                #[cfg(not(any(
-                    target_os = "android",
-                    target_os = "linux",
-                    target_os = "solaris",
-                    target_os = "illumos",
-                    target_os = "fuchsia",
-                    target_os = "redox",
-                )))]
-                end_of_stream: false,
-            },
-            new_parent_fd,
-        ))
+        let inner = InnerReadDir { dirp, root: dummy_root };
+        Ok((ReadDir::new(inner), new_parent_fd))
     }
 
     #[cfg(any(
index 94546ca09d00d859bdf3863eb4cead3f9223d120..6fa85e859c05b303495ac8e2d808832a13fd0e5b 100644 (file)
 use crate::sync::atomic::{AtomicBool, AtomicU8, Ordering};
 use crate::sys::cvt;
 use crate::sys::weak::syscall;
+#[cfg(not(target_os = "linux"))]
+use libc::sendfile as sendfile64;
+#[cfg(target_os = "linux")]
+use libc::sendfile64;
 use libc::{EBADF, EINVAL, ENOSYS, EOPNOTSUPP, EOVERFLOW, EPERM, EXDEV};
 
 #[cfg(test)]
@@ -647,7 +651,7 @@ fn splice(
 
         let result = match mode {
             SpliceMode::Sendfile => {
-                cvt(unsafe { libc::sendfile(writer, reader, ptr::null_mut(), chunk_size) })
+                cvt(unsafe { sendfile64(writer, reader, ptr::null_mut(), chunk_size) })
             }
             SpliceMode::Splice => cvt(unsafe {
                 splice(reader, ptr::null_mut(), writer, ptr::null_mut(), chunk_size, 0)
index 1ddb09905db2cfa0f3002535eb8729c3400310b9..6be1abc2b080a0164d772b5f6eed32b7f2bc9b9d 100644 (file)
@@ -2,6 +2,7 @@
 use crate::ptr;
 use crate::sync::atomic::{AtomicPtr, Ordering::Relaxed};
 use crate::sys::locks::{pthread_mutex, Mutex};
+use crate::sys::time::TIMESPEC_MAX;
 use crate::sys_common::lazy_box::{LazyBox, LazyInit};
 use crate::time::Duration;
 
@@ -12,13 +13,6 @@ pub struct Condvar {
     mutex: AtomicPtr<libc::pthread_mutex_t>,
 }
 
-const TIMESPEC_MAX: libc::timespec =
-    libc::timespec { tv_sec: <libc::time_t>::MAX, tv_nsec: 1_000_000_000 - 1 };
-
-fn saturating_cast_to_time_t(value: u64) -> libc::time_t {
-    if value > <libc::time_t>::MAX as u64 { <libc::time_t>::MAX } else { value as libc::time_t }
-}
-
 #[inline]
 fn raw(c: &Condvar) -> *mut libc::pthread_cond_t {
     c.inner.0.get()
@@ -133,26 +127,15 @@ pub unsafe fn wait(&self, mutex: &Mutex) {
         target_os = "horizon"
     )))]
     pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
-        use crate::mem;
+        use crate::sys::time::Timespec;
 
         let mutex = pthread_mutex::raw(mutex);
         self.verify(mutex);
 
-        let mut now: libc::timespec = mem::zeroed();
-        let r = libc::clock_gettime(libc::CLOCK_MONOTONIC, &mut now);
-        assert_eq!(r, 0);
-
-        // Nanosecond calculations can't overflow because both values are below 1e9.
-        let nsec = dur.subsec_nanos() + now.tv_nsec as u32;
-
-        let sec = saturating_cast_to_time_t(dur.as_secs())
-            .checked_add((nsec / 1_000_000_000) as libc::time_t)
-            .and_then(|s| s.checked_add(now.tv_sec));
-        let nsec = nsec % 1_000_000_000;
-
-        let timeout =
-            sec.map(|s| libc::timespec { tv_sec: s, tv_nsec: nsec as _ }).unwrap_or(TIMESPEC_MAX);
-
+        let timeout = Timespec::now(libc::CLOCK_MONOTONIC)
+            .checked_add_duration(&dur)
+            .and_then(|t| t.to_timespec())
+            .unwrap_or(TIMESPEC_MAX);
         let r = libc::pthread_cond_timedwait(raw(self), mutex, &timeout);
         assert!(r == libc::ETIMEDOUT || r == 0);
         r == 0
@@ -169,57 +152,41 @@ pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
         target_os = "espidf",
         target_os = "horizon"
     ))]
-    pub unsafe fn wait_timeout(&self, mutex: &Mutex, mut dur: Duration) -> bool {
+    pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
+        use crate::sys::time::SystemTime;
         use crate::time::Instant;
 
         let mutex = pthread_mutex::raw(mutex);
         self.verify(mutex);
 
-        // 1000 years
-        let max_dur = Duration::from_secs(1000 * 365 * 86400);
-
-        if dur > max_dur {
-            // OSX implementation of `pthread_cond_timedwait` is buggy
-            // with super long durations. When duration is greater than
-            // 0x100_0000_0000_0000 seconds, `pthread_cond_timedwait`
-            // in macOS Sierra return error 316.
-            //
-            // This program demonstrates the issue:
-            // https://gist.github.com/stepancheg/198db4623a20aad2ad7cddb8fda4a63c
-            //
-            // To work around this issue, and possible bugs of other OSes, timeout
-            // is clamped to 1000 years, which is allowable per the API of `wait_timeout`
-            // because of spurious wakeups.
-
-            dur = max_dur;
-        }
-
-        // First, figure out what time it currently is, in both system and
-        // stable time.  pthread_cond_timedwait uses system time, but we want to
-        // report timeout based on stable time.
-        let mut sys_now = libc::timeval { tv_sec: 0, tv_usec: 0 };
-        let stable_now = Instant::now();
-        let r = libc::gettimeofday(&mut sys_now, ptr::null_mut());
-        assert_eq!(r, 0, "unexpected error: {:?}", crate::io::Error::last_os_error());
-
-        let nsec = dur.subsec_nanos() as libc::c_long + (sys_now.tv_usec * 1000) as libc::c_long;
-        let extra = (nsec / 1_000_000_000) as libc::time_t;
-        let nsec = nsec % 1_000_000_000;
-        let seconds = saturating_cast_to_time_t(dur.as_secs());
-
-        let timeout = sys_now
-            .tv_sec
-            .checked_add(extra)
-            .and_then(|s| s.checked_add(seconds))
-            .map(|s| libc::timespec { tv_sec: s, tv_nsec: nsec })
+        // OSX implementation of `pthread_cond_timedwait` is buggy
+        // with super long durations. When duration is greater than
+        // 0x100_0000_0000_0000 seconds, `pthread_cond_timedwait`
+        // in macOS Sierra returns error 316.
+        //
+        // This program demonstrates the issue:
+        // https://gist.github.com/stepancheg/198db4623a20aad2ad7cddb8fda4a63c
+        //
+        // To work around this issue, and possible bugs of other OSes, timeout
+        // is clamped to 1000 years, which is allowable per the API of `wait_timeout`
+        // because of spurious wakeups.
+        let dur = Duration::min(dur, Duration::from_secs(1000 * 365 * 86400));
+
+        // pthread_cond_timedwait uses system time, but we want to report timeout
+        // based on stable time.
+        let now = Instant::now();
+
+        let timeout = SystemTime::now()
+            .t
+            .checked_add_duration(&dur)
+            .and_then(|t| t.to_timespec())
             .unwrap_or(TIMESPEC_MAX);
 
-        // And wait!
         let r = libc::pthread_cond_timedwait(raw(self), mutex, &timeout);
         debug_assert!(r == libc::ETIMEDOUT || r == 0);
 
         // ETIMEDOUT is not a totally reliable method of determining timeout due
         // to clock shifts, so do the check ourselves
-        stable_now.elapsed() < dur
+        now.elapsed() < dur
     }
 }
index 9055a011c515e18bd33b44953477220266f17f23..3d60941e84e393c0a7fac39d1fb70f736ed448db 100644 (file)
@@ -95,6 +95,10 @@ unsafe fn sanitize_standard_fds() {
         )))]
         'poll: {
             use crate::sys::os::errno;
+            #[cfg(not(target_os = "linux"))]
+            use libc::open as open64;
+            #[cfg(target_os = "linux")]
+            use libc::open64;
             let pfds: &mut [_] = &mut [
                 libc::pollfd { fd: 0, events: 0, revents: 0 },
                 libc::pollfd { fd: 1, events: 0, revents: 0 },
@@ -116,7 +120,7 @@ unsafe fn sanitize_standard_fds() {
                 if pfd.revents & libc::POLLNVAL == 0 {
                     continue;
                 }
-                if libc::open("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
+                if open64("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
                     // If the stream is closed but we failed to reopen it, abort the
                     // process. Otherwise we wouldn't preserve the safety of
                     // operations on the corresponding Rust object Stdin, Stdout, or
@@ -139,9 +143,13 @@ unsafe fn sanitize_standard_fds() {
         )))]
         {
             use crate::sys::os::errno;
+            #[cfg(not(target_os = "linux"))]
+            use libc::open as open64;
+            #[cfg(target_os = "linux")]
+            use libc::open64;
             for fd in 0..3 {
                 if libc::fcntl(fd, libc::F_GETFD) == -1 && errno() == libc::EBADF {
-                    if libc::open("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
+                    if open64("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
                         // If the stream is closed but we failed to reopen it, abort the
                         // process. Otherwise we wouldn't preserve the safety of
                         // operations on the corresponding Rust object Stdin, Stdout, or
index a56c275c942071793a3e456ffa97260d5fb2f7fb..a744d0ab6404334e2b43512a5b81b9283a687a84 100644 (file)
@@ -58,6 +58,10 @@ pub fn is_read_vectored(&self) -> bool {
         self.0.is_read_vectored()
     }
 
+    pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
+        self.0.read_to_end(buf)
+    }
+
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
         self.0.write(buf)
     }
index 66ea3db2015a40fd3868d4a51077b5c29fda3ae2..4c99d758c93a3156e1ccfafe6252443c4f4468b5 100644 (file)
@@ -35,6 +35,11 @@ pub fn spawn(
         Ok((Process { handle: Handle::new(process_handle) }, ours))
     }
 
+    pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
+        let (proc, pipes) = self.spawn(Stdio::MakePipe, false)?;
+        crate::sys_common::process::wait_with_output(proc, pipes)
+    }
+
     pub fn exec(&mut self, default: Stdio) -> io::Error {
         if self.saw_nul() {
             return io::const_io_error!(
index 56a805cef7318fe8e6ed00f57997d90647a03b22..39d1c8b1d8ebc75d0da500c882e4683bd167ba40 100644 (file)
@@ -66,14 +66,15 @@ pub fn spawn(
         //
         // Note that as soon as we're done with the fork there's no need to hold
         // a lock any more because the parent won't do anything and the child is
-        // in its own process. Thus the parent drops the lock guard while the child
-        // forgets it to avoid unlocking it on a new thread, which would be invalid.
+        // in its own process. Thus the parent drops the lock guard immediately.
+        // The child calls `mem::forget` to leak the lock, which is crucial because
+        // releasing a lock is not async-signal-safe.
         let env_lock = sys::os::env_read_lock();
         let (pid, pidfd) = unsafe { self.do_fork()? };
 
         if pid == 0 {
             crate::panic::always_abort();
-            mem::forget(env_lock);
+            mem::forget(env_lock); // avoid non-async-signal-safe unlocking
             drop(input);
             let Err(err) = unsafe { self.do_exec(theirs, envp.as_ref()) };
             let errno = err.raw_os_error().unwrap_or(libc::EINVAL) as u32;
@@ -132,6 +133,11 @@ pub fn spawn(
         }
     }
 
+    pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
+        let (proc, pipes) = self.spawn(Stdio::MakePipe, false)?;
+        crate::sys_common::process::wait_with_output(proc, pipes)
+    }
+
     // Attempts to fork the process. If successful, returns Ok((0, -1))
     // in the child, and Ok((child_pid, -1)) in the parent.
     #[cfg(not(target_os = "linux"))]
index 72f9f3f9ca74c0371427c67df9a337f1fe603db4..f28ca58d02038ade1af035abc4f7abc627455b0d 100644 (file)
@@ -20,6 +20,10 @@ pub fn spawn(
         unsupported()
     }
 
+    pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
+        unsupported()
+    }
+
     pub fn exec(&mut self, _default: Stdio) -> io::Error {
         unsupported_err()
     }
index 200ef6719679845ca7ed9076ebc7a23bc46ccbea..f549d37c301165fad9019ca014f5770398cdcf5c 100644 (file)
@@ -108,6 +108,11 @@ macro_rules! t {
         }
     }
 
+    pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
+        let (proc, pipes) = self.spawn(Stdio::MakePipe, false)?;
+        crate::sys_common::process::wait_with_output(proc, pipes)
+    }
+
     pub fn exec(&mut self, default: Stdio) -> io::Error {
         let ret = Command::spawn(self, default, false);
         match ret {
index 75a5c0f927982b3e8b542048839b7e9a0a8e7278..957e086798fd3cd786acd7f01970f42b813f2231 100644 (file)
@@ -45,7 +45,10 @@ mod imp {
     use crate::thread;
 
     use libc::MAP_FAILED;
-    use libc::{mmap, munmap};
+    #[cfg(not(target_os = "linux"))]
+    use libc::{mmap as mmap64, munmap};
+    #[cfg(target_os = "linux")]
+    use libc::{mmap64, munmap};
     use libc::{sigaction, sighandler_t, SA_ONSTACK, SA_SIGINFO, SIGBUS, SIG_DFL};
     use libc::{sigaltstack, SIGSTKSZ, SS_DISABLE};
     use libc::{MAP_ANON, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE, SIGSEGV};
@@ -135,7 +138,7 @@ unsafe fn get_stackp() -> *mut libc::c_void {
         #[cfg(not(any(target_os = "openbsd", target_os = "netbsd", target_os = "linux",)))]
         let flags = MAP_PRIVATE | MAP_ANON;
         let stackp =
-            mmap(ptr::null_mut(), SIGSTKSZ + page_size(), PROT_READ | PROT_WRITE, flags, -1, 0);
+            mmap64(ptr::null_mut(), SIGSTKSZ + page_size(), PROT_READ | PROT_WRITE, flags, -1, 0);
         if stackp == MAP_FAILED {
             panic!("failed to allocate an alternative stack: {}", io::Error::last_os_error());
         }
index c1d30dd9d521b318ed83cdf225df4ee918da1fcc..d454a2a717c0639a326555d3dc8b21a60450b1dd 100644 (file)
@@ -136,7 +136,7 @@ pub fn set_name(name: &CStr) {
 
         unsafe {
             // Available since glibc 2.12, musl 1.1.16, and uClibc 1.0.20.
-            let name = truncate_cstr(name, TASK_COMM_LEN);
+            let name = truncate_cstr::<{ TASK_COMM_LEN }>(name);
             let res = libc::pthread_setname_np(libc::pthread_self(), name.as_ptr());
             // We have no good way of propagating errors here, but in debug-builds let's check that this actually worked.
             debug_assert_eq!(res, 0);
@@ -153,7 +153,7 @@ pub fn set_name(name: &CStr) {
     #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
     pub fn set_name(name: &CStr) {
         unsafe {
-            let name = truncate_cstr(name, libc::MAXTHREADNAMESIZE);
+            let name = truncate_cstr::<{ libc::MAXTHREADNAMESIZE }>(name);
             let res = libc::pthread_setname_np(name.as_ptr());
             // We have no good way of propagating errors here, but in debug-builds let's check that this actually worked.
             debug_assert_eq!(res, 0);
@@ -285,17 +285,12 @@ fn drop(&mut self) {
 }
 
 #[cfg(any(target_os = "linux", target_os = "macos", target_os = "ios", target_os = "watchos"))]
-fn truncate_cstr(cstr: &CStr, max_with_nul: usize) -> crate::borrow::Cow<'_, CStr> {
-    use crate::{borrow::Cow, ffi::CString};
-
-    if cstr.to_bytes_with_nul().len() > max_with_nul {
-        let bytes = cstr.to_bytes()[..max_with_nul - 1].to_vec();
-        // SAFETY: the non-nul bytes came straight from a CStr.
-        // (CString will add the terminating nul.)
-        Cow::Owned(unsafe { CString::from_vec_unchecked(bytes) })
-    } else {
-        Cow::Borrowed(cstr)
+fn truncate_cstr<const MAX_WITH_NUL: usize>(cstr: &CStr) -> [libc::c_char; MAX_WITH_NUL] {
+    let mut result = [0; MAX_WITH_NUL];
+    for (src, dst) in cstr.to_bytes().iter().zip(&mut result[..MAX_WITH_NUL - 1]) {
+        *dst = *src as libc::c_char;
     }
+    result
 }
 
 pub fn available_parallelism() -> io::Result<NonZeroUsize> {
@@ -658,7 +653,10 @@ pub unsafe fn init() -> Option<Guard> {
 ))]
 #[cfg_attr(test, allow(dead_code))]
 pub mod guard {
-    use libc::{mmap, mprotect};
+    #[cfg(not(target_os = "linux"))]
+    use libc::{mmap as mmap64, mprotect};
+    #[cfg(target_os = "linux")]
+    use libc::{mmap64, mprotect};
     use libc::{MAP_ANON, MAP_FAILED, MAP_FIXED, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE};
 
     use crate::io;
@@ -808,7 +806,7 @@ pub unsafe fn init() -> Option<Guard> {
             // read/write permissions and only then mprotect() it to
             // no permissions at all. See issue #50313.
             let stackptr = get_stack_start_aligned()?;
-            let result = mmap(
+            let result = mmap64(
                 stackptr,
                 page_size,
                 PROT_READ | PROT_WRITE,
index 3dfc0026ed1a43a219c51c870c5d402944913789..c400c7715676f7856d47e3be8ed83e0c839cd340 100644 (file)
@@ -6,6 +6,7 @@
 use crate::ptr::addr_of_mut;
 use crate::sync::atomic::AtomicUsize;
 use crate::sync::atomic::Ordering::SeqCst;
+use crate::sys::time::TIMESPEC_MAX;
 use crate::time::Duration;
 
 const EMPTY: usize = 0;
@@ -32,9 +33,6 @@ unsafe fn wait(cond: *mut libc::pthread_cond_t, lock: *mut libc::pthread_mutex_t
     debug_assert_eq!(r, 0);
 }
 
-const TIMESPEC_MAX: libc::timespec =
-    libc::timespec { tv_sec: <libc::time_t>::MAX, tv_nsec: 1_000_000_000 - 1 };
-
 unsafe fn wait_timeout(
     cond: *mut libc::pthread_cond_t,
     lock: *mut libc::pthread_mutex_t,
index d5abd9b581c65b67adf203f4e8a5c345e5897de8..2daad981b73e9a94af6e3b3f779b029d4026076e 100644 (file)
@@ -5,6 +5,9 @@
 
 const NSEC_PER_SEC: u64 = 1_000_000_000;
 pub const UNIX_EPOCH: SystemTime = SystemTime { t: Timespec::zero() };
+#[allow(dead_code)] // Used for pthread condvar timeouts
+pub const TIMESPEC_MAX: libc::timespec =
+    libc::timespec { tv_sec: <libc::time_t>::MAX, tv_nsec: 1_000_000_000 - 1 };
 
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
 #[repr(transparent)]
index e4ff21b25bd9ce47aea69b7fd0f2eb696c873306..f5a4ce929b2a9219311c6c6d1298fad26c695b0c 100644 (file)
 use crate::sync::atomic::{self, AtomicPtr, Ordering};
 
 // We can use true weak linkage on ELF targets.
-#[cfg(not(any(target_os = "macos", target_os = "ios")))]
+#[cfg(all(not(any(target_os = "macos", target_os = "ios")), not(bootstrap)))]
+pub(crate) macro weak {
+    (fn $name:ident($($t:ty),*) -> $ret:ty) => (
+        let ref $name: ExternWeak<unsafe extern "C" fn($($t),*) -> $ret> = {
+            extern "C" {
+                #[linkage = "extern_weak"]
+                static $name: Option<unsafe extern "C" fn($($t),*) -> $ret>;
+            }
+            #[allow(unused_unsafe)]
+            ExternWeak::new(unsafe { $name })
+        };
+    )
+}
+
+#[cfg(all(not(any(target_os = "macos", target_os = "ios")), bootstrap))]
 pub(crate) macro weak {
     (fn $name:ident($($t:ty),*) -> $ret:ty) => (
         let ref $name: ExternWeak<unsafe extern "C" fn($($t),*) -> $ret> = {
 #[cfg(any(target_os = "macos", target_os = "ios"))]
 pub(crate) use self::dlsym as weak;
 
+#[cfg(not(bootstrap))]
+pub(crate) struct ExternWeak<F: Copy> {
+    weak_ptr: Option<F>,
+}
+
+#[cfg(not(bootstrap))]
+impl<F: Copy> ExternWeak<F> {
+    #[inline]
+    pub(crate) fn new(weak_ptr: Option<F>) -> Self {
+        ExternWeak { weak_ptr }
+    }
+
+    #[inline]
+    pub(crate) fn get(&self) -> Option<F> {
+        self.weak_ptr
+    }
+}
+
+#[cfg(bootstrap)]
 pub(crate) struct ExternWeak<F> {
     weak_ptr: *const libc::c_void,
     _marker: PhantomData<F>,
 }
 
+#[cfg(bootstrap)]
 impl<F> ExternWeak<F> {
     #[inline]
     pub(crate) fn new(weak_ptr: *const libc::c_void) -> Self {
@@ -59,6 +93,7 @@ pub(crate) fn new(weak_ptr: *const libc::c_void) -> Self {
     }
 }
 
+#[cfg(bootstrap)]
 impl<F> ExternWeak<F> {
     #[inline]
     pub(crate) fn get(&self) -> Option<F> {
index 25514c2322fa45d3890efeb67f86dc2a99b0c99c..0bba673b458cb690011d413db588dffb9bde88c1 100644 (file)
@@ -15,6 +15,10 @@ pub fn is_read_vectored(&self) -> bool {
         self.0
     }
 
+    pub fn read_to_end(&self, _buf: &mut Vec<u8>) -> io::Result<usize> {
+        self.0
+    }
+
     pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
         self.0
     }
index 633f17c054bc670c59d6f17c4a51003ba2c92e3b..a494f2d6b4c1529314c3a2a4b91184d9d6fa1697 100644 (file)
@@ -75,6 +75,10 @@ pub fn spawn(
     ) -> io::Result<(Process, StdioPipes)> {
         unsupported()
     }
+
+    pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
+        unsupported()
+    }
 }
 
 impl From<AnonPipe> for Stdio {
index 9f26acc45205cde3ac32ffcf38747a5c8e0e7f95..7b25edaa556f082e211cf0f90ad07ba67181d29f 100644 (file)
@@ -1,7 +1,7 @@
 use crate::os::windows::prelude::*;
 
 use crate::ffi::OsStr;
-use crate::io::{self, IoSlice, IoSliceMut};
+use crate::io::{self, IoSlice, IoSliceMut, Read};
 use crate::mem;
 use crate::path::Path;
 use crate::ptr;
@@ -261,6 +261,10 @@ pub fn is_read_vectored(&self) -> bool {
         self.inner.is_read_vectored()
     }
 
+    pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
+        self.handle().read_to_end(buf)
+    }
+
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
         unsafe {
             let len = crate::cmp::min(buf.len(), c::DWORD::MAX as usize) as c::DWORD;
index 9cbb4ef19e9b7a80dff8732c8e318dc2051b1c72..10bc949e1f45faf7c167e66e6b5c61a4c2aae980 100644 (file)
@@ -252,10 +252,6 @@ pub fn spawn(
     ) -> io::Result<(Process, StdioPipes)> {
         let maybe_env = self.env.capture_if_changed();
 
-        let mut si = zeroed_startupinfo();
-        si.cb = mem::size_of::<c::STARTUPINFO>() as c::DWORD;
-        si.dwFlags = c::STARTF_USESTDHANDLES;
-
         let child_paths = if let Some(env) = maybe_env.as_ref() {
             env.get(&EnvKey::new("PATH")).map(|s| s.as_os_str())
         } else {
@@ -314,9 +310,21 @@ pub fn spawn(
         let stdin = stdin.to_handle(c::STD_INPUT_HANDLE, &mut pipes.stdin)?;
         let stdout = stdout.to_handle(c::STD_OUTPUT_HANDLE, &mut pipes.stdout)?;
         let stderr = stderr.to_handle(c::STD_ERROR_HANDLE, &mut pipes.stderr)?;
-        si.hStdInput = stdin.as_raw_handle();
-        si.hStdOutput = stdout.as_raw_handle();
-        si.hStdError = stderr.as_raw_handle();
+
+        let mut si = zeroed_startupinfo();
+        si.cb = mem::size_of::<c::STARTUPINFO>() as c::DWORD;
+
+        // If at least one of stdin, stdout or stderr are set (i.e. are non null)
+        // then set the `hStd` fields in `STARTUPINFO`.
+        // Otherwise skip this and allow the OS to apply its default behaviour.
+        // This provides more consistent behaviour between Win7 and Win8+.
+        let is_set = |stdio: &Handle| !stdio.as_raw_handle().is_null();
+        if is_set(&stderr) || is_set(&stdout) || is_set(&stdin) {
+            si.dwFlags |= c::STARTF_USESTDHANDLES;
+            si.hStdInput = stdin.as_raw_handle();
+            si.hStdOutput = stdout.as_raw_handle();
+            si.hStdError = stderr.as_raw_handle();
+        }
 
         unsafe {
             cvt(c::CreateProcessW(
@@ -343,6 +351,11 @@ pub fn spawn(
             ))
         }
     }
+
+    pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
+        let (proc, pipes) = self.spawn(Stdio::MakePipe, false)?;
+        crate::sys_common::process::wait_with_output(proc, pipes)
+    }
 }
 
 impl fmt::Debug for Command {
@@ -513,9 +526,6 @@ fn program_exists(path: &Path) -> Option<Vec<u16>> {
 impl Stdio {
     fn to_handle(&self, stdio_id: c::DWORD, pipe: &mut Option<AnonPipe>) -> io::Result<Handle> {
         match *self {
-            // If no stdio handle is available, then inherit means that it
-            // should still be unavailable so propagate the
-            // INVALID_HANDLE_VALUE.
             Stdio::Inherit => match stdio::get_handle(stdio_id) {
                 Ok(io) => unsafe {
                     let io = Handle::from_raw_handle(io);
@@ -523,7 +533,8 @@ fn to_handle(&self, stdio_id: c::DWORD, pipe: &mut Option<AnonPipe>) -> io::Resu
                     io.into_raw_handle();
                     ret
                 },
-                Err(..) => unsafe { Ok(Handle::from_raw_handle(c::INVALID_HANDLE_VALUE)) },
+                // If no stdio handle is available, then propagate the null value.
+                Err(..) => unsafe { Ok(Handle::from_raw_handle(ptr::null_mut())) },
             },
 
             Stdio::MakePipe => {
@@ -730,9 +741,9 @@ fn zeroed_startupinfo() -> c::STARTUPINFO {
         wShowWindow: 0,
         cbReserved2: 0,
         lpReserved2: ptr::null_mut(),
-        hStdInput: c::INVALID_HANDLE_VALUE,
-        hStdOutput: c::INVALID_HANDLE_VALUE,
-        hStdError: c::INVALID_HANDLE_VALUE,
+        hStdInput: ptr::null_mut(),
+        hStdOutput: ptr::null_mut(),
+        hStdError: ptr::null_mut(),
     }
 }
 
index 9f978789a62322c782245759d1cc4d66f0227405..ae11412067b549a719ec243442bd2beb7606c270 100644 (file)
@@ -4,7 +4,9 @@
 use crate::collections::BTreeMap;
 use crate::env;
 use crate::ffi::{OsStr, OsString};
-use crate::sys::process::EnvKey;
+use crate::io;
+use crate::sys::pipe::read2;
+use crate::sys::process::{EnvKey, ExitStatus, Process, StdioPipes};
 
 // Stores a set of changes to an environment
 #[derive(Clone, Debug)]
@@ -117,3 +119,30 @@ fn is_empty(&self) -> bool {
         self.iter.is_empty()
     }
 }
+
+pub fn wait_with_output(
+    mut process: Process,
+    mut pipes: StdioPipes,
+) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
+    drop(pipes.stdin.take());
+
+    let (mut stdout, mut stderr) = (Vec::new(), Vec::new());
+    match (pipes.stdout.take(), pipes.stderr.take()) {
+        (None, None) => {}
+        (Some(out), None) => {
+            let res = out.read_to_end(&mut stdout);
+            res.unwrap();
+        }
+        (None, Some(err)) => {
+            let res = err.read_to_end(&mut stderr);
+            res.unwrap();
+        }
+        (Some(out), Some(err)) => {
+            let res = read2(out, &mut stdout, err, &mut stderr);
+            res.unwrap();
+        }
+    }
+
+    let status = process.wait()?;
+    Ok((status, stdout, stderr))
+}
index f86a9a555d322e02c08c885aadcd4af194795921..08a2bdd82298b9f622e5589ff2550d20ccd0658a 100644 (file)
@@ -16,6 +16,8 @@
         pub use wait_flag::Parker;
     } else if #[cfg(any(windows, target_family = "unix"))] {
         pub use crate::sys::thread_parker::Parker;
+    } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] {
+        pub use crate::sys::thread_parker::Parker;
     } else {
         mod generic;
         pub use generic::Parker;
index 8ee6d49da8f0e419b4fc9ff2898a4e21f5c47bae..1d37d68c1d4050d807d4e73fe68591d434e05158 100644 (file)
@@ -19,6 +19,7 @@
 use crate::install;
 use crate::native;
 use crate::run;
+use crate::setup;
 use crate::test;
 use crate::tool::{self, SourceType};
 use crate::util::{self, add_dylib_path, add_link_lib_path, exe, libdir, output, t};
@@ -433,8 +434,11 @@ pub(crate) fn crates(mut self, crates: Vec<&Crate>) -> Self {
 
     // single alias, which does not correspond to any on-disk path
     pub fn alias(mut self, alias: &str) -> Self {
+        // exceptional case for `Kind::Setup` because its `library`
+        // and `compiler` options would otherwise naively match with
+        // `compiler` and `library` folders respectively.
         assert!(
-            !self.builder.src.join(alias).exists(),
+            self.kind == Kind::Setup || !self.builder.src.join(alias).exists(),
             "use `builder.path()` for real paths: {}",
             alias
         );
@@ -744,6 +748,7 @@ macro_rules! describe {
                 install::RustDemangler,
                 install::Clippy,
                 install::Miri,
+                install::LlvmTools,
                 install::Analysis,
                 install::Src,
                 install::Rustc
@@ -757,8 +762,9 @@ macro_rules! describe {
                 run::CollectLicenseMetadata,
                 run::GenerateCopyright,
             ),
+            Kind::Setup => describe!(setup::Profile),
             // These commands either don't use paths, or they're special-cased in Build::build()
-            Kind::Clean | Kind::Format | Kind::Setup => vec![],
+            Kind::Clean | Kind::Format => vec![],
         }
     }
 
@@ -821,7 +827,11 @@ pub fn new(build: &Build) -> Builder<'_> {
             Subcommand::Install { ref paths } => (Kind::Install, &paths[..]),
             Subcommand::Run { ref paths, .. } => (Kind::Run, &paths[..]),
             Subcommand::Format { .. } => (Kind::Format, &[][..]),
-            Subcommand::Clean { .. } | Subcommand::Setup { .. } => {
+            Subcommand::Setup { profile: ref path } => (
+                Kind::Setup,
+                path.as_ref().map_or([].as_slice(), |path| std::slice::from_ref(path)),
+            ),
+            Subcommand::Clean { .. } => {
                 panic!()
             }
         };
index be5c9bb07880891cbe23550c952f2aed26a93c9a..05f25af68ea8fe5985e11370df9bbe03c2951e01 100644 (file)
@@ -89,16 +89,16 @@ fn hash<H: Hasher>(&self, state: &mut H) {
 
 impl<T: Internable + Deref> Deref for Interned<T> {
     type Target = T::Target;
-    fn deref(&self) -> &'static Self::Target {
+    fn deref(&self) -> &Self::Target {
         let l = T::intern_cache().lock().unwrap();
-        unsafe { mem::transmute::<&Self::Target, &'static Self::Target>(l.get(*self)) }
+        unsafe { mem::transmute::<&Self::Target, &Self::Target>(l.get(*self)) }
     }
 }
 
 impl<T: Internable + AsRef<U>, U: ?Sized> AsRef<U> for Interned<T> {
-    fn as_ref(&self) -> &'static U {
+    fn as_ref(&self) -> &U {
         let l = T::intern_cache().lock().unwrap();
-        unsafe { mem::transmute::<&U, &'static U>(l.get(*self).as_ref()) }
+        unsafe { mem::transmute::<&U, &U>(l.get(*self).as_ref()) }
     }
 }
 
index d8c15c76e2d615b3a936a0b4e8616077a92d3c87..2906616ffad142958e4debc08d55472a7b348971 100644 (file)
@@ -3,6 +3,9 @@
 //! This module implements parsing `config.toml` configuration files to tweak
 //! how the build runs.
 
+#[cfg(test)]
+mod tests;
+
 use std::cell::{Cell, RefCell};
 use std::cmp;
 use std::collections::{HashMap, HashSet};
@@ -635,6 +638,7 @@ struct Build {
         dist_stage: Option<u32> = "dist-stage",
         bench_stage: Option<u32> = "bench-stage",
         patch_binaries_for_nix: Option<bool> = "patch-binaries-for-nix",
+        // NOTE: only parsed by bootstrap.py, `--feature build-metrics` enables metrics unconditionally
         metrics: Option<bool> = "metrics",
     }
 }
@@ -696,7 +700,7 @@ struct Dist {
     }
 }
 
-#[derive(Deserialize)]
+#[derive(Debug, Deserialize)]
 #[serde(untagged)]
 enum StringOrBool {
     String(String),
@@ -822,6 +826,29 @@ pub fn default_opts() -> Config {
     }
 
     pub fn parse(args: &[String]) -> Config {
+        #[cfg(test)]
+        let get_toml = |_: &_| TomlConfig::default();
+        #[cfg(not(test))]
+        let get_toml = |file: &Path| {
+            let contents =
+                t!(fs::read_to_string(file), format!("config file {} not found", file.display()));
+            // Deserialize to Value and then TomlConfig to prevent the Deserialize impl of
+            // TomlConfig and sub types to be monomorphized 5x by toml.
+            match toml::from_str(&contents)
+                .and_then(|table: toml::Value| TomlConfig::deserialize(table))
+            {
+                Ok(table) => table,
+                Err(err) => {
+                    eprintln!("failed to parse TOML configuration '{}': {}", file.display(), err);
+                    crate::detail_exit(2);
+                }
+            }
+        };
+
+        Self::parse_inner(args, get_toml)
+    }
+
+    fn parse_inner<'a>(args: &[String], get_toml: impl 'a + Fn(&Path) -> TomlConfig) -> Config {
         let flags = Flags::parse(&args);
         let mut config = Config::default_opts();
 
@@ -907,25 +934,6 @@ pub fn parse(args: &[String]) -> Config {
 
         config.stage0_metadata = t!(serde_json::from_slice::<Stage0Metadata>(&stage0_json));
 
-        #[cfg(test)]
-        let get_toml = |_| TomlConfig::default();
-        #[cfg(not(test))]
-        let get_toml = |file: &Path| {
-            let contents =
-                t!(fs::read_to_string(file), format!("config file {} not found", file.display()));
-            // Deserialize to Value and then TomlConfig to prevent the Deserialize impl of
-            // TomlConfig and sub types to be monomorphized 5x by toml.
-            match toml::from_str(&contents)
-                .and_then(|table: toml::Value| TomlConfig::deserialize(table))
-            {
-                Ok(table) => table,
-                Err(err) => {
-                    eprintln!("failed to parse TOML configuration '{}': {}", file.display(), err);
-                    crate::detail_exit(2);
-                }
-            }
-        };
-
         // Read from `--config`, then `RUST_BOOTSTRAP_CONFIG`, then `./config.toml`, then `config.toml` in the root directory.
         let toml_path = flags
             .config
@@ -1063,6 +1071,79 @@ pub fn parse(args: &[String]) -> Config {
         let mut optimize = None;
         let mut ignore_git = None;
 
+        if let Some(rust) = toml.rust {
+            debug = rust.debug;
+            debug_assertions = rust.debug_assertions;
+            debug_assertions_std = rust.debug_assertions_std;
+            overflow_checks = rust.overflow_checks;
+            overflow_checks_std = rust.overflow_checks_std;
+            debug_logging = rust.debug_logging;
+            debuginfo_level = rust.debuginfo_level;
+            debuginfo_level_rustc = rust.debuginfo_level_rustc;
+            debuginfo_level_std = rust.debuginfo_level_std;
+            debuginfo_level_tools = rust.debuginfo_level_tools;
+            debuginfo_level_tests = rust.debuginfo_level_tests;
+            config.rust_split_debuginfo = rust
+                .split_debuginfo
+                .as_deref()
+                .map(SplitDebuginfo::from_str)
+                .map(|v| v.expect("invalid value for rust.split_debuginfo"))
+                .unwrap_or(SplitDebuginfo::default_for_platform(&config.build.triple));
+            optimize = rust.optimize;
+            ignore_git = rust.ignore_git;
+            config.rust_new_symbol_mangling = rust.new_symbol_mangling;
+            set(&mut config.rust_optimize_tests, rust.optimize_tests);
+            set(&mut config.codegen_tests, rust.codegen_tests);
+            set(&mut config.rust_rpath, rust.rpath);
+            set(&mut config.jemalloc, rust.jemalloc);
+            set(&mut config.test_compare_mode, rust.test_compare_mode);
+            set(&mut config.backtrace, rust.backtrace);
+            set(&mut config.channel, rust.channel);
+            config.description = rust.description;
+            set(&mut config.rust_dist_src, rust.dist_src);
+            set(&mut config.verbose_tests, rust.verbose_tests);
+            // in the case "false" is set explicitly, do not overwrite the command line args
+            if let Some(true) = rust.incremental {
+                config.incremental = true;
+            }
+            set(&mut config.use_lld, rust.use_lld);
+            set(&mut config.lld_enabled, rust.lld);
+            set(&mut config.llvm_tools_enabled, rust.llvm_tools);
+            config.rustc_parallel = rust.parallel_compiler.unwrap_or(false);
+            config.rustc_default_linker = rust.default_linker;
+            config.musl_root = rust.musl_root.map(PathBuf::from);
+            config.save_toolstates = rust.save_toolstates.map(PathBuf::from);
+            set(&mut config.deny_warnings, flags.deny_warnings.or(rust.deny_warnings));
+            set(&mut config.backtrace_on_ice, rust.backtrace_on_ice);
+            set(&mut config.rust_verify_llvm_ir, rust.verify_llvm_ir);
+            config.rust_thin_lto_import_instr_limit = rust.thin_lto_import_instr_limit;
+            set(&mut config.rust_remap_debuginfo, rust.remap_debuginfo);
+            set(&mut config.control_flow_guard, rust.control_flow_guard);
+            config.llvm_libunwind_default = rust
+                .llvm_libunwind
+                .map(|v| v.parse().expect("failed to parse rust.llvm-libunwind"));
+
+            if let Some(ref backends) = rust.codegen_backends {
+                config.rust_codegen_backends =
+                    backends.iter().map(|s| INTERNER.intern_str(s)).collect();
+            }
+
+            config.rust_codegen_units = rust.codegen_units.map(threads_from_config);
+            config.rust_codegen_units_std = rust.codegen_units_std.map(threads_from_config);
+            config.rust_profile_use = flags.rust_profile_use.or(rust.profile_use);
+            config.rust_profile_generate = flags.rust_profile_generate.or(rust.profile_generate);
+            config.download_rustc_commit = config.download_ci_rustc_commit(rust.download_rustc);
+
+            config.rust_lto = rust
+                .lto
+                .as_deref()
+                .map(|value| RustcLto::from_str(value).unwrap())
+                .unwrap_or_default();
+        } else {
+            config.rust_profile_use = flags.rust_profile_use;
+            config.rust_profile_generate = flags.rust_profile_generate;
+        }
+
         if let Some(llvm) = toml.llvm {
             match llvm.ccache {
                 Some(StringOrBool::String(ref s)) => config.ccache = Some(s.to_string()),
@@ -1099,13 +1180,17 @@ pub fn parse(args: &[String]) -> Config {
             config.llvm_polly = llvm.polly.unwrap_or(false);
             config.llvm_clang = llvm.clang.unwrap_or(false);
             config.llvm_build_config = llvm.build_config.clone().unwrap_or(Default::default());
+
+            let asserts = llvm_assertions.unwrap_or(false);
             config.llvm_from_ci = match llvm.download_ci_llvm {
                 Some(StringOrBool::String(s)) => {
                     assert!(s == "if-available", "unknown option `{}` for download-ci-llvm", s);
-                    crate::native::is_ci_llvm_available(&config, llvm_assertions.unwrap_or(false))
+                    crate::native::is_ci_llvm_available(&config, asserts)
                 }
                 Some(StringOrBool::Bool(b)) => b,
-                None => false,
+                None => {
+                    config.channel == "dev" && crate::native::is_ci_llvm_available(&config, asserts)
+                }
             };
 
             if config.llvm_from_ci {
@@ -1145,79 +1230,9 @@ pub fn parse(args: &[String]) -> Config {
                 // the link step) with each stage.
                 config.llvm_link_shared.set(Some(true));
             }
-        }
-
-        if let Some(rust) = toml.rust {
-            debug = rust.debug;
-            debug_assertions = rust.debug_assertions;
-            debug_assertions_std = rust.debug_assertions_std;
-            overflow_checks = rust.overflow_checks;
-            overflow_checks_std = rust.overflow_checks_std;
-            debug_logging = rust.debug_logging;
-            debuginfo_level = rust.debuginfo_level;
-            debuginfo_level_rustc = rust.debuginfo_level_rustc;
-            debuginfo_level_std = rust.debuginfo_level_std;
-            debuginfo_level_tools = rust.debuginfo_level_tools;
-            debuginfo_level_tests = rust.debuginfo_level_tests;
-            config.rust_split_debuginfo = rust
-                .split_debuginfo
-                .as_deref()
-                .map(SplitDebuginfo::from_str)
-                .map(|v| v.expect("invalid value for rust.split_debuginfo"))
-                .unwrap_or(SplitDebuginfo::default_for_platform(&config.build.triple));
-            optimize = rust.optimize;
-            ignore_git = rust.ignore_git;
-            config.rust_new_symbol_mangling = rust.new_symbol_mangling;
-            set(&mut config.rust_optimize_tests, rust.optimize_tests);
-            set(&mut config.codegen_tests, rust.codegen_tests);
-            set(&mut config.rust_rpath, rust.rpath);
-            set(&mut config.jemalloc, rust.jemalloc);
-            set(&mut config.test_compare_mode, rust.test_compare_mode);
-            set(&mut config.backtrace, rust.backtrace);
-            set(&mut config.channel, rust.channel);
-            config.description = rust.description;
-            set(&mut config.rust_dist_src, rust.dist_src);
-            set(&mut config.verbose_tests, rust.verbose_tests);
-            // in the case "false" is set explicitly, do not overwrite the command line args
-            if let Some(true) = rust.incremental {
-                config.incremental = true;
-            }
-            set(&mut config.use_lld, rust.use_lld);
-            set(&mut config.lld_enabled, rust.lld);
-            set(&mut config.llvm_tools_enabled, rust.llvm_tools);
-            config.rustc_parallel = rust.parallel_compiler.unwrap_or(false);
-            config.rustc_default_linker = rust.default_linker;
-            config.musl_root = rust.musl_root.map(PathBuf::from);
-            config.save_toolstates = rust.save_toolstates.map(PathBuf::from);
-            set(&mut config.deny_warnings, flags.deny_warnings.or(rust.deny_warnings));
-            set(&mut config.backtrace_on_ice, rust.backtrace_on_ice);
-            set(&mut config.rust_verify_llvm_ir, rust.verify_llvm_ir);
-            config.rust_thin_lto_import_instr_limit = rust.thin_lto_import_instr_limit;
-            set(&mut config.rust_remap_debuginfo, rust.remap_debuginfo);
-            set(&mut config.control_flow_guard, rust.control_flow_guard);
-            config.llvm_libunwind_default = rust
-                .llvm_libunwind
-                .map(|v| v.parse().expect("failed to parse rust.llvm-libunwind"));
-
-            if let Some(ref backends) = rust.codegen_backends {
-                config.rust_codegen_backends =
-                    backends.iter().map(|s| INTERNER.intern_str(s)).collect();
-            }
-
-            config.rust_codegen_units = rust.codegen_units.map(threads_from_config);
-            config.rust_codegen_units_std = rust.codegen_units_std.map(threads_from_config);
-            config.rust_profile_use = flags.rust_profile_use.or(rust.profile_use);
-            config.rust_profile_generate = flags.rust_profile_generate.or(rust.profile_generate);
-            config.download_rustc_commit = config.download_ci_rustc_commit(rust.download_rustc);
-
-            config.rust_lto = rust
-                .lto
-                .as_deref()
-                .map(|value| RustcLto::from_str(value).unwrap())
-                .unwrap_or_default();
         } else {
-            config.rust_profile_use = flags.rust_profile_use;
-            config.rust_profile_generate = flags.rust_profile_generate;
+            config.llvm_from_ci =
+                config.channel == "dev" && crate::native::is_ci_llvm_available(&config, false);
         }
 
         if let Some(t) = toml.target {
diff --git a/src/bootstrap/config/tests.rs b/src/bootstrap/config/tests.rs
new file mode 100644 (file)
index 0000000..c30c913
--- /dev/null
@@ -0,0 +1,24 @@
+use super::{Config, TomlConfig};
+use std::path::Path;
+
+fn toml(config: &str) -> impl '_ + Fn(&Path) -> TomlConfig {
+    |&_| toml::from_str(config).unwrap()
+}
+
+fn parse(config: &str) -> Config {
+    Config::parse_inner(&["check".to_owned(), "--config=/does/not/exist".to_owned()], toml(config))
+}
+
+#[test]
+fn download_ci_llvm() {
+    let parse_llvm = |s| parse(s).llvm_from_ci;
+    let if_available = parse_llvm("llvm.download-ci-llvm = \"if-available\"");
+
+    assert!(parse_llvm("llvm.download-ci-llvm = true"));
+    assert!(!parse_llvm("llvm.download-ci-llvm = false"));
+    assert_eq!(parse_llvm(""), if_available);
+    assert_eq!(parse_llvm("rust.channel = \"dev\""), if_available);
+    assert!(!parse_llvm("rust.channel = \"stable\""));
+}
+
+// FIXME: add test for detecting `src` and `out`
index 6647061d88fcbc99005ed446871d4ab2c420273c..48ae2fe448de2070ddcfd37b57b99434386b5ba4 100644 (file)
@@ -7,3 +7,7 @@ test-stage = 2
 doc-stage = 2
 # When compiling from source, you usually want all tools.
 extended = true
+
+[llvm]
+# Most users installing from source want to build all parts of the project from source, not just rustc itself.
+download-ci-llvm = false
index 2fef7f65827dd65c90e43c4b2141b964a4943fef..3cb0eccd324d42574b082e4c1af721ada6a6bb77 100644 (file)
@@ -1470,7 +1470,7 @@ fn filter(contents: &str, marker: &str) -> String {
 
         let xform = |p: &Path| {
             let mut contents = t!(fs::read_to_string(p));
-            for tool in &["rust-demangler"] {
+            for tool in &["rust-demangler", "miri"] {
                 if !built_tools.contains(tool) {
                     contents = filter(&contents, tool);
                 }
@@ -1510,9 +1510,8 @@ fn filter(contents: &str, marker: &str) -> String {
             prepare("rust-std");
             prepare("rust-analysis");
             prepare("clippy");
-            prepare("miri");
             prepare("rust-analyzer");
-            for tool in &["rust-docs", "rust-demangler"] {
+            for tool in &["rust-docs", "rust-demangler", "miri"] {
                 if built_tools.contains(tool) {
                     prepare(tool);
                 }
@@ -1571,9 +1570,8 @@ fn filter(contents: &str, marker: &str) -> String {
             prepare("rust-docs");
             prepare("rust-std");
             prepare("clippy");
-            prepare("miri");
             prepare("rust-analyzer");
-            for tool in &["rust-demangler"] {
+            for tool in &["rust-demangler", "miri"] {
                 if built_tools.contains(tool) {
                     prepare(tool);
                 }
@@ -1710,23 +1708,25 @@ fn filter(contents: &str, marker: &str) -> String {
                         .arg(etc.join("msi/remove-duplicates.xsl")),
                 );
             }
-            builder.run(
-                Command::new(&heat)
-                    .current_dir(&exe)
-                    .arg("dir")
-                    .arg("miri")
-                    .args(&heat_flags)
-                    .arg("-cg")
-                    .arg("MiriGroup")
-                    .arg("-dr")
-                    .arg("Miri")
-                    .arg("-var")
-                    .arg("var.MiriDir")
-                    .arg("-out")
-                    .arg(exe.join("MiriGroup.wxs"))
-                    .arg("-t")
-                    .arg(etc.join("msi/remove-duplicates.xsl")),
-            );
+            if built_tools.contains("miri") {
+                builder.run(
+                    Command::new(&heat)
+                        .current_dir(&exe)
+                        .arg("dir")
+                        .arg("miri")
+                        .args(&heat_flags)
+                        .arg("-cg")
+                        .arg("MiriGroup")
+                        .arg("-dr")
+                        .arg("Miri")
+                        .arg("-var")
+                        .arg("var.MiriDir")
+                        .arg("-out")
+                        .arg(exe.join("MiriGroup.wxs"))
+                        .arg("-t")
+                        .arg(etc.join("msi/remove-duplicates.xsl")),
+                );
+            }
             builder.run(
                 Command::new(&heat)
                     .current_dir(&exe)
@@ -1774,7 +1774,6 @@ fn filter(contents: &str, marker: &str) -> String {
                     .arg("-dStdDir=rust-std")
                     .arg("-dAnalysisDir=rust-analysis")
                     .arg("-dClippyDir=clippy")
-                    .arg("-dMiriDir=miri")
                     .arg("-arch")
                     .arg(&arch)
                     .arg("-out")
@@ -1788,6 +1787,9 @@ fn filter(contents: &str, marker: &str) -> String {
                 if built_tools.contains("rust-analyzer") {
                     cmd.arg("-dRustAnalyzerDir=rust-analyzer");
                 }
+                if built_tools.contains("miri") {
+                    cmd.arg("-dMiriDir=miri");
+                }
                 if target.ends_with("windows-gnu") {
                     cmd.arg("-dGccDir=rust-mingw");
                 }
@@ -1801,7 +1803,9 @@ fn filter(contents: &str, marker: &str) -> String {
             candle("CargoGroup.wxs".as_ref());
             candle("StdGroup.wxs".as_ref());
             candle("ClippyGroup.wxs".as_ref());
-            candle("MiriGroup.wxs".as_ref());
+            if built_tools.contains("miri") {
+                candle("MiriGroup.wxs".as_ref());
+            }
             if built_tools.contains("rust-demangler") {
                 candle("RustDemanglerGroup.wxs".as_ref());
             }
@@ -1837,9 +1841,11 @@ fn filter(contents: &str, marker: &str) -> String {
                 .arg("StdGroup.wixobj")
                 .arg("AnalysisGroup.wixobj")
                 .arg("ClippyGroup.wixobj")
-                .arg("MiriGroup.wixobj")
                 .current_dir(&exe);
 
+            if built_tools.contains("miri") {
+                cmd.arg("MiriGroup.wixobj");
+            }
             if built_tools.contains("rust-analyzer") {
                 cmd.arg("RustAnalyzerGroup.wixobj");
             }
index 37a8eb884efb02beba7ca57c462108a1bca96ae1..851cb5ecf4c2694ee7c77b7b97e4bd92a1c7d6a4 100644 (file)
@@ -143,7 +143,7 @@ pub enum Subcommand {
         args: Vec<String>,
     },
     Setup {
-        profile: Option<Profile>,
+        profile: Option<PathBuf>,
     },
 }
 
@@ -351,7 +351,7 @@ pub fn parse(args: &[String]) -> Flags {
 
         // fn usage()
         let usage = |exit_code: i32, opts: &Options, verbose: bool, subcommand_help: &str| -> ! {
-            let config = Config::parse(&["build".to_string()]);
+            let config = Config::parse(&["setup".to_string()]);
             let build = Build::new(config);
             let paths = Builder::get_help(&build, subcommand);
 
@@ -621,7 +621,7 @@ pub fn parse(args: &[String]) -> Flags {
             }
             Kind::Setup => {
                 let profile = if paths.len() > 1 {
-                    println!("\nat most one profile can be passed to setup\n");
+                    eprintln!("\nerror: At most one profile can be passed to setup\n");
                     usage(1, &opts, verbose, &subcommand_help)
                 } else if let Some(path) = paths.pop() {
                     let profile_string = t!(path.into_os_string().into_string().map_err(
index 5e7264fe765a950ac9980b7ef55b5e05023312d6..b2f6afead798088e12ae27425b354540ea6c302b 100644 (file)
@@ -8,7 +8,7 @@
 use std::process::{Command, Stdio};
 use std::sync::mpsc::SyncSender;
 
-fn rustfmt(src: &Path, rustfmt: &Path, paths: &[PathBuf], check: bool) -> impl FnMut() {
+fn rustfmt(src: &Path, rustfmt: &Path, paths: &[PathBuf], check: bool) -> impl FnMut(bool) -> bool {
     let mut cmd = Command::new(&rustfmt);
     // avoid the submodule config paths from coming into play,
     // we only allow a single global config for the workspace for now
@@ -23,7 +23,13 @@ fn rustfmt(src: &Path, rustfmt: &Path, paths: &[PathBuf], check: bool) -> impl F
     let cmd_debug = format!("{:?}", cmd);
     let mut cmd = cmd.spawn().expect("running rustfmt");
     // poor man's async: return a closure that'll wait for rustfmt's completion
-    move || {
+    move |block: bool| -> bool {
+        if !block {
+            match cmd.try_wait() {
+                Ok(Some(_)) => {}
+                _ => return false,
+            }
+        }
         let status = cmd.wait().unwrap();
         if !status.success() {
             eprintln!(
@@ -34,6 +40,7 @@ fn rustfmt(src: &Path, rustfmt: &Path, paths: &[PathBuf], check: bool) -> impl F
             );
             crate::detail_exit(1);
         }
+        true
     }
 }
 
@@ -146,15 +153,23 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) {
             let child = rustfmt(&src, &rustfmt_path, paths.as_slice(), check);
             children.push_back(child);
 
+            // poll completion before waiting
+            for i in (0..children.len()).rev() {
+                if children[i](false) {
+                    children.swap_remove_back(i);
+                    break;
+                }
+            }
+
             if children.len() >= max_processes {
                 // await oldest child
-                children.pop_front().unwrap()();
+                children.pop_front().unwrap()(true);
             }
         }
 
         // await remaining children
         for mut child in children {
-            child();
+            child(true);
         }
     });
 
index 7672b7c913594cb9ecc3f2c4f550cbe53e09278b..c53d0d7e4cb7c03964ec1f2364c6a7a2600cadfa 100644 (file)
@@ -205,6 +205,12 @@ fn run($sel, $builder: &Builder<'_>) {
             .expect("missing miri");
         install_sh(builder, "miri", self.compiler.stage, Some(self.target), &tarball);
     };
+    LlvmTools, alias = "llvm-tools", Self::should_build(_config), only_hosts: true, {
+        let tarball = builder
+            .ensure(dist::LlvmTools { target: self.target })
+            .expect("missing llvm-tools");
+        install_sh(builder, "llvm-tools", self.compiler.stage, Some(self.target), &tarball);
+    };
     Rustfmt, alias = "rustfmt", Self::should_build(_config), only_hosts: true, {
         if let Some(tarball) = builder.ensure(dist::Rustfmt {
             compiler: self.compiler,
index 3ed53452309c76a54d0c11eec05cfb28b8d39447..47fb4a38d05be381e074f199401b03c7b1de9db4 100644 (file)
 use std::env;
 use std::fs::{self, File};
 use std::io;
+use std::io::ErrorKind;
 use std::path::{Path, PathBuf};
 use std::process::Command;
 use std::str;
 
 use crate::builder::Kind;
 use crate::config::{LlvmLibunwind, TargetSelection};
-use crate::util::{exe, libdir, mtime, output, run, run_suppressed, try_run_suppressed, CiEnv};
+use crate::util::{
+    exe, libdir, mtime, output, run, run_suppressed, symlink_dir, try_run_suppressed, CiEnv,
+};
 
 mod bolt;
 mod builder;
@@ -586,6 +589,20 @@ pub fn new(mut config: Config) -> Build {
             metadata::build(&mut build);
         }
 
+        // Make a symbolic link so we can use a consistent directory in the documentation.
+        let build_triple = build.out.join(&build.build.triple);
+        let host = build.out.join("host");
+        if let Err(e) = symlink_dir(&build.config, &build_triple, &host) {
+            if e.kind() != ErrorKind::AlreadyExists {
+                panic!(
+                    "symlink_dir({} => {}) failed with {}",
+                    host.display(),
+                    build_triple.display(),
+                    e
+                );
+            }
+        }
+
         build
     }
 
@@ -713,10 +730,6 @@ pub fn build(&mut self) {
             return clean::clean(self, all);
         }
 
-        if let Subcommand::Setup { profile } = &self.config.cmd {
-            return setup::setup(&self.config, *profile);
-        }
-
         // Download rustfmt early so that it can be used in rust-analyzer configs.
         let _ = &builder::Builder::new(&self).initial_rustfmt();
 
@@ -1639,10 +1652,10 @@ fn chmod(_path: &Path, _perms: u32) {}
 /// If the test is running and code is an error code, it will cause a panic.
 fn detail_exit(code: i32) -> ! {
     // if in test and code is an error code, panic with status code provided
-    if cfg!(test) && code != 0 {
+    if cfg!(test) {
         panic!("status code: {}", code);
     } else {
-        //otherwise,exit with provided status code
+        // otherwise,exit with provided status code
         std::process::exit(code);
     }
 }
index c7f98a7d0d149ae28c21ad6dadb109034e9bbff6..57426ce3d51094b259f863addc6a3509e098befb 100644 (file)
@@ -1,3 +1,4 @@
+use crate::builder::{Builder, RunConfig, ShouldRun, Step};
 use crate::Config;
 use crate::{t, VERSION};
 use std::env::consts::EXE_SUFFIX;
@@ -9,7 +10,7 @@
 use std::str::FromStr;
 use std::{fmt, fs, io};
 
-#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
 pub enum Profile {
     Compiler,
     Codegen,
@@ -48,6 +49,16 @@ pub fn all_for_help(indent: &str) -> String {
         }
         out
     }
+
+    pub fn as_str(&self) -> &'static str {
+        match self {
+            Profile::Compiler => "compiler",
+            Profile::Codegen => "codegen",
+            Profile::Library => "library",
+            Profile::Tools => "tools",
+            Profile::User => "user",
+        }
+    }
 }
 
 impl FromStr for Profile {
@@ -69,24 +80,58 @@ fn from_str(s: &str) -> Result<Self, Self::Err> {
 
 impl fmt::Display for Profile {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            Profile::Compiler => write!(f, "compiler"),
-            Profile::Codegen => write!(f, "codegen"),
-            Profile::Library => write!(f, "library"),
-            Profile::User => write!(f, "user"),
-            Profile::Tools => write!(f, "tools"),
+        f.write_str(self.as_str())
+    }
+}
+
+impl Step for Profile {
+    type Output = ();
+    const DEFAULT: bool = true;
+
+    fn should_run(mut run: ShouldRun<'_>) -> ShouldRun<'_> {
+        for choice in Profile::all() {
+            run = run.alias(choice.as_str());
         }
+        run
+    }
+
+    fn make_run(run: RunConfig<'_>) {
+        // for Profile, `run.paths` will have 1 and only 1 element
+        // this is because we only accept at most 1 path from user input.
+        // If user calls `x.py setup` without arguments, the interactive TUI
+        // will guide user to provide one.
+        let profile = if run.paths.len() > 1 {
+            // HACK: `builder` runs this step with all paths if no path was passed.
+            t!(interactive_path())
+        } else {
+            run.paths
+                .first()
+                .unwrap()
+                .assert_single_path()
+                .path
+                .as_path()
+                .as_os_str()
+                .to_str()
+                .unwrap()
+                .parse()
+                .unwrap()
+        };
+
+        run.builder.ensure(profile);
+    }
+
+    fn run(self, builder: &Builder<'_>) {
+        setup(&builder.build.config, self)
     }
 }
 
-pub fn setup(config: &Config, profile: Option<Profile>) {
-    let profile = profile.unwrap_or_else(|| t!(interactive_path()));
+pub fn setup(config: &Config, profile: Profile) {
     let stage_path =
         ["build", config.build.rustc_target_arg(), "stage1"].join(&MAIN_SEPARATOR.to_string());
 
     if !rustup_installed() && profile != Profile::User {
         eprintln!("`rustup` is not installed; cannot link `stage1` toolchain");
-    } else if stage_dir_exists(&stage_path[..]) {
+    } else if stage_dir_exists(&stage_path[..]) && !config.dry_run() {
         attempt_toolchain_link(&stage_path[..]);
     }
 
@@ -104,7 +149,9 @@ pub fn setup(config: &Config, profile: Option<Profile>) {
         Profile::User => &["dist", "build"],
     };
 
-    t!(install_git_hook_maybe(&config));
+    if !config.dry_run() {
+        t!(install_git_hook_maybe(&config));
+    }
 
     println!();
 
@@ -144,6 +191,7 @@ fn setup_config_toml(path: &PathBuf, profile: Profile, config: &Config) {
     changelog-seen = {}\n",
         profile, VERSION
     );
+
     t!(fs::write(path, settings));
 
     let include_path = profile.include_path(&config.src);
index e0be4c432f168baceeb1a32666d3a1c482d94e90..24b033cc0dc5eb4f6e63104efc065a507d35a114 100644 (file)
@@ -747,19 +747,9 @@ impl Step for RustAnalyzerProcMacroSrv {
     const ONLY_HOSTS: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        let builder = run.builder;
-
         // Allow building `rust-analyzer-proc-macro-srv` both as part of the `rust-analyzer` and as a stand-alone tool.
         run.path("src/tools/rust-analyzer")
             .path("src/tools/rust-analyzer/crates/proc-macro-srv-cli")
-            .default_condition(
-                builder.config.extended
-                    && builder.config.tools.as_ref().map_or(true, |tools| {
-                        tools.iter().any(|tool| {
-                            tool == "rust-analyzer" || tool == "rust-analyzer-proc-macro-srv"
-                        })
-                    }),
-            )
     }
 
     fn make_run(run: RunConfig<'_>) {
index 9a290edd561cc7a6eccb1dd7fd01cb77f67a4f52..6b7b32a8bc77f85c4a7eb5b84892d9b5cbfae844 100644 (file)
@@ -24,5 +24,5 @@ ENV \
 
 ENV HOSTS=powerpc64le-unknown-linux-gnu
 
-ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs
+ENV RUST_CONFIGURE_ARGS --enable-extended --enable-profiler --disable-docs
 ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
index 40caa7c50135d31dae92b8331501572436f874dd..9e2568af13f689d07688c03881cfd33cdbbd9f82 100644 (file)
@@ -40,13 +40,13 @@ COPY host-x86_64/mingw-check/validate-error-codes.sh /scripts/
 
 ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1
 ENV SCRIPT python3 ../x.py --stage 2 test src/tools/expand-yaml-anchors && \
+           python3 ../x.py test --stage 0 src/tools/tidy && \
            python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu --all-targets && \
            python3 ../x.py build --stage 0 src/tools/build-manifest && \
            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 && \
            # Build both public and internal documentation.
-           RUSTDOCFLAGS="--document-private-items" python3 ../x.py doc --stage 0 library/test && \
+           RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc --stage 0 library/test && \
            /scripts/validate-toolstate.sh && \
            /scripts/validate-error-codes.sh && \
            reuse lint && \
index c3b47c3510d46fef2fc0071f43a709140f72cc83..06f15bd121174eb5a195056bf12e75bfab390775 100644 (file)
@@ -25,7 +25,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   zlib1g-dev \
   xz-utils \
   nodejs \
-
+  \
 # Install powershell so we can test x.ps1 on Linux
     apt-transport-https software-properties-common && \
     curl -s "https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb" > packages-microsoft-prod.deb && \
index 501d27816462aace153eb6ecc578210fa681018d..58c0c5db1a5d613a962e15ec93002e0e13b0a0bc 100644 (file)
@@ -15,7 +15,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   sudo \
   xz-utils \
   tidy \
-
+  \
 # Install dependencies for chromium browser
   gconf-service \
   libasound2 \
index a2708d16947f0c92ed302106fba70382792eee2f..3e86339859dd360528d5ff6719286f58ae407a8d 100755 (executable)
@@ -346,7 +346,7 @@ class TestEnvironment:
                 "-f",
                 self.ssh_keyfile_path(),
                 "-C",
-                "Generated by test_toolchain.py",
+                "Generated by fuchsia-test-runner.py",
             ],
             stdout=self.subprocess_output(),
             stderr=self.subprocess_output(),
index 75e44fe49874a7cca91f1f2590f80b9ad1893a08..5a0397a3d123cf714bb63dbf40b4a87a9ae9f69a 100644 (file)
@@ -667,6 +667,7 @@ jobs:
                 --target=x86_64-pc-windows-msvc
                 --enable-full-tools
                 --enable-profiler
+                --set rust.lto=thin
               SCRIPT: PGO_HOST=x86_64-pc-windows-msvc src/ci/pgo.sh python x.py dist bootstrap --include-default-paths
               DIST_REQUIRE_ALL_TOOLS: 1
             <<: *job-windows-xl
index 7de06ec35c36bba75da44543d567f7603835341b..f05bb81d4a1e3b31ba260b357e237911979d8f17 100755 (executable)
@@ -56,6 +56,7 @@ fi
 if ! isCI || isCiBranch auto || isCiBranch beta || isCiBranch try || isCiBranch try-perf; then
     RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.print-step-timings --enable-verbose-tests"
     RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.metrics"
+    HAS_METRICS=1
 fi
 
 RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-sccache"
@@ -157,13 +158,6 @@ trap datecheck EXIT
 # sccache server at the start of the build, but no need to worry if this fails.
 SCCACHE_IDLE_TIMEOUT=10800 sccache --start-server || true
 
-if [ "$RUN_CHECK_WITH_PARALLEL_QUERIES" != "" ]; then
-  $SRC/configure --set rust.parallel-compiler
-  CARGO_INCREMENTAL=0 $PYTHON ../x.py check
-  rm -f config.toml
-  rm -rf build
-fi
-
 $SRC/configure $RUST_CONFIGURE_ARGS
 
 retry make prepare
@@ -193,4 +187,21 @@ else
   do_make "$RUST_CHECK_TARGET"
 fi
 
+if [ "$RUN_CHECK_WITH_PARALLEL_QUERIES" != "" ]; then
+  rm -f config.toml
+  $SRC/configure --set rust.parallel-compiler
+
+  # Save the build metrics before we wipe the directory
+  if [ $HAS_METRICS = 1 ]; then
+    mv build/metrics.json .
+  fi
+  rm -rf build
+  if [ $HAS_METRICS = 1 ]; then
+    mkdir build
+    mv metrics.json build
+  fi
+
+  CARGO_INCREMENTAL=0 $PYTHON ../x.py check
+fi
+
 sccache --show-stats || true
index ef6eee75f1ce6c2cdc4d0ed83e43144e60bb68de..d4d26654ed114fa7cb3bc3ff3302500838d54ccf 100644 (file)
@@ -434,6 +434,9 @@ replacement is purely textual, with no consideration of the current system's
 pathname syntax. For example `--remap-path-prefix foo=bar` will match
 `foo/lib.rs` but not `./foo/lib.rs`.
 
+When multiple remappings are given and several of them match, the **last**
+matching one is applied.
+
 <a id="option-json"></a>
 ## `--json`: configure json messages printed by the compiler
 
index fa38dd54d60c89bc7730daa6c20b1c501df0d6df..98b49e07171c20c39fcfb11ff004576b34634b20 100644 (file)
@@ -217,7 +217,7 @@ It is recommended that explicit wrapping methods such as `wrapping_add` be
 used when wrapping semantics are intended, and that explicit checking and
 wrapping methods always be used when using Unsafe Rust.
 
-<small id="fn:2">2\. See <https://doc.rust-lang.org/std/primitive.u32.html>
+<small id="fn:2">2\. See [the `u32` docs](../std/primitive.u32.html)
 for more information on the checked, overflowing, saturating, and wrapping
 methods (using u32 as an example). <a href="#fnref:2"
 class="reversefootnote" role="doc-backlink">↩</a></small>
@@ -575,17 +575,17 @@ defaults (unrelated to `READ_IMPLIES_EXEC`).
    <https://hacks.mozilla.org/2019/02/fearless-security-thread-safety/>.
 
 3. S. Klabnik and C. Nichols. “What Is Ownership?.” The Rust Programming
-   Language. <https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html>.
+   Language. [https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html](../book/ch04-01-what-is-ownership.html).
 
 4. S. Klabnik and C. Nichols. “References and Borrowing.” The Rust
    Programming Language.
-   <https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html>.
+   [https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html](../book/ch04-02-references-and-borrowing.html).
 
 5. S. Klabnik and C. Nichols. “The Slice Type.” The Rust Programming
-   Language. <https://doc.rust-lang.org/book/ch04-03-slices.html>.
+   Language. [https://doc.rust-lang.org/book/ch04-03-slices.html](../book/ch04-03-slices.html).
 
 6. S. Klabnik and C. Nichols. “Unsafe Rust.” The Rust Programming Language.
-   <https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html>.
+   [https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html](../book/ch19-01-unsafe-rust.html).
 
 7. S. Davidoff. “How Rust’s standard library was vulnerable for years and
    nobody noticed.” Medium.
@@ -696,4 +696,4 @@ defaults (unrelated to `READ_IMPLIES_EXEC`).
     for Rust #89653.” GitHub. <https://github.com/rust-lang/rust/issues/89653>.
 
 41. “ControlFlowIntegrity.” The Rust Unstable Book.
-    <https://doc.rust-lang.org/beta/unstable-book/compiler-flags/sanitizer.html#controlflowintegrity>.
+    [https://doc.rust-lang.org/unstable-book/compiler-flags/sanitizer.html#controlflowintegrity](../unstable-book/compiler-flags/sanitizer.html#controlflowintegrity).
index 9272b9ac9b2d45be95b2278b97dc36b0b5c00446..858b7bc79c4c86f12e9b82a0008b285319ab7bb8 100644 (file)
@@ -112,7 +112,7 @@ targeting Windows-like targets
 This is fixed if you explicitly set the target, for example
 `cargo build --target x86_64-pc-windows-msvc`
 Without an explicit --target the flags will be passed to all compiler invocations (including build
-scripts and proc macros), see [cargo docs on rustflags](https://doc.rust-lang.org/cargo/reference/config.html#buildrustflags)
+scripts and proc macros), see [cargo docs on rustflags](../cargo/reference/config.html#buildrustflags)
 
 If you have dependencies using the `cc` crate, you will need to set these
 environment variables:
index b2c8e5d4df73601d1113e88c15e8ad41f5d3595b..e351cfaf89c2c985bb645c13d8394766a65419d8 100644 (file)
@@ -42,4 +42,4 @@ edition of the [Android NDK].  Supported Android targets are:
 [Android NDK]: https://developer.android.com/ndk/downloads
 
 A list of all supported targets can be found
-[here](https://doc.rust-lang.org/rustc/platform-support.html)
+[here](../platform-support.html)
index 215290e389843d9279e5049c3269506ab1d4ac9f..2ce0ccb78769c8a2acdcd3343de4deef94ee3f2a 100644 (file)
@@ -111,7 +111,7 @@ to an SD card to be inserted in the device.
 The `cargo-3ds` tool mentioned in [Building Rust programs](#building-rust-programs)
 supports the use of `3dslink` with `cargo 3ds run`. The default Rust test runner
 is not supported, but
-[custom test frameworks](https://doc.rust-lang.org/beta/unstable-book/language-features/custom-test-frameworks.html)
+[custom test frameworks](../../unstable-book/language-features/custom-test-frameworks.html)
 can be used with `cargo 3ds test` to run unit tests on a device.
 
 The Rust test suite for `library/std` is not yet supported.
index fbf999f97151b3e8169a90a5ed476159c6fd601d..cc4ee2e67b14eb7610c7bd9e6b4bbf140c334bb5 100644 (file)
@@ -90,7 +90,7 @@ rustup target add aarch64-fuchsia
 After installing our Fuchsia targets, we can now compile a Rust binary that targets
 Fuchsia.
 
-To create our Rust project, we can issue a standard `cargo` command as follows:
+To create our Rust project, we can use [`cargo`][cargo] as follows:
 
 **From base working directory**
 ```sh
@@ -867,7 +867,7 @@ ${SDK_PATH}/tools/${ARCH}/ffx debug connect -- \
 [Fuchsia]: https://fuchsia.dev/
 [source tree]: https://fuchsia.dev/fuchsia-src/get-started/learn/build
 [rustup]: https://rustup.rs/
-[cargo]: https://doc.rust-lang.org/cargo/
+[cargo]: ../../cargo/index.html
 [Fuchsia SDK]: https://chrome-infra-packages.appspot.com/p/fuchsia/sdk/core
 [overview of CML]: https://fuchsia.dev/fuchsia-src/concepts/components/v2/component_manifests
 [reference for the file format]: https://fuchsia.dev/reference/cml
index 27ef2f49eee58611d6516bf90887d440141d2e85..a67cb10fc75a8b8b9d277ab50f7b4cb6acd52cd1 100644 (file)
@@ -14,4 +14,4 @@ To see it for a different target, add the `--target` flag:
 rustc +nightly -Z unstable-options --target=wasm32-unknown-unknown --print target-spec-json
 ```
 
-To use a custom target, see the (unstable) [`build-std` feature](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std) of `cargo`.
+To use a custom target, see the (unstable) [`build-std` feature](../../cargo/reference/unstable.html#build-std) of `cargo`.
index 85403748e1dcdab014366fea01034f98adf508d2..ca5664835f26fbf55a8b5b352c67da799f82806a 100644 (file)
@@ -1,7 +1,7 @@
 # `branch-protection`
 
 This option lets you enable branch authentication instructions on AArch64.
-This option is ignored for non-AArch64 architectures.
+This option is only accepted when targeting AArch64 architectures.
 It takes some combination of the following values, separated by a `,`.
 
 - `pac-ret` - Enable pointer authentication for non-leaf functions.
@@ -15,4 +15,4 @@ For example, `-Z branch-protection=bti,pac-ret,leaf` is valid, but
 
 Rust's standard library does not ship with BTI or pointer authentication enabled by default.
 In Cargo projects the standard library can be recompiled with pointer authentication using the nightly
-[build-std](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std) feature.
+[build-std](../../cargo/reference/unstable.html#build-std) feature.
index 08c16d95f4670bce556395f3d8e53b5cbb4dc4ab..dbb741422a87508534ddbb9507a4baba26326c15 100644 (file)
@@ -39,7 +39,7 @@ It is strongly recommended to also enable CFG checks for all linked libraries, i
 
 To enable CFG in the standard library, use the [cargo `-Z build-std` functionality][build-std] to recompile the standard library with the same configuration options as the main program.
 
-[build-std]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std
+[build-std]: ../../cargo/reference/unstable.html#build-std
 
 For example:
 ```cmd
index b33405f18e90bcc2c92672cdaecfdc0df869a78b..a9616c34bffcb6be02e464c0b8f915c1b7cc1319 100644 (file)
@@ -14,6 +14,9 @@ This feature allows for use of one of following sanitizers:
   forward-edge control flow protection.
 * [HWAddressSanitizer](#hwaddresssanitizer) a memory error detector similar to
   AddressSanitizer, but based on partial hardware assistance.
+* [KernelControlFlowIntegrity](#kernelcontrolflowintegrity) LLVM Kernel Control
+  Flow Integrity (KCFI) provides forward-edge control flow protection for
+  operating systems kernels.
 * [LeakSanitizer](#leaksanitizer) a run-time memory leak detector.
 * [MemorySanitizer](#memorysanitizer) a detector of uninitialized reads.
 * [MemTagSanitizer](#memtagsanitizer) fast memory error detector based on
@@ -417,8 +420,8 @@ flow using an indirect branch/call to a function with different return and
 parameter types than the return type expected and arguments intended/passed in
 the call/branch site, the execution is also terminated (see Fig. 9).
 
-[rust-book-ch19-05]: https://doc.rust-lang.org/book/ch19-05-advanced-functions-and-closures.html
-[rust-book]: https://doc.rust-lang.org/book/title-page.html
+[rust-book-ch19-05]: ../../book/ch19-05-advanced-functions-and-closures.html
+[rust-book]: ../../book/title-page.html
 
 # HWAddressSanitizer
 
@@ -502,6 +505,32 @@ Registers where the failure occurred (pc 0xaaaae0ae4a98):
 SUMMARY: HWAddressSanitizer: tag-mismatch (/.../main+0x54a94)
 ```
 
+# KernelControlFlowIntegrity
+
+The LLVM Kernel Control Flow Integrity (CFI) support to the Rust compiler
+initially provides forward-edge control flow protection for operating systems
+kernels for Rust-compiled code only by aggregating function pointers in groups
+identified by their return and parameter types. (See [LLVM commit cff5bef "KCFI
+sanitizer"](https://github.com/llvm/llvm-project/commit/cff5bef948c91e4919de8a5fb9765e0edc13f3de).)
+
+Forward-edge control flow protection for C or C++ and Rust -compiled code "mixed
+binaries" (i.e., for when C or C++ and Rust -compiled code share the same
+virtual address space) will be provided in later work by defining and using
+compatible type identifiers (see Type metadata in the design document in the
+tracking issue [#89653](https://github.com/rust-lang/rust/issues/89653)).
+
+LLVM KCFI can be enabled with `-Zsanitizer=kcfi`.
+
+LLVM KCFI is supported on the following targets:
+
+* `aarch64-linux-android`
+* `aarch64-unknown-linux-gnu`
+* `x86_64-linux-android`
+* `x86_64-unknown-linux-gnu`
+
+See the [Clang KernelControlFlowIntegrity documentation][clang-kcfi] for more
+details.
+
 # LeakSanitizer
 
 LeakSanitizer is run-time memory leak detector.
@@ -662,7 +691,7 @@ It is strongly recommended to combine sanitizers with recompiled and
 instrumented standard library, for example using [cargo `-Zbuild-std`
 functionality][build-std].
 
-[build-std]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std
+[build-std]: ../../cargo/reference/unstable.html#build-std
 
 # Build scripts and procedural macros
 
@@ -693,6 +722,7 @@ Sanitizers produce symbolized stacktraces when llvm-symbolizer binary is in `PAT
 [clang-asan]: https://clang.llvm.org/docs/AddressSanitizer.html
 [clang-cfi]: https://clang.llvm.org/docs/ControlFlowIntegrity.html
 [clang-hwasan]: https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html
+[clang-kcfi]: https://clang.llvm.org/docs/ControlFlowIntegrity.html#fsanitize-kcfi
 [clang-lsan]: https://clang.llvm.org/docs/LeakSanitizer.html
 [clang-msan]: https://clang.llvm.org/docs/MemorySanitizer.html
 [clang-scs]: https://clang.llvm.org/docs/ShadowCallStack.html
index c6516d838ddc8d99bc6c6b9a3446dd0f92442091..5cb9758409a778af004c5430c5f9f38b5003dbb9 100644 (file)
@@ -36,4 +36,4 @@ optimized out, if unused. However, with `make_foo` you can produce a wrapped
 to inlining of `f`, `Foo::foo` can then be called from a foreign crate. This can
 lead to miscompilations.
 
-[Clto]: https://doc.rust-lang.org/rustc/codegen-options/index.html#lto
+[Clto]: ../../rustc/codegen-options/index.html#lto
index f967c11fc4d0895e637e36041bc0271dc3ce7b06..014e15d1ada6833d828961f1e5879cf333611a96 100644 (file)
@@ -13,8 +13,8 @@ that are automatically implemented for every type, unless the type, or a type it
 has explicitly opted out via a negative impl. (Negative impls are separately controlled
 by the `negative_impls` feature.)
 
-[`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html
-[`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
+[`Send`]: ../../std/marker/trait.Send.html
+[`Sync`]: ../../std/marker/trait.Sync.html
 
 ```rust,ignore (partial-example)
 impl !Trait for Type {}
index e4113d72d0914823d1835a8d2a6e8d38d43c11c7..3609e7f52f800ed63680af1095508341dc4266ce 100644 (file)
@@ -12,7 +12,7 @@ The `unboxed_closures` feature allows you to write functions using the `"rust-ca
 required for implementing the [`Fn*`] family of traits. `"rust-call"` functions must have
 exactly one (non self) argument, a tuple representing the argument list.
 
-[`Fn*`]: https://doc.rust-lang.org/std/ops/trait.Fn.html
+[`Fn*`]: ../../std/ops/trait.Fn.html
 
 ```rust
 #![feature(unboxed_closures)]
index d40a27dddf362537a684669241b17ff0656afd84..bafc9ac4d0d966d0743389c1e7466a9624acf99b 100644 (file)
@@ -10,7 +10,7 @@ Adds a free `default()` function to the `std::default` module.  This function
 just forwards to [`Default::default()`], but may remove repetition of the word
 "default" from the call site.
 
-[`Default::default()`]: https://doc.rust-lang.org/nightly/std/default/trait.Default.html#tymethod.default
+[`Default::default()`]: ../../std/default/trait.Default.html#tymethod.default
 
 Here is an example:
 
index 29a8aecee6c2fd26e5420a2c06640823e01b99fa..180184146d1a0506053dab9425b361ee8133e84b 100644 (file)
@@ -11,7 +11,7 @@ See Also: [`unboxed_closures`](../language-features/unboxed-closures.md)
 The `fn_traits` feature allows for implementation of the [`Fn*`] traits
 for creating custom closure-like types.
 
-[`Fn*`]: https://doc.rust-lang.org/std/ops/trait.Fn.html
+[`Fn*`]: ../../std/ops/trait.Fn.html
 
 ```rust
 #![feature(unboxed_closures)]
index 953f4aa8a1b482137f4f24d4cd9447ed84b76c25..4d6f1524732f77453e2ce2489cd3eee1b6f848e8 100644 (file)
@@ -44,7 +44,7 @@ fn generate_for_trait(
         discard_positive_impl: bool,
     ) -> Option<Item> {
         let tcx = self.cx.tcx;
-        let trait_ref = tcx.mk_trait_ref(trait_def_id, [ty]);
+        let trait_ref = ty::Binder::dummy(tcx.mk_trait_ref(trait_def_id, [ty]));
         if !self.cx.generated_synthetics.insert((ty, trait_def_id)) {
             debug!("get_auto_trait_impl_for({:?}): already generated, aborting", trait_ref);
             return None;
@@ -124,7 +124,7 @@ fn generate_for_trait(
                 unsafety: hir::Unsafety::Normal,
                 generics: new_generics,
                 trait_: Some(clean_trait_ref_with_bindings(self.cx, trait_ref, ThinVec::new())),
-                for_: clean_middle_ty(ty, self.cx, None),
+                for_: clean_middle_ty(ty::Binder::dummy(ty), self.cx, None),
                 items: Vec::new(),
                 polarity,
                 kind: ImplKind::Auto,
index a1145b90d6580c7da0f996dbd4d9420eff7d5d7b..4ef5747596bb39a7d4900a393c216f84626f3447 100644 (file)
@@ -105,10 +105,10 @@ pub(crate) fn get_blanket_impls(&mut self, item_def_id: DefId) -> Vec<Item> {
                         // the post-inference `trait_ref`, as it's more accurate.
                         trait_: Some(clean_trait_ref_with_bindings(
                             cx,
-                            trait_ref.0,
+                            ty::Binder::dummy(trait_ref.0),
                             ThinVec::new(),
                         )),
-                        for_: clean_middle_ty(ty.0, cx, None),
+                        for_: clean_middle_ty(ty::Binder::dummy(ty.0), cx, None),
                         items: cx
                             .tcx
                             .associated_items(impl_def_id)
@@ -117,7 +117,7 @@ pub(crate) fn get_blanket_impls(&mut self, item_def_id: DefId) -> Vec<Item> {
                             .collect::<Vec<_>>(),
                         polarity: ty::ImplPolarity::Positive,
                         kind: ImplKind::Blanket(Box::new(clean_middle_ty(
-                            trait_ref.0.self_ty(),
+                            ty::Binder::dummy(trait_ref.0.self_ty()),
                             cx,
                             None,
                         ))),
index 7f72d5d39a75283bc061e15796bca6f723a09a24..81f6767243683eb9fb26909ec5eaece2502db971 100644 (file)
@@ -1,9 +1,8 @@
 use super::*;
 
-use rustc_ast::attr;
-use rustc_ast::Path;
+use rustc_ast::{LitKind, MetaItemLit, Path, StrStyle};
 use rustc_span::create_default_session_globals_then;
-use rustc_span::symbol::{Ident, Symbol};
+use rustc_span::symbol::{kw, Ident, Symbol};
 use rustc_span::DUMMY_SP;
 
 fn word_cfg(s: &str) -> Cfg {
@@ -22,6 +21,15 @@ fn dummy_meta_item_word(name: &str) -> MetaItem {
     }
 }
 
+fn dummy_meta_item_name_value(name: &str, symbol: Symbol, kind: LitKind) -> MetaItem {
+    let lit = MetaItemLit { symbol, suffix: None, kind, span: DUMMY_SP };
+    MetaItem {
+        path: Path::from_ident(Ident::from_str(name)),
+        kind: MetaItemKind::NameValue(lit),
+        span: DUMMY_SP,
+    }
+}
+
 macro_rules! dummy_meta_item_list {
     ($name:ident, [$($list:ident),* $(,)?]) => {
         MetaItem {
@@ -242,8 +250,8 @@ fn test_parse_ok() {
         let mi = dummy_meta_item_word("all");
         assert_eq!(Cfg::parse(&mi), Ok(word_cfg("all")));
 
-        let mi =
-            attr::mk_name_value_item_str(Ident::from_str("all"), Symbol::intern("done"), DUMMY_SP);
+        let done = Symbol::intern("done");
+        let mi = dummy_meta_item_name_value("all", done, LitKind::Str(done, StrStyle::Cooked));
         assert_eq!(Cfg::parse(&mi), Ok(name_value_cfg("all", "done")));
 
         let mi = dummy_meta_item_list!(all, [a, b]);
@@ -272,7 +280,7 @@ fn test_parse_ok() {
 #[test]
 fn test_parse_err() {
     create_default_session_globals_then(|| {
-        let mi = attr::mk_name_value_item(Ident::from_str("foo"), LitKind::Bool(false), DUMMY_SP);
+        let mi = dummy_meta_item_name_value("foo", kw::False, LitKind::Bool(false));
         assert!(Cfg::parse(&mi).is_err());
 
         let mi = dummy_meta_item_list!(not, [a, b]);
index e7c3e5a45e8387f079015a7db93c30212ca8075f..d1601272af7596e709ab607294aa430b953ca4c0 100644 (file)
@@ -293,7 +293,7 @@ fn build_union(cx: &mut DocContext<'_>, did: DefId) -> clean::Union {
 
 fn build_type_alias(cx: &mut DocContext<'_>, did: DefId) -> Box<clean::Typedef> {
     let predicates = cx.tcx.explicit_predicates_of(did);
-    let type_ = clean_middle_ty(cx.tcx.type_of(did), cx, Some(did));
+    let type_ = clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(did)), cx, Some(did));
 
     Box::new(clean::Typedef {
         type_,
@@ -325,7 +325,7 @@ pub(crate) fn build_impls(
     // * https://github.com/rust-lang/rust/pull/99917 — where the feature got used
     // * https://github.com/rust-lang/rust/issues/53487 — overall tracking issue for Error
     if tcx.has_attr(did, sym::rustc_has_incoherent_inherent_impls) {
-        use rustc_middle::ty::fast_reject::SimplifiedTypeGen::*;
+        use rustc_middle::ty::fast_reject::SimplifiedType::*;
         let type_ =
             if tcx.is_trait(did) { TraitSimplifiedType(did) } else { AdtSimplifiedType(did) };
         for &did in tcx.incoherent_impls(type_) {
@@ -405,7 +405,7 @@ pub(crate) fn build_impl(
 
     let for_ = match &impl_item {
         Some(impl_) => clean_ty(impl_.self_ty, cx),
-        None => clean_middle_ty(tcx.type_of(did), cx, Some(did)),
+        None => clean_middle_ty(ty::Binder::dummy(tcx.type_of(did)), cx, Some(did)),
     };
 
     // Only inline impl if the implementing type is
@@ -496,7 +496,8 @@ pub(crate) fn build_impl(
         ),
     };
     let polarity = tcx.impl_polarity(did);
-    let trait_ = associated_trait.map(|t| clean_trait_ref_with_bindings(cx, t, ThinVec::new()));
+    let trait_ = associated_trait
+        .map(|t| clean_trait_ref_with_bindings(cx, ty::Binder::dummy(t), ThinVec::new()));
     if trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait() {
         super::build_deref_target_impls(cx, &trait_items, ret);
     }
@@ -640,14 +641,14 @@ pub(crate) fn print_inlined_const(tcx: TyCtxt<'_>, did: DefId) -> String {
 
 fn build_const(cx: &mut DocContext<'_>, def_id: DefId) -> clean::Constant {
     clean::Constant {
-        type_: clean_middle_ty(cx.tcx.type_of(def_id), cx, Some(def_id)),
+        type_: clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(def_id)), cx, Some(def_id)),
         kind: clean::ConstantKind::Extern { def_id },
     }
 }
 
 fn build_static(cx: &mut DocContext<'_>, did: DefId, mutable: bool) -> clean::Static {
     clean::Static {
-        type_: clean_middle_ty(cx.tcx.type_of(did), cx, Some(did)),
+        type_: clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(did)), cx, Some(did)),
         mutability: if mutable { Mutability::Mut } else { Mutability::Not },
         expr: None,
     }
index 2a2a9470d25c0ee4da19badf253f0207a6dcdda7..92886bbfe26b4e5d03953f9eb3362bfe03bd3ae9 100644 (file)
@@ -22,6 +22,7 @@
 use rustc_middle::middle::resolve_lifetime as rl;
 use rustc_middle::ty::fold::TypeFolder;
 use rustc_middle::ty::InternalSubsts;
+use rustc_middle::ty::TypeVisitable;
 use rustc_middle::ty::{self, AdtKind, DefIdTree, EarlyBinder, Ty, TyCtxt};
 use rustc_middle::{bug, span_bug};
 use rustc_span::hygiene::{AstPass, MacroKind};
@@ -127,7 +128,7 @@ fn clean_generic_bound<'tcx>(
         hir::GenericBound::LangItemTrait(lang_item, span, _, generic_args) => {
             let def_id = cx.tcx.require_lang_item(lang_item, Some(span));
 
-            let trait_ref = ty::TraitRef::identity(cx.tcx, def_id).skip_binder();
+            let trait_ref = ty::TraitRef::identity(cx.tcx, def_id);
 
             let generic_args = clean_generic_args(generic_args, cx);
             let GenericArgs::AngleBracketed { bindings, .. } = generic_args
@@ -156,17 +157,18 @@ fn clean_generic_bound<'tcx>(
 
 pub(crate) fn clean_trait_ref_with_bindings<'tcx>(
     cx: &mut DocContext<'tcx>,
-    trait_ref: ty::TraitRef<'tcx>,
+    trait_ref: ty::PolyTraitRef<'tcx>,
     bindings: ThinVec<TypeBinding>,
 ) -> Path {
-    let kind = cx.tcx.def_kind(trait_ref.def_id).into();
+    let kind = cx.tcx.def_kind(trait_ref.def_id()).into();
     if !matches!(kind, ItemType::Trait | ItemType::TraitAlias) {
-        span_bug!(cx.tcx.def_span(trait_ref.def_id), "`TraitRef` had unexpected kind {:?}", kind);
+        span_bug!(cx.tcx.def_span(trait_ref.def_id()), "`TraitRef` had unexpected kind {:?}", kind);
     }
-    inline::record_extern_fqn(cx, trait_ref.def_id, kind);
-    let path = external_path(cx, trait_ref.def_id, true, bindings, trait_ref.substs);
+    inline::record_extern_fqn(cx, trait_ref.def_id(), kind);
+    let path =
+        external_path(cx, trait_ref.def_id(), true, bindings, trait_ref.map_bound(|tr| tr.substs));
 
-    debug!("ty::TraitRef\n  subst: {:?}\n", trait_ref.substs);
+    debug!(?trait_ref);
 
     path
 }
@@ -187,7 +189,7 @@ fn clean_poly_trait_ref_with_bindings<'tcx>(
         })
         .collect();
 
-    let trait_ = clean_trait_ref_with_bindings(cx, poly_trait_ref.skip_binder(), bindings);
+    let trait_ = clean_trait_ref_with_bindings(cx, poly_trait_ref, bindings);
     GenericBound::TraitBound(
         PolyTrait { trait_, generic_params: late_bound_regions },
         hir::TraitBoundModifier::None,
@@ -212,19 +214,19 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) ->
 pub(crate) fn clean_const<'tcx>(constant: &hir::ConstArg, cx: &mut DocContext<'tcx>) -> Constant {
     let def_id = cx.tcx.hir().body_owner_def_id(constant.value.body).to_def_id();
     Constant {
-        type_: clean_middle_ty(cx.tcx.type_of(def_id), cx, Some(def_id)),
+        type_: clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(def_id)), cx, Some(def_id)),
         kind: ConstantKind::Anonymous { body: constant.value.body },
     }
 }
 
 pub(crate) fn clean_middle_const<'tcx>(
-    constant: ty::Const<'tcx>,
+    constant: ty::Binder<'tcx, ty::Const<'tcx>>,
     cx: &mut DocContext<'tcx>,
 ) -> Constant {
     // FIXME: instead of storing the stringified expression, store `self` directly instead.
     Constant {
-        type_: clean_middle_ty(constant.ty(), cx, None),
-        kind: ConstantKind::TyConst { expr: constant.to_string().into() },
+        type_: clean_middle_ty(constant.map_bound(|c| c.ty()), cx, None),
+        kind: ConstantKind::TyConst { expr: constant.skip_binder().to_string().into() },
     }
 }
 
@@ -333,7 +335,7 @@ fn clean_poly_trait_predicate<'tcx>(
 
     let poly_trait_ref = pred.map_bound(|pred| pred.trait_ref);
     Some(WherePredicate::BoundPredicate {
-        ty: clean_middle_ty(poly_trait_ref.skip_binder().self_ty(), cx, None),
+        ty: clean_middle_ty(poly_trait_ref.self_ty(), cx, None),
         bounds: vec![clean_poly_trait_ref_with_bindings(cx, poly_trait_ref, ThinVec::new())],
         bound_params: Vec::new(),
     })
@@ -359,7 +361,7 @@ fn clean_type_outlives_predicate<'tcx>(
     let ty::OutlivesPredicate(ty, lt) = pred;
 
     Some(WherePredicate::BoundPredicate {
-        ty: clean_middle_ty(ty, cx, None),
+        ty: clean_middle_ty(ty::Binder::dummy(ty), cx, None),
         bounds: vec![GenericBound::Outlives(
             clean_middle_region(lt).expect("failed to clean lifetimes"),
         )],
@@ -367,10 +369,13 @@ fn clean_type_outlives_predicate<'tcx>(
     })
 }
 
-fn clean_middle_term<'tcx>(term: ty::Term<'tcx>, cx: &mut DocContext<'tcx>) -> Term {
-    match term.unpack() {
-        ty::TermKind::Ty(ty) => Term::Type(clean_middle_ty(ty, cx, None)),
-        ty::TermKind::Const(c) => Term::Constant(clean_middle_const(c, cx)),
+fn clean_middle_term<'tcx>(
+    term: ty::Binder<'tcx, ty::Term<'tcx>>,
+    cx: &mut DocContext<'tcx>,
+) -> Term {
+    match term.skip_binder().unpack() {
+        ty::TermKind::Ty(ty) => Term::Type(clean_middle_ty(term.rebind(ty), cx, None)),
+        ty::TermKind::Const(c) => Term::Constant(clean_middle_const(term.rebind(c), cx)),
     }
 }
 
@@ -379,7 +384,10 @@ fn clean_hir_term<'tcx>(term: &hir::Term<'tcx>, cx: &mut DocContext<'tcx>) -> Te
         hir::Term::Ty(ty) => Term::Type(clean_ty(ty, cx)),
         hir::Term::Const(c) => {
             let def_id = cx.tcx.hir().local_def_id(c.hir_id);
-            Term::Constant(clean_middle_const(ty::Const::from_anon_const(cx.tcx, def_id), cx))
+            Term::Constant(clean_middle_const(
+                ty::Binder::dummy(ty::Const::from_anon_const(cx.tcx, def_id)),
+                cx,
+            ))
         }
     }
 }
@@ -398,32 +406,31 @@ fn clean_projection_predicate<'tcx>(
         })
         .collect();
 
-    let ty::ProjectionPredicate { projection_ty, term } = pred.skip_binder();
-
     WherePredicate::EqPredicate {
-        lhs: Box::new(clean_projection(projection_ty, cx, None)),
-        rhs: Box::new(clean_middle_term(term, cx)),
+        lhs: Box::new(clean_projection(pred.map_bound(|p| p.projection_ty), cx, None)),
+        rhs: Box::new(clean_middle_term(pred.map_bound(|p| p.term), cx)),
         bound_params: late_bound_regions,
     }
 }
 
 fn clean_projection<'tcx>(
-    ty: ty::ProjectionTy<'tcx>,
+    ty: ty::Binder<'tcx, ty::AliasTy<'tcx>>,
     cx: &mut DocContext<'tcx>,
     def_id: Option<DefId>,
 ) -> Type {
-    if cx.tcx.def_kind(ty.item_def_id) == DefKind::ImplTraitPlaceholder {
+    if cx.tcx.def_kind(ty.skip_binder().def_id) == DefKind::ImplTraitPlaceholder {
         let bounds = cx
             .tcx
-            .explicit_item_bounds(ty.item_def_id)
+            .explicit_item_bounds(ty.skip_binder().def_id)
             .iter()
-            .map(|(bound, _)| EarlyBinder(*bound).subst(cx.tcx, ty.substs))
+            .map(|(bound, _)| EarlyBinder(*bound).subst(cx.tcx, ty.skip_binder().substs))
             .collect::<Vec<_>>();
         return clean_middle_opaque_bounds(cx, bounds);
     }
 
-    let trait_ = clean_trait_ref_with_bindings(cx, ty.trait_ref(cx.tcx), ThinVec::new());
-    let self_type = clean_middle_ty(ty.self_ty(), cx, None);
+    let trait_ =
+        clean_trait_ref_with_bindings(cx, ty.map_bound(|ty| ty.trait_ref(cx.tcx)), ThinVec::new());
+    let self_type = clean_middle_ty(ty.map_bound(|ty| ty.self_ty()), cx, None);
     let self_def_id = if let Some(def_id) = def_id {
         cx.tcx.opt_parent(def_id).or(Some(def_id))
     } else {
@@ -446,15 +453,16 @@ fn compute_should_show_cast(self_def_id: Option<DefId>, trait_: &Path, self_type
 }
 
 fn projection_to_path_segment<'tcx>(
-    ty: ty::ProjectionTy<'tcx>,
+    ty: ty::Binder<'tcx, ty::AliasTy<'tcx>>,
     cx: &mut DocContext<'tcx>,
 ) -> PathSegment {
-    let item = cx.tcx.associated_item(ty.item_def_id);
-    let generics = cx.tcx.generics_of(ty.item_def_id);
+    let item = cx.tcx.associated_item(ty.skip_binder().def_id);
+    let generics = cx.tcx.generics_of(ty.skip_binder().def_id);
     PathSegment {
         name: item.name,
         args: GenericArgs::AngleBracketed {
-            args: substs_to_args(cx, &ty.substs[generics.parent_count..], false).into(),
+            args: substs_to_args(cx, ty.map_bound(|ty| &ty.substs[generics.parent_count..]), false)
+                .into(),
             bindings: Default::default(),
         },
     }
@@ -470,7 +478,11 @@ fn clean_generic_param_def<'tcx>(
         }
         ty::GenericParamDefKind::Type { has_default, synthetic, .. } => {
             let default = if has_default {
-                Some(clean_middle_ty(cx.tcx.type_of(def.def_id), cx, Some(def.def_id)))
+                Some(clean_middle_ty(
+                    ty::Binder::dummy(cx.tcx.type_of(def.def_id)),
+                    cx,
+                    Some(def.def_id),
+                ))
             } else {
                 None
             };
@@ -488,7 +500,11 @@ fn clean_generic_param_def<'tcx>(
             def.name,
             GenericParamDefKind::Const {
                 did: def.def_id,
-                ty: Box::new(clean_middle_ty(cx.tcx.type_of(def.def_id), cx, Some(def.def_id))),
+                ty: Box::new(clean_middle_ty(
+                    ty::Binder::dummy(cx.tcx.type_of(def.def_id)),
+                    cx,
+                    Some(def.def_id),
+                )),
                 default: match has_default {
                     true => Some(Box::new(cx.tcx.const_param_default(def.def_id).to_string())),
                     false => None,
@@ -733,8 +749,10 @@ fn clean_ty_generics<'tcx>(
         .collect::<ThinVec<GenericParamDef>>();
 
     // param index -> [(trait DefId, associated type name & generics, type, higher-ranked params)]
-    let mut impl_trait_proj =
-        FxHashMap::<u32, Vec<(DefId, PathSegment, Ty<'_>, Vec<GenericParamDef>)>>::default();
+    let mut impl_trait_proj = FxHashMap::<
+        u32,
+        Vec<(DefId, PathSegment, ty::Binder<'_, Ty<'_>>, Vec<GenericParamDef>)>,
+    >::default();
 
     let where_predicates = preds
         .predicates
@@ -783,8 +801,8 @@ fn clean_ty_generics<'tcx>(
 
                     let proj = projection.map(|p| {
                         (
-                            clean_projection(p.skip_binder().projection_ty, cx, None),
-                            p.skip_binder().term,
+                            clean_projection(p.map_bound(|p| p.projection_ty), cx, None),
+                            p.map_bound(|p| p.term),
                         )
                     });
                     if let Some(((_, trait_did, name), rhs)) = proj
@@ -795,7 +813,7 @@ fn clean_ty_generics<'tcx>(
                         impl_trait_proj.entry(param_idx).or_default().push((
                             trait_did,
                             name,
-                            rhs.ty().unwrap(),
+                            rhs.map_bound(|rhs| rhs.ty().unwrap()),
                             p.get_bound_params()
                                 .into_iter()
                                 .flatten()
@@ -1066,7 +1084,7 @@ fn clean_fn_decl_from_did_and_sig<'tcx>(
 
     // We assume all empty tuples are default return type. This theoretically can discard `-> ()`,
     // but shouldn't change any code meaning.
-    let output = match clean_middle_ty(sig.skip_binder().output(), cx, None) {
+    let output = match clean_middle_ty(sig.output(), cx, None) {
         Type::Tuple(inner) if inner.is_empty() => DefaultReturn,
         ty => Return(ty),
     };
@@ -1076,11 +1094,10 @@ fn clean_fn_decl_from_did_and_sig<'tcx>(
         c_variadic: sig.skip_binder().c_variadic,
         inputs: Arguments {
             values: sig
-                .skip_binder()
                 .inputs()
                 .iter()
                 .map(|t| Argument {
-                    type_: clean_middle_ty(*t, cx, None),
+                    type_: clean_middle_ty(t.map_bound(|t| *t), cx, None),
                     name: names
                         .next()
                         .map(|i| i.name)
@@ -1134,7 +1151,8 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext
             hir::TraitItemKind::Type(bounds, Some(default)) => {
                 let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx));
                 let bounds = bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect();
-                let item_type = clean_middle_ty(hir_ty_to_ty(cx.tcx, default), cx, None);
+                let item_type =
+                    clean_middle_ty(ty::Binder::dummy(hir_ty_to_ty(cx.tcx, default)), cx, None);
                 AssocTypeItem(
                     Box::new(Typedef {
                         type_: clean_ty(default, cx),
@@ -1173,7 +1191,8 @@ pub(crate) fn clean_impl_item<'tcx>(
             hir::ImplItemKind::Type(hir_ty) => {
                 let type_ = clean_ty(hir_ty, cx);
                 let generics = clean_generics(impl_.generics, cx);
-                let item_type = clean_middle_ty(hir_ty_to_ty(cx.tcx, hir_ty), cx, None);
+                let item_type =
+                    clean_middle_ty(ty::Binder::dummy(hir_ty_to_ty(cx.tcx, hir_ty)), cx, None);
                 AssocTypeItem(
                     Box::new(Typedef { type_, generics, item_type: Some(item_type) }),
                     Vec::new(),
@@ -1192,7 +1211,11 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
     let tcx = cx.tcx;
     let kind = match assoc_item.kind {
         ty::AssocKind::Const => {
-            let ty = clean_middle_ty(tcx.type_of(assoc_item.def_id), cx, Some(assoc_item.def_id));
+            let ty = clean_middle_ty(
+                ty::Binder::dummy(tcx.type_of(assoc_item.def_id)),
+                cx,
+                Some(assoc_item.def_id),
+            );
 
             let provided = match assoc_item.container {
                 ty::ImplContainer => true,
@@ -1375,7 +1398,7 @@ fn param_eq_arg(param: &GenericParamDef, arg: &GenericArg) -> bool {
                     AssocTypeItem(
                         Box::new(Typedef {
                             type_: clean_middle_ty(
-                                tcx.type_of(assoc_item.def_id),
+                                ty::Binder::dummy(tcx.type_of(assoc_item.def_id)),
                                 cx,
                                 Some(assoc_item.def_id),
                             ),
@@ -1393,7 +1416,7 @@ fn param_eq_arg(param: &GenericParamDef, arg: &GenericArg) -> bool {
                 AssocTypeItem(
                     Box::new(Typedef {
                         type_: clean_middle_ty(
-                            tcx.type_of(assoc_item.def_id),
+                            ty::Binder::dummy(tcx.type_of(assoc_item.def_id)),
                             cx,
                             Some(assoc_item.def_id),
                         ),
@@ -1437,8 +1460,11 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
         hir::QPath::Resolved(Some(qself), p) => {
             // Try to normalize `<X as Y>::T` to a type
             let ty = hir_ty_to_ty(cx.tcx, hir_ty);
-            if let Some(normalized_value) = normalize(cx, ty) {
-                return clean_middle_ty(normalized_value, cx, None);
+            // `hir_to_ty` can return projection types with escaping vars for GATs, e.g. `<() as Trait>::Gat<'_>`
+            if !ty.has_escaping_bound_vars() {
+                if let Some(normalized_value) = normalize(cx, ty::Binder::dummy(ty)) {
+                    return clean_middle_ty(normalized_value, cx, None);
+                }
             }
 
             let trait_segments = &p.segments[..p.segments.len() - 1];
@@ -1461,11 +1487,13 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
         hir::QPath::TypeRelative(qself, segment) => {
             let ty = hir_ty_to_ty(cx.tcx, hir_ty);
             let res = match ty.kind() {
-                ty::Projection(proj) => Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id),
+                ty::Alias(ty::Projection, proj) => {
+                    Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id)
+                }
                 // Rustdoc handles `ty::Error`s by turning them into `Type::Infer`s.
                 ty::Error(_) => return Type::Infer,
                 // Otherwise, this is an inherent associated type.
-                _ => return clean_middle_ty(ty, cx, None),
+                _ => return clean_middle_ty(ty::Binder::dummy(ty), cx, None),
             };
             let trait_ = clean_path(&hir::Path { span, res, segments: &[] }, cx);
             register_res(cx, trait_.res);
@@ -1632,7 +1660,10 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
 }
 
 /// Returns `None` if the type could not be normalized
-fn normalize<'tcx>(cx: &mut DocContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
+fn normalize<'tcx>(
+    cx: &mut DocContext<'tcx>,
+    ty: ty::Binder<'tcx, Ty<'tcx>>,
+) -> Option<ty::Binder<'tcx, Ty<'tcx>>> {
     // HACK: low-churn fix for #79459 while we wait for a trait normalization fix
     if !cx.tcx.sess.opts.unstable_opts.normalize_docs {
         return None;
@@ -1660,14 +1691,14 @@ fn normalize<'tcx>(cx: &mut DocContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>>
     }
 }
 
+#[instrument(level = "trace", skip(cx), ret)]
 pub(crate) fn clean_middle_ty<'tcx>(
-    ty: Ty<'tcx>,
+    bound_ty: ty::Binder<'tcx, Ty<'tcx>>,
     cx: &mut DocContext<'tcx>,
     def_id: Option<DefId>,
 ) -> Type {
-    trace!("cleaning type: {:?}", ty);
-    let ty = normalize(cx, ty).unwrap_or(ty);
-    match *ty.kind() {
+    let bound_ty = normalize(cx, bound_ty).unwrap_or(bound_ty);
+    match *bound_ty.skip_binder().kind() {
         ty::Never => Primitive(PrimitiveType::Never),
         ty::Bool => Primitive(PrimitiveType::Bool),
         ty::Char => Primitive(PrimitiveType::Char),
@@ -1675,20 +1706,23 @@ pub(crate) fn clean_middle_ty<'tcx>(
         ty::Uint(uint_ty) => Primitive(uint_ty.into()),
         ty::Float(float_ty) => Primitive(float_ty.into()),
         ty::Str => Primitive(PrimitiveType::Str),
-        ty::Slice(ty) => Slice(Box::new(clean_middle_ty(ty, cx, None))),
+        ty::Slice(ty) => Slice(Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None))),
         ty::Array(ty, mut n) => {
             n = n.eval(cx.tcx, ty::ParamEnv::reveal_all());
             let n = print_const(cx, n);
-            Array(Box::new(clean_middle_ty(ty, cx, None)), n.into())
+            Array(Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None)), n.into())
+        }
+        ty::RawPtr(mt) => {
+            RawPointer(mt.mutbl, Box::new(clean_middle_ty(bound_ty.rebind(mt.ty), cx, None)))
         }
-        ty::RawPtr(mt) => RawPointer(mt.mutbl, Box::new(clean_middle_ty(mt.ty, cx, None))),
         ty::Ref(r, ty, mutbl) => BorrowedRef {
             lifetime: clean_middle_region(r),
             mutability: mutbl,
-            type_: Box::new(clean_middle_ty(ty, cx, None)),
+            type_: Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None)),
         },
         ty::FnDef(..) | ty::FnPtr(_) => {
-            let sig = ty.fn_sig(cx.tcx);
+            // FIXME: should we merge the outer and inner binders somehow?
+            let sig = bound_ty.skip_binder().fn_sig(cx.tcx);
             let decl = clean_fn_decl_from_did_and_sig(cx, None, sig);
             BareFunction(Box::new(BareFunctionDecl {
                 unsafety: sig.unsafety(),
@@ -1705,12 +1739,18 @@ pub(crate) fn clean_middle_ty<'tcx>(
                 AdtKind::Enum => ItemType::Enum,
             };
             inline::record_extern_fqn(cx, did, kind);
-            let path = external_path(cx, did, false, ThinVec::new(), substs);
+            let path = external_path(cx, did, false, ThinVec::new(), bound_ty.rebind(substs));
             Type::Path { path }
         }
         ty::Foreign(did) => {
             inline::record_extern_fqn(cx, did, ItemType::ForeignType);
-            let path = external_path(cx, did, false, ThinVec::new(), InternalSubsts::empty());
+            let path = external_path(
+                cx,
+                did,
+                false,
+                ThinVec::new(),
+                ty::Binder::dummy(InternalSubsts::empty()),
+            );
             Type::Path { path }
         }
         ty::Dynamic(obj, ref reg, _) => {
@@ -1721,11 +1761,11 @@ pub(crate) fn clean_middle_ty<'tcx>(
             let did = obj
                 .principal_def_id()
                 .or_else(|| dids.next())
-                .unwrap_or_else(|| panic!("found trait object `{:?}` with no traits?", ty));
+                .unwrap_or_else(|| panic!("found trait object `{bound_ty:?}` with no traits?"));
             let substs = match obj.principal() {
-                Some(principal) => principal.skip_binder().substs,
+                Some(principal) => principal.map_bound(|p| p.substs),
                 // marker traits have no substs.
-                _ => cx.tcx.intern_substs(&[]),
+                _ => ty::Binder::dummy(InternalSubsts::empty()),
             };
 
             inline::record_extern_fqn(cx, did, ItemType::Trait);
@@ -1736,7 +1776,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
             let lifetime = clean_middle_region(*reg);
             let mut bounds = dids
                 .map(|did| {
-                    let empty = cx.tcx.intern_substs(&[]);
+                    let empty = ty::Binder::dummy(InternalSubsts::empty());
                     let path = external_path(cx, did, false, ThinVec::new(), empty);
                     inline::record_extern_fqn(cx, did, ItemType::Trait);
                     PolyTrait { trait_: path, generic_params: Vec::new() }
@@ -1747,15 +1787,17 @@ pub(crate) fn clean_middle_ty<'tcx>(
                 .projection_bounds()
                 .map(|pb| TypeBinding {
                     assoc: projection_to_path_segment(
-                        pb.skip_binder()
-                            // HACK(compiler-errors): Doesn't actually matter what self
-                            // type we put here, because we're only using the GAT's substs.
-                            .with_self_ty(cx.tcx, cx.tcx.types.self_param)
-                            .projection_ty,
+                        pb.map_bound(|pb| {
+                            pb
+                                // HACK(compiler-errors): Doesn't actually matter what self
+                                // type we put here, because we're only using the GAT's substs.
+                                .with_self_ty(cx.tcx, cx.tcx.types.self_param)
+                                .projection_ty
+                        }),
                         cx,
                     ),
                     kind: TypeBindingKind::Equality {
-                        term: clean_middle_term(pb.skip_binder().term, cx),
+                        term: clean_middle_term(pb.map_bound(|pb| pb.term), cx),
                     },
                 })
                 .collect();
@@ -1779,9 +1821,11 @@ pub(crate) fn clean_middle_ty<'tcx>(
 
             DynTrait(bounds, lifetime)
         }
-        ty::Tuple(t) => Tuple(t.iter().map(|t| clean_middle_ty(t, cx, None)).collect()),
+        ty::Tuple(t) => {
+            Tuple(t.iter().map(|t| clean_middle_ty(bound_ty.rebind(t), cx, None)).collect())
+        }
 
-        ty::Projection(ref data) => clean_projection(*data, cx, def_id),
+        ty::Alias(ty::Projection, ref data) => clean_projection(bound_ty.rebind(*data), cx, def_id),
 
         ty::Param(ref p) => {
             if let Some(bounds) = cx.impl_trait_bounds.remove(&p.index.into()) {
@@ -1791,7 +1835,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
             }
         }
 
-        ty::Opaque(def_id, substs) => {
+        ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
             // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
             // by looking up the bounds associated with the def_id.
             let bounds = cx
@@ -1854,9 +1898,12 @@ fn clean_middle_opaque_bounds<'tcx>(
                     {
                         if proj.projection_ty.trait_ref(cx.tcx) == trait_ref.skip_binder() {
                             Some(TypeBinding {
-                                assoc: projection_to_path_segment(proj.projection_ty, cx),
+                                assoc: projection_to_path_segment(
+                                    bound.kind().rebind(proj.projection_ty),
+                                    cx,
+                                ),
                                 kind: TypeBindingKind::Equality {
-                                    term: clean_middle_term(proj.term, cx),
+                                    term: clean_middle_term(bound.kind().rebind(proj.term), cx),
                                 },
                             })
                         } else {
@@ -1887,7 +1934,7 @@ pub(crate) fn clean_middle_field<'tcx>(field: &ty::FieldDef, cx: &mut DocContext
     clean_field_with_def_id(
         field.did,
         field.name,
-        clean_middle_ty(cx.tcx.type_of(field.did), cx, Some(field.did)),
+        clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(field.did)), cx, Some(field.did)),
         cx,
     )
 }
@@ -2100,7 +2147,7 @@ fn clean_maybe_renamed_item<'tcx>(
             }),
             ItemKind::TyAlias(hir_ty, generics) => {
                 let rustdoc_ty = clean_ty(hir_ty, cx);
-                let ty = clean_middle_ty(hir_ty_to_ty(cx.tcx, hir_ty), cx, None);
+                let ty = clean_middle_ty(ty::Binder::dummy(hir_ty_to_ty(cx.tcx, hir_ty)), cx, None);
                 TypedefItem(Box::new(Typedef {
                     type_: rustdoc_ty,
                     generics: clean_generics(generics, cx),
@@ -2211,7 +2258,9 @@ fn clean_impl<'tcx>(
 
     let for_ = clean_ty(impl_.self_ty, cx);
     let type_alias = for_.def_id(&cx.cache).and_then(|did| match tcx.def_kind(did) {
-        DefKind::TyAlias => Some(clean_middle_ty(tcx.type_of(did), cx, Some(did))),
+        DefKind::TyAlias => {
+            Some(clean_middle_ty(ty::Binder::dummy(tcx.type_of(did)), cx, Some(did)))
+        }
         _ => None,
     });
     let mut make_item = |trait_: Option<Path>, for_: Type, items: Vec<Item>| {
index 2590bb0df3f0e62ef74c84ce9eab4b3922e2862b..7a13e7e36d169c3c50cb31561469381a9414b651 100644 (file)
@@ -10,7 +10,6 @@
 use arrayvec::ArrayVec;
 use thin_vec::ThinVec;
 
-use rustc_ast::attr;
 use rustc_ast::util::comments::beautify_doc_string;
 use rustc_ast::{self as ast, AttrStyle};
 use rustc_attr::{ConstStability, Deprecation, Stability, StabilityLevel};
@@ -27,7 +26,6 @@
 use rustc_middle::ty::{self, DefIdTree, TyCtxt, Visibility};
 use rustc_session::Session;
 use rustc_span::hygiene::MacroKind;
-use rustc_span::source_map::DUMMY_SP;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{self, FileName, Loc};
 use rustc_target::abi::VariantIdx;
@@ -982,12 +980,12 @@ fn single<T: IntoIterator>(it: T) -> Option<T::Item> {
         // #[doc(cfg(target_feature = "feat"))] attributes as well
         for attr in self.lists(sym::target_feature) {
             if attr.has_name(sym::enable) {
-                if let Some(feat) = attr.value_str() {
-                    let meta = attr::mk_name_value_item_str(
-                        Ident::with_dummy_span(sym::target_feature),
-                        feat,
-                        DUMMY_SP,
-                    );
+                if attr.value_str().is_some() {
+                    // Clone `enable = "feat"`, change to `target_feature = "feat"`.
+                    // Unwrap is safe because `value_str` succeeded above.
+                    let mut meta = attr.meta_item().unwrap().clone();
+                    meta.path = ast::Path::from_ident(Ident::with_dummy_span(sym::target_feature));
+
                     if let Ok(feat_cfg) = Cfg::parse(&meta) {
                         cfg &= feat_cfg;
                     }
@@ -1345,7 +1343,7 @@ pub(crate) enum GenericBound {
 impl GenericBound {
     pub(crate) fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
         let did = cx.tcx.require_lang_item(LangItem::Sized, None);
-        let empty = cx.tcx.intern_substs(&[]);
+        let empty = ty::Binder::dummy(ty::InternalSubsts::empty());
         let path = external_path(cx, did, false, ThinVec::new(), empty);
         inline::record_extern_fqn(cx, did, ItemType::Trait);
         GenericBound::TraitBound(
@@ -1872,7 +1870,7 @@ pub(crate) fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
     }
 
     pub(crate) fn simplified_types() -> &'static SimplifiedTypes {
-        use ty::fast_reject::SimplifiedTypeGen::*;
+        use ty::fast_reject::SimplifiedType::*;
         use ty::{FloatTy, IntTy, UintTy};
         use PrimitiveType::*;
         static CELL: OnceCell<SimplifiedTypes> = OnceCell::new();
index 246560bad291ffcc173fd72610030f1138951f75..a12f764fa8e3b739404df7937b83969a10e6bb8f 100644 (file)
@@ -78,12 +78,16 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate {
 
 pub(crate) fn substs_to_args<'tcx>(
     cx: &mut DocContext<'tcx>,
-    substs: &[ty::subst::GenericArg<'tcx>],
+    substs: ty::Binder<'tcx, &[ty::subst::GenericArg<'tcx>]>,
     mut skip_first: bool,
 ) -> Vec<GenericArg> {
     let mut ret_val =
-        Vec::with_capacity(substs.len().saturating_sub(if skip_first { 1 } else { 0 }));
-    ret_val.extend(substs.iter().filter_map(|kind| match kind.unpack() {
+        Vec::with_capacity(substs.skip_binder().len().saturating_sub(if skip_first {
+            1
+        } else {
+            0
+        }));
+    ret_val.extend(substs.iter().filter_map(|kind| match kind.skip_binder().unpack() {
         GenericArgKind::Lifetime(lt) => {
             Some(GenericArg::Lifetime(clean_middle_region(lt).unwrap_or(Lifetime::elided())))
         }
@@ -91,8 +95,12 @@ pub(crate) fn substs_to_args<'tcx>(
             skip_first = false;
             None
         }
-        GenericArgKind::Type(ty) => Some(GenericArg::Type(clean_middle_ty(ty, cx, None))),
-        GenericArgKind::Const(ct) => Some(GenericArg::Const(Box::new(clean_middle_const(ct, cx)))),
+        GenericArgKind::Type(ty) => {
+            Some(GenericArg::Type(clean_middle_ty(kind.rebind(ty), cx, None)))
+        }
+        GenericArgKind::Const(ct) => {
+            Some(GenericArg::Const(Box::new(clean_middle_const(kind.rebind(ct), cx))))
+        }
     }));
     ret_val
 }
@@ -102,15 +110,20 @@ fn external_generic_args<'tcx>(
     did: DefId,
     has_self: bool,
     bindings: ThinVec<TypeBinding>,
-    substs: SubstsRef<'tcx>,
+    substs: ty::Binder<'tcx, SubstsRef<'tcx>>,
 ) -> GenericArgs {
-    let args = substs_to_args(cx, substs, has_self);
+    let args = substs_to_args(cx, substs.map_bound(|substs| &substs[..]), has_self);
 
     if cx.tcx.fn_trait_kind_from_def_id(did).is_some() {
+        let ty = substs
+            .iter()
+            .nth(if has_self { 1 } else { 0 })
+            .unwrap()
+            .map_bound(|arg| arg.expect_ty());
         let inputs =
             // The trait's first substitution is the one after self, if there is one.
-            match substs.iter().nth(if has_self { 1 } else { 0 }).unwrap().expect_ty().kind() {
-                ty::Tuple(tys) => tys.iter().map(|t| clean_middle_ty(t, cx, None)).collect::<Vec<_>>().into(),
+            match ty.skip_binder().kind() {
+                ty::Tuple(tys) => tys.iter().map(|t| clean_middle_ty(ty.rebind(t), cx, None)).collect::<Vec<_>>().into(),
                 _ => return GenericArgs::AngleBracketed { args: args.into(), bindings },
             };
         let output = bindings.into_iter().next().and_then(|binding| match binding.kind {
@@ -130,7 +143,7 @@ pub(super) fn external_path<'tcx>(
     did: DefId,
     has_self: bool,
     bindings: ThinVec<TypeBinding>,
-    substs: SubstsRef<'tcx>,
+    substs: ty::Binder<'tcx, SubstsRef<'tcx>>,
 ) -> Path {
     let def_kind = cx.tcx.def_kind(did);
     let name = cx.tcx.item_name(did);
index e0cdb86d9d1dc152e47f97f85e5ea4456ed0f2ea..56b40d8c66baffa627ab03e1a9b83788b73d276d 100644 (file)
@@ -69,6 +69,8 @@ pub(crate) struct Options {
     pub(crate) input: PathBuf,
     /// The name of the crate being documented.
     pub(crate) crate_name: Option<String>,
+    /// Whether or not this is a bin crate
+    pub(crate) bin_crate: bool,
     /// Whether or not this is a proc-macro crate
     pub(crate) proc_macro_crate: bool,
     /// How to format errors and warnings.
@@ -176,6 +178,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("Options")
             .field("input", &self.input)
             .field("crate_name", &self.crate_name)
+            .field("bin_crate", &self.bin_crate)
             .field("proc_macro_crate", &self.proc_macro_crate)
             .field("error_format", &self.error_format)
             .field("libs", &self.libs)
@@ -667,6 +670,7 @@ fn println_condition(condition: Condition) {
             None => OutputFormat::default(),
         };
         let crate_name = matches.opt_str("crate-name");
+        let bin_crate = crate_types.contains(&CrateType::Executable);
         let proc_macro_crate = crate_types.contains(&CrateType::ProcMacro);
         let playground_url = matches.opt_str("playground-url");
         let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from);
@@ -718,6 +722,7 @@ fn println_condition(condition: Condition) {
             rustc_feature::UnstableFeatures::from_environment(crate_name.as_deref());
         let options = Options {
             input,
+            bin_crate,
             proc_macro_crate,
             error_format,
             diagnostic_width,
index f21e60a64e0055f87060c44de8b5b492866deb66..2f1f4cbf3592457e7972dc043e04e6b86f27c3ae 100644 (file)
@@ -177,6 +177,9 @@ pub(crate) fn as_str(&self) -> &'static str {
             ItemType::TraitAlias => "traitalias",
         }
     }
+    pub(crate) fn is_method(&self) -> bool {
+        matches!(*self, ItemType::Method | ItemType::TyMethod)
+    }
 }
 
 impl fmt::Display for ItemType {
index cd8c8c463b1ab60bafcaf15168de9dc1d6003362..8a9e6caf611bad111308874cd8bd3d7685cb130d 100644 (file)
 use super::format::{self, Buffer};
 
 /// This type is needed in case we want to render links on items to allow to go to their definition.
-pub(crate) struct HrefContext<'a, 'b, 'c> {
-    pub(crate) context: &'a Context<'b>,
+pub(crate) struct HrefContext<'a, 'tcx> {
+    pub(crate) context: &'a Context<'tcx>,
     /// This span contains the current file we're going through.
     pub(crate) file_span: Span,
     /// This field is used to know "how far" from the top of the directory we are to link to either
     /// documentation pages or other source pages.
-    pub(crate) root_path: &'c str,
+    pub(crate) root_path: &'a str,
     /// This field is used to calculate precise local URLs.
-    pub(crate) current_href: &'c str,
+    pub(crate) current_href: String,
 }
 
 /// Decorations are represented as a map from CSS class to vector of character ranges.
@@ -70,7 +70,7 @@ pub(crate) fn render_source_with_highlighting(
     src: &str,
     out: &mut Buffer,
     line_numbers: Buffer,
-    href_context: HrefContext<'_, '_, '_>,
+    href_context: HrefContext<'_, '_>,
     decoration_info: DecorationInfo,
     extra: Option<&str>,
 ) {
@@ -137,7 +137,7 @@ fn can_merge(class1: Option<Class>, class2: Option<Class>, text: &str) -> bool {
 
 /// This type is used as a conveniency to prevent having to pass all its fields as arguments into
 /// the various functions (which became its methods).
-struct TokenHandler<'a, 'b, 'c, 'd, 'e> {
+struct TokenHandler<'a, 'tcx> {
     out: &'a mut Buffer,
     /// It contains the closing tag and the associated `Class`.
     closing_tags: Vec<(&'static str, Class)>,
@@ -149,11 +149,11 @@ struct TokenHandler<'a, 'b, 'c, 'd, 'e> {
     current_class: Option<Class>,
     /// We need to keep the `Class` for each element because it could contain a `Span` which is
     /// used to generate links.
-    pending_elems: Vec<(&'b str, Option<Class>)>,
-    href_context: Option<HrefContext<'c, 'd, 'e>>,
+    pending_elems: Vec<(&'a str, Option<Class>)>,
+    href_context: Option<HrefContext<'a, 'tcx>>,
 }
 
-impl<'a, 'b, 'c, 'd, 'e> TokenHandler<'a, 'b, 'c, 'd, 'e> {
+impl<'a, 'tcx> TokenHandler<'a, 'tcx> {
     fn handle_exit_span(&mut self) {
         // We can't get the last `closing_tags` element using `pop()` because `closing_tags` is
         // being used in `write_pending_elems`.
@@ -205,7 +205,7 @@ fn write_pending_elems(&mut self, current_class: Option<Class>) -> bool {
     }
 }
 
-impl<'a, 'b, 'c, 'd, 'e> Drop for TokenHandler<'a, 'b, 'c, 'd, 'e> {
+impl<'a, 'tcx> Drop for TokenHandler<'a, 'tcx> {
     /// When leaving, we need to flush all pending data to not have missing content.
     fn drop(&mut self) {
         if self.pending_exit_span.is_some() {
@@ -230,7 +230,7 @@ fn drop(&mut self) {
 fn write_code(
     out: &mut Buffer,
     src: &str,
-    href_context: Option<HrefContext<'_, '_, '_>>,
+    href_context: Option<HrefContext<'_, '_>>,
     decoration_info: Option<DecorationInfo>,
 ) {
     // This replace allows to fix how the code source with DOS backline characters is displayed.
@@ -514,18 +514,18 @@ fn new(info: DecorationInfo) -> Self {
 
 /// Processes program tokens, classifying strings of text by highlighting
 /// category (`Class`).
-struct Classifier<'a> {
-    tokens: PeekIter<'a>,
+struct Classifier<'src> {
+    tokens: PeekIter<'src>,
     in_attribute: bool,
     in_macro: bool,
     in_macro_nonterminal: bool,
     byte_pos: u32,
     file_span: Span,
-    src: &'a str,
+    src: &'src str,
     decorations: Option<Decorations>,
 }
 
-impl<'a> Classifier<'a> {
+impl<'src> Classifier<'src> {
     /// Takes as argument the source code to HTML-ify, the rust edition to use and the source code
     /// file span which will be used later on by the `span_correspondance_map`.
     fn new(src: &str, file_span: Span, decoration_info: Option<DecorationInfo>) -> Classifier<'_> {
@@ -603,7 +603,7 @@ fn get_full_ident_path(&mut self) -> Vec<(TokenKind, usize, usize)> {
     ///
     /// It returns the token's kind, the token as a string and its byte position in the source
     /// string.
-    fn next(&mut self) -> Option<(TokenKind, &'a str, u32)> {
+    fn next(&mut self) -> Option<(TokenKind, &'src str, u32)> {
         if let Some((kind, text)) = self.tokens.next() {
             let before = self.byte_pos;
             self.byte_pos += text.len() as u32;
@@ -618,7 +618,7 @@ fn next(&mut self) -> Option<(TokenKind, &'a str, u32)> {
     /// The general structure for this method is to iterate over each token,
     /// possibly giving it an HTML span with a class specifying what flavor of
     /// token is used.
-    fn highlight(mut self, sink: &mut dyn FnMut(Highlight<'a>)) {
+    fn highlight(mut self, sink: &mut dyn FnMut(Highlight<'src>)) {
         loop {
             if let Some(decs) = self.decorations.as_mut() {
                 let byte_pos = self.byte_pos;
@@ -666,8 +666,8 @@ fn highlight(mut self, sink: &mut dyn FnMut(Highlight<'a>)) {
     fn advance(
         &mut self,
         token: TokenKind,
-        text: &'a str,
-        sink: &mut dyn FnMut(Highlight<'a>),
+        text: &'src str,
+        sink: &mut dyn FnMut(Highlight<'src>),
         before: u32,
     ) {
         let lookahead = self.peek();
@@ -881,7 +881,7 @@ fn check_if_is_union_keyword(&mut self) -> bool {
 fn enter_span(
     out: &mut Buffer,
     klass: Class,
-    href_context: &Option<HrefContext<'_, '_, '_>>,
+    href_context: &Option<HrefContext<'_, '_>>,
 ) -> &'static str {
     string_without_closing_tag(out, "", Some(klass), href_context, true).expect(
         "internal error: enter_span was called with Some(klass) but did not return a \
@@ -914,7 +914,7 @@ fn string<T: Display>(
     out: &mut Buffer,
     text: T,
     klass: Option<Class>,
-    href_context: &Option<HrefContext<'_, '_, '_>>,
+    href_context: &Option<HrefContext<'_, '_>>,
     open_tag: bool,
 ) {
     if let Some(closing_tag) = string_without_closing_tag(out, text, klass, href_context, open_tag)
@@ -936,7 +936,7 @@ fn string_without_closing_tag<T: Display>(
     out: &mut Buffer,
     text: T,
     klass: Option<Class>,
-    href_context: &Option<HrefContext<'_, '_, '_>>,
+    href_context: &Option<HrefContext<'_, '_>>,
     open_tag: bool,
 ) -> Option<&'static str> {
     let Some(klass) = klass
@@ -985,7 +985,7 @@ fn string_without_closing_tag<T: Display>(
                 // https://github.com/rust-lang/rust/blob/60f1a2fc4b535ead9c85ce085fdce49b1b097531/src/librustdoc/html/render/context.rs#L315-L338
                 match href {
                     LinkFromSrc::Local(span) => {
-                        context.href_from_span_relative(*span, href_context.current_href)
+                        context.href_from_span_relative(*span, &href_context.current_href)
                     }
                     LinkFromSrc::External(def_id) => {
                         format::href_with_root_path(*def_id, context, Some(href_context.root_path))
index 5ce62224d35e54130d87c5c1fcac24162c2578d9..aeaee524fd4532b820f130d04ccb7912ceb68411 100644 (file)
@@ -236,18 +236,16 @@ fn next(&mut self) -> Option<Self::Item> {
             return event;
         };
 
-        let mut origtext = String::new();
+        let mut original_text = String::new();
         for event in &mut self.inner {
             match event {
                 Event::End(Tag::CodeBlock(..)) => break,
                 Event::Text(ref s) => {
-                    origtext.push_str(s);
+                    original_text.push_str(s);
                 }
                 _ => {}
             }
         }
-        let lines = origtext.lines().filter_map(|l| map_line(l).for_html());
-        let text = lines.intersperse("\n".into()).collect::<String>();
 
         let parse_result = match kind {
             CodeBlockKind::Fenced(ref lang) => {
@@ -260,7 +258,7 @@ fn next(&mut self) -> Option<Self::Item> {
                                  <pre class=\"language-{}\"><code>{}</code></pre>\
                              </div>",
                             lang,
-                            Escape(&text),
+                            Escape(&original_text),
                         )
                         .into(),
                     ));
@@ -270,6 +268,9 @@ fn next(&mut self) -> Option<Self::Item> {
             CodeBlockKind::Indented => Default::default(),
         };
 
+        let lines = original_text.lines().filter_map(|l| map_line(l).for_html());
+        let text = lines.intersperse("\n".into()).collect::<String>();
+
         compile_fail = parse_result.compile_fail;
         should_panic = parse_result.should_panic;
         ignore = parse_result.ignore;
@@ -284,7 +285,7 @@ fn next(&mut self) -> Option<Self::Item> {
             if url.is_empty() {
                 return None;
             }
-            let test = origtext
+            let test = original_text
                 .lines()
                 .map(|l| map_line(l).for_code())
                 .intersperse("\n".into())
@@ -566,11 +567,12 @@ struct SummaryLine<'a, I: Iterator<Item = Event<'a>>> {
     inner: I,
     started: bool,
     depth: u32,
+    skipped_tags: u32,
 }
 
 impl<'a, I: Iterator<Item = Event<'a>>> SummaryLine<'a, I> {
     fn new(iter: I) -> Self {
-        SummaryLine { inner: iter, started: false, depth: 0 }
+        SummaryLine { inner: iter, started: false, depth: 0, skipped_tags: 0 }
     }
 }
 
@@ -600,6 +602,7 @@ fn next(&mut self) -> Option<Self::Item> {
             let is_allowed_tag = match event {
                 Event::Start(ref c) => {
                     if is_forbidden_tag(c) {
+                        self.skipped_tags += 1;
                         return None;
                     }
                     self.depth += 1;
@@ -607,6 +610,7 @@ fn next(&mut self) -> Option<Self::Item> {
                 }
                 Event::End(ref c) => {
                     if is_forbidden_tag(c) {
+                        self.skipped_tags += 1;
                         return None;
                     }
                     self.depth -= 1;
@@ -615,6 +619,9 @@ fn next(&mut self) -> Option<Self::Item> {
                 }
                 _ => true,
             };
+            if !is_allowed_tag {
+                self.skipped_tags += 1;
+            }
             return if !is_allowed_tag {
                 if is_start {
                     Some(Event::Start(Tag::Paragraph))
@@ -1095,11 +1102,11 @@ pub(crate) fn into_string(self) -> String {
 }
 
 impl MarkdownSummaryLine<'_> {
-    pub(crate) fn into_string(self) -> String {
+    pub(crate) fn into_string_with_has_more_content(self) -> (String, bool) {
         let MarkdownSummaryLine(md, links) = self;
         // This is actually common enough to special-case
         if md.is_empty() {
-            return String::new();
+            return (String::new(), false);
         }
 
         let mut replacer = |broken_link: BrokenLink<'_>| {
@@ -1109,17 +1116,26 @@ pub(crate) fn into_string(self) -> String {
                 .map(|link| (link.href.as_str().into(), link.new_text.as_str().into()))
         };
 
-        let p = Parser::new_with_broken_link_callback(md, summary_opts(), Some(&mut replacer));
+        let p = Parser::new_with_broken_link_callback(md, summary_opts(), Some(&mut replacer))
+            .peekable();
+        let mut summary = SummaryLine::new(p);
 
         let mut s = String::new();
 
-        let without_paragraphs = LinkReplacer::new(SummaryLine::new(p), links).filter(|event| {
+        let without_paragraphs = LinkReplacer::new(&mut summary, links).filter(|event| {
             !matches!(event, Event::Start(Tag::Paragraph) | Event::End(Tag::Paragraph))
         });
 
         html::push_html(&mut s, without_paragraphs);
 
-        s
+        let has_more_content =
+            matches!(summary.inner.peek(), Some(Event::Start(_))) || summary.skipped_tags > 0;
+
+        (s, has_more_content)
+    }
+
+    pub(crate) fn into_string(self) -> String {
+        self.into_string_with_has_more_content().0
     }
 }
 
index e4f72a057892f5ee1098859fecc557aae49df72a..5878c58264ec361f7c008a1165a6e43d9f0bae2e 100644 (file)
@@ -309,3 +309,48 @@ fn add_test(&mut self, _test: String, _config: LangString, line: usize) {
     t("```rust\n```\n```rust\n```", &[1, 3]);
     t("```rust\n```\n ```rust\n```", &[1, 3]);
 }
+
+#[test]
+fn test_ascii_with_prepending_hashtag() {
+    fn t(input: &str, expect: &str) {
+        let mut map = IdMap::new();
+        let output = Markdown {
+            content: input,
+            links: &[],
+            ids: &mut map,
+            error_codes: ErrorCodes::Yes,
+            edition: DEFAULT_EDITION,
+            playground: &None,
+            heading_offset: HeadingOffset::H2,
+        }
+        .into_string();
+        assert_eq!(output, expect, "original: {}", input);
+    }
+
+    t(
+        r#"```ascii
+#..#.####.#....#.....##..
+#..#.#....#....#....#..#.
+####.###..#....#....#..#.
+#..#.#....#....#....#..#.
+#..#.#....#....#....#..#.
+#..#.####.####.####..##..
+```"#,
+        "<div class=\"example-wrap\"><pre class=\"language-ascii\"><code>\
+#..#.####.#....#.....##..
+#..#.#....#....#....#..#.
+####.###..#....#....#..#.
+#..#.#....#....#....#..#.
+#..#.#....#....#....#..#.
+#..#.####.####.####..##..
+</code></pre></div>",
+    );
+    t(
+        r#"```markdown
+# hello
+```"#,
+        "<div class=\"example-wrap\"><pre class=\"language-markdown\"><code>\
+# hello
+</code></pre></div>",
+    );
+}
index 73690c86f4f72b97070c9c42718fe47022c2b468..d4d3e4f6ea7952c0399ca2c3e5066d361b222e64 100644 (file)
@@ -637,7 +637,7 @@ fn after_krate(&mut self) -> Result<(), Error> {
                             You need to enable Javascript be able to update your settings.\
                         </section>\
                      </noscript>\
-                     <link rel=\"stylesheet\" type=\"text/css\" \
+                     <link rel=\"stylesheet\" \
                          href=\"{static_root_path}{settings_css}\">\
                      <script defer src=\"{static_root_path}{settings_js}\"></script>",
                     static_root_path = page.get_static_root_path(),
index 08f8096b07bd66399ac9bda4b17f6f19d8fa56c7..146e5010e4e42827d7743a3ef2e73ae04d15f354 100644 (file)
@@ -467,9 +467,10 @@ fn document_short(
         return;
     }
     if let Some(s) = item.doc_value() {
-        let mut summary_html = MarkdownSummaryLine(&s, &item.links(cx)).into_string();
+        let (mut summary_html, has_more_content) =
+            MarkdownSummaryLine(&s, &item.links(cx)).into_string_with_has_more_content();
 
-        if s.contains('\n') {
+        if has_more_content {
             let link = format!(r#" <a{}>Read more</a>"#, assoc_href_attr(item, link, cx));
 
             if let Some(idx) = summary_html.rfind("</p>") {
@@ -1512,8 +1513,7 @@ fn doc_impl_item(
 
         let toggled = !doc_buffer.is_empty();
         if toggled {
-            let method_toggle_class =
-                if item_type == ItemType::Method { " method-toggle" } else { "" };
+            let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" };
             write!(w, "<details class=\"rustdoc-toggle{}\" open><summary>", method_toggle_class);
         }
         match &*item.kind {
@@ -2957,14 +2957,23 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite
 
     // The call locations are output in sequence, so that sequence needs to be determined.
     // Ideally the most "relevant" examples would be shown first, but there's no general algorithm
-    // for determining relevance. Instead, we prefer the smallest examples being likely the easiest to
-    // understand at a glance.
+    // for determining relevance. We instead proxy relevance with the following heuristics:
+    //   1. Code written to be an example is better than code not written to be an example, e.g.
+    //      a snippet from examples/foo.rs is better than src/lib.rs. We don't know the Cargo
+    //      directory structure in Rustdoc, so we proxy this by prioritizing code that comes from
+    //      a --crate-type bin.
+    //   2. Smaller examples are better than large examples. So we prioritize snippets that have
+    //      the smallest number of lines in their enclosing item.
+    //   3. Finally we sort by the displayed file name, which is arbitrary but prevents the
+    //      ordering of examples from randomly changing between Rustdoc invocations.
     let ordered_locations = {
-        let sort_criterion = |(_, call_data): &(_, &CallData)| {
+        fn sort_criterion<'a>(
+            (_, call_data): &(&PathBuf, &'a CallData),
+        ) -> (bool, u32, &'a String) {
             // Use the first location because that's what the user will see initially
             let (lo, hi) = call_data.locations[0].enclosing_item.byte_span;
-            hi - lo
-        };
+            (!call_data.is_bin, hi - lo, &call_data.display_name)
+        }
 
         let mut locs = call_locations.iter().collect::<Vec<_>>();
         locs.sort_by_key(sort_criterion);
index acbe3f22889cc03d10cf4f541477c8f6a2b9d8f7..a7b57c373e3bec3b4a9219758d8d020f2b1a0642 100644 (file)
@@ -732,7 +732,8 @@ fn trait_item(w: &mut Buffer, cx: &mut Context<'_>, m: &clean::Item, t: &clean::
         document(&mut content, cx, m, Some(t), HeadingOffset::H5);
         let toggled = !content.is_empty();
         if toggled {
-            write!(w, "<details class=\"rustdoc-toggle method-toggle\" open><summary>");
+            let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" };
+            write!(w, "<details class=\"rustdoc-toggle{method_toggle_class}\" open><summary>");
         }
         write!(w, "<section id=\"{}\" class=\"method has-srclink\">", id);
         render_rightside(w, cx, m, t, RenderMode::Normal);
index 54e296959b0ec97fb569a2210d1e0054cece775f..e639fadeb96733ddb5848e6ef9c677614eaaa5b0 100644 (file)
@@ -276,7 +276,7 @@ pub(crate) fn print_src(
     let mut line_numbers = Buffer::empty_from(buf);
     let extra;
     line_numbers.write_str("<pre class=\"src-line-numbers\">");
-    let current_href = &context
+    let current_href = context
         .href_from_span(clean::Span::new(file_span), false)
         .expect("only local crates should have sources emitted");
     match source_context {
index 5ebc545d10c2b0fa4ff67cc9938cbaa82e81add0..022ed606cc3b8b96718361ef59effac37de2fe56 100644 (file)
@@ -212,8 +212,7 @@ pre.rust a,
 .mobile-topbar h2 a,
 h1 a,
 .search-results a,
-.module-item .stab,
-.import-item .stab,
+.stab,
 .result-name .primitive > i, .result-name .keyword > i {
        color: var(--main-color);
 }
@@ -397,15 +396,15 @@ img {
        overflow-y: hidden;
 }
 
-.source .sidebar, #sidebar-toggle, #source-sidebar {
+.source .sidebar, #src-sidebar-toggle, #source-sidebar {
        background-color: var(--sidebar-background-color);
 }
 
-#sidebar-toggle > button:hover, #sidebar-toggle > button:focus {
+#src-sidebar-toggle > button:hover, #src-sidebar-toggle > button:focus {
        background-color: var(--sidebar-background-color-hover);
 }
 
-.source .sidebar > *:not(#sidebar-toggle) {
+.source .sidebar > *:not(#src-sidebar-toggle) {
        visibility: hidden;
 }
 
@@ -414,7 +413,7 @@ img {
        flex-basis: 300px;
 }
 
-.source-sidebar-expanded .source .sidebar > *:not(#sidebar-toggle) {
+.source-sidebar-expanded .source .sidebar > *:not(#src-sidebar-toggle) {
        visibility: visible;
 }
 
@@ -524,7 +523,6 @@ ul.block, .block li {
 }
 
 .source .content pre.rust {
-       overflow: auto;
        padding-left: 0;
 }
 
@@ -587,8 +585,8 @@ ul.block, .block li {
        text-overflow: ellipsis;
 }
 /* Wrap non-pre code blocks (`text`) but not (```text```). */
-.docblock :not(pre) > code,
-.docblock-short code {
+.docblock :not(pre) > code,
+.docblock-short code {
        white-space: pre-wrap;
 }
 
@@ -631,22 +629,16 @@ pre, .rustdoc.source .example-wrap {
 
 .docblock table {
        margin: .5em 0;
-       width: calc(100% - 2px);
-       overflow-x: auto;
-       display: block;
        border-collapse: collapse;
 }
 
-.docblock table td {
+.docblock table td, .docblock table th {
        padding: .5em;
-       border: 1px dashed var(--border-color);
-       vertical-align: top;
+       border: 1px solid var(--border-color);
 }
 
-.docblock table th {
-       padding: .5em;
-       text-align: left;
-       border: 1px solid var(--border-color);
+.docblock table tbody tr:nth-child(2n) {
+       background: var(--table-alt-row-background-color);
 }
 
 /* Shift "where ..." part of method or fn definition down a line */
@@ -910,10 +902,11 @@ so that we can apply CSS-filters to change the arrow color in themes */
        top: 100%;
        right: 0;
        z-index: 2;
-       display: block;
        margin-top: 7px;
        border-radius: 3px;
        border: 1px solid var(--border-color);
+       background-color: var(--main-background-color);
+       color: var(--main-color);
        --popover-arrow-offset: 11px;
 }
 
@@ -924,16 +917,12 @@ so that we can apply CSS-filters to change the arrow color in themes */
        right: var(--popover-arrow-offset);
        border: solid var(--border-color);
        border-width: 1px 1px 0 0;
+       background-color: var(--main-background-color);
        padding: 4px;
        transform: rotate(-45deg);
        top: -5px;
 }
 
-.popover, .popover::before {
-       background-color: var(--main-background-color);
-       color: var(--main-color);
-}
-
 /* use larger max-width for help popover, but not for help.html */
 #help.popover {
        max-width: 600px;
@@ -967,22 +956,29 @@ so that we can apply CSS-filters to change the arrow color in themes */
 }
 
 .item-info .stab {
-       width: fit-content;
        /* This min-height is needed to unify the height of the stab elements because some of them
           have emojis.
        */
        min-height: 36px;
        display: flex;
-       align-items: center;
-       white-space: pre-wrap;
-}
-.stab {
        padding: 3px;
        margin-bottom: 5px;
+}
+.item-left .stab {
+       margin-left: 0.3125em;
+}
+.stab {
+       padding: 0 2px;
        font-size: 0.875rem;
        font-weight: normal;
        color: var(--main-color);
        background-color: var(--stab-background-color);
+       width: fit-content;
+       align-items: center;
+       white-space: pre-wrap;
+       border-radius: 3px;
+       display: inline-flex;
+       vertical-align: text-bottom;
 }
 
 .stab.portability > code {
@@ -995,12 +991,6 @@ so that we can apply CSS-filters to change the arrow color in themes */
        margin-right: 0.3rem;
 }
 
-/* This is to prevent the `.stab` elements to overflow the .docblock elements. */
-.docblock .stab {
-       padding: 0 0.125em;
-       margin-bottom: 0;
-}
-
 /* Black one-pixel outline around emoji shapes */
 .emoji {
        text-shadow:
@@ -1010,17 +1000,6 @@ so that we can apply CSS-filters to change the arrow color in themes */
                0 -1px 0 black;
 }
 
-.module-item .stab,
-.import-item .stab {
-       border-radius: 3px;
-       display: inline-block;
-       line-height: 1.2;
-       margin-bottom: 0;
-       margin-left: 0.3125em;
-       padding: 2px;
-       vertical-align: text-bottom;
-}
-
 .module-item.unstable,
 .import-item.unstable {
        opacity: 0.65;
@@ -1092,6 +1071,10 @@ pre.rust .doccomment {
        color: var(--code-highlight-doc-comment-color);
 }
 
+.rustdoc.source .example-wrap pre.rust a {
+       background: var(--codeblock-link-background);
+}
+
 .example-wrap.compile_fail,
 .example-wrap.should_panic {
        border-left: 2px solid var(--codeblock-error-color);
@@ -1135,8 +1118,7 @@ pre.rust .doccomment {
        top: 5px;
 }
 
-.example-wrap .tooltip::after {
-       display: none;
+.example-wrap .tooltip:hover::after {
        text-align: center;
        padding: 5px 3px 3px 3px;
        border-radius: 6px;
@@ -1151,35 +1133,30 @@ pre.rust .doccomment {
        color: var(--tooltip-color);
 }
 
-.example-wrap .tooltip::before {
+.example-wrap .tooltip:hover::before {
        content: " ";
        position: absolute;
        top: 50%;
        left: 16px;
        margin-top: -5px;
-       display: none;
        z-index: 1;
        border: 5px solid transparent;
        border-right-color: var(--tooltip-background-color);
 }
 
-.example-wrap.ignore .tooltip::after {
+.example-wrap.ignore .tooltip:hover::after {
        content: "This example is not tested";
 }
-.example-wrap.compile_fail .tooltip::after {
+.example-wrap.compile_fail .tooltip:hover::after {
        content: "This example deliberately fails to compile";
 }
-.example-wrap.should_panic .tooltip::after {
+.example-wrap.should_panic .tooltip:hover::after {
        content: "This example panics";
 }
-.example-wrap.edition .tooltip::after {
+.example-wrap.edition .tooltip:hover::after {
        content: "This code runs with edition " attr(data-edition);
 }
 
-.example-wrap .tooltip:hover::before, .example-wrap .tooltip:hover::after {
-       display: inline;
-}
-
 .example-wrap.compile_fail .tooltip,
 .example-wrap.should_panic .tooltip,
 .example-wrap.ignore .tooltip {
@@ -1312,7 +1289,7 @@ a.test-arrow:hover {
        font-size: 1rem;
 }
 
-#sidebar-toggle {
+#src-sidebar-toggle {
        position: sticky;
        top: 0;
        left: 0;
@@ -1341,7 +1318,7 @@ a.test-arrow:hover {
 #source-sidebar div.files > a.selected {
        background-color: var(--source-sidebar-background-selected);
 }
-#sidebar-toggle > button {
+#src-sidebar-toggle > button {
        font-size: inherit;
        font-weight: bold;
        background: none;
@@ -1417,7 +1394,6 @@ kbd {
        vertical-align: middle;
        border: solid 1px var(--border-color);
        border-radius: 3px;
-       cursor: default;
        color: var(--kbd--color);
        background-color: var(--kbd-background);
        box-shadow: inset 0 -1px 0 var(--kbd-box-shadow-color);
@@ -1744,13 +1720,12 @@ in storage.js
                left: -11px;
        }
 
-       #sidebar-toggle {
+       #src-sidebar-toggle {
                position: fixed;
                left: 1px;
                top: 100px;
                width: 30px;
                font-size: 1.5rem;
-               text-align: center;
                padding: 0;
                z-index: 10;
                border-top-right-radius: 3px;
@@ -1759,7 +1734,7 @@ in storage.js
                border-left: 0;
        }
 
-       .source-sidebar-expanded #sidebar-toggle {
+       .source-sidebar-expanded #src-sidebar-toggle {
                left: unset;
                top: unset;
                width: unset;
@@ -1815,6 +1790,22 @@ in storage.js
        }
 }
 
+/* Should have min-width: (N + 1)px where N is the mobile breakpoint above. */
+@media (min-width: 701px) {
+       /* Places file-link for a scraped example on top of the example to save space.
+          We only do this on large screens so the file-link doesn't overlap too much
+                with the example's content. */
+       .scraped-example-title {
+               position: absolute;
+               z-index: 10;
+               background: var(--main-background-color);
+               bottom: 8px;
+               right: 5px;
+               padding: 2px 4px;
+               box-shadow: 0 0 4px var(--main-background-color);
+       }
+}
+
 @media print {
        nav.sidebar, nav.sub, .out-of-band, a.srclink, #copy-path,
        details.rustdoc-toggle[open] > summary::before, details.rustdoc-toggle > summary::before,
@@ -1854,10 +1845,10 @@ in storage.js
                width: 35px;
        }
 
-       #sidebar-toggle {
+       #src-sidebar-toggle {
                top: 10px;
        }
-       .source-sidebar-expanded #sidebar-toggle {
+       .source-sidebar-expanded #src-sidebar-toggle {
                top: unset;
        }
 }
@@ -1875,6 +1866,7 @@ in storage.js
 }
 
 .variants > .docblock,
+.implementors-toggle > .docblock,
 .impl-items > .rustdoc-toggle[open]:not(:last-child),
 .methods > .rustdoc-toggle[open]:not(:last-child),
 .implementors-toggle[open]:not(:last-child) {
@@ -1901,6 +1893,11 @@ in storage.js
        border-radius: 50px;
 }
 
+.scraped-example {
+       /* So .scraped-example-title can be positioned absolutely */
+       position: relative;
+}
+
 .scraped-example .code-wrapper {
        position: relative;
        display: flex;
@@ -1910,18 +1907,30 @@ in storage.js
 }
 
 .scraped-example:not(.expanded) .code-wrapper {
-       max-height: 240px;
+       /* scrape-examples.js has a constant DEFAULT_MAX_LINES (call it N) for the number
+        * of lines shown in the un-expanded example code viewer. This pre needs to have
+        * a max-height equal to line-height * N. The line-height is currently 1.5em,
+        * and we include additional 10px for padding. */
+        max-height: calc(1.5em * 5 + 10px);
 }
 
 .scraped-example:not(.expanded) .code-wrapper pre {
        overflow-y: hidden;
-       max-height: 240px;
        padding-bottom: 0;
+       /* See above comment, should be the same max-height. */
+       max-height: calc(1.5em * 5 + 10px);
+}
+
+.more-scraped-examples .scraped-example:not(.expanded) .code-wrapper,
+.more-scraped-examples .scraped-example:not(.expanded) .code-wrapper pre {
+       /* See above comment, except this height is based on HIDDEN_MAX_LINES. */
+       max-height: calc(1.5em * 10 + 10px);
 }
 
 .scraped-example .code-wrapper .next,
 .scraped-example .code-wrapper .prev,
 .scraped-example .code-wrapper .expand {
+       color: var(--main-color);
        position: absolute;
        top: 0.25em;
        z-index: 1;
@@ -1958,7 +1967,6 @@ in storage.js
 }
 
 .scraped-example .code-wrapper .src-line-numbers {
-       margin: 0;
        padding: 14px 0;
 }
 
@@ -1995,7 +2003,6 @@ in storage.js
 
 .more-examples-toggle .hide-more {
        margin-left: 25px;
-       margin-bottom: 5px;
        cursor: pointer;
 }
 
@@ -2023,16 +2030,12 @@ in storage.js
        height: 100%;
 }
 
-.more-scraped-examples .scraped-example {
-       margin-bottom: 20px;
-}
-
-.more-scraped-examples .scraped-example:last-child {
-       margin-bottom: 0;
+.more-scraped-examples .scraped-example, .example-links {
+       margin-top: 20px;
 }
 
-.example-links a {
-       margin-top: 20px;
+.more-scraped-examples .scraped-example:first-child {
+       margin-top: 5px;
 }
 
 .example-links ul {
index 1f6fb961e918d430a5ad45ba293819769717c982..875a260c8115ebdb849b8f26593ed7d4981cb4ba 100644 (file)
        cursor: pointer;
 }
 
-.setting-line > .sub-settings {
-       padding-left: 42px;
-       width: 100%;
-       display: block;
-}
-
 #settings .setting-line {
        margin: 1.2em 0.6em;
 }
index 6e0905e730d0896f2e12bd2db518e4d0ca5918f8..de0dfcd469045e74c94e3037f60500bfbc2d50e4 100644 (file)
@@ -87,6 +87,8 @@ Original by Dempfi (https://github.com/dempfi/ayu)
        --crate-search-hover-border: #e0e0e0;
        --source-sidebar-background-selected: #14191f;
        --source-sidebar-background-hover: #14191f;
+       --table-alt-row-background-color: #191f26;
+       --codeblock-link-background: #333;
 }
 
 h1, h2, h3, h4 {
@@ -149,20 +151,10 @@ pre, .rustdoc.source .example-wrap {
        color: #c5c5c5;
 }
 
-.content .item-info::before { color: #ccc; }
-
 .sidebar h2 a,
 .sidebar h3 a {
        color: white;
 }
-body.source .example-wrap pre.rust a {
-       background: #333;
-}
-
-.module-item .stab,
-.import-item .stab {
-       color: #000;
-}
 
 .result-name .primitive > i, .result-name .keyword > i {
        color: #788797;
index 334fc3de5616d5103d8ab484c74106451c369620..dd7fc6892537c35b57a5e12ce63cfc1a71b3e545 100644 (file)
        --crate-search-hover-border: #2196f3;
        --source-sidebar-background-selected: #333;
        --source-sidebar-background-hover: #444;
-}
-
-.content .item-info::before { color: #ccc; }
-
-body.source .example-wrap pre.rust a {
-       background: #333;
+       --table-alt-row-background-color: #2A2A2A;
+       --codeblock-link-background: #333;
 }
 
 #titles > button:not(.selected) {
index 453e7508af4ba85eefdc211ce913d0cd1e2eedc2..b69d8a1cff95753f1255550bc5d87be641af01f0 100644 (file)
        --crate-search-hover-border: #717171;
        --source-sidebar-background-selected: #fff;
        --source-sidebar-background-hover: #e0e0e0;
-}
-
-.content .item-info::before { color: #ccc; }
-
-body.source .example-wrap pre.rust a {
-       background: #eee;
+       --table-alt-row-background-color: #F5F5F5;
+       --codeblock-link-background: #eee;
 }
 
 #titles > button:not(.selected) {
index 623f46b109666facbd7a2a2d9400ae88620c95a8..3f97e4e2e39f05ffbcb47f3f4329f952e69bd4e9 100644 (file)
@@ -184,7 +184,6 @@ function browserSupportsHistoryApi() {
 function loadCss(cssUrl) {
     const link = document.createElement("link");
     link.href = cssUrl;
-    link.type = "text/css";
     link.rel = "stylesheet";
     document.getElementsByTagName("head")[0].appendChild(link);
 }
@@ -622,7 +621,7 @@ function loadCss(cssUrl) {
         const innerToggle = document.getElementById(toggleAllDocsId);
         removeClass(innerToggle, "will-expand");
         onEachLazy(document.getElementsByClassName("rustdoc-toggle"), e => {
-            if (!hasClass(e, "type-contents-toggle")) {
+            if (!hasClass(e, "type-contents-toggle") && !hasClass(e, "more-examples-toggle")) {
                 e.open = true;
             }
         });
index e328e656edda4caa59625cdca9b5c0b9d53b143f..7a3a9c5f3400190fb62ec8ea3ee904171a06d048 100644 (file)
@@ -3,25 +3,33 @@
 "use strict";
 
 (function() {
-    // Number of lines shown when code viewer is not expanded
-    const MAX_LINES = 10;
+    // Number of lines shown when code viewer is not expanded.
+    // DEFAULT is the first example shown by default, while HIDDEN is
+    // the examples hidden beneath the "More examples" toggle.
+    //
+    // NOTE: these values MUST be synchronized with certain rules in rustdoc.css!
+    const DEFAULT_MAX_LINES = 5;
+    const HIDDEN_MAX_LINES = 10;
 
     // Scroll code block to the given code location
-    function scrollToLoc(elt, loc) {
+    function scrollToLoc(elt, loc, isHidden) {
         const lines = elt.querySelector(".src-line-numbers");
         let scrollOffset;
 
         // If the block is greater than the size of the viewer,
         // then scroll to the top of the block. Otherwise scroll
         // to the middle of the block.
-        if (loc[1] - loc[0] > MAX_LINES) {
+        const maxLines = isHidden ? HIDDEN_MAX_LINES : DEFAULT_MAX_LINES;
+        if (loc[1] - loc[0] > maxLines) {
             const line = Math.max(0, loc[0] - 1);
             scrollOffset = lines.children[line].offsetTop;
         } else {
             const wrapper = elt.querySelector(".code-wrapper");
             const halfHeight = wrapper.offsetHeight / 2;
-            const offsetMid = (lines.children[loc[0]].offsetTop
-                             + lines.children[loc[1]].offsetTop) / 2;
+            const offsetTop = lines.children[loc[0]].offsetTop;
+            const lastLine = lines.children[loc[1]];
+            const offsetBot = lastLine.offsetTop + lastLine.offsetHeight;
+            const offsetMid = (offsetTop + offsetBot) / 2;
             scrollOffset = offsetMid - halfHeight;
         }
 
@@ -29,7 +37,7 @@
         elt.querySelector(".rust").scrollTo(0, scrollOffset);
     }
 
-    function updateScrapedExample(example) {
+    function updateScrapedExample(example, isHidden) {
         const locs = JSON.parse(example.attributes.getNamedItem("data-locs").textContent);
         let locIndex = 0;
         const highlights = Array.prototype.slice.call(example.querySelectorAll(".highlight"));
@@ -40,7 +48,7 @@
             const onChangeLoc = changeIndex => {
                 removeClass(highlights[locIndex], "focus");
                 changeIndex();
-                scrollToLoc(example, locs[locIndex][0]);
+                scrollToLoc(example, locs[locIndex][0], isHidden);
                 addClass(highlights[locIndex], "focus");
 
                 const url = locs[locIndex][1];
@@ -70,7 +78,7 @@
             expandButton.addEventListener("click", () => {
                 if (hasClass(example, "expanded")) {
                     removeClass(example, "expanded");
-                    scrollToLoc(example, locs[0][0]);
+                    scrollToLoc(example, locs[0][0], isHidden);
                 } else {
                     addClass(example, "expanded");
                 }
         }
 
         // Start with the first example in view
-        scrollToLoc(example, locs[0][0]);
+        scrollToLoc(example, locs[0][0], isHidden);
     }
 
     const firstExamples = document.querySelectorAll(".scraped-example-list > .scraped-example");
-    onEachLazy(firstExamples, updateScrapedExample);
+    onEachLazy(firstExamples, el => updateScrapedExample(el, false));
     onEachLazy(document.querySelectorAll(".more-examples-toggle"), toggle => {
         // Allow users to click the left border of the <details> section to close it,
         // since the section can be large and finding the [+] button is annoying.
             // depends on offsetHeight, a property that requires an element to be visible to
             // compute correctly.
             setTimeout(() => {
-                onEachLazy(moreExamples, updateScrapedExample);
+                onEachLazy(moreExamples, el => updateScrapedExample(el, true));
             });
         }, {once: true});
     });
index 5db768c1c5753aa063d1b9f828b67ef76f005660..0e1c864e62d84800243b619e83ba490639e76f00 100644 (file)
@@ -83,7 +83,7 @@ function toggleSidebar() {
 
 function createSidebarToggle() {
     const sidebarToggle = document.createElement("div");
-    sidebarToggle.id = "sidebar-toggle";
+    sidebarToggle.id = "src-sidebar-toggle";
 
     const inner = document.createElement("button");
 
index 035b2e18b00ebeaf1839e4ce3b4e85a9158e4e62..002d19ec9b67dae6c0b3724e6b46aac4213f9766 100644 (file)
@@ -1,4 +1,4 @@
-Rustdoc will automatically scrape examples of documented items from the `examples/` directory of a project. These examples will be included within the generated documentation for that item. For example, if your library contains a public function:
+Rustdoc will automatically scrape examples of documented items from a project's source code. These examples will be included within the generated documentation for that item. For example, if your library contains a public function:
 
 ```rust
 // src/lib.rs
@@ -16,6 +16,7 @@ fn main() {
 
 Then this code snippet will be included in the documentation for `a_func`.
 
+
 ## How to read scraped examples
 
 Scraped examples are shown as blocks of code from a given file. The relevant item will be highlighted. If the file is larger than a couple lines, only a small window will be shown which you can expand by clicking &varr; in the top-right. If a file contains multiple instances of an item, you can use the &pr; and &sc; buttons to toggle through each instance.
@@ -25,7 +26,7 @@ If there is more than one file that contains examples, then you should click "Mo
 
 ## How Rustdoc scrapes examples
 
-When you run `cargo doc`, Rustdoc will analyze all the crates that match Cargo's `--examples` filter for instances of items that occur in the crates being documented. Then Rustdoc will include the source code of these instances in the generated documentation.
+When you run `cargo doc -Zunstable-options -Zrustdoc-scrape-examples`, Rustdoc will analyze all the documented crates for uses of documented items. Then Rustdoc will include the source code of these instances in the generated documentation.
 
 Rustdoc has a few techniques to ensure this doesn't overwhelm documentation readers, and that it doesn't blow up the page size:
 
index 6d34f484754c7a6c2c60d85b3ac9c0ca1e740b5e..ef1d7da5a341cf8ca191f171ba22dba6cd462abc 100644 (file)
@@ -674,7 +674,7 @@ fn usage(argv0: &str) {
 
 fn wrap_return(diag: &rustc_errors::Handler, res: Result<(), String>) -> MainResult {
     match res {
-        Ok(()) => Ok(()),
+        Ok(()) => diag.has_errors().map_or(Ok(()), Err),
         Err(err) => {
             let reported = diag.struct_err(&err).emit();
             Err(reported)
@@ -689,7 +689,7 @@ fn run_renderer<'tcx, T: formats::FormatRenderer<'tcx>>(
     tcx: TyCtxt<'tcx>,
 ) -> MainResult {
     match formats::run_format::<T>(krate, renderopts, cache, tcx) {
-        Ok(_) => Ok(()),
+        Ok(_) => tcx.sess.has_errors().map_or(Ok(()), Err),
         Err(e) => {
             let mut msg =
                 tcx.sess.struct_err(&format!("couldn't generate documentation: {}", e.error));
@@ -774,6 +774,7 @@ fn main_args(at_args: &[String]) -> MainResult {
     let output_format = options.output_format;
     let externs = options.externs.clone();
     let scrape_examples_options = options.scrape_examples_options.clone();
+    let bin_crate = options.bin_crate;
 
     let config = core::create_config(options);
 
@@ -832,7 +833,14 @@ fn main_args(at_args: &[String]) -> MainResult {
                 info!("finished with rustc");
 
                 if let Some(options) = scrape_examples_options {
-                    return scrape_examples::run(krate, render_opts, cache, tcx, options);
+                    return scrape_examples::run(
+                        krate,
+                        render_opts,
+                        cache,
+                        tcx,
+                        options,
+                        bin_crate,
+                    );
                 }
 
                 cache.crate_version = crate_version;
index 044e051440c52bb9117416d75ca0a3fa52885b86..5f4ad6d2aea345073d79b30dcf5baf38dbfeeda8 100644 (file)
@@ -53,7 +53,7 @@ pub(crate) fn render<P: AsRef<Path>>(
 
     let mut css = String::new();
     for name in &options.markdown_css {
-        write!(css, r#"<link rel="stylesheet" type="text/css" href="{name}">"#)
+        write!(css, r#"<link rel="stylesheet" href="{name}">"#)
             .expect("Writing to a String can't fail");
     }
 
index 37a28b6b7bd84a17282686cdc40dc816d1e70ce6..4f0eb8b8076e5fae8214dfb8a71ace1658385d36 100644 (file)
@@ -538,11 +538,10 @@ fn def_id_to_res(&self, ty_id: DefId) -> Option<Res> {
             ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did, .. }, _)), _) | ty::Foreign(did) => {
                 Res::from_def_id(self.cx.tcx, did)
             }
-            ty::Projection(_)
+            ty::Alias(..)
             | ty::Closure(..)
             | ty::Generator(..)
             | ty::GeneratorWitness(_)
-            | ty::Opaque(..)
             | ty::Dynamic(..)
             | ty::Param(_)
             | ty::Bound(..)
index d57f981d51a84fac39729d530f055d8324a8d68c..79db3c6c3e78699845da1046efadd30e849c33ed 100644 (file)
 };
 
 pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate {
+    // We need to check if there are errors before running this pass because it would crash when
+    // we try to get auto and blanket implementations.
+    if cx.tcx.sess.diagnostic().has_errors_or_lint_errors().is_some() {
+        return krate;
+    }
+
     let synth_impls = cx.sess().time("collect_synthetic_impls", || {
         let mut synth = SyntheticImplCollector { cx, impls: Vec::new() };
         synth.visit_crate(&krate);
index dfa6ba38b883b11559e2a8b03f97a90817aa7852..f2ee99cd9d4943e1e1a576d1c26a52d1f8881541 100644 (file)
@@ -110,6 +110,7 @@ pub(crate) struct CallData {
     pub(crate) url: String,
     pub(crate) display_name: String,
     pub(crate) edition: Edition,
+    pub(crate) is_bin: bool,
 }
 
 pub(crate) type FnCallLocations = FxHashMap<PathBuf, CallData>;
@@ -122,6 +123,7 @@ struct FindCalls<'a, 'tcx> {
     cx: Context<'tcx>,
     target_crates: Vec<CrateNum>,
     calls: &'a mut AllCallLocations,
+    bin_crate: bool,
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for FindCalls<'a, 'tcx>
@@ -245,7 +247,9 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
                 let mk_call_data = || {
                     let display_name = file_path.display().to_string();
                     let edition = call_span.edition();
-                    CallData { locations: Vec::new(), url, display_name, edition }
+                    let is_bin = self.bin_crate;
+
+                    CallData { locations: Vec::new(), url, display_name, edition, is_bin }
                 };
 
                 let fn_key = tcx.def_path_hash(*def_id);
@@ -274,6 +278,7 @@ pub(crate) fn run(
     cache: formats::cache::Cache,
     tcx: TyCtxt<'_>,
     options: ScrapeExamplesOptions,
+    bin_crate: bool,
 ) -> interface::Result<()> {
     let inner = move || -> Result<(), String> {
         // Generates source files for examples
@@ -300,7 +305,8 @@ pub(crate) fn run(
 
         // Run call-finder on all items
         let mut calls = FxHashMap::default();
-        let mut finder = FindCalls { calls: &mut calls, tcx, map: tcx.hir(), cx, target_crates };
+        let mut finder =
+            FindCalls { calls: &mut calls, tcx, map: tcx.hir(), cx, target_crates, bin_crate };
         tcx.hir().visit_all_item_likes_in_crate(&mut finder);
 
         // The visitor might have found a type error, which we need to
index a1232c451fc27173f8718e05d174b2503ca0b607..3dfd4d93fa013e1c0578d3ceac5c8f4ebba4b6ec 160000 (submodule)
@@ -1 +1 @@
-Subproject commit a1232c451fc27173f8718e05d174b2503ca0b607
+Subproject commit 3dfd4d93fa013e1c0578d3ceac5c8f4ebba4b6ec
index cbbcfad3ef4833016debbc3b8ad3eb299f0fb5b5..e9740e30da483d6a5231c8e47a17fe2a678d015a 100644 (file)
@@ -9,7 +9,7 @@
 // It also validates that functions can be called through function pointers
 // through traits.
 
-#![feature(no_core, lang_items, unboxed_closures, arbitrary_self_types)]
+#![feature(no_core, lang_items, intrinsics, unboxed_closures, arbitrary_self_types)]
 #![crate_type = "lib"]
 #![no_core]
 
@@ -49,6 +49,10 @@ pub trait Fn<Args: Tuple>: FnOnce<Args> {
     extern "rust-call" fn call(&self, args: Args) -> Self::Output;
 }
 
+extern "rust-intrinsic" {
+    pub fn transmute<Src, Dst>(src: Src) -> Dst;
+}
+
 pub static mut STORAGE_FOO: fn(&usize, &mut u32) -> Result<(), ()> = arbitrary_black_box;
 pub static mut STORAGE_BAR: u32 = 12;
 
@@ -87,3 +91,21 @@ pub extern "C" fn test() {
         STORAGE_FOO(&1, &mut buf);
     }
 }
+
+// Validate that we can codegen transmutes between data ptrs and fn ptrs.
+
+// CHECK: define{{.+}}{{void \(\) addrspace\(1\)\*|ptr addrspace\(1\)}} @transmute_data_ptr_to_fn({{\{\}\*|ptr}}{{.*}} %x)
+#[no_mangle]
+pub unsafe fn transmute_data_ptr_to_fn(x: *const ()) -> fn() {
+    // It doesn't matter precisely how this is codegenned (through memory or an addrspacecast),
+    // as long as it doesn't cause a verifier error by using `bitcast`.
+    transmute(x)
+}
+
+// CHECK: define{{.+}}{{\{\}\*|ptr}} @transmute_fn_ptr_to_data({{void \(\) addrspace\(1\)\*|ptr addrspace\(1\)}}{{.*}} %x)
+#[no_mangle]
+pub unsafe fn transmute_fn_ptr_to_data(x: fn()) -> *const () {
+    // It doesn't matter precisely how this is codegenned (through memory or an addrspacecast),
+    // as long as it doesn't cause a verifier error by using `bitcast`.
+    transmute(x)
+}
index 3ea3a24bfae11daf42e148a4ed0b061a0be51f97..b90ef104ce72a3fd2c2a28744066d545c42d6b34 100644 (file)
@@ -8,6 +8,8 @@
 // On riscv the closure is another function, placed before fn foo so CHECK can't
 // find it
 // ignore-riscv64 FIXME
+// On s390x the closure is also in another function
+// ignore-s390x FIXME
 
 #![crate_type = "lib"]
 #![feature(c_unwind)]
index 44f1b408d21b8f0ede3c3ceb48cec463f614e142..827eb20154afd0195cc1da957b67aa483444f56b 100644 (file)
@@ -34,8 +34,8 @@ pub enum Enum1 {
 
 // CHECK: define i8 @match1{{.*}}
 // CHECK-NEXT: start:
-// CHECK-NEXT: %1 = {{.*}}call i8 @llvm.usub.sat.i8(i8 %0, i8 1)
-// CHECK-NEXT: switch i8 %1, label {{.*}} [
+// CHECK-NEXT: [[DISCR:%.*]] = {{.*}}call i8 @llvm.usub.sat.i8(i8 %0, i8 1)
+// CHECK-NEXT: switch i8 [[DISCR]], label {{.*}} [
 #[no_mangle]
 pub fn match1(e: Enum1) -> u8 {
     use Enum1::*;
diff --git a/src/test/codegen/issue-105386-ub-in-debuginfo.rs b/src/test/codegen/issue-105386-ub-in-debuginfo.rs
new file mode 100644 (file)
index 0000000..d54ac9e
--- /dev/null
@@ -0,0 +1,22 @@
+// compile-flags: --crate-type=lib -O -Cdebuginfo=2 -Cno-prepopulate-passes
+// min-llvm-version: 15.0 # this test uses opaque pointer notation
+#![feature(stmt_expr_attributes)]
+
+pub struct S([usize; 8]);
+
+#[no_mangle]
+pub fn outer_function(x: S, y: S) -> usize {
+    (#[inline(always)]|| {
+        let _z = x;
+        y.0[0]
+    })()
+}
+
+// Check that we do not attempt to load from the spilled arg before it is assigned to
+// when generating debuginfo.
+// CHECK-LABEL: @outer_function
+// CHECK: [[spill:%.*]] = alloca %"[closure@{{.*.rs}}:9:23: 9:25]"
+// CHECK-NOT: [[ptr_tmp:%.*]] = getelementptr inbounds %"[closure@{{.*.rs}}:9:23: 9:25]", ptr [[spill]]
+// CHECK-NOT: [[load:%.*]] = load ptr, ptr
+// CHECK: call void @llvm.lifetime.start{{.*}}({{.*}}, ptr [[spill]])
+// CHECK: call void @llvm.memcpy{{.*}}(ptr {{align .*}} [[spill]], ptr {{align .*}} %x
diff --git a/src/test/codegen/pgo-counter-bias.rs b/src/test/codegen/pgo-counter-bias.rs
new file mode 100644 (file)
index 0000000..28caa7f
--- /dev/null
@@ -0,0 +1,10 @@
+// Test that __llvm_profile_counter_bias does not get internalized by lto.
+
+// ignore-macos -runtime-counter-relocation not honored on Mach-O
+// compile-flags: -Cprofile-generate -Cllvm-args=-runtime-counter-relocation -Clto=fat
+// needs-profiler-support
+// no-prefer-dynamic
+
+// CHECK: @__llvm_profile_counter_bias = {{.*}}global
+
+pub fn main() {}
index 9bef743ddcb414127a0b7cae1e26a12ffdab1f1c..78ebbccfce1950fe372e1dc74f9f9723d6f92cdf 100644 (file)
@@ -12,7 +12,7 @@
 include!("aux_mod.rs");
 
 // Here we check that the expansion of the file!() macro is mapped.
-// CHECK: @alloc2 = private unnamed_addr constant <{ [34 x i8] }> <{ [34 x i8] c"/the/src/remap_path_prefix/main.rs" }>, align 1
+// CHECK: @alloc2 = private unnamed_addr constant <{ [34 x i8] }> <{ [34 x i8] c"/the/src/remap_path_prefix/main.rs" }>
 pub static FILE_PATH: &'static str = file!();
 
 fn main() {
index 9d18c5f03c665151ce0757988ba88588376e2996..f733de12b3537097f21a0f4a3cea52185d7c18d0 100644 (file)
@@ -8,6 +8,7 @@
 // ignore-powerpc
 // ignore-powerpc64
 // ignore-riscv64 see codegen/riscv-abi
+// ignore-s390x
 // ignore-windows
 // See repr-transparent.rs
 
index c68ba8460cb1409d91fc4508aef19da815a50e58..4f2313ce47a979be33140172948c254831e8b538 100644 (file)
@@ -2,6 +2,7 @@
 
 // ignore-riscv64 riscv64 has an i128 type used with test_Vector
 // see codegen/riscv-abi for riscv functiona call tests
+// ignore-s390x s390x with default march passes vector types per reference
 
 #![crate_type="lib"]
 #![feature(repr_simd, transparent_unions)]
diff --git a/src/test/codegen/sanitizer-kcfi-add-kcfi-flag.rs b/src/test/codegen/sanitizer-kcfi-add-kcfi-flag.rs
new file mode 100644 (file)
index 0000000..c2eb852
--- /dev/null
@@ -0,0 +1,11 @@
+// Verifies that "kcfi" module flag is added.
+//
+// needs-sanitizer-kcfi
+// compile-flags: -Ctarget-feature=-crt-static -Zsanitizer=kcfi
+
+#![crate_type="lib"]
+
+pub fn foo() {
+}
+
+// CHECK: !{{[0-9]+}} = !{i32 4, !"kcfi", i32 1}
diff --git a/src/test/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi.rs b/src/test/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi.rs
new file mode 100644 (file)
index 0000000..0afd972
--- /dev/null
@@ -0,0 +1,47 @@
+// Verifies that KCFI type metadata for functions are emitted.
+//
+// revisions: aarch64 x86_64
+// [aarch64] compile-flags: --target aarch64-unknown-none
+// [aarch64] needs-llvm-components: aarch64
+// [x86_64] compile-flags: --target x86_64-unknown-none
+// [x86_64] needs-llvm-components:
+// compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi
+
+#![crate_type="lib"]
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang="sized"]
+trait Sized { }
+#[lang="copy"]
+trait Copy { }
+
+impl Copy for i32 {}
+
+pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
+    // CHECK-LABEL: define{{.*}}foo
+    // FIXME(rcvalle): Change <unknown kind #36> to !kcfi_type when Rust is updated to LLVM 16
+    // CHECK-SAME: {{.*}}!<unknown kind #36> ![[TYPE1:[0-9]+]]
+    // CHECK: call i32 %f(i32 %arg){{.*}}[ "kcfi"(i32 -1666898348) ]
+    f(arg)
+}
+
+pub fn bar(f: fn(i32, i32) -> i32, arg1: i32, arg2: i32) -> i32 {
+    // CHECK-LABEL: define{{.*}}bar
+    // FIXME(rcvalle): Change <unknown kind #36> to !kcfi_type when Rust is updated to LLVM 16
+    // CHECK-SAME: {{.*}}!<unknown kind #36> ![[TYPE2:[0-9]+]]
+    // CHECK: call i32 %f(i32 %arg1, i32 %arg2){{.*}}[ "kcfi"(i32 -1789026986) ]
+    f(arg1, arg2)
+}
+
+pub fn baz(f: fn(i32, i32, i32) -> i32, arg1: i32, arg2: i32, arg3: i32) -> i32 {
+    // CHECK-LABEL: define{{.*}}baz
+    // FIXME(rcvalle): Change <unknown kind #36> to !kcfi_type when Rust is updated to LLVM 16
+    // CHECK-SAME: {{.*}}!<unknown kind #36> ![[TYPE3:[0-9]+]]
+    // CHECK: call i32 %f(i32 %arg1, i32 %arg2, i32 %arg3){{.*}}[ "kcfi"(i32 1248878270) ]
+    f(arg1, arg2, arg3)
+}
+
+// CHECK: ![[TYPE1]] = !{i32 653723426}
+// CHECK: ![[TYPE2]] = !{i32 412174924}
+// CHECK: ![[TYPE3]] = !{i32 -636668840}
index 4c07740b3560420eb3cc38acab4643e3ec60cf70..98a6761f8abbb3261bf660427bc97392f6891431 100644 (file)
@@ -14,7 +14,7 @@ pub struct PartiallyUninit {
 
 // CHECK: [[FULLY_UNINIT:@[0-9]+]] = private unnamed_addr constant <{ [10 x i8] }> undef
 
-// CHECK: [[PARTIALLY_UNINIT:@[0-9]+]] = private unnamed_addr constant <{ [4 x i8], [12 x i8] }> <{ [4 x i8] c"\EF\BE\AD\DE", [12 x i8] undef }>, align 4
+// CHECK: [[PARTIALLY_UNINIT:@[0-9]+]] = private unnamed_addr constant <{ [4 x i8], [12 x i8] }> <{ [4 x i8] c"{{\\EF\\BE\\AD\\DE|\\DE\\AD\\BE\\EF}}", [12 x i8] undef }>, align 4
 
 // This shouldn't contain undef, since it contains more chunks
 // than the default value of uninit_const_chunk_threshold.
index a12cd0d021e59cf910896954d410af5c5eae0bec..ada541e644a3130236366d1b562303afe9059f38 100644 (file)
@@ -187,9 +187,9 @@ pub fn change_continue_label() {
 }
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
-#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck, optimized_mir")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail6")]
 pub fn change_continue_label() {
     let mut _x = 0;
index f81855e42becbd67a13dc5f45f5b7e7e63a1ed81..88fd4d89b2827661b9d9f74dcaf4be3e5692d4d7 100644 (file)
@@ -158,9 +158,9 @@ pub fn change_break_label() {
 }
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
-#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail6")]
 pub fn change_break_label() {
     let mut _x = 0;
@@ -210,9 +210,9 @@ pub fn change_continue_label() {
 }
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
-#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail6")]
 pub fn change_continue_label() {
     let mut _x = 0;
index e432cf8fe4cc3068753af5b375c1408de6185a59..9b4d23757b871340e7418c03025e449d978ccf63 100644 (file)
@@ -158,9 +158,9 @@ pub fn change_break_label() {
 }
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
-#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail6")]
 pub fn change_break_label() {
     let mut _x = 0;
@@ -212,9 +212,9 @@ pub fn change_continue_label() {
 }
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
-#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail6")]
 pub fn change_continue_label() {
     let mut _x = 0;
index 57e298625f9a086c1e19dac1904153824bafc34f..9780332d8bf18813d2658000920e92e91f7e8824 100644 (file)
@@ -8,7 +8,7 @@
   
       bb0: {
           _2 = discriminant(_1);           // scope 0 at $DIR/76803_regression.rs:+1:11: +1:12
-          switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/76803_regression.rs:+1:5: +1:12
+          switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/76803_regression.rs:+1:5: +1:12
       }
   
       bb1: {
index 9c5a9fa9abb0e617036579f0fb741ee04a890e93..0af5d82d31540debb60c201f5201332058981578 100644 (file)
@@ -14,7 +14,7 @@
 -         _2 = Ne(move _3, const true);    // scope 0 at $DIR/bool_compare.rs:+1:8: +1:17
 +         _2 = Not(move _3);               // scope 0 at $DIR/bool_compare.rs:+1:8: +1:17
           StorageDead(_3);                 // scope 0 at $DIR/bool_compare.rs:+1:16: +1:17
-          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:+1:8: +1:17
+          switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:+1:8: +1:17
       }
   
       bb1: {
index 58c52c4b7d7ff36bfc528cf4d28031226194a406..f5d1febd991cd5aef3f2964c80372d1966e8fd5b 100644 (file)
@@ -14,7 +14,7 @@
 -         _2 = Ne(const true, move _3);    // scope 0 at $DIR/bool_compare.rs:+1:8: +1:17
 +         _2 = Not(move _3);               // scope 0 at $DIR/bool_compare.rs:+1:8: +1:17
           StorageDead(_3);                 // scope 0 at $DIR/bool_compare.rs:+1:16: +1:17
-          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:+1:8: +1:17
+          switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:+1:8: +1:17
       }
   
       bb1: {
index 676428c95c1bf01d89e674f8017c66358bcbcec0..e7432adac7d9d366e75830c62b45d8f9ae3ff569 100644 (file)
@@ -14,7 +14,7 @@
 -         _2 = Eq(move _3, const false);   // scope 0 at $DIR/bool_compare.rs:+1:8: +1:18
 +         _2 = Not(move _3);               // scope 0 at $DIR/bool_compare.rs:+1:8: +1:18
           StorageDead(_3);                 // scope 0 at $DIR/bool_compare.rs:+1:17: +1:18
-          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:+1:8: +1:18
+          switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:+1:8: +1:18
       }
   
       bb1: {
index addfcd769a5468327578048b5c8838661877957c..6b3e27772f71c978b4bd06feb76e83cf5d0226a0 100644 (file)
@@ -14,7 +14,7 @@
 -         _2 = Eq(const false, move _3);   // scope 0 at $DIR/bool_compare.rs:+1:8: +1:18
 +         _2 = Not(move _3);               // scope 0 at $DIR/bool_compare.rs:+1:8: +1:18
           StorageDead(_3);                 // scope 0 at $DIR/bool_compare.rs:+1:17: +1:18
-          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:+1:8: +1:18
+          switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:+1:8: +1:18
       }
   
       bb1: {
diff --git a/src/test/mir-opt/building/custom/enums.rs b/src/test/mir-opt/building/custom/enums.rs
new file mode 100644 (file)
index 0000000..e5cd456
--- /dev/null
@@ -0,0 +1,120 @@
+#![feature(custom_mir, core_intrinsics)]
+
+extern crate core;
+use core::intrinsics::mir::*;
+
+// EMIT_MIR enums.switch_bool.built.after.mir
+#[custom_mir(dialect = "built")]
+pub fn switch_bool(b: bool) -> u32 {
+    mir!(
+        {
+            match b {
+                true => t,
+                false => f,
+                _ => f,
+            }
+        }
+
+        t = {
+            RET = 5;
+            Return()
+        }
+
+        f = {
+            RET = 10;
+            Return()
+        }
+    )
+}
+
+// EMIT_MIR enums.switch_option.built.after.mir
+#[custom_mir(dialect = "built")]
+pub fn switch_option(option: Option<()>) -> bool {
+    mir!(
+        {
+            let discr = Discriminant(option);
+            match discr {
+                0 => n,
+                1 => s,
+                _ => s,
+            }
+        }
+
+        n = {
+            RET = false;
+            Return()
+        }
+
+        s = {
+            RET = true;
+            Return()
+        }
+    )
+}
+
+#[repr(u8)]
+enum Bool {
+    False = 0,
+    True = 1,
+}
+
+// EMIT_MIR enums.switch_option_repr.built.after.mir
+#[custom_mir(dialect = "built")]
+fn switch_option_repr(option: Bool) -> bool {
+    mir!(
+        {
+            let discr = Discriminant(option);
+            match discr {
+                0 => f,
+                _ => t,
+            }
+        }
+
+        t = {
+            RET = true;
+            Return()
+        }
+
+        f = {
+            RET = false;
+            Return()
+        }
+    )
+}
+
+// EMIT_MIR enums.set_discr.built.after.mir
+#[custom_mir(dialect = "runtime", phase = "initial")]
+fn set_discr(option: &mut Option<()>) {
+    mir!({
+        SetDiscriminant(*option, 0);
+        Return()
+    })
+}
+
+// EMIT_MIR enums.set_discr_repr.built.after.mir
+#[custom_mir(dialect = "runtime", phase = "initial")]
+fn set_discr_repr(b: &mut Bool) {
+    mir!({
+        SetDiscriminant(*b, 0);
+        Return()
+    })
+}
+
+fn main() {
+    assert_eq!(switch_bool(true), 5);
+    assert_eq!(switch_bool(false), 10);
+
+    assert_eq!(switch_option(Some(())), true);
+    assert_eq!(switch_option(None), false);
+
+    assert_eq!(switch_option_repr(Bool::True), true);
+    assert_eq!(switch_option_repr(Bool::False), false);
+
+    let mut opt = Some(());
+    set_discr(&mut opt);
+    assert_eq!(opt, None);
+
+    let mut b = Bool::True;
+    set_discr_repr(&mut b);
+    assert!(matches!(b, Bool::False));
+}
diff --git a/src/test/mir-opt/building/custom/enums.set_discr.built.after.mir b/src/test/mir-opt/building/custom/enums.set_discr.built.after.mir
new file mode 100644 (file)
index 0000000..7de9ed0
--- /dev/null
@@ -0,0 +1,10 @@
+// MIR for `set_discr` after built
+
+fn set_discr(_1: &mut Option<()>) -> () {
+    let mut _0: ();                      // return place in scope 0 at $DIR/enums.rs:+0:39: +0:39
+
+    bb0: {
+        discriminant((*_1)) = 0;         // scope 0 at $DIR/enums.rs:+2:9: +2:36
+        return;                          // scope 0 at $DIR/enums.rs:+3:9: +3:17
+    }
+}
diff --git a/src/test/mir-opt/building/custom/enums.set_discr_repr.built.after.mir b/src/test/mir-opt/building/custom/enums.set_discr_repr.built.after.mir
new file mode 100644 (file)
index 0000000..6fdc3d0
--- /dev/null
@@ -0,0 +1,10 @@
+// MIR for `set_discr_repr` after built
+
+fn set_discr_repr(_1: &mut Bool) -> () {
+    let mut _0: ();                      // return place in scope 0 at $DIR/enums.rs:+0:33: +0:33
+
+    bb0: {
+        discriminant((*_1)) = 0;         // scope 0 at $DIR/enums.rs:+2:9: +2:31
+        return;                          // scope 0 at $DIR/enums.rs:+3:9: +3:17
+    }
+}
diff --git a/src/test/mir-opt/building/custom/enums.switch_bool.built.after.mir b/src/test/mir-opt/building/custom/enums.switch_bool.built.after.mir
new file mode 100644 (file)
index 0000000..95c57d2
--- /dev/null
@@ -0,0 +1,19 @@
+// MIR for `switch_bool` after built
+
+fn switch_bool(_1: bool) -> u32 {
+    let mut _0: u32;                     // return place in scope 0 at $DIR/enums.rs:+0:32: +0:35
+
+    bb0: {
+        switchInt(_1) -> [1: bb1, 0: bb2, otherwise: bb2]; // scope 0 at $DIR/enums.rs:+3:13: +7:14
+    }
+
+    bb1: {
+        _0 = const 5_u32;                // scope 0 at $DIR/enums.rs:+11:13: +11:20
+        return;                          // scope 0 at $DIR/enums.rs:+12:13: +12:21
+    }
+
+    bb2: {
+        _0 = const 10_u32;               // scope 0 at $DIR/enums.rs:+16:13: +16:21
+        return;                          // scope 0 at $DIR/enums.rs:+17:13: +17:21
+    }
+}
diff --git a/src/test/mir-opt/building/custom/enums.switch_option.built.after.mir b/src/test/mir-opt/building/custom/enums.switch_option.built.after.mir
new file mode 100644 (file)
index 0000000..a659ba7
--- /dev/null
@@ -0,0 +1,21 @@
+// MIR for `switch_option` after built
+
+fn switch_option(_1: Option<()>) -> bool {
+    let mut _0: bool;                    // return place in scope 0 at $DIR/enums.rs:+0:45: +0:49
+    let mut _2: isize;                   // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+
+    bb0: {
+        _2 = discriminant(_1);           // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+        switchInt(_2) -> [0: bb1, 1: bb2, otherwise: bb2]; // scope 0 at $DIR/enums.rs:+4:13: +8:14
+    }
+
+    bb1: {
+        _0 = const false;                // scope 0 at $DIR/enums.rs:+12:13: +12:24
+        return;                          // scope 0 at $DIR/enums.rs:+13:13: +13:21
+    }
+
+    bb2: {
+        _0 = const true;                 // scope 0 at $DIR/enums.rs:+17:13: +17:23
+        return;                          // scope 0 at $DIR/enums.rs:+18:13: +18:21
+    }
+}
diff --git a/src/test/mir-opt/building/custom/enums.switch_option_repr.built.after.mir b/src/test/mir-opt/building/custom/enums.switch_option_repr.built.after.mir
new file mode 100644 (file)
index 0000000..d60e4b1
--- /dev/null
@@ -0,0 +1,21 @@
+// MIR for `switch_option_repr` after built
+
+fn switch_option_repr(_1: Bool) -> bool {
+    let mut _0: bool;                    // return place in scope 0 at $DIR/enums.rs:+0:40: +0:44
+    let mut _2: u8;                      // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+
+    bb0: {
+        _2 = discriminant(_1);           // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+        switchInt(_2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/enums.rs:+4:13: +7:14
+    }
+
+    bb1: {
+        _0 = const true;                 // scope 0 at $DIR/enums.rs:+11:13: +11:23
+        return;                          // scope 0 at $DIR/enums.rs:+12:13: +12:21
+    }
+
+    bb2: {
+        _0 = const false;                // scope 0 at $DIR/enums.rs:+16:13: +16:24
+        return;                          // scope 0 at $DIR/enums.rs:+17:13: +17:21
+    }
+}
diff --git a/src/test/mir-opt/building/custom/projections.rs b/src/test/mir-opt/building/custom/projections.rs
new file mode 100644 (file)
index 0000000..5e472e5
--- /dev/null
@@ -0,0 +1,85 @@
+#![feature(custom_mir, core_intrinsics)]
+
+extern crate core;
+use core::intrinsics::mir::*;
+
+union U {
+    a: i32,
+    b: u32,
+}
+
+// EMIT_MIR projections.unions.built.after.mir
+#[custom_mir(dialect = "built")]
+fn unions(u: U) -> i32 {
+    mir!({
+        RET = u.a;
+        Return()
+    })
+}
+
+// EMIT_MIR projections.tuples.built.after.mir
+#[custom_mir(dialect = "analysis", phase = "post-cleanup")]
+fn tuples(i: (u32, i32)) -> (u32, i32) {
+    mir!(
+        // FIXME(JakobDegen): This is necessary because we can't give type hints for `RET`
+        let temp: (u32, i32);
+        {
+            temp.0 = i.0;
+            temp.1 = i.1;
+
+            RET = temp;
+            Return()
+        }
+    )
+}
+
+// EMIT_MIR projections.unwrap.built.after.mir
+#[custom_mir(dialect = "built")]
+fn unwrap(opt: Option<i32>) -> i32 {
+    mir!({
+        RET = Field(Variant(opt, 1), 0);
+        Return()
+    })
+}
+
+// EMIT_MIR projections.unwrap_deref.built.after.mir
+#[custom_mir(dialect = "built")]
+fn unwrap_deref(opt: Option<&i32>) -> i32 {
+    mir!({
+        RET = *Field::<&i32>(Variant(opt, 1), 0);
+        Return()
+    })
+}
+
+// EMIT_MIR projections.set.built.after.mir
+#[custom_mir(dialect = "built")]
+fn set(opt: &mut Option<i32>) {
+    mir!({
+        place!(Field(Variant(*opt, 1), 0)) = 10;
+        Return()
+    })
+}
+
+// EMIT_MIR projections.simple_index.built.after.mir
+#[custom_mir(dialect = "built")]
+fn simple_index(a: [i32; 10], b: &[i32]) -> i32 {
+    mir!({
+        let temp = 3;
+        RET = a[temp];
+        RET = (*b)[temp];
+        Return()
+    })
+}
+
+fn main() {
+    assert_eq!(unions(U { a: 5 }), 5);
+    assert_eq!(tuples((5, 6)), (5, 6));
+
+    assert_eq!(unwrap(Some(5)), 5);
+    assert_eq!(unwrap_deref(Some(&5)), 5);
+    let mut o = Some(5);
+    set(&mut o);
+    assert_eq!(o, Some(10));
+
+    assert_eq!(simple_index([0; 10], &[0; 10]), 0);
+}
diff --git a/src/test/mir-opt/building/custom/projections.set.built.after.mir b/src/test/mir-opt/building/custom/projections.set.built.after.mir
new file mode 100644 (file)
index 0000000..2f15176
--- /dev/null
@@ -0,0 +1,10 @@
+// MIR for `set` after built
+
+fn set(_1: &mut Option<i32>) -> () {
+    let mut _0: ();                      // return place in scope 0 at $DIR/projections.rs:+0:31: +0:31
+
+    bb0: {
+        (((*_1) as variant#1).0: i32) = const 10_i32; // scope 0 at $DIR/projections.rs:+2:9: +2:48
+        return;                          // scope 0 at $DIR/projections.rs:+3:9: +3:17
+    }
+}
diff --git a/src/test/mir-opt/building/custom/projections.simple_index.built.after.mir b/src/test/mir-opt/building/custom/projections.simple_index.built.after.mir
new file mode 100644 (file)
index 0000000..fc422e4
--- /dev/null
@@ -0,0 +1,13 @@
+// MIR for `simple_index` after built
+
+fn simple_index(_1: [i32; 10], _2: &[i32]) -> i32 {
+    let mut _0: i32;                     // return place in scope 0 at $DIR/projections.rs:+0:45: +0:48
+    let mut _3: usize;                   // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+
+    bb0: {
+        _3 = const 3_usize;              // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+        _0 = _1[_3];                     // scope 0 at $DIR/projections.rs:+3:9: +3:22
+        _0 = (*_2)[_3];                  // scope 0 at $DIR/projections.rs:+4:9: +4:25
+        return;                          // scope 0 at $DIR/projections.rs:+5:9: +5:17
+    }
+}
diff --git a/src/test/mir-opt/building/custom/projections.tuples.built.after.mir b/src/test/mir-opt/building/custom/projections.tuples.built.after.mir
new file mode 100644 (file)
index 0000000..65487d3
--- /dev/null
@@ -0,0 +1,13 @@
+// MIR for `tuples` after built
+
+fn tuples(_1: (u32, i32)) -> (u32, i32) {
+    let mut _0: (u32, i32);              // return place in scope 0 at $DIR/projections.rs:+0:29: +0:39
+    let mut _2: (u32, i32);              // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+
+    bb0: {
+        (_2.0: u32) = (_1.0: u32);       // scope 0 at $DIR/projections.rs:+5:13: +5:25
+        (_2.1: i32) = (_1.1: i32);       // scope 0 at $DIR/projections.rs:+6:13: +6:25
+        _0 = _2;                         // scope 0 at $DIR/projections.rs:+8:13: +8:23
+        return;                          // scope 0 at $DIR/projections.rs:+9:13: +9:21
+    }
+}
diff --git a/src/test/mir-opt/building/custom/projections.unions.built.after.mir b/src/test/mir-opt/building/custom/projections.unions.built.after.mir
new file mode 100644 (file)
index 0000000..922538a
--- /dev/null
@@ -0,0 +1,10 @@
+// MIR for `unions` after built
+
+fn unions(_1: U) -> i32 {
+    let mut _0: i32;                     // return place in scope 0 at $DIR/projections.rs:+0:20: +0:23
+
+    bb0: {
+        _0 = (_1.0: i32);                // scope 0 at $DIR/projections.rs:+2:9: +2:18
+        return;                          // scope 0 at $DIR/projections.rs:+3:9: +3:17
+    }
+}
diff --git a/src/test/mir-opt/building/custom/projections.unwrap.built.after.mir b/src/test/mir-opt/building/custom/projections.unwrap.built.after.mir
new file mode 100644 (file)
index 0000000..75b03a3
--- /dev/null
@@ -0,0 +1,10 @@
+// MIR for `unwrap` after built
+
+fn unwrap(_1: Option<i32>) -> i32 {
+    let mut _0: i32;                     // return place in scope 0 at $DIR/projections.rs:+0:32: +0:35
+
+    bb0: {
+        _0 = ((_1 as variant#1).0: i32); // scope 0 at $DIR/projections.rs:+2:9: +2:40
+        return;                          // scope 0 at $DIR/projections.rs:+3:9: +3:17
+    }
+}
diff --git a/src/test/mir-opt/building/custom/projections.unwrap_deref.built.after.mir b/src/test/mir-opt/building/custom/projections.unwrap_deref.built.after.mir
new file mode 100644 (file)
index 0000000..c6b0f7e
--- /dev/null
@@ -0,0 +1,10 @@
+// MIR for `unwrap_deref` after built
+
+fn unwrap_deref(_1: Option<&i32>) -> i32 {
+    let mut _0: i32;                     // return place in scope 0 at $DIR/projections.rs:+0:39: +0:42
+
+    bb0: {
+        _0 = (*((_1 as variant#1).0: &i32)); // scope 0 at $DIR/projections.rs:+2:9: +2:49
+        return;                          // scope 0 at $DIR/projections.rs:+3:9: +3:17
+    }
+}
diff --git a/src/test/mir-opt/building/custom/references.raw_pointer.built.after.mir b/src/test/mir-opt/building/custom/references.raw_pointer.built.after.mir
new file mode 100644 (file)
index 0000000..775e5e3
--- /dev/null
@@ -0,0 +1,10 @@
+// MIR for `raw_pointer` after built
+
+fn raw_pointer(_1: *const i32) -> *const i32 {
+    let mut _0: *const i32;              // return place in scope 0 at $DIR/references.rs:+0:38: +0:48
+
+    bb0: {
+        _0 = &raw const (*_1);           // scope 0 at $DIR/references.rs:+4:9: +4:27
+        return;                          // scope 0 at $DIR/references.rs:+5:9: +5:17
+    }
+}
index dee85722e8656daaffc42780c5d8ef5946dc0023..c93f6ec624b3551784c67643d449ce3a4bce8c7c 100644 (file)
@@ -36,8 +36,22 @@ pub fn immut_ref(x: &i32) -> &i32 {
     )
 }
 
+// EMIT_MIR references.raw_pointer.built.after.mir
+#[custom_mir(dialect = "built")]
+pub fn raw_pointer(x: *const i32) -> *const i32 {
+    // Regression test for a bug in which unsafetyck was not correctly turned off for
+    // `dialect = "built"`
+    mir!({
+        RET = addr_of!(*x);
+        Return()
+    })
+}
+
 fn main() {
     let mut x = 5;
     assert_eq!(*mut_ref(&mut x), 5);
     assert_eq!(*immut_ref(&x), 5);
+    unsafe {
+        assert_eq!(*raw_pointer(addr_of!(x)), 5);
+    }
 }
diff --git a/src/test/mir-opt/building/custom/terminators.assert_nonzero.built.after.mir b/src/test/mir-opt/building/custom/terminators.assert_nonzero.built.after.mir
new file mode 100644 (file)
index 0000000..a1a2722
--- /dev/null
@@ -0,0 +1,17 @@
+// MIR for `assert_nonzero` after built
+
+fn assert_nonzero(_1: i32) -> () {
+    let mut _0: ();                      // return place in scope 0 at $DIR/terminators.rs:+0:27: +0:27
+
+    bb0: {
+        switchInt(_1) -> [0: bb1, otherwise: bb2]; // scope 0 at $DIR/terminators.rs:+3:13: +6:14
+    }
+
+    bb1: {
+        unreachable;                     // scope 0 at $DIR/terminators.rs:+10:13: +10:26
+    }
+
+    bb2: {
+        return;                          // scope 0 at $DIR/terminators.rs:+14:13: +14:21
+    }
+}
diff --git a/src/test/mir-opt/building/custom/terminators.direct_call.built.after.mir b/src/test/mir-opt/building/custom/terminators.direct_call.built.after.mir
new file mode 100644 (file)
index 0000000..1b2345a
--- /dev/null
@@ -0,0 +1,16 @@
+// MIR for `direct_call` after built
+
+fn direct_call(_1: i32) -> i32 {
+    let mut _0: i32;                     // return place in scope 0 at $DIR/terminators.rs:+0:27: +0:30
+
+    bb0: {
+        _0 = ident::<i32>(_1) -> bb1;    // scope 0 at $DIR/terminators.rs:+3:13: +3:42
+                                         // mir::Constant
+                                         // + span: $DIR/terminators.rs:15:33: 15:38
+                                         // + literal: Const { ty: fn(i32) -> i32 {ident::<i32>}, val: Value(<ZST>) }
+    }
+
+    bb1: {
+        return;                          // scope 0 at $DIR/terminators.rs:+7:13: +7:21
+    }
+}
diff --git a/src/test/mir-opt/building/custom/terminators.drop_first.built.after.mir b/src/test/mir-opt/building/custom/terminators.drop_first.built.after.mir
new file mode 100644 (file)
index 0000000..c903e59
--- /dev/null
@@ -0,0 +1,13 @@
+// MIR for `drop_first` after built
+
+fn drop_first(_1: WriteOnDrop<'_>, _2: WriteOnDrop<'_>) -> () {
+    let mut _0: ();                      // return place in scope 0 at $DIR/terminators.rs:+0:59: +0:59
+
+    bb0: {
+        replace(_1 <- move _2) -> bb1;   // scope 0 at $DIR/terminators.rs:+3:13: +3:49
+    }
+
+    bb1: {
+        return;                          // scope 0 at $DIR/terminators.rs:+7:13: +7:21
+    }
+}
diff --git a/src/test/mir-opt/building/custom/terminators.drop_second.built.after.mir b/src/test/mir-opt/building/custom/terminators.drop_second.built.after.mir
new file mode 100644 (file)
index 0000000..f14246f
--- /dev/null
@@ -0,0 +1,13 @@
+// MIR for `drop_second` after built
+
+fn drop_second(_1: WriteOnDrop<'_>, _2: WriteOnDrop<'_>) -> () {
+    let mut _0: ();                      // return place in scope 0 at $DIR/terminators.rs:+0:60: +0:60
+
+    bb0: {
+        drop(_2) -> bb1;                 // scope 0 at $DIR/terminators.rs:+3:13: +3:30
+    }
+
+    bb1: {
+        return;                          // scope 0 at $DIR/terminators.rs:+7:13: +7:21
+    }
+}
diff --git a/src/test/mir-opt/building/custom/terminators.indirect_call.built.after.mir b/src/test/mir-opt/building/custom/terminators.indirect_call.built.after.mir
new file mode 100644 (file)
index 0000000..2f1b140
--- /dev/null
@@ -0,0 +1,13 @@
+// MIR for `indirect_call` after built
+
+fn indirect_call(_1: i32, _2: fn(i32) -> i32) -> i32 {
+    let mut _0: i32;                     // return place in scope 0 at $DIR/terminators.rs:+0:48: +0:51
+
+    bb0: {
+        _0 = _2(_1) -> bb1;              // scope 0 at $DIR/terminators.rs:+3:13: +3:38
+    }
+
+    bb1: {
+        return;                          // scope 0 at $DIR/terminators.rs:+7:13: +7:21
+    }
+}
diff --git a/src/test/mir-opt/building/custom/terminators.rs b/src/test/mir-opt/building/custom/terminators.rs
new file mode 100644 (file)
index 0000000..c23233f
--- /dev/null
@@ -0,0 +1,108 @@
+#![feature(custom_mir, core_intrinsics)]
+
+extern crate core;
+use core::intrinsics::mir::*;
+
+fn ident<T>(t: T) -> T {
+    t
+}
+
+// EMIT_MIR terminators.direct_call.built.after.mir
+#[custom_mir(dialect = "built")]
+fn direct_call(x: i32) -> i32 {
+    mir!(
+        {
+            Call(RET, retblock, ident(x))
+        }
+
+        retblock = {
+            Return()
+        }
+    )
+}
+
+// EMIT_MIR terminators.indirect_call.built.after.mir
+#[custom_mir(dialect = "built")]
+fn indirect_call(x: i32, f: fn(i32) -> i32) -> i32 {
+    mir!(
+        {
+            Call(RET, retblock, f(x))
+        }
+
+        retblock = {
+            Return()
+        }
+    )
+}
+
+struct WriteOnDrop<'a>(&'a mut i32, i32);
+
+impl<'a> Drop for WriteOnDrop<'a> {
+    fn drop(&mut self) {
+        *self.0 = self.1;
+    }
+}
+
+// EMIT_MIR terminators.drop_first.built.after.mir
+#[custom_mir(dialect = "built")]
+fn drop_first<'a>(a: WriteOnDrop<'a>, b: WriteOnDrop<'a>) {
+    mir!(
+        {
+            DropAndReplace(a, Move(b), retblock)
+        }
+
+        retblock = {
+            Return()
+        }
+    )
+}
+
+// EMIT_MIR terminators.drop_second.built.after.mir
+#[custom_mir(dialect = "built")]
+fn drop_second<'a>(a: WriteOnDrop<'a>, b: WriteOnDrop<'a>) {
+    mir!(
+        {
+            Drop(b, retblock)
+        }
+
+        retblock = {
+            Return()
+        }
+    )
+}
+
+// EMIT_MIR terminators.assert_nonzero.built.after.mir
+#[custom_mir(dialect = "built")]
+fn assert_nonzero(a: i32) {
+    mir!(
+        {
+            match a {
+                0 => unreachable,
+                _ => retblock
+            }
+        }
+
+        unreachable = {
+            Unreachable()
+        }
+
+        retblock = {
+            Return()
+        }
+    )
+}
+
+fn main() {
+    assert_eq!(direct_call(5), 5);
+    assert_eq!(indirect_call(5, ident), 5);
+
+    let mut a = 0;
+    let mut b = 0;
+    drop_first(WriteOnDrop(&mut a, 1), WriteOnDrop(&mut b, 1));
+    assert_eq!((a, b), (1, 0));
+
+    let mut a = 0;
+    let mut b = 0;
+    drop_second(WriteOnDrop(&mut a, 1), WriteOnDrop(&mut b, 1));
+    assert_eq!((a, b), (0, 1));
+}
index 0ebd840cf2d5cc02db12cc2fe1250bec9caba143..628a33f1020a5f625d333a536f9c795061a24d79 100644 (file)
@@ -27,7 +27,7 @@ fn main() -> () {
         StorageLive(_5);                 // scope 1 at $DIR/issue_101867.rs:+2:14: +2:15
         FakeRead(ForMatchedPlace(None), _1); // scope 1 at $DIR/issue_101867.rs:+2:19: +2:20
         _6 = discriminant(_1);           // scope 1 at $DIR/issue_101867.rs:+2:19: +2:20
-        switchInt(move _6) -> [1_isize: bb4, otherwise: bb3]; // scope 1 at $DIR/issue_101867.rs:+2:9: +2:16
+        switchInt(move _6) -> [1: bb4, otherwise: bb3]; // scope 1 at $DIR/issue_101867.rs:+2:9: +2:16
     }
 
     bb1: {
index 9182bcaa21fa6afa92f1056c1698d95db2e1def3..de5e4c0f6ed48dc33a50002ebb2bb8edc0b9f33c 100644 (file)
@@ -25,7 +25,7 @@ fn main() -> () {
         StorageLive(_3);                 // scope 0 at $DIR/issue_49232.rs:+3:19: +3:23
         _3 = const true;                 // scope 0 at $DIR/issue_49232.rs:+3:19: +3:23
         FakeRead(ForMatchedPlace(None), _3); // scope 0 at $DIR/issue_49232.rs:+3:19: +3:23
-        switchInt(_3) -> [false: bb3, otherwise: bb4]; // scope 0 at $DIR/issue_49232.rs:+3:13: +3:23
+        switchInt(_3) -> [0: bb3, otherwise: bb4]; // scope 0 at $DIR/issue_49232.rs:+3:13: +3:23
     }
 
     bb3: {
index 9a190c3d60ea49607f9e76a3ceb031bb659e18f8..cb36bc64da69597809b68fdb2dac704c6ff7accc 100644 (file)
@@ -28,7 +28,7 @@ fn full_tested_match() -> () {
         _2 = Option::<i32>::Some(const 42_i32); // scope 0 at $DIR/match_false_edges.rs:+1:19: +1:27
         FakeRead(ForMatchedPlace(None), _2); // scope 0 at $DIR/match_false_edges.rs:+1:19: +1:27
         _3 = discriminant(_2);           // scope 0 at $DIR/match_false_edges.rs:+1:19: +1:27
-        switchInt(move _3) -> [0_isize: bb1, 1_isize: bb2, otherwise: bb4]; // scope 0 at $DIR/match_false_edges.rs:+1:13: +1:27
+        switchInt(move _3) -> [0: bb1, 1: bb2, otherwise: bb4]; // scope 0 at $DIR/match_false_edges.rs:+1:13: +1:27
     }
 
     bb1: {
@@ -60,7 +60,7 @@ fn full_tested_match() -> () {
     }
 
     bb6: {
-        switchInt(move _7) -> [false: bb8, otherwise: bb7]; // scope 0 at $DIR/match_false_edges.rs:+2:20: +2:27
+        switchInt(move _7) -> [0: bb8, otherwise: bb7]; // scope 0 at $DIR/match_false_edges.rs:+2:20: +2:27
     }
 
     bb7: {
index 1c9953e7efc11ec538638eeed0355ad50f1a1024..7f8755faac6cf78f146d55ec9a291ced6ae387dc 100644 (file)
@@ -28,7 +28,7 @@ fn full_tested_match2() -> () {
         _2 = Option::<i32>::Some(const 42_i32); // scope 0 at $DIR/match_false_edges.rs:+1:19: +1:27
         FakeRead(ForMatchedPlace(None), _2); // scope 0 at $DIR/match_false_edges.rs:+1:19: +1:27
         _3 = discriminant(_2);           // scope 0 at $DIR/match_false_edges.rs:+1:19: +1:27
-        switchInt(move _3) -> [0_isize: bb1, 1_isize: bb2, otherwise: bb4]; // scope 0 at $DIR/match_false_edges.rs:+1:13: +1:27
+        switchInt(move _3) -> [0: bb1, 1: bb2, otherwise: bb4]; // scope 0 at $DIR/match_false_edges.rs:+1:13: +1:27
     }
 
     bb1: {
@@ -66,7 +66,7 @@ fn full_tested_match2() -> () {
     }
 
     bb6: {
-        switchInt(move _7) -> [false: bb8, otherwise: bb7]; // scope 0 at $DIR/match_false_edges.rs:+2:20: +2:27
+        switchInt(move _7) -> [0: bb8, otherwise: bb7]; // scope 0 at $DIR/match_false_edges.rs:+2:20: +2:27
     }
 
     bb7: {
index 08c67d39d78074f393be1f3963fa60d8be60db3e..e8b93f4371ecbadb05ce0c559300d80d3de25c31 100644 (file)
@@ -39,7 +39,7 @@ fn main() -> () {
         _2 = Option::<i32>::Some(const 1_i32); // scope 0 at $DIR/match_false_edges.rs:+1:19: +1:26
         FakeRead(ForMatchedPlace(None), _2); // scope 0 at $DIR/match_false_edges.rs:+1:19: +1:26
         _4 = discriminant(_2);           // scope 0 at $DIR/match_false_edges.rs:+1:19: +1:26
-        switchInt(move _4) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/match_false_edges.rs:+1:13: +1:26
+        switchInt(move _4) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/match_false_edges.rs:+1:13: +1:26
     }
 
     bb1: {
@@ -56,7 +56,7 @@ fn main() -> () {
 
     bb4: {
         _3 = discriminant(_2);           // scope 0 at $DIR/match_false_edges.rs:+1:19: +1:26
-        switchInt(move _3) -> [1_isize: bb6, otherwise: bb5]; // scope 0 at $DIR/match_false_edges.rs:+1:13: +1:26
+        switchInt(move _3) -> [1: bb6, otherwise: bb5]; // scope 0 at $DIR/match_false_edges.rs:+1:13: +1:26
     }
 
     bb5: {
@@ -87,7 +87,7 @@ fn main() -> () {
     }
 
     bb9: {
-        switchInt(move _8) -> [false: bb11, otherwise: bb10]; // scope 0 at $DIR/match_false_edges.rs:+2:21: +2:28
+        switchInt(move _8) -> [0: bb11, otherwise: bb10]; // scope 0 at $DIR/match_false_edges.rs:+2:21: +2:28
     }
 
     bb10: {
@@ -134,7 +134,7 @@ fn main() -> () {
     }
 
     bb15: {
-        switchInt(move _12) -> [false: bb17, otherwise: bb16]; // scope 0 at $DIR/match_false_edges.rs:+4:20: +4:29
+        switchInt(move _12) -> [0: bb17, otherwise: bb16]; // scope 0 at $DIR/match_false_edges.rs:+4:20: +4:29
     }
 
     bb16: {
index a4516026c3b47b748f11661169ba7260ee504f1a..aa2fd46320e137fa281c34109ea89ed27f5187b7 100644 (file)
@@ -6,7 +6,7 @@ fn match_bool(_1: bool) -> usize {
 
     bb0: {
         FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/simple_match.rs:+1:11: +1:12
-        switchInt(_1) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/simple_match.rs:+1:5: +1:12
+        switchInt(_1) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/simple_match.rs:+1:5: +1:12
     }
 
     bb1: {
index fade2d0bc6edf7890e10417738eac10e5a344278..a717d1bbd12f2c2ab965969cdebd33d9fdd30efa 100644 (file)
@@ -11,9 +11,9 @@
       bb0: {
 -         StorageLive(_2);                 // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
 -         _3 = discriminant(_1);           // scope 0 at $DIR/const_goto.rs:+1:17: +1:20
--         switchInt(move _3) -> [1_isize: bb2, 2_isize: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+-         switchInt(move _3) -> [1: bb2, 2: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
 +         _2 = discriminant(_1);           // scope 0 at $DIR/const_goto.rs:+1:17: +1:20
-+         switchInt(move _2) -> [1_isize: bb2, 2_isize: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++         switchInt(move _2) -> [1: bb2, 2: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       }
   
       bb1: {
@@ -29,7 +29,7 @@
 -     }
 - 
 -     bb3: {
--         switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+-         switchInt(move _2) -> [0: bb5, otherwise: bb4]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
 -     }
 - 
 -     bb4: {
index 623297aeba5062e240963802333e99c46c135f13..24be8c9b86845b8147db55dbfe373cf695a6eebb 100644 (file)
@@ -10,7 +10,7 @@
           StorageLive(_1);                 // scope 0 at $DIR/const_goto_const_eval_fail.rs:+1:11: +6:6
           StorageLive(_2);                 // scope 0 at $DIR/const_goto_const_eval_fail.rs:+2:15: +2:16
           _2 = const A;                    // scope 0 at $DIR/const_goto_const_eval_fail.rs:+2:15: +2:16
-          switchInt(_2) -> [1_i32: bb2, 2_i32: bb2, 3_i32: bb2, otherwise: bb1]; // scope 0 at $DIR/const_goto_const_eval_fail.rs:+2:9: +2:16
+          switchInt(_2) -> [1: bb2, 2: bb2, 3: bb2, otherwise: bb1]; // scope 0 at $DIR/const_goto_const_eval_fail.rs:+2:9: +2:16
       }
   
       bb1: {
       bb2: {
           _1 = const B;                    // scope 0 at $DIR/const_goto_const_eval_fail.rs:+3:26: +3:27
 -         goto -> bb3;                     // scope 0 at $DIR/const_goto_const_eval_fail.rs:+3:26: +3:27
-+         switchInt(_1) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/const_goto_const_eval_fail.rs:+1:5: +6:6
++         switchInt(_1) -> [0: bb4, otherwise: bb3]; // scope 0 at $DIR/const_goto_const_eval_fail.rs:+1:5: +6:6
       }
   
       bb3: {
--         switchInt(_1) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/const_goto_const_eval_fail.rs:+1:5: +6:6
+-         switchInt(_1) -> [0: bb5, otherwise: bb4]; // scope 0 at $DIR/const_goto_const_eval_fail.rs:+1:5: +6:6
 -     }
 - 
 -     bb4: {
index 81c356cb1db526b0373d8664983d63a44ae428ba..f54577259431da796336b9c52d937c479de6e213 100644 (file)
 -         StorageLive(_5);                 // scope 0 at $DIR/const_goto_storage.rs:+2:21: +2:52
 -         StorageLive(_6);                 // scope 0 at $DIR/const_goto_storage.rs:+2:24: +2:28
 -         _6 = const true;                 // scope 0 at $DIR/const_goto_storage.rs:+2:24: +2:28
--         switchInt(move _6) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/const_goto_storage.rs:+2:24: +2:28
+-         switchInt(move _6) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/const_goto_storage.rs:+2:24: +2:28
 +         StorageLive(_2);                 // scope 0 at $DIR/const_goto_storage.rs:+2:24: +2:28
 +         _2 = const true;                 // scope 0 at $DIR/const_goto_storage.rs:+2:24: +2:28
-+         switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/const_goto_storage.rs:+2:24: +2:28
++         switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/const_goto_storage.rs:+2:24: +2:28
       }
   
       bb1: {
@@ -41,7 +41,7 @@
 - 
 -     bb3: {
 -         StorageDead(_6);                 // scope 0 at $DIR/const_goto_storage.rs:+2:51: +2:52
--         switchInt(move _5) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/const_goto_storage.rs:+2:21: +2:52
+-         switchInt(move _5) -> [0: bb5, otherwise: bb4]; // scope 0 at $DIR/const_goto_storage.rs:+2:21: +2:52
 -     }
 - 
 -     bb4: {
@@ -56,7 +56,7 @@
 - 
 -     bb6: {
 -         StorageDead(_5);                 // scope 0 at $DIR/const_goto_storage.rs:+2:75: +2:76
--         switchInt(move _4) -> [false: bb8, otherwise: bb7]; // scope 0 at $DIR/const_goto_storage.rs:+2:18: +2:76
+-         switchInt(move _4) -> [0: bb8, otherwise: bb7]; // scope 0 at $DIR/const_goto_storage.rs:+2:18: +2:76
 -     }
 - 
 -     bb7: {
@@ -70,7 +70,7 @@
 -     }
 - 
 -     bb9: {
--         switchInt(move _3) -> [false: bb11, otherwise: bb10]; // scope 0 at $DIR/const_goto_storage.rs:+2:15: +6:10
+-         switchInt(move _3) -> [0: bb11, otherwise: bb10]; // scope 0 at $DIR/const_goto_storage.rs:+2:15: +6:10
 -     }
 - 
 -     bb10: {
index 8b3b9d0a4c1bbd87457eeb1322931cb4a80705a3..147670f8a915c4681eb853556097617f52ebf063 100644 (file)
@@ -9,8 +9,8 @@
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/control_flow_simplification.rs:+1:8: +1:21
           _1 = const _;                    // scope 0 at $DIR/control_flow_simplification.rs:+1:8: +1:21
--         switchInt(move _1) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/control_flow_simplification.rs:+1:8: +1:21
-+         switchInt(const false) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/control_flow_simplification.rs:+1:8: +1:21
+-         switchInt(move _1) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/control_flow_simplification.rs:+1:8: +1:21
++         switchInt(const false) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/control_flow_simplification.rs:+1:8: +1:21
       }
   
       bb1: {
index 6b29bb59c40dacc56c3161cb4bdfe71a6e0d6098..b4dccecc67265e74d5191fa6930acf8b1ee8e307 100644 (file)
           ((_3 as Some).0: bool) = const true; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
           discriminant(_3) = 1;            // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
 -         _4 = discriminant(_3);           // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
--         switchInt(move _4) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
+-         switchInt(move _4) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
 +         _4 = const 1_isize;              // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
-+         switchInt(const 1_isize) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
++         switchInt(const 1_isize) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
       }
   
       bb1: {
-          switchInt(((_3 as Some).0: bool)) -> [false: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
+          switchInt(((_3 as Some).0: bool)) -> [0: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
       }
   
       bb2: {
index 6b29bb59c40dacc56c3161cb4bdfe71a6e0d6098..b4dccecc67265e74d5191fa6930acf8b1ee8e307 100644 (file)
           ((_3 as Some).0: bool) = const true; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
           discriminant(_3) = 1;            // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
 -         _4 = discriminant(_3);           // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
--         switchInt(move _4) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
+-         switchInt(move _4) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
 +         _4 = const 1_isize;              // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
-+         switchInt(const 1_isize) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
++         switchInt(const 1_isize) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
       }
   
       bb1: {
-          switchInt(((_3 as Some).0: bool)) -> [false: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
+          switchInt(((_3 as Some).0: bool)) -> [0: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
       }
   
       bb2: {
index 9d7c2784d8b2cab9060446aac746879752e33243..ddc1a4493dbbf697a02a4a41f868e8fc83c7e8cb 100644 (file)
@@ -8,8 +8,8 @@
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/switch_int.rs:+1:11: +1:12
           _1 = const 1_i32;                // scope 0 at $DIR/switch_int.rs:+1:11: +1:12
--         switchInt(_1) -> [1_i32: bb2, otherwise: bb1]; // scope 0 at $DIR/switch_int.rs:+1:5: +1:12
-+         switchInt(const 1_i32) -> [1_i32: bb2, otherwise: bb1]; // scope 0 at $DIR/switch_int.rs:+1:5: +1:12
+-         switchInt(_1) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/switch_int.rs:+1:5: +1:12
++         switchInt(const 1_i32) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/switch_int.rs:+1:5: +1:12
       }
   
       bb1: {
index 74f9eafe42061cd0724e94a550eef3aa487dea20..09c47ee6e8309deaa6504a8c0f9d55faefc55223 100644 (file)
@@ -8,7 +8,7 @@
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/switch_int.rs:+1:11: +1:12
           _1 = const 1_i32;                // scope 0 at $DIR/switch_int.rs:+1:11: +1:12
--         switchInt(const 1_i32) -> [1_i32: bb2, otherwise: bb1]; // scope 0 at $DIR/switch_int.rs:+1:5: +1:12
+-         switchInt(const 1_i32) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/switch_int.rs:+1:5: +1:12
 +         goto -> bb2;                     // scope 0 at $DIR/switch_int.rs:+1:5: +1:12
       }
   
index fd21b14af25f3b8fcd1d3e1e0ef6b85d29e72c25..c4d389b2d764818426147cf1822148f1d089174d 100644 (file)
@@ -7,7 +7,7 @@ digraph Cov_0_3 {
     bcb1__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb1</td></tr><tr><td align="left" balign="left">Expression(bcb0 + bcb3) at 10:5-11:17<br align="left"/>    11:12-11:17: @2.Call: _2 = bar() -&gt; [return: bb3, unwind: bb6]</td></tr><tr><td align="left" balign="left">bb1: FalseUnwind<br align="left"/>bb2: Call</td></tr><tr><td align="left" balign="left">bb3: SwitchInt</td></tr></table>>];
     bcb0__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb0</td></tr><tr><td align="left" balign="left"></td></tr><tr><td align="left" balign="left">Counter(bcb0) at 9:1-9:11<br align="left"/>    </td></tr><tr><td align="left" balign="left">bb0: Goto</td></tr></table>>];
     bcb3__Cov_0_3 -> bcb1__Cov_0_3 [label=<>];
-    bcb1__Cov_0_3 -> bcb3__Cov_0_3 [label=<false>];
+    bcb1__Cov_0_3 -> bcb3__Cov_0_3 [label=<0>];
     bcb1__Cov_0_3 -> bcb2__Cov_0_3 [label=<otherwise>];
     bcb0__Cov_0_3 -> bcb1__Cov_0_3 [label=<>];
 }
index 2ced794e628f0462813e4f0065136af076984464..fce18fae4362f17224dfcc0ed6213575176167c5 100644 (file)
@@ -28,7 +28,7 @@
           discriminant(_1) = 0;            // scope 0 at $DIR/enum.rs:+1:13: +1:21
           StorageLive(_2);                 // scope 1 at $DIR/enum.rs:+2:9: +2:10
           _3 = discriminant(_1);           // scope 1 at $DIR/enum.rs:+2:19: +2:20
-          switchInt(move _3) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 1 at $DIR/enum.rs:+2:13: +2:20
+          switchInt(move _3) -> [0: bb3, 1: bb1, otherwise: bb2]; // scope 1 at $DIR/enum.rs:+2:13: +2:20
       }
   
       bb1: {
index 26808c70fbf2c42a711020001ff4790f24320c1e..32489b4bd6bfeb57987277e2e1fe14fea90ea0a8 100644 (file)
@@ -42,8 +42,8 @@
 +         _4 = const 1_i32;                // scope 1 at $DIR/if.rs:+2:16: +2:17
 +         _3 = const true;                 // scope 1 at $DIR/if.rs:+2:16: +2:22
           StorageDead(_4);                 // scope 1 at $DIR/if.rs:+2:21: +2:22
--         switchInt(move _3) -> [false: bb2, otherwise: bb1]; // scope 1 at $DIR/if.rs:+2:16: +2:22
-+         switchInt(const true) -> [false: bb2, otherwise: bb1]; // scope 1 at $DIR/if.rs:+2:16: +2:22
+-         switchInt(move _3) -> [0: bb2, otherwise: bb1]; // scope 1 at $DIR/if.rs:+2:16: +2:22
++         switchInt(const true) -> [0: bb2, otherwise: bb1]; // scope 1 at $DIR/if.rs:+2:16: +2:22
       }
   
       bb1: {
@@ -73,8 +73,8 @@
 +         _9 = const 1_i32;                // scope 3 at $DIR/if.rs:+5:16: +5:17
 +         _8 = const true;                 // scope 3 at $DIR/if.rs:+5:16: +5:22
           StorageDead(_9);                 // scope 3 at $DIR/if.rs:+5:21: +5:22
--         switchInt(move _8) -> [false: bb5, otherwise: bb4]; // scope 3 at $DIR/if.rs:+5:16: +5:22
-+         switchInt(const true) -> [false: bb5, otherwise: bb4]; // scope 3 at $DIR/if.rs:+5:16: +5:22
+-         switchInt(move _8) -> [0: bb5, otherwise: bb4]; // scope 3 at $DIR/if.rs:+5:16: +5:22
++         switchInt(const true) -> [0: bb5, otherwise: bb4]; // scope 3 at $DIR/if.rs:+5:16: +5:22
       }
   
       bb4: {
index 881d80f7c032606fa969eddf7adc8d4db00b2e89..5a87884977c39bc3b8aa7f711dc2159561ac4ef8 100644 (file)
@@ -10,8 +10,8 @@
           StorageLive(_1);                 // scope 0 at $DIR/issue_81605.rs:+1:9: +1:33
           StorageLive(_2);                 // scope 0 at $DIR/issue_81605.rs:+1:12: +1:16
           _2 = const true;                 // scope 0 at $DIR/issue_81605.rs:+1:12: +1:16
--         switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/issue_81605.rs:+1:12: +1:16
-+         switchInt(const true) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/issue_81605.rs:+1:12: +1:16
+-         switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/issue_81605.rs:+1:12: +1:16
++         switchInt(const true) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/issue_81605.rs:+1:12: +1:16
       }
   
       bb1: {
index 61d24c3b517fbfd84eb5f0977c7986ff81b839ff..80f8905adc92d93ae714a7b326a16ec22e6f11cd 100644 (file)
@@ -37,8 +37,8 @@
       }
   
       bb2: {
--         switchInt(move _5) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/cycle.rs:+3:11: +3:17
-+         switchInt(move _4) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/cycle.rs:+3:11: +3:17
+-         switchInt(move _5) -> [0: bb4, otherwise: bb3]; // scope 0 at $DIR/cycle.rs:+3:11: +3:17
++         switchInt(move _4) -> [0: bb4, otherwise: bb3]; // scope 0 at $DIR/cycle.rs:+3:11: +3:17
       }
   
       bb3: {
index fb18089e040f08a47e7a86c5457469059c050df4..210d3849e18a106bb1e76987b5934588e335ba34 100644 (file)
@@ -12,7 +12,7 @@
       bb0: {
           StorageLive(_3);                 // scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:8: +1:9
           _3 = _1;                         // scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:8: +1:9
-          switchInt(move _3) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:8: +1:9
+          switchInt(move _3) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:8: +1:9
       }
   
       bb1: {
index 995611f0e966416fdf9a7b938d2036e27e1c7dc0..3b1f81175cbfcc49148618d7a177f8522b0e7c8b 100644 (file)
           _7 = Len((*_2));                 // scope 0 at $DIR/deduplicate_blocks.rs:+2:9: +2:37
           _8 = const 4_usize;              // scope 0 at $DIR/deduplicate_blocks.rs:+2:9: +2:37
           _9 = Ge(move _7, move _8);       // scope 0 at $DIR/deduplicate_blocks.rs:+2:9: +2:37
-          switchInt(move _9) -> [false: bb6, otherwise: bb2]; // scope 0 at $DIR/deduplicate_blocks.rs:+2:9: +2:37
+          switchInt(move _9) -> [0: bb6, otherwise: bb2]; // scope 0 at $DIR/deduplicate_blocks.rs:+2:9: +2:37
       }
   
       bb2: {
-          switchInt((*_2)[0 of 4]) -> [47_u8: bb3, otherwise: bb6]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
+          switchInt((*_2)[0 of 4]) -> [47: bb3, otherwise: bb6]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
       }
   
       bb3: {
-          switchInt((*_2)[1 of 4]) -> [47_u8: bb4, otherwise: bb6]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
+          switchInt((*_2)[1 of 4]) -> [47: bb4, otherwise: bb6]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
       }
   
       bb4: {
-          switchInt((*_2)[2 of 4]) -> [47_u8: bb5, otherwise: bb6]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
+          switchInt((*_2)[2 of 4]) -> [47: bb5, otherwise: bb6]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
       }
   
       bb5: {
--         switchInt((*_2)[3 of 4]) -> [47_u8: bb11, otherwise: bb6]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
-+         switchInt((*_2)[3 of 4]) -> [47_u8: bb10, otherwise: bb6]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
+-         switchInt((*_2)[3 of 4]) -> [47: bb11, otherwise: bb6]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
++         switchInt((*_2)[3 of 4]) -> [47: bb10, otherwise: bb6]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
       }
   
       bb6: {
           _4 = Len((*_2));                 // scope 0 at $DIR/deduplicate_blocks.rs:+3:9: +3:31
           _5 = const 3_usize;              // scope 0 at $DIR/deduplicate_blocks.rs:+3:9: +3:31
           _6 = Ge(move _4, move _5);       // scope 0 at $DIR/deduplicate_blocks.rs:+3:9: +3:31
-          switchInt(move _6) -> [false: bb10, otherwise: bb7]; // scope 0 at $DIR/deduplicate_blocks.rs:+3:9: +3:31
+          switchInt(move _6) -> [0: bb10, otherwise: bb7]; // scope 0 at $DIR/deduplicate_blocks.rs:+3:9: +3:31
       }
   
       bb7: {
-          switchInt((*_2)[0 of 3]) -> [47_u8: bb8, otherwise: bb10]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
+          switchInt((*_2)[0 of 3]) -> [47: bb8, otherwise: bb10]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
       }
   
       bb8: {
-          switchInt((*_2)[1 of 3]) -> [47_u8: bb9, otherwise: bb10]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
+          switchInt((*_2)[1 of 3]) -> [47: bb9, otherwise: bb10]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
       }
   
       bb9: {
--         switchInt((*_2)[2 of 3]) -> [47_u8: bb12, 33_u8: bb13, otherwise: bb10]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
-+         switchInt((*_2)[2 of 3]) -> [47_u8: bb11, 33_u8: bb11, otherwise: bb10]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
+-         switchInt((*_2)[2 of 3]) -> [47: bb12, 33: bb13, otherwise: bb10]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
++         switchInt((*_2)[2 of 3]) -> [47: bb11, 33: bb11, otherwise: bb10]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
       }
   
       bb10: {
index 5b185082d4d87f839f31e472c7bdb5475b9a934d..9597a0c835fddd26907f92f59533943e9eb7b009 100644 (file)
@@ -17,7 +17,7 @@ fn foo(_1: Option<String>) -> i32 {
         _7 = const false;                // scope 0 at $DIR/string.rs:+1:11: +1:12
         _7 = const true;                 // scope 0 at $DIR/string.rs:+1:11: +1:12
         _5 = discriminant(_1);           // scope 0 at $DIR/string.rs:+1:11: +1:12
-        switchInt(move _5) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/string.rs:+1:5: +1:12
+        switchInt(move _5) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/string.rs:+1:5: +1:12
     }
 
     bb1: {
@@ -47,7 +47,7 @@ fn foo(_1: Option<String>) -> i32 {
     }
 
     bb4: {
-        switchInt(move _4) -> [false: bb1, otherwise: bb5]; // scope 0 at $DIR/string.rs:+2:14: +2:17
+        switchInt(move _4) -> [0: bb1, otherwise: bb5]; // scope 0 at $DIR/string.rs:+2:14: +2:17
     }
 
     bb5: {
@@ -69,6 +69,6 @@ fn foo(_1: Option<String>) -> i32 {
     }
 
     bb9: {
-        switchInt(_7) -> [false: bb7, otherwise: bb8]; // scope 0 at $DIR/string.rs:+5:1: +5:2
+        switchInt(_7) -> [0: bb7, otherwise: bb8]; // scope 0 at $DIR/string.rs:+5:1: +5:2
     }
 }
index 713d56c383613aad9ab9b9072b75f25252f762fc..fa3eeedc40fffee479371c748617291fe96cd852 100644 (file)
@@ -62,7 +62,7 @@
       bb3: {
           StorageDead(_8);                 // scope 1 at $DIR/derefer_complex_case.rs:+1:25: +1:26
           _10 = discriminant(_7);          // scope 1 at $DIR/derefer_complex_case.rs:+1:17: +1:26
-          switchInt(move _10) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 1 at $DIR/derefer_complex_case.rs:+1:17: +1:26
+          switchInt(move _10) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 1 at $DIR/derefer_complex_case.rs:+1:17: +1:26
       }
   
       bb4: {
index 60f7b9d5607b0ae646c83e0b6a652b3711b75f80..ab2388d1323a85cb6f0ab499ef9c1915fa0c6fc3 100644 (file)
           _6 = &_7;                        // scope 2 at $DIR/derefer_terminator_test.rs:+3:18: +3:21
           _5 = &_6;                        // scope 2 at $DIR/derefer_terminator_test.rs:+3:17: +3:21
           _4 = &_5;                        // scope 2 at $DIR/derefer_terminator_test.rs:+3:15: +3:22
--         switchInt((*(*(*(*_4))))) -> [false: bb3, otherwise: bb4]; // scope 2 at $DIR/derefer_terminator_test.rs:+3:5: +3:22
+-         switchInt((*(*(*(*_4))))) -> [0: bb3, otherwise: bb4]; // scope 2 at $DIR/derefer_terminator_test.rs:+3:5: +3:22
 +         _10 = deref_copy (*_4);          // scope 2 at $DIR/derefer_terminator_test.rs:+3:5: +3:22
 +         _11 = deref_copy (*_10);         // scope 2 at $DIR/derefer_terminator_test.rs:+3:5: +3:22
 +         _12 = deref_copy (*_11);         // scope 2 at $DIR/derefer_terminator_test.rs:+3:5: +3:22
-+         switchInt((*_12)) -> [false: bb3, otherwise: bb4]; // scope 2 at $DIR/derefer_terminator_test.rs:+3:5: +3:22
++         switchInt((*_12)) -> [0: bb3, otherwise: bb4]; // scope 2 at $DIR/derefer_terminator_test.rs:+3:5: +3:22
       }
   
       bb3: {
index 5fa7013d5ca762daba0f0a1ce1933be91a4b6497..9c729663265e087f5507fb2b769c4d0acbc81eaf 100644 (file)
@@ -37,7 +37,7 @@
       }
   
       bb2: {
-          switchInt(move _3) -> [false: bb4, otherwise: bb3]; // scope 1 at $DIR/branch.rs:+3:16: +3:22
+          switchInt(move _3) -> [0: bb4, otherwise: bb3]; // scope 1 at $DIR/branch.rs:+3:16: +3:22
       }
   
       bb3: {
diff --git a/src/test/mir-opt/dest-prop/unreachable.f.DestinationPropagation.diff b/src/test/mir-opt/dest-prop/unreachable.f.DestinationPropagation.diff
new file mode 100644 (file)
index 0000000..9ea756c
--- /dev/null
@@ -0,0 +1,86 @@
+- // MIR for `f` before DestinationPropagation
++ // MIR for `f` after DestinationPropagation
+  
+  fn f(_1: T) -> () {
+      debug a => _1;                       // in scope 0 at $DIR/unreachable.rs:+0:19: +0:20
+      let mut _0: ();                      // return place in scope 0 at $DIR/unreachable.rs:+0:25: +0:25
+      let _2: T;                           // in scope 0 at $DIR/unreachable.rs:+1:9: +1:10
+      let mut _3: bool;                    // in scope 0 at $DIR/unreachable.rs:+2:8: +2:13
+      let _4: ();                          // in scope 0 at $DIR/unreachable.rs:+3:9: +3:16
+      let mut _5: T;                       // in scope 0 at $DIR/unreachable.rs:+3:11: +3:12
+      let mut _6: T;                       // in scope 0 at $DIR/unreachable.rs:+3:14: +3:15
+      let _7: ();                          // in scope 0 at $DIR/unreachable.rs:+5:9: +5:16
+      let mut _8: T;                       // in scope 0 at $DIR/unreachable.rs:+5:11: +5:12
+      let mut _9: T;                       // in scope 0 at $DIR/unreachable.rs:+5:14: +5:15
+      scope 1 {
+-         debug b => _2;                   // in scope 1 at $DIR/unreachable.rs:+1:9: +1:10
++         debug b => _1;                   // in scope 1 at $DIR/unreachable.rs:+1:9: +1:10
+      }
+  
+      bb0: {
+-         StorageLive(_2);                 // scope 0 at $DIR/unreachable.rs:+1:9: +1:10
+-         _2 = _1;                         // scope 0 at $DIR/unreachable.rs:+1:13: +1:14
++         nop;                             // scope 0 at $DIR/unreachable.rs:+1:9: +1:10
++         nop;                             // scope 0 at $DIR/unreachable.rs:+1:13: +1:14
+          StorageLive(_3);                 // scope 1 at $DIR/unreachable.rs:+2:8: +2:13
+          _3 = const false;                // scope 1 at $DIR/unreachable.rs:+2:8: +2:13
+-         goto -> bb3;                     // scope 1 at $DIR/unreachable.rs:+2:8: +2:13
++         goto -> bb1;                     // scope 1 at $DIR/unreachable.rs:+2:8: +2:13
+      }
+  
+      bb1: {
+-         StorageLive(_4);                 // scope 1 at $DIR/unreachable.rs:+3:9: +3:16
+-         StorageLive(_5);                 // scope 1 at $DIR/unreachable.rs:+3:11: +3:12
+-         _5 = _1;                         // scope 1 at $DIR/unreachable.rs:+3:11: +3:12
+-         StorageLive(_6);                 // scope 1 at $DIR/unreachable.rs:+3:14: +3:15
+-         _6 = _2;                         // scope 1 at $DIR/unreachable.rs:+3:14: +3:15
+-         _4 = g::<T>(move _5, move _6) -> bb2; // scope 1 at $DIR/unreachable.rs:+3:9: +3:16
+-                                          // mir::Constant
+-                                          // + span: $DIR/unreachable.rs:11:9: 11:10
+-                                          // + literal: Const { ty: fn(T, T) {g::<T>}, val: Value(<ZST>) }
+-     }
+- 
+-     bb2: {
+-         StorageDead(_6);                 // scope 1 at $DIR/unreachable.rs:+3:15: +3:16
+-         StorageDead(_5);                 // scope 1 at $DIR/unreachable.rs:+3:15: +3:16
+-         StorageDead(_4);                 // scope 1 at $DIR/unreachable.rs:+3:16: +3:17
+-         _0 = const ();                   // scope 1 at $DIR/unreachable.rs:+2:14: +4:6
+-         goto -> bb5;                     // scope 1 at $DIR/unreachable.rs:+2:5: +6:6
+-     }
+- 
+-     bb3: {
+          StorageLive(_7);                 // scope 1 at $DIR/unreachable.rs:+5:9: +5:16
+-         StorageLive(_8);                 // scope 1 at $DIR/unreachable.rs:+5:11: +5:12
+-         _8 = _2;                         // scope 1 at $DIR/unreachable.rs:+5:11: +5:12
++         nop;                             // scope 1 at $DIR/unreachable.rs:+5:11: +5:12
++         nop;                             // scope 1 at $DIR/unreachable.rs:+5:11: +5:12
+          StorageLive(_9);                 // scope 1 at $DIR/unreachable.rs:+5:14: +5:15
+-         _9 = _2;                         // scope 1 at $DIR/unreachable.rs:+5:14: +5:15
+-         _7 = g::<T>(move _8, move _9) -> bb4; // scope 1 at $DIR/unreachable.rs:+5:9: +5:16
++         _9 = _1;                         // scope 1 at $DIR/unreachable.rs:+5:14: +5:15
++         _7 = g::<T>(move _1, move _9) -> bb2; // scope 1 at $DIR/unreachable.rs:+5:9: +5:16
+                                           // mir::Constant
+                                           // + span: $DIR/unreachable.rs:13:9: 13:10
+                                           // + literal: Const { ty: fn(T, T) {g::<T>}, val: Value(<ZST>) }
+      }
+  
+-     bb4: {
++     bb2: {
+          StorageDead(_9);                 // scope 1 at $DIR/unreachable.rs:+5:15: +5:16
+-         StorageDead(_8);                 // scope 1 at $DIR/unreachable.rs:+5:15: +5:16
++         nop;                             // scope 1 at $DIR/unreachable.rs:+5:15: +5:16
+          StorageDead(_7);                 // scope 1 at $DIR/unreachable.rs:+5:16: +5:17
+          _0 = const ();                   // scope 1 at $DIR/unreachable.rs:+4:12: +6:6
+-         goto -> bb5;                     // scope 1 at $DIR/unreachable.rs:+2:5: +6:6
++         goto -> bb3;                     // scope 1 at $DIR/unreachable.rs:+2:5: +6:6
+      }
+  
+-     bb5: {
++     bb3: {
+          StorageDead(_3);                 // scope 1 at $DIR/unreachable.rs:+6:5: +6:6
+-         StorageDead(_2);                 // scope 0 at $DIR/unreachable.rs:+7:1: +7:2
++         nop;                             // scope 0 at $DIR/unreachable.rs:+7:1: +7:2
+          return;                          // scope 0 at $DIR/unreachable.rs:+7:2: +7:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/dest-prop/unreachable.rs b/src/test/mir-opt/dest-prop/unreachable.rs
new file mode 100644 (file)
index 0000000..32b5def
--- /dev/null
@@ -0,0 +1,18 @@
+// Check that unreachable code is removed after the destination propagation.
+// Regression test for issue #105428.
+//
+// compile-flags: --crate-type=lib -Zmir-opt-level=0
+// compile-flags: -Zmir-enable-passes=+ConstProp,+SimplifyConstCondition-after-const-prop,+DestinationPropagation
+
+// EMIT_MIR unreachable.f.DestinationPropagation.diff
+pub fn f<T: Copy>(a: T) {
+    let b = a;
+    if false {
+        g(a, b);
+    } else {
+        g(b, b);
+    }
+}
+
+#[inline(never)]
+pub fn g<T: Copy>(_: T, _: T) {}
index 89d8106ae3ce7394079b1f33df0ca5e804fcebff..98a02ee38dd1769b2e6bd0cf5bcac0f74b14b2eb 100644 (file)
           StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
           StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
           _7 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
--         switchInt(move _7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+-         switchInt(move _7) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 +         StorageLive(_10);                // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 +         _10 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 +         StorageLive(_11);                // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 +         _11 = Ne(_7, move _10);          // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 +         StorageDead(_10);                // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
-+         switchInt(move _11) -> [false: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
++         switchInt(move _11) -> [0: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
       }
   
       bb1: {
@@ -49,7 +49,7 @@
   
       bb2: {
 -         _6 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
--         switchInt(move _6) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+-         switchInt(move _6) -> [1: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 -     }
 - 
 -     bb3: {
@@ -72,7 +72,7 @@
 + 
 +     bb4: {
 +         StorageDead(_11);                // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
-+         switchInt(_7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
++         switchInt(_7) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
       }
   }
   
index 1a9efa930036c40e0583477d27e55f5a2b3c1067..aa75c44b809a90543004dbd7f49c9ec9d949953c 100644 (file)
           StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
           StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
           _8 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
--         switchInt(move _8) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+-         switchInt(move _8) -> [0: bb1, 1: bb3, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 +         StorageLive(_11);                // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 +         _11 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 +         StorageLive(_12);                // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 +         _12 = Ne(_8, move _11);          // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 +         StorageDead(_11);                // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
-+         switchInt(move _12) -> [false: bb5, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
++         switchInt(move _12) -> [0: bb5, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
       }
   
       bb1: {
 -         _6 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
--         switchInt(move _6) -> [0_isize: bb5, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+-         switchInt(move _6) -> [0: bb5, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 -     }
 - 
 -     bb2: {
@@ -55,7 +55,7 @@
   
 -     bb3: {
 -         _7 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
--         switchInt(move _7) -> [1_isize: bb4, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+-         switchInt(move _7) -> [1: bb4, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 -     }
 - 
 -     bb4: {
@@ -86,7 +86,7 @@
 + 
 +     bb5: {
 +         StorageDead(_12);                // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
-+         switchInt(_8) -> [0_isize: bb3, 1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
++         switchInt(_8) -> [0: bb3, 1: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
       }
   }
   
index 309a72ae58b68d19fd25dad179090f67508f318e..cea6ff7cd05e07bd02d4a2c46194cb30969f9908 100644 (file)
           StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
           StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
           _7 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
--         switchInt(move _7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+-         switchInt(move _7) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 +         StorageLive(_10);                // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 +         _10 = discriminant((_3.1: std::option::Option<bool>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 +         StorageLive(_11);                // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 +         _11 = Ne(_7, move _10);          // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 +         StorageDead(_10);                // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
-+         switchInt(move _11) -> [false: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
++         switchInt(move _11) -> [0: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
       }
   
       bb1: {
@@ -49,7 +49,7 @@
   
       bb2: {
 -         _6 = discriminant((_3.1: std::option::Option<bool>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
--         switchInt(move _6) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+-         switchInt(move _6) -> [1: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 -     }
 - 
 -     bb3: {
@@ -72,7 +72,7 @@
 + 
 +     bb4: {
 +         StorageDead(_11);                // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
-+         switchInt(_7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
++         switchInt(_7) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
       }
   }
   
index 9574f32f7f06bd2c28b7d683a936add26f1f5ef7..b90d70ce43aa0ca0d884663a1a775d85a3a3edf6 100644 (file)
           StorageDead(_6);                 // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:19: +1:20
           StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:19: +1:20
           _10 = discriminant((_4.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:11: +1:20
--         switchInt(move _10) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
+-         switchInt(move _10) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
 +         StorageLive(_14);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
 +         _14 = discriminant((_4.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
 +         StorageLive(_15);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
 +         _15 = Ne(_10, move _14);         // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
 +         StorageDead(_14);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
-+         switchInt(move _15) -> [false: bb5, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
++         switchInt(move _15) -> [0: bb5, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
       }
   
       bb1: {
   
       bb2: {
 -         _9 = discriminant((_4.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:11: +1:20
--         switchInt(move _9) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
+-         switchInt(move _9) -> [1: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
 -     }
 - 
 -     bb3: {
           _8 = discriminant((_4.2: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:11: +1:20
--         switchInt(move _8) -> [1_isize: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
-+         switchInt(move _8) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
+-         switchInt(move _8) -> [1: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
++         switchInt(move _8) -> [1: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
       }
   
 -     bb4: {
@@ -94,7 +94,7 @@
 + 
 +     bb5: {
 +         StorageDead(_15);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
-+         switchInt(_10) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
++         switchInt(_10) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
       }
   }
   
index 6bc025bb5b204897dc703bc1ddfa995e634377de..9edd1a39f45f9b050f4a50d1d1c5875461e45ffe 100644 (file)
           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: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
+          switchInt(move _11) -> [0: bb1, 1: bb3, 2: bb4, 3: bb5, otherwise: bb2]; // 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
+          switchInt(move _7) -> [0: bb6, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
       }
   
       bb2: {
       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
+          switchInt(move _8) -> [1: 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
+          switchInt(move _9) -> [2: 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
+          switchInt(move _10) -> [3: bb9, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
       }
   
       bb6: {
index 321f57951b465309ffebc42d4c86b0d7dab64451..82d8b2fc5a463a740edb395c2c44968a2269f016 100644 (file)
           StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:16: +1:17
           StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:16: +1:17
           _8 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:11: +1:17
-          switchInt(move _8) -> [0_isize: bb1, 1_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:5: +1:17
+          switchInt(move _8) -> [0: bb1, 1: bb4, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:5: +1:17
       }
   
       bb1: {
           _6 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:11: +1:17
-          switchInt(move _6) -> [0_isize: bb2, 1_isize: bb7, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:5: +1:17
+          switchInt(move _6) -> [0: bb2, 1: bb7, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:5: +1:17
       }
   
       bb2: {
@@ -57,7 +57,7 @@
   
       bb4: {
           _7 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:11: +1:17
-          switchInt(move _7) -> [0_isize: bb6, 1_isize: bb5, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:5: +1:17
+          switchInt(move _7) -> [0: bb6, 1: bb5, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:5: +1:17
       }
   
       bb5: {
index 8b556acb2c4520a2382270a677f56e4218062923..a3fa2529b1868cb8a113059fb620c811a71b2633 100644 (file)
@@ -14,7 +14,7 @@
   
       bb0: {
           _3 = discriminant(_1);           // scope 0 at $DIR/early_otherwise_branch_soundness.rs:+1:11: +1:12
-          switchInt(move _3) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:+1:5: +1:12
+          switchInt(move _3) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:+1:5: +1:12
       }
   
       bb1: {
@@ -24,7 +24,7 @@
   
       bb2: {
           _4 = discriminant((*_2));        // scope 0 at $DIR/early_otherwise_branch_soundness.rs:+3:26: +3:28
-          switchInt(move _4) -> [1_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:+3:20: +3:28
+          switchInt(move _4) -> [1: bb4, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:+3:20: +3:28
       }
   
       bb3: {
index 659aed18f0436370ad71c3d48de54dbb09988a31..6d0224b547f4fe2036ac730d6e5b289ac1627328 100644 (file)
   
       bb0: {
           _3 = discriminant((*_1));        // scope 1 at $DIR/early_otherwise_branch_soundness.rs:+1:12: +1:31
-          switchInt(move _3) -> [1_isize: bb1, otherwise: bb3]; // scope 1 at $DIR/early_otherwise_branch_soundness.rs:+1:12: +1:31
+          switchInt(move _3) -> [1: bb1, otherwise: bb3]; // scope 1 at $DIR/early_otherwise_branch_soundness.rs:+1:12: +1:31
       }
   
       bb1: {
           _4 = deref_copy (((*_1) as Some).0: &E<'_>); // scope 1 at $DIR/early_otherwise_branch_soundness.rs:+1:12: +1:31
           _2 = discriminant((*_4));        // scope 1 at $DIR/early_otherwise_branch_soundness.rs:+1:12: +1:31
-          switchInt(move _2) -> [1_isize: bb2, otherwise: bb3]; // scope 1 at $DIR/early_otherwise_branch_soundness.rs:+1:12: +1:31
+          switchInt(move _2) -> [1: bb2, otherwise: bb3]; // scope 1 at $DIR/early_otherwise_branch_soundness.rs:+1:12: +1:31
       }
   
       bb2: {
index 89982308e71619408943b34bf1e16f0fab8943ad..8b542a7c19d63ae1f189275a83713485de931875 100644 (file)
@@ -14,7 +14,7 @@
 -         _2 = Eq(move _3, const true);    // scope 0 at $DIR/equal_true.rs:+1:8: +1:17
 +         _2 = move _3;                    // scope 0 at $DIR/equal_true.rs:+1:8: +1:17
           StorageDead(_3);                 // scope 0 at $DIR/equal_true.rs:+1:16: +1:17
-          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/equal_true.rs:+1:8: +1:17
+          switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/equal_true.rs:+1:8: +1:17
       }
   
       bb1: {
index 08481777ed494e81293c32dce0e85aa77ba168ca..ab955049965ada01ad44a6744c897e80d9f3fcdf 100644 (file)
@@ -19,7 +19,7 @@ fn match_tuple(_1: (u32, bool, Option<i32>, u32)) -> u32 {
 
     bb0: {
         FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/exponential_or.rs:+1:11: +1:12
-        switchInt((_1.0: u32)) -> [1_u32: bb2, 4_u32: bb2, otherwise: bb1]; // scope 0 at $DIR/exponential_or.rs:+2:15: +2:20
+        switchInt((_1.0: u32)) -> [1: bb2, 4: bb2, otherwise: bb1]; // scope 0 at $DIR/exponential_or.rs:+2:15: +2:20
     }
 
     bb1: {
@@ -29,31 +29,31 @@ fn match_tuple(_1: (u32, bool, Option<i32>, u32)) -> u32 {
 
     bb2: {
         _2 = discriminant((_1.2: std::option::Option<i32>)); // scope 0 at $DIR/exponential_or.rs:+2:37: +2:55
-        switchInt(move _2) -> [0_isize: bb4, 1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/exponential_or.rs:+2:37: +2:55
+        switchInt(move _2) -> [0: bb4, 1: bb3, otherwise: bb1]; // scope 0 at $DIR/exponential_or.rs:+2:37: +2:55
     }
 
     bb3: {
-        switchInt((((_1.2: std::option::Option<i32>) as Some).0: i32)) -> [1_i32: bb4, 8_i32: bb4, otherwise: bb1]; // scope 0 at $DIR/exponential_or.rs:+2:37: +2:55
+        switchInt((((_1.2: std::option::Option<i32>) as Some).0: i32)) -> [1: bb4, 8: bb4, otherwise: bb1]; // scope 0 at $DIR/exponential_or.rs:+2:37: +2:55
     }
 
     bb4: {
         _5 = Le(const 6_u32, (_1.3: u32)); // scope 0 at $DIR/exponential_or.rs:+2:62: +2:67
-        switchInt(move _5) -> [false: bb6, otherwise: bb5]; // scope 0 at $DIR/exponential_or.rs:+2:62: +2:67
+        switchInt(move _5) -> [0: bb6, otherwise: bb5]; // scope 0 at $DIR/exponential_or.rs:+2:62: +2:67
     }
 
     bb5: {
         _6 = Le((_1.3: u32), const 9_u32); // scope 0 at $DIR/exponential_or.rs:+2:62: +2:67
-        switchInt(move _6) -> [false: bb6, otherwise: bb8]; // scope 0 at $DIR/exponential_or.rs:+2:62: +2:67
+        switchInt(move _6) -> [0: bb6, otherwise: bb8]; // scope 0 at $DIR/exponential_or.rs:+2:62: +2:67
     }
 
     bb6: {
         _3 = Le(const 13_u32, (_1.3: u32)); // scope 0 at $DIR/exponential_or.rs:+2:70: +2:77
-        switchInt(move _3) -> [false: bb1, otherwise: bb7]; // scope 0 at $DIR/exponential_or.rs:+2:70: +2:77
+        switchInt(move _3) -> [0: bb1, otherwise: bb7]; // scope 0 at $DIR/exponential_or.rs:+2:70: +2:77
     }
 
     bb7: {
         _4 = Le((_1.3: u32), const 16_u32); // scope 0 at $DIR/exponential_or.rs:+2:70: +2:77
-        switchInt(move _4) -> [false: bb1, otherwise: bb8]; // scope 0 at $DIR/exponential_or.rs:+2:70: +2:77
+        switchInt(move _4) -> [0: bb1, otherwise: bb8]; // scope 0 at $DIR/exponential_or.rs:+2:70: +2:77
     }
 
     bb8: {
index 6ab63e82e35d28fdda6e0c376f47344509a50d56..c1c2cde71ab5b38f485885cd7f3a60bc4f13ad37 100644 (file)
@@ -47,7 +47,7 @@
       bb1: {
           StorageDead(_5);                 // scope 0 at $DIR/funky_arms.rs:+4:36: +4:37
           StorageLive(_6);                 // scope 1 at $DIR/funky_arms.rs:+8:9: +8:13
-          switchInt(_4) -> [false: bb3, otherwise: bb2]; // scope 1 at $DIR/funky_arms.rs:+8:16: +8:32
+          switchInt(_4) -> [0: bb3, otherwise: bb2]; // scope 1 at $DIR/funky_arms.rs:+8:16: +8:32
       }
   
       bb2: {
@@ -75,7 +75,7 @@
       bb5: {
           StorageDead(_8);                 // scope 3 at $DIR/funky_arms.rs:+13:44: +13:45
           _9 = discriminant(_7);           // scope 3 at $DIR/funky_arms.rs:+13:12: +13:27
-          switchInt(move _9) -> [1_isize: bb6, otherwise: bb8]; // scope 3 at $DIR/funky_arms.rs:+13:12: +13:27
+          switchInt(move _9) -> [1: bb6, otherwise: bb8]; // scope 3 at $DIR/funky_arms.rs:+13:12: +13:27
       }
   
       bb6: {
index c3b08bf0648925498c1891d1ecda038e9dfd02db..a8e090020c3d31bb70ee083e59d02adc982a4d36 100644 (file)
@@ -29,7 +29,7 @@ fn main::{closure#0}(_1: *mut [generator@$DIR/generator_drop_cleanup.rs:10:15: 1
 
     bb0: {
         _8 = discriminant((*_1));        // scope 0 at $DIR/generator_drop_cleanup.rs:+0:15: +3:6
-        switchInt(move _8) -> [0_u32: bb7, 3_u32: bb10, otherwise: bb11]; // scope 0 at $DIR/generator_drop_cleanup.rs:+0:15: +3:6
+        switchInt(move _8) -> [0: bb7, 3: bb10, otherwise: bb11]; // scope 0 at $DIR/generator_drop_cleanup.rs:+0:15: +3:6
     }
 
     bb1: {
index fee6da2c6352ff5b7667252d7ea87927938ae1c2..b3d3c768a5dd9a22ded6107eec3ec9f87c196c3c 100644 (file)
@@ -32,7 +32,7 @@ fn main::{closure#0}(_1: Pin<&mut [generator@$DIR/generator_tiny.rs:19:16: 19:24
 
     bb0: {
         _11 = discriminant((*(_1.0: &mut [generator@$DIR/generator_tiny.rs:19:16: 19:24]))); // scope 0 at $DIR/generator_tiny.rs:+0:16: +6:6
-        switchInt(move _11) -> [0_u32: bb1, 3_u32: bb5, otherwise: bb6]; // scope 0 at $DIR/generator_tiny.rs:+0:16: +6:6
+        switchInt(move _11) -> [0: bb1, 3: bb5, otherwise: bb6]; // scope 0 at $DIR/generator_tiny.rs:+0:16: +6:6
     }
 
     bb1: {
index 94180d203439902eabd66afd82477437b955c12d..de4235c9e9e935f7e65cf743d98593365495d122 100644 (file)
@@ -9,7 +9,7 @@
       bb0: {
           StorageLive(_2);                 // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9
           _2 = _1;                         // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9
-          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9
+          switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9
       }
   
       bb1: {
index b22c7eac622f543108726d383573110ba91e7c0c..754c6579af08fc3c91bc1a645e18e45ebe6090ba 100644 (file)
@@ -13,7 +13,7 @@
           _3 = _1;                         // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9
           _2 = Eq(move _3, const -42f32);  // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:18
           StorageDead(_3);                 // scope 0 at $DIR/if_condition_int.rs:+1:17: +1:18
-          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:18
+          switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:18
       }
   
       bb1: {
index cc0995f99cfdf237b7a02e21de93c3bf9bc61173..ff23839e29179fa1bb413e5ac09d2ac5820f2800 100644 (file)
           _3 = _1;                         // scope 0 at $DIR/if_condition_int.rs:+1:13: +1:14
 -         _2 = Eq(move _3, const 17_i8);   // scope 0 at $DIR/if_condition_int.rs:+1:13: +1:20
 -         StorageDead(_3);                 // scope 0 at $DIR/if_condition_int.rs:+1:19: +1:20
--         switchInt(_2) -> [false: bb2, otherwise: bb1]; // scope 1 at $DIR/if_condition_int.rs:+2:5: +2:12
+-         switchInt(_2) -> [0: bb2, otherwise: bb1]; // scope 1 at $DIR/if_condition_int.rs:+2:5: +2:12
 +         _2 = Eq(_3, const 17_i8);        // scope 0 at $DIR/if_condition_int.rs:+1:13: +1:20
 +         nop;                             // scope 0 at $DIR/if_condition_int.rs:+1:19: +1:20
-+         switchInt(move _3) -> [17_i8: bb1, otherwise: bb2]; // scope 1 at $DIR/if_condition_int.rs:+2:5: +2:12
++         switchInt(move _3) -> [17: bb1, otherwise: bb2]; // scope 1 at $DIR/if_condition_int.rs:+2:5: +2:12
       }
   
       bb1: {
index 801ea04020343105f203f423acd6466b509fe54e..5964d76a4b96f24149c2bddbf3081d38f05a1cbe 100644 (file)
           _3 = _1;                         // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9
 -         _2 = Eq(move _3, const 'x');     // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
 -         StorageDead(_3);                 // scope 0 at $DIR/if_condition_int.rs:+1:15: +1:16
--         switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
+-         switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
 +         nop;                             // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
 +         nop;                             // scope 0 at $DIR/if_condition_int.rs:+1:15: +1:16
-+         switchInt(move _3) -> ['x': bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
++         switchInt(move _3) -> [120: bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
       }
   
       bb1: {
index 4297f4d646645e4570a9f98090aea9c15664374e..98918cc743ce0efb6ad9f3661b30b3f4a21c9178 100644 (file)
           _3 = _1;                         // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9
 -         _2 = Eq(move _3, const 42_i8);   // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
 -         StorageDead(_3);                 // scope 0 at $DIR/if_condition_int.rs:+1:14: +1:15
--         switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
+-         switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
 +         nop;                             // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
 +         nop;                             // scope 0 at $DIR/if_condition_int.rs:+1:14: +1:15
-+         switchInt(move _3) -> [42_i8: bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
++         switchInt(move _3) -> [42: bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
       }
   
       bb1: {
index 8fb794abbd41fa89bba3dc7f76beeb00ea45d580..db38140b8d00b576c2bdbe4626894202908cb8d2 100644 (file)
           _3 = _1;                         // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9
 -         _2 = Eq(move _3, const 42_u32);  // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
 -         StorageDead(_3);                 // scope 0 at $DIR/if_condition_int.rs:+1:14: +1:15
--         switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
+-         switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
 +         nop;                             // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
 +         nop;                             // scope 0 at $DIR/if_condition_int.rs:+1:14: +1:15
-+         switchInt(move _3) -> [42_u32: bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
++         switchInt(move _3) -> [42: bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
       }
   
       bb1: {
           _5 = _1;                         // scope 0 at $DIR/if_condition_int.rs:+3:15: +3:16
 -         _4 = Ne(move _5, const 21_u32);  // scope 0 at $DIR/if_condition_int.rs:+3:15: +3:22
 -         StorageDead(_5);                 // scope 0 at $DIR/if_condition_int.rs:+3:21: +3:22
--         switchInt(move _4) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/if_condition_int.rs:+3:15: +3:22
+-         switchInt(move _4) -> [0: bb4, otherwise: bb3]; // scope 0 at $DIR/if_condition_int.rs:+3:15: +3:22
 +         nop;                             // scope 0 at $DIR/if_condition_int.rs:+3:15: +3:22
 +         nop;                             // scope 0 at $DIR/if_condition_int.rs:+3:21: +3:22
-+         switchInt(move _5) -> [21_u32: bb4, otherwise: bb3]; // scope 0 at $DIR/if_condition_int.rs:+3:15: +3:22
++         switchInt(move _5) -> [21: bb4, otherwise: bb3]; // scope 0 at $DIR/if_condition_int.rs:+3:15: +3:22
       }
   
       bb3: {
index 992253ea780d933cd4e2da77454e495b352c3480..1a1ac4caafaf0ee363dbd4097aab1cf5137604de 100644 (file)
           _3 = _1;                         // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9
 -         _2 = Eq(move _3, const -42_i32); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
 -         StorageDead(_3);                 // scope 0 at $DIR/if_condition_int.rs:+1:15: +1:16
--         switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
+-         switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
 +         nop;                             // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
 +         nop;                             // scope 0 at $DIR/if_condition_int.rs:+1:15: +1:16
-+         switchInt(move _3) -> [-42_i32: bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
++         switchInt(move _3) -> [4294967254: bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
       }
   
       bb1: {
index 7cea9472d3a05e4172bb242e65bdb972f6bb9cab..fc3f50227dcb93718c1e48496ecc29160c5d905c 100644 (file)
           _3 = _1;                         // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9
 -         _2 = Eq(move _3, const 42_u32);  // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
 -         StorageDead(_3);                 // scope 0 at $DIR/if_condition_int.rs:+1:14: +1:15
--         switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
+-         switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
 +         nop;                             // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
 +         nop;                             // scope 0 at $DIR/if_condition_int.rs:+1:14: +1:15
-+         switchInt(move _3) -> [42_u32: bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
++         switchInt(move _3) -> [42: bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
       }
   
       bb1: {
index 1e703a8fd2baf357508020763b0776f6e2c45245..b787a19f4b21c0d9c82050872e791553984abcbc 100644 (file)
@@ -19,7 +19,7 @@
           _3 = _1;                         // scope 0 at $DIR/inline_diverging.rs:+1:8: +1:9
           _2 = Gt(move _3, const 0_i32);   // scope 0 at $DIR/inline_diverging.rs:+1:8: +1:13
           StorageDead(_3);                 // scope 0 at $DIR/inline_diverging.rs:+1:12: +1:13
-          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/inline_diverging.rs:+1:8: +1:13
+          switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/inline_diverging.rs:+1:8: +1:13
       }
   
       bb1: {
index 91bff3d3234db25ab9dbcccf089da7d0e3492e54..bd21405f14b3fcc663cbefef4caa0fb860c690d1 100644 (file)
@@ -72,7 +72,7 @@
 +         _7 = const false;                // scope 0 at $DIR/inline_generator.rs:+1:14: +1:46
 +         _10 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline_generator.rs:15:5: 15:41
 +         _9 = discriminant((*_10));       // scope 6 at $DIR/inline_generator.rs:15:5: 15:41
-+         switchInt(move _9) -> [0_u32: bb3, 1_u32: bb8, 3_u32: bb7, otherwise: bb9]; // scope 6 at $DIR/inline_generator.rs:15:5: 15:41
++         switchInt(move _9) -> [0: bb3, 1: bb8, 3: bb7, otherwise: bb9]; // scope 6 at $DIR/inline_generator.rs:15:5: 15:41
       }
   
 -     bb3: {
@@ -92,7 +92,7 @@
 + 
 +     bb3: {
 +         StorageLive(_8);                 // scope 6 at $DIR/inline_generator.rs:15:17: 15:39
-+         switchInt(move _7) -> [false: bb5, otherwise: bb4]; // scope 6 at $DIR/inline_generator.rs:15:20: 15:21
++         switchInt(move _7) -> [0: bb5, otherwise: bb4]; // scope 6 at $DIR/inline_generator.rs:15:20: 15:21
 +     }
 + 
 +     bb4: {
index 75af20d482ddd22d88088d9cde6f977031e5a541..60149ff36064ecc3d87e433209e01328f5dc1843 100644 (file)
@@ -38,9 +38,7 @@ fn bar() -> bool {
                                          // + literal: Const { ty: &i32, val: Unevaluated(bar, [], Some(promoted[1])) }
         Retag(_10);                      // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9
         _4 = &(*_10);                    // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9
-        Retag(_4);                       // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9
         _3 = &(*_4);                     // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9
-        Retag(_3);                       // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9
         StorageLive(_6);                 // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
         StorageLive(_7);                 // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
         _9 = const _;                    // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
@@ -49,9 +47,7 @@ fn bar() -> bool {
                                          // + literal: Const { ty: &i32, val: Unevaluated(bar, [], Some(promoted[0])) }
         Retag(_9);                       // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
         _7 = &(*_9);                     // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
-        Retag(_7);                       // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
         _6 = &(*_7);                     // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
-        Retag(_6);                       // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
         Retag(_3);                       // scope 2 at $DIR/inline_retag.rs:16:8: 16:9
         Retag(_6);                       // scope 2 at $DIR/inline_retag.rs:16:17: 16:18
         StorageLive(_11);                // scope 2 at $DIR/inline_retag.rs:17:5: 17:7
index 7a54beca2336c06a16b08a36c7466415056b0174..36ddb189e0d3365eabea7fa2a977a89d9cb29fdf 100644 (file)
@@ -39,7 +39,7 @@
 +         StorageLive(_6);                 // scope 2 at $DIR/inline_shims.rs:+2:14: +2:40
 +         StorageLive(_7);                 // scope 2 at $DIR/inline_shims.rs:+2:14: +2:40
 +         _6 = discriminant((*_5));        // scope 3 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-+         switchInt(move _6) -> [0_isize: bb2, otherwise: bb3]; // scope 3 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
++         switchInt(move _6) -> [0: bb2, otherwise: bb3]; // scope 3 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
       }
   
       bb2: {
index 81d5528231db65fb0437724d99cde06f9dd27b0c..2f6f5f87efcc7a8c911a53a449660f9f0b61c53f 100644 (file)
@@ -26,7 +26,7 @@
       }
   
       bb3: {
-          switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at /the/src/instrument_coverage.rs:+2:12: +2:17
+          switchInt(move _2) -> [0: bb5, otherwise: bb4]; // scope 0 at /the/src/instrument_coverage.rs:+2:12: +2:17
       }
   
       bb4: {
index 82210081832c88d9a8d153963876aa7b1092e677..b0d5b291b6cb55c734a24f0f43c19eed94c4b341 100644 (file)
@@ -26,7 +26,7 @@ fn main() -> () {
         StorageLive(_3);                 // scope 1 at $DIR/issue_38669.rs:+3:9: +5:10
         StorageLive(_4);                 // scope 1 at $DIR/issue_38669.rs:+3:12: +3:24
         _4 = _1;                         // scope 1 at $DIR/issue_38669.rs:+3:12: +3:24
-        switchInt(move _4) -> [false: bb4, otherwise: bb3]; // scope 1 at $DIR/issue_38669.rs:+3:12: +3:24
+        switchInt(move _4) -> [0: bb4, otherwise: bb3]; // scope 1 at $DIR/issue_38669.rs:+3:12: +3:24
     }
 
     bb3: {
index c573ad5a8e4a406e385813b39ec2b70042761e60..c2ea3ac502f89dc3f89446f4700bea44444d19a4 100644 (file)
@@ -65,6 +65,6 @@ fn main() -> () {
     }
 
     bb8 (cleanup): {
-        switchInt(_5) -> [false: bb6, otherwise: bb7]; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
+        switchInt(_5) -> [0: bb6, otherwise: bb7]; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
     }
 }
index 470b032328184926af5acdefc16d5ebed1932bca..82989c3f071b43d39f022ca6dadc2e802aa7404e 100644 (file)
@@ -96,6 +96,6 @@ fn test() -> () {
     }
 
     bb14 (cleanup): {
-        switchInt(_6) -> [false: bb10, otherwise: bb13]; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
+        switchInt(_6) -> [0: bb10, otherwise: bb13]; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
     }
 }
index 73372c97bea7287fc19ed0388a8856ab1428ca81..00504273245b1d2a9acb320e5a5929061fb6a401 100644 (file)
@@ -33,7 +33,7 @@ fn main() -> () {
     }
 
     bb1: {
-        switchInt(move _2) -> [false: bb7, otherwise: bb2]; // scope 1 at $DIR/issue_41888.rs:+2:8: +2:14
+        switchInt(move _2) -> [0: bb7, otherwise: bb2]; // scope 1 at $DIR/issue_41888.rs:+2:8: +2:14
     }
 
     bb2: {
@@ -52,7 +52,7 @@ fn main() -> () {
     bb4: {
         StorageDead(_3);                 // scope 1 at $DIR/issue_41888.rs:+3:19: +3:20
         _5 = discriminant(_1);           // scope 2 at $DIR/issue_41888.rs:+4:16: +4:24
-        switchInt(move _5) -> [0_isize: bb5, otherwise: bb6]; // scope 2 at $DIR/issue_41888.rs:+4:16: +4:24
+        switchInt(move _5) -> [0: bb5, otherwise: bb6]; // scope 2 at $DIR/issue_41888.rs:+4:16: +4:24
     }
 
     bb5: {
@@ -134,19 +134,19 @@ fn main() -> () {
 
     bb19: {
         _10 = discriminant(_1);          // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
-        switchInt(move _10) -> [0_isize: bb15, otherwise: bb17]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
+        switchInt(move _10) -> [0: bb15, otherwise: bb17]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
     }
 
     bb20: {
-        switchInt(_7) -> [false: bb15, otherwise: bb19]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
+        switchInt(_7) -> [0: bb15, otherwise: bb19]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
     }
 
     bb21 (cleanup): {
         _11 = discriminant(_1);          // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
-        switchInt(move _11) -> [0_isize: bb16, otherwise: bb18]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
+        switchInt(move _11) -> [0: bb16, otherwise: bb18]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
     }
 
     bb22 (cleanup): {
-        switchInt(_7) -> [false: bb12, otherwise: bb21]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
+        switchInt(_7) -> [0: bb12, otherwise: bb21]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
     }
 }
index 6969a66ac19253a321282731d812fc2bb11c11f1..adfa3a7733b1d6ed1819c1b7a829d2939c7fade5 100644 (file)
@@ -52,7 +52,7 @@ fn test() -> Option<Box<u32>> {
     bb2: {
         StorageDead(_7);                 // scope 0 at $DIR/issue_62289.rs:+1:19: +1:20
         _8 = discriminant(_6);           // scope 0 at $DIR/issue_62289.rs:+1:15: +1:20
-        switchInt(move _8) -> [0_isize: bb3, 1_isize: bb5, otherwise: bb4]; // scope 0 at $DIR/issue_62289.rs:+1:15: +1:20
+        switchInt(move _8) -> [0: bb3, 1: bb5, otherwise: bb4]; // scope 0 at $DIR/issue_62289.rs:+1:15: +1:20
     }
 
     bb3: {
index b88cdfcbc96c257f403fef974795d5d0aeaaf627..17b81633991fec12dfa7ead2aa8edb71d8080e89 100644 (file)
           StorageDead(_17);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           _15 = Not(move _16);             // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageDead(_16);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          switchInt(move _15) -> [false: bb5, otherwise: bb4]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          switchInt(move _15) -> [0: bb5, otherwise: bb4]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       }
   
       bb4: {
index 3db40412b2ef47dc727e11d56429671df7c361ee..3e035c18db862f3adcda96875dce95195dda1ca9 100644 (file)
@@ -109,7 +109,7 @@ fn main() -> () {
         StorageDead(_12);                // scope 1 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         _10 = Not(move _11);             // scope 1 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         StorageDead(_11);                // scope 1 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-        switchInt(move _10) -> [false: bb4, otherwise: bb3]; // scope 1 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+        switchInt(move _10) -> [0: bb4, otherwise: bb3]; // scope 1 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
     }
 
     bb3: {
@@ -218,7 +218,7 @@ fn main() -> () {
         StorageDead(_33);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         _31 = Not(move _32);             // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         StorageDead(_32);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-        switchInt(move _31) -> [false: bb13, otherwise: bb12]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+        switchInt(move _31) -> [0: bb13, otherwise: bb12]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
     }
 
     bb12: {
index 5a2f4feff355263fa2db23b1d4e01977aee90145..e0d6b58f229c4a63be620ad3d46b16ac70629b9e 100644 (file)
@@ -47,7 +47,7 @@ fn num_to_digit(_1: char) -> u32 {
 
     bb2: {
         _7 = discriminant(_2);           // scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
-        switchInt(move _7) -> [0_isize: bb6, 1_isize: bb8, otherwise: bb7]; // scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
+        switchInt(move _7) -> [0: bb6, 1: bb8, otherwise: bb7]; // scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
     }
 
     bb3: {
@@ -66,7 +66,7 @@ fn num_to_digit(_1: char) -> u32 {
         StorageDead(_4);                 // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
         StorageDead(_5);                 // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
         StorageDead(_3);                 // scope 0 at $DIR/issue_59352.rs:+2:8: +2:23
-        switchInt(move _9) -> [1_isize: bb1, otherwise: bb3]; // scope 0 at $DIR/issue_59352.rs:+2:8: +2:23
+        switchInt(move _9) -> [1: bb1, otherwise: bb3]; // scope 0 at $DIR/issue_59352.rs:+2:8: +2:23
     }
 
     bb6: {
index 87066cc62c02a6b1e32dbab67c84bd7931997890..1c69a6232d60631e30f8b36dc538819916abf6bc 100644 (file)
   
       bb1: {
           StorageDead(_3);                 // scope 2 at $DIR/issue_75439.rs:+2:52: +2:53
-          switchInt(_2[0 of 4]) -> [0_u32: bb2, otherwise: bb8]; // scope 3 at $DIR/issue_75439.rs:+4:12: +4:30
+          switchInt(_2[0 of 4]) -> [0: bb2, otherwise: bb8]; // scope 3 at $DIR/issue_75439.rs:+4:12: +4:30
       }
   
       bb2: {
-          switchInt(_2[1 of 4]) -> [0_u32: bb3, otherwise: bb8]; // scope 3 at $DIR/issue_75439.rs:+4:12: +4:30
+          switchInt(_2[1 of 4]) -> [0: bb3, otherwise: bb8]; // scope 3 at $DIR/issue_75439.rs:+4:12: +4:30
       }
   
       bb3: {
-          switchInt(_2[2 of 4]) -> [0_u32: bb5, 4294901760_u32: bb6, otherwise: bb8]; // scope 3 at $DIR/issue_75439.rs:+4:12: +4:30
+          switchInt(_2[2 of 4]) -> [0: bb5, 4294901760: bb6, otherwise: bb8]; // scope 3 at $DIR/issue_75439.rs:+4:12: +4:30
       }
   
       bb4: {
index 5981ab885f90c9beea07295c5c0ef9e38a95a110..4ee2dae49b3f34652228d4b6b1379a4249313edf 100644 (file)
@@ -16,7 +16,7 @@ fn main() -> () {
         StorageLive(_1);                 // scope 0 at $DIR/loop_test.rs:+4:5: +6:6
         StorageLive(_2);                 // scope 0 at $DIR/loop_test.rs:+4:8: +4:12
         _2 = const true;                 // scope 0 at $DIR/loop_test.rs:+4:8: +4:12
-        switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/loop_test.rs:+4:8: +4:12
+        switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/loop_test.rs:+4:8: +4:12
     }
 
     bb1: {
index 049bbeac867f90a036751cca8a500e072a8e45d9..9bc7060e958ebf56c4083692fc647fcc9d746149 100644 (file)
@@ -38,7 +38,7 @@
           _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: bb4, otherwise: bb2]; // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
+          switchInt(move _3) -> [0: bb4, otherwise: bb2]; // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
       }
   
       bb2: {
index 40ec01eeb41a61167fce7775f2ac7287e1fa08b9..cf427cfd1e6dbb7a71c4b57401847c4b37cc500a 100644 (file)
@@ -41,7 +41,7 @@
           _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: bb4, otherwise: bb2]; // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
+          switchInt(move _3) -> [0: bb4, otherwise: bb2]; // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
       }
   
       bb2: {
index 9b1b07f38fcd3307627ad291a64371f8331df376..701c2ad705af2997fdf4e501f706819260a5bd27 100644 (file)
@@ -19,7 +19,7 @@ fn array_bound(_1: usize, _2: &[u8; N]) -> u8 {
         _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
+        switchInt(move _3) -> [0: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
     }
 
     bb1: {
index 29e379777b05894b824527199ce3f90e331c1938..0440cfce2893f152437667e746632f89763ecb4b 100644 (file)
@@ -22,7 +22,7 @@ fn array_bound_mut(_1: usize, _2: &mut [u8; N]) -> u8 {
         _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
+        switchInt(move _3) -> [0: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
     }
 
     bb1: {
index 5f5d6e68fdc17eeb606bde560efdaedee37e3f87..2b0370cf35800c3f157f81008023abdd6348d4c6 100644 (file)
@@ -33,7 +33,7 @@
           _3 = Lt(move _4, move _5);       // scope 0 at $DIR/lower_slice_len.rs:+1:8: +1:27
           StorageDead(_5);                 // scope 0 at $DIR/lower_slice_len.rs:+1:26: +1:27
           StorageDead(_4);                 // scope 0 at $DIR/lower_slice_len.rs:+1:26: +1:27
-          switchInt(move _3) -> [false: bb4, otherwise: bb2]; // scope 0 at $DIR/lower_slice_len.rs:+1:8: +1:27
+          switchInt(move _3) -> [0: bb4, otherwise: bb2]; // scope 0 at $DIR/lower_slice_len.rs:+1:8: +1:27
       }
   
       bb2: {
index d3db3b182717d3c2a1177b421aef1cb92ce4a218..84e4d35f908170560e24550e7d6239ecd7cdeae1 100644 (file)
   
       bb0: {
 -         FakeRead(ForMatchedPlace(None), _2); // scope 0 at $DIR/match_arm_scopes.rs:+1:11: +1:16
--         switchInt((_2.0: bool)) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
-+         switchInt((_2.0: bool)) -> [false: bb5, otherwise: bb1]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
+-         switchInt((_2.0: bool)) -> [0: bb1, otherwise: bb2]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
++         switchInt((_2.0: bool)) -> [0: bb5, otherwise: bb1]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
       }
   
       bb1: {
 -         falseEdge -> [real: bb8, imaginary: bb3]; // scope 0 at $DIR/match_arm_scopes.rs:+2:9: +2:22
-+         switchInt((_2.1: bool)) -> [false: bb10, otherwise: bb2]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
++         switchInt((_2.1: bool)) -> [0: bb10, otherwise: bb2]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
       }
   
       bb2: {
--         switchInt((_2.1: bool)) -> [false: bb3, otherwise: bb4]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
-+         switchInt((_2.0: bool)) -> [false: bb3, otherwise: bb17]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
+-         switchInt((_2.1: bool)) -> [0: bb3, otherwise: bb4]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
++         switchInt((_2.0: bool)) -> [0: bb3, otherwise: bb17]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
       }
   
       bb3: {
@@ -51,7 +51,7 @@
 -     }
 - 
 -     bb4: {
--         switchInt((_2.0: bool)) -> [false: bb6, otherwise: bb5]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
+-         switchInt((_2.0: bool)) -> [0: bb6, otherwise: bb5]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
 -     }
 - 
 -     bb5: {
@@ -85,8 +85,8 @@
           StorageLive(_9);                 // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73
           StorageLive(_10);                // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
           _10 = _1;                        // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
--         switchInt(move _10) -> [false: bb10, otherwise: bb9]; // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
-+         switchInt(move _10) -> [false: bb7, otherwise: bb6]; // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
+-         switchInt(move _10) -> [0: bb10, otherwise: bb9]; // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
++         switchInt(move _10) -> [0: bb7, otherwise: bb6]; // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
       }
   
 -     bb9: {
 -     bb10: {
 +     bb7: {
           _9 = (*_6);                      // scope 0 at $DIR/match_arm_scopes.rs:+2:70: +2:71
--         switchInt(move _9) -> [false: bb12, otherwise: bb11]; // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73
-+         switchInt(move _9) -> [false: bb9, otherwise: bb8]; // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73
+-         switchInt(move _9) -> [0: bb12, otherwise: bb11]; // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73
++         switchInt(move _9) -> [0: bb9, otherwise: bb8]; // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73
       }
   
 -     bb11: {
           StorageLive(_12);                // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73
           StorageLive(_13);                // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
           _13 = _1;                        // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
--         switchInt(move _13) -> [false: bb15, otherwise: bb14]; // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
-+         switchInt(move _13) -> [false: bb12, otherwise: bb11]; // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
+-         switchInt(move _13) -> [0: bb15, otherwise: bb14]; // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
++         switchInt(move _13) -> [0: bb12, otherwise: bb11]; // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
       }
   
 -     bb14: {
 -     bb15: {
 +     bb12: {
           _12 = (*_6);                     // scope 0 at $DIR/match_arm_scopes.rs:+2:70: +2:71
--         switchInt(move _12) -> [false: bb17, otherwise: bb16]; // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73
-+         switchInt(move _12) -> [false: bb14, otherwise: bb13]; // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73
+-         switchInt(move _12) -> [0: bb17, otherwise: bb16]; // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73
++         switchInt(move _12) -> [0: bb14, otherwise: bb13]; // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73
       }
   
 -     bb16: {
index b184ffc404e6bb05d6eadcde84a7b86deda955f8..d51dbf4258c541ba8eb8bde8b49c1fdd325f335c 100644 (file)
@@ -28,12 +28,12 @@ fn main() -> () {
         StorageLive(_3);                 // scope 2 at $DIR/match_test.rs:+6:5: +11:6
         FakeRead(ForMatchedPlace(None), _1); // scope 2 at $DIR/match_test.rs:+6:11: +6:12
         _6 = Le(const 0_i32, _1);        // scope 2 at $DIR/match_test.rs:+7:9: +7:14
-        switchInt(move _6) -> [false: bb4, otherwise: bb1]; // scope 2 at $DIR/match_test.rs:+7:9: +7:14
+        switchInt(move _6) -> [0: bb4, otherwise: bb1]; // scope 2 at $DIR/match_test.rs:+7:9: +7:14
     }
 
     bb1: {
         _7 = Lt(_1, const 10_i32);       // scope 2 at $DIR/match_test.rs:+7:9: +7:14
-        switchInt(move _7) -> [false: bb4, otherwise: bb2]; // scope 2 at $DIR/match_test.rs:+7:9: +7:14
+        switchInt(move _7) -> [0: bb4, otherwise: bb2]; // scope 2 at $DIR/match_test.rs:+7:9: +7:14
     }
 
     bb2: {
@@ -47,12 +47,12 @@ fn main() -> () {
 
     bb4: {
         _4 = Le(const 10_i32, _1);       // scope 2 at $DIR/match_test.rs:+8:9: +8:16
-        switchInt(move _4) -> [false: bb7, otherwise: bb5]; // scope 2 at $DIR/match_test.rs:+8:9: +8:16
+        switchInt(move _4) -> [0: bb7, otherwise: bb5]; // scope 2 at $DIR/match_test.rs:+8:9: +8:16
     }
 
     bb5: {
         _5 = Le(_1, const 20_i32);       // scope 2 at $DIR/match_test.rs:+8:9: +8:16
-        switchInt(move _5) -> [false: bb7, otherwise: bb6]; // scope 2 at $DIR/match_test.rs:+8:9: +8:16
+        switchInt(move _5) -> [0: bb7, otherwise: bb6]; // scope 2 at $DIR/match_test.rs:+8:9: +8:16
     }
 
     bb6: {
@@ -60,7 +60,7 @@ fn main() -> () {
     }
 
     bb7: {
-        switchInt(_1) -> [-1_i32: bb8, otherwise: bb3]; // scope 2 at $DIR/match_test.rs:+6:5: +6:12
+        switchInt(_1) -> [4294967295: bb8, otherwise: bb3]; // scope 2 at $DIR/match_test.rs:+6:5: +6:12
     }
 
     bb8: {
@@ -71,7 +71,7 @@ fn main() -> () {
         _8 = &shallow _1;                // scope 2 at $DIR/match_test.rs:+6:11: +6:12
         StorageLive(_9);                 // scope 2 at $DIR/match_test.rs:+7:18: +7:19
         _9 = _2;                         // scope 2 at $DIR/match_test.rs:+7:18: +7:19
-        switchInt(move _9) -> [false: bb11, otherwise: bb10]; // scope 2 at $DIR/match_test.rs:+7:18: +7:19
+        switchInt(move _9) -> [0: bb11, otherwise: bb10]; // scope 2 at $DIR/match_test.rs:+7:18: +7:19
     }
 
     bb10: {
index f9eeb1ea5b96095be840b3afd1c193409cdb55ba..be91b0bfe6820f1ea61ef4ee00ab1d9ca4109a06 100644 (file)
@@ -33,7 +33,7 @@
           StorageLive(_4);                 // scope 2 at $DIR/matches_reduce_branches.rs:+3:9: +3:10
           StorageLive(_5);                 // scope 3 at $DIR/matches_reduce_branches.rs:+4:9: +4:10
           StorageLive(_6);                 // scope 4 at $DIR/matches_reduce_branches.rs:+6:5: +21:6
--         switchInt(_1) -> [7_i32: bb2, otherwise: bb1]; // scope 4 at $DIR/matches_reduce_branches.rs:+6:5: +6:12
+-         switchInt(_1) -> [7: bb2, otherwise: bb1]; // scope 4 at $DIR/matches_reduce_branches.rs:+6:5: +6:12
 -     }
 - 
 -     bb1: {
index 0b40b3be8bdd41efd5e773ab32228a05b64f394c..aa8092ece663a7e53b8cd3efa017ffc6cf763c8e 100644 (file)
       bb0: {
           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
+-         switchInt(move _3) -> [0: 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
++         switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       }
   
       bb1: {
@@ -30,7 +30,7 @@
 -     }
 - 
 -     bb3: {
--         switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+-         switchInt(move _2) -> [0: bb5, otherwise: bb4]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
 -     }
 - 
 -     bb4: {
index b8c7722cd3713c905b31331b98b0cc2623594660..193104dd30e7e3e711c46390732435ce5cfd704e 100644 (file)
@@ -26,7 +26,7 @@
           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
+-         switchInt(move _6) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
 -     }
 - 
 -     bb1: {
@@ -45,7 +45,7 @@
 +         _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
+-         switchInt(move _5) -> [0: bb5, otherwise: bb4]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
 -     }
 - 
 -     bb4: {
@@ -64,7 +64,7 @@
 +         _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
+-         switchInt(move _4) -> [0: bb8, otherwise: bb7]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
 -     }
 - 
 -     bb7: {
@@ -78,7 +78,7 @@
 -     }
 - 
 -     bb9: {
--         switchInt(move _3) -> [false: bb11, otherwise: bb10]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
+-         switchInt(move _3) -> [0: bb11, otherwise: bb10]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
 -     }
 - 
 -     bb10: {
index 1b4dddc1d43a030a725a4793feb833d5ae40cad4..3766d99a43b3b01d2f8f27702da114456e8a324e 100644 (file)
@@ -8,7 +8,7 @@
   
       bb0: {
           _2 = discriminant(_1);           // scope 0 at $DIR/matches_u8.rs:+1:11: +1:12
-          switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/matches_u8.rs:+1:5: +1:12
+          switchInt(move _2) -> [0: bb3, 1: bb1, otherwise: bb2]; // scope 0 at $DIR/matches_u8.rs:+1:5: +1:12
       }
   
       bb1: {
index 6e734852e1af490fec52362d823beb6ab07e7b2d..b5146cd539f396425714f2d50d210e96e6a8e4b1 100644 (file)
@@ -8,7 +8,7 @@
   
       bb0: {
           _2 = discriminant(_1);           // scope 0 at $DIR/matches_u8.rs:+1:11: +1:12
-          switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/matches_u8.rs:+1:5: +1:12
+          switchInt(move _2) -> [0: bb3, 1: bb1, otherwise: bb2]; // scope 0 at $DIR/matches_u8.rs:+1:5: +1:12
       }
   
       bb1: {
index 3e3fda6141aec93fb430e9e8dd3853b9baab523c..8e6564a38b0bbbaafe2dfd25125cdb4c2efefaf2 100644 (file)
@@ -62,7 +62,7 @@ fn main() -> () {
         FakeRead(ForLet(None), _6);      // bb1[4]: scope 2 at $DIR/region_subtyping_basic.rs:+3:9: +3:10
         StorageLive(_7);                 // bb1[5]: scope 3 at $DIR/region_subtyping_basic.rs:+4:8: +4:12
         _7 = const ConstValue(Scalar(0x01): bool); // bb1[6]: scope 3 at $DIR/region_subtyping_basic.rs:+4:8: +4:12
-        switchInt(move _7) -> [ConstValue(Scalar(0x00): bool): bb4, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region_subtyping_basic.rs:+4:8: +4:12
+        switchInt(move _7) -> [0: bb4, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region_subtyping_basic.rs:+4:8: +4:12
     }
 
     bb2: {
index 39a53702a4cbb6921c0cb35bc5d2e7d6558349ff..74d44c6741a92747b01cf35d5f7d1b52324ff91e 100644 (file)
@@ -62,7 +62,7 @@ fn main() -> () {
         FakeRead(ForLet(None), _6);      // bb1[4]: scope 2 at $DIR/region_subtyping_basic.rs:+3:9: +3:10
         StorageLive(_7);                 // bb1[5]: scope 3 at $DIR/region_subtyping_basic.rs:+4:8: +4:12
         _7 = const ConstValue(Scalar(0x01): bool); // bb1[6]: scope 3 at $DIR/region_subtyping_basic.rs:+4:8: +4:12
-        switchInt(move _7) -> [ConstValue(Scalar(0x00): bool): bb4, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region_subtyping_basic.rs:+4:8: +4:12
+        switchInt(move _7) -> [0: bb4, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region_subtyping_basic.rs:+4:8: +4:12
     }
 
     bb2: {
index e708255cea4304adb10b16ef597f21b54dad1b97..69327b7afac7ec3d59cce6f5f5eb20af5501da9a 100644 (file)
@@ -15,7 +15,7 @@ fn unwrap(_1: Option<T>) -> T {
 
     bb0: {
         _2 = discriminant(_1);           // scope 0 at $DIR/no_drop_for_inactive_variant.rs:+1:11: +1:14
-        switchInt(move _2) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/no_drop_for_inactive_variant.rs:+1:5: +1:14
+        switchInt(move _2) -> [0: bb1, 1: bb3, otherwise: bb2]; // scope 0 at $DIR/no_drop_for_inactive_variant.rs:+1:5: +1:14
     }
 
     bb1: {
index 5009d090668f0630c78791906544ea3dbfed39ee..b558c35ac1eeb8a6331e65622ab69bc4364e4cc3 100644 (file)
@@ -14,7 +14,7 @@
 -         _2 = Ne(move _3, const false);   // scope 0 at $DIR/not_equal_false.rs:+1:8: +1:18
 +         _2 = move _3;                    // scope 0 at $DIR/not_equal_false.rs:+1:8: +1:18
           StorageDead(_3);                 // scope 0 at $DIR/not_equal_false.rs:+1:17: +1:18
-          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/not_equal_false.rs:+1:8: +1:18
+          switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/not_equal_false.rs:+1:8: +1:18
       }
   
       bb1: {
index 243a54b6a8454d68ca0a50e4a570535b80be20d9..bb5920b28ca9456e0aae3e953ae2baa5de7d13b5 100644 (file)
@@ -16,7 +16,7 @@
 -         FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/remove_fake_borrows.rs:+1:11: +1:12
 +         nop;                             // scope 0 at $DIR/remove_fake_borrows.rs:+1:11: +1:12
           _3 = discriminant(_1);           // scope 0 at $DIR/remove_fake_borrows.rs:+1:11: +1:12
-          switchInt(move _3) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/remove_fake_borrows.rs:+1:5: +1:12
+          switchInt(move _3) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/remove_fake_borrows.rs:+1:5: +1:12
       }
   
       bb1: {
@@ -25,7 +25,7 @@
       }
   
       bb2: {
-          switchInt((*(*((_1 as Some).0: &&i32)))) -> [0_i32: bb3, otherwise: bb1]; // scope 0 at $DIR/remove_fake_borrows.rs:+1:5: +1:12
+          switchInt((*(*((_1 as Some).0: &&i32)))) -> [0: bb3, otherwise: bb1]; // scope 0 at $DIR/remove_fake_borrows.rs:+1:5: +1:12
       }
   
       bb3: {
@@ -43,7 +43,7 @@
 +         nop;                             // scope 0 at $DIR/remove_fake_borrows.rs:+1:11: +1:12
           StorageLive(_8);                 // scope 0 at $DIR/remove_fake_borrows.rs:+2:20: +2:21
           _8 = _2;                         // scope 0 at $DIR/remove_fake_borrows.rs:+2:20: +2:21
-          switchInt(move _8) -> [false: bb6, otherwise: bb5]; // scope 0 at $DIR/remove_fake_borrows.rs:+2:20: +2:21
+          switchInt(move _8) -> [0: bb6, otherwise: bb5]; // scope 0 at $DIR/remove_fake_borrows.rs:+2:20: +2:21
       }
   
       bb5: {
index 188aa55649069a7951e43495e09cd43a6fc9d358..ed1d0b87f603373ada39bd462539ebbf2207f29a 100644 (file)
@@ -63,7 +63,7 @@
       bb3: {
 -         StorageDead(_8);                 // scope 2 at $DIR/remove_storage_markers.rs:+2:18: +2:19
           _10 = discriminant(_7);          // scope 2 at $DIR/remove_storage_markers.rs:+2:14: +2:19
-          switchInt(move _10) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 2 at $DIR/remove_storage_markers.rs:+2:14: +2:19
+          switchInt(move _10) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 2 at $DIR/remove_storage_markers.rs:+2:14: +2:19
       }
   
       bb4: {
index fe57e32a7acc236cc8e7728e8d878db194cd766f..19b726e74845392e72cec5427d02ef1543fd047d 100644 (file)
@@ -68,9 +68,7 @@ fn array_casts() -> () {
         StorageLive(_3);                 // scope 1 at $DIR/retag.rs:+2:13: +2:19
         StorageLive(_4);                 // scope 1 at $DIR/retag.rs:+2:13: +2:19
         _4 = &mut _1;                    // scope 1 at $DIR/retag.rs:+2:13: +2:19
-        Retag(_4);                       // scope 1 at $DIR/retag.rs:+2:13: +2:19
         _3 = &raw mut (*_4);             // scope 1 at $DIR/retag.rs:+2:13: +2:19
-        Retag([raw] _3);                 // scope 1 at $DIR/retag.rs:+2:13: +2:19
         _2 = move _3 as *mut usize (Pointer(ArrayToPointer)); // scope 1 at $DIR/retag.rs:+2:13: +2:33
         StorageDead(_3);                 // scope 1 at $DIR/retag.rs:+2:32: +2:33
         StorageDead(_4);                 // scope 1 at $DIR/retag.rs:+2:33: +2:34
@@ -96,9 +94,7 @@ fn array_casts() -> () {
         StorageLive(_10);                // scope 4 at $DIR/retag.rs:+6:13: +6:15
         StorageLive(_11);                // scope 4 at $DIR/retag.rs:+6:13: +6:15
         _11 = &_8;                       // scope 4 at $DIR/retag.rs:+6:13: +6:15
-        Retag(_11);                      // scope 4 at $DIR/retag.rs:+6:13: +6:15
         _10 = &raw const (*_11);         // scope 4 at $DIR/retag.rs:+6:13: +6:15
-        Retag([raw] _10);                // scope 4 at $DIR/retag.rs:+6:13: +6:15
         _9 = move _10 as *const usize (Pointer(ArrayToPointer)); // scope 4 at $DIR/retag.rs:+6:13: +6:31
         StorageDead(_10);                // scope 4 at $DIR/retag.rs:+6:30: +6:31
         StorageDead(_11);                // scope 4 at $DIR/retag.rs:+6:31: +6:32
@@ -119,7 +115,6 @@ fn array_casts() -> () {
         StorageDead(_17);                // scope 6 at $DIR/retag.rs:+7:33: +7:34
         _15 = (*_16);                    // scope 6 at $DIR/retag.rs:+7:25: +7:34
         _14 = &_15;                      // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-        Retag(_14);                      // 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
         _35 = const _;                   // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                          // mir::Constant
@@ -127,7 +122,6 @@ fn array_casts() -> () {
                                          // + literal: Const { ty: &usize, val: Unevaluated(array_casts, [], Some(promoted[0])) }
         Retag(_35);                      // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         _18 = &(*_35);                   // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-        Retag(_18);                      // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         Deinit(_13);                     // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         (_13.0: &usize) = move _14;      // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         (_13.1: &usize) = move _18;      // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
@@ -151,7 +145,7 @@ fn array_casts() -> () {
         StorageDead(_24);                // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         _22 = Not(move _23);             // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         StorageDead(_23);                // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-        switchInt(move _22) -> [false: bb4, otherwise: bb3]; // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+        switchInt(move _22) -> [0: bb4, otherwise: bb3]; // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
     }
 
     bb3: {
@@ -164,15 +158,11 @@ fn array_casts() -> () {
         StorageLive(_30);                // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         StorageLive(_31);                // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         _31 = &(*_20);                   // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-        Retag(_31);                      // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         _30 = &(*_31);                   // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-        Retag(_30);                      // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         StorageLive(_32);                // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         StorageLive(_33);                // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         _33 = &(*_21);                   // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-        Retag(_33);                      // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         _32 = &(*_33);                   // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-        Retag(_32);                      // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         StorageLive(_34);                // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         Deinit(_34);                     // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         discriminant(_34) = 0;           // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
index cdc413c568f184c485e83c6d6143ec741493f1ce..14f297e948bec91b29791e7fce4c216c06c76458 100644 (file)
@@ -6,7 +6,6 @@ fn std::ptr::drop_in_place(_1: *mut Test) -> () {
     let mut _3: ();                      // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
 
     bb0: {
-        Retag([raw] _1);                 // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
         _2 = &mut (*_1);                 // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
         _3 = <Test as Drop>::drop(move _2) -> bb1; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
                                          // mir::Constant
index 96fc7e6493ab94dc7e19a5e503c4bcd87791ef01..9e5c119a2b24e3300dcca541b860c806c37efe34 100644 (file)
@@ -15,7 +15,6 @@ fn main::{closure#0}(_1: &[closure@main::{closure#0}], _2: &i32) -> &i32 {
         _3 = _2;                         // scope 0 at $DIR/retag.rs:+1:18: +1:19
         Retag(_3);                       // scope 0 at $DIR/retag.rs:+1:18: +1:19
         _0 = &(*_2);                     // scope 1 at $DIR/retag.rs:+2:9: +2:10
-        Retag(_0);                       // scope 1 at $DIR/retag.rs:+2:9: +2:10
         StorageDead(_3);                 // scope 0 at $DIR/retag.rs:+3:5: +3:6
         return;                          // scope 0 at $DIR/retag.rs:+3:6: +3:6
     }
index 81225b44ebf9fd5d572e1d250ef6e3cfd46f068f..b853e450541729d82ad1b577e63cd67309746209 100644 (file)
@@ -65,13 +65,10 @@ fn main() -> () {
         Deinit(_5);                      // scope 1 at $DIR/retag.rs:+3:17: +3:24
         (_5.0: i32) = const 0_i32;       // scope 1 at $DIR/retag.rs:+3:17: +3:24
         _4 = &_5;                        // scope 1 at $DIR/retag.rs:+3:17: +3:36
-        Retag(_4);                       // scope 1 at $DIR/retag.rs:+3:17: +3:36
         StorageLive(_6);                 // scope 1 at $DIR/retag.rs:+3:29: +3:35
         StorageLive(_7);                 // scope 1 at $DIR/retag.rs:+3:29: +3:35
         _7 = &mut _1;                    // scope 1 at $DIR/retag.rs:+3:29: +3:35
-        Retag(_7);                       // scope 1 at $DIR/retag.rs:+3:29: +3:35
         _6 = &mut (*_7);                 // scope 1 at $DIR/retag.rs:+3:29: +3:35
-        Retag([2phase] _6);              // scope 1 at $DIR/retag.rs:+3:29: +3:35
         _3 = Test::foo(move _4, move _6) -> [return: bb1, unwind: bb8]; // scope 1 at $DIR/retag.rs:+3:17: +3:36
                                          // mir::Constant
                                          // + span: $DIR/retag.rs:33:25: 33:28
@@ -93,7 +90,6 @@ fn main() -> () {
         _9 = move _3;                    // scope 2 at $DIR/retag.rs:+4:19: +4:20
         Retag(_9);                       // scope 2 at $DIR/retag.rs:+4:19: +4:20
         _8 = &mut (*_9);                 // scope 2 at $DIR/retag.rs:+4:19: +4:20
-        Retag(_8);                       // scope 2 at $DIR/retag.rs:+4:19: +4:20
         StorageDead(_9);                 // scope 2 at $DIR/retag.rs:+4:22: +4:23
         StorageLive(_10);                // scope 3 at $DIR/retag.rs:+5:13: +5:14
         _10 = move _8;                   // scope 3 at $DIR/retag.rs:+5:17: +5:18
@@ -101,7 +97,6 @@ fn main() -> () {
         StorageLive(_11);                // scope 4 at $DIR/retag.rs:+7:13: +7:15
         StorageLive(_12);                // scope 4 at $DIR/retag.rs:+7:18: +7:29
         _12 = &raw mut (*_10);           // scope 4 at $DIR/retag.rs:+7:18: +7:19
-        Retag([raw] _12);                // scope 4 at $DIR/retag.rs:+7:18: +7:19
         _11 = _12;                       // scope 4 at $DIR/retag.rs:+7:18: +7:29
         StorageDead(_12);                // scope 4 at $DIR/retag.rs:+7:29: +7:30
         _2 = const ();                   // scope 1 at $DIR/retag.rs:+2:5: +8:6
@@ -122,9 +117,7 @@ fn main() -> () {
         StorageLive(_17);                // scope 6 at $DIR/retag.rs:+15:16: +15:18
         StorageLive(_18);                // scope 6 at $DIR/retag.rs:+15:16: +15:18
         _18 = &_1;                       // scope 6 at $DIR/retag.rs:+15:16: +15:18
-        Retag(_18);                      // scope 6 at $DIR/retag.rs:+15:16: +15:18
         _17 = &(*_18);                   // scope 6 at $DIR/retag.rs:+15:16: +15:18
-        Retag(_17);                      // scope 6 at $DIR/retag.rs:+15:16: +15:18
         _15 = move _16(move _17) -> bb3; // scope 6 at $DIR/retag.rs:+15:14: +15:19
     }
 
@@ -139,7 +132,6 @@ fn main() -> () {
         Deinit(_21);                     // scope 7 at $DIR/retag.rs:+18:5: +18:12
         (_21.0: i32) = const 0_i32;      // scope 7 at $DIR/retag.rs:+18:5: +18:12
         _20 = &_21;                      // scope 7 at $DIR/retag.rs:+18:5: +18:24
-        Retag(_20);                      // scope 7 at $DIR/retag.rs:+18:5: +18:24
         StorageLive(_22);                // scope 7 at $DIR/retag.rs:+18:21: +18:23
         StorageLive(_23);                // scope 7 at $DIR/retag.rs:+18:21: +18:23
         _28 = const _;                   // scope 7 at $DIR/retag.rs:+18:21: +18:23
@@ -148,9 +140,7 @@ fn main() -> () {
                                          // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) }
         Retag(_28);                      // scope 7 at $DIR/retag.rs:+18:21: +18:23
         _23 = &(*_28);                   // scope 7 at $DIR/retag.rs:+18:21: +18:23
-        Retag(_23);                      // scope 7 at $DIR/retag.rs:+18:21: +18:23
         _22 = &(*_23);                   // scope 7 at $DIR/retag.rs:+18:21: +18:23
-        Retag(_22);                      // scope 7 at $DIR/retag.rs:+18:21: +18:23
         _19 = Test::foo_shr(move _20, move _22) -> [return: bb4, unwind: bb7]; // scope 7 at $DIR/retag.rs:+18:5: +18:24
                                          // mir::Constant
                                          // + span: $DIR/retag.rs:48:13: 48:20
@@ -171,7 +161,6 @@ fn main() -> () {
         StorageLive(_25);                // scope 7 at $DIR/retag.rs:+21:9: +21:11
         StorageLive(_26);                // scope 7 at $DIR/retag.rs:+21:14: +21:28
         _26 = &raw const (*_15);         // scope 7 at $DIR/retag.rs:+21:14: +21:16
-        Retag([raw] _26);                // scope 7 at $DIR/retag.rs:+21:14: +21:16
         _25 = _26;                       // scope 7 at $DIR/retag.rs:+21:14: +21:28
         StorageDead(_26);                // scope 7 at $DIR/retag.rs:+21:28: +21:29
         StorageLive(_27);                // scope 8 at $DIR/retag.rs:+23:5: +23:18
index 08fd655ae29bb979f6161bc63c8886cadee45b50..4b50205fa8081ce7e284517a96d9c43f4a013bef 100644 (file)
@@ -11,9 +11,7 @@ fn <impl at $DIR/retag.rs:12:1: 12:10>::foo(_1: &Test, _2: &mut i32) -> &mut i32
         Retag([fn entry] _2);            // scope 0 at $DIR/retag.rs:+0:23: +0:24
         StorageLive(_3);                 // scope 0 at $DIR/retag.rs:+1:9: +1:10
         _3 = &mut (*_2);                 // scope 0 at $DIR/retag.rs:+1:9: +1:10
-        Retag(_3);                       // scope 0 at $DIR/retag.rs:+1:9: +1:10
         _0 = &mut (*_3);                 // scope 0 at $DIR/retag.rs:+1:9: +1:10
-        Retag(_0);                       // scope 0 at $DIR/retag.rs:+1:9: +1:10
         StorageDead(_3);                 // scope 0 at $DIR/retag.rs:+2:5: +2:6
         return;                          // scope 0 at $DIR/retag.rs:+2:6: +2:6
     }
index b28c6f687f70d75a37707306fa7efc2a4cb91f5b..6ae16bdb5b88a6b673807d83b9a32fedf2c0b6c6 100644 (file)
           StorageLive(_4);                 // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:9
           _4 = _1;                         // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:9
           _10 = discriminant(_4);          // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
--         switchInt(move _10) -> [0_isize: bb7, 1_isize: bb5, otherwise: bb6]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
-+         switchInt(move _10) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+-         switchInt(move _10) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++         switchInt(move _10) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
       }
   
       bb1: {
 -         StorageDead(_4);                 // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
 -         _5 = discriminant(_3);           // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
--         switchInt(move _5) -> [0_isize: bb2, 1_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
+-         switchInt(move _5) -> [0: bb2, 1: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
 -     }
 - 
 -     bb2: {
 -         goto -> bb1;                     // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
 +         StorageDead(_4);                 // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
 +         _5 = discriminant(_3);           // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
-+         switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
++         switchInt(move _5) -> [0: bb1, 1: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
       }
   
 -     bb6: {
 -         goto -> bb1;                     // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
 +         StorageDead(_4);                 // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
 +         _5 = discriminant(_3);           // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
-+         switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
++         switchInt(move _5) -> [0: bb1, 1: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
       }
   
 -     bb8: {
index 437979081367a1bc26cc9fa565bac77fcf25104b..8cc0c6a18353c2b8ea33f0c5c25d065a6b1a0ff2 100644 (file)
@@ -30,7 +30,7 @@
       bb0: {
           StorageLive(_2);                 // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6
           _3 = discriminant(_1);           // scope 0 at $DIR/separate_const_switch.rs:+6:15: +6:16
-          switchInt(move _3) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+6:9: +6:16
+          switchInt(move _3) -> [0: bb3, 1: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+6:9: +6:16
       }
   
       bb1: {
@@ -45,7 +45,7 @@
           StorageDead(_6);                 // scope 0 at $DIR/separate_const_switch.rs:+8:43: +8:44
 -         goto -> bb4;                     // scope 0 at $DIR/separate_const_switch.rs:+8:43: +8:44
 +         _8 = discriminant(_2);           // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6
-+         switchInt(move _8) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
++         switchInt(move _8) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
       }
   
       bb2: {
@@ -67,8 +67,8 @@
 - 
 -     bb4: {
           _8 = discriminant(_2);           // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6
--         switchInt(move _8) -> [0_isize: bb7, 1_isize: bb5, otherwise: bb6]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
-+         switchInt(move _8) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
+-         switchInt(move _8) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
++         switchInt(move _8) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
       }
   
 -     bb5: {
index e068b81bc3bc2f8d5b1c906fbc036c42efe3435c..8eb1aa1f3b3d0cf85b697f543aa937b6aad37f9d 100644 (file)
@@ -25,9 +25,9 @@
       }
   
 -     bb3: {
--         switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/simplify_cfg.rs:+2:12: +2:17
+-         switchInt(move _2) -> [0: bb5, otherwise: bb4]; // scope 0 at $DIR/simplify_cfg.rs:+2:12: +2:17
 +     bb2: {
-+         switchInt(move _2) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/simplify_cfg.rs:+2:12: +2:17
++         switchInt(move _2) -> [0: bb4, otherwise: bb3]; // scope 0 at $DIR/simplify_cfg.rs:+2:12: +2:17
       }
   
 -     bb4: {
index f693798eb942d3dc177dd10c0f6637f9e42e91d8..1e66b1f703e3fea1d8bd151d44b25e8239460f10 100644 (file)
@@ -26,7 +26,7 @@
       }
   
       bb3: {
-          switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/simplify_cfg.rs:+2:12: +2:17
+          switchInt(move _2) -> [0: bb5, otherwise: bb4]; // scope 0 at $DIR/simplify_cfg.rs:+2:12: +2:17
       }
   
       bb4: {
index 9b1bea2704b7771d78e66262746755337499d1ee..aea0114744352d0b7a2af771f2cdc8db318a670d 100644 (file)
@@ -9,7 +9,7 @@
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/simplify_if.rs:+1:8: +1:13
           _1 = const false;                // scope 0 at $DIR/simplify_if.rs:+1:8: +1:13
--         switchInt(const false) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/simplify_if.rs:+1:8: +1:13
+-         switchInt(const false) -> [0: bb3, otherwise: bb1]; // scope 0 at $DIR/simplify_if.rs:+1:8: +1:13
 +         goto -> bb3;                     // scope 0 at $DIR/simplify_if.rs:+1:8: +1:13
       }
   
index 8feddcef2ceefe67ec2ed32ac8db97b3ddb17827..a2b55229303d39446a364aadbf2e0025cb202825 100644 (file)
           StorageDead(_3);                 // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:68: +1:69
           StorageDead(_2);                 // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:68: +1:69
           _5 = discriminant((_1.0: std::option::Option<u8>)); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:12: +1:27
-          switchInt(move _5) -> [1_isize: bb1, otherwise: bb3]; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:12: +1:27
+          switchInt(move _5) -> [1: bb1, otherwise: bb3]; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:12: +1:27
       }
   
       bb1: {
           _4 = discriminant((_1.1: std::option::Option<T>)); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:12: +1:27
-          switchInt(move _4) -> [0_isize: bb2, otherwise: bb3]; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:12: +1:27
+          switchInt(move _4) -> [0: bb2, otherwise: bb3]; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:12: +1:27
       }
   
       bb2: {
index 6e7294003afae8e5eb09590912f0229cbb8b6f35..9ec138dd82f44b43230b458e4f785038b6d45e92 100644 (file)
@@ -18,7 +18,7 @@
 -         _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
+          switchInt(move _2) -> [0: bb3, 1: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+1:5: +1:12
       }
   
       bb1: {
index e4f9a4c12d9cb43a0a2f3bd0b0aeb54138ce31d2..f00ac5716a7517c7b29f56dc48688ca8ee37784e 100644 (file)
@@ -16,8 +16,8 @@
 -         _1 = _2;                         // scope 1 at $DIR/simplify_match.rs:+1:28: +1:29
 +         _1 = const false;                // scope 1 at $DIR/simplify_match.rs:+1:28: +1:29
           StorageDead(_2);                 // scope 0 at $DIR/simplify_match.rs:+1:30: +1:31
--         switchInt(_1) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_match.rs:+1:5: +1:31
-+         switchInt(const false) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_match.rs:+1:5: +1:31
+-         switchInt(_1) -> [0: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_match.rs:+1:5: +1:31
++         switchInt(const false) -> [0: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_match.rs:+1:5: +1:31
       }
   
       bb1: {
index 31ccf14549ca21637c82ab8dd8f0578bb05982c7..391b00effacfa0577a60e22008770449fab227a6 100644 (file)
@@ -37,7 +37,7 @@ fn std::ptr::drop_in_place(_1: *mut [String]) -> () {
 
     bb4 (cleanup): {
         _6 = Eq(_4, _3);                 // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-        switchInt(move _6) -> [false: bb3, otherwise: bb2]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+        switchInt(move _6) -> [0: bb3, otherwise: bb2]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
     }
 
     bb5: {
@@ -48,7 +48,7 @@ fn std::ptr::drop_in_place(_1: *mut [String]) -> () {
 
     bb6: {
         _8 = Eq(_4, _3);                 // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-        switchInt(move _8) -> [false: bb5, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+        switchInt(move _8) -> [0: bb5, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
     }
 
     bb7: {
@@ -68,7 +68,7 @@ fn std::ptr::drop_in_place(_1: *mut [String]) -> () {
 
     bb10 (cleanup): {
         _12 = Eq(_9, _10);               // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-        switchInt(move _12) -> [false: bb9, otherwise: bb2]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+        switchInt(move _12) -> [0: bb9, otherwise: bb2]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
     }
 
     bb11: {
@@ -79,7 +79,7 @@ fn std::ptr::drop_in_place(_1: *mut [String]) -> () {
 
     bb12: {
         _14 = Eq(_9, _10);               // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-        switchInt(move _14) -> [false: bb11, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+        switchInt(move _14) -> [0: bb11, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
     }
 
     bb13: {
@@ -96,6 +96,6 @@ fn std::ptr::drop_in_place(_1: *mut [String]) -> () {
     bb15: {
         _2 = SizeOf(std::string::String); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
         _3 = Len((*_1));                 // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-        switchInt(move _2) -> [0_usize: bb8, otherwise: bb14]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+        switchInt(move _2) -> [0: bb8, otherwise: bb14]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
     }
 }
index 7c7e87c32a2d311858a93168a5ab864e98b1394e..a5488c1ec7bfee1f31c4ae7fc8d7ab3331b345ab 100644 (file)
@@ -21,7 +21,7 @@
           discriminant(_2) = 1;            // scope 1 at $DIR/sroa.rs:+1:22: +1:29
           StorageDead(_3);                 // scope 1 at $DIR/sroa.rs:+1:28: +1:29
           _4 = discriminant(_2);           // scope 1 at $DIR/sroa.rs:+1:12: +1:19
-          switchInt(move _4) -> [1_isize: bb1, otherwise: bb2]; // scope 1 at $DIR/sroa.rs:+1:12: +1:19
+          switchInt(move _4) -> [1: bb1, otherwise: bb2]; // scope 1 at $DIR/sroa.rs:+1:12: +1:19
       }
   
       bb1: {
index 30185f3ffab29ab55a634ce5eaec34e5ace56b52..b254bfeb7c992500212de9570d51fd6ae98b8dbc 100644 (file)
@@ -26,7 +26,7 @@ fn new(_1: Result<T, E>) -> Result<T, E> {
     bb0: {
         StorageLive(_2);                 // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
         _3 = discriminant(_1);           // scope 0 at $DIR/try_identity_e2e.rs:+3:19: +3:20
-        switchInt(move _3) -> [0_isize: bb2, 1_isize: bb1, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+3:13: +3:20
+        switchInt(move _3) -> [0: bb2, 1: bb1, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+3:13: +3:20
     }
 
     bb1: {
@@ -35,7 +35,7 @@ fn new(_1: Result<T, E>) -> Result<T, E> {
         ((_2 as Break).0: E) = move _5;  // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48
         discriminant(_2) = 1;            // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48
         _6 = discriminant(_2);           // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
-        switchInt(move _6) -> [0_isize: bb5, 1_isize: bb3, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +7:10
+        switchInt(move _6) -> [0: bb5, 1: bb3, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +7:10
     }
 
     bb2: {
@@ -44,7 +44,7 @@ fn new(_1: Result<T, E>) -> Result<T, E> {
         ((_2 as Continue).0: T) = move _4; // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50
         discriminant(_2) = 0;            // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50
         _6 = discriminant(_2);           // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
-        switchInt(move _6) -> [0_isize: bb5, 1_isize: bb3, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +7:10
+        switchInt(move _6) -> [0: bb5, 1: bb3, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +7:10
     }
 
     bb3: {
index 2a9c7408c66eb4a36bb7181df80d4cf8d01000f8..cdbc0681cb8a363ae2acadeeb236c7718ad3c00a 100644 (file)
@@ -15,7 +15,7 @@ fn old(_1: Result<T, E>) -> Result<T, E> {
 
     bb0: {
         _2 = discriminant(_1);           // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +2:16
-        switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +2:16
+        switchInt(move _2) -> [0: bb3, 1: bb1, otherwise: bb2]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +2:16
     }
 
     bb1: {
index 4aa5ba007f11937b6fbfb2fb9fc6b9a9e03fd255..39ec05277595518ba60e39de7973cdbb8b998c71 100644 (file)
@@ -18,7 +18,7 @@ fn main() -> () {
         Deinit(_2);                      // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
         discriminant(_2) = 2;            // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
         _3 = discriminant(_2);           // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
-        switchInt(move _3) -> [2_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19
+        switchInt(move _3) -> [2: bb1, otherwise: bb2]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19
     }
 
     bb1: {
@@ -36,7 +36,7 @@ fn main() -> () {
         Deinit(_7);                      // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
         discriminant(_7) = 0;            // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
         _8 = discriminant(_7);           // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
-        switchInt(move _8) -> [4_isize: bb5, 5_isize: bb3, otherwise: bb4]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:5: +7:19
+        switchInt(move _8) -> [4: bb5, 5: bb3, otherwise: bb4]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:5: +7:19
     }
 
     bb2: {
index c3d356aedb28176cdf145143d968b26da0ac166b..598413a1d82de896744266987d7f71afe96793b8 100644 (file)
@@ -19,8 +19,8 @@
           Deinit(_2);                      // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
           discriminant(_2) = 2;            // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
           _3 = discriminant(_2);           // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
--         switchInt(move _3) -> [0_isize: bb3, 1_isize: bb4, 2_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19
-+         switchInt(move _3) -> [2_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19
+-         switchInt(move _3) -> [0: bb3, 1: bb4, 2: bb1, otherwise: bb2]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19
++         switchInt(move _3) -> [2: bb1, otherwise: bb2]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19
       }
   
       bb1: {
@@ -65,7 +65,7 @@
           Deinit(_7);                      // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
           discriminant(_7) = 0;            // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
           _8 = discriminant(_7);           // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
-          switchInt(move _8) -> [4_isize: bb8, 5_isize: bb6, otherwise: bb7]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:5: +7:19
+          switchInt(move _8) -> [4: bb8, 5: bb6, otherwise: bb7]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:5: +7:19
       }
   
       bb6: {
index ec5612ad76790d5619dcba69a2b3d0797f7b108f..c8cd6f6c1ea1d69950ee8f65accd39fb1acdaf6f 100644 (file)
@@ -32,7 +32,7 @@ fn main() -> () {
         StorageLive(_4);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:11: +3:22
         _4 = &(_1.1: Test1);             // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:11: +3:22
         _5 = discriminant((*_4));        // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:11: +3:22
-        switchInt(move _5) -> [2_isize: bb3, 3_isize: bb1, otherwise: bb2]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:5: +3:22
+        switchInt(move _5) -> [2: bb3, 3: bb1, otherwise: bb2]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:5: +3:22
     }
 
     bb1: {
@@ -66,7 +66,7 @@ fn main() -> () {
         StorageDead(_3);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:+8:6: +8:7
         StorageLive(_9);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:5: +15:6
         _10 = discriminant((_1.1: Test1)); // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:11: +10:21
-        switchInt(move _10) -> [2_isize: bb7, 3_isize: bb5, otherwise: bb6]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:5: +10:21
+        switchInt(move _10) -> [2: bb7, 3: bb5, otherwise: bb6]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:5: +10:21
     }
 
     bb5: {
index 77b358a4801e5b7870c8f3424f87270325d03bee..2aee6d2681d642466be5cab4bb5b8b93da629ea4 100644 (file)
@@ -33,8 +33,8 @@
           StorageLive(_4);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:11: +3:22
           _4 = &(_1.1: Test1);             // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:11: +3:22
           _5 = discriminant((*_4));        // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:11: +3:22
--         switchInt(move _5) -> [0_isize: bb3, 1_isize: bb4, 2_isize: bb5, 3_isize: bb1, otherwise: bb2]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:5: +3:22
-+         switchInt(move _5) -> [2_isize: bb5, 3_isize: bb1, otherwise: bb2]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:5: +3:22
+-         switchInt(move _5) -> [0: bb3, 1: bb4, 2: bb5, 3: bb1, otherwise: bb2]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:5: +3:22
++         switchInt(move _5) -> [2: bb5, 3: bb1, otherwise: bb2]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:5: +3:22
       }
   
       bb1: {
@@ -87,8 +87,8 @@
           StorageDead(_3);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:+8:6: +8:7
           StorageLive(_9);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:5: +15:6
           _10 = discriminant((_1.1: Test1)); // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:11: +10:21
--         switchInt(move _10) -> [0_isize: bb9, 1_isize: bb10, 2_isize: bb11, 3_isize: bb7, otherwise: bb8]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:5: +10:21
-+         switchInt(move _10) -> [2_isize: bb11, 3_isize: bb7, otherwise: bb8]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:5: +10:21
+-         switchInt(move _10) -> [0: bb9, 1: bb10, 2: bb11, 3: bb7, otherwise: bb8]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:5: +10:21
++         switchInt(move _10) -> [2: bb11, 3: bb7, otherwise: bb8]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:5: +10:21
       }
   
       bb7: {
index 11d93fca7e0866cf33a1c16bbd9ce9dcab4ff8ec..58e085dd041972089317a9e7964b4ea9c64c0107 100644 (file)
@@ -8,8 +8,8 @@
   
       bb0: {
           _2 = discriminant(_1);           // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:+1:11: +1:12
--         switchInt(move _2) -> [1_isize: bb3, 2_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:+1:5: +1:12
-+         switchInt(move _2) -> [1_isize: bb3, 2_isize: bb2, otherwise: bb5]; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:+1:5: +1:12
+-         switchInt(move _2) -> [1: bb3, 2: bb2, otherwise: bb1]; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:+1:5: +1:12
++         switchInt(move _2) -> [1: bb3, 2: bb2, otherwise: bb5]; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:+1:5: +1:12
       }
   
       bb1: {
index a7f8321ae34bac4c6dab3392bd7cedcceab3486f..e765851eb78b7a75d50d871407ce6e196744ec57 100644 (file)
@@ -8,8 +8,8 @@
   
       bb0: {
           _2 = discriminant(_1);           // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:+1:11: +1:12
--         switchInt(move _2) -> [0_isize: bb2, 1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:+1:5: +1:12
-+         switchInt(move _2) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:+1:5: +1:12
+-         switchInt(move _2) -> [0: bb2, 1: bb3, otherwise: bb1]; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:+1:5: +1:12
++         switchInt(move _2) -> [1: bb3, otherwise: bb1]; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:+1:5: +1:12
       }
   
       bb1: {
index 9cd4b8ccf331abe00c198e09b85b3feae81d2aa5..848bff1d4920c18695bb801134b4d80c0b90b75c 100644 (file)
@@ -27,8 +27,8 @@
   
       bb1: {
           _2 = discriminant(_1);           // scope 1 at $DIR/unreachable.rs:+1:12: +1:20
--         switchInt(move _2) -> [1_isize: bb2, otherwise: bb6]; // scope 1 at $DIR/unreachable.rs:+1:12: +1:20
-+         switchInt(move _2) -> [1_isize: bb2, otherwise: bb3]; // scope 1 at $DIR/unreachable.rs:+1:12: +1:20
+-         switchInt(move _2) -> [1: bb2, otherwise: bb6]; // scope 1 at $DIR/unreachable.rs:+1:12: +1:20
++         switchInt(move _2) -> [1: bb2, otherwise: bb3]; // scope 1 at $DIR/unreachable.rs:+1:12: +1:20
       }
   
       bb2: {
@@ -38,7 +38,7 @@
 -         StorageLive(_5);                 // scope 2 at $DIR/unreachable.rs:+4:9: +8:10
 -         StorageLive(_6);                 // scope 2 at $DIR/unreachable.rs:+4:12: +4:16
 -         _6 = const true;                 // scope 2 at $DIR/unreachable.rs:+4:12: +4:16
--         switchInt(move _6) -> [false: bb4, otherwise: bb3]; // scope 2 at $DIR/unreachable.rs:+4:12: +4:16
+-         switchInt(move _6) -> [0: bb4, otherwise: bb3]; // scope 2 at $DIR/unreachable.rs:+4:12: +4:16
 +         unreachable;                     // scope 2 at $DIR/unreachable.rs:+4:12: +4:16
       }
   
index afd6b00aac3ea92ac3091c48a1168a46d031a151..fb778470e532323d8958c6dfc3001ec7b5a39bf3 100644 (file)
@@ -29,7 +29,7 @@
   
       bb1: {
           _3 = discriminant(_2);           // scope 2 at $DIR/unreachable_diverging.rs:+2:12: +2:22
-          switchInt(move _3) -> [1_isize: bb2, otherwise: bb6]; // scope 2 at $DIR/unreachable_diverging.rs:+2:12: +2:22
+          switchInt(move _3) -> [1: bb2, otherwise: bb6]; // scope 2 at $DIR/unreachable_diverging.rs:+2:12: +2:22
       }
   
       bb2: {
@@ -38,7 +38,7 @@
           StorageLive(_5);                 // scope 2 at $DIR/unreachable_diverging.rs:+3:9: +5:10
           StorageLive(_6);                 // scope 2 at $DIR/unreachable_diverging.rs:+3:12: +3:13
           _6 = _1;                         // scope 2 at $DIR/unreachable_diverging.rs:+3:12: +3:13
-          switchInt(move _6) -> [false: bb4, otherwise: bb3]; // scope 2 at $DIR/unreachable_diverging.rs:+3:12: +3:13
+          switchInt(move _6) -> [0: bb4, otherwise: bb3]; // scope 2 at $DIR/unreachable_diverging.rs:+3:12: +3:13
       }
   
       bb3: {
index eef7011149d3e5341cb26a448cab0e620bf4df92..984ef476e10209d4e5f830ccabc9f1af04a989ef 100644 (file)
           Deinit(_3);                      // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32
           discriminant(_3) = 0;            // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32
 -         _4 = discriminant(_3);           // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
--         switchInt(move _4) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
+-         switchInt(move _4) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
 +         _4 = const 0_isize;              // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
-+         switchInt(const 0_isize) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
++         switchInt(const 0_isize) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
       }
   
       bb1: {
-          switchInt(((_3 as Some).0: u32)) -> [0_u32: bb2, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
+          switchInt(((_3 as Some).0: u32)) -> [0: bb2, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
       }
   
       bb2: {
index 68aa3e5db32980b69defcf16cfc7ce80c11fbeb0..1556c240dc57a4335f848ca05289bff38cb366a6 100644 (file)
@@ -24,7 +24,7 @@ fn while_loop(_1: bool) -> () {
 
     bb2: {
         StorageDead(_3);                 // scope 0 at $DIR/while_storage.rs:+1:21: +1:22
-        switchInt(move _2) -> [false: bb7, otherwise: bb3]; // scope 0 at $DIR/while_storage.rs:+1:11: +1:22
+        switchInt(move _2) -> [0: bb7, otherwise: bb3]; // scope 0 at $DIR/while_storage.rs:+1:11: +1:22
     }
 
     bb3: {
@@ -39,7 +39,7 @@ fn while_loop(_1: bool) -> () {
 
     bb4: {
         StorageDead(_5);                 // scope 0 at $DIR/while_storage.rs:+2:22: +2:23
-        switchInt(move _4) -> [false: bb6, otherwise: bb5]; // scope 0 at $DIR/while_storage.rs:+2:12: +2:23
+        switchInt(move _4) -> [0: bb6, otherwise: bb5]; // scope 0 at $DIR/while_storage.rs:+2:12: +2:23
     }
 
     bb5: {
index d083aaa662005a62e9cfc370ef32f8134c8614de..ec05ebea55582f22894bc7d7e63103e3c1495b4d 100644 (file)
@@ -1,4 +1,4 @@
 include ../tools.mk
 
 all:
-       $(RUSTC) --edition=2021 --crate-type=rlib ../../../../library/core/src/lib.rs --cfg no_fp_fmt_parse
+       $(RUSTC) --edition=2021 -Dwarnings --crate-type=rlib ../../../../library/core/src/lib.rs --cfg no_fp_fmt_parse
index 2c4309fbe66f96e8d0666620d8772120212692c7..3aa57d58908bb7b30d61a7eff9ffff9e7af95eff 100644 (file)
@@ -67,7 +67,7 @@ fn link(
             if crate_type != CrateType::Rlib {
                 sess.fatal(&format!("Crate type is {:?}", crate_type));
             }
-            let output_name = out_filename(sess, crate_type, &outputs, &*crate_name.as_str());
+            let output_name = out_filename(sess, crate_type, &outputs, crate_name);
             let mut out_file = ::std::fs::File::create(output_name).unwrap();
             write!(out_file, "This has been \"compiled\" successfully.").unwrap();
         }
index 436aebf1174ddb841086ae2699ecf5247b539315..d06cd9c6a54f077f1e115528565d17ab902fdb08 100644 (file)
@@ -80,7 +80,7 @@ ifdef RUSTC_BLESS_TEST
        rm -f expected_*
 endif
 
-include clear_expected_if_blessed
+-include clear_expected_if_blessed
 
 %: $(SOURCEDIR)/lib/%.rs
        # Compile the test library with coverage instrumentation
index 16d9a56e6bf78c472846074595c86a26aaede6b7..57497f5205384cc5883a6809b4c29feb75cfd921 100644 (file)
@@ -2,6 +2,7 @@ include ../../run-make-fulldeps/tools.mk
 
 # ignore-msvc
 # needs-rust-lld
+# ignore-s390x lld does not yet support s390x as target
 all:
        RUSTC_LOG=rustc_codegen_ssa::back::link=info $(RUSTC) -Z gcc-ld=lld -C link-args=-Wl,-v main.rs 2> $(TMPDIR)/output.txt
        $(CGREP) -e "^LLD [0-9]+\.[0-9]+\.[0-9]+" < $(TMPDIR)/output.txt
diff --git a/src/test/rustdoc-gui/basic.goml b/src/test/rustdoc-gui/basic.goml
deleted file mode 100644 (file)
index 6029283..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
-assert: ("#functions")
-goto: "./struct.Foo.html"
-assert: ("div.item-decl")
index 00a0ea1e1a27ca578ec6cab5838bc5e881ca1940..df665bd46c03b7f5cf053afa41c25d94741935e0 100644 (file)
@@ -1,7 +1,7 @@
 // This test checks that the source code pages sidebar toggle is working as expected.
 goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
 click: ".srclink"
-wait-for: "#sidebar-toggle"
-click: "#sidebar-toggle"
+wait-for: "#src-sidebar-toggle"
+click: "#src-sidebar-toggle"
 fail: true
 assert-css: ("#source-sidebar", { "left": "-300px" })
index 4d923be3e786446d12ee8879581cf1d98bdb13fc..aab27394eb1f3b1b50d5ec902aa6a42ae61353eb 100644 (file)
@@ -20,7 +20,7 @@ define-function: (
             {"border-left": "2px solid rgba(255, 0, 0, 0.5)"},
         )),
 
-        ("move-cursor-to", ".docblock .example-wrap.compile_fail"),
+        ("move-cursor-to", ".docblock .example-wrap.compile_fail .tooltip"),
 
         ("assert-css", (
             ".docblock .example-wrap.compile_fail .tooltip",
@@ -60,7 +60,7 @@ define-function: (
             {"border-left": "2px solid rgba(255, 0, 0, 0.5)"},
         )),
 
-        ("move-cursor-to", ".docblock .example-wrap.should_panic"),
+        ("move-cursor-to", ".docblock .example-wrap.should_panic .tooltip"),
 
         ("assert-css", (
             ".docblock .example-wrap.should_panic .tooltip",
@@ -100,7 +100,7 @@ define-function: (
             {"border-left": "2px solid rgba(255, 142, 0, 0.6)"},
         )),
 
-        ("move-cursor-to", ".docblock .example-wrap.ignore"),
+        ("move-cursor-to", ".docblock .example-wrap.ignore .tooltip"),
 
         ("assert-css", (
             ".docblock .example-wrap.ignore .tooltip",
index b2e91cb81fba7495b9e79a1a67204f28263796c9..cb6716a76f5c0d6ae17511dfcd2617ee0d75d398 100644 (file)
@@ -21,4 +21,4 @@ assert-css: (".sidebar-menu-toggle", {"cursor": "pointer"})
 
 // the sidebar toggle button on the source code pages
 goto: "file://" + |DOC_PATH| + "/src/lib2/lib.rs.html"
-assert-css: ("#sidebar-toggle > button", {"cursor": "pointer"})
+assert-css: ("#src-sidebar-toggle > button", {"cursor": "pointer"})
index 9f8df44d762ce5f9402b144b6af81320dfec3b1e..3ce921c2c91cb1a3de4aef659a576085852ca4c7 100644 (file)
@@ -7,3 +7,7 @@ show-text: true // We need to enable text draw to be able to have the "real" siz
 // Little explanations for this test: if the text wasn't displayed on two lines, it would take
 // around 20px (which is the font size).
 assert-property: (".docblock p > code", {"offsetHeight": "44"})
+
+// Same check, but where the long code block is also a link
+goto: "file://" + |DOC_PATH| + "/test_docs/long_code_block_link/index.html"
+assert-property: (".docblock p > a > code", {"offsetHeight": "44"})
index fec21ad35c3ebe098cbebcd4d24d7bf1e87d249f..b094c483876410365962462bcc910734c8492814 100644 (file)
@@ -33,7 +33,9 @@ assert-css: ("#settings", {"display": "block"})
 click: "input#line-numbers"
 wait-for: 100 // wait-for-false does not exist
 assert-false: "pre.example-line-numbers"
+assert-local-storage: {"rustdoc-line-numbers": "false" }
 
 // Finally, turn it on again.
 click: "input#line-numbers"
 wait-for: "pre.example-line-numbers"
+assert-local-storage: {"rustdoc-line-numbers": "true" }
index 4e316ce0bcbfd45b7cbda1a2c965b9be6d0e32fc..8645c1b1949e3f79533a5d76345bea8aec5285b6 100644 (file)
@@ -2,3 +2,50 @@ goto: "file://" + |DOC_PATH| + "/test_docs/doc_block_table/struct.DocBlockTable.
 
 compare-elements-css: (".impl-items .docblock table th", ".top-doc .docblock table th", ["border"])
 compare-elements-css: (".impl-items .docblock table td", ".top-doc .docblock table td", ["border"])
+
+define-function: (
+    "check-colors",
+    (theme, border_color, zebra_stripe_color),
+    [
+        ("local-storage", {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|}),
+        ("reload"),
+        ("assert-css", (".top-doc .docblock table tbody tr:nth-child(1)", {
+            "background-color": "rgba(0, 0, 0, 0)",
+        })),
+        ("assert-css", (".top-doc .docblock table tbody tr:nth-child(2)", {
+            "background-color": |zebra_stripe_color|,
+        })),
+        ("assert-css", (".top-doc .docblock table tbody tr:nth-child(3)", {
+            "background-color": "rgba(0, 0, 0, 0)",
+        })),
+        ("assert-css", (".top-doc .docblock table tbody tr:nth-child(4)", {
+            "background-color": |zebra_stripe_color|,
+        })),
+        ("assert-css", (".top-doc .docblock table td", {
+            "border-style": "solid",
+            "border-width": "1px",
+            "border-color": |border_color|,
+        })),
+        ("assert-css", (".top-doc .docblock table th", {
+            "border-style": "solid",
+            "border-width": "1px",
+            "border-color": |border_color|,
+        })),
+    ]
+)
+
+call-function: ("check-colors", {
+    "theme": "dark",
+    "border_color": "rgb(224, 224, 224)",
+    "zebra_stripe_color": "rgb(42, 42, 42)",
+})
+call-function: ("check-colors", {
+    "theme": "ayu",
+    "border_color": "rgb(92, 103, 115)",
+    "zebra_stripe_color": "rgb(25, 31, 38)",
+})
+call-function: ("check-colors", {
+    "theme": "light",
+    "border_color": "rgb(224, 224, 224)",
+    "zebra_stripe_color": "rgb(245, 245, 245)",
+})
index 799ba851c92f9a1aaa7892c758e87bba78d5b182..80203901ed3c4c5c4678d48cd7a3461e4a3f1ca5 100644 (file)
@@ -27,7 +27,6 @@ define-function: (
             "color": |color|,
             "background-color": |background|,
             "box-shadow": |box_shadow| + " 0px -1px 0px 0px inset",
-            "cursor": "default",
         }, ALL)),
     ],
 )
diff --git a/src/test/rustdoc-gui/impl-doc.goml b/src/test/rustdoc-gui/impl-doc.goml
new file mode 100644 (file)
index 0000000..7322032
--- /dev/null
@@ -0,0 +1,9 @@
+// A docblock on an impl must have a margin to separate it from the contents.
+goto: "file://" + |DOC_PATH| + "/test_docs/struct.TypeWithImplDoc.html"
+
+// The text is about 24px tall, so if there's a margin, then their position will be >24px apart
+compare-elements-position-near-false: (
+       "#implementations-list > .implementors-toggle > .docblock > p",
+       "#implementations-list > .implementors-toggle > .impl-items",
+       {"y": 24}
+)
index a222139f1dc44751b44ff9fbf7b9a44e210ad96f..bba518db099a49693956915158ffb3e224478716 100644 (file)
@@ -1,5 +1,6 @@
 goto: "file://" + |DOC_PATH| + "/scrape_examples/fn.test.html"
 
+// The next/prev buttons vertically scroll the code viewport between examples
 store-property: (initialScrollTop, ".scraped-example-list > .scraped-example pre", "scrollTop")
 focus: ".scraped-example-list > .scraped-example .next"
 press-key: "Enter"
@@ -12,6 +13,7 @@ assert-property: (".scraped-example-list > .scraped-example pre", {
        "scrollTop": |initialScrollTop|
 })
 
+// The expand button increases the scrollHeight of the minimized code viewport
 store-property: (smallOffsetHeight, ".scraped-example-list > .scraped-example pre", "offsetHeight")
 assert-property-false: (".scraped-example-list > .scraped-example pre", {
        "scrollHeight": |smallOffsetHeight|
diff --git a/src/test/rustdoc-gui/scrape-examples-toggle.goml b/src/test/rustdoc-gui/scrape-examples-toggle.goml
new file mode 100644 (file)
index 0000000..ee720af
--- /dev/null
@@ -0,0 +1,14 @@
+goto: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html"
+
+// Clicking "More examples..." will open additional examples
+assert-attribute-false: (".more-examples-toggle", {"open": ""})
+click: ".more-examples-toggle"
+assert-attribute: (".more-examples-toggle", {"open": ""})
+
+// Toggling all docs will close additional examples
+click: "#toggle-all-docs"
+assert-attribute-false: (".more-examples-toggle", {"open": ""})
+
+// After re-opening the docs, the additional examples should stay closed
+click: "#toggle-all-docs"
+assert-attribute-false: (".more-examples-toggle", {"open": ""})
index 40ae4af81be45329419f13e007cdf1559d39f178..df4506e1119648a7c76f379170da131cab39d51f 100644 (file)
@@ -2,18 +2,18 @@
 javascript: false
 goto: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
 // Since the javascript is disabled, there shouldn't be a toggle.
-assert-false: "#sidebar-toggle"
+assert-false: "#src-sidebar-toggle"
 wait-for-css: (".sidebar", {"display": "none"})
 
 // Let's retry with javascript enabled.
 javascript: true
 reload:
-wait-for: "#sidebar-toggle"
-assert-css: ("#sidebar-toggle", {"visibility": "visible"})
-assert-css: (".sidebar > *:not(#sidebar-toggle)", {"visibility": "hidden"})
+wait-for: "#src-sidebar-toggle"
+assert-css: ("#src-sidebar-toggle", {"visibility": "visible"})
+assert-css: (".sidebar > *:not(#src-sidebar-toggle)", {"visibility": "hidden"})
 // Let's expand the sidebar now.
-click: "#sidebar-toggle"
-wait-for-css: ("#sidebar-toggle", {"visibility": "visible"})
+click: "#src-sidebar-toggle"
+wait-for-css: ("#src-sidebar-toggle", {"visibility": "visible"})
 
 // We now check that opening the sidebar and clicking a link will leave it open.
 // The behavior here on desktop is different than the behavior on mobile,
@@ -38,25 +38,25 @@ define-function: (
     [
         ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
         ("reload"),
-        ("wait-for-css", ("#sidebar-toggle", {"visibility": "visible"})),
+        ("wait-for-css", ("#src-sidebar-toggle", {"visibility": "visible"})),
         ("assert-css", (
             "#source-sidebar details[open] > .files a.selected",
             {"color": |color_hover|, "background-color": |background|},
         )),
 
         // Without hover or focus.
-        ("assert-css", ("#sidebar-toggle > button", {"background-color": |background_toggle|})),
+        ("assert-css", ("#src-sidebar-toggle > button", {"background-color": |background_toggle|})),
         // With focus.
-        ("focus", "#sidebar-toggle > button"),
+        ("focus", "#src-sidebar-toggle > button"),
         ("assert-css", (
-            "#sidebar-toggle > button:focus",
+            "#src-sidebar-toggle > button:focus",
             {"background-color": |background_toggle_hover|},
         )),
         ("focus", ".search-input"),
         // With hover.
-        ("move-cursor-to", "#sidebar-toggle > button"),
+        ("move-cursor-to", "#src-sidebar-toggle > button"),
         ("assert-css", (
-            "#sidebar-toggle > button:hover",
+            "#src-sidebar-toggle > button:hover",
             {"background-color": |background_toggle_hover|},
         )),
 
@@ -151,16 +151,16 @@ call-function: ("check-colors", {
 size: (500, 700)
 reload:
 // Waiting for the sidebar to be displayed...
-wait-for-css: ("#sidebar-toggle", {"visibility": "visible"})
+wait-for-css: ("#src-sidebar-toggle", {"visibility": "visible"})
 
 // We now check it takes the full size of the display.
 assert-property: ("body", {"clientWidth": "500", "clientHeight": "700"})
 assert-property: (".sidebar", {"clientWidth": "500", "clientHeight": "700"})
 
 // We now check the display of the toggle once the sidebar is expanded.
-assert-property: ("#sidebar-toggle", {"clientWidth": "500", "clientHeight": "39"})
+assert-property: ("#src-sidebar-toggle", {"clientWidth": "500", "clientHeight": "39"})
 assert-css: (
-    "#sidebar-toggle",
+    "#src-sidebar-toggle",
     {
         "border-top-width": "0px",
         "border-right-width": "0px",
@@ -170,28 +170,28 @@ assert-css: (
 )
 
 // We now check that the scroll position is kept when opening the sidebar.
-click: "#sidebar-toggle"
+click: "#src-sidebar-toggle"
 wait-for-css: (".sidebar", {"width": "0px"})
 // We scroll to line 117 to change the scroll position.
 scroll-to: '//*[@id="117"]'
 assert-window-property: {"pageYOffset": "2542"}
 // Expanding the sidebar...
-click: "#sidebar-toggle"
+click: "#src-sidebar-toggle"
 wait-for-css: (".sidebar", {"width": "500px"})
-click: "#sidebar-toggle"
+click: "#src-sidebar-toggle"
 wait-for-css: (".sidebar", {"width": "0px"})
 // The "scrollTop" property should be the same.
 assert-window-property: {"pageYOffset": "2542"}
 
 // We now check that the scroll position is restored if the window is resized.
 size: (500, 700)
-click: "#sidebar-toggle"
+click: "#src-sidebar-toggle"
 wait-for-css: ("#source-sidebar", {"visibility": "visible"})
 assert-window-property: {"pageYOffset": "0"}
 size: (900, 900)
 assert-window-property: {"pageYOffset": "2542"}
 size: (500, 700)
-click: "#sidebar-toggle"
+click: "#src-sidebar-toggle"
 wait-for-css: ("#source-sidebar", {"visibility": "hidden"})
 
 // We now check that opening the sidebar and clicking a link will close it.
@@ -199,7 +199,7 @@ wait-for-css: ("#source-sidebar", {"visibility": "hidden"})
 // but common sense dictates that if you have a list of files that fills the entire screen, and
 // you click one of them, you probably want to actually see the file's contents, and not just
 // make it the current selection.
-click: "#sidebar-toggle"
+click: "#src-sidebar-toggle"
 wait-for-css: ("#source-sidebar", {"visibility": "visible"})
 assert-local-storage: {"rustdoc-source-sidebar-show": "true"}
 click: ".sidebar a.selected"
@@ -210,6 +210,6 @@ assert-local-storage: {"rustdoc-source-sidebar-show": "false"}
 size: (1000, 1000)
 wait-for-css: ("#source-sidebar", {"visibility": "hidden"})
 assert-local-storage: {"rustdoc-source-sidebar-show": "false"}
-click: "#sidebar-toggle"
+click: "#src-sidebar-toggle"
 wait-for-css: ("#source-sidebar", {"visibility": "visible"})
 assert-local-storage: {"rustdoc-source-sidebar-show": "true"}
index b3b837ad377c80bb74e8b2a7e81a181e8bb44fa0..25da74e5173eba34e77995a5e0ee083e010a8d24 100644 (file)
@@ -97,7 +97,7 @@ assert-document-property: ({"URL": "/lib.rs.html"}, ENDS_WITH)
 // Checking the source code sidebar.
 
 // First we "open" it.
-click: "#sidebar-toggle"
+click: "#src-sidebar-toggle"
 assert: ".source-sidebar-expanded"
 
 // We check that the first entry of the sidebar is collapsed
index 1340511d4726b381b6ca4a118d2caf5dc1d4f91f..f1b69d4dc1d40ba174e47ff29422f24033ce7279 100644 (file)
@@ -154,6 +154,11 @@ pub mod huge_amount_of_consts {
 /// Very long code text `hereIgoWithLongTextBecauseWhyNotAndWhyWouldntI`.
 pub mod long_code_block {}
 
+/// Very long code text [`hereIgoWithLongTextBecauseWhyNotAndWhyWouldntI`][lnk].
+///
+/// [lnk]: crate::long_code_block_link
+pub mod long_code_block_link {}
+
 #[macro_export]
 macro_rules! repro {
     () => {};
@@ -343,6 +348,9 @@ pub trait DocBlockTableTrait {
     /// | header1                  | header2                  |
     /// |--------------------------|--------------------------|
     /// | Lorem Ipsum, Lorem Ipsum | Lorem Ipsum, Lorem Ipsum |
+    /// | Lorem Ipsum, Lorem Ipsum | Lorem Ipsum, Lorem Ipsum |
+    /// | Lorem Ipsum, Lorem Ipsum | Lorem Ipsum, Lorem Ipsum |
+    /// | Lorem Ipsum, Lorem Ipsum | Lorem Ipsum, Lorem Ipsum |
     pub struct DocBlockTable {}
 
     impl DocBlockTableTrait for DocBlockTable {
@@ -439,3 +447,11 @@ fn function() {}
         fn function2() {}
     }
 }
+
+pub struct TypeWithImplDoc;
+
+/// impl doc
+impl TypeWithImplDoc {
+    /// fn doc
+    pub fn test_fn() {}
+}
diff --git a/src/test/rustdoc-gui/stab-badge.goml b/src/test/rustdoc-gui/stab-badge.goml
new file mode 100644 (file)
index 0000000..aaed844
--- /dev/null
@@ -0,0 +1,41 @@
+// All stability badges should have rounded corners and colored backgrounds.
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+show-text: true
+define-function: (
+       "check-badge",
+       (theme, background, color),
+       [
+        ("local-storage", {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|}),
+        ("goto", "file://" + |DOC_PATH| + "/test_docs/index.html"),
+               ("assert", (".docblock .stab")),
+               ("assert", (".item-table .stab")),
+               ("assert-css", (".stab", {
+                       "border-radius": "3px",
+                       "color": |color|,
+                       "background-color": |background|,
+               })),
+        ("goto", "file://" + |DOC_PATH| + "/test_docs/fn.replaced_function.html"),
+               ("assert", (".item-info .stab")),
+               ("assert-css", (".stab", {
+                       "border-radius": "3px",
+                       "color": |color|,
+                       "background-color": |background|,
+               })),
+       ]
+)
+
+call-function: ("check-badge", {
+       "theme": "ayu",
+       "color": "rgb(197, 197, 197)",
+       "background": "rgb(49, 69, 89)",
+})
+call-function: ("check-badge", {
+       "theme": "dark",
+       "color": "rgb(221, 221, 221)",
+       "background": "rgb(49, 69, 89)",
+})
+call-function: ("check-badge", {
+       "theme": "light",
+       "color": "rgb(0, 0, 0)",
+       "background": "rgb(255, 245, 214)",
+})
diff --git a/src/test/rustdoc-ui/const-evalutation-ice.rs b/src/test/rustdoc-ui/const-evalutation-ice.rs
new file mode 100644 (file)
index 0000000..0dd3bca
--- /dev/null
@@ -0,0 +1,11 @@
+// Just check we don't get an ICE for `N`.
+
+use std::cell::Cell;
+use std::mem;
+
+pub struct S {
+    s: Cell<usize>
+}
+
+pub const N: usize = 0 - (mem::size_of::<S>() != 400) as usize;
+//~^ ERROR evaluation of constant value failed
diff --git a/src/test/rustdoc-ui/const-evalutation-ice.stderr b/src/test/rustdoc-ui/const-evalutation-ice.stderr
new file mode 100644 (file)
index 0000000..5d9c16c
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-evalutation-ice.rs:10:22
+   |
+LL | pub const N: usize = 0 - (mem::size_of::<S>() != 400) as usize;
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
index b379f6febe29f1c8511aa49bcd902d650e7e37b3..14b7b17e04d3af476d66cc25a0c917976f8b0e53 100644 (file)
@@ -2,7 +2,7 @@ error: `cfg` predicate is not specified
   --> $DIR/doc-cfg.rs:3:7
    |
 LL | #[doc(cfg(), cfg(foo, bar))]
-   |       ^^^^^
+   |       ^^^^^ help: expected syntax is: `cfg(/* predicate */)`
 
 error: multiple `cfg` predicates are specified
   --> $DIR/doc-cfg.rs:3:23
@@ -14,7 +14,7 @@ error: `cfg` predicate is not specified
   --> $DIR/doc-cfg.rs:7:7
    |
 LL | #[doc(cfg())]
-   |       ^^^^^
+   |       ^^^^^ help: expected syntax is: `cfg(/* predicate */)`
 
 error: multiple `cfg` predicates are specified
   --> $DIR/doc-cfg.rs:8:16
diff --git a/src/test/rustdoc-ui/unable-fulfill-trait.rs b/src/test/rustdoc-ui/unable-fulfill-trait.rs
new file mode 100644 (file)
index 0000000..7035708
--- /dev/null
@@ -0,0 +1,13 @@
+// This test ensures that it's not crashing rustdoc.
+
+pub struct Foo<'a, 'b, T> {
+    field1: dyn Bar<'a, 'b,>,
+    //~^ ERROR
+    //~^^ ERROR
+}
+
+pub trait Bar<'x, 's, U>
+    where U: 'x,
+    Self:'x,
+    Self:'s
+{}
diff --git a/src/test/rustdoc-ui/unable-fulfill-trait.stderr b/src/test/rustdoc-ui/unable-fulfill-trait.stderr
new file mode 100644 (file)
index 0000000..a16b5b6
--- /dev/null
@@ -0,0 +1,26 @@
+error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
+  --> $DIR/unable-fulfill-trait.rs:4:17
+   |
+LL |     field1: dyn Bar<'a, 'b,>,
+   |                 ^^^ expected 1 generic argument
+   |
+note: trait defined here, with 1 generic parameter: `U`
+  --> $DIR/unable-fulfill-trait.rs:9:11
+   |
+LL | pub trait Bar<'x, 's, U>
+   |           ^^^         -
+help: add missing generic argument
+   |
+LL |     field1: dyn Bar<'a, 'b, U,>,
+   |                           +++
+
+error[E0227]: ambiguous lifetime bound, explicit lifetime bound required
+  --> $DIR/unable-fulfill-trait.rs:4:13
+   |
+LL |     field1: dyn Bar<'a, 'b,>,
+   |             ^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0107, E0227.
+For more information about an error, try `rustc --explain E0107`.
index 94cf7b94241df8d79144969b852f538de8ccfa88..3537e669608d15faf6afbcc26b5410b865225720 100644 (file)
@@ -35,6 +35,7 @@
     -Z            dump-mir-exclude-pass-number=val -- exclude the pass number when dumping MIR (used in tests) (default: no)
     -Z                       dump-mir-graphviz=val -- in addition to `.mir` files, create graphviz `.dot` files (and with `-Z instrument-coverage`, also create a `.dot` file for the MIR-derived coverage graph) (default: no)
     -Z                       dump-mir-spanview=val -- in addition to `.mir` files, create `.html` files to view spans for all `statement`s (including terminators), only `terminator` spans, or computed `block` spans (one span encompassing a block's terminator and all statements). If `-Z instrument-coverage` is also enabled, create an additional `.html` file showing the computed coverage spans.
+    -Z                         dump-mono-stats=val -- output statistics about monomorphization collection (format: markdown)
     -Z                           dwarf-version=val -- version of DWARF debug information to emit (default: 2 or 4, depending on platform)
     -Z                               dylib-lto=val -- enables LTO for dylib crate type
     -Z                        emit-stack-sizes=val -- emit a section containing stack size metadata (default: no)
diff --git a/src/test/rustdoc/const-evalutation-ice.rs b/src/test/rustdoc/const-evalutation-ice.rs
deleted file mode 100644 (file)
index 68c7f9c..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// Just check we don't get an ICE for `N`.
-
-use std::cell::Cell;
-use std::mem;
-
-pub struct S {
-    s: Cell<usize>
-}
-
-pub const N: usize = 0 - (mem::size_of::<S>() != 4) as usize;
diff --git a/src/test/rustdoc/read-more-unneeded.rs b/src/test/rustdoc/read-more-unneeded.rs
new file mode 100644 (file)
index 0000000..0303e44
--- /dev/null
@@ -0,0 +1,34 @@
+// Regression test for https://github.com/rust-lang/rust/issues/105677.
+// This test ensures that the "Read more" link is only generated when
+// there is actually more documentation to read after the short summary.
+
+#![crate_name = "foo"]
+
+pub trait MyFrom {
+    /// # Hello
+    /// ## Yolo
+    /// more!
+    fn try_from1();
+    /// a
+    /// b
+    /// c
+    fn try_from2();
+    /// a
+    ///
+    /// b
+    ///
+    /// c
+    fn try_from3();
+}
+
+pub struct NonZero;
+
+// @has 'foo/struct.NonZero.html'
+impl MyFrom for NonZero {
+    // @matches - '//*[@class="docblock"]' '^Hello Read more$'
+    fn try_from1() {}
+    // @matches - '//*[@class="docblock"]' '^a\sb\sc$'
+    fn try_from2() {}
+    // @matches - '//*[@class="docblock"]' '^a Read more$'
+    fn try_from3() {}
+}
index e41422ce7c516b5033d7185ce068dce5b9f1e6f6..0a1f088b9ab5c8fb830f55120be7a6fb3d6b2f64 100644 (file)
@@ -4,6 +4,8 @@
 // summary. Trait methods with no documentation should not be wrapped.
 //
 // @has foo/trait.Foo.html
+// @has - '//details[@class="rustdoc-toggle"]//summary//h4[@class="code-header"]' 'type Item'
+// @!has - '//details[@class="rustdoc-toggle"]//summary//h4[@class="code-header"]' 'type Item2'
 // @has -  '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'is_documented()'
 // @!has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented()'
 // @has -  '//details[@class="rustdoc-toggle method-toggle"]//*[@class="docblock"]' 'is_documented is documented'
 // @!has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented_optional()'
 // @has -  '//details[@class="rustdoc-toggle method-toggle"]//*[@class="docblock"]' 'is_documented_optional is documented'
 pub trait Foo {
+    /// is documented
+    type Item;
+
+    type Item2;
+
     fn not_documented();
 
     /// is_documented is documented
index 195cdf009b9937f37d355f15702347a69942fe7b..9cf3226f738c804da6357ecf5e058eee0e568280 100644 (file)
@@ -30,8 +30,6 @@ fn a() {}
     // @has - '//*[@id="method.b"]/../../div[@class="docblock"]' 'These docs contain'
     // @has - '//*[@id="method.b"]/../../div[@class="docblock"]/a' 'reference link'
     // @has - '//*[@id="method.b"]/../../div[@class="docblock"]/a/@href' 'https://example.com'
-    // @has - '//*[@id="method.b"]/../../div[@class="docblock"]/a' 'Read more'
-    // @has - '//*[@id="method.b"]/../../div[@class="docblock"]/a/@href' 'trait.Trait.html#tymethod.b'
     fn b() {}
 
     // @!has - '//*[@id="method.c"]/../../div[@class="docblock"]' 'code block'
index 2cb1ed6fcb76b349133493d7a627d91ba157e16a..3f7429a5fccf83cef8b9f289ac2b1d1c36527125 100644 (file)
@@ -33,8 +33,7 @@ fn main() {
         TyKind::GeneratorWitness(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
         TyKind::Never => (),                //~ ERROR usage of `ty::TyKind::<kind>`
         TyKind::Tuple(..) => (),            //~ ERROR usage of `ty::TyKind::<kind>`
-        TyKind::Projection(..) => (),       //~ ERROR usage of `ty::TyKind::<kind>`
-        TyKind::Opaque(..) => (),           //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Alias(..) => (),            //~ ERROR usage of `ty::TyKind::<kind>`
         TyKind::Param(..) => (),            //~ ERROR usage of `ty::TyKind::<kind>`
         TyKind::Bound(..) => (),            //~ ERROR usage of `ty::TyKind::<kind>`
         TyKind::Placeholder(..) => (),      //~ ERROR usage of `ty::TyKind::<kind>`
index 171f49087d6953fc4818eafa7c00b7794fa7a038..1f49d6b64646f0282b4d214c63f6ecd69f0e1a60 100644 (file)
@@ -133,53 +133,47 @@ LL |         TyKind::Tuple(..) => (),
 error: usage of `ty::TyKind::<kind>`
   --> $DIR/ty_tykind_usage.rs:36:9
    |
-LL |         TyKind::Projection(..) => (),
+LL |         TyKind::Alias(..) => (),
    |         ^^^^^^ help: try using `ty::<kind>` directly: `ty`
 
 error: usage of `ty::TyKind::<kind>`
   --> $DIR/ty_tykind_usage.rs:37:9
    |
-LL |         TyKind::Opaque(..) => (),
-   |         ^^^^^^ help: try using `ty::<kind>` directly: `ty`
-
-error: usage of `ty::TyKind::<kind>`
-  --> $DIR/ty_tykind_usage.rs:38:9
-   |
 LL |         TyKind::Param(..) => (),
    |         ^^^^^^ help: try using `ty::<kind>` directly: `ty`
 
 error: usage of `ty::TyKind::<kind>`
-  --> $DIR/ty_tykind_usage.rs:39:9
+  --> $DIR/ty_tykind_usage.rs:38:9
    |
 LL |         TyKind::Bound(..) => (),
    |         ^^^^^^ help: try using `ty::<kind>` directly: `ty`
 
 error: usage of `ty::TyKind::<kind>`
-  --> $DIR/ty_tykind_usage.rs:40:9
+  --> $DIR/ty_tykind_usage.rs:39:9
    |
 LL |         TyKind::Placeholder(..) => (),
    |         ^^^^^^ help: try using `ty::<kind>` directly: `ty`
 
 error: usage of `ty::TyKind::<kind>`
-  --> $DIR/ty_tykind_usage.rs:41:9
+  --> $DIR/ty_tykind_usage.rs:40:9
    |
 LL |         TyKind::Infer(..) => (),
    |         ^^^^^^ help: try using `ty::<kind>` directly: `ty`
 
 error: usage of `ty::TyKind::<kind>`
-  --> $DIR/ty_tykind_usage.rs:42:9
+  --> $DIR/ty_tykind_usage.rs:41:9
    |
 LL |         TyKind::Error(_) => (),
    |         ^^^^^^ help: try using `ty::<kind>` directly: `ty`
 
 error: usage of `ty::TyKind::<kind>`
-  --> $DIR/ty_tykind_usage.rs:47:12
+  --> $DIR/ty_tykind_usage.rs:46:12
    |
 LL |     if let TyKind::Int(int_ty) = kind {}
    |            ^^^^^^ help: try using `ty::<kind>` directly: `ty`
 
 error: usage of `ty::TyKind`
-  --> $DIR/ty_tykind_usage.rs:49:24
+  --> $DIR/ty_tykind_usage.rs:48:24
    |
 LL |     fn ty_kind(ty_bad: TyKind<'_>, ty_good: Ty<'_>) {}
    |                        ^^^^^^^^^^
@@ -187,7 +181,7 @@ LL |     fn ty_kind(ty_bad: TyKind<'_>, ty_good: Ty<'_>) {}
    = help: try using `Ty` instead
 
 error: usage of `ty::TyKind`
-  --> $DIR/ty_tykind_usage.rs:51:37
+  --> $DIR/ty_tykind_usage.rs:50:37
    |
 LL |     fn ir_ty_kind<I: Interner>(bad: IrTyKind<I>) -> IrTyKind<I> {
    |                                     ^^^^^^^^^^^
@@ -195,7 +189,7 @@ LL |     fn ir_ty_kind<I: Interner>(bad: IrTyKind<I>) -> IrTyKind<I> {
    = help: try using `Ty` instead
 
 error: usage of `ty::TyKind`
-  --> $DIR/ty_tykind_usage.rs:51:53
+  --> $DIR/ty_tykind_usage.rs:50:53
    |
 LL |     fn ir_ty_kind<I: Interner>(bad: IrTyKind<I>) -> IrTyKind<I> {
    |                                                     ^^^^^^^^^^^
@@ -203,12 +197,12 @@ LL |     fn ir_ty_kind<I: Interner>(bad: IrTyKind<I>) -> IrTyKind<I> {
    = help: try using `Ty` instead
 
 error: usage of `ty::TyKind::<kind>`
-  --> $DIR/ty_tykind_usage.rs:54:9
+  --> $DIR/ty_tykind_usage.rs:53:9
    |
 LL |         IrTyKind::Bool
    |         --------^^^^^^
    |         |
    |         help: try using `ty::<kind>` directly: `ty`
 
-error: aborting due to 33 previous errors
+error: aborting due to 32 previous errors
 
index cb4cd466590b626e5e2553dacda2df9e2047af42..c19b639a8d5819d1f84a23f9330cbd7a4f02f03d 100644 (file)
@@ -683,7 +683,7 @@ struct RawIdentDiagnosticArg {
 #[diag(compiletest_example)]
 struct SubdiagnosticBad {
     #[subdiagnostic(bad)]
-    //~^ ERROR `#[subdiagnostic(bad)]` is not a valid attribute
+    //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
     note: Note,
 }
 
@@ -707,7 +707,7 @@ struct SubdiagnosticBadTwice {
 #[diag(compiletest_example)]
 struct SubdiagnosticBadLitStr {
     #[subdiagnostic("bad")]
-    //~^ ERROR `#[subdiagnostic("...")]` is not a valid attribute
+    //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
     note: Note,
 }
 
@@ -723,6 +723,7 @@ struct SubdiagnosticEagerLint {
 #[diag(compiletest_example)]
 struct SubdiagnosticEagerCorrect {
     #[subdiagnostic(eager)]
+    //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
     note: Note,
 }
 
@@ -743,6 +744,7 @@ pub(crate) struct SubdiagnosticWithSuggestion {
 #[diag(compiletest_example)]
 struct SubdiagnosticEagerSuggestion {
     #[subdiagnostic(eager)]
+    //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
     sub: SubdiagnosticWithSuggestion,
 }
 
index b4c211db47cd9e090bdc8e6f5fc3e8be399628d9..f39d32a221cacc1084bbecd15b635a1ef43a7fb9 100644 (file)
@@ -533,21 +533,19 @@ LL | #[label]
    |
    = help: `#[label]` and `#[suggestion]` can only be applied to fields
 
-error: `#[subdiagnostic(bad)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:685:21
+error: `#[subdiagnostic(...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:685:5
    |
 LL |     #[subdiagnostic(bad)]
-   |                     ^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: `eager` is the only supported nested attribute for `subdiagnostic`
+   = help: `subdiagnostic` does not support nested attributes
 
 error: `#[subdiagnostic = ...]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:693:5
    |
 LL |     #[subdiagnostic = "bad"]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: `eager` is the only supported nested attribute for `subdiagnostic`
 
 error: `#[subdiagnostic(...)]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:701:5
@@ -555,15 +553,15 @@ error: `#[subdiagnostic(...)]` is not a valid attribute
 LL |     #[subdiagnostic(bad, bad)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: `eager` is the only supported nested attribute for `subdiagnostic`
+   = help: `subdiagnostic` does not support nested attributes
 
-error: `#[subdiagnostic("...")]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:709:21
+error: `#[subdiagnostic(...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:709:5
    |
 LL |     #[subdiagnostic("bad")]
-   |                     ^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: `eager` is the only supported nested attribute for `subdiagnostic`
+   = help: `subdiagnostic` does not support nested attributes
 
 error: `#[subdiagnostic(...)]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:717:5
@@ -571,22 +569,38 @@ error: `#[subdiagnostic(...)]` is not a valid attribute
 LL |     #[subdiagnostic(eager)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: eager subdiagnostics are not supported on lints
+   = help: `subdiagnostic` does not support nested attributes
+
+error: `#[subdiagnostic(...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:725:5
+   |
+LL |     #[subdiagnostic(eager)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `subdiagnostic` does not support nested attributes
+
+error: `#[subdiagnostic(...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:746:5
+   |
+LL |     #[subdiagnostic(eager)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `subdiagnostic` does not support nested attributes
 
 error: expected at least one string literal for `code(...)`
-  --> $DIR/diagnostic-derive.rs:775:18
+  --> $DIR/diagnostic-derive.rs:777:18
    |
 LL |     #[suggestion(code())]
    |                  ^^^^^^
 
 error: `code(...)` must contain only string literals
-  --> $DIR/diagnostic-derive.rs:783:23
+  --> $DIR/diagnostic-derive.rs:785:23
    |
 LL |     #[suggestion(code(foo))]
    |                       ^^^
 
 error: `code = "..."`/`code(...)` must contain only string literals
-  --> $DIR/diagnostic-derive.rs:791:18
+  --> $DIR/diagnostic-derive.rs:793:18
    |
 LL |     #[suggestion(code = 3)]
    |                  ^^^^^^^^
@@ -660,12 +674,9 @@ LL | #[derive(Diagnostic)]
    = help: normalized in stderr
 note: required by a bound in `DiagnosticBuilder::<'a, G>::set_arg`
   --> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:LL:CC
-   |
-LL |         arg: impl IntoDiagnosticArg,
-   |                   ^^^^^^^^^^^^^^^^^ required by this bound in `DiagnosticBuilder::<'a, G>::set_arg`
-   = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the derive macro `Diagnostic` which comes from the expansion of the macro `forward` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 83 previous errors
+error: aborting due to 85 previous errors
 
 Some errors have detailed explanations: E0277, E0425.
 For more information about an error, try `rustc --explain E0277`.
index adb652fe61659bcf94a699b7dc6b427980a81cd8..2673ee9f937fb1e87bee5d6ebf36c177d097622b 100644 (file)
@@ -17,9 +17,6 @@ LL | |  }
    = note: struct `core::alloc::Layout` and struct `Layout` have similar names, but are actually distinct types
 note: struct `core::alloc::Layout` is defined in crate `core`
   --> $SRC_DIR/core/src/alloc/layout.rs:LL:COL
-   |
-LL | pub struct Layout {
-   | ^^^^^^^^^^^^^^^^^
 note: struct `Layout` is defined in the current crate
   --> $DIR/alloc-error-handler-bad-signature-2.rs:7:1
    |
index 851da231a73441708317aabc4c681f92e967f2dc..28926243390932390a6873f0c85fea9b707e6493 100644 (file)
@@ -7,9 +7,10 @@
 // compile-flags:-C panic=abort
 // aux-build:helper.rs
 
-#![feature(start, rustc_private, new_uninit, panic_info_message, lang_items)]
+#![feature(rustc_private, lang_items)]
 #![feature(alloc_error_handler)]
 #![no_std]
+#![no_main]
 
 extern crate alloc;
 extern crate libc;
@@ -21,35 +22,30 @@ pub fn __aeabi_unwind_cpp_pr0() {}
 #[no_mangle]
 pub fn __aeabi_unwind_cpp_pr1() {}
 
-use core::ptr::null_mut;
-use core::alloc::{GlobalAlloc, Layout};
 use alloc::boxed::Box;
+use alloc::string::ToString;
+use core::alloc::{GlobalAlloc, Layout};
+use core::ptr::null_mut;
 
 extern crate helper;
 
 struct MyAllocator;
 
 #[alloc_error_handler]
-fn my_oom(layout: Layout) -> !
-{
+fn my_oom(layout: Layout) -> ! {
     use alloc::fmt::write;
     unsafe {
         let size = layout.size();
         let mut s = alloc::string::String::new();
         write(&mut s, format_args!("My OOM: failed to allocate {} bytes!\n", size)).unwrap();
-        let s = s.as_str();
-        libc::write(libc::STDERR_FILENO, s as *const _ as _, s.len());
+        libc::write(libc::STDERR_FILENO, s.as_ptr() as *const _, s.len());
         libc::exit(0)
     }
 }
 
 unsafe impl GlobalAlloc for MyAllocator {
     unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
-        if layout.size() < 4096 {
-            libc::malloc(layout.size()) as _
-        } else {
-            null_mut()
-        }
+        if layout.size() < 4096 { libc::malloc(layout.size()) as _ } else { null_mut() }
     }
     unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
 }
@@ -60,26 +56,12 @@ unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
 #[panic_handler]
 fn panic(panic_info: &core::panic::PanicInfo) -> ! {
     unsafe {
-        if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
-            const PSTR: &str = "panic occurred: ";
-            const CR: &str = "\n";
-            libc::write(libc::STDERR_FILENO, PSTR as *const _ as _, PSTR.len());
-            libc::write(libc::STDERR_FILENO, s as *const _ as _, s.len());
-            libc::write(libc::STDERR_FILENO, CR as *const _ as _, CR.len());
-        }
-        if let Some(args) = panic_info.message() {
-            let mut s = alloc::string::String::new();
-            alloc::fmt::write(&mut s, *args).unwrap();
-            let s = s.as_str();
-            const PSTR: &str = "panic occurred: ";
-            const CR: &str = "\n";
-            libc::write(libc::STDERR_FILENO, PSTR as *const _ as _, PSTR.len());
-            libc::write(libc::STDERR_FILENO, s as *const _ as _, s.len());
-            libc::write(libc::STDERR_FILENO, CR as *const _ as _, CR.len());
-        } else {
-            const PSTR: &str = "panic occurred\n";
-            libc::write(libc::STDERR_FILENO, PSTR as *const _ as _, PSTR.len());
-        }
+        let s = panic_info.to_string();
+        const PSTR: &str = "panic occurred: ";
+        const CR: &str = "\n";
+        libc::write(libc::STDERR_FILENO, PSTR.as_ptr() as *const _, PSTR.len());
+        libc::write(libc::STDERR_FILENO, s.as_ptr() as *const _, s.len());
+        libc::write(libc::STDERR_FILENO, CR.as_ptr() as *const _, CR.len());
         libc::exit(1)
     }
 }
@@ -89,15 +71,14 @@ fn panic(panic_info: &core::panic::PanicInfo) -> ! {
 // in these libraries will refer to `rust_eh_personality` if LLVM can not *prove* the contents won't
 // unwind. So, for this test case we will define the symbol.
 #[lang = "eh_personality"]
-extern fn rust_eh_personality() {}
+extern "C" fn rust_eh_personality() {}
 
-#[derive(Debug)]
+#[derive(Default, Debug)]
 struct Page(#[allow(unused_tuple_struct_fields)] [[u64; 32]; 16]);
 
-#[start]
-pub fn main(_argc: isize, _argv: *const *const u8) -> isize {
-    let zero = Box::<Page>::new_zeroed();
-    let zero = unsafe { zero.assume_init() };
+#[no_mangle]
+fn main(_argc: i32, _argv: *const *const u8) -> isize {
+    let zero = Box::<Page>::new(Default::default());
     helper::work_with(&zero);
     1
 }
index 30ce0f162c7ac55d21b1e362078abbee6f8c22dd..56409e71339148d845199c63a58bf0d601db5a1d 100644 (file)
@@ -6,11 +6,10 @@
 // only-linux
 // compile-flags:-C panic=abort
 // aux-build:helper.rs
-// gate-test-default_alloc_error_handler
 
-#![feature(start, rustc_private, new_uninit, panic_info_message, lang_items)]
-#![feature(default_alloc_error_handler)]
+#![feature(rustc_private, lang_items)]
 #![no_std]
+#![no_main]
 
 extern crate alloc;
 extern crate libc;
@@ -23,6 +22,7 @@ pub fn __aeabi_unwind_cpp_pr0() {}
 pub fn __aeabi_unwind_cpp_pr1() {}
 
 use alloc::boxed::Box;
+use alloc::string::ToString;
 use core::alloc::{GlobalAlloc, Layout};
 use core::ptr::null_mut;
 
@@ -32,11 +32,7 @@ pub fn __aeabi_unwind_cpp_pr1() {}
 
 unsafe impl GlobalAlloc for MyAllocator {
     unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
-        if layout.size() < 4096 {
-            libc::malloc(layout.size()) as _
-        } else {
-            null_mut()
-        }
+        if layout.size() < 4096 { libc::malloc(layout.size()) as _ } else { null_mut() }
     }
     unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
 }
@@ -47,26 +43,12 @@ unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
 #[panic_handler]
 fn panic(panic_info: &core::panic::PanicInfo) -> ! {
     unsafe {
-        if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
-            const PSTR: &str = "panic occurred: ";
-            const CR: &str = "\n";
-            libc::write(libc::STDERR_FILENO, PSTR as *const _ as _, PSTR.len());
-            libc::write(libc::STDERR_FILENO, s as *const _ as _, s.len());
-            libc::write(libc::STDERR_FILENO, CR as *const _ as _, CR.len());
-        }
-        if let Some(args) = panic_info.message() {
-            let mut s = alloc::string::String::new();
-            alloc::fmt::write(&mut s, *args).unwrap();
-            let s = s.as_str();
-            const PSTR: &str = "panic occurred: ";
-            const CR: &str = "\n";
-            libc::write(libc::STDERR_FILENO, PSTR as *const _ as _, PSTR.len());
-            libc::write(libc::STDERR_FILENO, s as *const _ as _, s.len());
-            libc::write(libc::STDERR_FILENO, CR as *const _ as _, CR.len());
-        } else {
-            const PSTR: &str = "panic occurred\n";
-            libc::write(libc::STDERR_FILENO, PSTR as *const _ as _, PSTR.len());
-        }
+        let s = panic_info.to_string();
+        const PSTR: &str = "panic occurred: ";
+        const CR: &str = "\n";
+        libc::write(libc::STDERR_FILENO, PSTR.as_ptr() as *const _, PSTR.len());
+        libc::write(libc::STDERR_FILENO, s.as_ptr() as *const _, s.len());
+        libc::write(libc::STDERR_FILENO, CR.as_ptr() as *const _, CR.len());
         libc::exit(0)
     }
 }
@@ -76,15 +58,14 @@ fn panic(panic_info: &core::panic::PanicInfo) -> ! {
 // in these libraries will refer to `rust_eh_personality` if LLVM can not *prove* the contents won't
 // unwind. So, for this test case we will define the symbol.
 #[lang = "eh_personality"]
-extern fn rust_eh_personality() {}
+extern "C" fn rust_eh_personality() {}
 
-#[derive(Debug)]
+#[derive(Default, Debug)]
 struct Page(#[allow(unused_tuple_struct_fields)] [[u64; 32]; 16]);
 
-#[start]
-pub fn main(_argc: isize, _argv: *const *const u8) -> isize {
-    let zero = Box::<Page>::new_zeroed();
-    let zero = unsafe { zero.assume_init() };
+#[no_mangle]
+fn main(_argc: i32, _argv: *const *const u8) -> isize {
+    let zero = Box::<Page>::new(Default::default());
     helper::work_with(&zero);
     1
 }
index bf5f642ca823d61b6e0517308a3c72bbccce8327..afb7f8fea92a1fae2aa6c205b9e55849c3720ddb 100644 (file)
@@ -13,6 +13,10 @@ note: required by a bound in `f1`
    |
 LL | fn f1<F>(_: F) where F: Fn(&(), &()) {}
    |                         ^^^^^^^^^^^^ required by this bound in `f1`
+help: consider borrowing the argument
+   |
+LL |     f1(|_: &(), _: &()| {});
+   |            ~~~     ~~~
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:3:5
@@ -29,6 +33,10 @@ note: required by a bound in `f2`
    |
 LL | fn f2<F>(_: F) where F: for<'a> Fn(&'a (), &()) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f2`
+help: consider borrowing the argument
+   |
+LL |     f2(|_: &'a (), _: &()| {});
+   |            ~~~~~~     ~~~
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:4:5
@@ -45,6 +53,10 @@ note: required by a bound in `f3`
    |
 LL | fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {}
    |                             ^^^^^^^^^^^^^^^ required by this bound in `f3`
+help: consider borrowing the argument
+   |
+LL |     f3(|_: &(), _: &()| {});
+   |            ~~~     ~~~
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:5:5
@@ -61,6 +73,10 @@ note: required by a bound in `f4`
    |
 LL | fn f4<F>(_: F) where F: for<'r> Fn(&(), &'r ()) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f4`
+help: consider borrowing the argument
+   |
+LL |     f4(|_: &(), _: &'r ()| {});
+   |            ~~~     ~~~~~~
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:6:5
@@ -77,13 +93,19 @@ note: required by a bound in `f5`
    |
 LL | fn f5<F>(_: F) where F: for<'r> Fn(&'r (), &'r ()) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f5`
+help: consider borrowing the argument
+   |
+LL |     f5(|_: &'r (), _: &'r ()| {});
+   |            ~~~~~~     ~~~~~~
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:7:5
    |
 LL |     g1(|_: (), _: ()| {});
-   |     ^^ -------------- found signature defined here
-   |     |
+   |     ^^ --------------
+   |     |  |   |
+   |     |  |   help: consider borrowing the argument: `&()`
+   |     |  found signature defined here
    |     expected due to this
    |
    = note: expected closure signature `for<'a> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>) -> _`
@@ -98,8 +120,10 @@ error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:8:5
    |
 LL |     g2(|_: (), _: ()| {});
-   |     ^^ -------------- found signature defined here
-   |     |
+   |     ^^ --------------
+   |     |  |   |
+   |     |  |   help: consider borrowing the argument: `&()`
+   |     |  found signature defined here
    |     expected due to this
    |
    = note: expected closure signature `for<'a> fn(&'a (), for<'a> fn(&'a ())) -> _`
@@ -114,8 +138,10 @@ error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:9:5
    |
 LL |     g3(|_: (), _: ()| {});
-   |     ^^ -------------- found signature defined here
-   |     |
+   |     ^^ --------------
+   |     |  |   |
+   |     |  |   help: consider borrowing the argument: `&'s ()`
+   |     |  found signature defined here
    |     expected due to this
    |
    = note: expected closure signature `for<'s> fn(&'s (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>) -> _`
@@ -130,8 +156,10 @@ error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:10:5
    |
 LL |     g4(|_: (), _: ()| {});
-   |     ^^ -------------- found signature defined here
-   |     |
+   |     ^^ --------------
+   |     |  |   |
+   |     |  |   help: consider borrowing the argument: `&()`
+   |     |  found signature defined here
    |     expected due to this
    |
    = note: expected closure signature `for<'a> fn(&'a (), for<'r> fn(&'r ())) -> _`
@@ -157,6 +185,10 @@ note: required by a bound in `h1`
    |
 LL | fn h1<F>(_: F) where F: Fn(&(), Box<dyn Fn(&())>, &(), fn(&(), &())) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `h1`
+help: consider borrowing the argument
+   |
+LL |     h1(|_: &(), _: (), _: &(), _: ()| {});
+   |            ~~~            ~~~
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/anonymous-higher-ranked-lifetime.rs:12:5
@@ -173,6 +205,10 @@ note: required by a bound in `h2`
    |
 LL | fn h2<F>(_: F) where F: for<'t0> Fn(&(), Box<dyn Fn(&())>, &'t0 (), fn(&(), &())) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `h2`
+help: consider borrowing the argument
+   |
+LL |     h2(|_: &(), _: (), _: &'t0 (), _: ()| {});
+   |            ~~~            ~~~~~~~
 
 error: aborting due to 11 previous errors
 
diff --git a/src/test/ui/argument-suggestions/display-is-suggestable.rs b/src/test/ui/argument-suggestions/display-is-suggestable.rs
new file mode 100644 (file)
index 0000000..d765bc4
--- /dev/null
@@ -0,0 +1,8 @@
+use std::fmt::Display;
+
+fn foo(x: &(dyn Display + Send)) {}
+
+fn main() {
+    foo();
+    //~^ ERROR this function takes 1 argument but 0 arguments were supplied
+}
diff --git a/src/test/ui/argument-suggestions/display-is-suggestable.stderr b/src/test/ui/argument-suggestions/display-is-suggestable.stderr
new file mode 100644 (file)
index 0000000..edd72b5
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0061]: this function takes 1 argument but 0 arguments were supplied
+  --> $DIR/display-is-suggestable.rs:6:5
+   |
+LL |     foo();
+   |     ^^^-- an argument of type `&dyn std::fmt::Display + Send` is missing
+   |
+note: function defined here
+  --> $DIR/display-is-suggestable.rs:3:4
+   |
+LL | fn foo(x: &(dyn Display + Send)) {}
+   |    ^^^ ------------------------
+help: provide the argument
+   |
+LL |     foo(/* &dyn std::fmt::Display + Send */);
+   |        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0061`.
index 919550cac3087df1ee0e968f8c56eeb6c78d4215..c2a509a196344b910131329e9e49d6de0971d92b 100644 (file)
@@ -6,8 +6,8 @@ LL |     let [_, _] = a.into();
    |
 help: consider giving this pattern a type
    |
-LL |     let [_, _]: _ = a.into();
-   |               +++
+LL |     let [_, _]: /* Type */ = a.into();
+   |               ++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/associated-inherent-types/style.rs b/src/test/ui/associated-inherent-types/style.rs
new file mode 100644 (file)
index 0000000..8775bd1
--- /dev/null
@@ -0,0 +1,12 @@
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features, dead_code)]
+#![deny(non_camel_case_types)]
+
+struct S;
+
+impl S {
+    type typ = ();
+    //~^ ERROR associated type `typ` should have an upper camel case name
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-inherent-types/style.stderr b/src/test/ui/associated-inherent-types/style.stderr
new file mode 100644 (file)
index 0000000..f83061f
--- /dev/null
@@ -0,0 +1,14 @@
+error: associated type `typ` should have an upper camel case name
+  --> $DIR/style.rs:8:10
+   |
+LL |     type typ = ();
+   |          ^^^ help: convert the identifier to upper camel case: `Typ`
+   |
+note: the lint level is defined here
+  --> $DIR/style.rs:3:9
+   |
+LL | #![deny(non_camel_case_types)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/associated-item/issue-105449.rs b/src/test/ui/associated-item/issue-105449.rs
new file mode 100644 (file)
index 0000000..dd14e05
--- /dev/null
@@ -0,0 +1,59 @@
+// check-pass
+// compile-flags: -C debug_assertions=yes -Zunstable-options
+
+#[allow(dead_code)]
+fn problematic_function<Space>()
+where
+    DefaultAlloc: FinAllok<R1, Space>,
+{
+    let e = Edge2dElement;
+    let _ = Into::<Point>::into(e.map_reference_coords());
+}
+impl<N> Allocator<N, R0> for DefaultAlloc {
+    type Buffer = MStorage;
+}
+impl<N> Allocator<N, R1> for DefaultAlloc {
+    type Buffer = MStorage;
+}
+impl<N, D> From<VectorN<N, D>> for Point
+where
+    DefaultAlloc: Allocator<N, D>,
+{
+    fn from(_: VectorN<N, D>) -> Self {
+        unimplemented!()
+    }
+}
+impl<GeometryDim, NodalDim> FinAllok<GeometryDim, NodalDim> for DefaultAlloc
+where
+    DefaultAlloc: Allocator<Ure, GeometryDim>,
+    DefaultAlloc: Allocator<Ure, NodalDim>
+{
+}
+impl FiniteElement<R1> for Edge2dElement {
+    fn map_reference_coords(&self) -> VectorN<Ure, R1> {
+        unimplemented!()
+    }
+}
+type VectorN<N, R> = (N, R, <DefaultAlloc as Allocator<N, R>>::Buffer);
+struct DefaultAlloc;
+struct R0;
+struct R1;
+struct MStorage;
+struct Point;
+struct Edge2dElement;
+struct Ure;
+trait Allocator<N, R> {
+    type Buffer;
+}
+trait FinAllok<GeometryDim, NodalDim>:
+    Allocator<Ure, GeometryDim> +
+    Allocator<Ure, NodalDim> +
+{
+}
+trait FiniteElement<Rau>
+where
+    DefaultAlloc: FinAllok<Rau, Rau>,
+{
+    fn map_reference_coords(&self) -> VectorN<Ure, Rau>;
+}
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/const-projection-err.gce.stderr b/src/test/ui/associated-type-bounds/const-projection-err.gce.stderr
new file mode 100644 (file)
index 0000000..0f1ec9a
--- /dev/null
@@ -0,0 +1,24 @@
+warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/const-projection-err.rs:4:26
+   |
+LL | #![cfg_attr(gce, feature(generic_const_exprs))]
+   |                          ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0271]: type mismatch resolving `<T as TraitWAssocConst>::A == 1`
+  --> $DIR/const-projection-err.rs:14:11
+   |
+LL |     foo::<T>();
+   |           ^ expected `0`, found `1`
+   |
+note: required by a bound in `foo`
+  --> $DIR/const-projection-err.rs:11:28
+   |
+LL | fn foo<T: TraitWAssocConst<A = 1>>() {}
+   |                            ^^^^^ required by this bound in `foo`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/associated-type-bounds/const-projection-err.rs b/src/test/ui/associated-type-bounds/const-projection-err.rs
new file mode 100644 (file)
index 0000000..bead856
--- /dev/null
@@ -0,0 +1,18 @@
+// revisions: stock gce
+
+#![feature(associated_const_equality)]
+#![cfg_attr(gce, feature(generic_const_exprs))]
+//[gce]~^ WARN the feature `generic_const_exprs` is incomplete
+
+trait TraitWAssocConst {
+    const A: usize;
+}
+
+fn foo<T: TraitWAssocConst<A = 1>>() {}
+
+fn bar<T: TraitWAssocConst<A = 0>>() {
+    foo::<T>();
+    //~^ ERROR type mismatch resolving `<T as TraitWAssocConst>::A == 1`
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/const-projection-err.stock.stderr b/src/test/ui/associated-type-bounds/const-projection-err.stock.stderr
new file mode 100644 (file)
index 0000000..bf08242
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0271]: type mismatch resolving `<T as TraitWAssocConst>::A == 1`
+  --> $DIR/const-projection-err.rs:14:11
+   |
+LL |     foo::<T>();
+   |           ^ expected `1`, found `<T as TraitWAssocConst>::A`
+   |
+   = note: expected constant `1`
+              found constant `<T as TraitWAssocConst>::A`
+note: required by a bound in `foo`
+  --> $DIR/const-projection-err.rs:11:28
+   |
+LL | fn foo<T: TraitWAssocConst<A = 1>>() {}
+   |                            ^^^^^ required by this bound in `foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
index 1c20ead0556593267c0de5ff5de5e0e81c38309e..dc93c47dace2331381d8445925cde9e9befe1eea 100644 (file)
@@ -15,9 +15,6 @@ LL | fn get_iter(vec: &[i32]) -> impl Iterator<Item = {}> + '_ {
    |
 note: associated type defined here
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     type Item;
-   |     ^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
index 26b9f4b3a92660ea78b923adb3884545ea4eb81a..fed60ccf089d05c85288a7ef3774506f7d2dbd96 100644 (file)
@@ -4,5 +4,5 @@
 
 fn main() {
     let _: &dyn I32Iterator<Item = u32> = &vec![42].into_iter();
-    //~^ ERROR expected `std::vec::IntoIter<u32>` to be an iterator that yields `i32`, but it yields `u32`
+    //~^ ERROR expected `IntoIter<u32>` to be an iterator that yields `i32`, but it yields `u32`
 }
index 2d25f68de44ad1c34a7c36976ce21a9300699deb..a28a0b74e4accd98c47bbf6f001d9562560f4ff8 100644 (file)
@@ -1,4 +1,4 @@
-error[E0271]: expected `std::vec::IntoIter<u32>` to be an iterator that yields `i32`, but it yields `u32`
+error[E0271]: expected `IntoIter<u32>` to be an iterator that yields `i32`, but it yields `u32`
   --> $DIR/associated-types-overridden-binding-2.rs:6:43
    |
 LL |     let _: &dyn I32Iterator<Item = u32> = &vec![42].into_iter();
index e51a8f3bd1a3ae05363f2db0ff0862ae66d0956d..ef9b7cae01bbd4c00290ff2dd006e5562335662d 100644 (file)
@@ -6,6 +6,11 @@ LL |     fn bar() -> isize;
 ...
 LL |     let x: isize = Foo::bar();
    |                    ^^^^^^^^ cannot call associated function of trait
+   |
+help: use the fully-qualified path to the only available implementation
+   |
+LL |     let x: isize = <isize as Foo>::bar();
+   |                    +++++++++    +
 
 error: aborting due to previous error
 
index 8455f88f18e7a996cac6562c274689a65d7014f2..fc830b8d6768657f9ef06dc1a29b89088ac2d090 100644 (file)
@@ -7,9 +7,6 @@ LL |     type Ty = Vec<[u8]>;
    = help: the trait `Sized` is not implemented for `[u8]`
 note: required by a bound in `Vec`
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
-   |                ^ required by this bound in `Vec`
 
 error: aborting due to previous error
 
index 0edc9a556b7f6090402256492f1069d6fe7aad27..8e7cf86c4066f112e8125e443e759ebb606f0957 100644 (file)
@@ -6,9 +6,6 @@ LL | trait ArithmeticOps: Add<Output=Self> + Sub<Output=Self> + Mul<Output=Self>
    |
 note: required by a bound in `Add`
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait Add<Rhs = Self> {
-   |               ^^^^^^^^^^ required by this bound in `Add`
 help: consider further restricting `Self`
    |
 LL | trait ArithmeticOps: Add<Output=Self> + Sub<Output=Self> + Mul<Output=Self> + Div<Output=Self> + Sized {}
index 616623ee07759eeabd7c7fb4dc211d435aedd462..f0f5245a3b42ba5d395058ed9bad1037146056b0 100644 (file)
@@ -68,14 +68,10 @@ note: future is not `Send` as this value is used across an await
   --> $DIR/async-await-let-else.rs:33:28
    |
 LL |         (Rc::new(()), bar().await);
-   |          -----------       ^^^^^^ await occurs here, with `Rc::new(())` maybe used later
-   |          |
+   |          -----------       ^^^^^^ - `Rc::new(())` is later dropped here
+   |          |                 |
+   |          |                 await occurs here, with `Rc::new(())` maybe used later
    |          has type `Rc<()>` which is not `Send`
-note: `Rc::new(())` is later dropped here
-  --> $DIR/async-await-let-else.rs:33:35
-   |
-LL |         (Rc::new(()), bar().await);
-   |                                   ^
 note: required by a bound in `is_send`
   --> $DIR/async-await-let-else.rs:19:15
    |
index 7f93563e28842119a6b983edbf1418a09b5955ec..d3c5e80a30df443ee5cf66c942c445ba95cec701 100644 (file)
@@ -53,14 +53,10 @@ note: future is not `Send` as this value is used across an await
   --> $DIR/async-await-let-else.rs:33:28
    |
 LL |         (Rc::new(()), bar().await);
-   |          -----------       ^^^^^^ await occurs here, with `Rc::new(())` maybe used later
-   |          |
+   |          -----------       ^^^^^^ - `Rc::new(())` is later dropped here
+   |          |                 |
+   |          |                 await occurs here, with `Rc::new(())` maybe used later
    |          has type `Rc<()>` which is not `Send`
-note: `Rc::new(())` is later dropped here
-  --> $DIR/async-await-let-else.rs:33:35
-   |
-LL |         (Rc::new(()), bar().await);
-   |                                   ^
 note: required by a bound in `is_send`
   --> $DIR/async-await-let-else.rs:19:15
    |
diff --git a/src/test/ui/async-await/drop-track-bad-field-in-fru.rs b/src/test/ui/async-await/drop-track-bad-field-in-fru.rs
new file mode 100644 (file)
index 0000000..28ad776
--- /dev/null
@@ -0,0 +1,10 @@
+// compile-flags: -Zdrop-tracking
+// edition: 2021
+
+fn main() {}
+
+async fn foo() {
+    None { value: (), ..Default::default() }.await;
+    //~^ ERROR `Option<_>` is not a future
+    //~| ERROR variant `Option<_>::None` has no field named `value`
+}
diff --git a/src/test/ui/async-await/drop-track-bad-field-in-fru.stderr b/src/test/ui/async-await/drop-track-bad-field-in-fru.stderr
new file mode 100644 (file)
index 0000000..819b64a
--- /dev/null
@@ -0,0 +1,23 @@
+error[E0559]: variant `Option<_>::None` has no field named `value`
+  --> $DIR/drop-track-bad-field-in-fru.rs:7:12
+   |
+LL |     None { value: (), ..Default::default() }.await;
+   |            ^^^^^ `Option<_>::None` does not have this field
+
+error[E0277]: `Option<_>` is not a future
+  --> $DIR/drop-track-bad-field-in-fru.rs:7:45
+   |
+LL |     None { value: (), ..Default::default() }.await;
+   |                                             ^^^^^^
+   |                                             |
+   |                                             `Option<_>` is not a future
+   |                                             help: remove the `.await`
+   |
+   = help: the trait `Future` is not implemented for `Option<_>`
+   = note: Option<_> must be a future or must implement `IntoFuture` to be awaited
+   = note: required for `Option<_>` to implement `IntoFuture`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0559.
+For more information about an error, try `rustc --explain E0277`.
index 1686153acf9a63aa8a9cddb14e64f0a990a5cade..963c6ba57adf89448eac3463e72257edc5a0cbd1 100644 (file)
@@ -12,9 +12,6 @@ LL |     fun(async {}, async {});
               found `async` block `[async block@$DIR/generator-desc.rs:10:19: 10:27]`
 note: function defined here
   --> $SRC_DIR/core/src/future/mod.rs:LL:COL
-   |
-LL | pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut {
-   |              ^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/generator-desc.rs:12:16
index 61d7e2520eab7a8cea7c3f8f97fd2a932aa4d5bd..1b1b3cffd58f3d81f2eccfd6d53a374a64c272aa 100644 (file)
@@ -1,4 +1,3 @@
-// check-pass
 // edition: 2021
 
 #![feature(async_fn_in_trait)]
@@ -13,11 +12,9 @@ trait MyTrait {
 }
 
 impl MyTrait for i32 {
-    // This will break once a PR that implements #102745 is merged
     fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>> {
-        Box::pin(async {
-            *self
-        })
+        //~^ ERROR method `foo` should be async
+        Box::pin(async { *self })
     }
 }
 
diff --git a/src/test/ui/async-await/in-trait/async-example-desugared-boxed.stderr b/src/test/ui/async-await/in-trait/async-example-desugared-boxed.stderr
new file mode 100644 (file)
index 0000000..60fa534
--- /dev/null
@@ -0,0 +1,11 @@
+error: method `foo` should be async because the method from the trait is async
+  --> $DIR/async-example-desugared-boxed.rs:15:5
+   |
+LL |     async fn foo(&self) -> i32;
+   |     --------------------------- required because the trait method is async
+...
+LL |     fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>> {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/async-await/in-trait/async-example-desugared-extra.rs b/src/test/ui/async-await/in-trait/async-example-desugared-extra.rs
new file mode 100644 (file)
index 0000000..81e1e59
--- /dev/null
@@ -0,0 +1,37 @@
+// check-pass
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+use std::pin::Pin;
+use std::task::Poll;
+
+trait MyTrait {
+    async fn foo(&self) -> i32;
+}
+
+#[derive(Clone)]
+struct MyFuture(i32);
+
+impl Future for MyFuture {
+    type Output = i32;
+    fn poll(
+        self: Pin<&mut Self>,
+        _: &mut std::task::Context<'_>,
+    ) -> Poll<<Self as Future>::Output> {
+        Poll::Ready(self.0)
+    }
+}
+
+impl MyTrait for i32 {
+    // FIXME: this should eventually require `#[refine]` to compile, because it also provides
+    // `Clone`.
+    fn foo(&self) -> impl Future<Output = i32> + Clone {
+        MyFuture(*self)
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/in-trait/async-example-desugared-manual.rs b/src/test/ui/async-await/in-trait/async-example-desugared-manual.rs
new file mode 100644 (file)
index 0000000..71473e7
--- /dev/null
@@ -0,0 +1,29 @@
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+use std::task::Poll;
+
+trait MyTrait {
+    async fn foo(&self) -> i32;
+}
+
+struct MyFuture;
+impl Future for MyFuture {
+    type Output = i32;
+    fn poll(self: std::pin::Pin<&mut Self>, _: &mut std::task::Context<'_>) -> Poll<Self::Output> {
+        Poll::Ready(0)
+    }
+}
+
+impl MyTrait for u32 {
+    fn foo(&self) -> MyFuture {
+        //~^ ERROR method `foo` should be async
+        MyFuture
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/in-trait/async-example-desugared-manual.stderr b/src/test/ui/async-await/in-trait/async-example-desugared-manual.stderr
new file mode 100644 (file)
index 0000000..567a36a
--- /dev/null
@@ -0,0 +1,11 @@
+error: method `foo` should be async because the method from the trait is async
+  --> $DIR/async-example-desugared-manual.rs:23:5
+   |
+LL |     async fn foo(&self) -> i32;
+   |     --------------------------- required because the trait method is async
+...
+LL |     fn foo(&self) -> MyFuture {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
index 1313c9edd861c213850af2725cadc84f52146fed..fb92ec786746f9cb9ba3c18b0c9a239da183fa1e 100644 (file)
@@ -12,11 +12,8 @@ trait MyTrait {
 }
 
 impl MyTrait for i32 {
-    // This will break once a PR that implements #102745 is merged
     fn foo(&self) -> impl Future<Output = i32> + '_ {
-        async {
-            *self
-        }
+        async { *self }
     }
 }
 
diff --git a/src/test/ui/async-await/in-trait/bad-signatures.rs b/src/test/ui/async-await/in-trait/bad-signatures.rs
new file mode 100644 (file)
index 0000000..b86f1d1
--- /dev/null
@@ -0,0 +1,16 @@
+// edition:2021
+
+#![feature(async_fn_in_trait)]
+//~^ WARN the feature `async_fn_in_trait` is incomplete
+
+trait MyTrait {
+    async fn bar(&abc self);
+    //~^ ERROR expected identifier, found keyword `self`
+    //~| ERROR expected one of `:`, `@`, or `|`, found keyword `self`
+}
+
+impl MyTrait for () {
+    async fn bar(&self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/in-trait/bad-signatures.stderr b/src/test/ui/async-await/in-trait/bad-signatures.stderr
new file mode 100644 (file)
index 0000000..e0ba7b5
--- /dev/null
@@ -0,0 +1,26 @@
+error: expected identifier, found keyword `self`
+  --> $DIR/bad-signatures.rs:7:23
+   |
+LL |     async fn bar(&abc self);
+   |                       ^^^^ expected identifier, found keyword
+
+error: expected one of `:`, `@`, or `|`, found keyword `self`
+  --> $DIR/bad-signatures.rs:7:23
+   |
+LL |     async fn bar(&abc self);
+   |                  -----^^^^
+   |                  |    |
+   |                  |    expected one of `:`, `@`, or `|`
+   |                  help: declare the type after the parameter binding: `<identifier>: <type>`
+
+warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/bad-signatures.rs:3:12
+   |
+LL | #![feature(async_fn_in_trait)]
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
index f94d32145a290297c1750035ba89297ecf8220eb..9598d53bce8b2ec02cd2f6e91086eb8560b90595 100644 (file)
@@ -9,7 +9,7 @@ trait MyTrait {
 
 impl MyTrait for i32 {
     fn foo(&self) -> i32 {
-        //~^ ERROR: `i32` is not a future [E0277]
+        //~^ ERROR: method `foo` should be async
         *self
     }
 }
index 03321dc5b5af16a4ccbd9baa3f78fb005151201b..579801d0f3975cf89a8bbe03eae3dd7f9837fadc 100644 (file)
@@ -1,17 +1,11 @@
-error[E0277]: `i32` is not a future
-  --> $DIR/fn-not-async-err.rs:11:22
-   |
-LL |     fn foo(&self) -> i32 {
-   |                      ^^^ `i32` is not a future
-   |
-   = help: the trait `Future` is not implemented for `i32`
-   = note: i32 must be a future or must implement `IntoFuture` to be awaited
-note: required by a bound in `MyTrait::foo::{opaque#0}`
-  --> $DIR/fn-not-async-err.rs:7:28
+error: method `foo` should be async because the method from the trait is async
+  --> $DIR/fn-not-async-err.rs:11:5
    |
 LL |     async fn foo(&self) -> i32;
-   |                            ^^^ required by this bound in `MyTrait::foo::{opaque#0}`
+   |     --------------------------- required because the trait method is async
+...
+LL |     fn foo(&self) -> i32 {
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0277`.
index 594baa91ad8ba61c21eb6914ae4c0b24e5fedd0b..2c4ed5535801e95db3c17300b6784db11b3fbeb4 100644 (file)
@@ -12,9 +12,7 @@ trait MyTrait {
 impl MyTrait for i32 {
     fn foo(&self) -> impl Future<Output = i32> {
         //~^ ERROR `impl Trait` only allowed in function and inherent method return types, not in `impl` method return [E0562]
-        async {
-            *self
-        }
+        async { *self }
     }
 }
 
diff --git a/src/test/ui/async-await/in-trait/issue-104678.rs b/src/test/ui/async-await/in-trait/issue-104678.rs
new file mode 100644 (file)
index 0000000..e396df4
--- /dev/null
@@ -0,0 +1,31 @@
+// edition:2021
+// check-pass
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+pub trait Pool {
+    type Conn;
+
+    async fn async_callback<'a, F: FnOnce(&'a Self::Conn) -> Fut, Fut: Future<Output = ()>>(
+        &'a self,
+        callback: F,
+    ) -> ();
+}
+
+pub struct PoolImpl;
+pub struct ConnImpl;
+
+impl Pool for PoolImpl {
+    type Conn = ConnImpl;
+
+    async fn async_callback<'a, F: FnOnce(&'a Self::Conn) -> Fut, Fut: Future<Output = ()>>(
+        &'a self,
+        _callback: F,
+    ) -> () {
+        todo!()
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/in-trait/nested-rpit.rs b/src/test/ui/async-await/in-trait/nested-rpit.rs
new file mode 100644 (file)
index 0000000..ae8e0ae
--- /dev/null
@@ -0,0 +1,17 @@
+// check-pass
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+use std::marker::PhantomData;
+
+trait Lockable<K, V> {
+    async fn lock_all_entries(&self) -> impl Future<Output = Guard<'_>>;
+}
+
+struct Guard<'a>(PhantomData<&'a ()>);
+
+fn main() {}
index 34b31198e4f613a16a485e4d1d5a0ea144e7f9e8..8036d82daa4a33f51f3dff008efa3c58b55c50bb 100644 (file)
@@ -12,14 +12,10 @@ LL |           baz(|| async{
    |  _____________-
 LL | |             foo(tx.clone());
 LL | |         }).await;
-   | |         - ^^^^^^ await occurs here, with the value maybe used later
-   | |_________|
+   | |         - ^^^^^^- the value is later dropped here
+   | |         | |
+   | |_________| await occurs here, with the value maybe used later
    |           has type `[closure@$DIR/issue-70935-complex-spans.rs:17:13: 17:15]` which is not `Send`
-note: the value is later dropped here
-  --> $DIR/issue-70935-complex-spans.rs:19:17
-   |
-LL |         }).await;
-   |                 ^
 
 error: aborting due to previous error
 
index 919abf646037deaa2bcd7ceae1f8aa14e4214d1f..4a1705715caccbae37ea337820e2a12a5c57d4cf 100644 (file)
@@ -8,9 +8,6 @@ LL |             let mut f = File::open(path.to_str())?;
    |
 note: required by a bound in `File::open`
   --> $SRC_DIR/std/src/fs.rs:LL:COL
-   |
-LL |     pub fn open<P: AsRef<Path>>(path: P) -> io::Result<File> {
-   |                    ^^^^^^^^^^^ required by this bound in `File::open`
 
 error: aborting due to previous error
 
index 45f5ec40cd758b08f914aabdce72e0d85bd7996f..40c0e72b20391047a5ff92bb21ff2aafa86e4883 100644 (file)
@@ -6,11 +6,6 @@ LL | async fn copy() -> Result<()>
    |                    |
    |                    expected 2 generic arguments
    |
-note: enum defined here, with 2 generic parameters: `T`, `E`
-  --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   |          ^^^^^^ -  -
 help: add missing generic argument
    |
 LL | async fn copy() -> Result<(), E>
index ab196dca20cc460bbf61e21bcbdd6ad43eb384cb..1033fa6cc8b344c474a9c79b6d74fdaa9eb903e9 100644 (file)
@@ -13,14 +13,10 @@ note: future is not `Send` as this value is used across an await
   --> $DIR/issue-65436-raw-ptr-not-send.rs:18:35
    |
 LL |         bar(Foo(std::ptr::null())).await;
-   |                 ----------------  ^^^^^^ await occurs here, with `std::ptr::null()` maybe used later
-   |                 |
+   |                 ----------------  ^^^^^^- `std::ptr::null()` is later dropped here
+   |                 |                 |
+   |                 |                 await occurs here, with `std::ptr::null()` maybe used later
    |                 has type `*const u8` which is not `Send`
-note: `std::ptr::null()` is later dropped here
-  --> $DIR/issue-65436-raw-ptr-not-send.rs:18:41
-   |
-LL |         bar(Foo(std::ptr::null())).await;
-   |                                         ^
 help: consider moving this into a `let` binding to create a shorter lived borrow
   --> $DIR/issue-65436-raw-ptr-not-send.rs:18:13
    |
index 316b6d06f932ac1189cbbe6370beb920c259a178..2ce68a782918cf064c449afedab10f6815a2f3e2 100644 (file)
@@ -9,14 +9,10 @@ note: future is not `Send` as this value is used across an await
   --> $DIR/auxiliary/issue_67893.rs:9:26
    |
 LL |     f(*x.lock().unwrap()).await;
-   |        ----------------- ^^^^^^ await occurs here, with `x.lock().unwrap()` maybe used later
-   |        |
+   |        ----------------- ^^^^^^- `x.lock().unwrap()` is later dropped here
+   |        |                 |
+   |        |                 await occurs here, with `x.lock().unwrap()` maybe used later
    |        has type `MutexGuard<'_, ()>` which is not `Send`
-note: `x.lock().unwrap()` is later dropped here
-  --> $DIR/auxiliary/issue_67893.rs:9:32
-   |
-LL |     f(*x.lock().unwrap()).await;
-   |                                ^
 note: required by a bound in `g`
   --> $DIR/issue-67893.rs:6:14
    |
index 83d1a02c876b19e3ca71523aba19fdc147b0005d..0a6f705e255ae4c89646860970e94e4cd53cbe93 100644 (file)
@@ -14,9 +14,6 @@ LL | struct Sleep(std::marker::PhantomPinned);
    |        ^^^^^
 note: required by a bound in `Pin::<P>::new`
   --> $SRC_DIR/core/src/pin.rs:LL:COL
-   |
-LL | impl<P: Deref<Target: Unpin>> Pin<P> {
-   |                       ^^^^^ required by this bound in `Pin::<P>::new`
 
 error: aborting due to previous error
 
index 2e8723b2743a79062274a8c25f471193dcaec66a..b1f4a73aafeabf317352e1ccf16cb163f9726e8c 100644 (file)
@@ -6,11 +6,9 @@ LL | struct Sleep;
 ...
 LL |         self.sleep.poll(cx)
    |                    ^^^^ method not found in `Sleep`
+  --> $SRC_DIR/core/src/future/future.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/future/future.rs:LL:COL
-   |
-LL |     fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
-   |        ---- the method is available for `Pin<&mut Sleep>` here
+   = note: the method is available for `Pin<&mut Sleep>` here
    |
 help: consider wrapping the receiver expression with the appropriate type
    |
diff --git a/src/test/ui/async-await/track-caller/async-block.rs b/src/test/ui/async-await/track-caller/async-block.rs
new file mode 100644 (file)
index 0000000..8e81387
--- /dev/null
@@ -0,0 +1,9 @@
+// edition:2021
+
+#![feature(closure_track_caller, stmt_expr_attributes)]
+
+fn main() {
+    let _ = #[track_caller] async {
+        //~^ ERROR attribute should be applied to a function definition [E0739]
+    };
+}
diff --git a/src/test/ui/async-await/track-caller/async-block.stderr b/src/test/ui/async-await/track-caller/async-block.stderr
new file mode 100644 (file)
index 0000000..4074399
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0739]: attribute should be applied to a function definition
+  --> $DIR/async-block.rs:6:13
+   |
+LL |       let _ = #[track_caller] async {
+   |  _____________^^^^^^^^^^^^^^^_-
+LL | |
+LL | |     };
+   | |_____- not a function definition
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0739`.
diff --git a/src/test/ui/async-await/track-caller/async-closure-gate.rs b/src/test/ui/async-await/track-caller/async-closure-gate.rs
new file mode 100644 (file)
index 0000000..9593fdb
--- /dev/null
@@ -0,0 +1,10 @@
+// edition:2021
+
+#![feature(async_closure, stmt_expr_attributes)]
+
+fn main() {
+    let _ = #[track_caller] async || {
+        //~^ ERROR `#[track_caller]` on closures is currently unstable [E0658]
+        //~| ERROR `#[track_caller]` on closures is currently unstable [E0658]
+    };
+}
diff --git a/src/test/ui/async-await/track-caller/async-closure-gate.stderr b/src/test/ui/async-await/track-caller/async-closure-gate.stderr
new file mode 100644 (file)
index 0000000..be3d110
--- /dev/null
@@ -0,0 +1,25 @@
+error[E0658]: `#[track_caller]` on closures is currently unstable
+  --> $DIR/async-closure-gate.rs:6:13
+   |
+LL |     let _ = #[track_caller] async || {
+   |             ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
+   = help: add `#![feature(closure_track_caller)]` to the crate attributes to enable
+
+error[E0658]: `#[track_caller]` on closures is currently unstable
+  --> $DIR/async-closure-gate.rs:6:38
+   |
+LL |       let _ = #[track_caller] async || {
+   |  ______________________________________^
+LL | |
+LL | |
+LL | |     };
+   | |_____^
+   |
+   = note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
+   = help: add `#![feature(closure_track_caller)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
index 5ebfeb3f36ac162f402dc3b780f6767c2911d35a..066cf97628fa5cd9d5852847bfddb5f799c7555a 100644 (file)
@@ -1,7 +1,7 @@
 // run-pass
 // edition:2021
 // needs-unwind
-#![feature(closure_track_caller)]
+#![feature(closure_track_caller, async_closure, stmt_expr_attributes)]
 
 use std::future::Future;
 use std::panic;
@@ -67,6 +67,13 @@ async fn foo_assoc() {
     Foo::bar_assoc().await
 }
 
+async fn foo_closure() {
+    let c = #[track_caller] async || {
+        panic!();
+    };
+    c().await
+}
+
 fn panicked_at(f: impl FnOnce() + panic::UnwindSafe) -> u32 {
     let loc = Arc::new(Mutex::new(None));
 
@@ -87,4 +94,5 @@ fn main() {
     assert_eq!(panicked_at(|| block_on(foo())), 41);
     assert_eq!(panicked_at(|| block_on(foo_track_caller())), 54);
     assert_eq!(panicked_at(|| block_on(foo_assoc())), 67);
+    assert_eq!(panicked_at(|| block_on(foo_closure())), 74);
 }
index c734f8c1e17e3471dd2e82daf9bc2d5bc0cf2dce..6fbbb55437eb2f8b91a0d3dd17346411fbdcf7c4 100644 (file)
@@ -10,9 +10,6 @@ LL |     drop(lhs);
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL |     fn add(self, rhs: Rhs) -> Self::Output;
-   |            ^^^^
 help: consider further restricting this bound
    |
 LL | fn add<A: Add<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -46,9 +43,6 @@ LL |     drop(lhs);
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL |     fn sub(self, rhs: Rhs) -> Self::Output;
-   |            ^^^^
 help: consider further restricting this bound
    |
 LL | fn sub<A: Sub<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -82,9 +76,6 @@ LL |     drop(lhs);
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL |     fn mul(self, rhs: Rhs) -> Self::Output;
-   |            ^^^^
 help: consider further restricting this bound
    |
 LL | fn mul<A: Mul<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -118,9 +109,6 @@ LL |     drop(lhs);
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL |     fn div(self, rhs: Rhs) -> Self::Output;
-   |            ^^^^
 help: consider further restricting this bound
    |
 LL | fn div<A: Div<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -154,9 +142,6 @@ LL |     drop(lhs);
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL |     fn rem(self, rhs: Rhs) -> Self::Output;
-   |            ^^^^
 help: consider further restricting this bound
    |
 LL | fn rem<A: Rem<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -190,9 +175,6 @@ LL |     drop(lhs);
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL |     fn bitand(self, rhs: Rhs) -> Self::Output;
-   |               ^^^^
 help: consider further restricting this bound
    |
 LL | fn bitand<A: BitAnd<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -226,9 +208,6 @@ LL |     drop(lhs);
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL |     fn bitor(self, rhs: Rhs) -> Self::Output;
-   |              ^^^^
 help: consider further restricting this bound
    |
 LL | fn bitor<A: BitOr<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -262,9 +241,6 @@ LL |     drop(lhs);
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL |     fn bitxor(self, rhs: Rhs) -> Self::Output;
-   |               ^^^^
 help: consider further restricting this bound
    |
 LL | fn bitxor<A: BitXor<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -298,9 +274,6 @@ LL |     drop(lhs);
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL |     fn shl(self, rhs: Rhs) -> Self::Output;
-   |            ^^^^
 help: consider further restricting this bound
    |
 LL | fn shl<A: Shl<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -334,9 +307,6 @@ LL |     drop(lhs);
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL |     fn shr(self, rhs: Rhs) -> Self::Output;
-   |            ^^^^
 help: consider further restricting this bound
    |
 LL | fn shr<A: Shr<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
index 994eaf9d8c77885a219ea90c5a0a41e07896e4ec..dae267da05d1758bd31791fff00a437cc3066a8a 100644 (file)
@@ -13,9 +13,6 @@ LL | |     x;
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL |     fn add(self, rhs: Rhs) -> Self::Output;
-   |            ^^^^
 help: consider further restricting this bound
    |
 LL | fn double_move<T: Add<Output=()> + Copy>(x: T) {
@@ -78,9 +75,6 @@ LL | |     *n;
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL |     fn add(self, rhs: Rhs) -> Self::Output;
-   |            ^^^^
 
 error[E0507]: cannot move out of `*n` which is behind a shared reference
   --> $DIR/binop-move-semantics.rs:32:5
index b9c7e1bea706a0d8f08036f950cb9d83548fdf50..6e236ca5296a17eee6b9489dbcb05e4b3a4b32b6 100644 (file)
@@ -11,11 +11,8 @@ note: an implementation of `Add<_>` might be missing for `A`
    |
 LL | struct A;
    | ^^^^^^^^ must implement `Add<_>`
-note: the following trait must be implemented
+note: the trait `Add` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait Add<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0369]: cannot subtract `A` from `A`
   --> $DIR/issue-28837.rs:8:7
@@ -30,11 +27,8 @@ note: an implementation of `Sub<_>` might be missing for `A`
    |
 LL | struct A;
    | ^^^^^^^^ must implement `Sub<_>`
-note: the following trait must be implemented
+note: the trait `Sub` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait Sub<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0369]: cannot multiply `A` by `A`
   --> $DIR/issue-28837.rs:10:7
@@ -49,11 +43,8 @@ note: an implementation of `Mul<_>` might be missing for `A`
    |
 LL | struct A;
    | ^^^^^^^^ must implement `Mul<_>`
-note: the following trait must be implemented
+note: the trait `Mul` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait Mul<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0369]: cannot divide `A` by `A`
   --> $DIR/issue-28837.rs:12:7
@@ -68,11 +59,8 @@ note: an implementation of `Div<_>` might be missing for `A`
    |
 LL | struct A;
    | ^^^^^^^^ must implement `Div<_>`
-note: the following trait must be implemented
+note: the trait `Div` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait Div<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0369]: cannot mod `A` by `A`
   --> $DIR/issue-28837.rs:14:7
@@ -87,11 +75,8 @@ note: an implementation of `Rem<_>` might be missing for `A`
    |
 LL | struct A;
    | ^^^^^^^^ must implement `Rem<_>`
-note: the following trait must be implemented
+note: the trait `Rem` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait Rem<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0369]: no implementation for `A & A`
   --> $DIR/issue-28837.rs:16:7
@@ -106,11 +91,8 @@ note: an implementation of `BitAnd<_>` might be missing for `A`
    |
 LL | struct A;
    | ^^^^^^^^ must implement `BitAnd<_>`
-note: the following trait must be implemented
+note: the trait `BitAnd` must be implemented
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL | pub trait BitAnd<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0369]: no implementation for `A | A`
   --> $DIR/issue-28837.rs:18:7
@@ -125,11 +107,8 @@ note: an implementation of `BitOr<_>` might be missing for `A`
    |
 LL | struct A;
    | ^^^^^^^^ must implement `BitOr<_>`
-note: the following trait must be implemented
+note: the trait `BitOr` must be implemented
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL | pub trait BitOr<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0369]: no implementation for `A << A`
   --> $DIR/issue-28837.rs:20:7
@@ -144,11 +123,8 @@ note: an implementation of `Shl<_>` might be missing for `A`
    |
 LL | struct A;
    | ^^^^^^^^ must implement `Shl<_>`
-note: the following trait must be implemented
+note: the trait `Shl` must be implemented
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL | pub trait Shl<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0369]: no implementation for `A >> A`
   --> $DIR/issue-28837.rs:22:7
@@ -163,11 +139,8 @@ note: an implementation of `Shr<_>` might be missing for `A`
    |
 LL | struct A;
    | ^^^^^^^^ must implement `Shr<_>`
-note: the following trait must be implemented
+note: the trait `Shr` must be implemented
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL | pub trait Shr<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0369]: binary operation `==` cannot be applied to type `A`
   --> $DIR/issue-28837.rs:24:7
index f21f890691120cdd4e50c07fda0f9324e52aa4d5..c313ed6037f3ab043aef865989ef6725449c7fb7 100644 (file)
@@ -11,11 +11,8 @@ note: an implementation of `Mul<_>` might be missing for `Thing`
    |
 LL | struct Thing {
    | ^^^^^^^^^^^^ must implement `Mul<_>`
-note: the following trait must be implemented
+note: the trait `Mul` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait Mul<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 13a6277da14c0898b95ab55ef527e3b4fe8fa72e..abee72ba8cf97cb1ed9d5ca73462a894368d393b 100644 (file)
@@ -3,10 +3,15 @@ error[E0507]: cannot move out of `s` which is behind a shared reference
    |
 LL |         match *s { S(v) => v }
    |               ^^     -
-   |               |      |
-   |               |      data moved here
-   |               |      move occurs because `v` has type `Vec<isize>`, which does not implement the `Copy` trait
-   |               help: consider borrowing here: `&*s`
+   |                      |
+   |                      data moved here
+   |                      move occurs because `v` has type `Vec<isize>`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -         match *s { S(v) => v }
+LL +         match s { S(v) => v }
+   |
 
 error: aborting due to previous error
 
index 2eabc1f1d9df5844218a35a4640b537ea1e52136..f9ced03e0f038fd86afc5020f3c737349a99727b 100644 (file)
@@ -2,31 +2,46 @@ error[E0507]: cannot move out of a shared reference
   --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:12:15
    |
 LL |     for &a in x.iter() {
-   |         --    ^^^^^^^^
-   |         ||
-   |         |data moved here
-   |         |move occurs because `a` has type `&mut i32`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `a`
+   |          -    ^^^^^^^^
+   |          |
+   |          data moved here
+   |          move occurs because `a` has type `&mut i32`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     for &a in x.iter() {
+LL +     for a in x.iter() {
+   |
 
 error[E0507]: cannot move out of a shared reference
   --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:18:15
    |
 LL |     for &a in &f.a {
-   |         --    ^^^^
-   |         ||
-   |         |data moved here
-   |         |move occurs because `a` has type `Box<isize>`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `a`
+   |          -    ^^^^
+   |          |
+   |          data moved here
+   |          move occurs because `a` has type `Box<isize>`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     for &a in &f.a {
+LL +     for a in &f.a {
+   |
 
 error[E0507]: cannot move out of a shared reference
   --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:22:15
    |
 LL |     for &a in x.iter() {
-   |         --    ^^^^^^^^
-   |         ||
-   |         |data moved here
-   |         |move occurs because `a` has type `Box<i32>`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `a`
+   |          -    ^^^^^^^^
+   |          |
+   |          data moved here
+   |          move occurs because `a` has type `Box<i32>`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     for &a in x.iter() {
+LL +     for a in x.iter() {
+   |
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-issue-2657-2.fixed b/src/test/ui/borrowck/borrowck-issue-2657-2.fixed
new file mode 100644 (file)
index 0000000..625e7c3
--- /dev/null
@@ -0,0 +1,12 @@
+// run-rustfix
+fn main() {
+
+    let x: Option<Box<_>> = Some(Box::new(1));
+
+    match x {
+      Some(ref y) => {
+        let _b = y; //~ ERROR cannot move out
+      }
+      _ => {}
+    }
+}
index 7dbac02154a6e29bddf4ad389f38a403b7bf25b8..f79a846e70e7bcc9448267766c5050853ab43e20 100644 (file)
@@ -1,3 +1,4 @@
+// run-rustfix
 fn main() {
 
     let x: Option<Box<_>> = Some(Box::new(1));
index f9ba2ca416bdde0fe40b542b914bb91b155a8480..850bb9ae3930c87c80ed595f8e22ae5789262c9f 100644 (file)
@@ -1,11 +1,14 @@
 error[E0507]: cannot move out of `*y` which is behind a shared reference
-  --> $DIR/borrowck-issue-2657-2.rs:7:18
+  --> $DIR/borrowck-issue-2657-2.rs:8:18
    |
 LL |         let _b = *y;
-   |                  ^^
-   |                  |
-   |                  move occurs because `*y` has type `Box<i32>`, which does not implement the `Copy` trait
-   |                  help: consider borrowing here: `&*y`
+   |                  ^^ move occurs because `*y` has type `Box<i32>`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -         let _b = *y;
+LL +         let _b = y;
+   |
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-move-error-with-note.fixed b/src/test/ui/borrowck/borrowck-move-error-with-note.fixed
new file mode 100644 (file)
index 0000000..cf6c382
--- /dev/null
@@ -0,0 +1,56 @@
+// run-rustfix
+#![allow(unused)]
+enum Foo {
+    Foo1(Box<u32>, Box<u32>),
+    Foo2(Box<u32>),
+    Foo3,
+}
+
+
+
+fn blah() {
+    let f = &Foo::Foo1(Box::new(1), Box::new(2));
+    match f { //~ ERROR cannot move out of
+        Foo::Foo1(num1,
+                  num2) => (),
+        Foo::Foo2(num) => (),
+        Foo::Foo3 => ()
+    }
+}
+
+struct S {
+    f: String,
+    g: String
+}
+impl Drop for S {
+    fn drop(&mut self) { println!("{}", self.f); }
+}
+
+fn move_in_match() {
+    match (S {f: "foo".to_string(), g: "bar".to_string()}) {
+        //~^ ERROR cannot move out of type `S`, which implements the `Drop` trait
+        S {
+            f: ref _s,
+            g: ref _t
+        } => {}
+    }
+}
+
+// from issue-8064
+struct A {
+    a: Box<isize>,
+}
+
+fn free<T>(_: T) {}
+
+fn blah2() {
+    let a = &A { a: Box::new(1) };
+    match &a.a { //~ ERROR cannot move out of
+        n => {
+            free(n)
+        }
+    }
+    free(a)
+}
+
+fn main() {}
index ef38cbb63a5e3455cb31328eaa43ba5eb3ee5af2..f336ac4f994fa6990d648c9a9fa5a8303a020102 100644 (file)
@@ -1,3 +1,5 @@
+// run-rustfix
+#![allow(unused)]
 enum Foo {
     Foo1(Box<u32>, Box<u32>),
     Foo2(Box<u32>),
index 96246d9ae1a8909ce949a36ce288f00f3821828b..722c2c1443a7fd6d4a74d04f1920b44f1052c79c 100644 (file)
@@ -1,8 +1,8 @@
 error[E0507]: cannot move out of `f` as enum variant `Foo1` which is behind a shared reference
-  --> $DIR/borrowck-move-error-with-note.rs:11:11
+  --> $DIR/borrowck-move-error-with-note.rs:13:11
    |
 LL |     match *f {
-   |           ^^ help: consider borrowing here: `&*f`
+   |           ^^
 LL |         Foo::Foo1(num1,
    |                   ---- data moved here
 LL |                   num2) => (),
@@ -11,9 +11,14 @@ LL |         Foo::Foo2(num) => (),
    |                   --- ...and here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the dereference here
+   |
+LL -     match *f {
+LL +     match f {
+   |
 
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
-  --> $DIR/borrowck-move-error-with-note.rs:28:11
+  --> $DIR/borrowck-move-error-with-note.rs:30:11
    |
 LL |     match (S {f: "foo".to_string(), g: "bar".to_string()}) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
@@ -24,17 +29,30 @@ LL |             g: _t
    |                -- ...and here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider borrowing the pattern binding
+   |
+LL |             f: ref _s,
+   |                +++
+help: consider borrowing the pattern binding
+   |
+LL |             g: ref _t
+   |                +++
 
 error[E0507]: cannot move out of `a.a` which is behind a shared reference
-  --> $DIR/borrowck-move-error-with-note.rs:46:11
+  --> $DIR/borrowck-move-error-with-note.rs:48:11
    |
 LL |     match a.a {
-   |           ^^^ help: consider borrowing here: `&a.a`
+   |           ^^^
 LL |         n => {
    |         -
    |         |
    |         data moved here
    |         move occurs because `n` has type `Box<isize>`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     match &a.a {
+   |           +
 
 error: aborting due to 3 previous errors
 
index 7ac095e808a85a9537696b0e7834b6ca63bd1071..43fc102bd6256c90ea6a650670e487b1e0c49b60 100644 (file)
@@ -2,10 +2,13 @@ error[E0507]: cannot move out of `*x` which is behind a raw pointer
   --> $DIR/borrowck-move-from-unsafe-ptr.rs:2:13
    |
 LL |     let y = *x;
-   |             ^^
-   |             |
-   |             move occurs because `*x` has type `Box<isize>`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&*x`
+   |             ^^ move occurs because `*x` has type `Box<isize>`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let y = *x;
+LL +     let y = x;
+   |
 
 error: aborting due to previous error
 
index 6b19f9d977efab0f887398bc4a98e1e8e44a3342..21bd073321b8374dff41d9e842a537a21ec33fbb 100644 (file)
@@ -3,30 +3,45 @@ error[E0507]: cannot move out of a shared reference
    |
 LL | fn arg_item(&_x: &String) {}
    |             ^--
-   |             ||
-   |             |data moved here
-   |             |move occurs because `_x` has type `String`, which does not implement the `Copy` trait
-   |             help: consider removing the `&`: `_x`
+   |              |
+   |              data moved here
+   |              move occurs because `_x` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL - fn arg_item(&_x: &String) {}
+LL + fn arg_item(_x: &String) {}
+   |
 
 error[E0507]: cannot move out of a shared reference
   --> $DIR/borrowck-move-in-irrefut-pat.rs:7:11
    |
 LL |     with(|&_x| ())
    |           ^--
-   |           ||
-   |           |data moved here
-   |           |move occurs because `_x` has type `String`, which does not implement the `Copy` trait
-   |           help: consider removing the `&`: `_x`
+   |            |
+   |            data moved here
+   |            move occurs because `_x` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     with(|&_x| ())
+LL +     with(|_x| ())
+   |
 
 error[E0507]: cannot move out of a shared reference
   --> $DIR/borrowck-move-in-irrefut-pat.rs:12:15
    |
 LL |     let &_x = &"hi".to_string();
-   |         ---   ^^^^^^^^^^^^^^^^^
-   |         ||
-   |         |data moved here
-   |         |move occurs because `_x` has type `String`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `_x`
+   |          --   ^^^^^^^^^^^^^^^^^
+   |          |
+   |          data moved here
+   |          move occurs because `_x` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     let &_x = &"hi".to_string();
+LL +     let _x = &"hi".to_string();
+   |
 
 error: aborting due to 3 previous errors
 
index 800f30b34e58921dd71977b9d9c753562928429a..ecf5382e863e00336d9ec449722a272f8044d628 100644 (file)
@@ -7,11 +7,8 @@ LL |     let _x = Rc::new(vec![1, 2]).into_iter();
    |              |                   value moved due to this method call
    |              move occurs because value has type `Vec<i32>`, which does not implement the `Copy` trait
    |
-note: this function takes ownership of the receiver `self`, which moves value
+note: `into_iter` takes ownership of the receiver `self`, which moves value
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 
 error: aborting due to previous error
 
index 68994c2071bef2abcea6de94504e2b25e64e6933..599fa1e88dfecdd4dfd882aa6a31f94091c48ed6 100644 (file)
@@ -2,10 +2,13 @@ error[E0507]: cannot move out of an `Rc`
   --> $DIR/borrowck-move-out-of-overloaded-deref.rs:4:14
    |
 LL |     let _x = *Rc::new("hi".to_string());
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |              |
-   |              move occurs because value has type `String`, which does not implement the `Copy` trait
-   |              help: consider borrowing here: `&*Rc::new("hi".to_string())`
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ move occurs because value has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let _x = *Rc::new("hi".to_string());
+LL +     let _x = Rc::new("hi".to_string());
+   |
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.fixed b/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.fixed
new file mode 100644 (file)
index 0000000..c463c65
--- /dev/null
@@ -0,0 +1,24 @@
+// run-rustfix
+#![allow(unused)]
+struct S {f:String}
+impl Drop for S {
+    fn drop(&mut self) { println!("{}", self.f); }
+}
+
+fn move_in_match() {
+    match (S {f:"foo".to_string()}) {
+        //~^ ERROR [E0509]
+        S {f:ref _s} => {}
+    }
+}
+
+fn move_in_let() {
+    let S {f:ref _s} = S {f:"foo".to_string()};
+    //~^ ERROR [E0509]
+}
+
+fn move_in_fn_arg(S {f:ref _s}: S) {
+    //~^ ERROR [E0509]
+}
+
+fn main() {}
index a429f4bc33b066ec22fba29668ff94f9a8b338ef..93183062d61b319ac075ee4249d6c8d291f47899 100644 (file)
@@ -1,3 +1,5 @@
+// run-rustfix
+#![allow(unused)]
 struct S {f:String}
 impl Drop for S {
     fn drop(&mut self) { println!("{}", self.f); }
index 7b00ac9f1c3a6c5fa7cd9f2f375a1e5c03f26ec3..58f706c65ff281fc78101fac28e4812d7a084877 100644 (file)
@@ -1,5 +1,5 @@
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
-  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:7:11
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:9:11
    |
 LL |     match (S {f:"foo".to_string()}) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
@@ -9,18 +9,28 @@ LL |         S {f:_s} => {}
    |              |
    |              data moved here
    |              move occurs because `_s` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         S {f:ref _s} => {}
+   |              +++
 
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
-  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:14:20
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:16:20
    |
 LL |     let S {f:_s} = S {f:"foo".to_string()};
    |              --    ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
    |              |
    |              data moved here
    |              move occurs because `_s` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     let S {f:ref _s} = S {f:"foo".to_string()};
+   |              +++
 
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
-  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:18:19
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:20:19
    |
 LL | fn move_in_fn_arg(S {f:_s}: S) {
    |                   ^^^^^--^
@@ -28,6 +38,11 @@ LL | fn move_in_fn_arg(S {f:_s}: S) {
    |                   |    data moved here
    |                   |    move occurs because `_s` has type `String`, which does not implement the `Copy` trait
    |                   cannot move out of here
+   |
+help: consider borrowing the pattern binding
+   |
+LL | fn move_in_fn_arg(S {f:ref _s}: S) {
+   |                        +++
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.fixed b/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.fixed
new file mode 100644 (file)
index 0000000..bc2ddf8
--- /dev/null
@@ -0,0 +1,24 @@
+// run-rustfix
+#![allow(unused)]
+struct S(String);
+impl Drop for S {
+    fn drop(&mut self) { }
+}
+
+fn move_in_match() {
+    match S("foo".to_string()) {
+        //~^ ERROR cannot move out of type `S`, which implements the `Drop` trait
+        S(ref _s) => {}
+    }
+}
+
+fn move_in_let() {
+    let S(ref _s) = S("foo".to_string());
+    //~^ ERROR cannot move out of type `S`, which implements the `Drop` trait
+}
+
+fn move_in_fn_arg(S(ref _s): S) {
+    //~^ ERROR cannot move out of type `S`, which implements the `Drop` trait
+}
+
+fn main() {}
index 5bd32f82ebc447309fe7538a9834ce12a3cfbc54..f050bce87406799608f4e1db27e3c26f845ecc30 100644 (file)
@@ -1,3 +1,5 @@
+// run-rustfix
+#![allow(unused)]
 struct S(String);
 impl Drop for S {
     fn drop(&mut self) { }
index f00181b74689bb027c114c66ef02690e5f6b5c45..160a1f99f63f657c536ed8d63481af37d3246a42 100644 (file)
@@ -1,5 +1,5 @@
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
-  --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:7:11
+  --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:9:11
    |
 LL |     match S("foo".to_string()) {
    |           ^^^^^^^^^^^^^^^^^^^^ cannot move out of here
@@ -9,18 +9,28 @@ LL |         S(_s) => {}
    |           |
    |           data moved here
    |           move occurs because `_s` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         S(ref _s) => {}
+   |           +++
 
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
-  --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:14:17
+  --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:16:17
    |
 LL |     let S(_s) = S("foo".to_string());
    |           --    ^^^^^^^^^^^^^^^^^^^^ cannot move out of here
    |           |
    |           data moved here
    |           move occurs because `_s` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     let S(ref _s) = S("foo".to_string());
+   |           +++
 
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
-  --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:18:19
+  --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:20:19
    |
 LL | fn move_in_fn_arg(S(_s): S) {
    |                   ^^--^
@@ -28,6 +38,11 @@ LL | fn move_in_fn_arg(S(_s): S) {
    |                   | data moved here
    |                   | move occurs because `_s` has type `String`, which does not implement the `Copy` trait
    |                   cannot move out of here
+   |
+help: consider borrowing the pattern binding
+   |
+LL | fn move_in_fn_arg(S(ref _s): S) {
+   |                     +++
 
 error: aborting due to 3 previous errors
 
index a865812cb4a7c4708fc90d1354659f21fea9ffd6..9ff20a1f46a127ea3c5c6a970869eb53966d20f1 100644 (file)
@@ -10,10 +10,10 @@ LL |                   Foo { string: b }] => {
    |                                 - ...and here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
-help: consider removing the `&`
+help: consider removing the borrow
    |
-LL ~                 [Foo { string: a },
-LL ~                   Foo { string: b }] => {
+LL -                 &[Foo { string: a },
+LL +                 [Foo { string: a },
    |
 
 error: aborting due to previous error
index 2b4293b433e0190c8997f8179af9c1bbe67e5ba0..f5f4817e9bf3220f9a619064f3c8d75d5c766dc6 100644 (file)
@@ -2,10 +2,12 @@ error[E0507]: cannot move out of index of `MyVec<Box<i32>>`
   --> $DIR/borrowck-overloaded-index-move-from-vec.rs:20:15
    |
 LL |     let bad = v[0];
-   |               ^^^^
-   |               |
-   |               move occurs because value has type `Box<i32>`, which does not implement the `Copy` trait
-   |               help: consider borrowing here: `&v[0]`
+   |               ^^^^ move occurs because value has type `Box<i32>`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     let bad = &v[0];
+   |               +
 
 error: aborting due to previous error
 
index 8a9296c597828adb834b6cb0bebe93f6cfbb464f..0e9284a2cadd26cf48564328da88ebe070829077 100644 (file)
@@ -37,7 +37,7 @@ fn c() {
         &mut [_a,
         //~^ NOTE data moved here
         //~| NOTE move occurs because `_a` has type
-        //~| HELP consider removing the `&mut`
+        //~| HELP consider removing the mutable borrow
             ..
         ] => {
         }
@@ -56,7 +56,7 @@ fn d() {
         //~^ ERROR cannot move out
         //~| NOTE cannot move out
         &mut [
-        //~^ HELP consider removing the `&mut`
+        //~^ HELP consider removing the mutable borrow
          _b] => {}
         //~^ NOTE data moved here
         //~| NOTE move occurs because `_b` has type
@@ -79,7 +79,7 @@ fn e() {
         //~^ NOTE data moved here
         //~| NOTE and here
         //~| NOTE and here
-        //~| HELP consider removing the `&mut`
+        //~| HELP consider removing the mutable borrow
         _ => {}
     }
     let a = vec[0]; //~ ERROR cannot move out
index c3bcb7de65daa8fd07550695aaeaafae769f60a9..0dc5e64e4ff3022ee92075d07b49bd3c2134729e 100644 (file)
@@ -34,14 +34,10 @@ LL |         &mut [_a,
    |               data moved here
    |               move occurs because `_a` has type `Box<isize>`, which does not implement the `Copy` trait
    |
-help: consider removing the `&mut`
+help: consider removing the mutable borrow
    |
-LL ~         [_a,
-LL +
-LL +
-LL +
-LL +             ..
-LL ~         ] => {
+LL -         &mut [_a,
+LL +         [_a,
    |
 
 error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
@@ -52,7 +48,11 @@ LL |     let a = vec[0];
    |             |
    |             cannot move out of here
    |             move occurs because `vec[_]` has type `Box<isize>`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&vec[0]`
+   |
+help: consider borrowing here
+   |
+LL |     let a = &vec[0];
+   |             +
 
 error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
   --> $DIR/borrowck-vec-pattern-nesting.rs:55:11
@@ -66,11 +66,10 @@ LL |          _b] => {}
    |          data moved here
    |          move occurs because `_b` has type `Box<isize>`, which does not implement the `Copy` trait
    |
-help: consider removing the `&mut`
+help: consider removing the mutable borrow
    |
-LL ~         [
-LL +
-LL ~          _b] => {}
+LL -         &mut [
+LL +         [
    |
 
 error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
@@ -81,7 +80,11 @@ LL |     let a = vec[0];
    |             |
    |             cannot move out of here
    |             move occurs because `vec[_]` has type `Box<isize>`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&vec[0]`
+   |
+help: consider borrowing here
+   |
+LL |     let a = &vec[0];
+   |             +
 
 error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
   --> $DIR/borrowck-vec-pattern-nesting.rs:74:11
@@ -90,14 +93,17 @@ LL |     match vec {
    |           ^^^ cannot move out of here
 ...
 LL |         &mut [_a, _b, _c] => {}
-   |         -----------------
-   |         |     |   |   |
-   |         |     |   |   ...and here
-   |         |     |   ...and here
-   |         |     data moved here
-   |         help: consider removing the `&mut`: `[_a, _b, _c]`
+   |               --  --  -- ...and here
+   |               |   |
+   |               |   ...and here
+   |               data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+   |
+LL -         &mut [_a, _b, _c] => {}
+LL +         [_a, _b, _c] => {}
+   |
 
 error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
   --> $DIR/borrowck-vec-pattern-nesting.rs:85:13
@@ -107,7 +113,11 @@ LL |     let a = vec[0];
    |             |
    |             cannot move out of here
    |             move occurs because `vec[_]` has type `Box<isize>`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&vec[0]`
+   |
+help: consider borrowing here
+   |
+LL |     let a = &vec[0];
+   |             +
 
 error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/borrowck/issue-104639-lifetime-order.rs b/src/test/ui/borrowck/issue-104639-lifetime-order.rs
new file mode 100644 (file)
index 0000000..db1f8f8
--- /dev/null
@@ -0,0 +1,10 @@
+// edition:2018
+// check-pass
+
+#![allow(dead_code)]
+async fn fail<'a, 'b, 'c>(_: &'static str) where 'a: 'c, 'b: 'c, {}
+async fn pass<'a, 'c, 'b>(_: &'static str) where 'a: 'c, 'b: 'c, {}
+async fn pass2<'a, 'b, 'c>(_: &'static str) where 'a: 'c, 'b: 'c, 'c: 'a, {}
+async fn pass3<'a, 'b, 'c>(_: &'static str) where 'a: 'b, 'b: 'c, 'c: 'a, {}
+
+fn main() { }
index 984534bfb8b86cbe19adeef35ac5699d7343c72f..65aea5b1834b0dc750be678ea46c8216b05773f7 100644 (file)
@@ -2,10 +2,12 @@ error[E0507]: cannot move out of static item `FOO`
   --> $DIR/issue-17718-static-move.rs:6:14
    |
 LL |     let _a = FOO;
-   |              ^^^
-   |              |
-   |              move occurs because `FOO` has type `Foo`, which does not implement the `Copy` trait
-   |              help: consider borrowing here: `&FOO`
+   |              ^^^ move occurs because `FOO` has type `Foo`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     let _a = &FOO;
+   |              +
 
 error: aborting due to previous error
 
index d276231dc0c967103b894dff7784ed953f5daa48..215bf0100636949a6eda04a58eec81bdaab2dd8f 100644 (file)
@@ -2,37 +2,49 @@ error[E0507]: cannot move out of a mutable reference
   --> $DIR/issue-20801.rs:26:22
    |
 LL |     let a = unsafe { *mut_ref() };
-   |                      ^^^^^^^^^^
-   |                      |
-   |                      move occurs because value has type `T`, which does not implement the `Copy` trait
-   |                      help: consider borrowing here: `&*mut_ref()`
+   |                      ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let a = unsafe { *mut_ref() };
+LL +     let a = unsafe { mut_ref() };
+   |
 
 error[E0507]: cannot move out of a shared reference
   --> $DIR/issue-20801.rs:29:22
    |
 LL |     let b = unsafe { *imm_ref() };
-   |                      ^^^^^^^^^^
-   |                      |
-   |                      move occurs because value has type `T`, which does not implement the `Copy` trait
-   |                      help: consider borrowing here: `&*imm_ref()`
+   |                      ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let b = unsafe { *imm_ref() };
+LL +     let b = unsafe { imm_ref() };
+   |
 
 error[E0507]: cannot move out of a raw pointer
   --> $DIR/issue-20801.rs:32:22
    |
 LL |     let c = unsafe { *mut_ptr() };
-   |                      ^^^^^^^^^^
-   |                      |
-   |                      move occurs because value has type `T`, which does not implement the `Copy` trait
-   |                      help: consider borrowing here: `&*mut_ptr()`
+   |                      ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let c = unsafe { *mut_ptr() };
+LL +     let c = unsafe { mut_ptr() };
+   |
 
 error[E0507]: cannot move out of a raw pointer
   --> $DIR/issue-20801.rs:35:22
    |
 LL |     let d = unsafe { *const_ptr() };
-   |                      ^^^^^^^^^^^^
-   |                      |
-   |                      move occurs because value has type `T`, which does not implement the `Copy` trait
-   |                      help: consider borrowing here: `&*const_ptr()`
+   |                      ^^^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let d = unsafe { *const_ptr() };
+LL +     let d = unsafe { const_ptr() };
+   |
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/borrowck/issue-29166.rs b/src/test/ui/borrowck/issue-29166.rs
new file mode 100644 (file)
index 0000000..ca819ba
--- /dev/null
@@ -0,0 +1,21 @@
+// run-pass
+// This test ensures that vec.into_iter does not overconstrain element lifetime.
+
+pub fn main() {
+    original_report();
+    revision_1();
+    revision_2();
+}
+
+fn original_report() {
+    drop(vec![&()].into_iter())
+}
+
+fn revision_1() {
+    // below is what above `vec!` expands into at time of this writing.
+    drop(<[_]>::into_vec(::std::boxed::Box::new([&()])).into_iter())
+}
+
+fn revision_2() {
+    drop((match (Vec::new(), &()) { (mut v, b) => { v.push(b); v } }).into_iter())
+}
index eb41af1cea80d6b47aed6ff53d6141cde4f92899..8d4918867f75ec1d9bf0d1675fe904225b39aa4f 100644 (file)
@@ -2,10 +2,12 @@ error[E0507]: cannot move out of static item `X`
   --> $DIR/issue-47215-ice-from-drop-elab.rs:17:21
    |
 LL |         let mut x = X;
-   |                     ^
-   |                     |
-   |                     move occurs because `X` has type `AtomicUsize`, which does not implement the `Copy` trait
-   |                     help: consider borrowing here: `&X`
+   |                     ^ move occurs because `X` has type `AtomicUsize`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         let mut x = &X;
+   |                     +
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/issue-51301.rs b/src/test/ui/borrowck/issue-51301.rs
new file mode 100644 (file)
index 0000000..7e0a519
--- /dev/null
@@ -0,0 +1,35 @@
+use std::any::TypeId;
+use std::collections::HashMap;
+use std::hash::Hash;
+
+trait State {
+    type EventType;
+    fn get_type_id_of_state(&self) -> TypeId;
+}
+
+struct StateMachine<EventType: Hash + Eq> {
+    current_state: Box<dyn State<EventType = EventType>>,
+    transition_table:
+        HashMap<TypeId, HashMap<EventType, fn() -> Box<dyn State<EventType = EventType>>>>,
+}
+
+impl<EventType: Hash + Eq> StateMachine<EventType> {
+    fn inner_process_event(&mut self, event: EventType) -> Result<(), i8> {
+        let new_state_creation_function = self
+            .transition_table
+            .iter()
+            .find(|(&event_typeid, _)| event_typeid == self.current_state.get_type_id_of_state())
+            .ok_or(1)?
+            .1
+            .iter()
+            .find(|(&event_type, _)| event == event_type)
+            //~^ ERROR cannot move out of a shared reference
+            .ok_or(2)?
+            .1;
+
+        self.current_state = new_state_creation_function();
+        Ok(())
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/issue-51301.stderr b/src/test/ui/borrowck/issue-51301.stderr
new file mode 100644 (file)
index 0000000..6ec920c
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0507]: cannot move out of a shared reference
+  --> $DIR/issue-51301.rs:25:20
+   |
+LL |             .find(|(&event_type, _)| event == event_type)
+   |                    ^^----------^^^^
+   |                      |
+   |                      data moved here
+   |                      move occurs because `event_type` has type `EventType`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |             .find(|(&ref event_type, _)| event == event_type)
+   |                      +++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/issue-51415.fixed b/src/test/ui/borrowck/issue-51415.fixed
new file mode 100644 (file)
index 0000000..92943f6
--- /dev/null
@@ -0,0 +1,12 @@
+// run-rustfix
+// Regression test for #51415: match default bindings were failing to
+// see the "move out" implied by `&s` below.
+
+fn main() {
+    let a = vec![String::from("a")];
+    let opt = a.iter().enumerate().find(|(_, &ref s)| {
+        //~^ ERROR cannot move out
+        *s == String::from("d")
+    }).map(|(i, _)| i);
+    println!("{:?}", opt);
+}
index f031308fb7871ff4c2b6aa6a5bf20fb32fe8a23b..56ed57a61a0feeb252c3acc6d6bc38491fc78c18 100644 (file)
@@ -1,3 +1,4 @@
+// run-rustfix
 // Regression test for #51415: match default bindings were failing to
 // see the "move out" implied by `&s` below.
 
index a88819efcf7989f0fac0ff0c08358e223270ca71..0d486b45592b5d7f792dd3f9779c1afb78cc7c03 100644 (file)
@@ -1,11 +1,16 @@
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/issue-51415.rs:6:42
+  --> $DIR/issue-51415.rs:7:42
    |
 LL |     let opt = a.iter().enumerate().find(|(_, &s)| {
    |                                          ^^^^^-^
    |                                               |
    |                                               data moved here
    |                                               move occurs because `s` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     let opt = a.iter().enumerate().find(|(_, &ref s)| {
+   |                                               +++
 
 error: aborting due to previous error
 
index 1f9cbdb73425d3455acac1c24aa8dc57f59f94a2..99c63e4db50d3edbeff290d2a2a503b9b3f80cae 100644 (file)
@@ -2,10 +2,13 @@ error[E0507]: cannot move out of `*array` which is behind a shared reference
   --> $DIR/issue-54597-reject-move-out-of-borrow-via-pat.rs:14:13
    |
 LL |             *array
-   |             ^^^^^^
-   |             |
-   |             move occurs because `*array` has type `Vec<Value>`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&*array`
+   |             ^^^^^^ move occurs because `*array` has type `Vec<Value>`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -             *array
+LL +             array
+   |
 
 error: aborting due to previous error
 
index a4d5f212188d6bb978734f4a8d5b3de0fa3771ec..1b03bc3af9c72d8c4fbbc0d84141233aedf7b078 100644 (file)
@@ -1,15 +1,19 @@
 error[E0080]: evaluation of constant value failed
   --> $DIR/issue-81899.rs:11:5
    |
-LL | const _CONST: &[u8] = &f(&[], |_| {});
-   |                        -------------- inside `_CONST` at $DIR/issue-81899.rs:4:24
-...
+LL |     panic!()
+   |     ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/issue-81899.rs:11:5
+   |
+note: inside `f::<[closure@$DIR/issue-81899.rs:4:31: 4:34]>`
+  --> $DIR/issue-81899.rs:11:5
+   |
 LL |     panic!()
    |     ^^^^^^^^
-   |     |
-   |     the evaluated program panicked at 'explicit panic', $DIR/issue-81899.rs:11:5
-   |     inside `f::<[closure@$DIR/issue-81899.rs:4:31: 4:34]>` at $SRC_DIR/std/src/panic.rs:LL:COL
+note: inside `_CONST`
+  --> $DIR/issue-81899.rs:4:24
    |
+LL | const _CONST: &[u8] = &f(&[], |_| {});
+   |                        ^^^^^^^^^^^^^^
    = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: erroneous constant used
index 2552fff860cd369a94b66b767d80f63f8a27df7e..a585bff0c654395b8c208ca5c29ca9f5f7a70d2b 100644 (file)
@@ -27,11 +27,8 @@ LL |         foo = Some(Struct);
 LL |     let _y = foo;
    |              ^^^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `foo`
+note: `Option::<T>::unwrap` takes ownership of the receiver `self`, which moves `foo`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     pub const fn unwrap(self) -> T {
-   |                         ^^^^
 
 error[E0382]: use of moved value: `foo`
   --> $DIR/issue-83760.rs:37:14
@@ -55,11 +52,8 @@ LL |         foo = Some(Struct);
 LL |     } else if true {
 LL |         foo = Some(Struct);
    |         ^^^^^^^^^^^^^^^^^^
-note: this function takes ownership of the receiver `self`, which moves `foo`
+note: `Option::<T>::unwrap` takes ownership of the receiver `self`, which moves `foo`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     pub const fn unwrap(self) -> T {
-   |                         ^^^^
 
 error: aborting due to 3 previous errors
 
index 039575a8d79a5633b3e37c6f0273760a4289a8d8..afd141125ac7c9b3204ab714eab1e35244ef84bc 100644 (file)
@@ -8,10 +8,12 @@ LL |     take_mut(|| {
    |              -- captured by this `FnMut` closure
 LL |
 LL |         let _foo: String = val;
-   |                            ^^^
-   |                            |
-   |                            move occurs because `val` has type `String`, which does not implement the `Copy` trait
-   |                            help: consider borrowing here: `&val`
+   |                            ^^^ move occurs because `val` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         let _foo: String = &val;
+   |                            +
 
 error: aborting due to previous error
 
index b95ddc49c9964da69cab2d90c0c83124a1fe5f14..a5a571c6d4df09036758caf0ffe792cba65a8e02 100644 (file)
@@ -1,15 +1,19 @@
 error[E0080]: evaluation of constant value failed
   --> $DIR/issue-88434-minimal-example.rs:10:5
    |
-LL | const _CONST: &() = &f(&|_| {});
-   |                      ---------- inside `_CONST` at $DIR/issue-88434-minimal-example.rs:3:22
-...
+LL |     panic!()
+   |     ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/issue-88434-minimal-example.rs:10:5
+   |
+note: inside `f::<[closure@$DIR/issue-88434-minimal-example.rs:3:25: 3:28]>`
+  --> $DIR/issue-88434-minimal-example.rs:10:5
+   |
 LL |     panic!()
    |     ^^^^^^^^
-   |     |
-   |     the evaluated program panicked at 'explicit panic', $DIR/issue-88434-minimal-example.rs:10:5
-   |     inside `f::<[closure@$DIR/issue-88434-minimal-example.rs:3:25: 3:28]>` at $SRC_DIR/std/src/panic.rs:LL:COL
+note: inside `_CONST`
+  --> $DIR/issue-88434-minimal-example.rs:3:22
    |
+LL | const _CONST: &() = &f(&|_| {});
+   |                      ^^^^^^^^^^
    = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: erroneous constant used
index 604a6577639f458ff1db6ee86baf34b17e2a584e..00023c459a8e7228b6e5c4bcd3250debddb2c507 100644 (file)
@@ -1,15 +1,19 @@
 error[E0080]: evaluation of constant value failed
   --> $DIR/issue-88434-removal-index-should-be-less.rs:10:5
    |
-LL | const _CONST: &[u8] = &f(&[], |_| {});
-   |                        -------------- inside `_CONST` at $DIR/issue-88434-removal-index-should-be-less.rs:3:24
-...
+LL |     panic!()
+   |     ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/issue-88434-removal-index-should-be-less.rs:10:5
+   |
+note: inside `f::<[closure@$DIR/issue-88434-removal-index-should-be-less.rs:3:31: 3:34]>`
+  --> $DIR/issue-88434-removal-index-should-be-less.rs:10:5
+   |
 LL |     panic!()
    |     ^^^^^^^^
-   |     |
-   |     the evaluated program panicked at 'explicit panic', $DIR/issue-88434-removal-index-should-be-less.rs:10:5
-   |     inside `f::<[closure@$DIR/issue-88434-removal-index-should-be-less.rs:3:31: 3:34]>` at $SRC_DIR/std/src/panic.rs:LL:COL
+note: inside `_CONST`
+  --> $DIR/issue-88434-removal-index-should-be-less.rs:3:24
    |
+LL | const _CONST: &[u8] = &f(&[], |_| {});
+   |                        ^^^^^^^^^^^^^^
    = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: erroneous constant used
index 984981ce2ea14c85a11b8ed87c03850633082754..8ac711e9e59db806a8d128dd54bb999c60be2fe1 100644 (file)
@@ -2,10 +2,7 @@ error[E0507]: cannot move out of static item `D`
   --> $DIR/move-error-snippets-ext.rs:5:17
    |
 LL |         let a = $c;
-   |                 ^^
-   |                 |
-   |                 move occurs because `D` has type `A`, which does not implement the `Copy` trait
-   |                 help: consider borrowing here: `&$c`
+   |                 ^^ move occurs because `D` has type `A`, which does not implement the `Copy` trait
    |
   ::: $DIR/move-error-snippets.rs:21:1
    |
@@ -13,6 +10,10 @@ LL | sss!();
    | ------ in this macro invocation
    |
    = note: this error originates in the macro `aaa` which comes from the expansion of the macro `sss` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider borrowing here
+   |
+LL |         let a = &$c;
+   |                 +
 
 error: aborting due to previous error
 
index 13a2005e2ef4c40ef38abd3ee3034f7fb972f656..ecd916a59fcbd725da4a3d607e951a71377ff885 100644 (file)
@@ -9,11 +9,8 @@ LL |
 LL |     fill_segment(state);
    |                  ^^^^^ value borrowed here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `state`
+note: `into_iter` takes ownership of the receiver `self`, which moves `state`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 help: consider creating a fresh reborrow of `state` here
    |
 LL |     for _ in &mut *state {}
index b1af090aec2b03346a79cca26359c72d1dbece38..4621d8793514ac8dd2cf858dd6e1d424cd6c9eb8 100644 (file)
@@ -8,11 +8,8 @@ LL |     cb.map(|cb| cb());
    |     help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
    |     move occurs because `*cb` has type `Option<&mut dyn FnMut()>`, which does not implement the `Copy` trait
    |
-note: this function takes ownership of the receiver `self`, which moves `*cb`
+note: `Option::<T>::map` takes ownership of the receiver `self`, which moves `*cb`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     pub const fn map<U, F>(self, f: F) -> Option<U>
-   |                            ^^^^
 
 error[E0596]: cannot borrow `*cb` as mutable, as it is behind a `&` reference
   --> $DIR/suggest-as-ref-on-mut-closure.rs:12:26
index 0c151b097077ec0475c6669fedf1fa9c8ffec71f..b1367c652188bd8f4bafd95c2addf26ea843e94b 100644 (file)
@@ -10,11 +10,8 @@ LL |         y.into_iter();
    |         |
    |         move occurs because `y` has type `Vec<String>`, which does not implement the `Copy` trait
    |
-note: this function takes ownership of the receiver `self`, which moves `y`
+note: `into_iter` takes ownership of the receiver `self`, which moves `y`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 
 error: aborting due to previous error
 
index de654fdc1a4b5540125520e7825586a083a7f672..f102f666dc2769daf19207fafb13ed30af11cb3a 100644 (file)
@@ -9,9 +9,6 @@ LL |     let _ = Box::into_boxed_slice(boxed_slice);
    = help: the trait `Sized` is not implemented for `[u8]`
 note: required by a bound in `Box::<T, A>::into_boxed_slice`
   --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
-   |
-LL | impl<T, A: Allocator> Box<T, A> {
-   |      ^ required by this bound in `Box::<T, A>::into_boxed_slice`
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
   --> $DIR/into-boxed-slice-fail.rs:7:13
@@ -33,9 +30,6 @@ LL |     let _ = Box::into_boxed_slice(boxed_trait);
    = help: the trait `Sized` is not implemented for `dyn Debug`
 note: required by a bound in `Box::<T, A>::into_boxed_slice`
   --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
-   |
-LL | impl<T, A: Allocator> Box<T, A> {
-   |      ^ required by this bound in `Box::<T, A>::into_boxed_slice`
 
 error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time
   --> $DIR/into-boxed-slice-fail.rs:11:13
index d4c9f23164f8bcb1d55ec5e0fd19c8b2af78a703..f68d181291dd7f49456e8ae28eeaf9cbf445035b 100644 (file)
@@ -19,4 +19,11 @@ fn main() {
         &E::Foo => {}
         &E::Bar(ref identifier) => println!("{}", *identifier)
     };
+    if let &E::Bar(identifier) = &s.x { //~ ERROR cannot move
+        f(identifier.clone());
+    };
+    let &E::Bar(identifier) = &s.x else { //~ ERROR cannot move
+        return;
+    };
+    f(identifier.clone());
 }
index 0012f67cfa1cd02af3e7c1c8b9e802a0befd5cbc..203e37dc387c1526798c544ae1dec9e3c36b4963 100644 (file)
@@ -5,12 +5,47 @@ LL |     match &s.x {
    |           ^^^^
 LL |         &E::Foo => {}
 LL |         &E::Bar(identifier) => f(identifier.clone())
-   |         -------------------
-   |         |       |
-   |         |       data moved here
-   |         |       move occurs because `identifier` has type `String`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `E::Bar(identifier)`
+   |                 ----------
+   |                 |
+   |                 data moved here
+   |                 move occurs because `identifier` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -         &E::Bar(identifier) => f(identifier.clone())
+LL +         E::Bar(identifier) => f(identifier.clone())
+   |
+
+error[E0507]: cannot move out of a shared reference
+  --> $DIR/by-move-pattern-binding.rs:22:34
+   |
+LL |     if let &E::Bar(identifier) = &s.x {
+   |                    ----------    ^^^^
+   |                    |
+   |                    data moved here
+   |                    move occurs because `identifier` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     if let &E::Bar(identifier) = &s.x {
+LL +     if let E::Bar(identifier) = &s.x {
+   |
+
+error[E0507]: cannot move out of a shared reference
+  --> $DIR/by-move-pattern-binding.rs:25:31
+   |
+LL |     let &E::Bar(identifier) = &s.x else {
+   |                 ----------    ^^^^
+   |                 |
+   |                 data moved here
+   |                 move occurs because `identifier` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     let &E::Bar(identifier) = &s.x else {
+LL +     let E::Bar(identifier) = &s.x else {
+   |
 
-error: aborting due to previous error
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0507`.
index 075bd1fc488e6b50d6782335b526417cb728a3e2..d1f13d52362da8bf6f8e89045d4a432e497a42f5 100644 (file)
@@ -63,11 +63,9 @@ error[E0412]: cannot find type `F` in this scope
    |
 LL |     self , ... ,   self ,   self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
    |                                                ^
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   | -------------------------------------- similarly named trait `Fn` defined here
+   = note: similarly named trait `Fn` defined here
    |
 help: a trait with a similar name exists
    |
index 4804df133401b89ff13e53d2be426491469f223e..eda867f4159ff7d5f82f5a8f8050f904137cf01b 100644 (file)
@@ -14,9 +14,6 @@ LL | | }
    = note: [async fn body@$DIR/async.rs:7:29: 9:2] must be a future or must implement `IntoFuture` to be awaited
 note: required by a bound in `identity_future`
   --> $SRC_DIR/core/src/future/mod.rs:LL:COL
-   |
-LL | pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut {
-   |                                      ^^^^^^^^^^^^^^^^^^ required by this bound in `identity_future`
 
 error[E0277]: the size for values of type `<[async fn body@$DIR/async.rs:7:29: 9:2] as Future>::Output` cannot be known at compilation time
   --> $DIR/async.rs:7:29
@@ -30,9 +27,6 @@ LL | | }
    = help: the trait `Sized` is not implemented for `<[async fn body@$DIR/async.rs:7:29: 9:2] as Future>::Output`
 note: required by a bound in `identity_future`
   --> $SRC_DIR/core/src/future/mod.rs:LL:COL
-   |
-LL | pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut {
-   |                              ^ required by this bound in `identity_future`
 
 error[E0277]: `[async fn body@$DIR/async.rs:7:29: 9:2]` is not a future
   --> $DIR/async.rs:7:25
index 31939f7f6db5d9fd098d716a62bce8ebb6c8dee0..b13700a4ea5ba9fedaee2a266d22dc47b392e564 100644 (file)
@@ -58,10 +58,12 @@ error[E0507]: cannot move out of static item `x`
   --> $DIR/check-static-values-constraints.rs:110:45
    |
 LL |     let y = { static x: Box<isize> = box 3; x };
-   |                                             ^
-   |                                             |
-   |                                             move occurs because `x` has type `Box<isize>`, which does not implement the `Copy` trait
-   |                                             help: consider borrowing here: `&x`
+   |                                             ^ move occurs because `x` has type `Box<isize>`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     let y = { static x: Box<isize> = box 3; &x };
+   |                                             +
 
 error[E0010]: allocations are not allowed in statics
   --> $DIR/check-static-values-constraints.rs:110:38
index d5432755cfed3fd2981c31270e6effbfacd50fec..7a04ed7381e66d198123edeacbee33379f1eb7dc 100644 (file)
@@ -6,8 +6,8 @@ LL |     with_closure(|x: u32, y| {});
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |     with_closure(|x: u32, y: _| {});
-   |                            +++
+LL |     with_closure(|x: u32, y: /* Type */| {});
+   |                            ++++++++++++
 
 error: aborting due to previous error
 
index 7ffe3c1ef954ab6378d2c072698f6189be11a194..87a5d67a420c498c2a7926dfbaf6f4300eb83d5f 100644 (file)
@@ -10,9 +10,6 @@ LL |     let y = x.or_else(4);
    = note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }`
 note: required by a bound in `Option::<T>::or_else`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |         F: ~const FnOnce() -> Option<T>,
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Option::<T>::or_else`
 
 error: aborting due to previous error
 
index a2ca06b4e6e1aa7917d8a5a1864ea51d6238a08b..64e3b51ea713bf25e60f05b4ab0a9befcba53042 100644 (file)
@@ -19,9 +19,6 @@ LL |     let t = thread::spawn(|| {
    |                           ^^
 note: required by a bound in `spawn`
   --> $SRC_DIR/std/src/thread/mod.rs:LL:COL
-   |
-LL |     F: Send + 'static,
-   |        ^^^^ required by this bound in `spawn`
 
 error[E0277]: `Sender<()>` cannot be shared between threads safely
   --> $DIR/closure-move-sync.rs:18:19
@@ -40,9 +37,6 @@ LL |     thread::spawn(|| tx.send(()).unwrap());
    |                   ^^
 note: required by a bound in `spawn`
   --> $SRC_DIR/std/src/thread/mod.rs:LL:COL
-   |
-LL |     F: Send + 'static,
-   |        ^^^^ required by this bound in `spawn`
 
 error: aborting due to 2 previous errors
 
index b07425bd82501fff334063b0f1d6eb6433ff37ac..d4fc723fa8176c07eabcedbf0a8aaf54d9c4d98f 100644 (file)
@@ -19,7 +19,7 @@ note: required by a bound in `a::bar`
   --> $DIR/closure-return-type-must-be-sized.rs:14:19
    |
 LL |     pub fn bar<F: FnOnce() -> R, R: ?Sized>() {}
-   |                   ^^^^^^^^^^^^^ required by this bound in `a::bar`
+   |                   ^^^^^^^^^^^^^ required by this bound in `bar`
 
 error[E0277]: the size for values of type `dyn A` cannot be known at compilation time
   --> $DIR/closure-return-type-must-be-sized.rs:56:5
@@ -51,7 +51,7 @@ note: required by a bound in `b::bar`
   --> $DIR/closure-return-type-must-be-sized.rs:28:19
    |
 LL |     pub fn bar<F: Fn() -> R, R: ?Sized>() {}
-   |                   ^^^^^^^^^ required by this bound in `b::bar`
+   |                   ^^^^^^^^^ required by this bound in `bar`
 
 error[E0277]: the size for values of type `dyn A` cannot be known at compilation time
   --> $DIR/closure-return-type-must-be-sized.rs:63:5
@@ -83,7 +83,7 @@ note: required by a bound in `c::bar`
   --> $DIR/closure-return-type-must-be-sized.rs:42:19
    |
 LL |     pub fn bar<F: FnMut() -> R, R: ?Sized>() {}
-   |                   ^^^^^^^^^^^^ required by this bound in `c::bar`
+   |                   ^^^^^^^^^^^^ required by this bound in `bar`
 
 error[E0277]: the size for values of type `dyn A` cannot be known at compilation time
   --> $DIR/closure-return-type-must-be-sized.rs:70:5
index 6ce63e829b314f5faa831247a4021492c5b04ef6..449cd0b317757bfef4d48f71d1fd4e9d1a84fa6c 100644 (file)
@@ -10,9 +10,6 @@ LL |     let x: Option<&[u8]> = Some("foo").map(std::mem::transmute);
    = note: unsafe function cannot be called generically without an unsafe block
 note: required by a bound in `Option::<T>::map`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |         F: ~const FnOnce(T) -> U,
-   |            ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Option::<T>::map`
 
 error: aborting due to previous error
 
index 4c24a54bbbe014ddc03ee083e274aa58d97110de..9ba24c7a886958ab32b9d2ddfae01774d4438ea0 100644 (file)
@@ -12,8 +12,8 @@ LL |     [(); &(&'static: loop { |x| {}; }) as *const _ as usize]
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |     [(); &(&'static: loop { |x: _| {}; }) as *const _ as usize]
-   |                               +++
+LL |     [(); &(&'static: loop { |x: /* Type */| {}; }) as *const _ as usize]
+   |                               ++++++++++++
 
 error: aborting due to 2 previous errors
 
index da3f539a0071d27a651c8ab8d34c839dc69963cc..1e860d32b2a06ea523cfc0ec086cf25cf61c35d1 100644 (file)
@@ -9,11 +9,9 @@ error[E0412]: cannot find type `F` in this scope
    |
 LL |     _func: F,
    |            ^
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   | -------------------------------------- similarly named trait `Fn` defined here
+   = note: similarly named trait `Fn` defined here
    |
 help: a trait with a similar name exists
    |
index 0e788a16eb0411fffe661c2069146868aa732f0a..72337892734e6af3a29009053ff42133f6f92f51 100644 (file)
@@ -8,9 +8,6 @@ LL |     Ok(())
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^
 
 error[E0308]: mismatched types
   --> $DIR/issue-87461.rs:17:8
@@ -22,9 +19,6 @@ LL |     Ok(())
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^
 
 error[E0308]: mismatched types
   --> $DIR/issue-87461.rs:26:12
@@ -36,9 +30,6 @@ LL |         Ok(())
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^
 
 error: aborting due to 3 previous errors
 
index a482750fbd016bf61dcb0383277d3991a8b9d10f..4a578b4d7f536204cfc6ae09a79ab5338f82c55e 100644 (file)
@@ -3,11 +3,9 @@ error[E0412]: cannot find type `n` in this scope
    |
 LL |     type_ascribe!(2, n([u8; || 1]))
    |                      ^ help: a trait with a similar name exists: `Fn`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   | -------------------------------------- similarly named trait `Fn` defined here
+   = note: similarly named trait `Fn` defined here
 
 error[E0308]: mismatched types
   --> $DIR/issue-90871.rs:4:29
index eefc123fed7ac3ed07714d9666abfafc89141c6f..da26302c9d8a48219e8845a02c3820b764b95d4d 100644 (file)
@@ -2,8 +2,10 @@ error[E0631]: type mismatch in closure arguments
   --> $DIR/multiple-fn-bounds.rs:10:5
    |
 LL |     foo(move |x| v);
-   |     ^^^ -------- found signature defined here
-   |     |
+   |     ^^^ --------
+   |     |   |     |
+   |     |   |     help: do not borrow the argument: `char`
+   |     |   found signature defined here
    |     expected due to this
    |
    = note: expected closure signature `fn(char) -> _`
diff --git a/src/test/ui/codegen/issue-55976.rs b/src/test/ui/codegen/issue-55976.rs
new file mode 100644 (file)
index 0000000..3142704
--- /dev/null
@@ -0,0 +1,13 @@
+// run-pass
+// ^-- The above is needed as this issue is related to LLVM/codegen.
+// min-llvm-version:15.0.0
+// ^-- The above is needed as this issue is fixed by the opaque pointers.
+
+fn main() {
+    type_error(|x| &x);
+}
+
+fn type_error<T>(
+    _selector: for<'a> fn(&'a Vec<Box<dyn for<'b> Fn(&'b u8)>>) -> &'a Vec<Box<dyn Fn(T)>>,
+) {
+}
index 080f6c39449f040993ae98e851ad7fc8e5fbaeea..e0e369124a4be83557473cfd87160a5837647408 100644 (file)
@@ -9,11 +9,8 @@ LL |     {
 LL |         println!("{:?}", some_vec);
    |                          ^^^^^^^^ value borrowed here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `some_vec`
+note: `into_iter` takes ownership of the receiver `self`, which moves `some_vec`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
    = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider cloning the value if the performance cost is acceptable
    |
index d4bd673b84e1b70083273e08d5ccae0a4a4b36b8..d5b4349c00f6f090078578a84fefd5fffa3fb040 100644 (file)
@@ -14,7 +14,7 @@ error: `cfg` predicate is not specified
   --> $DIR/cfg-attr-syntax-validation.rs:7:1
    |
 LL | #[cfg()]
-   | ^^^^^^^^
+   | ^^^^^^^^ help: expected syntax is: `cfg(/* predicate */)`
 
 error: multiple `cfg` predicates are specified
   --> $DIR/cfg-attr-syntax-validation.rs:10:10
index 34debb6831734568330e7b6d8ccfaa32ae753e3f..3906d64c9462453682f8edf42d47332c5619b14f 100644 (file)
@@ -1,4 +1,4 @@
-error[E0599]: no method named `closure` found for reference `&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:45]>` in the current scope
+error[E0599]: no method named `closure` found for reference `&Obj<[closure@issue-33784.rs:25:43]>` in the current scope
   --> $DIR/issue-33784.rs:27:7
    |
 LL |     p.closure();
@@ -9,7 +9,7 @@ help: to call the function stored in `closure`, surround the field access with p
 LL |     (p.closure)();
    |     +         +
 
-error[E0599]: no method named `fn_ptr` found for reference `&&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:45]>` in the current scope
+error[E0599]: no method named `fn_ptr` found for reference `&&Obj<[closure@issue-33784.rs:25:43]>` in the current scope
   --> $DIR/issue-33784.rs:29:7
    |
 LL |     q.fn_ptr();
diff --git a/src/test/ui/const-generics/defaults/complex-unord-param.min.stderr b/src/test/ui/const-generics/defaults/complex-unord-param.min.stderr
deleted file mode 100644 (file)
index 8e8d26a..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: type parameters must be declared prior to const parameters
-  --> $DIR/complex-unord-param.rs:8:41
-   |
-LL | struct NestedArrays<'a, const N: usize, A: 'a, const M: usize, T:'a =u32> {
-   |                    ---------------------^----------------------^--------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, A: 'a, T: 'a = u32, const N: usize, const M: usize>`
-
-error: aborting due to previous error
-
index 688db695fa848cc4b7761acf444292bbe0fc2785..13ea4a295afd75dbc4ee43c746c528e9b6c4ea5b 100644 (file)
@@ -5,11 +5,14 @@ LL |     let y = Mask::<_, _>::splat(false);
    |         ^   ------------------- type must be known at this point
    |
    = note: cannot satisfy `_: MaskElement`
+   = help: the following types implement trait `MaskElement`:
+             i16
+             i32
+             i64
+             i8
+             isize
 note: required by a bound in `Mask::<T, LANES>::splat`
   --> $SRC_DIR/core/src/../../portable-simd/crates/core_simd/src/masks.rs:LL:COL
-   |
-LL |     T: MaskElement,
-   |        ^^^^^^^^^^^ required by this bound in `Mask::<T, LANES>::splat`
 help: consider giving `y` an explicit type, where the type for type parameter `T` is specified
    |
 LL |     let y: Mask<_, LANES> = Mask::<_, _>::splat(false);
index ada1050d35f35a3f6a26a78fab0127f7b456f2f6..cdf97bd88fd236cf10c097e75947f08356db71c3 100644 (file)
@@ -14,7 +14,7 @@ note: required by a bound in `use_trait_impl::assert_impl`
   --> $DIR/abstract-const-as-cast-3.rs:14:23
    |
 LL |     fn assert_impl<T: Trait>() {}
-   |                       ^^^^^ required by this bound in `use_trait_impl::assert_impl`
+   |                       ^^^^^ required by this bound in `assert_impl`
 
 error[E0308]: mismatched types
   --> $DIR/abstract-const-as-cast-3.rs:17:5
@@ -28,7 +28,7 @@ note: required by a bound in `use_trait_impl::assert_impl`
   --> $DIR/abstract-const-as-cast-3.rs:14:23
    |
 LL |     fn assert_impl<T: Trait>() {}
-   |                       ^^^^^ required by this bound in `use_trait_impl::assert_impl`
+   |                       ^^^^^ required by this bound in `assert_impl`
 
 error: unconstrained generic constant
   --> $DIR/abstract-const-as-cast-3.rs:20:19
@@ -46,7 +46,7 @@ note: required by a bound in `use_trait_impl::assert_impl`
   --> $DIR/abstract-const-as-cast-3.rs:14:23
    |
 LL |     fn assert_impl<T: Trait>() {}
-   |                       ^^^^^ required by this bound in `use_trait_impl::assert_impl`
+   |                       ^^^^^ required by this bound in `assert_impl`
 
 error[E0308]: mismatched types
   --> $DIR/abstract-const-as-cast-3.rs:20:5
@@ -60,7 +60,7 @@ note: required by a bound in `use_trait_impl::assert_impl`
   --> $DIR/abstract-const-as-cast-3.rs:14:23
    |
 LL |     fn assert_impl<T: Trait>() {}
-   |                       ^^^^^ required by this bound in `use_trait_impl::assert_impl`
+   |                       ^^^^^ required by this bound in `assert_impl`
 
 error[E0308]: mismatched types
   --> $DIR/abstract-const-as-cast-3.rs:23:5
@@ -74,7 +74,7 @@ note: required by a bound in `use_trait_impl::assert_impl`
   --> $DIR/abstract-const-as-cast-3.rs:14:23
    |
 LL |     fn assert_impl<T: Trait>() {}
-   |                       ^^^^^ required by this bound in `use_trait_impl::assert_impl`
+   |                       ^^^^^ required by this bound in `assert_impl`
 
 error[E0308]: mismatched types
   --> $DIR/abstract-const-as-cast-3.rs:25:5
@@ -88,7 +88,7 @@ note: required by a bound in `use_trait_impl::assert_impl`
   --> $DIR/abstract-const-as-cast-3.rs:14:23
    |
 LL |     fn assert_impl<T: Trait>() {}
-   |                       ^^^^^ required by this bound in `use_trait_impl::assert_impl`
+   |                       ^^^^^ required by this bound in `assert_impl`
 
 error: unconstrained generic constant
   --> $DIR/abstract-const-as-cast-3.rs:35:19
@@ -106,7 +106,7 @@ note: required by a bound in `use_trait_impl_2::assert_impl`
   --> $DIR/abstract-const-as-cast-3.rs:32:23
    |
 LL |     fn assert_impl<T: Trait>() {}
-   |                       ^^^^^ required by this bound in `use_trait_impl_2::assert_impl`
+   |                       ^^^^^ required by this bound in `assert_impl`
 
 error[E0308]: mismatched types
   --> $DIR/abstract-const-as-cast-3.rs:35:5
@@ -120,7 +120,7 @@ note: required by a bound in `use_trait_impl_2::assert_impl`
   --> $DIR/abstract-const-as-cast-3.rs:32:23
    |
 LL |     fn assert_impl<T: Trait>() {}
-   |                       ^^^^^ required by this bound in `use_trait_impl_2::assert_impl`
+   |                       ^^^^^ required by this bound in `assert_impl`
 
 error: unconstrained generic constant
   --> $DIR/abstract-const-as-cast-3.rs:38:19
@@ -138,7 +138,7 @@ note: required by a bound in `use_trait_impl_2::assert_impl`
   --> $DIR/abstract-const-as-cast-3.rs:32:23
    |
 LL |     fn assert_impl<T: Trait>() {}
-   |                       ^^^^^ required by this bound in `use_trait_impl_2::assert_impl`
+   |                       ^^^^^ required by this bound in `assert_impl`
 
 error[E0308]: mismatched types
   --> $DIR/abstract-const-as-cast-3.rs:38:5
@@ -152,7 +152,7 @@ note: required by a bound in `use_trait_impl_2::assert_impl`
   --> $DIR/abstract-const-as-cast-3.rs:32:23
    |
 LL |     fn assert_impl<T: Trait>() {}
-   |                       ^^^^^ required by this bound in `use_trait_impl_2::assert_impl`
+   |                       ^^^^^ required by this bound in `assert_impl`
 
 error[E0308]: mismatched types
   --> $DIR/abstract-const-as-cast-3.rs:41:5
@@ -166,7 +166,7 @@ note: required by a bound in `use_trait_impl_2::assert_impl`
   --> $DIR/abstract-const-as-cast-3.rs:32:23
    |
 LL |     fn assert_impl<T: Trait>() {}
-   |                       ^^^^^ required by this bound in `use_trait_impl_2::assert_impl`
+   |                       ^^^^^ required by this bound in `assert_impl`
 
 error[E0308]: mismatched types
   --> $DIR/abstract-const-as-cast-3.rs:43:5
@@ -180,7 +180,7 @@ note: required by a bound in `use_trait_impl_2::assert_impl`
   --> $DIR/abstract-const-as-cast-3.rs:32:23
    |
 LL |     fn assert_impl<T: Trait>() {}
-   |                       ^^^^^ required by this bound in `use_trait_impl_2::assert_impl`
+   |                       ^^^^^ required by this bound in `assert_impl`
 
 error: aborting due to 12 previous errors
 
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-105257.rs b/src/test/ui/const-generics/generic_const_exprs/issue-105257.rs
new file mode 100644 (file)
index 0000000..d8b23bc
--- /dev/null
@@ -0,0 +1,9 @@
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+trait Trait<T> {
+    fn fnc<const N: usize = "">(&self) {} //~ERROR defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+    fn foo<const N: usize = { std::mem::size_of::<T>() }>(&self) {} //~ERROR defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-105257.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-105257.stderr
new file mode 100644 (file)
index 0000000..ed7a8cb
--- /dev/null
@@ -0,0 +1,14 @@
+error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+  --> $DIR/issue-105257.rs:5:12
+   |
+LL |     fn fnc<const N: usize = "">(&self) {}
+   |            ^^^^^^^^^^^^^^^^^^^
+
+error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+  --> $DIR/issue-105257.rs:6:12
+   |
+LL |     fn foo<const N: usize = { std::mem::size_of::<T>() }>(&self) {}
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-105608.rs b/src/test/ui/const-generics/generic_const_exprs/issue-105608.rs
new file mode 100644 (file)
index 0000000..e28ba3b
--- /dev/null
@@ -0,0 +1,15 @@
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+struct Combination<const STRATEGIES: usize>;
+
+impl<const STRATEGIES: usize> Combination<STRATEGIES> {
+    fn and<M>(self) -> Combination<{ STRATEGIES + 1 }> {
+        Combination
+    }
+}
+
+pub fn main() {
+    Combination::<0>.and::<_>().and::<_>();
+    //~^ ERROR: type annotations needed
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-105608.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-105608.stderr
new file mode 100644 (file)
index 0000000..0be4c43
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-105608.rs:13:22
+   |
+LL |     Combination::<0>.and::<_>().and::<_>();
+   |                      ^^^ cannot infer type of the type parameter `M` declared on the associated function `and`
+   |
+help: consider specifying the generic argument
+   |
+LL |     Combination::<0>.and::<_>().and::<_>();
+   |                         ~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
index 4d0d0253f1b6d4a08206836089a6ee89fda0f6f6..0af5493f81675502ced616895b8f4bf9b1ccc503 100644 (file)
@@ -40,7 +40,17 @@ error[E0283]: type annotations needed: cannot satisfy `IsLessOrEqual<I, 8>: True
 LL |     IsLessOrEqual<I, 8>: True,
    |                          ^^^^
    |
-   = note: cannot satisfy `IsLessOrEqual<I, 8>: True`
+note: multiple `impl`s or `where` clauses satisfying `IsLessOrEqual<I, 8>: True` found
+  --> $DIR/issue-72787.rs:10:1
+   |
+LL | impl<const LHS: u32, const RHS: u32> True for IsLessOrEqual<LHS, RHS> where
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     IsLessOrEqual<I, 8>: True,
+   |                          ^^^^
+...
+LL |     IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
+   |                                          ^^^^
 
 error[E0283]: type annotations needed: cannot satisfy `IsLessOrEqual<I, 8>: True`
   --> $DIR/issue-72787.rs:21:26
@@ -48,7 +58,17 @@ error[E0283]: type annotations needed: cannot satisfy `IsLessOrEqual<I, 8>: True
 LL |     IsLessOrEqual<I, 8>: True,
    |                          ^^^^
    |
-   = note: cannot satisfy `IsLessOrEqual<I, 8>: True`
+note: multiple `impl`s or `where` clauses satisfying `IsLessOrEqual<I, 8>: True` found
+  --> $DIR/issue-72787.rs:10:1
+   |
+LL | impl<const LHS: u32, const RHS: u32> True for IsLessOrEqual<LHS, RHS> where
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     IsLessOrEqual<I, 8>: True,
+   |                          ^^^^
+...
+LL |     IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
+   |                                          ^^^^
 
 error: aborting due to 6 previous errors
 
index c90774e944f1f48d690099893a5025992b15054c..029528c3a8172772da0aa816061918b95613641e 100644 (file)
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/issue-79518-default_trait_method_normalization.rs:16:32
    |
 LL |         Self::AssocInstance == [(); std::mem::size_of::<Self::Assoc>()];
-   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found array `[(); _]`
+   |         -------------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found array `[(); _]`
+   |         |
+   |         expected because this is `<Self as Foo>::Assoc`
    |
    = note: expected associated type `<Self as Foo>::Assoc`
                         found array `[(); _]`
index 1b502642eb7d03f12f881017b5547aa13c8b51da..a08c9912527c732eb8de4b647310e3c2628d019d 100644 (file)
@@ -1,16 +1,15 @@
 error[E0080]: evaluation of `Inline::<dyn std::fmt::Debug>::{constant#0}` failed
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
    |
-LL |     intrinsics::size_of::<T>()
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |     |
-   |     size_of called on unsized type `dyn Debug`
-   |     inside `std::mem::size_of::<dyn Debug>` at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+   = note: size_of called on unsized type `dyn Debug`
    |
-  ::: $DIR/issue-80742.rs:22:10
+note: inside `std::mem::size_of::<dyn Debug>`
+  --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+note: inside `Inline::<dyn Debug>::{constant#0}`
+  --> $DIR/issue-80742.rs:22:10
    |
 LL |     [u8; size_of::<T>() + 1]: ,
-   |          -------------- inside `Inline::<dyn Debug>::{constant#0}` at $DIR/issue-80742.rs:22:10
+   |          ^^^^^^^^^^^^^^
 
 error[E0599]: the function or associated item `new` exists for struct `Inline<dyn Debug>`, but its trait bounds were not satisfied
   --> $DIR/issue-80742.rs:30:36
@@ -20,11 +19,9 @@ LL | struct Inline<T>
 ...
 LL |     let dst = Inline::<dyn Debug>::new(0);
    |                                    ^^^ function or associated item cannot be called on `Inline<dyn Debug>` due to unsatisfied trait bounds
+  --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-   |
-LL | pub trait Debug {
-   | --------------- doesn't satisfy `dyn Debug: Sized`
+   = note: doesn't satisfy `dyn Debug: Sized`
    |
    = note: the following trait bounds were not satisfied:
            `dyn Debug: Sized`
@@ -32,16 +29,15 @@ LL | pub trait Debug {
 error[E0080]: evaluation of `Inline::<dyn std::fmt::Debug>::{constant#0}` failed
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
    |
-LL |     intrinsics::size_of::<T>()
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |     |
-   |     size_of called on unsized type `dyn Debug`
-   |     inside `std::mem::size_of::<dyn Debug>` at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+   = note: size_of called on unsized type `dyn Debug`
    |
-  ::: $DIR/issue-80742.rs:14:10
+note: inside `std::mem::size_of::<dyn Debug>`
+  --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+note: inside `Inline::<dyn Debug>::{constant#0}`
+  --> $DIR/issue-80742.rs:14:10
    |
 LL |     [u8; size_of::<T>() + 1]: ,
-   |          -------------- inside `Inline::<dyn Debug>::{constant#0}` at $DIR/issue-80742.rs:14:10
+   |          ^^^^^^^^^^^^^^
 
 error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time
   --> $DIR/issue-80742.rs:30:15
diff --git a/src/test/ui/const-generics/generic_const_exprs/normed_to_param_is_evaluatable.rs b/src/test/ui/const-generics/generic_const_exprs/normed_to_param_is_evaluatable.rs
new file mode 100644 (file)
index 0000000..b37b354
--- /dev/null
@@ -0,0 +1,12 @@
+// check-pass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features, unused_braces)]
+
+#[rustfmt::skip]
+fn foo<const N: usize>() {
+    bar::<{{{{{{ N }}}}}}>();
+}
+
+fn bar<const N: usize>() {}
+
+fn main() {}
index d955b4f9651daa4906530e94bb19a0278ac331af..8c76ca6902962df686e03c185f2bd4c3f4ba9a6f 100644 (file)
@@ -4,11 +4,6 @@ error[E0107]: this associated function takes 0 generic arguments but 1 generic a
 LL |     let _: u32 = 5i32.try_into::<32>().unwrap();
    |                       ^^^^^^^^ expected 0 generic arguments
    |
-note: associated function defined here, with 0 generic parameters
-  --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
-   |
-LL |     fn try_into(self) -> Result<T, Self::Error>;
-   |        ^^^^^^^^
 help: consider moving this generic argument to the `TryInto` trait, which takes up to 1 argument
    |
 LL |     let _: u32 = TryInto::<32>::try_into(5i32).unwrap();
index 1400d2bf5a7ba64ff65b98d3bad000bb0fb93cab..993b63518e44cbb8b40f3c6c7138405475b6ab47 100644 (file)
@@ -5,12 +5,6 @@ LL |     let _: Cell<&str, "a"> = Cell::new("");
    |            ^^^^       --- help: remove this generic argument
    |            |
    |            expected 1 generic argument
-   |
-note: struct defined here, with 1 generic parameter: `T`
-  --> $SRC_DIR/core/src/cell.rs:LL:COL
-   |
-LL | pub struct Cell<T: ?Sized> {
-   |            ^^^^ -
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/issue-105689.rs b/src/test/ui/const-generics/issue-105689.rs
new file mode 100644 (file)
index 0000000..4237b3c
--- /dev/null
@@ -0,0 +1,14 @@
+// check-pass
+// edition:2021
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+#[allow(unused)]
+async fn foo<'a>() {
+    let _data = &mut [0u8; { 1 + 4 }];
+    bar().await
+}
+
+async fn bar() {}
+
+fn main() {}
index f3ce357c2bb8d9b8f221d0f9e436b36c4a9eb84e..d4b486376cac822ddf8dd2dc2f7825755b1773f1 100644 (file)
@@ -1,14 +1,19 @@
 error[E0080]: evaluation of constant value failed
   --> $DIR/issue-100313.rs:10:13
    |
+LL |             *(B as *const bool as *mut bool) = false;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ writing to alloc7 which is read-only
+   |
+note: inside `T::<&true>::set_false`
+  --> $DIR/issue-100313.rs:10:13
+   |
 LL |             *(B as *const bool as *mut bool) = false;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |             |
-   |             writing to alloc7 which is read-only
-   |             inside `T::<&true>::set_false` at $DIR/issue-100313.rs:10:13
-...
+note: inside `_`
+  --> $DIR/issue-100313.rs:18:5
+   |
 LL |     x.set_false();
-   |     ------------- inside `_` at $DIR/issue-100313.rs:18:5
+   |     ^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 362b8554b2fcb91617bc1a4c371c44753b4928a2..7491fdc8a693e413a79937c04443cdad93df9995 100644 (file)
@@ -6,8 +6,8 @@ LL |     let _ = foo([0; 1]);
    |
 help: consider giving this pattern a type
    |
-LL |     let _: _ = foo([0; 1]);
-   |          +++
+LL |     let _: /* Type */ = foo([0; 1]);
+   |          ++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/type-after-const-ok.min.stderr b/src/test/ui/const-generics/type-after-const-ok.min.stderr
deleted file mode 100644 (file)
index ad38754..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: type parameters must be declared prior to const parameters
-  --> $DIR/type-after-const-ok.rs:8:26
-   |
-LL | struct A<const N: usize, T>(T);
-   |         -----------------^- help: reorder the parameters: lifetimes, then types, then consts: `<T, const N: usize>`
-
-error: aborting due to previous error
-
index 8978ab436d07d9f54ff118893cc629a5169613a9..0079bb3aad6df5b72e8fb68ff9f1d7844c5a581b 100644 (file)
@@ -1,44 +1,41 @@
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
-   |         inside `std::slice::from_raw_parts::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   = note: dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
    |
-  ::: $DIR/forbidden_slices.rs:18:34
+note: inside `std::slice::from_raw_parts::<'_, u32>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `S0`
+  --> $DIR/forbidden_slices.rs:18:34
    |
 LL | pub static S0: &[u32] = unsafe { from_raw_parts(ptr::null(), 0) };
-   |                                  ------------------------------ inside `S0` at $DIR/forbidden_slices.rs:18:34
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
-   |         inside `std::slice::from_raw_parts::<'_, ()>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   = note: dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
    |
-  ::: $DIR/forbidden_slices.rs:19:33
+note: inside `std::slice::from_raw_parts::<'_, ()>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `S1`
+  --> $DIR/forbidden_slices.rs:19:33
    |
 LL | pub static S1: &[()] = unsafe { from_raw_parts(ptr::null(), 0) };
-   |                                 ------------------------------ inside `S1` at $DIR/forbidden_slices.rs:19:33
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         dereferencing pointer failed: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
-   |         inside `std::slice::from_raw_parts::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   = note: dereferencing pointer failed: allocN has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
    |
-  ::: $DIR/forbidden_slices.rs:22:34
+note: inside `std::slice::from_raw_parts::<'_, u32>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `S2`
+  --> $DIR/forbidden_slices.rs:22:34
    |
 LL | pub static S2: &[u32] = unsafe { from_raw_parts(&D0, 2) };
-   |                                  ---------------------- inside `S2` at $DIR/forbidden_slices.rs:22:34
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/forbidden_slices.rs:25:1
@@ -48,7 +45,7 @@ LL | pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) }
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾─ALLOC_ID─╼ 01 00 00 00                         │ ╾──╼....
+               ╾ALLOC_ID╼ 01 00 00 00                         │ ╾──╼....
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -60,7 +57,7 @@ LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, size
    = help: this code performed an operation that depends on the underlying bytes representing a pointer
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾─ALLOC_ID─╼ 04 00 00 00                         │ ╾──╼....
+               ╾ALLOC_ID╼ 04 00 00 00                         │ ╾──╼....
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -71,90 +68,78 @@ LL | pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾─ALLOC_ID─╼ 04 00 00 00                         │ ╾──╼....
+               ╾ALLOC_ID╼ 04 00 00 00                         │ ╾──╼....
            }
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/forbidden_slices.rs:32:1
    |
 LL | pub static S7: &[u16] = unsafe {
-   | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1)
+   | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[1]: encountered uninitialized bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾─A_ID+0x1─╼ 04 00 00 00                         │ ╾──╼....
+               ╾ALLOC_ID+0x2╼ 04 00 00 00                         │ ╾──╼....
            }
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         dereferencing pointer failed: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
-   |         inside `std::slice::from_raw_parts::<'_, u64>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   = note: dereferencing pointer failed: allocN has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
    |
-  ::: $DIR/forbidden_slices.rs:43:5
+note: inside `std::slice::from_raw_parts::<'_, u64>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `S8`
+  --> $DIR/forbidden_slices.rs:43:5
    |
 LL |     from_raw_parts(ptr, 1)
-   |     ---------------------- inside `S8` at $DIR/forbidden_slices.rs:43:5
+   |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
-   |                  inside `ptr::const_ptr::<impl *const u32>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-  ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   = note: out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
    |
-LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
-   |                                          ------------------------------ inside `from_ptr_range::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-  ::: $DIR/forbidden_slices.rs:46:34
+note: inside `ptr::const_ptr::<impl *const u32>::sub_ptr`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `from_ptr_range::<'_, u32>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `R0`
+  --> $DIR/forbidden_slices.rs:46:34
    |
 LL | pub static R0: &[u32] = unsafe { from_ptr_range(ptr::null()..ptr::null()) };
-   |                                  ---------------------------------------- inside `R0` at $DIR/forbidden_slices.rs:46:34
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         assert!(0 < pointee_size && pointee_size <= isize::MAX as usize);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         the evaluated program panicked at 'assertion failed: 0 < pointee_size && pointee_size <= isize::MAX as usize', $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |         inside `ptr::const_ptr::<impl *const ()>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-  ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   = note: the evaluated program panicked at 'assertion failed: 0 < pointee_size && pointee_size <= isize::MAX as usize', $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
-   |                                          ------------------------------ inside `from_ptr_range::<'_, ()>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-  ::: $DIR/forbidden_slices.rs:47:33
+note: inside `ptr::const_ptr::<impl *const ()>::sub_ptr`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `from_ptr_range::<'_, ()>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `R1`
+  --> $DIR/forbidden_slices.rs:47:33
    |
 LL | pub static R1: &[()] = unsafe { from_ptr_range(ptr::null()..ptr::null()) };
-   |                                 ---------------------------------------- inside `R1` at $DIR/forbidden_slices.rs:47:33
-   |
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  out-of-bounds pointer arithmetic: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
-   |                  inside `ptr::const_ptr::<impl *const u32>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-...
-LL |         unsafe { self.offset(count as isize) }
-   |                  --------------------------- inside `ptr::const_ptr::<impl *const u32>::add` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   = note: out-of-bounds pointer arithmetic: allocN has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
    |
-  ::: $DIR/forbidden_slices.rs:50:25
+note: inside `ptr::const_ptr::<impl *const u32>::offset`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u32>::add`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `R2`
+  --> $DIR/forbidden_slices.rs:50:25
    |
 LL |     from_ptr_range(ptr..ptr.add(2))
-   |                         ---------- inside `R2` at $DIR/forbidden_slices.rs:50:25
+   |                         ^^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/forbidden_slices.rs:52:1
@@ -164,7 +149,7 @@ LL | pub static R4: &[u8] = unsafe {
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               â\95¾ALLOC_IDâ\94\80â\95¼ 01 00 00 00                         â\94\82 â\95¾â\94\80â\94\80â\95¼....
+               ╾ALLOC_ID╼ 01 00 00 00                         │ ╾──╼....
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -176,7 +161,7 @@ LL | pub static R5: &[u8] = unsafe {
    = help: this code performed an operation that depends on the underlying bytes representing a pointer
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               â\95¾ALLOC_IDâ\94\80â\95¼ 04 00 00 00                         â\94\82 â\95¾â\94\80â\94\80â\95¼....
+               ╾ALLOC_ID╼ 04 00 00 00                         │ ╾──╼....
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -187,74 +172,68 @@ LL | pub static R6: &[bool] = unsafe {
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               â\95¾ALLOC_IDâ\94\80â\95¼ 04 00 00 00                         â\94\82 â\95¾â\94\80â\94\80â\95¼....
+               ╾ALLOC_ID╼ 04 00 00 00                         │ ╾──╼....
            }
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/forbidden_slices.rs:67:1
+error[E0080]: could not evaluate static initializer
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-LL | pub static R7: &[u16] = unsafe {
-   | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1)
+   = note: accessing memory with alignment 1, but alignment 2 is required
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾A_ID+0x1─╼ 04 00 00 00                         │ ╾──╼....
-           }
+note: inside `std::slice::from_raw_parts::<'_, u16>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `from_ptr_range::<'_, u16>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `R7`
+  --> $DIR/forbidden_slices.rs:69:5
+   |
+LL |     from_ptr_range(ptr..ptr.add(4))
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  out-of-bounds pointer arithmetic: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
-   |                  inside `ptr::const_ptr::<impl *const u64>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-...
-LL |         unsafe { self.offset(count as isize) }
-   |                  --------------------------- inside `ptr::const_ptr::<impl *const u64>::add` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   = note: out-of-bounds pointer arithmetic: allocN has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
    |
-  ::: $DIR/forbidden_slices.rs:74:25
+note: inside `ptr::const_ptr::<impl *const u64>::offset`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u64>::add`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `R8`
+  --> $DIR/forbidden_slices.rs:73:25
    |
 LL |     from_ptr_range(ptr..ptr.add(1))
-   |                         ---------- inside `R8` at $DIR/forbidden_slices.rs:74:25
+   |                         ^^^^^^^^^^
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  `ptr_offset_from_unsigned` called on pointers into different allocations
-   |                  inside `ptr::const_ptr::<impl *const u32>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   = note: `ptr_offset_from_unsigned` called on pointers into different allocations
    |
-  ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
-   |                                          ------------------------------ inside `from_ptr_range::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-  ::: $DIR/forbidden_slices.rs:79:34
+note: inside `ptr::const_ptr::<impl *const u32>::sub_ptr`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `from_ptr_range::<'_, u32>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `R9`
+  --> $DIR/forbidden_slices.rs:78:34
    |
 LL | pub static R9: &[u32] = unsafe { from_ptr_range(&D0..(&D0 as *const u32).add(1)) };
-   |                                  ----------------------------------------------- inside `R9` at $DIR/forbidden_slices.rs:79:34
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  `ptr_offset_from_unsigned` called on pointers into different allocations
-   |                  inside `ptr::const_ptr::<impl *const u32>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   = note: `ptr_offset_from_unsigned` called on pointers into different allocations
    |
-  ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
-   |                                          ------------------------------ inside `from_ptr_range::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-  ::: $DIR/forbidden_slices.rs:80:35
+note: inside `ptr::const_ptr::<impl *const u32>::sub_ptr`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `from_ptr_range::<'_, u32>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `R10`
+  --> $DIR/forbidden_slices.rs:79:35
    |
 LL | pub static R10: &[u32] = unsafe { from_ptr_range(&D0..&D0) };
-   |                                   ------------------------ inside `R10` at $DIR/forbidden_slices.rs:80:35
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 18 previous errors
 
index db42b7c98307d229d350b1fcf5dfbec79e38b628..f4f9fe69516a6a258a1abb022c7c35b5b135d37a 100644 (file)
@@ -1,44 +1,41 @@
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
-   |         inside `std::slice::from_raw_parts::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   = note: dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
    |
-  ::: $DIR/forbidden_slices.rs:18:34
+note: inside `std::slice::from_raw_parts::<'_, u32>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `S0`
+  --> $DIR/forbidden_slices.rs:18:34
    |
 LL | pub static S0: &[u32] = unsafe { from_raw_parts(ptr::null(), 0) };
-   |                                  ------------------------------ inside `S0` at $DIR/forbidden_slices.rs:18:34
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
-   |         inside `std::slice::from_raw_parts::<'_, ()>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   = note: dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
    |
-  ::: $DIR/forbidden_slices.rs:19:33
+note: inside `std::slice::from_raw_parts::<'_, ()>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `S1`
+  --> $DIR/forbidden_slices.rs:19:33
    |
 LL | pub static S1: &[()] = unsafe { from_raw_parts(ptr::null(), 0) };
-   |                                 ------------------------------ inside `S1` at $DIR/forbidden_slices.rs:19:33
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         dereferencing pointer failed: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
-   |         inside `std::slice::from_raw_parts::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   = note: dereferencing pointer failed: allocN has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
    |
-  ::: $DIR/forbidden_slices.rs:22:34
+note: inside `std::slice::from_raw_parts::<'_, u32>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `S2`
+  --> $DIR/forbidden_slices.rs:22:34
    |
 LL | pub static S2: &[u32] = unsafe { from_raw_parts(&D0, 2) };
-   |                                  ---------------------- inside `S2` at $DIR/forbidden_slices.rs:22:34
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/forbidden_slices.rs:25:1
@@ -48,7 +45,7 @@ LL | pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) }
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾───────ALLOC_ID───────╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -60,7 +57,7 @@ LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, size
    = help: this code performed an operation that depends on the underlying bytes representing a pointer
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾───────ALLOC_ID───────╼ 08 00 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ 08 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -71,90 +68,78 @@ LL | pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾───────ALLOC_ID───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/forbidden_slices.rs:32:1
    |
 LL | pub static S7: &[u16] = unsafe {
-   | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1)
+   | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[1]: encountered uninitialized bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾─────ALLOC_ID+0x1─────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID+0x2╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         dereferencing pointer failed: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
-   |         inside `std::slice::from_raw_parts::<'_, u64>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   = note: dereferencing pointer failed: allocN has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
    |
-  ::: $DIR/forbidden_slices.rs:43:5
+note: inside `std::slice::from_raw_parts::<'_, u64>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `S8`
+  --> $DIR/forbidden_slices.rs:43:5
    |
 LL |     from_raw_parts(ptr, 1)
-   |     ---------------------- inside `S8` at $DIR/forbidden_slices.rs:43:5
+   |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
-   |                  inside `ptr::const_ptr::<impl *const u32>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-  ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   = note: out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
    |
-LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
-   |                                          ------------------------------ inside `from_ptr_range::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-  ::: $DIR/forbidden_slices.rs:46:34
+note: inside `ptr::const_ptr::<impl *const u32>::sub_ptr`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `from_ptr_range::<'_, u32>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `R0`
+  --> $DIR/forbidden_slices.rs:46:34
    |
 LL | pub static R0: &[u32] = unsafe { from_ptr_range(ptr::null()..ptr::null()) };
-   |                                  ---------------------------------------- inside `R0` at $DIR/forbidden_slices.rs:46:34
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         assert!(0 < pointee_size && pointee_size <= isize::MAX as usize);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         the evaluated program panicked at 'assertion failed: 0 < pointee_size && pointee_size <= isize::MAX as usize', $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |         inside `ptr::const_ptr::<impl *const ()>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-  ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   = note: the evaluated program panicked at 'assertion failed: 0 < pointee_size && pointee_size <= isize::MAX as usize', $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
-   |                                          ------------------------------ inside `from_ptr_range::<'_, ()>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-  ::: $DIR/forbidden_slices.rs:47:33
+note: inside `ptr::const_ptr::<impl *const ()>::sub_ptr`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `from_ptr_range::<'_, ()>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `R1`
+  --> $DIR/forbidden_slices.rs:47:33
    |
 LL | pub static R1: &[()] = unsafe { from_ptr_range(ptr::null()..ptr::null()) };
-   |                                 ---------------------------------------- inside `R1` at $DIR/forbidden_slices.rs:47:33
-   |
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  out-of-bounds pointer arithmetic: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
-   |                  inside `ptr::const_ptr::<impl *const u32>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-...
-LL |         unsafe { self.offset(count as isize) }
-   |                  --------------------------- inside `ptr::const_ptr::<impl *const u32>::add` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   = note: out-of-bounds pointer arithmetic: allocN has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
    |
-  ::: $DIR/forbidden_slices.rs:50:25
+note: inside `ptr::const_ptr::<impl *const u32>::offset`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u32>::add`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `R2`
+  --> $DIR/forbidden_slices.rs:50:25
    |
 LL |     from_ptr_range(ptr..ptr.add(2))
-   |                         ---------- inside `R2` at $DIR/forbidden_slices.rs:50:25
+   |                         ^^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/forbidden_slices.rs:52:1
@@ -164,7 +149,7 @@ LL | pub static R4: &[u8] = unsafe {
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾──────ALLOC_ID───────╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -176,7 +161,7 @@ LL | pub static R5: &[u8] = unsafe {
    = help: this code performed an operation that depends on the underlying bytes representing a pointer
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾──────ALLOC_ID───────╼ 08 00 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ 08 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -187,74 +172,68 @@ LL | pub static R6: &[bool] = unsafe {
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾──────ALLOC_ID───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/forbidden_slices.rs:67:1
+error[E0080]: could not evaluate static initializer
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-LL | pub static R7: &[u16] = unsafe {
-   | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1)
+   = note: accessing memory with alignment 1, but alignment 2 is required
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾────ALLOC_ID+0x1─────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
-           }
+note: inside `std::slice::from_raw_parts::<'_, u16>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `from_ptr_range::<'_, u16>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `R7`
+  --> $DIR/forbidden_slices.rs:69:5
+   |
+LL |     from_ptr_range(ptr..ptr.add(4))
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  out-of-bounds pointer arithmetic: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
-   |                  inside `ptr::const_ptr::<impl *const u64>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-...
-LL |         unsafe { self.offset(count as isize) }
-   |                  --------------------------- inside `ptr::const_ptr::<impl *const u64>::add` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   = note: out-of-bounds pointer arithmetic: allocN has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
    |
-  ::: $DIR/forbidden_slices.rs:74:25
+note: inside `ptr::const_ptr::<impl *const u64>::offset`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u64>::add`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `R8`
+  --> $DIR/forbidden_slices.rs:73:25
    |
 LL |     from_ptr_range(ptr..ptr.add(1))
-   |                         ---------- inside `R8` at $DIR/forbidden_slices.rs:74:25
+   |                         ^^^^^^^^^^
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  `ptr_offset_from_unsigned` called on pointers into different allocations
-   |                  inside `ptr::const_ptr::<impl *const u32>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   = note: `ptr_offset_from_unsigned` called on pointers into different allocations
    |
-  ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
-   |                                          ------------------------------ inside `from_ptr_range::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-  ::: $DIR/forbidden_slices.rs:79:34
+note: inside `ptr::const_ptr::<impl *const u32>::sub_ptr`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `from_ptr_range::<'_, u32>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `R9`
+  --> $DIR/forbidden_slices.rs:78:34
    |
 LL | pub static R9: &[u32] = unsafe { from_ptr_range(&D0..(&D0 as *const u32).add(1)) };
-   |                                  ----------------------------------------------- inside `R9` at $DIR/forbidden_slices.rs:79:34
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  `ptr_offset_from_unsigned` called on pointers into different allocations
-   |                  inside `ptr::const_ptr::<impl *const u32>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   = note: `ptr_offset_from_unsigned` called on pointers into different allocations
    |
-  ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
-   |                                          ------------------------------ inside `from_ptr_range::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
-   |
-  ::: $DIR/forbidden_slices.rs:80:35
+note: inside `ptr::const_ptr::<impl *const u32>::sub_ptr`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `from_ptr_range::<'_, u32>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `R10`
+  --> $DIR/forbidden_slices.rs:79:35
    |
 LL | pub static R10: &[u32] = unsafe { from_ptr_range(&D0..&D0) };
-   |                                   ------------------------ inside `R10` at $DIR/forbidden_slices.rs:80:35
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 18 previous errors
 
index e2184911f422c47cfe2318fd641c688e7d4cc90a..cc6100226dc1c00794ec90bbaf9524e9489f5f88 100644 (file)
@@ -1,6 +1,6 @@
 // stderr-per-bitwidth
-// normalize-stderr-test "alloc[0-9]+" -> "ALLOC_ID"
-// normalize-stderr-test "a[0-9]+\+0x" -> "A_ID+0x"
+// normalize-stderr-test "╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼" -> "╾ALLOC_ID$2╼"
+// normalize-stderr-test "alloc\d+" -> "allocN"
 // error-pattern: could not evaluate static initializer
 #![feature(
     slice_from_ptr_range,
@@ -31,7 +31,7 @@
 // Reading padding is not ok
 pub static S7: &[u16] = unsafe {
     //~^ ERROR: it is undefined behavior to use this value
-    let ptr = (&D2 as *const Struct as *const u16).byte_add(1);
+    let ptr = (&D2 as *const Struct as *const u16).add(1);
 
     from_raw_parts(ptr, 4)
 };
     from_ptr_range(ptr..ptr.add(4))
 };
 pub static R7: &[u16] = unsafe {
-    //~^ ERROR: it is undefined behavior to use this value
     let ptr = (&D2 as *const Struct as *const u16).byte_add(1);
-    from_ptr_range(ptr..ptr.add(4))
+    from_ptr_range(ptr..ptr.add(4)) //~ inside `R7`
 };
 pub static R8: &[u64] = unsafe {
     let ptr = (&D4 as *const [u32; 2] as *const u32).byte_add(1).cast::<u64>();
-    from_ptr_range(ptr..ptr.add(1))
+    from_ptr_range(ptr..ptr.add(1)) //~ inside `R8`
 };
 
 // This is sneaky: &D0 and &D0 point to different objects
index 52b173c4d04a8107dc522f71a8424386deb859db..3e7b09a5982d9597c17e44f7db08f5be6840dab9 100644 (file)
@@ -1,54 +1,45 @@
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
-LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
-   |         inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   = note: memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
    |
-  ::: $DIR/out_of_bounds_read.rs:12:33
+note: inside `std::ptr::read::<u32>`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `_READ`
+  --> $DIR/out_of_bounds_read.rs:12:33
    |
 LL |     const _READ: u32 = unsafe { ptr::read(PAST_END_PTR) };
-   |                                 ----------------------- inside `_READ` at $DIR/out_of_bounds_read.rs:12:33
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
-LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
-   |         inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-   |
-  ::: $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   = note: memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
    |
-LL |         unsafe { read(self) }
-   |                  ---------- inside `ptr::const_ptr::<impl *const u32>::read` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-  ::: $DIR/out_of_bounds_read.rs:13:39
+note: inside `std::ptr::read::<u32>`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u32>::read`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `_CONST_READ`
+  --> $DIR/out_of_bounds_read.rs:13:39
    |
 LL |     const _CONST_READ: u32 = unsafe { PAST_END_PTR.read() };
-   |                                       ------------------- inside `_CONST_READ` at $DIR/out_of_bounds_read.rs:13:39
+   |                                       ^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
-LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
-   |         inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   = note: memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
    |
-  ::: $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-   |
-LL |         unsafe { read(self) }
-   |                  ---------- inside `ptr::mut_ptr::<impl *mut u32>::read` at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-   |
-  ::: $DIR/out_of_bounds_read.rs:14:37
+note: inside `std::ptr::read::<u32>`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `ptr::mut_ptr::<impl *mut u32>::read`
+  --> $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+note: inside `_MUT_READ`
+  --> $DIR/out_of_bounds_read.rs:14:37
    |
 LL |     const _MUT_READ: u32 = unsafe { (PAST_END_PTR as *mut u32).read() };
-   |                                     --------------------------------- inside `_MUT_READ` at $DIR/out_of_bounds_read.rs:14:37
+   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
index 3784a3861c3deedc67a0c2346e1d5699d076e4ca..0734f479f9897b41a2190df93da3462fab41698e 100644 (file)
@@ -1,26 +1,36 @@
 error[E0080]: evaluation of constant value failed
   --> $DIR/const_fn_ptr_fail2.rs:9:5
    |
+LL |     x(y)
+   |     ^^^^ calling non-const function `double`
+   |
+note: inside `bar`
+  --> $DIR/const_fn_ptr_fail2.rs:9:5
+   |
 LL |     x(y)
    |     ^^^^
-   |     |
-   |     calling non-const function `double`
-   |     inside `bar` at $DIR/const_fn_ptr_fail2.rs:9:5
-...
+note: inside `Y`
+  --> $DIR/const_fn_ptr_fail2.rs:14:18
+   |
 LL | const Y: usize = bar(X, 2); // FIXME: should fail to typeck someday
-   |                  --------- inside `Y` at $DIR/const_fn_ptr_fail2.rs:14:18
+   |                  ^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/const_fn_ptr_fail2.rs:9:5
    |
+LL |     x(y)
+   |     ^^^^ calling non-const function `double`
+   |
+note: inside `bar`
+  --> $DIR/const_fn_ptr_fail2.rs:9:5
+   |
 LL |     x(y)
    |     ^^^^
-   |     |
-   |     calling non-const function `double`
-   |     inside `bar` at $DIR/const_fn_ptr_fail2.rs:9:5
-...
+note: inside `Z`
+  --> $DIR/const_fn_ptr_fail2.rs:15:18
+   |
 LL | const Z: usize = bar(double, 2); // FIXME: should fail to typeck someday
-   |                  -------------- inside `Z` at $DIR/const_fn_ptr_fail2.rs:15:18
+   |                  ^^^^^^^^^^^^^^
 
 warning: skipping const checks
    |
index 5c3b412d37fcc1752520abd7df779648c8e14705..846458176d6fd79fc1fb710ace41c55912adc867 100644 (file)
@@ -1,14 +1,19 @@
 error[E0080]: evaluation of constant value failed
   --> $DIR/const_panic_track_caller.rs:15:5
    |
+LL |     b()
+   |     ^^^ the evaluated program panicked at 'hey', $DIR/const_panic_track_caller.rs:15:5
+   |
+note: inside `c`
+  --> $DIR/const_panic_track_caller.rs:15:5
+   |
 LL |     b()
    |     ^^^
-   |     |
-   |     the evaluated program panicked at 'hey', $DIR/const_panic_track_caller.rs:15:5
-   |     inside `c` at $DIR/const_panic_track_caller.rs:15:5
-...
+note: inside `X`
+  --> $DIR/const_panic_track_caller.rs:21:16
+   |
 LL | const X: u32 = c();
-   |                --- inside `X` at $DIR/const_panic_track_caller.rs:21:16
+   |                ^^^
 
 error: aborting due to previous error
 
index 2628a78455c76b3f5a5f3100852c11807ecb8a26..8f3b3d5f700a22c037f5519126495dd722befa7d 100644 (file)
@@ -1,14 +1,19 @@
 error[E0080]: evaluation of constant value failed
   --> $DIR/alloc_intrinsic_errors.rs:9:17
    |
-LL | const FOO: i32 = foo();
-   |                  ----- inside `FOO` at $DIR/alloc_intrinsic_errors.rs:6:18
-...
+LL |         let _ = intrinsics::const_allocate(4, 3) as *mut i32;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ align has to be a power of 2, `3` is not a power of 2
+   |
+note: inside `foo`
+  --> $DIR/alloc_intrinsic_errors.rs:9:17
+   |
 LL |         let _ = intrinsics::const_allocate(4, 3) as *mut i32;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                 |
-   |                 align has to be a power of 2, `3` is not a power of 2
-   |                 inside `foo` at $DIR/alloc_intrinsic_errors.rs:9:17
+note: inside `FOO`
+  --> $DIR/alloc_intrinsic_errors.rs:6:18
+   |
+LL | const FOO: i32 = foo();
+   |                  ^^^^^
 
 error: aborting due to previous error
 
index e5b5c7a846c116f0cd6092036eed1473f323254c..a0a8d76d10d2d9b86e6fbd6733ddd3662f0b6026 100644 (file)
@@ -1,5 +1,5 @@
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:13:1
+  --> $DIR/ub-ref-ptr.rs:14:1
    |
 LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
    | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1)
@@ -10,7 +10,7 @@ LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:17:1
+  --> $DIR/ub-ref-ptr.rs:18:1
    |
 LL | const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned box (required 2 byte alignment but found 1)
@@ -21,7 +21,7 @@ LL | const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:21:1
+  --> $DIR/ub-ref-ptr.rs:22:1
    |
 LL | const NULL: &u16 = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null reference
@@ -32,7 +32,7 @@ LL | const NULL: &u16 = unsafe { mem::transmute(0usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:24:1
+  --> $DIR/ub-ref-ptr.rs:25:1
    |
 LL | const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null box
@@ -43,7 +43,7 @@ LL | const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) };
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-ref-ptr.rs:31:1
+  --> $DIR/ub-ref-ptr.rs:32:1
    |
 LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -52,7 +52,7 @@ LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-ref-ptr.rs:34:39
+  --> $DIR/ub-ref-ptr.rs:35:39
    |
 LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
    |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -61,13 +61,13 @@ LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 note: erroneous constant used
-  --> $DIR/ub-ref-ptr.rs:34:38
+  --> $DIR/ub-ref-ptr.rs:35:38
    |
 LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-ref-ptr.rs:37:86
+  --> $DIR/ub-ref-ptr.rs:38:86
    |
 LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
    |                                                                                      ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -76,13 +76,13 @@ LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[us
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 note: erroneous constant used
-  --> $DIR/ub-ref-ptr.rs:37:85
+  --> $DIR/ub-ref-ptr.rs:38:85
    |
 LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
    |                                                                                     ^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:40:1
+  --> $DIR/ub-ref-ptr.rs:41:1
    |
 LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (address 0x539 is unallocated)
@@ -93,7 +93,7 @@ LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:43:1
+  --> $DIR/ub-ref-ptr.rs:44:1
    |
 LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (address 0x539 is unallocated)
@@ -104,13 +104,13 @@ LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-ref-ptr.rs:46:41
+  --> $DIR/ub-ref-ptr.rs:47:41
    |
 LL | const UNINIT_PTR: *const i32 = unsafe { MaybeUninit { uninit: () }.init };
    |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:50:1
+  --> $DIR/ub-ref-ptr.rs:51:1
    |
 LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a function pointer
@@ -121,13 +121,13 @@ LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) };
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-ref-ptr.rs:52:38
+  --> $DIR/ub-ref-ptr.rs:53:38
    |
 LL | const UNINIT_FN_PTR: fn() = unsafe { MaybeUninit { uninit: () }.init };
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:55:1
+  --> $DIR/ub-ref-ptr.rs:56:1
    |
 LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0xd[noalloc], but expected a function pointer
@@ -138,7 +138,7 @@ LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:57:1
+  --> $DIR/ub-ref-ptr.rs:58:1
    |
 LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
    | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered alloc41, but expected a function pointer
@@ -148,6 +148,39 @@ LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
                ╾─alloc41─╼                                     │ ╾──╼
            }
 
-error: aborting due to 14 previous errors
+error: accessing memory with alignment 1, but alignment 4 is required
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #68585 <https://github.com/rust-lang/rust/issues/104616>
+note: inside `std::ptr::read::<u32>`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u32>::read`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `UNALIGNED_READ`
+  --> $DIR/ub-ref-ptr.rs:65:5
+   |
+LL |     ptr.read();
+   |     ^^^^^^^^^^
+   = note: `#[deny(invalid_alignment)]` on by default
+
+error: aborting due to 15 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+error: accessing memory with alignment 1, but alignment 4 is required
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #68585 <https://github.com/rust-lang/rust/issues/104616>
+note: inside `std::ptr::read::<u32>`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u32>::read`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `UNALIGNED_READ`
+  --> $DIR/ub-ref-ptr.rs:65:5
+   |
+LL |     ptr.read();
+   |     ^^^^^^^^^^
+   = note: `#[deny(invalid_alignment)]` on by default
+
index 607366cabc4e9d30c5a2ba70964fe4eb69854d61..d53b44671e3f48eb53a2c6f1c3a085cb95b92d7b 100644 (file)
@@ -1,5 +1,5 @@
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:13:1
+  --> $DIR/ub-ref-ptr.rs:14:1
    |
 LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
    | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1)
@@ -10,7 +10,7 @@ LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:17:1
+  --> $DIR/ub-ref-ptr.rs:18:1
    |
 LL | const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned box (required 2 byte alignment but found 1)
@@ -21,7 +21,7 @@ LL | const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:21:1
+  --> $DIR/ub-ref-ptr.rs:22:1
    |
 LL | const NULL: &u16 = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null reference
@@ -32,7 +32,7 @@ LL | const NULL: &u16 = unsafe { mem::transmute(0usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:24:1
+  --> $DIR/ub-ref-ptr.rs:25:1
    |
 LL | const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null box
@@ -43,7 +43,7 @@ LL | const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) };
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-ref-ptr.rs:31:1
+  --> $DIR/ub-ref-ptr.rs:32:1
    |
 LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -52,7 +52,7 @@ LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-ref-ptr.rs:34:39
+  --> $DIR/ub-ref-ptr.rs:35:39
    |
 LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
    |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -61,13 +61,13 @@ LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 note: erroneous constant used
-  --> $DIR/ub-ref-ptr.rs:34:38
+  --> $DIR/ub-ref-ptr.rs:35:38
    |
 LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-ref-ptr.rs:37:86
+  --> $DIR/ub-ref-ptr.rs:38:86
    |
 LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
    |                                                                                      ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -76,13 +76,13 @@ LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[us
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 note: erroneous constant used
-  --> $DIR/ub-ref-ptr.rs:37:85
+  --> $DIR/ub-ref-ptr.rs:38:85
    |
 LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
    |                                                                                     ^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:40:1
+  --> $DIR/ub-ref-ptr.rs:41:1
    |
 LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (address 0x539 is unallocated)
@@ -93,7 +93,7 @@ LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:43:1
+  --> $DIR/ub-ref-ptr.rs:44:1
    |
 LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (address 0x539 is unallocated)
@@ -104,13 +104,13 @@ LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-ref-ptr.rs:46:41
+  --> $DIR/ub-ref-ptr.rs:47:41
    |
 LL | const UNINIT_PTR: *const i32 = unsafe { MaybeUninit { uninit: () }.init };
    |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:50:1
+  --> $DIR/ub-ref-ptr.rs:51:1
    |
 LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a function pointer
@@ -121,13 +121,13 @@ LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) };
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-ref-ptr.rs:52:38
+  --> $DIR/ub-ref-ptr.rs:53:38
    |
 LL | const UNINIT_FN_PTR: fn() = unsafe { MaybeUninit { uninit: () }.init };
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:55:1
+  --> $DIR/ub-ref-ptr.rs:56:1
    |
 LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0xd[noalloc], but expected a function pointer
@@ -138,7 +138,7 @@ LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-ref-ptr.rs:57:1
+  --> $DIR/ub-ref-ptr.rs:58:1
    |
 LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
    | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered alloc41, but expected a function pointer
@@ -148,6 +148,39 @@ LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
                ╾───────alloc41───────╼                         │ ╾──────╼
            }
 
-error: aborting due to 14 previous errors
+error: accessing memory with alignment 1, but alignment 4 is required
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #68585 <https://github.com/rust-lang/rust/issues/104616>
+note: inside `std::ptr::read::<u32>`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u32>::read`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `UNALIGNED_READ`
+  --> $DIR/ub-ref-ptr.rs:65:5
+   |
+LL |     ptr.read();
+   |     ^^^^^^^^^^
+   = note: `#[deny(invalid_alignment)]` on by default
+
+error: aborting due to 15 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+error: accessing memory with alignment 1, but alignment 4 is required
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #68585 <https://github.com/rust-lang/rust/issues/104616>
+note: inside `std::ptr::read::<u32>`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u32>::read`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `UNALIGNED_READ`
+  --> $DIR/ub-ref-ptr.rs:65:5
+   |
+LL |     ptr.read();
+   |     ^^^^^^^^^^
+   = note: `#[deny(invalid_alignment)]` on by default
+
index a1c81239009ac0569e45d8217764ccf07ad9c81a..b0fc3c196a49fc3457915955dd277d352d6154c0 100644 (file)
@@ -1,6 +1,7 @@
 // ignore-tidy-linelength
 // stderr-per-bitwidth
 #![allow(invalid_value)]
+#![feature(const_ptr_read)]
 
 use std::mem;
 
@@ -57,4 +58,12 @@ union MaybeUninit<T: Copy> {
 const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
 //~^ ERROR it is undefined behavior to use this value
 
+
+const UNALIGNED_READ: () = unsafe {
+    let x = &[0u8; 4];
+    let ptr = x.as_ptr().cast::<u32>();
+    ptr.read(); //~ inside `UNALIGNED_READ`
+};
+
+
 fn main() {}
index 9994c2e5a83458c27cb6e3ad8ee66071eeabad14..90a3dcada058d691ec0dfee66edc0e1e87ad53da 100644 (file)
@@ -1,27 +1,27 @@
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:36:1
+  --> $DIR/ub-wide-ptr.rs:37:1
    |
 LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾─allocN──╼ e7 03 00 00                         │ ╾──╼....
+               ╾ALLOC_ID╼ e7 03 00 00                         │ ╾──╼....
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:38:1
+  --> $DIR/ub-wide-ptr.rs:39:1
    |
 LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid reference metadata: slice is bigger than largest supported object
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾─allocN─╼ ff ff ff ff                         │ ╾──╼....
+               ╾ALLOC_ID╼ ff ff ff ff                         │ ╾──╼....
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:41:1
+  --> $DIR/ub-wide-ptr.rs:42:1
    |
 LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -30,7 +30,7 @@ LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) };
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:44:1
+  --> $DIR/ub-wide-ptr.rs:45:1
    |
 LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -39,68 +39,68 @@ LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) };
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:46:1
+  --> $DIR/ub-wide-ptr.rs:47:1
    |
 LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾─allocN─╼ ff ff ff ff                         │ ╾──╼....
+               ╾ALLOC_ID╼ ff ff ff ff                         │ ╾──╼....
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:50:1
+  --> $DIR/ub-wide-ptr.rs:51:1
    |
 LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
    | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered uninitialized data in `str`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾─allocN─╼ 01 00 00 00                         │ ╾──╼....
+               ╾ALLOC_ID╼ 01 00 00 00                         │ ╾──╼....
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:53:1
+  --> $DIR/ub-wide-ptr.rs:54:1
    |
 LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered uninitialized data in `str`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾─allocN─╼ 01 00 00 00                         │ ╾──╼....
+               ╾ALLOC_ID╼ 01 00 00 00                         │ ╾──╼....
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:60:1
+  --> $DIR/ub-wide-ptr.rs:61:1
    |
 LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:67:1
+  --> $DIR/ub-wide-ptr.rs:68:1
    |
 LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾─allocN─╼ e7 03 00 00                         │ ╾──╼....
+               ╾ALLOC_ID╼ e7 03 00 00                         │ ╾──╼....
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:70:1
+  --> $DIR/ub-wide-ptr.rs:71:1
    |
 LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, isize::MAX)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾─allocN─╼ ff ff ff 7f                         │ ╾──╼....
+               ╾ALLOC_ID╼ ff ff ff 7f                         │ ╾──╼....
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:73:1
+  --> $DIR/ub-wide-ptr.rs:74:1
    |
 LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -109,18 +109,18 @@ LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:76:1
+  --> $DIR/ub-wide-ptr.rs:77:1
    |
 LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (going beyond the bounds of its allocation)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾─allocN─╼ e7 03 00 00                         │ ╾──╼....
+               ╾ALLOC_ID╼ e7 03 00 00                         │ ╾──╼....
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:79:1
+  --> $DIR/ub-wide-ptr.rs:80:1
    |
 LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -129,165 +129,165 @@ LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:83:1
+  --> $DIR/ub-wide-ptr.rs:84:1
    |
 LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x03, but expected a boolean
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
-               ╾─allocN─╼                                     │ ╾──╼
+               ╾ALLOC_ID╼                                     │ ╾──╼
            }
 
 note: erroneous constant used
-  --> $DIR/ub-wide-ptr.rs:83:40
+  --> $DIR/ub-wide-ptr.rs:84:40
    |
 LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
    |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:90:1
+  --> $DIR/ub-wide-ptr.rs:91:1
    |
 LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered 0x03, but expected a boolean
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
-               ╾allocN─╼                                     │ ╾──╼
+               ╾ALLOC_ID╼                                     │ ╾──╼
            }
 
 note: erroneous constant used
-  --> $DIR/ub-wide-ptr.rs:90:42
+  --> $DIR/ub-wide-ptr.rs:91:42
    |
 LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:94:1
+  --> $DIR/ub-wide-ptr.rs:95:1
    |
 LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.1[0]: encountered 0x03, but expected a boolean
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
-               ╾allocN─╼                                     │ ╾──╼
+               ╾ALLOC_ID╼                                     │ ╾──╼
            }
 
 note: erroneous constant used
-  --> $DIR/ub-wide-ptr.rs:94:42
+  --> $DIR/ub-wide-ptr.rs:95:42
    |
 LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:102:1
+  --> $DIR/ub-wide-ptr.rs:103:1
    |
 LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:111:1
+  --> $DIR/ub-wide-ptr.rs:112:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾allocN─╼ ╾allocN─╼                         │ ╾──╼╾──╼
+               ╾ALLOC_ID╼ ╾ALLOC_ID╼                         │ ╾──╼╾──╼
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:115:1
+  --> $DIR/ub-wide-ptr.rs:116:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾allocN─╼ ╾allocN─╼                         │ ╾──╼╾──╼
+               ╾ALLOC_ID╼ ╾ALLOC_ID╼                         │ ╾──╼╾──╼
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:119:1
+  --> $DIR/ub-wide-ptr.rs:120:1
    |
 LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0x4[noalloc], but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾allocN─╼ 04 00 00 00                         │ ╾──╼....
+               ╾ALLOC_ID╼ 04 00 00 00                         │ ╾──╼....
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:122:57
+  --> $DIR/ub-wide-ptr.rs:123:57
    |
 LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) };
    |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:125:57
+  --> $DIR/ub-wide-ptr.rs:126:57
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) };
    |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:128:56
+  --> $DIR/ub-wide-ptr.rs:129:56
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) };
    |                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:131:1
+  --> $DIR/ub-wide-ptr.rs:132:1
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾allocN─╼ ╾allocN─╼                         │ ╾──╼╾──╼
+               ╾ALLOC_ID╼ ╾ALLOC_ID╼                         │ ╾──╼╾──╼
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:136:1
+  --> $DIR/ub-wide-ptr.rs:137:1
    |
 LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.<dyn-downcast>: encountered 0x03, but expected a boolean
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾allocN─╼ ╾allocN─╼                         │ ╾──╼╾──╼
+               ╾ALLOC_ID╼ ╾ALLOC_ID╼                         │ ╾──╼╾──╼
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:141:1
+  --> $DIR/ub-wide-ptr.rs:142:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾allocN─╼ 00 00 00 00                         │ ╾──╼....
+               ╾ALLOC_ID╼ 00 00 00 00                         │ ╾──╼....
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:143:1
+  --> $DIR/ub-wide-ptr.rs:144:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾allocN─╼ ╾allocN─╼                         │ ╾──╼╾──╼
+               ╾ALLOC_ID╼ ╾ALLOC_ID╼                         │ ╾──╼╾──╼
            }
 
 error[E0080]: could not evaluate static initializer
-  --> $DIR/ub-wide-ptr.rs:149:5
+  --> $DIR/ub-wide-ptr.rs:150:5
    |
 LL |     mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
 
 error[E0080]: could not evaluate static initializer
-  --> $DIR/ub-wide-ptr.rs:153:5
+  --> $DIR/ub-wide-ptr.rs:154:5
    |
 LL |     mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
index 06a377d9f7c97982b8d7c29cac7a628b6eee2832..ab25303ddc0cf611df2a306a549d4fde936f52e0 100644 (file)
@@ -1,27 +1,27 @@
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:36:1
+  --> $DIR/ub-wide-ptr.rs:37:1
    |
 LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾───────allocN────────╼ e7 03 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ e7 03 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:38:1
+  --> $DIR/ub-wide-ptr.rs:39:1
    |
 LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid reference metadata: slice is bigger than largest supported object
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾───────allocN───────╼ ff ff ff ff ff ff ff ff │ ╾──────╼........
+               ╾ALLOC_ID╼ ff ff ff ff ff ff ff ff │ ╾──────╼........
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:41:1
+  --> $DIR/ub-wide-ptr.rs:42:1
    |
 LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -30,7 +30,7 @@ LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) };
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:44:1
+  --> $DIR/ub-wide-ptr.rs:45:1
    |
 LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -39,68 +39,68 @@ LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) };
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:46:1
+  --> $DIR/ub-wide-ptr.rs:47:1
    |
 LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾───────allocN───────╼ ff ff ff ff ff ff ff ff │ ╾──────╼........
+               ╾ALLOC_ID╼ ff ff ff ff ff ff ff ff │ ╾──────╼........
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:50:1
+  --> $DIR/ub-wide-ptr.rs:51:1
    |
 LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
    | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered uninitialized data in `str`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾───────allocN───────╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:53:1
+  --> $DIR/ub-wide-ptr.rs:54:1
    |
 LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered uninitialized data in `str`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾───────allocN───────╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:60:1
+  --> $DIR/ub-wide-ptr.rs:61:1
    |
 LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:67:1
+  --> $DIR/ub-wide-ptr.rs:68:1
    |
 LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾───────allocN───────╼ e7 03 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ e7 03 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:70:1
+  --> $DIR/ub-wide-ptr.rs:71:1
    |
 LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, isize::MAX)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾───────allocN───────╼ ff ff ff ff ff ff ff 7f │ ╾──────╼........
+               ╾ALLOC_ID╼ ff ff ff ff ff ff ff 7f │ ╾──────╼........
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:73:1
+  --> $DIR/ub-wide-ptr.rs:74:1
    |
 LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -109,18 +109,18 @@ LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:76:1
+  --> $DIR/ub-wide-ptr.rs:77:1
    |
 LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (going beyond the bounds of its allocation)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾───────allocN───────╼ e7 03 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ e7 03 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:79:1
+  --> $DIR/ub-wide-ptr.rs:80:1
    |
 LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -129,165 +129,165 @@ LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:83:1
+  --> $DIR/ub-wide-ptr.rs:84:1
    |
 LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x03, but expected a boolean
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾───────allocN───────╼                         │ ╾──────╼
+               ╾ALLOC_ID╼                         │ ╾──────╼
            }
 
 note: erroneous constant used
-  --> $DIR/ub-wide-ptr.rs:83:40
+  --> $DIR/ub-wide-ptr.rs:84:40
    |
 LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
    |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:90:1
+  --> $DIR/ub-wide-ptr.rs:91:1
    |
 LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered 0x03, but expected a boolean
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾──────allocN───────╼                         │ ╾──────╼
+               ╾ALLOC_ID╼                         │ ╾──────╼
            }
 
 note: erroneous constant used
-  --> $DIR/ub-wide-ptr.rs:90:42
+  --> $DIR/ub-wide-ptr.rs:91:42
    |
 LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:94:1
+  --> $DIR/ub-wide-ptr.rs:95:1
    |
 LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.1[0]: encountered 0x03, but expected a boolean
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾──────allocN───────╼                         │ ╾──────╼
+               ╾ALLOC_ID╼                         │ ╾──────╼
            }
 
 note: erroneous constant used
-  --> $DIR/ub-wide-ptr.rs:94:42
+  --> $DIR/ub-wide-ptr.rs:95:42
    |
 LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:102:1
+  --> $DIR/ub-wide-ptr.rs:103:1
    |
 LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:111:1
+  --> $DIR/ub-wide-ptr.rs:112:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾──────allocN───────╼ ╾──────allocN───────╼ │ ╾──────╼╾──────╼
+               ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:115:1
+  --> $DIR/ub-wide-ptr.rs:116:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾──────allocN───────╼ ╾──────allocN───────╼ │ ╾──────╼╾──────╼
+               ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:119:1
+  --> $DIR/ub-wide-ptr.rs:120:1
    |
 LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0x4[noalloc], but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾──────allocN───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:122:57
+  --> $DIR/ub-wide-ptr.rs:123:57
    |
 LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) };
    |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:125:57
+  --> $DIR/ub-wide-ptr.rs:126:57
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) };
    |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:128:56
+  --> $DIR/ub-wide-ptr.rs:129:56
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) };
    |                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:131:1
+  --> $DIR/ub-wide-ptr.rs:132:1
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾──────allocN───────╼ ╾──────allocN───────╼ │ ╾──────╼╾──────╼
+               ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:136:1
+  --> $DIR/ub-wide-ptr.rs:137:1
    |
 LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.<dyn-downcast>: encountered 0x03, but expected a boolean
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾──────allocN───────╼ ╾──────allocN───────╼ │ ╾──────╼╾──────╼
+               ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:141:1
+  --> $DIR/ub-wide-ptr.rs:142:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾──────allocN───────╼ 00 00 00 00 00 00 00 00 │ ╾──────╼........
+               ╾ALLOC_ID╼ 00 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:143:1
+  --> $DIR/ub-wide-ptr.rs:144:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾──────allocN───────╼ ╾──────allocN───────╼ │ ╾──────╼╾──────╼
+               ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼
            }
 
 error[E0080]: could not evaluate static initializer
-  --> $DIR/ub-wide-ptr.rs:149:5
+  --> $DIR/ub-wide-ptr.rs:150:5
    |
 LL |     mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
 
 error[E0080]: could not evaluate static initializer
-  --> $DIR/ub-wide-ptr.rs:153:5
+  --> $DIR/ub-wide-ptr.rs:154:5
    |
 LL |     mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
index 2894ef831884cda462a4acbf9bbd9d643bd9fb6d..d12e5e2bed93ef20daa6f5b98b4cb27b3920146a 100644 (file)
@@ -4,6 +4,7 @@
 
 use std::mem;
 
+// normalize-stderr-test "╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼" -> "╾ALLOC_ID$2╼"
 // normalize-stderr-test "offset \d+" -> "offset N"
 // normalize-stderr-test "alloc\d+" -> "allocN"
 // normalize-stderr-test "size \d+" -> "size N"
index 99178ae8c83d1bddfbcc430d905cd158aee4552a..759ce15ab1b5d30e74961ac7077802d0f0d8317e 100644 (file)
@@ -1,15 +1,19 @@
 error[E0080]: evaluation of constant value failed
   --> $DIR/unwind-abort.rs:4:5
    |
+LL |     panic!()
+   |     ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/unwind-abort.rs:4:5
+   |
+note: inside `foo`
+  --> $DIR/unwind-abort.rs:4:5
+   |
 LL |     panic!()
    |     ^^^^^^^^
-   |     |
-   |     the evaluated program panicked at 'explicit panic', $DIR/unwind-abort.rs:4:5
-   |     inside `foo` at $SRC_DIR/std/src/panic.rs:LL:COL
-...
-LL | const _: () = foo();
-   |               ----- inside `_` at $DIR/unwind-abort.rs:7:15
+note: inside `_`
+  --> $DIR/unwind-abort.rs:7:15
    |
+LL | const _: () = foo();
+   |               ^^^^^
    = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
index 8b4d845b30eaa0ee857d6614645a4e6bee00cf8f..9710bf476ecc913b26808998c73240d9bad37f3f 100644 (file)
@@ -13,14 +13,19 @@ LL |     unsafe { std::mem::transmute(()) }
 error[E0080]: evaluation of constant value failed
   --> $DIR/validate_uninhabited_zsts.rs:4:14
    |
+LL |     unsafe { std::mem::transmute(()) }
+   |              ^^^^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
+   |
+note: inside `foo`
+  --> $DIR/validate_uninhabited_zsts.rs:4:14
+   |
 LL |     unsafe { std::mem::transmute(()) }
    |              ^^^^^^^^^^^^^^^^^^^^^^^
-   |              |
-   |              transmuting to uninhabited type
-   |              inside `foo` at $DIR/validate_uninhabited_zsts.rs:4:14
-...
+note: inside `FOO`
+  --> $DIR/validate_uninhabited_zsts.rs:19:33
+   |
 LL | const FOO: [empty::Empty; 3] = [foo(); 3];
-   |                                 ----- inside `FOO` at $DIR/validate_uninhabited_zsts.rs:19:33
+   |                                 ^^^^^
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/validate_uninhabited_zsts.rs:21:1
index 8b4d845b30eaa0ee857d6614645a4e6bee00cf8f..9710bf476ecc913b26808998c73240d9bad37f3f 100644 (file)
@@ -13,14 +13,19 @@ LL |     unsafe { std::mem::transmute(()) }
 error[E0080]: evaluation of constant value failed
   --> $DIR/validate_uninhabited_zsts.rs:4:14
    |
+LL |     unsafe { std::mem::transmute(()) }
+   |              ^^^^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
+   |
+note: inside `foo`
+  --> $DIR/validate_uninhabited_zsts.rs:4:14
+   |
 LL |     unsafe { std::mem::transmute(()) }
    |              ^^^^^^^^^^^^^^^^^^^^^^^
-   |              |
-   |              transmuting to uninhabited type
-   |              inside `foo` at $DIR/validate_uninhabited_zsts.rs:4:14
-...
+note: inside `FOO`
+  --> $DIR/validate_uninhabited_zsts.rs:19:33
+   |
 LL | const FOO: [empty::Empty; 3] = [foo(); 3];
-   |                                 ----- inside `FOO` at $DIR/validate_uninhabited_zsts.rs:19:33
+   |                                 ^^^^^
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/validate_uninhabited_zsts.rs:21:1
index e1ad72416f264f02496400b43fa1caf19ad6be50..7ad02252094203a3f8b6865b53a6f7382bfe88e6 100644 (file)
@@ -1,39 +1,33 @@
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/num/f32.rs:LL:COL
    |
-LL |                     panic!("const-eval error: cannot use f32::to_bits on a NaN")
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                     |
-   |                     the evaluated program panicked at 'const-eval error: cannot use f32::to_bits on a NaN', $SRC_DIR/core/src/num/f32.rs:LL:COL
-   |                     inside `core::f32::<impl f32>::to_bits::ct_f32_to_u32` at $SRC_DIR/core/src/panic.rs:LL:COL
-...
-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
+   = note: the evaluated program panicked at 'const-eval error: cannot use f32::to_bits on a NaN', $SRC_DIR/core/src/num/f32.rs:LL:COL
    |
-  ::: $DIR/const-float-bits-reject-conv.rs:28:30
+note: inside `core::f32::<impl f32>::to_bits::ct_f32_to_u32`
+  --> $SRC_DIR/core/src/num/f32.rs:LL:COL
+note: inside `core::f32::<impl f32>::to_bits`
+  --> $SRC_DIR/core/src/num/f32.rs:LL:COL
+note: inside `f32::MASKED_NAN1`
+  --> $DIR/const-float-bits-reject-conv.rs:28:30
    |
 LL |     const MASKED_NAN1: u32 = f32::NAN.to_bits() ^ 0x002A_AAAA;
-   |                              ------------------ inside `f32::MASKED_NAN1` at $DIR/const-float-bits-reject-conv.rs:28:30
-   |
+   |                              ^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/num/f32.rs:LL:COL
    |
-LL |                     panic!("const-eval error: cannot use f32::to_bits on a NaN")
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                     |
-   |                     the evaluated program panicked at 'const-eval error: cannot use f32::to_bits on a NaN', $SRC_DIR/core/src/num/f32.rs:LL:COL
-   |                     inside `core::f32::<impl f32>::to_bits::ct_f32_to_u32` at $SRC_DIR/core/src/panic.rs:LL:COL
-...
-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
+   = note: the evaluated program panicked at 'const-eval error: cannot use f32::to_bits on a NaN', $SRC_DIR/core/src/num/f32.rs:LL:COL
    |
-  ::: $DIR/const-float-bits-reject-conv.rs:30:30
+note: inside `core::f32::<impl f32>::to_bits::ct_f32_to_u32`
+  --> $SRC_DIR/core/src/num/f32.rs:LL:COL
+note: inside `core::f32::<impl f32>::to_bits`
+  --> $SRC_DIR/core/src/num/f32.rs:LL:COL
+note: inside `f32::MASKED_NAN2`
+  --> $DIR/const-float-bits-reject-conv.rs:30:30
    |
 LL |     const MASKED_NAN2: u32 = f32::NAN.to_bits() ^ 0x0055_5555;
-   |                              ------------------ inside `f32::MASKED_NAN2` at $DIR/const-float-bits-reject-conv.rs:30:30
-   |
+   |                              ^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: erroneous constant used
@@ -63,39 +57,33 @@ LL |     const_assert!(f32::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/num/f64.rs:LL:COL
    |
-LL |                     panic!("const-eval error: cannot use f64::to_bits on a NaN")
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                     |
-   |                     the evaluated program panicked at 'const-eval error: cannot use f64::to_bits on a NaN', $SRC_DIR/core/src/num/f64.rs:LL:COL
-   |                     inside `core::f64::<impl f64>::to_bits::ct_f64_to_u64` at $SRC_DIR/core/src/panic.rs:LL:COL
-...
-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
+   = note: the evaluated program panicked at 'const-eval error: cannot use f64::to_bits on a NaN', $SRC_DIR/core/src/num/f64.rs:LL:COL
    |
-  ::: $DIR/const-float-bits-reject-conv.rs:50:30
+note: inside `core::f64::<impl f64>::to_bits::ct_f64_to_u64`
+  --> $SRC_DIR/core/src/num/f64.rs:LL:COL
+note: inside `core::f64::<impl f64>::to_bits`
+  --> $SRC_DIR/core/src/num/f64.rs:LL:COL
+note: inside `f64::MASKED_NAN1`
+  --> $DIR/const-float-bits-reject-conv.rs:50:30
    |
 LL |     const MASKED_NAN1: u64 = f64::NAN.to_bits() ^ 0x000A_AAAA_AAAA_AAAA;
-   |                              ------------------ inside `f64::MASKED_NAN1` at $DIR/const-float-bits-reject-conv.rs:50:30
-   |
+   |                              ^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/num/f64.rs:LL:COL
    |
-LL |                     panic!("const-eval error: cannot use f64::to_bits on a NaN")
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                     |
-   |                     the evaluated program panicked at 'const-eval error: cannot use f64::to_bits on a NaN', $SRC_DIR/core/src/num/f64.rs:LL:COL
-   |                     inside `core::f64::<impl f64>::to_bits::ct_f64_to_u64` at $SRC_DIR/core/src/panic.rs:LL:COL
-...
-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
+   = note: the evaluated program panicked at 'const-eval error: cannot use f64::to_bits on a NaN', $SRC_DIR/core/src/num/f64.rs:LL:COL
    |
-  ::: $DIR/const-float-bits-reject-conv.rs:52:30
+note: inside `core::f64::<impl f64>::to_bits::ct_f64_to_u64`
+  --> $SRC_DIR/core/src/num/f64.rs:LL:COL
+note: inside `core::f64::<impl f64>::to_bits`
+  --> $SRC_DIR/core/src/num/f64.rs:LL:COL
+note: inside `f64::MASKED_NAN2`
+  --> $DIR/const-float-bits-reject-conv.rs:52:30
    |
 LL |     const MASKED_NAN2: u64 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555;
-   |                              ------------------ inside `f64::MASKED_NAN2` at $DIR/const-float-bits-reject-conv.rs:52:30
-   |
+   |                              ^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: erroneous constant used
index 02960b363e78f695824f372021ff5c280c73d709..f6b532fb6586590a33aa1ce6e96d563c3ffe370c 100644 (file)
@@ -21,9 +21,6 @@ LL |     for i in 0..x {
    |
 note: impl defined here, but it is not `const`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL | impl<I: Iterator> const IntoIterator for I {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 
 error[E0658]: mutable references are not allowed in constant functions
index 11e4ae309c01f5abddb458968d476586dc84dd63..294ea627d8544e9fbf91135146432570b0adbf5a 100644 (file)
@@ -6,9 +6,6 @@ LL |     for _ in 0..5 {}
    |
 note: impl defined here, but it is not `const`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL | impl<I: Iterator> const IntoIterator for I {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: calls in constants are limited to constant functions, tuple structs and tuple variants
 
 error[E0015]: cannot call non-const fn `<std::ops::Range<i32> as Iterator>::next` in constants
index 234e55e3a96c8beb7e5cb0cd84e332fa35ceeade..6e110dbdd6417dd5f87e0f8e845437e592dd6d6f 100644 (file)
@@ -1,14 +1,19 @@
 error[E0080]: evaluation of constant value failed
   --> $DIR/mut_ref_in_final_dynamic_check.rs:13:10
    |
+LL |     Some(&mut *(42 as *mut i32))
+   |          ^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: 0x2a[noalloc] is a dangling pointer (it has no provenance)
+   |
+note: inside `helper`
+  --> $DIR/mut_ref_in_final_dynamic_check.rs:13:10
+   |
 LL |     Some(&mut *(42 as *mut i32))
    |          ^^^^^^^^^^^^^^^^^^^^^^
-   |          |
-   |          dereferencing pointer failed: 0x2a[noalloc] is a dangling pointer (it has no provenance)
-   |          inside `helper` at $DIR/mut_ref_in_final_dynamic_check.rs:13:10
-...
+note: inside `A`
+  --> $DIR/mut_ref_in_final_dynamic_check.rs:18:29
+   |
 LL | const A: Option<&mut i32> = helper();
-   |                             -------- inside `A` at $DIR/mut_ref_in_final_dynamic_check.rs:18:29
+   |                             ^^^^^^^^
 
 error: encountered dangling pointer in final constant
   --> $DIR/mut_ref_in_final_dynamic_check.rs:25:1
index f6de3699f778189891594022be12634cd343def9..593a51bfe8fea6f7282a4b8d6804bff8c891e2a8 100644 (file)
@@ -1,19 +1,20 @@
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/hint.rs:LL:COL
    |
-LL |         intrinsics::unreachable()
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         entering unreachable code
-   |         inside `unreachable_unchecked` at $SRC_DIR/core/src/hint.rs:LL:COL
+   = note: entering unreachable code
    |
-  ::: $DIR/const_unsafe_unreachable_ub.rs:6:18
+note: inside `unreachable_unchecked`
+  --> $SRC_DIR/core/src/hint.rs:LL:COL
+note: inside `foo`
+  --> $DIR/const_unsafe_unreachable_ub.rs:6:18
    |
 LL |         false => std::hint::unreachable_unchecked(),
-   |                  ---------------------------------- inside `foo` at $DIR/const_unsafe_unreachable_ub.rs:6:18
-...
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `BAR`
+  --> $DIR/const_unsafe_unreachable_ub.rs:10:28
+   |
 LL | const BAR: bool = unsafe { foo(false) };
-   |                            ---------- inside `BAR` at $DIR/const_unsafe_unreachable_ub.rs:10:28
+   |                            ^^^^^^^^^^
 
 error: aborting due to previous error
 
index 249bbb5991cc98dc6da6f19feff3bdb06b4bff36..94d7bdc6bae9ff6222411821a5a3b912f6728fbf 100644 (file)
@@ -17,7 +17,7 @@
     // Since we are not copying anything, this should be allowed.
     let src = ();
     let mut dst = ();
-    copy_nonoverlapping(&src as *const _ as *const i32, &mut dst as *mut _ as *mut i32, 0);
+    copy_nonoverlapping(&src as *const _ as *const u8, &mut dst as *mut _ as *mut u8, 0);
 };
 
 const COPY_OOB_1: () = unsafe {
index 9c239c8a100f991e60176a3364a15478940bf252..e2f8149883b1d980978e431889112462f1dd4e85 100644 (file)
     //[with_flag]~| invalid value
 };
 
-const UNALIGNED_READ: () = {
-    INNER; //[with_flag]~ constant
-    // There is an error here but its span is in the standard library so we cannot match it...
-    // so we have this in a *nested* const, such that the *outer* const fails to use it.
-    const INNER: () = unsafe {
-        let x = &[0u8; 4];
-        let ptr = x.as_ptr().cast::<u32>();
-        ptr.read();
-    };
-};
-
 fn main() {}
index 4726905ade341e5d42d5daac35cbbda59ca49fef..b2a5fd90149a3eee815afc6625507556b9a01c45 100644 (file)
@@ -28,31 +28,6 @@ error[E0080]: evaluation of constant value failed
 LL |     let _x: &u32 = transmute(&[0u8; 4]);
    |                    ^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 4 byte alignment but found 1)
 
-error[E0080]: evaluation of constant value failed
-  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-   |
-LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         accessing memory with alignment 1, but alignment 4 is required
-   |         inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-   |
-  ::: $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { read(self) }
-   |                  ---------- inside `ptr::const_ptr::<impl *const u32>::read` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-  ::: $DIR/detect-extra-ub.rs:38:9
-   |
-LL |         ptr.read();
-   |         ---------- inside `INNER` at $DIR/detect-extra-ub.rs:38:9
-
-note: erroneous constant used
-  --> $DIR/detect-extra-ub.rs:32:5
-   |
-LL |     INNER;
-   |     ^^^^^
-
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
index 3872e3d4f0decb2cdd1d4ca13e09d390a90ff7ab..61865b1dad764240adeb9cfaead4efedb5cc9806 100644 (file)
@@ -1,24 +1,19 @@
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
-LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         unable to copy parts of a pointer from memory at ALLOC
-   |         inside `std::ptr::read::<u8>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-   |
-  ::: $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |         unsafe { read(self) }
-   |                  ---------- inside `ptr::const_ptr::<impl *const u8>::read` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-  ::: $DIR/issue-miri-1910.rs:8:5
-   |
-LL |     (&foo as *const _ as *const u8).add(one_and_a_half_pointers).read();
-   |     ------------------------------------------------------------------- inside `C` at $DIR/issue-miri-1910.rs:8:5
+   = note: unable to copy parts of a pointer from memory at ALLOC
    |
    = help: this code performed an operation that depends on the underlying bytes representing a pointer
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
+note: inside `std::ptr::read::<u8>`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u8>::read`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `C`
+  --> $DIR/issue-miri-1910.rs:8:5
+   |
+LL |     (&foo as *const _ as *const u8).add(one_and_a_half_pointers).read();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 840d698ebbfaf7b044ee486e2332a324010daede..cf3fd88d0342e06c15700d8e46ea2ad669b4add0 100644 (file)
@@ -1,14 +1,19 @@
 error[E0080]: could not evaluate static initializer
   --> $DIR/abi-mismatch.rs:9:5
    |
+LL |     my_fn();
+   |     ^^^^^^^ calling a function with calling convention C using calling convention Rust
+   |
+note: inside `call_rust_fn`
+  --> $DIR/abi-mismatch.rs:9:5
+   |
 LL |     my_fn();
    |     ^^^^^^^
-   |     |
-   |     calling a function with calling convention C using calling convention Rust
-   |     inside `call_rust_fn` at $DIR/abi-mismatch.rs:9:5
-...
+note: inside `VAL`
+  --> $DIR/abi-mismatch.rs:15:18
+   |
 LL | static VAL: () = call_rust_fn(unsafe { std::mem::transmute(c_fn as extern "C" fn()) });
-   |                  --------------------------------------------------------------------- inside `VAL` at $DIR/abi-mismatch.rs:15:18
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: skipping const checks
    |
index 33e7e4af276f7418cfb443c530f9a312d37fa828..e1da43c3aea4134f15025cd694071cbca338dbc2 100644 (file)
@@ -1,17 +1,17 @@
 error[E0080]: evaluation of `<std::string::String as Bar<std::vec::Vec<u32>, std::string::String>>::F` failed
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
-LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   | |
-   | calling non-const function `<Vec<u32> as Drop>::drop`
-   | inside `std::ptr::drop_in_place::<Vec<u32>> - shim(Some(Vec<u32>))` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-   | inside `std::ptr::drop_in_place::<(Vec<u32>, u32)> - shim(Some((Vec<u32>, u32)))` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   = note: calling non-const function `<Vec<u32> as Drop>::drop`
    |
-  ::: $DIR/assoc_const.rs:12:31
+note: inside `std::ptr::drop_in_place::<Vec<u32>> - shim(Some(Vec<u32>))`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `std::ptr::drop_in_place::<(Vec<u32>, u32)> - shim(Some((Vec<u32>, u32)))`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `<String as Bar<Vec<u32>, String>>::F`
+  --> $DIR/assoc_const.rs:12:31
    |
 LL |     const F: u32 = (U::X, 42).1;
-   |                               - inside `<String as Bar<Vec<u32>, String>>::F` at $DIR/assoc_const.rs:12:31
+   |                               ^
 
 note: erroneous constant used
   --> $DIR/assoc_const.rs:29:13
index a3a502723d223d1399ad88dbe4f089eda6c4b99d..4f60b8820691ba0fb23de283c30845d8442ca100 100644 (file)
@@ -1,16 +1,15 @@
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
-LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   | |
-   | calling non-const function `<Vec<i32> as Drop>::drop`
-   | inside `std::ptr::drop_in_place::<Vec<i32>> - shim(Some(Vec<i32>))` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   = note: calling non-const function `<Vec<i32> as Drop>::drop`
    |
-  ::: $DIR/drop.rs:17:1
+note: inside `std::ptr::drop_in_place::<Vec<i32>> - shim(Some(Vec<i32>))`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `TEST_BAD`
+  --> $DIR/drop.rs:17:1
    |
 LL | };
-   | - inside `TEST_BAD` at $DIR/drop.rs:17:1
+   | ^
 
 warning: skipping const checks
    |
diff --git a/src/test/ui/consts/missing_span_in_backtrace.rs b/src/test/ui/consts/missing_span_in_backtrace.rs
new file mode 100644 (file)
index 0000000..dd2b81c
--- /dev/null
@@ -0,0 +1,27 @@
+// compile-flags: -Z ui-testing=no
+// normalize-stderr-test "alloc[0-9]+" -> "ALLOC_ID"
+
+#![feature(const_swap)]
+#![feature(const_mut_refs)]
+use std::{
+    mem::{self, MaybeUninit},
+    ptr,
+};
+
+const X: () = {
+    let mut ptr1 = &1;
+    let mut ptr2 = &2;
+
+    // Swap them, bytewise.
+    unsafe {
+        ptr::swap_nonoverlapping(
+            &mut ptr1 as *mut _ as *mut MaybeUninit<u8>,
+            &mut ptr2 as *mut _ as *mut MaybeUninit<u8>,
+            mem::size_of::<&i32>(),
+        );
+    }
+};
+
+fn main() {
+    X
+}
diff --git a/src/test/ui/consts/missing_span_in_backtrace.stderr b/src/test/ui/consts/missing_span_in_backtrace.stderr
new file mode 100644 (file)
index 0000000..e6d3d51
--- /dev/null
@@ -0,0 +1,28 @@
+error[E0080]: evaluation of constant value failed
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   |
+   = note: unable to copy parts of a pointer from memory at ALLOC_ID
+   |
+   = help: this code performed an operation that depends on the underlying bytes representing a pointer
+   = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
+note: inside `std::ptr::read::<MaybeUninit<MaybeUninit<u8>>>`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `mem::swap_simple::<MaybeUninit<MaybeUninit<u8>>>`
+  --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+note: inside `ptr::swap_nonoverlapping_simple_untyped::<MaybeUninit<u8>>`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `swap_nonoverlapping::<MaybeUninit<u8>>`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `X`
+  --> $DIR/missing_span_in_backtrace.rs:17:9
+   |
+17 | /         ptr::swap_nonoverlapping(
+18 | |             &mut ptr1 as *mut _ as *mut MaybeUninit<u8>,
+19 | |             &mut ptr2 as *mut _ as *mut MaybeUninit<u8>,
+20 | |             mem::size_of::<&i32>(),
+21 | |         );
+   | |_________^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
index 62a087d94d3565894d4043cff00b66526097b54b..fff4729689f54058a1969380dfa67407af7a274c 100644 (file)
@@ -7,16 +7,15 @@ LL |     let offset = unsafe { ptr_offset_from(field_ptr, base_ptr) };
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::ptr_offset_from(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  `ptr_offset_from` called on pointers into different allocations
-   |                  inside `ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   = note: `ptr_offset_from` called on pointers into different allocations
    |
-  ::: $DIR/offset_from_ub.rs:24:14
+note: inside `ptr::const_ptr::<impl *const u8>::offset_from`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `NOT_PTR`
+  --> $DIR/offset_from_ub.rs:24:14
    |
 LL |     unsafe { (42 as *const u8).offset_from(&5u8) as usize }
-   |              ----------------------------------- inside `NOT_PTR` at $DIR/offset_from_ub.rs:24:14
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/offset_from_ub.rs:31:14
@@ -87,30 +86,28 @@ LL |     unsafe { ptr_offset_from_unsigned(ptr2, ptr1) }
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::ptr_offset_from(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
-   |                  inside `ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   = note: out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
    |
-  ::: $DIR/offset_from_ub.rs:115:14
+note: inside `ptr::const_ptr::<impl *const u8>::offset_from`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `OFFSET_VERY_FAR1`
+  --> $DIR/offset_from_ub.rs:115:14
    |
 LL |     unsafe { ptr2.offset_from(ptr1) }
-   |              ---------------------- inside `OFFSET_VERY_FAR1` at $DIR/offset_from_ub.rs:115:14
+   |              ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::ptr_offset_from(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
-   |                  inside `ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   = note: out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
    |
-  ::: $DIR/offset_from_ub.rs:121:14
+note: inside `ptr::const_ptr::<impl *const u8>::offset_from`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `OFFSET_VERY_FAR2`
+  --> $DIR/offset_from_ub.rs:121:14
    |
 LL |     unsafe { ptr1.offset_from(ptr2.wrapping_offset(1)) }
-   |              ----------------------------------------- inside `OFFSET_VERY_FAR2` at $DIR/offset_from_ub.rs:121:14
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 15 previous errors
 
index 5a792bba50cb2ecb20e42fd29a21f248a09f8784..c0c851df5076e078bb5529b11f9b612d9740010a 100644 (file)
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  overflowing in-bounds pointer arithmetic
-   |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   = note: overflowing in-bounds pointer arithmetic
    |
-  ::: $DIR/offset_ub.rs:7:46
+note: inside `ptr::const_ptr::<impl *const u8>::offset`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `BEFORE_START`
+  --> $DIR/offset_ub.rs:7:46
    |
 LL | pub const BEFORE_START: *const u8 = unsafe { (&0u8 as *const u8).offset(-1) };
-   |                                              ------------------------------ inside `BEFORE_START` at $DIR/offset_ub.rs:7:46
+   |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  out-of-bounds pointer arithmetic: allocN has size 1, so pointer to 2 bytes starting at offset 0 is out-of-bounds
-   |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   = note: out-of-bounds pointer arithmetic: allocN has size 1, so pointer to 2 bytes starting at offset 0 is out-of-bounds
    |
-  ::: $DIR/offset_ub.rs:8:43
+note: inside `ptr::const_ptr::<impl *const u8>::offset`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `AFTER_END`
+  --> $DIR/offset_ub.rs:8:43
    |
 LL | pub const AFTER_END: *const u8 = unsafe { (&0u8 as *const u8).offset(2) };
-   |                                           ----------------------------- inside `AFTER_END` at $DIR/offset_ub.rs:8:43
+   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  out-of-bounds pointer arithmetic: allocN has size 100, so pointer to 101 bytes starting at offset 0 is out-of-bounds
-   |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   = note: out-of-bounds pointer arithmetic: allocN has size 100, so pointer to 101 bytes starting at offset 0 is out-of-bounds
    |
-  ::: $DIR/offset_ub.rs:9:45
+note: inside `ptr::const_ptr::<impl *const u8>::offset`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `AFTER_ARRAY`
+  --> $DIR/offset_ub.rs:9:45
    |
 LL | pub const AFTER_ARRAY: *const u8 = unsafe { [0u8; 100].as_ptr().offset(101) };
-   |                                             ------------------------------- inside `AFTER_ARRAY` at $DIR/offset_ub.rs:9:45
+   |                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  overflowing in-bounds pointer arithmetic
-   |                  inside `ptr::const_ptr::<impl *const u16>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   = note: overflowing in-bounds pointer arithmetic
    |
-  ::: $DIR/offset_ub.rs:11:43
+note: inside `ptr::const_ptr::<impl *const u16>::offset`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `OVERFLOW`
+  --> $DIR/offset_ub.rs:11:43
    |
 LL | pub const OVERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MAX) };
-   |                                           ------------------------------------- inside `OVERFLOW` at $DIR/offset_ub.rs:11:43
+   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  overflowing in-bounds pointer arithmetic
-   |                  inside `ptr::const_ptr::<impl *const u16>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   = note: overflowing in-bounds pointer arithmetic
    |
-  ::: $DIR/offset_ub.rs:12:44
+note: inside `ptr::const_ptr::<impl *const u16>::offset`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `UNDERFLOW`
+  --> $DIR/offset_ub.rs:12:44
    |
 LL | pub const UNDERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MIN) };
-   |                                            ------------------------------------- inside `UNDERFLOW` at $DIR/offset_ub.rs:12:44
+   |                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  overflowing in-bounds pointer arithmetic
-   |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   = note: overflowing in-bounds pointer arithmetic
    |
-  ::: $DIR/offset_ub.rs:13:56
+note: inside `ptr::const_ptr::<impl *const u8>::offset`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `OVERFLOW_ADDRESS_SPACE`
+  --> $DIR/offset_ub.rs:13:56
    |
 LL | pub const OVERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (usize::MAX as *const u8).offset(2) };
-   |                                                        ----------------------------------- inside `OVERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:13:56
+   |                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  overflowing in-bounds pointer arithmetic
-   |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   = note: overflowing in-bounds pointer arithmetic
    |
-  ::: $DIR/offset_ub.rs:14:57
+note: inside `ptr::const_ptr::<impl *const u8>::offset`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `UNDERFLOW_ADDRESS_SPACE`
+  --> $DIR/offset_ub.rs:14:57
    |
 LL | pub const UNDERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (1 as *const u8).offset(-2) };
-   |                                                         --------------------------- inside `UNDERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:14:57
+   |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  out-of-bounds pointer arithmetic: allocN has size 1, so pointer to 2 bytes starting at offset -4 is out-of-bounds
-   |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   = note: out-of-bounds pointer arithmetic: allocN has size 1, so pointer to 2 bytes starting at offset -4 is out-of-bounds
    |
-  ::: $DIR/offset_ub.rs:15:49
+note: inside `ptr::const_ptr::<impl *const u8>::offset`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `NEGATIVE_OFFSET`
+  --> $DIR/offset_ub.rs:15:49
    |
 LL | pub const NEGATIVE_OFFSET: *const u8 = unsafe { [0u8; 1].as_ptr().wrapping_offset(-2).offset(-2) };
-   |                                                 ------------------------------------------------ inside `NEGATIVE_OFFSET` at $DIR/offset_ub.rs:15:49
+   |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  out-of-bounds pointer arithmetic: allocN has size 0, so pointer to 1 byte starting at offset 0 is out-of-bounds
-   |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   = note: out-of-bounds pointer arithmetic: allocN has size 0, so pointer to 1 byte starting at offset 0 is out-of-bounds
    |
-  ::: $DIR/offset_ub.rs:17:50
+note: inside `ptr::const_ptr::<impl *const u8>::offset`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `ZERO_SIZED_ALLOC`
+  --> $DIR/offset_ub.rs:17:50
    |
 LL | pub const ZERO_SIZED_ALLOC: *const u8 = unsafe { [0u8; 0].as_ptr().offset(1) };
-   |                                                  --------------------------- inside `ZERO_SIZED_ALLOC` at $DIR/offset_ub.rs:17:50
+   |                                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) as *mut T }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  out-of-bounds pointer arithmetic: 0x1[noalloc] is a dangling pointer (it has no provenance)
-   |                  inside `ptr::mut_ptr::<impl *mut u8>::offset` at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+   = note: out-of-bounds pointer arithmetic: 0x1[noalloc] is a dangling pointer (it has no provenance)
    |
-  ::: $DIR/offset_ub.rs:18:42
+note: inside `ptr::mut_ptr::<impl *mut u8>::offset`
+  --> $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+note: inside `DANGLING`
+  --> $DIR/offset_ub.rs:18:42
    |
 LL | pub const DANGLING: *const u8 = unsafe { ptr::NonNull::<u8>::dangling().as_ptr().offset(4) };
-   |                                          ------------------------------------------------- inside `DANGLING` at $DIR/offset_ub.rs:18:42
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  out-of-bounds pointer arithmetic: null pointer is a dangling pointer (it has no provenance)
-   |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   = note: out-of-bounds pointer arithmetic: null pointer is a dangling pointer (it has no provenance)
    |
-  ::: $DIR/offset_ub.rs:21:50
+note: inside `ptr::const_ptr::<impl *const u8>::offset`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `NULL_OFFSET_ZERO`
+  --> $DIR/offset_ub.rs:21:50
    |
 LL | pub const NULL_OFFSET_ZERO: *const u8 = unsafe { ptr::null::<u8>().offset(0) };
-   |                                                  --------------------------- inside `NULL_OFFSET_ZERO` at $DIR/offset_ub.rs:21:50
+   |                                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  out-of-bounds pointer arithmetic: 0x7f..f[noalloc] is a dangling pointer (it has no provenance)
-   |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   = note: out-of-bounds pointer arithmetic: 0x7f..f[noalloc] is a dangling pointer (it has no provenance)
    |
-  ::: $DIR/offset_ub.rs:24:47
+note: inside `ptr::const_ptr::<impl *const u8>::offset`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `UNDERFLOW_ABS`
+  --> $DIR/offset_ub.rs:24:47
    |
 LL | pub const UNDERFLOW_ABS: *const u8 = unsafe { (usize::MAX as *const u8).offset(isize::MIN) };
-   |                                               -------------------------------------------- inside `UNDERFLOW_ABS` at $DIR/offset_ub.rs:24:47
+   |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 12 previous errors
 
index b71964b92c77315ac67ff3b4c1dd41ff2e28c283..fea924d12e54ee60a79799be0f8845a707b3cf4a 100644 (file)
@@ -1,16 +1,15 @@
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  out-of-bounds pointer arithmetic: alloc3 has size $WORD, so pointer to $TWO_WORDS bytes starting at offset 0 is out-of-bounds
-   |                  inside `ptr::const_ptr::<impl *const usize>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   = note: out-of-bounds pointer arithmetic: alloc3 has size $WORD, so pointer to $TWO_WORDS bytes starting at offset 0 is out-of-bounds
    |
-  ::: $DIR/ptr_comparisons.rs:50:34
+note: inside `ptr::const_ptr::<impl *const usize>::offset`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `_`
+  --> $DIR/ptr_comparisons.rs:50:34
    |
 LL | const _: *const usize = unsafe { (FOO as *const usize).offset(2) };
-   |                                  ------------------------------- inside `_` at $DIR/ptr_comparisons.rs:50:34
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/ptr_comparisons.rs:53:33
index 14fa3da7ab0f2e3099ad58fa394936434c57732b..60ce64d2a1e0f4dd864a8d565bc61cd13718cfc7 100644 (file)
@@ -12,15 +12,24 @@ LL |     f(x);
 error[E0080]: evaluation of constant value failed
   --> $DIR/recursive.rs:4:5
    |
+LL |     f(x);
+   |     ^^^^ reached the configured maximum number of stack frames
+   |
+note: inside `f::<i32>`
+  --> $DIR/recursive.rs:4:5
+   |
 LL |     f(x);
    |     ^^^^
-   |     |
-   |     reached the configured maximum number of stack frames
-   |     inside `f::<i32>` at $DIR/recursive.rs:4:5
-   |     [... 126 additional calls inside `f::<i32>` at $DIR/recursive.rs:4:5 ...]
-...
+note: [... 126 additional calls inside `f::<i32>` ...]
+  --> $DIR/recursive.rs:4:5
+   |
+LL |     f(x);
+   |     ^^^^
+note: inside `X`
+  --> $DIR/recursive.rs:8:15
+   |
 LL | const X: () = f(1);
-   |               ---- inside `X` at $DIR/recursive.rs:8:15
+   |               ^^^^
 
 error: aborting due to previous error; 1 warning emitted
 
index 8b39f390bb47eb9ba0ba4c26e2d9d5cf575c7650..3a94e19313f6c52b719ead4dddf54b6e1872822c 100644 (file)
 error[E0080]: evaluation of `<i32 as Const>::CONSTANT` failed
   --> $DIR/uninhabited-const-issue-61744.rs:4:5
    |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^ reached the configured maximum number of stack frames
+   |
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
 LL |     hint_unreachable()
    |     ^^^^^^^^^^^^^^^^^^
-   |     |
-   |     reached the configured maximum number of stack frames
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<i32>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-...
-LL |     fake_type()
-   |     -----------
-   |     |
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-...
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<i32>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `<i32 as Const>::CONSTANT`
+  --> $DIR/uninhabited-const-issue-61744.rs:12:36
+   |
 LL |     const CONSTANT: i32 = unsafe { fake_type() };
-   |                                    ----------- inside `<i32 as Const>::CONSTANT` at $DIR/uninhabited-const-issue-61744.rs:12:36
+   |                                    ^^^^^^^^^^^
 
 note: erroneous constant used
   --> $DIR/uninhabited-const-issue-61744.rs:18:10
diff --git a/src/test/ui/debuginfo/issue-105386-debuginfo-ub.rs b/src/test/ui/debuginfo/issue-105386-debuginfo-ub.rs
new file mode 100644 (file)
index 0000000..6c6eb5d
--- /dev/null
@@ -0,0 +1,20 @@
+// run-pass
+// compile-flags: --edition 2021 -Copt-level=3 -Cdebuginfo=2 -Zmir-opt-level=3
+
+fn main() {
+    TranslatorI.visit_pre();
+}
+
+impl TranslatorI {
+    fn visit_pre(self) {
+        Some(())
+            .map(|_| self.flags())
+            .unwrap_or_else(|| self.flags());
+    }
+}
+
+struct TranslatorI;
+
+impl TranslatorI {
+    fn flags(&self) {}
+}
index e3fb234b96e4153b51ade0849d30f6a36c2a3a97..2be69a30b1c122222de25596e628ff372f5f9504 100644 (file)
@@ -9,9 +9,6 @@ LL |      x: Error
    |
 note: required by a bound in `AssertParamIsEq`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub struct AssertParamIsEq<T: Eq + ?Sized> {
-   |                               ^^ required by this bound in `AssertParamIsEq`
    = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `Error` with `#[derive(Eq)]`
    |
index 4e10c3f69e735a5df6d17b558f156aad35661078..4f4f821cca3e7c735302daf8c1c8b3103a67d80b 100644 (file)
@@ -9,9 +9,6 @@ LL |      Error
    |
 note: required by a bound in `AssertParamIsEq`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub struct AssertParamIsEq<T: Eq + ?Sized> {
-   |                               ^^ required by this bound in `AssertParamIsEq`
    = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `Error` with `#[derive(Eq)]`
    |
index bfdab052a2ed42167c6d6398d2dbbc5b8e11cba4..f15659c3e166c9807c66cc7cef251465884b933e 100644 (file)
@@ -9,9 +9,6 @@ LL |     x: Error
    |
 note: required by a bound in `AssertParamIsEq`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub struct AssertParamIsEq<T: Eq + ?Sized> {
-   |                               ^^ required by this bound in `AssertParamIsEq`
    = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `Error` with `#[derive(Eq)]`
    |
index 26b8be343336b95ac9f7947ccf639103d01ef928..4e5659b35f47a5434459c7681e33d7ccb1391a83 100644 (file)
@@ -9,9 +9,6 @@ LL |     Error
    |
 note: required by a bound in `AssertParamIsEq`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub struct AssertParamIsEq<T: Eq + ?Sized> {
-   |                               ^^ required by this bound in `AssertParamIsEq`
    = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `Error` with `#[derive(Eq)]`
    |
index f3ff95a85da1a3b314ed0a30af84a166a279f54f..053d34f68251a44082558ca4678c750b593aaf9d 100644 (file)
@@ -3,22 +3,18 @@ error: cannot find derive macro `Eqr` in this scope
    |
 LL | #[derive(Eqr)]
    |          ^^^ help: a derive macro with a similar name exists: `Eq`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub macro Eq($item:item) {
-   | ------------ similarly named derive macro `Eq` defined here
+   = note: similarly named derive macro `Eq` defined here
 
 error: cannot find derive macro `Eqr` in this scope
   --> $DIR/deriving-meta-unknown-trait.rs:1:10
    |
 LL | #[derive(Eqr)]
    |          ^^^ help: a derive macro with a similar name exists: `Eq`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub macro Eq($item:item) {
-   | ------------ similarly named derive macro `Eq` defined here
+   = note: similarly named derive macro `Eq` defined here
 
 error: aborting due to 2 previous errors
 
index ee3528fe1062ddd7f418667689da0e7376c0c352..b18e1e5098b34ba08ed6cfd5f7a39d06aa060d23 100644 (file)
@@ -20,9 +20,6 @@ LL |     Float(Option<f64>),
    = note: required for `Option<f64>` to implement `Eq`
 note: required by a bound in `AssertParamIsEq`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub struct AssertParamIsEq<T: Eq + ?Sized> {
-   |                               ^^ required by this bound in `AssertParamIsEq`
    = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
index e45344aa51fc335c3db50d7d8b91bee8c2d7be90..8a88332b73e105f8b06c85c634f8cdeefba70f7e 100644 (file)
@@ -49,11 +49,8 @@ note: an implementation of `AddAssign<_>` might be missing for `S`
    |
 LL | struct S { x: u8, y: u8 }
    | ^^^^^^^^ must implement `AddAssign<_>`
-note: the following trait must be implemented
+note: the trait `AddAssign` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait AddAssign<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0067]: invalid left-hand side of assignment
   --> $DIR/note-unsupported.rs:17:22
diff --git a/src/test/ui/diagnostic-width/long-E0308.rs b/src/test/ui/diagnostic-width/long-E0308.rs
new file mode 100644 (file)
index 0000000..f021f10
--- /dev/null
@@ -0,0 +1,97 @@
+// compile-flags: --diagnostic-width=60
+// normalize-stderr-test: "long-type-\d+" -> "long-type-hash"
+
+mod a {
+    // Force the "short path for unique types" machinery to trip up
+    pub struct Atype;
+    pub struct Btype;
+    pub struct Ctype;
+}
+
+mod b {
+    pub struct Atype<T, K>(T, K);
+    pub struct Btype<T, K>(T, K);
+    pub struct Ctype<T, K>(T, K);
+}
+
+use b::*;
+
+fn main() {
+    let x: Atype<
+      Btype<
+        Ctype<
+          Atype<
+            Btype<
+              Ctype<
+                Atype<
+                  Btype<
+                    Ctype<i32, i32>,
+                    i32
+                  >,
+                  i32
+                >,
+                i32
+              >,
+              i32
+            >,
+            i32
+          >,
+          i32
+        >,
+        i32
+      >,
+      i32
+    > = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(
+        Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(
+            Ok("")
+        ))))))))))))))))))))))))))))))
+    ))))))))))))))))))))))))))))));
+    //~^^^^^ ERROR E0308
+
+    let _ = Some(Ok(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(
+        Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(
+            Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(
+                Some(Some(Some(Some(Some(Some(Some(Some(Some("")))))))))
+            )))))))))))))))))
+        ))))))))))))))))))
+    ))))))))))))))))) == Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(
+        Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(
+            Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
+        ))))))))))))))))))))))))))))))
+    ))))))))))))))))))))))));
+    //~^^^^^ ERROR E0308
+
+    let x: Atype<
+      Btype<
+        Ctype<
+          Atype<
+            Btype<
+              Ctype<
+                Atype<
+                  Btype<
+                    Ctype<i32, i32>,
+                    i32
+                  >,
+                  i32
+                >,
+                i32
+              >,
+              i32
+            >,
+            i32
+          >,
+          i32
+        >,
+        i32
+      >,
+      i32
+    > = ();
+    //~^ ERROR E0308
+
+    let _: () = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(
+        Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(
+            Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
+        ))))))))))))))))))))))))))))))
+    ))))))))))))))))))))))));
+    //~^^^^^ ERROR E0308
+}
diff --git a/src/test/ui/diagnostic-width/long-E0308.stderr b/src/test/ui/diagnostic-width/long-E0308.stderr
new file mode 100644 (file)
index 0000000..1c99898
--- /dev/null
@@ -0,0 +1,80 @@
+error[E0308]: mismatched types
+  --> $DIR/long-E0308.rs:44:9
+   |
+LL |        let x: Atype<
+   |  _____________-
+LL | |        Btype<
+LL | |          Ctype<
+LL | |            Atype<
+...  |
+LL | |        i32
+LL | |      > = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok...
+   | | _____-___^
+   | ||_____|
+   |  |     expected due to this
+LL |  |         Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok...
+LL |  |             Ok("")
+LL |  |         ))))))))))))))))))))))))))))))
+LL |  |     ))))))))))))))))))))))))))))));
+   |  |__________________________________^ expected struct `Atype`, found enum `Result`
+   |
+   = note: expected struct `Atype<Btype<..., ...>, ...>`
+           the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
+                found enum `Result<Result<..., ...>, ...>`
+           the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
+
+error[E0308]: mismatched types
+  --> $DIR/long-E0308.rs:57:26
+   |
+LL |       ))))))))))))))))) == Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O...
+   |  __________________________^
+LL | |         Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(...
+LL | |             Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
+LL | |         ))))))))))))))))))))))))))))))
+LL | |     ))))))))))))))))))))))));
+   | |____________________________^ expected enum `Option`, found enum `Result`
+   |
+   = note: expected enum `Option<Result<..., ...>>`
+           the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
+              found enum `Result<Result<..., ...>, ...>`
+           the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
+
+error[E0308]: mismatched types
+  --> $DIR/long-E0308.rs:88:9
+   |
+LL |       let x: Atype<
+   |  ____________-
+LL | |       Btype<
+LL | |         Ctype<
+LL | |           Atype<
+...  |
+LL | |       i32
+LL | |     > = ();
+   | |     -   ^^ expected struct `Atype`, found `()`
+   | |_____|
+   |       expected due to this
+   |
+   = note: expected struct `Atype<Btype<..., ...>, ...>`
+           the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
+           found unit type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/long-E0308.rs:91:17
+   |
+LL |       let _: () = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O...
+   |  ____________--___^
+   | |            |
+   | |            expected due to this
+LL | |         Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(...
+LL | |             Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
+LL | |         ))))))))))))))))))))))))))))))
+LL | |     ))))))))))))))))))))))));
+   | |____________________________^ expected `()`, found enum `Result`
+   |
+   = note: expected unit type `()`
+                   found enum `Result<Result<..., ...>, ...>`
+           the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.fixed b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.fixed
new file mode 100644 (file)
index 0000000..ae0a84e
--- /dev/null
@@ -0,0 +1,21 @@
+// run-rustfix
+struct X {
+    x: String,
+}
+
+impl Drop for X {
+    fn drop(&mut self) {
+        println!("value: {}", self.x);
+    }
+}
+
+fn unwrap(x: X) -> String {
+    let X { x: ref y } = x; //~ ERROR cannot move out of type
+    y.to_string()
+}
+
+fn main() {
+    let x = X { x: "hello".to_string() };
+    let y = unwrap(x);
+    println!("contents: {}", y);
+}
index 8e394498a2349bd040bcdd7f8704c66fd40ffabc..c8db78610681336c8f03c060a6f6f3a353d69027 100644 (file)
@@ -1,3 +1,4 @@
+// run-rustfix
 struct X {
     x: String,
 }
@@ -10,7 +11,7 @@ fn drop(&mut self) {
 
 fn unwrap(x: X) -> String {
     let X { x: y } = x; //~ ERROR cannot move out of type
-    y
+    y.to_string()
 }
 
 fn main() {
index cda81d136699561c954b6ac95dbeee126a2d2be8..596ad4bf784bb531187d7b9c159925926fd2ef97 100644 (file)
@@ -1,11 +1,16 @@
 error[E0509]: cannot move out of type `X`, which implements the `Drop` trait
-  --> $DIR/disallowed-deconstructing-destructing-struct-let.rs:12:22
+  --> $DIR/disallowed-deconstructing-destructing-struct-let.rs:13:22
    |
 LL |     let X { x: y } = x;
    |                -     ^ cannot move out of here
    |                |
    |                data moved here
    |                move occurs because `y` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     let X { x: ref y } = x;
+   |                +++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.fixed b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.fixed
new file mode 100644 (file)
index 0000000..c8a451e
--- /dev/null
@@ -0,0 +1,19 @@
+// run-rustfix
+struct X {
+    x: String,
+}
+
+impl Drop for X {
+    fn drop(&mut self) {
+        println!("value: {}", self.x);
+    }
+}
+
+fn main() {
+    let x = X { x: "hello".to_string() };
+
+    match x {
+    //~^ ERROR cannot move out of type `X`, which implements the `Drop` trait
+        X { x: ref y } => println!("contents: {}", y)
+    }
+}
index 70cdd6446c8d987b1eef6a1676e6fc610ec3224c..e32a4dd44114963a94d804bc19bb6f20937675d7 100644 (file)
@@ -1,5 +1,5 @@
 error[E0509]: cannot move out of type `X`, which implements the `Drop` trait
-  --> $DIR/disallowed-deconstructing-destructing-struct-match.rs:14:11
+  --> $DIR/disallowed-deconstructing-destructing-struct-match.rs:15:11
    |
 LL |     match x {
    |           ^ cannot move out of here
@@ -9,6 +9,11 @@ LL |         X { x: y } => println!("contents: {}", y)
    |                |
    |                data moved here
    |                move occurs because `y` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         X { x: ref y } => println!("contents: {}", y)
+   |                +++
 
 error: aborting due to previous error
 
index 42925cfed5507f2ec6cc2e3b8fa4dc79eb20003d..87560c4c79735a9d83508be7d61b2e77a40c7893 100644 (file)
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/disambiguate-identical-names.rs:13:10
    |
 LL |     test(&v);
-   |     ---- ^^ expected struct `std::vec::Vec`, found struct `HashMap`
+   |     ---- ^^ expected struct `Vec`, found struct `HashMap`
    |     |
    |     arguments to this function are incorrect
    |
diff --git a/src/test/ui/drop/issue-21486.rs b/src/test/ui/drop/issue-21486.rs
new file mode 100644 (file)
index 0000000..46d6ccd
--- /dev/null
@@ -0,0 +1,77 @@
+// run-pass
+#![allow(unreachable_code)]
+// Issue #21486: Make sure that all structures are dropped, even when
+// created via FRU and control-flow breaks in the middle of
+// construction.
+
+use std::sync::atomic::{Ordering, AtomicUsize};
+
+#[derive(Debug)]
+struct Noisy(u8);
+impl Drop for Noisy {
+    fn drop(&mut self) {
+        // println!("splat #{}", self.0);
+        event(self.0);
+    }
+}
+
+#[allow(dead_code)]
+#[derive(Debug)]
+struct Foo { n0: Noisy, n1: Noisy }
+impl Foo {
+    fn vals(&self) -> (u8, u8) { (self.n0.0, self.n1.0) }
+}
+
+fn leak_1_ret() -> Foo {
+    let _old_foo = Foo { n0: Noisy(1), n1: Noisy(2) };
+    Foo { n0: { return Foo { n0: Noisy(3), n1: Noisy(4) } },
+          .._old_foo
+    };
+}
+
+fn leak_2_ret() -> Foo {
+    let _old_foo = Foo { n0: Noisy(1), n1: Noisy(2) };
+    Foo { n1: { return Foo { n0: Noisy(3), n1: Noisy(4) } },
+          .._old_foo
+    };
+}
+
+// In this case, the control flow break happens *before* we construct
+// `Foo(Noisy(1),Noisy(2))`, so there should be no record of it in the
+// event log.
+fn leak_3_ret() -> Foo {
+    let _old_foo = || Foo { n0: Noisy(1), n1: Noisy(2) };
+    Foo { n1: { return Foo { n0: Noisy(3), n1: Noisy(4) } },
+          .._old_foo()
+    };
+}
+
+pub fn main() {
+    reset_log();
+    assert_eq!(leak_1_ret().vals(), (3,4));
+    assert_eq!(0x01_02_03_04, event_log());
+
+    reset_log();
+    assert_eq!(leak_2_ret().vals(), (3,4));
+    assert_eq!(0x01_02_03_04, event_log());
+
+    reset_log();
+    assert_eq!(leak_3_ret().vals(), (3,4));
+    assert_eq!(0x03_04, event_log());
+}
+
+static LOG: AtomicUsize = AtomicUsize::new(0);
+
+fn reset_log() {
+    LOG.store(0, Ordering::SeqCst);
+}
+
+fn event_log() -> usize {
+    LOG.load(Ordering::SeqCst)
+}
+
+fn event(tag: u8) {
+    let old_log = LOG.load(Ordering::SeqCst);
+    let new_log = (old_log << 8) + tag as usize;
+    LOG.store(new_log, Ordering::SeqCst);
+}
index c447e2f7987cc869c64127a8e984e2ad3f55a8c9..3e39d15f9b0cd3e665c7ab133de94995f189314c 100644 (file)
@@ -8,3 +8,4 @@ LL |     let ft =
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0320`.
index cd4706dd903f41612be335cb2259a38f6978008c..dbb74354471385a053ebb957dc187ca2064afea0 100644 (file)
@@ -8,3 +8,4 @@ LL |     let ft =
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0320`.
index 18cd1b6cd413ba42b0d1e9dd79ebe194df12cc94..deaf116b647afe421a327ecc5c7472225f21a87c 100644 (file)
@@ -16,3 +16,4 @@ LL |         Some(Wrapper::Simple::<u32>);
 
 error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0320`.
index 727f4d843033fd132349d2571fffd4fd812420e3..8d0a82b707ddaa07ffcebd0df4cc2b9bd60b1227 100644 (file)
@@ -9,9 +9,6 @@ LL |     let _x: Box<str> = Box::new(*"hello world");
    = help: the trait `Sized` is not implemented for `str`
 note: required by a bound in `Box::<T>::new`
   --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
-   |
-LL | impl<T> Box<T> {
-   |      ^ required by this bound in `Box::<T>::new`
 
 error[E0277]: the size for values of type `[isize]` cannot be known at compilation time
   --> $DIR/dst-rvalue.rs:8:37
@@ -24,9 +21,6 @@ LL |     let _x: Box<[isize]> = Box::new(*array);
    = help: the trait `Sized` is not implemented for `[isize]`
 note: required by a bound in `Box::<T>::new`
   --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
-   |
-LL | impl<T> Box<T> {
-   |      ^ required by this bound in `Box::<T>::new`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/dyn-star/dyn-to-rigid.rs b/src/test/ui/dyn-star/dyn-to-rigid.rs
new file mode 100644 (file)
index 0000000..e80ee15
--- /dev/null
@@ -0,0 +1,11 @@
+#![feature(dyn_star)]
+#![allow(incomplete_features)]
+
+trait Tr {}
+
+fn f(x: dyn* Tr) -> usize {
+    x as usize
+    //~^ ERROR casting `(dyn* Tr + 'static)` as `usize` is invalid
+}
+
+fn main() {}
diff --git a/src/test/ui/dyn-star/dyn-to-rigid.stderr b/src/test/ui/dyn-star/dyn-to-rigid.stderr
new file mode 100644 (file)
index 0000000..588e6d9
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0606]: casting `(dyn* Tr + 'static)` as `usize` is invalid
+  --> $DIR/dyn-to-rigid.rs:7:5
+   |
+LL |     x as usize
+   |     ^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0606`.
index e7c5918629bdc35f71dca040e4138e2af5270043..a3f4d21ca94bd882f67d9fd074e2ecbf9fac18bb 100644 (file)
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/no-implicit-dyn-star.rs:6:48
    |
 LL |     dyn_star_foreign::require_dyn_star_display(1usize);
-   |     ------------------------------------------ ^^^^^^ expected trait object `dyn std::fmt::Display`, found `usize`
+   |     ------------------------------------------ ^^^^^^ expected trait object `dyn Display`, found `usize`
    |     |
    |     arguments to this function are incorrect
    |
index e1a7a02a56869ad056ca3a15f05c57805b31c2eb..0e580aedeaa921e7fd548624dc075a660864600d 100644 (file)
@@ -100,22 +100,22 @@ help: a unit struct with a similar name exists
 LL |     let xe1 = XEmpty2();
    |               ~~~~~~~
 
-error[E0599]: no variant or associated item named `Empty3` found for enum `empty_struct::XE` in the current scope
+error[E0599]: no variant or associated item named `Empty3` found for enum `XE` in the current scope
   --> $DIR/empty-struct-braces-expr.rs:25:19
    |
 LL |     let xe3 = XE::Empty3;
    |                   ^^^^^^
    |                   |
-   |                   variant or associated item not found in `empty_struct::XE`
+   |                   variant or associated item not found in `XE`
    |                   help: there is a variant with a similar name: `XEmpty3`
 
-error[E0599]: no variant or associated item named `Empty3` found for enum `empty_struct::XE` in the current scope
+error[E0599]: no variant or associated item named `Empty3` found for enum `XE` in the current scope
   --> $DIR/empty-struct-braces-expr.rs:26:19
    |
 LL |     let xe3 = XE::Empty3();
    |                   ^^^^^^
    |                   |
-   |                   variant or associated item not found in `empty_struct::XE`
+   |                   variant or associated item not found in `XE`
    |                   help: there is a variant with a similar name: `XEmpty3`
 
 error[E0599]: no variant named `Empty1` found for enum `empty_struct::XE`
index 6f5bb4309c350e77fb6160671bab8620e0eff6c7..e829bac196f7962b27bb1ef0554b7717356d0879 100644 (file)
@@ -6,15 +6,12 @@ LL |     match x { }
    |
 note: `Option<i32>` defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
    |
-LL | pub enum Option<T> {
-   | ------------------
-...
-LL |     None,
-   |     ^^^^ not covered
-...
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^ not covered
+   = note: not covered
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
+   |
+   = note: not covered
    = note: the matched value is of type `Option<i32>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
index de8e6bac486c1238b985e7b76b0c5ddcd1d59722..0f179259356d50430ed09f38bf96f01e2762ed25 100644 (file)
@@ -8,12 +8,9 @@ LL |     let Some(y) = x;
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
 note: `Option<i32>` defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
    |
-LL | pub enum Option<T> {
-   | ------------------
-...
-LL |     None,
-   |     ^^^^ not covered
+   = note: not covered
    = note: the matched value is of type `Option<i32>`
 help: you might want to use `if let` to ignore the variant that isn't matched
    |
index f331d0142260e92c0d3447521274bb856d68117b..4f6abb22ab2f03f9ef63d1e81d1cb8669c4f49fb 100644 (file)
@@ -6,9 +6,6 @@ LL | fn foo<F: Fn<i32>>(f: F) -> F::Output { f(3) }
    |
 note: required by a bound in `Fn`
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   |                    ^^^^^ required by this bound in `Fn`
 
 error: aborting due to previous error
 
index 49a4d984af9eb6143418ea31f0bf55e6f02fc9e7..451a683ac8a6effeec6de3067304913763e77885 100644 (file)
@@ -5,7 +5,7 @@ LL | impl<T> Foo for T where Bar<T>: Foo {}
    |                                 ^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`E0275`)
-note: required for `Bar<Bar<Bar<Bar<Bar<Bar<...>>>>>>` to implement `Foo`
+note: required for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<...>>>>>>>>>>>>>>>>>>>>>` to implement `Foo`
   --> $DIR/E0275.rs:6:9
    |
 LL | impl<T> Foo for T where Bar<T>: Foo {}
index d01aa3617c764c1fe9f0c95b65a69bf689c59dc1..892d3a81f27f9543e5b87663e64dcb3e2894cb21 100644 (file)
@@ -6,8 +6,8 @@ LL |     let x = "hello".chars().rev().collect();
    |
 help: consider giving `x` an explicit type
    |
-LL |     let x: _ = "hello".chars().rev().collect();
-   |          +++
+LL |     let x: Vec<_> = "hello".chars().rev().collect();
+   |          ++++++++
 
 error: aborting due to previous error
 
index 693b079238d71d47f0a53b6a9a6aeaad83ab2efb..903422f3b9b8a59ba9b02f526ce33cd634bde089 100644 (file)
@@ -6,12 +6,9 @@ LL |     for Some(x) in xs {}
    |
 note: `Option<i32>` defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
    |
-LL | pub enum Option<T> {
-   | ------------------
-...
-LL |     None,
-   |     ^^^^ not covered
+   = note: not covered
    = note: the matched value is of type `Option<i32>`
 
 error: aborting due to previous error
index 9687eca61fab0b5d16a1968fda5f18defde0bfd9..fa4b91cacef7261c169b3692128daa38199f88af 100644 (file)
@@ -59,7 +59,7 @@ note: required by a bound in `bfnr`
    |
 LL |     fn bfnr<U, V: Baz<U>, W: Fn()>(y: T) {
    |                              ^^^^ required by this bound in `bfnr`
-help: consider specifying the type arguments in the function call
+help: consider specifying the generic arguments
    |
 LL |     bfnr::<U, V, W>(x);
    |         +++++++++++
index ce8d1ef03493c277c960ec783ee3da0f1e1d2697..03630f38987e23cc95304050b8b4b7105373c89a 100644 (file)
@@ -7,7 +7,7 @@ LL |     x.borrow().nothing_is_true();
    |     |          value moved due to this method call
    |     move occurs because value has type `TheDarkKnight`, which does not implement the `Copy` trait
    |
-note: this function takes ownership of the receiver `self`, which moves value
+note: `TheDarkKnight::nothing_is_true` takes ownership of the receiver `self`, which moves value
   --> $DIR/E0507.rs:6:24
    |
 LL |     fn nothing_is_true(self) {}
index b69d7743b6c2c98839dde8ad4ea8eb2a6f65a033..208ba30729f8b31b97c9b2860196801ff6f2c646 100644 (file)
@@ -6,7 +6,11 @@ LL |     let _value = array[0];
    |                  |
    |                  cannot move out of here
    |                  move occurs because `array[_]` has type `NonCopy`, which does not implement the `Copy` trait
-   |                  help: consider borrowing here: `&array[0]`
+   |
+help: consider borrowing here
+   |
+LL |     let _value = &array[0];
+   |                  +
 
 error: aborting due to previous error
 
index 5e7b56dcd372a7d257768702ed40eec12f72f88f..df2d3b0d311c93652b67f3c9b67418fddc672971 100644 (file)
@@ -6,7 +6,11 @@ LL |     let _value = array[0];
    |                  |
    |                  cannot move out of here
    |                  move occurs because `array[_]` has type `NonCopy`, which does not implement the `Copy` trait
-   |                  help: consider borrowing here: `&array[0]`
+   |
+help: consider borrowing here
+   |
+LL |     let _value = &array[0];
+   |                  +
 
 error: aborting due to previous error
 
index cbfbc3ccf6a879c2e95cc0c262e79b8877a7042e..c00d9142e750559552589fb6881319869969c50c 100644 (file)
@@ -6,7 +6,11 @@ LL |     let fancy_field = drop_struct.fancy;
    |                       |
    |                       cannot move out of here
    |                       move occurs because `drop_struct.fancy` has type `FancyNum`, which does not implement the `Copy` trait
-   |                       help: consider borrowing here: `&drop_struct.fancy`
+   |
+help: consider borrowing here
+   |
+LL |     let fancy_field = &drop_struct.fancy;
+   |                       +
 
 error: aborting due to previous error
 
index f68c0e7d220f369d4409d59e26baa99ecd954b7d..fc025a3fca2bfc47b4df9629ee8145e907878550 100644 (file)
@@ -37,8 +37,8 @@ LL |     inner::MyTrait::my_fn();
    |
 help: use the fully-qualified path to the only available implementation
    |
-LL |     inner::<MyStruct as MyTrait>::my_fn();
-   |            ++++++++++++        +
+LL |     <MyStruct as inner::MyTrait>::my_fn();
+   |     ++++++++++++               +
 
 error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type
   --> $DIR/E0790.rs:30:13
@@ -51,8 +51,8 @@ LL |     let _ = inner::MyTrait::MY_ASSOC_CONST;
    |
 help: use the fully-qualified path to the only available implementation
    |
-LL |     let _ = inner::<MyStruct as MyTrait>::MY_ASSOC_CONST;
-   |                    ++++++++++++        +
+LL |     let _ = <MyStruct as inner::MyTrait>::MY_ASSOC_CONST;
+   |             ++++++++++++               +
 
 error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
   --> $DIR/E0790.rs:50:5
index 43122c13efba88cdca97cd3f0176bf6d082a20f7..fe9956b70bdd75f3e9cb374adbb589cde91d2e50 100644 (file)
@@ -41,11 +41,8 @@ note: an implementation of `Not` might be missing for `Question`
    |
 LL | enum Question {
    | ^^^^^^^^^^^^^ must implement `Not`
-note: the following trait must be implemented
+note: the trait `Not` must be implemented
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL | pub trait Not {
-   | ^^^^^^^^^^^^^
 
 error[E0604]: only `u8` can be cast as `char`, not `u32`
   --> $DIR/error-festival.rs:25:5
index 759d79493a9cf6e89803649b6d4676be1605b5df..2f9d10d70a2fea087ef955ca6a2ad9e22dcb4108 100644 (file)
@@ -14,7 +14,7 @@ LL |       let p = Some(45).and_then({
 LL | |
 LL | |         |x| println!("doubling {}", x);
 LL | |         Some(x * 2)
-   | |         ----------- this tail expression is of type `std::option::Option<_>`
+   | |         ----------- this tail expression is of type `Option<_>`
 LL | |
 LL | |     });
    | |_____^ expected an `FnOnce<({integer},)>` closure, found `Option<_>`
@@ -22,9 +22,6 @@ LL | |     });
    = help: the trait `FnOnce<({integer},)>` is not implemented for `Option<_>`
 note: required by a bound in `Option::<T>::and_then`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |         F: ~const FnOnce(T) -> Option<U>,
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Option::<T>::and_then`
 
 error: aborting due to 2 previous errors
 
index 5ced344f13f38b510154bea9a586113f923a3fe8..e253e4791e8bd095b8941ffc4ce6f5a3f47e20fa 100644 (file)
@@ -8,12 +8,9 @@ LL |     let Ok(_x) = foo();
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
 note: `Result<u32, !>` defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
+  ::: $SRC_DIR/core/src/result.rs:LL:COL
    |
-LL | pub enum Result<T, E> {
-   | ---------------------
-...
-LL |     Err(#[stable(feature = "rust1", since = "1.0.0")] E),
-   |     ^^^ not covered
+   = note: not covered
    = note: the matched value is of type `Result<u32, !>`
 help: you might want to use `if let` to ignore the variant that isn't matched
    |
index c485bc5c3ab908db36abe89bbd0ba364828cb2c5..760dcb615c87903d522d89eb322e47139b919b82 100644 (file)
@@ -3,12 +3,18 @@ error[E0562]: `impl Trait` only allowed in function and inherent method return t
    |
 LL | fn f() -> impl Fn() -> impl Sized { || () }
    |                        ^^^^^^^^^^
+   |
+   = note: see issue #99697 <https://github.com/rust-lang/rust/issues/99697> for more information
+   = help: add `#![feature(impl_trait_in_fn_trait_return)]` to the crate attributes to enable
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return
   --> $DIR/feature-gate-impl_trait_in_fn_trait_return.rs:3:32
    |
 LL | fn g() -> &'static dyn Fn() -> impl Sized { &|| () }
    |                                ^^^^^^^^^^
+   |
+   = note: see issue #99697 <https://github.com/rust-lang/rust/issues/99697> for more information
+   = help: add `#![feature(impl_trait_in_fn_trait_return)]` to the crate attributes to enable
 
 error: aborting due to 2 previous errors
 
index 15b8d442aeb9a79a7017a0e4a63ad5633a7463ce..505f31ec6388d1d2bf4ce3a8b50ab77206527412 100644 (file)
@@ -1,5 +1,5 @@
 extern "C" {
-    #[linkage = "extern_weak"] static foo: isize;
+    #[linkage = "extern_weak"] static foo: *mut isize;
     //~^ ERROR: the `linkage` attribute is experimental and not portable
 }
 
index 3e5b79bfd417687e110bcc4dac046f347beb722e..a1c73e555ef7a35689004863f8bdf29cfc38d3ed 100644 (file)
@@ -1,7 +1,7 @@
 error[E0658]: the `linkage` attribute is experimental and not portable across platforms
   --> $DIR/feature-gate-linkage.rs:2:5
    |
-LL |     #[linkage = "extern_weak"] static foo: isize;
+LL |     #[linkage = "extern_weak"] static foo: *mut isize;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #29603 <https://github.com/rust-lang/rust/issues/29603> for more information
index 9b868ed7a9e93868b712ac46ca19482e99839947..c04e57843d4b21f4d16e5205630273d4f199cc37 100644 (file)
@@ -1,5 +1,5 @@
+#![allow(unused, bare_trait_objects)]
 #[repr(align(256))]
-#[allow(dead_code)]
 struct A {
     v: u8,
 }
@@ -14,13 +14,17 @@ fn foo(&self) {
     }
 }
 
-fn foo(x: dyn Foo) {
-    //~^ ERROR [E0277]
+fn foo(x: dyn Foo) { //~ ERROR [E0277]
     x.foo()
 }
 
+fn bar(x: Foo) { //~ ERROR [E0277]
+    x.foo()
+}
+
+fn qux(_: [()]) {} //~ ERROR [E0277]
+
 fn main() {
     let x: Box<dyn Foo> = Box::new(A { v: 22 });
-    foo(*x);
-    //~^ ERROR [E0277]
+    foo(*x); //~ ERROR [E0277]
 }
index 0f7520ef7f8a95a80644466eedf36a0a5902a143..92c71392672e197537c6a72525b9059a31c19852 100644 (file)
@@ -6,13 +6,47 @@ LL | fn foo(x: dyn Foo) {
    |
    = help: the trait `Sized` is not implemented for `(dyn Foo + 'static)`
    = help: unsized fn params are gated as an unstable feature
+help: you can use `impl Trait` as the argument type
+   |
+LL | fn foo(x: impl Foo) {
+   |           ~~~~
 help: function arguments must have a statically known size, borrowed types always have a known size
    |
 LL | fn foo(x: &dyn Foo) {
    |           +
 
 error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time
-  --> $DIR/feature-gate-unsized_fn_params.rs:24:9
+  --> $DIR/feature-gate-unsized_fn_params.rs:21:8
+   |
+LL | fn bar(x: Foo) {
+   |        ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `(dyn Foo + 'static)`
+   = help: unsized fn params are gated as an unstable feature
+help: you can use `impl Trait` as the argument type
+   |
+LL | fn bar(x: impl Foo) {
+   |           ++++
+help: function arguments must have a statically known size, borrowed types always have a known size
+   |
+LL | fn bar(x: &Foo) {
+   |           +
+
+error[E0277]: the size for values of type `[()]` cannot be known at compilation time
+  --> $DIR/feature-gate-unsized_fn_params.rs:25:8
+   |
+LL | fn qux(_: [()]) {}
+   |        ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[()]`
+   = 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 | fn qux(_: &[()]) {}
+   |           +
+
+error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time
+  --> $DIR/feature-gate-unsized_fn_params.rs:29:9
    |
 LL |     foo(*x);
    |         ^^ doesn't have a size known at compile-time
@@ -21,6 +55,6 @@ LL |     foo(*x);
    = note: all function arguments must have a statically known size
    = help: unsized fn params are gated as an unstable feature
 
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
index c4507843e366e06896824d284114ac97951075ed..9aeeb88cf04f2befd08f101afdb57860769e220d 100644 (file)
@@ -6,6 +6,10 @@ LL | fn f(f: dyn FnOnce()) {}
    |
    = help: the trait `Sized` is not implemented for `(dyn FnOnce() + 'static)`
    = help: unsized fn params are gated as an unstable feature
+help: you can use `impl Trait` as the argument type
+   |
+LL | fn f(f: impl FnOnce()) {}
+   |         ~~~~
 help: function arguments must have a statically known size, borrowed types always have a known size
    |
 LL | fn f(f: &dyn FnOnce()) {}
index 1b595a50e998494085ffe416afd18889946efa12..a8a2a47fe46e1f6ed7a478b9f99d3e9d1167dddf 100644 (file)
@@ -309,9 +309,6 @@ LL |     println!("{} {:.*} {}", 1, 3.2, 4);
               found reference `&{float}`
 note: associated function defined here
   --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-   |
-LL |     pub fn from_usize(x: &usize) -> ArgumentV1<'_> {
-   |            ^^^^^^^^^^
    = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0308]: mismatched types
@@ -327,9 +324,6 @@ LL |     println!("{} {:07$.*} {}", 1, 3.2, 4);
               found reference `&{float}`
 note: associated function defined here
   --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-   |
-LL |     pub fn from_usize(x: &usize) -> ArgumentV1<'_> {
-   |            ^^^^^^^^^^
    = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 38 previous errors
index 0e34f913511a3121913f6f496ee34690384de497..be321c3c5c08f1279e539132933ba9d391027627 100644 (file)
@@ -17,9 +17,6 @@ LL |     format!("{:X}", "3");
    = note: required for `&str` to implement `UpperHex`
 note: required by a bound in `ArgumentV1::<'a>::new_upper_hex`
   --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-   |
-LL |     arg_new!(new_upper_hex, UpperHex);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `ArgumentV1::<'a>::new_upper_hex`
    = note: this error originates in the macro `$crate::__export::format_args` which comes from the expansion of the macro `arg_new` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
index 2296666219eef2fbb284e11e7699db91b4adb20d..463ac7684ecdfea3a73122953e24915249278b66 100644 (file)
@@ -17,11 +17,11 @@ note: `Bar` defines an item `bar`, perhaps you need to implement it
 LL | trait Bar {
    | ^^^^^^^^^
 
-error[E0599]: no method named `bar` found for struct `Arc<[closure@$DIR/fn-help-with-err.rs:22:36: 22:38]>` in the current scope
+error[E0599]: no method named `bar` found for struct `Arc<[closure@fn-help-with-err.rs:22:36]>` in the current scope
   --> $DIR/fn-help-with-err.rs:23:10
    |
 LL |     arc2.bar();
-   |          ^^^ method not found in `Arc<[closure@$DIR/fn-help-with-err.rs:22:36: 22:38]>`
+   |          ^^^ method not found in `Arc<[closure@fn-help-with-err.rs:22:36]>`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `Bar` defines an item `bar`, perhaps you need to implement it
index 7b4d5021325176b33b55008a850a4607c83d1c46..afb39c9e594d17887c8890ca793d7dcad17a3df0 100644 (file)
@@ -6,9 +6,6 @@ LL |     Pin::new(&mut b).resume();
    |
 note: associated function defined here
   --> $SRC_DIR/core/src/ops/generator.rs:LL:COL
-   |
-LL |     fn resume(self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return>;
-   |        ^^^^^^
 help: provide the argument
    |
 LL |     Pin::new(&mut b).resume(());
index ea2a48d13cee62dc4a23d2bedda93ecd411cad73..fb34540d969dae4e9401c2281f0363d93e797038 100644 (file)
@@ -20,9 +20,6 @@ LL |    Pin::new(&mut gen).resume(());
    = help: the trait `Sized` is not implemented for `str`
 note: required by a bound in `GeneratorState`
   --> $SRC_DIR/core/src/ops/generator.rs:LL:COL
-   |
-LL | pub enum GeneratorState<Y, R> {
-   |                         ^ required by this bound in `GeneratorState`
 
 error: aborting due to 2 previous errors
 
index c81cd7e7718ca86f85392142b68bbbde3f5698ae..83ee04d5a6c600c1b66be81974620cbf4545b219 100644 (file)
@@ -8,7 +8,7 @@ note: required by a bound in `foo_defn::Foo::Bar`
   --> $DIR/auxiliary/foo_defn.rs:4:15
    |
 LL |     type Bar: AsRef<()>;
-   |               ^^^^^^^^^ required by this bound in `foo_defn::Foo::Bar`
+   |               ^^^^^^^^^ required by this bound in `Foo::Bar`
 
 error: aborting due to previous error
 
index b4e94cb83f7388c2647df7aaaf46f5205da55069..422ac5484271d519b82c04d253ef709720b9178a 100644 (file)
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `for<'a> &'a mut (): Foo<&'a mut ()>` is not satisfied
-  --> $DIR/issue-101020.rs:31:5
+  --> $DIR/issue-101020.rs:31:22
    |
 LL |     (&mut EmptyIter).consume(());
-   |     ^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
-   |     |
-   |     the trait `for<'a> Foo<&'a mut ()>` is not implemented for `&'a mut ()`
+   |                      ^^^^^^^ the trait `for<'a> Foo<&'a mut ()>` is not implemented for `&'a mut ()`
    |
 note: required for `&'a mut ()` to implement `for<'a> FuncInput<'a, &'a mut ()>`
   --> $DIR/issue-101020.rs:27:20
index 0475eb908a779d0e1174b6be53bd444937013ddf..b48966a1a1ed0c66f351b39ab7e7b8c5de8ddd8e 100644 (file)
@@ -889,11 +889,6 @@ error[E0107]: missing generics for struct `HashMap`
 LL |         type A = HashMap;
    |                  ^^^^^^^ expected at least 2 generic arguments
    |
-note: struct defined here, with at least 2 generic parameters: `K`, `V`
-  --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
-   |
-LL | pub struct HashMap<K, V, S = RandomState> {
-   |            ^^^^^^^ -  -
 help: add missing generic arguments
    |
 LL |         type A = HashMap<K, V>;
@@ -907,11 +902,6 @@ LL |         type B = HashMap<String>;
    |                  |
    |                  expected at least 2 generic arguments
    |
-note: struct defined here, with at least 2 generic parameters: `K`, `V`
-  --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
-   |
-LL | pub struct HashMap<K, V, S = RandomState> {
-   |            ^^^^^^^ -  -
 help: add missing generic argument
    |
 LL |         type B = HashMap<String, V>;
@@ -924,12 +914,6 @@ LL |         type C = HashMap<'static>;
    |                  ^^^^^^^--------- help: remove these generics
    |                  |
    |                  expected 0 lifetime arguments
-   |
-note: struct defined here, with 0 lifetime parameters
-  --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
-   |
-LL | pub struct HashMap<K, V, S = RandomState> {
-   |            ^^^^^^^
 
 error[E0107]: this struct takes at least 2 generic arguments but 0 generic arguments were supplied
   --> $DIR/wrong-number-of-args.rs:318:18
@@ -937,11 +921,6 @@ error[E0107]: this struct takes at least 2 generic arguments but 0 generic argum
 LL |         type C = HashMap<'static>;
    |                  ^^^^^^^ expected at least 2 generic arguments
    |
-note: struct defined here, with at least 2 generic parameters: `K`, `V`
-  --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
-   |
-LL | pub struct HashMap<K, V, S = RandomState> {
-   |            ^^^^^^^ -  -
 help: add missing generic arguments
    |
 LL |         type C = HashMap<'static, K, V>;
@@ -954,12 +933,6 @@ LL |         type D = HashMap<usize, String, char, f64>;
    |                  ^^^^^^^                      --- help: remove this generic argument
    |                  |
    |                  expected at most 3 generic arguments
-   |
-note: struct defined here, with at most 3 generic parameters: `K`, `V`, `S`
-  --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
-   |
-LL | pub struct HashMap<K, V, S = RandomState> {
-   |            ^^^^^^^ -  -  ---------------
 
 error[E0107]: this struct takes at least 2 generic arguments but 0 generic arguments were supplied
   --> $DIR/wrong-number-of-args.rs:328:18
@@ -967,11 +940,6 @@ error[E0107]: this struct takes at least 2 generic arguments but 0 generic argum
 LL |         type E = HashMap<>;
    |                  ^^^^^^^ expected at least 2 generic arguments
    |
-note: struct defined here, with at least 2 generic parameters: `K`, `V`
-  --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
-   |
-LL | pub struct HashMap<K, V, S = RandomState> {
-   |            ^^^^^^^ -  -
 help: add missing generic arguments
    |
 LL |         type E = HashMap<K, V>;
@@ -983,11 +951,6 @@ error[E0107]: missing generics for enum `Result`
 LL |         type A = Result;
    |                  ^^^^^^ expected 2 generic arguments
    |
-note: enum defined here, with 2 generic parameters: `T`, `E`
-  --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   |          ^^^^^^ -  -
 help: add missing generic arguments
    |
 LL |         type A = Result<T, E>;
@@ -1001,11 +964,6 @@ LL |         type B = Result<String>;
    |                  |
    |                  expected 2 generic arguments
    |
-note: enum defined here, with 2 generic parameters: `T`, `E`
-  --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   |          ^^^^^^ -  -
 help: add missing generic argument
    |
 LL |         type B = Result<String, E>;
@@ -1018,12 +976,6 @@ LL |         type C = Result<'static>;
    |                  ^^^^^^--------- help: remove these generics
    |                  |
    |                  expected 0 lifetime arguments
-   |
-note: enum defined here, with 0 lifetime parameters
-  --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   |          ^^^^^^
 
 error[E0107]: this enum takes 2 generic arguments but 0 generic arguments were supplied
   --> $DIR/wrong-number-of-args.rs:342:18
@@ -1031,11 +983,6 @@ error[E0107]: this enum takes 2 generic arguments but 0 generic arguments were s
 LL |         type C = Result<'static>;
    |                  ^^^^^^ expected 2 generic arguments
    |
-note: enum defined here, with 2 generic parameters: `T`, `E`
-  --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   |          ^^^^^^ -  -
 help: add missing generic arguments
    |
 LL |         type C = Result<'static, T, E>;
@@ -1048,12 +995,6 @@ LL |         type D = Result<usize, String, char>;
    |                  ^^^^^^                ---- help: remove this generic argument
    |                  |
    |                  expected 2 generic arguments
-   |
-note: enum defined here, with 2 generic parameters: `T`, `E`
-  --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   |          ^^^^^^ -  -
 
 error[E0107]: this enum takes 2 generic arguments but 0 generic arguments were supplied
   --> $DIR/wrong-number-of-args.rs:352:18
@@ -1061,11 +1002,6 @@ error[E0107]: this enum takes 2 generic arguments but 0 generic arguments were s
 LL |         type E = Result<>;
    |                  ^^^^^^ expected 2 generic arguments
    |
-note: enum defined here, with 2 generic parameters: `T`, `E`
-  --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   |          ^^^^^^ -  -
 help: add missing generic arguments
    |
 LL |         type E = Result<T, E>;
index a6f8563a047851e8a0ea337d02ca329895a881d5..095a1c6af37bcb5eb5946dbab8120bd91e4bca45 100644 (file)
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
 LL |     match [5..4, 99..105, 43..44] {
    |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
 LL |         [_, 99.., _] => {},
-   |             ^^ expected struct `std::ops::Range`, found integer
+   |             ^^ expected struct `Range`, found integer
    |
    = note: expected struct `std::ops::Range<{integer}>`
                 found type `{integer}`
index 4e0102c930da82b7ab86b7bac25a73033f2fe8f6..2ea3205dcd4acef72ba300757f41be06c3f0f11b 100644 (file)
@@ -10,7 +10,7 @@ error[E0308]: mismatched types
 LL |     match [5..4, 99..105, 43..44] {
    |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
 LL |         [_, 99..] => {},
-   |             ^^ expected struct `std::ops::Range`, found integer
+   |             ^^ expected struct `Range`, found integer
    |
    = note: expected struct `std::ops::Range<{integer}>`
                 found type `{integer}`
index 790a1337228d00eaab73825e8d7968032866a4b2..bbdf0c83f6203f073c9ba9f9876b239a5be4924a 100644 (file)
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
 LL |     match [5..4, 99..105, 43..44] {
    |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
 LL |         [..9, 99..100, _] => {},
-   |            ^ expected struct `std::ops::Range`, found integer
+   |            ^ expected struct `Range`, found integer
    |
    = note: expected struct `std::ops::Range<{integer}>`
                 found type `{integer}`
@@ -17,7 +17,7 @@ LL |     match [5..4, 99..105, 43..44] {
 LL |         [..9, 99..100, _] => {},
    |               ^^  --- this is of type `{integer}`
    |               |
-   |               expected struct `std::ops::Range`, found integer
+   |               expected struct `Range`, found integer
    |
    = note: expected struct `std::ops::Range<{integer}>`
                 found type `{integer}`
@@ -28,7 +28,7 @@ error[E0308]: mismatched types
 LL |     match [5..4, 99..105, 43..44] {
    |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
 LL |         [..9, 99..100, _] => {},
-   |               --  ^^^ expected struct `std::ops::Range`, found integer
+   |               --  ^^^ expected struct `Range`, found integer
    |               |
    |               this is of type `{integer}`
    |
diff --git a/src/test/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.rs b/src/test/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.rs
new file mode 100644 (file)
index 0000000..d34b7a2
--- /dev/null
@@ -0,0 +1,16 @@
+// normalize-stderr-test: "long-type-\d+" -> "long-type-hash"
+
+fn id(
+    f: &dyn Fn(u32),
+) -> &dyn Fn(
+    &dyn Fn(
+        &dyn Fn(
+            &dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(u32))))))))),
+        ),
+    ),
+) {
+    f
+    //~^ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.stderr b/src/test/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.stderr
new file mode 100644 (file)
index 0000000..71e196c
--- /dev/null
@@ -0,0 +1,22 @@
+error[E0308]: mismatched types
+  --> $DIR/hang-on-deeply-nested-dyn.rs:12:5
+   |
+LL |   ) -> &dyn Fn(
+   |  ______-
+LL | |     &dyn Fn(
+LL | |         &dyn Fn(
+LL | |             &dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(u32))))))))),
+LL | |         ),
+LL | |     ),
+LL | | ) {
+   | |_- expected `&dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn Fn(u32) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a))` because of return type
+LL |       f
+   |       ^ expected reference, found `u32`
+   |
+   = note: expected reference `&dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a ...) + 'a)) + 'a)) + 'a))`
+           the full type name has been written to '$TEST_BUILD_DIR/higher-rank-trait-bounds/hang-on-deeply-nested-dyn/hang-on-deeply-nested-dyn.long-type-hash.txt'
+              found reference `&dyn Fn(u32)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
index c1e235441d65df68f775e99f1de85b897185d040..0458d2535f2f56ad83eac2b0d3be6ceaaf28c22b 100644 (file)
@@ -1,4 +1,4 @@
-error[E0599]: the method `filterx` exists for struct `Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:34]>`, but its trait bounds were not satisfied
+error[E0599]: the method `filterx` exists for struct `Map<Repeat, [closure@issue-30786.rs:117:27]>`, but its trait bounds were not satisfied
   --> $DIR/issue-30786.rs:118:22
    |
 LL | pub struct Map<S, F> {
@@ -8,7 +8,7 @@ LL | pub struct Map<S, F> {
    | doesn't satisfy `_: StreamExt`
 ...
 LL |     let filter = map.filterx(|x: &_| true);
-   |                      ^^^^^^^ method cannot be called on `Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:34]>` due to unsatisfied trait bounds
+   |                      ^^^^^^^ method cannot be called on `Map<Repeat, [closure@issue-30786.rs:117:27]>` due to unsatisfied trait bounds
    |
 note: the following trait bounds were not satisfied:
       `&'a mut &Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:34]>: Stream`
@@ -19,7 +19,7 @@ note: the following trait bounds were not satisfied:
 LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
    |         ---------     -                          ^^^^^^ unsatisfied trait bound introduced here
 
-error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>`, but its trait bounds were not satisfied
+error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@issue-30786.rs:129:30]>`, but its trait bounds were not satisfied
   --> $DIR/issue-30786.rs:130:24
    |
 LL | pub struct Filter<S, F> {
@@ -29,7 +29,7 @@ LL | pub struct Filter<S, F> {
    | doesn't satisfy `_: StreamExt`
 ...
 LL |     let count = filter.countx();
-   |                        ^^^^^^ method cannot be called on `Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>` due to unsatisfied trait bounds
+   |                        ^^^^^^ method cannot be called due to unsatisfied trait bounds
    |
 note: the following trait bounds were not satisfied:
       `&'a mut &Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>: Stream`
index ab5598e364fc4f522b95e66080a7196a1c0cba93..fdd192f43137067a274ebe008c03d2641a9fad0b 100644 (file)
@@ -30,7 +30,7 @@ LL |     where
 LL |         F: for<'r> T0<'r, (<Self as Ty<'r>>::V,), O = <B as Ty<'r>>::V>,
    |                                                   ^^^^^^^^^^^^^^^^^^^^ required by this bound in `T1::m`
 
-error[E0271]: expected `[closure@$DIR/issue-62203-hrtb-ice.rs:42:16: 42:19]` to be a closure that returns `Unit3`, but it returns `Unit4`
+error[E0271]: expected `[closure@issue-62203-hrtb-ice.rs:42:16]` to be a closure that returns `Unit3`, but it returns `Unit4`
   --> $DIR/issue-62203-hrtb-ice.rs:39:9
    |
 LL |       let v = Unit2.m(
diff --git a/src/test/ui/hygiene/issue-15221.rs b/src/test/ui/hygiene/issue-15221.rs
new file mode 100644 (file)
index 0000000..4b8319a
--- /dev/null
@@ -0,0 +1,16 @@
+// run-pass
+#![allow(path_statements)]
+// pretty-expanded FIXME #23616
+
+macro_rules! inner {
+    ($e:pat ) => ($e)
+}
+
+macro_rules! outer {
+    ($e:pat ) => (inner!($e))
+}
+
+fn main() {
+    let outer!(g1) = 13;
+    g1;
+}
diff --git a/src/test/ui/illegal-sized-bound/mutability-mismatch.rs b/src/test/ui/illegal-sized-bound/mutability-mismatch.rs
new file mode 100644 (file)
index 0000000..deb84f6
--- /dev/null
@@ -0,0 +1,34 @@
+struct MutType;
+
+pub trait MutTrait {
+    fn function(&mut self)
+    where
+        Self: Sized;
+    //~^ this has a `Sized` requirement
+}
+
+impl MutTrait for MutType {
+    fn function(&mut self) {}
+}
+
+struct Type;
+
+pub trait Trait {
+    fn function(&self)
+    where
+        Self: Sized;
+    //~^ this has a `Sized` requirement
+}
+
+impl Trait for Type {
+    fn function(&self) {}
+}
+
+fn main() {
+    (&MutType as &dyn MutTrait).function();
+    //~^ ERROR the `function` method cannot be invoked on a trait object
+    //~| NOTE you need `&mut dyn MutTrait` instead of `&dyn MutTrait`
+    (&mut Type as &mut dyn Trait).function();
+    //~^ ERROR the `function` method cannot be invoked on a trait object
+    //~| NOTE you need `&dyn Trait` instead of `&mut dyn Trait`
+}
diff --git a/src/test/ui/illegal-sized-bound/mutability-mismatch.stderr b/src/test/ui/illegal-sized-bound/mutability-mismatch.stderr
new file mode 100644 (file)
index 0000000..dbbf79a
--- /dev/null
@@ -0,0 +1,24 @@
+error: the `function` method cannot be invoked on a trait object
+  --> $DIR/mutability-mismatch.rs:28:33
+   |
+LL |         Self: Sized;
+   |               ----- this has a `Sized` requirement
+...
+LL |     (&MutType as &dyn MutTrait).function();
+   |                                 ^^^^^^^^
+   |
+   = note: you need `&mut dyn MutTrait` instead of `&dyn MutTrait`
+
+error: the `function` method cannot be invoked on a trait object
+  --> $DIR/mutability-mismatch.rs:31:35
+   |
+LL |         Self: Sized;
+   |               ----- this has a `Sized` requirement
+...
+LL |     (&mut Type as &mut dyn Trait).function();
+   |                                   ^^^^^^^^
+   |
+   = note: you need `&dyn Trait` instead of `&mut dyn Trait`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/illegal-sized-bound/regular.rs b/src/test/ui/illegal-sized-bound/regular.rs
new file mode 100644 (file)
index 0000000..7abd27e
--- /dev/null
@@ -0,0 +1,32 @@
+struct MutType;
+
+pub trait MutTrait {
+    fn function(&mut self)
+    where
+        Self: Sized;
+    //~^ this has a `Sized` requirement
+}
+
+impl MutTrait for MutType {
+    fn function(&mut self) {}
+}
+
+struct Type;
+
+pub trait Trait {
+    fn function(&self)
+    where
+        Self: Sized;
+    //~^ this has a `Sized` requirement
+}
+
+impl Trait for Type {
+    fn function(&self) {}
+}
+
+fn main() {
+    (&mut MutType as &mut dyn MutTrait).function();
+    //~^ ERROR the `function` method cannot be invoked on a trait object
+    (&Type as &dyn Trait).function();
+    //~^ ERROR the `function` method cannot be invoked on a trait object
+}
diff --git a/src/test/ui/illegal-sized-bound/regular.stderr b/src/test/ui/illegal-sized-bound/regular.stderr
new file mode 100644 (file)
index 0000000..7f37441
--- /dev/null
@@ -0,0 +1,20 @@
+error: the `function` method cannot be invoked on a trait object
+  --> $DIR/regular.rs:28:41
+   |
+LL |         Self: Sized;
+   |               ----- this has a `Sized` requirement
+...
+LL |     (&mut MutType as &mut dyn MutTrait).function();
+   |                                         ^^^^^^^^
+
+error: the `function` method cannot be invoked on a trait object
+  --> $DIR/regular.rs:30:27
+   |
+LL |         Self: Sized;
+   |               ----- this has a `Sized` requirement
+...
+LL |     (&Type as &dyn Trait).function();
+   |                           ^^^^^^^^
+
+error: aborting due to 2 previous errors
+
index f90399b6b945888bad12c687d671387595b81093..7f73d5e12d1962a9288eb62d472d632b983b1ae4 100644 (file)
@@ -70,10 +70,6 @@ error[E0746]: return type cannot have an unboxed trait object
 LL | fn bak() -> dyn Trait { unimplemented!() }
    |             ^^^^^^^^^ doesn't have a size known at compile-time
    |
-help: use some type `T` that is `T: Sized` as the return type if all return paths have the same type
-   |
-LL | fn bak() -> T { unimplemented!() }
-   |             ~
 help: use `impl Trait` as the return type if all return paths have the same type but you want to expose only the trait in the signature
    |
 LL | fn bak() -> impl Trait { unimplemented!() }
index 542f02d7ec5673c82ebaf2d95564ec3959b0e739..973b65bfd625a6188cdf5c199dfa31284b5b4dbc 100644 (file)
@@ -46,11 +46,9 @@ error[E0643]: method `hash` has incompatible signature for trait
    |
 LL |     fn hash(&self, hasher: &mut impl Hasher) {}
    |                                 ^^^^^^^^^^^ expected generic parameter, found `impl Trait`
+  --> $SRC_DIR/core/src/hash/mod.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/hash/mod.rs:LL:COL
-   |
-LL |     fn hash<H: Hasher>(&self, state: &mut H);
-   |             - declaration in trait here
+   = note: declaration in trait here
 
 error: aborting due to 4 previous errors
 
index 92e36841b70c208c4387bc1365b7a2d09368a3ec..03cc4c2b93bed3948427b7ae028dd11a4da4e70a 100644 (file)
@@ -7,9 +7,6 @@ LL |     fn nya() -> impl Wf<Vec<[u8]>>;
    = help: the trait `Sized` is not implemented for `[u8]`
 note: required by a bound in `Vec`
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
-   |                ^ required by this bound in `Vec`
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
   --> $DIR/wf-bounds.rs:12:23
index 34f4dc2cef37dd3348af6f125f195abb12ea746d..bc342dc46893b80e02778235fc7437037bb9d406 100644 (file)
@@ -25,7 +25,7 @@ LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
    |
    = note: the following trait bounds were not satisfied:
            `RawImpl<()>: Raw<()>`
-note: the following trait must be implemented
+note: the trait `Raw` must be implemented
   --> $DIR/issue-62742.rs:12:1
    |
 LL | pub trait Raw<T: ?Sized> {
index 09047cdcbe15ca5f8d0b211bfc0075ed8b51d203..7592418fdfd62f412eeef998debec2ea78919c30 100644 (file)
@@ -20,8 +20,8 @@ LL |         |_| true
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |         |_: _| true
-   |           +++
+LL |         |_: /* Type */| true
+   |           ++++++++++++
 
 error: aborting due to 3 previous errors
 
index 34d5c2d61dc41148c07043a0c698f8b8352b7550..f09c14d3df1df216b7a01e75be34e8ab972b70ca 100644 (file)
@@ -4,11 +4,6 @@ error[E0107]: missing generics for struct `Vec`
 LL | fn f<T>(data: &[T]) -> impl Iterator<Item = Vec> {
    |                                             ^^^ expected at least 1 generic argument
    |
-note: struct defined here, with at least 1 generic parameter: `T`
-  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
-   |            ^^^ -
 help: add missing generic argument
    |
 LL | fn f<T>(data: &[T]) -> impl Iterator<Item = Vec<T>> {
index 3d4ae11e5767039ab3659d58f60c79c32545ad86..548c89d0a3871372e87270fd08b5ad3b2e1421a4 100644 (file)
@@ -145,11 +145,11 @@ note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
 LL |     pub trait Bar {
    |     ^^^^^^^^^^^^^
 
-error[E0599]: no method named `method2` found for struct `no_method_suggested_traits::Foo` in the current scope
+error[E0599]: no method named `method2` found for struct `Foo` in the current scope
   --> $DIR/no-method-suggested-traits.rs:50:37
    |
 LL |     no_method_suggested_traits::Foo.method2();
-   |                                     ^^^^^^^ method not found in `no_method_suggested_traits::Foo`
+   |                                     ^^^^^^^ method not found in `Foo`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
@@ -158,11 +158,11 @@ note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
 LL |     pub trait Bar {
    |     ^^^^^^^^^^^^^
 
-error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&no_method_suggested_traits::Foo>>` in the current scope
+error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&Foo>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:52:71
    |
 LL |     std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method2();
-   |                                                                       ^^^^^^^ method not found in `Rc<&mut Box<&no_method_suggested_traits::Foo>>`
+   |                                                                       ^^^^^^^ method not found in `Rc<&mut Box<&Foo>>`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
@@ -171,11 +171,11 @@ note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
 LL |     pub trait Bar {
    |     ^^^^^^^^^^^^^
 
-error[E0599]: no method named `method2` found for enum `no_method_suggested_traits::Bar` in the current scope
+error[E0599]: no method named `method2` found for enum `Bar` in the current scope
   --> $DIR/no-method-suggested-traits.rs:54:40
    |
 LL |     no_method_suggested_traits::Bar::X.method2();
-   |                                        ^^^^^^^ method not found in `no_method_suggested_traits::Bar`
+   |                                        ^^^^^^^ method not found in `Bar`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
@@ -184,11 +184,11 @@ note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
 LL |     pub trait Bar {
    |     ^^^^^^^^^^^^^
 
-error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&no_method_suggested_traits::Bar>>` in the current scope
+error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&Bar>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:56:74
    |
 LL |     std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method2();
-   |                                                                          ^^^^^^^ method not found in `Rc<&mut Box<&no_method_suggested_traits::Bar>>`
+   |                                                                          ^^^^^^^ method not found in `Rc<&mut Box<&Bar>>`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
@@ -255,29 +255,29 @@ error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&usize>>`
 LL |     std::rc::Rc::new(&mut Box::new(&1_usize)).method3();
    |                                               ^^^^^^^ method not found in `Rc<&mut Box<&usize>>`
 
-error[E0599]: no method named `method3` found for struct `no_method_suggested_traits::Foo` in the current scope
+error[E0599]: no method named `method3` found for struct `Foo` in the current scope
   --> $DIR/no-method-suggested-traits.rs:71:37
    |
 LL |     no_method_suggested_traits::Foo.method3();
-   |                                     ^^^^^^^ method not found in `no_method_suggested_traits::Foo`
+   |                                     ^^^^^^^ method not found in `Foo`
 
-error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&no_method_suggested_traits::Foo>>` in the current scope
+error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&Foo>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:72:71
    |
 LL |     std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method3();
-   |                                                                       ^^^^^^^ method not found in `Rc<&mut Box<&no_method_suggested_traits::Foo>>`
+   |                                                                       ^^^^^^^ method not found in `Rc<&mut Box<&Foo>>`
 
-error[E0599]: no method named `method3` found for enum `no_method_suggested_traits::Bar` in the current scope
+error[E0599]: no method named `method3` found for enum `Bar` in the current scope
   --> $DIR/no-method-suggested-traits.rs:74:40
    |
 LL |     no_method_suggested_traits::Bar::X.method3();
-   |                                        ^^^^^^^ method not found in `no_method_suggested_traits::Bar`
+   |                                        ^^^^^^^ method not found in `Bar`
 
-error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&no_method_suggested_traits::Bar>>` in the current scope
+error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&Bar>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:75:74
    |
 LL |     std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method3();
-   |                                                                          ^^^^^^^ method not found in `Rc<&mut Box<&no_method_suggested_traits::Bar>>`
+   |                                                                          ^^^^^^^ method not found in `Rc<&mut Box<&Bar>>`
 
 error: aborting due to 24 previous errors
 
index 3dda5761ada6b34a97ef22bab914c84611f369cf..3ee26f74a787be7424d2f48ad65f0be1e8fb4260 100644 (file)
@@ -15,7 +15,7 @@ LL |     type Foo = impl PartialEq<(Foo, i32)>;
 LL |         fn eq(&self, _other: &(Foo, i32)) -> bool {
    |                              ^^^^^^^^^^^
    |                              |
-   |                              expected struct `a::Bar`, found opaque type
+   |                              expected struct `Bar`, found opaque type
    |                              help: change the parameter type to match the trait: `&(a::Bar, i32)`
    |
    = note: expected fn pointer `fn(&a::Bar, &(a::Bar, i32)) -> _`
@@ -38,7 +38,7 @@ LL |     type Foo = impl PartialEq<(Foo, i32)>;
 LL |         fn eq(&self, _other: &(Bar, i32)) -> bool {
    |                              ^^^^^^^^^^^
    |                              |
-   |                              expected opaque type, found struct `b::Bar`
+   |                              expected opaque type, found struct `Bar`
    |                              help: change the parameter type to match the trait: `&(b::Foo, i32)`
    |
    = note: expected fn pointer `fn(&b::Bar, &(b::Foo, i32)) -> _`
index c31c8840381537217a3ac5273b2561718a1da352..ade479ed1022128a4bef62cabae71c1bccd4d10d 100644 (file)
@@ -24,11 +24,8 @@ LL |         extern crate std as Vec;
 ...
 LL | define_vec!();
    | ------------- in this macro invocation
-note: `Vec` could also refer to the struct defined here
+note: `Vec` could also refer to a struct from prelude
   --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
-   |
-LL |     pub use super::v1::*;
-   |             ^^^^^^^^^^^^
    = note: this error originates in the macro `define_vec` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/imports/issue-26930.rs b/src/test/ui/imports/issue-26930.rs
new file mode 100644 (file)
index 0000000..707e71b
--- /dev/null
@@ -0,0 +1,8 @@
+// check-pass
+
+extern crate core;
+use core as core_export;
+use self::x::*;
+mod x {}
+
+fn main() {}
index 034005697b4343b239e27871028732a1f068c5aa..3db67cdb5370a154642161edc43cd646195c4c84 100644 (file)
@@ -87,7 +87,10 @@ error[E0308]: mismatched types
   --> $DIR/deref-suggestion.rs:37:5
    |
 LL |     assert_eq!(3i32, &3i32);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `&i32`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     expected `i32`, found `&i32`
+   |     expected because this is `i32`
    |
    = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
index 5c52e7bcfab694f5c494fc7a3733be25facadba3..9be18286480113cb04682887824884706c221faf 100644 (file)
@@ -10,10 +10,10 @@ note: required by a bound in `foo`
    |
 LL | fn foo<T, K, W: Default, Z: Default>(t: T, k: K) -> Foo<T, K, W, Z> {
    |                 ^^^^^^^ required by this bound in `foo`
-help: consider specifying the type arguments in the function call
+help: consider giving `foo` an explicit type, where the type for type parameter `W` is specified
    |
-LL |     let foo = foo::<T, K, W, Z>(1, "");
-   |                  ++++++++++++++
+LL |     let foo: Foo<i32, &str, W, Z> = foo(1, "");
+   |            ++++++++++++++++++++++
 
 error[E0283]: type annotations needed for `Bar<i32, &str, Z>`
   --> $DIR/erase-type-params-in-label.rs:5:9
@@ -27,10 +27,10 @@ note: required by a bound in `bar`
    |
 LL | fn bar<T, K, Z: Default>(t: T, k: K) -> Bar<T, K, Z> {
    |                 ^^^^^^^ required by this bound in `bar`
-help: consider specifying the type arguments in the function call
+help: consider giving `bar` an explicit type, where the type for type parameter `Z` is specified
    |
-LL |     let bar = bar::<T, K, Z>(1, "");
-   |                  +++++++++++
+LL |     let bar: Bar<i32, &str, Z> = bar(1, "");
+   |            +++++++++++++++++++
 
 error: aborting due to 2 previous errors
 
index 79bee33280d2e45769cbc0e8a49e28e4d426b034..01b37f2acaa14444d7b043e2d1ab7c31572b7772 100644 (file)
@@ -12,9 +12,6 @@ LL |         .get(&"key".into())
              where T: ?Sized;
 note: required by a bound in `HashMap::<K, V, S>::get`
   --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
-   |
-LL |         K: Borrow<Q>,
-   |            ^^^^^^^^^ required by this bound in `HashMap::<K, V, S>::get`
 help: consider specifying the generic argument
    |
 LL |         .get::<Q>(&"key".into())
index d4eeda07366a8015c2a4c04374f6ee6b4fc32bf7..8eda71ec09bd3bf1410fb293eb00232808ea7508 100644 (file)
@@ -32,8 +32,8 @@ LL |     |x| String::from("x".as_ref());
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |     |x: _| String::from("x".as_ref());
-   |       +++
+LL |     |x: /* Type */| String::from("x".as_ref());
+   |       ++++++++++++
 
 error[E0283]: type annotations needed
   --> $DIR/issue-72690.rs:12:26
index 620c9e110ff6822b9d71151805beca0c365aae53..53b603a47b5516a7d2f6800ed980e593c16bbf0f 100644 (file)
@@ -2,143 +2,648 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/infinite-recursion-const-fn.rs:4:5
    |
 LL |     b()
+   |     ^^^ reached the configured maximum number of stack frames
+   |
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
    |     ^^^
-   |     |
-   |     reached the configured maximum number of stack frames
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-...
-LL |     a()
-   |     ---
-   |     |
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-LL | }
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `ARR::{constant#0}`
+  --> $DIR/infinite-recursion-const-fn.rs:9:18
+   |
 LL | const ARR: [i32; a()] = [5; 6];
-   |                  --- inside `ARR::{constant#0}` at $DIR/infinite-recursion-const-fn.rs:9:18
+   |                  ^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/inline-const/expr-unsafe-err.mir.stderr b/src/test/ui/inline-const/expr-unsafe-err.mir.stderr
new file mode 100644 (file)
index 0000000..1bec41e
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+  --> $DIR/expr-unsafe-err.rs:8:9
+   |
+LL |         require_unsafe();
+   |         ^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/inline-const/expr-unsafe-err.rs b/src/test/ui/inline-const/expr-unsafe-err.rs
new file mode 100644 (file)
index 0000000..adf05d3
--- /dev/null
@@ -0,0 +1,11 @@
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+#![feature(inline_const)]
+const unsafe fn require_unsafe() -> usize { 1 }
+
+fn main() {
+    const {
+        require_unsafe();
+        //~^ ERROR [E0133]
+    }
+}
diff --git a/src/test/ui/inline-const/expr-unsafe-err.thir.stderr b/src/test/ui/inline-const/expr-unsafe-err.thir.stderr
new file mode 100644 (file)
index 0000000..c971e8a
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0133]: call to unsafe function `require_unsafe` is unsafe and requires unsafe function or block
+  --> $DIR/expr-unsafe-err.rs:8:9
+   |
+LL |         require_unsafe();
+   |         ^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/inline-const/expr-unsafe.mir.stderr b/src/test/ui/inline-const/expr-unsafe.mir.stderr
new file mode 100644 (file)
index 0000000..1ab6e42
--- /dev/null
@@ -0,0 +1,14 @@
+warning: unnecessary `unsafe` block
+  --> $DIR/expr-unsafe.rs:12:13
+   |
+LL |             unsafe {}
+   |             ^^^^^^ unnecessary `unsafe` block
+   |
+note: the lint level is defined here
+  --> $DIR/expr-unsafe.rs:4:9
+   |
+LL | #![warn(unused_unsafe)]
+   |         ^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/inline-const/expr-unsafe.rs b/src/test/ui/inline-const/expr-unsafe.rs
new file mode 100644 (file)
index 0000000..d71efd3
--- /dev/null
@@ -0,0 +1,16 @@
+// check-pass
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+#![warn(unused_unsafe)]
+#![feature(inline_const)]
+const unsafe fn require_unsafe() -> usize { 1 }
+
+fn main() {
+    unsafe {
+        const {
+            require_unsafe();
+            unsafe {}
+            //~^ WARNING unnecessary `unsafe` block
+        }
+    }
+}
diff --git a/src/test/ui/inline-const/expr-unsafe.thir.stderr b/src/test/ui/inline-const/expr-unsafe.thir.stderr
new file mode 100644 (file)
index 0000000..4737444
--- /dev/null
@@ -0,0 +1,17 @@
+warning: unnecessary `unsafe` block
+  --> $DIR/expr-unsafe.rs:12:13
+   |
+LL |     unsafe {
+   |     ------ because it's nested under this `unsafe` block
+...
+LL |             unsafe {}
+   |             ^^^^^^ unnecessary `unsafe` block
+   |
+note: the lint level is defined here
+  --> $DIR/expr-unsafe.rs:4:9
+   |
+LL | #![warn(unused_unsafe)]
+   |         ^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/inline-const/pat-unsafe-err.rs b/src/test/ui/inline-const/pat-unsafe-err.rs
new file mode 100644 (file)
index 0000000..e290b43
--- /dev/null
@@ -0,0 +1,17 @@
+// ignore-test This is currently broken
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+#![allow(incomplete_features)]
+#![feature(inline_const_pat)]
+
+const unsafe fn require_unsafe() -> usize { 1 }
+
+fn main() {
+    match () {
+        const {
+            require_unsafe();
+            //~^ ERROR [E0133]
+        } => (),
+    }
+}
diff --git a/src/test/ui/inline-const/pat-unsafe.rs b/src/test/ui/inline-const/pat-unsafe.rs
new file mode 100644 (file)
index 0000000..bcf7f6e
--- /dev/null
@@ -0,0 +1,22 @@
+// ignore-test This is currently broken
+// check-pass
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+#![allow(incomplete_features)]
+#![warn(unused_unsafe)]
+#![feature(inline_const_pat)]
+
+const unsafe fn require_unsafe() -> usize { 1 }
+
+fn main() {
+    unsafe {
+        match () {
+            const {
+                require_unsafe();
+                unsafe {}
+                //~^ WARNING unnecessary `unsafe` block
+            } => (),
+        }
+    }
+}
index 94f41c92598866d4aaef7e8a1162a7de304aa3c9..034d22591b38a582360f86a5367183167019c8c6 100644 (file)
@@ -16,9 +16,6 @@ LL |     catch_unwind(|| { x.set(23); });
    |                  ^^
 note: required by a bound in `catch_unwind`
   --> $SRC_DIR/std/src/panic.rs:LL:COL
-   |
-LL | pub fn catch_unwind<F: FnOnce() -> R + UnwindSafe, R>(f: F) -> Result<R> {
-   |                                        ^^^^^^^^^^ required by this bound in `catch_unwind`
 
 error: aborting due to previous error
 
index 3720528ad4e402b0e4feb3131b1213ee50812ead..fd7d061b6b2e5627459e5ea11968c9539c345ff8 100644 (file)
@@ -37,9 +37,6 @@ LL |     const_eval_select((), 42, 0xDEADBEEF);
    = note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }`
 note: required by a bound in `const_eval_select`
   --> $SRC_DIR/core/src/intrinsics.rs:LL:COL
-   |
-LL |         F: FnOnce<ARG, Output = RET>;
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
 
 error: this argument must be a function item
   --> $DIR/const-eval-select-bad.rs:10:31
@@ -62,9 +59,6 @@ LL |     const_eval_select((), 42, 0xDEADBEEF);
    = note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }`
 note: required by a bound in `const_eval_select`
   --> $SRC_DIR/core/src/intrinsics.rs:LL:COL
-   |
-LL |         G: FnOnce<ARG, Output = RET>,
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
 
 error[E0271]: expected `fn(i32) -> bool {bar}` to be a fn item that returns `i32`, but it returns `bool`
   --> $DIR/const-eval-select-bad.rs:32:34
@@ -76,9 +70,6 @@ LL |     const_eval_select((1,), foo, bar);
    |
 note: required by a bound in `const_eval_select`
   --> $SRC_DIR/core/src/intrinsics.rs:LL:COL
-   |
-LL |         G: FnOnce<ARG, Output = RET>,
-   |                        ^^^^^^^^^^^^ required by this bound in `const_eval_select`
 
 error[E0631]: type mismatch in function arguments
   --> $DIR/const-eval-select-bad.rs:37:32
@@ -95,9 +86,6 @@ LL |     const_eval_select((true,), foo, baz);
               found function signature `fn(i32) -> _`
 note: required by a bound in `const_eval_select`
   --> $SRC_DIR/core/src/intrinsics.rs:LL:COL
-   |
-LL |         F: FnOnce<ARG, Output = RET>;
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
 
 error: this argument must be a `const fn`
   --> $DIR/const-eval-select-bad.rs:42:29
index 6bd9c6a0276f835418eaa0e7966390403e7ec22f..52a5919026463074199f87a216e1f8fc98723f15 100644 (file)
@@ -1,4 +1,4 @@
-error: -Zbranch-protection is only supported on aarch64
+error: `-Zbranch-protection` is only supported on aarch64
 
 error: aborting due to previous error
 
index 4bc4919bc935b2c8a61fc808ae27e1e4292cb068..1d7ec5cba17ca71ebf37a4478771d1836918e2a8 100644 (file)
@@ -3,7 +3,7 @@
 // [BADFLAGS] check-fail
 // [BADFLAGS] needs-llvm-components: aarch64
 // [BADTARGET] compile-flags: --target=x86_64-unknown-linux-gnu -Zbranch-protection=bti
-// [BADTARGET] build-fail
+// [BADTARGET] check-fail
 // [BADTARGET] needs-llvm-components: x86
 
 #![crate_type = "lib"]
index d328cafa00b9345f51bfbaa1b26de8bef76a4355..4600034952b395df64ffb824ea6a3b252be9beae 100644 (file)
@@ -4,7 +4,7 @@ error: invalid argument for `no_sanitize`
 LL | #[no_sanitize(brontosaurus)]
    |               ^^^^^^^^^^^^
    |
-   = note: expected one of: `address`, `cfi`, `hwaddress`, `memory`, `memtag`, `shadow-call-stack`, or `thread`
+   = note: expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/auxiliary/issue-11225-1.rs b/src/test/ui/issues/auxiliary/issue-11225-1.rs
deleted file mode 100644 (file)
index 2c6f899..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-mod inner {
-    pub trait Trait {
-        fn f(&self) { f(); }
-        fn f_ufcs(&self) { f_ufcs(); }
-    }
-
-    impl Trait for isize {}
-
-    fn f() {}
-    fn f_ufcs() {}
-}
-
-pub fn foo<T: inner::Trait>(t: T) {
-    t.f();
-}
-pub fn foo_ufcs<T: inner::Trait>(t: T) {
-    T::f_ufcs(&t);
-}
diff --git a/src/test/ui/issues/auxiliary/issue-11225-2.rs b/src/test/ui/issues/auxiliary/issue-11225-2.rs
deleted file mode 100644 (file)
index 4381f0a..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-use inner::Trait;
-
-mod inner {
-    pub struct Foo;
-    pub trait Trait {
-        fn f(&self);
-        fn f_ufcs(&self);
-    }
-
-    impl Trait for Foo {
-        fn f(&self) { }
-        fn f_ufcs(&self) { }
-    }
-}
-
-pub trait Outer {
-    fn foo<T: Trait>(&self, t: T) { t.f(); }
-    fn foo_ufcs<T: Trait>(&self, t: T) { T::f(&t); }
-}
-
-impl Outer for isize {}
-
-pub fn foo<T: Outer>(t: T) {
-    t.foo(inner::Foo);
-}
-pub fn foo_ufcs<T: Outer>(t: T) {
-    T::foo_ufcs(&t, inner::Foo)
-}
diff --git a/src/test/ui/issues/auxiliary/issue-11225-3.rs b/src/test/ui/issues/auxiliary/issue-11225-3.rs
deleted file mode 100644 (file)
index 266e42a..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-trait PrivateTrait {
-    fn private_trait_method(&self);
-    fn private_trait_method_ufcs(&self);
-}
-
-struct PrivateStruct;
-
-impl PrivateStruct {
-    fn private_inherent_method(&self) { }
-    fn private_inherent_method_ufcs(&self) { }
-}
-
-impl PrivateTrait for PrivateStruct {
-    fn private_trait_method(&self) { }
-    fn private_trait_method_ufcs(&self) { }
-}
-
-#[inline]
-pub fn public_inlinable_function() {
-    PrivateStruct.private_trait_method();
-    PrivateStruct.private_inherent_method();
-}
-
-#[inline]
-pub fn public_inlinable_function_ufcs() {
-    PrivateStruct::private_trait_method(&PrivateStruct);
-    PrivateStruct::private_inherent_method(&PrivateStruct);
-}
index 92f2ccb6544b10c2ba81744c921b4b945fd91d15..30c380152a5e6b88cf871a26dd82e1cf55f3403c 100644 (file)
@@ -55,8 +55,10 @@ error[E0271]: type mismatch resolving `<Demo as TraitWAssocConst>::A == 32`
   --> $DIR/issue-105330.rs:12:11
    |
 LL |     foo::<Demo>()();
-   |           ^^^^ types differ
+   |           ^^^^ expected `32`, found `<Demo as TraitWAssocConst>::A`
    |
+   = note: expected constant `32`
+              found constant `<Demo as TraitWAssocConst>::A`
 note: required by a bound in `foo`
   --> $DIR/issue-105330.rs:11:28
    |
@@ -89,8 +91,10 @@ error[E0271]: type mismatch resolving `<Demo as TraitWAssocConst>::A == 32`
   --> $DIR/issue-105330.rs:19:11
    |
 LL |     foo::<Demo>();
-   |           ^^^^ types differ
+   |           ^^^^ expected `32`, found `<Demo as TraitWAssocConst>::A`
    |
+   = note: expected constant `32`
+              found constant `<Demo as TraitWAssocConst>::A`
 note: required by a bound in `foo`
   --> $DIR/issue-105330.rs:11:28
    |
diff --git a/src/test/ui/issues/issue-11225-1.rs b/src/test/ui/issues/issue-11225-1.rs
deleted file mode 100644 (file)
index d1f2ea5..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// run-pass
-// aux-build:issue-11225-1.rs
-
-// pretty-expanded FIXME #23616
-
-extern crate issue_11225_1 as foo;
-
-pub fn main() {
-    foo::foo(1);
-    foo::foo_ufcs(1);
-}
diff --git a/src/test/ui/issues/issue-11225-2.rs b/src/test/ui/issues/issue-11225-2.rs
deleted file mode 100644 (file)
index d41c754..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// run-pass
-// aux-build:issue-11225-2.rs
-
-// pretty-expanded FIXME #23616
-
-extern crate issue_11225_2 as foo;
-
-pub fn main() {
-    foo::foo(1);
-    foo::foo_ufcs(1);
-}
diff --git a/src/test/ui/issues/issue-11225-3.rs b/src/test/ui/issues/issue-11225-3.rs
deleted file mode 100644 (file)
index e69496b..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// run-pass
-// aux-build:issue-11225-3.rs
-
-// pretty-expanded FIXME #23616
-
-extern crate issue_11225_3;
-
-pub fn main() {
-    issue_11225_3::public_inlinable_function();
-    issue_11225_3::public_inlinable_function_ufcs();
-}
index 3ce659ccd14da3ec29b531edb83eac3fb776910e..7fa06825f0f00c38bccf22c140a3752649cf5368 100644 (file)
@@ -11,6 +11,14 @@ LL |         (&[hd1, ..], &[hd2, ..])
    |            --- ...and here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider borrowing the pattern binding
+   |
+LL |         (&[], &[ref hd, ..]) | (&[hd, ..], &[])
+   |                 +++
+help: consider borrowing the pattern binding
+   |
+LL |         (&[ref hd1, ..], &[hd2, ..])
+   |            +++
 
 error[E0508]: cannot move out of type `[T]`, a non-copy slice
   --> $DIR/issue-12567.rs:2:11
@@ -25,6 +33,14 @@ LL |         (&[hd1, ..], &[hd2, ..])
    |                        --- ...and here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider borrowing the pattern binding
+   |
+LL |         (&[], &[ref hd, ..]) | (&[hd, ..], &[])
+   |                 +++
+help: consider borrowing the pattern binding
+   |
+LL |         (&[hd1, ..], &[ref hd2, ..])
+   |                        +++
 
 error: aborting due to 2 previous errors
 
index a191afd7980c65865392a4367b064fea46a8cff4..f8375d4ef9014ba6e7dcfe0ca100c93ee114a47d 100644 (file)
@@ -9,11 +9,8 @@ note: an implementation of `Not` might be missing for `BytePos`
    |
 LL | pub struct BytePos(pub u32);
    | ^^^^^^^^^^^^^^^^^^ must implement `Not`
-note: the following trait must be implemented
+note: the trait `Not` must be implemented
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL | pub trait Not {
-   | ^^^^^^^^^^^^^
    = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
index 7928b3fba2785fd2105560dd620fcba3316b9464..132e2b101a5ff1d4c207e69fa9e71951f41cb451 100644 (file)
@@ -4,13 +4,6 @@ error[E0107]: missing generics for struct `Box`
 LL | fn fn1(0: Box) {}
    |           ^^^ expected at least 1 generic argument
    |
-note: struct defined here, with at least 1 generic parameter: `T`
-  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
-   |
-LL | pub struct Box<
-   |            ^^^
-LL |     T: ?Sized,
-   |     -
 help: add missing generic argument
    |
 LL | fn fn1(0: Box<T>) {}
diff --git a/src/test/ui/issues/issue-15221.rs b/src/test/ui/issues/issue-15221.rs
deleted file mode 100644 (file)
index 4b8319a..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// run-pass
-#![allow(path_statements)]
-// pretty-expanded FIXME #23616
-
-macro_rules! inner {
-    ($e:pat ) => ($e)
-}
-
-macro_rules! outer {
-    ($e:pat ) => (inner!($e))
-}
-
-fn main() {
-    let outer!(g1) = 13;
-    g1;
-}
index 8524a62a0a42d2cb750114c81087f487b554b2e6..60f5190dbd0d640f790cf33863fdf06bfd1dc9fa 100644 (file)
@@ -5,11 +5,6 @@ LL |     panic!(std::default::Default::default());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `M` declared on the function `begin_panic`
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider specifying the generic argument
-  --> $SRC_DIR/std/src/panic.rs:LL:COL
-   |
-LL |         $crate::rt::begin_panic::<M>($msg)
-   |                                +++++
 
 error: aborting due to previous error
 
index 16678c8c8a9028f655b95231e70b1672a0d75574..81592320a2791b414f88788ba6c2e99c5ce21e5b 100644 (file)
@@ -3,11 +3,9 @@ error[E0573]: expected type, found variant `NoResult`
    |
 LL |     fn new() -> NoResult<MyEnum, String> {
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^
+  --> $SRC_DIR/core/src/result.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   | --------------------- similarly named enum `Result` defined here
+   = note: similarly named enum `Result` defined here
    |
 help: try using the variant's enum
    |
@@ -57,11 +55,9 @@ error[E0573]: expected type, found variant `NoResult`
    |
 LL | fn newer() -> NoResult<foo::MyEnum, String> {
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  --> $SRC_DIR/core/src/result.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   | --------------------- similarly named enum `Result` defined here
+   = note: similarly named enum `Result` defined here
    |
 help: try using the variant's enum
    |
index efaaeeda2fab6798d18b0b99e1f2eee73d8f9597..b37811e19559c3bdc82fe6c1036e2b3f8883040c 100644 (file)
@@ -9,9 +9,6 @@ LL |     (|| Box::new(*(&[0][..])))();
    = help: the trait `Sized` is not implemented for `[{integer}]`
 note: required by a bound in `Box::<T>::new`
   --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
-   |
-LL | impl<T> Box<T> {
-   |      ^ required by this bound in `Box::<T>::new`
 
 error: aborting due to previous error
 
index 28478457b296db68779f5227322583c657f518b9..1669b550a9bafe26442e406d91bb02a980d135e7 100644 (file)
@@ -4,10 +4,6 @@ error[E0746]: return type cannot have an unboxed trait object
 LL |     dyn AbstractRenderer
    |     ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-help: use some type `T` that is `T: Sized` as the return type if all return paths have the same type
-   |
-LL |     T
-   |
 help: use `impl AbstractRenderer` as the return type if all return paths have the same type but you want to expose only the trait in the signature
    |
 LL |     impl AbstractRenderer
index 605ff3829d19a6a70e88f7f83fa22763a3c6e2e4..5e0589eed435d0240aefb3f4eddf4f34506f326e 100644 (file)
@@ -6,8 +6,8 @@ LL |     let x;
    |
 help: consider giving `x` an explicit type
    |
-LL |     let x: _;
-   |          +++
+LL |     let x: /* Type */;
+   |          ++++++++++++
 
 error: aborting due to previous error
 
index 4711a3f3ce07ef57db1388c1320a73036051634d..bbf79366244a01d7381b2d9504b47742bbe86c25 100644 (file)
@@ -5,12 +5,6 @@ LL |     x: Box<'a, isize>
    |        ^^^ -- help: remove this lifetime argument
    |        |
    |        expected 0 lifetime arguments
-   |
-note: struct defined here, with 0 lifetime parameters
-  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
-   |
-LL | pub struct Box<
-   |            ^^^
 
 error: aborting due to previous error
 
index 3f9b3be98517946f728235e3e34d2956ce678b6c..1c5b76fbfc10b1e730ce7c738f264d4d5a05c998 100644 (file)
@@ -1,16 +1,11 @@
 error[E0277]: the trait bound `X: Ord` is not satisfied
-  --> $DIR/issue-20162.rs:5:5
+  --> $DIR/issue-20162.rs:5:7
    |
 LL |     b.sort();
-   |     ^ ---- required by a bound introduced by this call
-   |     |
-   |     the trait `Ord` is not implemented for `X`
+   |       ^^^^ the trait `Ord` is not implemented for `X`
    |
 note: required by a bound in `slice::<impl [T]>::sort`
   --> $SRC_DIR/alloc/src/slice.rs:LL:COL
-   |
-LL |         T: Ord,
-   |            ^^^ required by this bound in `slice::<impl [T]>::sort`
 help: consider annotating `X` with `#[derive(Ord)]`
    |
 LL | #[derive(Ord)]
index 91509ceace8cb3406806a91d1c75c54b504b47af..78df445972c94d34102044a095a0c10edc600cb4 100644 (file)
@@ -14,7 +14,7 @@ LL | impl<T> Foo for T where NoData<T>: Foo {
    |                                    ^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`)
-note: required for `NoData<NoData<NoData<NoData<NoData<NoData<...>>>>>>` to implement `Foo`
+note: required for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<...>>>>>>>>>>>>>` to implement `Foo`
   --> $DIR/issue-20413.rs:9:9
    |
 LL | impl<T> Foo for T where NoData<T>: Foo {
@@ -30,13 +30,13 @@ LL | impl<T> Bar for T where EvenLessData<T>: Baz {
    |                                          ^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`)
-note: required for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<...>>>>>>` to implement `Bar`
+note: required for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<...>>>>>>>` to implement `Bar`
   --> $DIR/issue-20413.rs:28:9
    |
 LL | impl<T> Bar for T where EvenLessData<T>: Baz {
    |         ^^^     ^
    = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt'
-note: required for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<...>>>>>>` to implement `Baz`
+note: required for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<...>>>>>>>` to implement `Baz`
   --> $DIR/issue-20413.rs:35:9
    |
 LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
@@ -52,13 +52,13 @@ LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
    |                                          ^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`)
-note: required for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<...>>>>>>` to implement `Baz`
+note: required for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<...>>>>>>>` to implement `Baz`
   --> $DIR/issue-20413.rs:35:9
    |
 LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
    |         ^^^     ^
    = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt'
-note: required for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<...>>>>>>` to implement `Bar`
+note: required for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<...>>>>>>>` to implement `Bar`
   --> $DIR/issue-20413.rs:28:9
    |
 LL | impl<T> Bar for T where EvenLessData<T>: Baz {
index 9d3bb8b924d6161c3d2e781ef459eee6c0ab7f27..3ae952546a62dd0d652b032fa346917fca174a08 100644 (file)
@@ -7,9 +7,6 @@ LL |     fn iceman(c: Vec<[i32]>) {}
    = help: the trait `Sized` is not implemented for `[i32]`
 note: required by a bound in `Vec`
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
-   |                ^ required by this bound in `Vec`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-21058.rs b/src/test/ui/issues/issue-21058.rs
deleted file mode 100644 (file)
index 6facf0b..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-// run-pass
-#![allow(dead_code)]
-
-use std::fmt::Debug;
-
-struct NT(str);
-struct DST { a: u32, b: str }
-
-macro_rules! check {
-    (val: $ty_of:expr, $expected:expr) => {
-        assert_eq!(type_name_of_val($ty_of), $expected);
-    };
-    ($ty:ty, $expected:expr) => {
-        assert_eq!(std::any::type_name::<$ty>(), $expected);
-    };
-}
-
-fn main() {
-    // type_name should support unsized types
-    check!([u8], "[u8]");
-    check!(str, "str");
-    check!(dyn Send, "dyn core::marker::Send");
-    check!(NT, "issue_21058::NT");
-    check!(DST, "issue_21058::DST");
-    check!(&i32, "&i32");
-    check!(&'static i32, "&i32");
-    check!((i32, u32), "(i32, u32)");
-    check!(val: foo(), "issue_21058::Foo");
-    check!(val: Foo::new, "issue_21058::Foo::new");
-    check!(val:
-        <Foo as Debug>::fmt,
-        "<issue_21058::Foo as core::fmt::Debug>::fmt"
-    );
-    check!(val: || {}, "issue_21058::main::{{closure}}");
-    bar::<i32>();
-}
-
-trait Trait {
-    type Assoc;
-}
-
-impl Trait for i32 {
-    type Assoc = String;
-}
-
-fn bar<T: Trait>() {
-    check!(T::Assoc, "alloc::string::String");
-    check!(T, "i32");
-}
-
-fn type_name_of_val<T>(_: T) -> &'static str {
-    std::any::type_name::<T>()
-}
-
-#[derive(Debug)]
-struct Foo;
-
-impl Foo {
-    fn new() -> Self { Foo }
-}
-
-fn foo() -> impl Debug {
-    Foo
-}
diff --git a/src/test/ui/issues/issue-21486.rs b/src/test/ui/issues/issue-21486.rs
deleted file mode 100644 (file)
index 46d6ccd..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-// run-pass
-#![allow(unreachable_code)]
-// Issue #21486: Make sure that all structures are dropped, even when
-// created via FRU and control-flow breaks in the middle of
-// construction.
-
-use std::sync::atomic::{Ordering, AtomicUsize};
-
-#[derive(Debug)]
-struct Noisy(u8);
-impl Drop for Noisy {
-    fn drop(&mut self) {
-        // println!("splat #{}", self.0);
-        event(self.0);
-    }
-}
-
-#[allow(dead_code)]
-#[derive(Debug)]
-struct Foo { n0: Noisy, n1: Noisy }
-impl Foo {
-    fn vals(&self) -> (u8, u8) { (self.n0.0, self.n1.0) }
-}
-
-fn leak_1_ret() -> Foo {
-    let _old_foo = Foo { n0: Noisy(1), n1: Noisy(2) };
-    Foo { n0: { return Foo { n0: Noisy(3), n1: Noisy(4) } },
-          .._old_foo
-    };
-}
-
-fn leak_2_ret() -> Foo {
-    let _old_foo = Foo { n0: Noisy(1), n1: Noisy(2) };
-    Foo { n1: { return Foo { n0: Noisy(3), n1: Noisy(4) } },
-          .._old_foo
-    };
-}
-
-// In this case, the control flow break happens *before* we construct
-// `Foo(Noisy(1),Noisy(2))`, so there should be no record of it in the
-// event log.
-fn leak_3_ret() -> Foo {
-    let _old_foo = || Foo { n0: Noisy(1), n1: Noisy(2) };
-    Foo { n1: { return Foo { n0: Noisy(3), n1: Noisy(4) } },
-          .._old_foo()
-    };
-}
-
-pub fn main() {
-    reset_log();
-    assert_eq!(leak_1_ret().vals(), (3,4));
-    assert_eq!(0x01_02_03_04, event_log());
-
-    reset_log();
-    assert_eq!(leak_2_ret().vals(), (3,4));
-    assert_eq!(0x01_02_03_04, event_log());
-
-    reset_log();
-    assert_eq!(leak_3_ret().vals(), (3,4));
-    assert_eq!(0x03_04, event_log());
-}
-
-static LOG: AtomicUsize = AtomicUsize::new(0);
-
-fn reset_log() {
-    LOG.store(0, Ordering::SeqCst);
-}
-
-fn event_log() -> usize {
-    LOG.load(Ordering::SeqCst)
-}
-
-fn event(tag: u8) {
-    let old_log = LOG.load(Ordering::SeqCst);
-    let new_log = (old_log << 8) + tag as usize;
-    LOG.store(new_log, Ordering::SeqCst);
-}
index 31a8ca5fbfac887a3b0b01e5eab249ac87b113da..c75038b6169c0a227995a7c9de27ff581ca6d42a 100644 (file)
@@ -8,8 +8,8 @@ LL |     x.clone();
    |
 help: consider giving `x` an explicit type
    |
-LL |     let x: _ = panic!();
-   |          +++
+LL |     let x: /* Type */ = panic!();
+   |          ++++++++++++
 
 error: aborting due to previous error
 
index 4e010a13653e7796c0723c35125c33bdb5ce60b1..2d60b18b1f208eae86ab14800e0e4053f93304d4 100644 (file)
@@ -4,7 +4,13 @@ error[E0283]: type annotations needed: cannot satisfy `&'a T: Foo`
 LL |     where &'a T : Foo,
    |                   ^^^
    |
-   = note: cannot satisfy `&'a T: Foo`
+note: multiple `impl`s or `where` clauses satisfying `&'a T: Foo` found
+  --> $DIR/issue-21974.rs:11:19
+   |
+LL |     where &'a T : Foo,
+   |                   ^^^
+LL |           &'b T : Foo
+   |                   ^^^
 
 error: aborting due to previous error
 
index dc8b34a70c3241de9f930c078e6670aa0b0a41a7..014eb2897b488871c5f0ea563ab1a30bea8119fd 100644 (file)
@@ -13,11 +13,6 @@ error[E0107]: missing generics for trait `Fn`
 LL |     println!("{:?}",(vfnfer[0] as dyn Fn)(3));
    |                                       ^^ expected 1 generic argument
    |
-note: trait defined here, with 1 generic parameter: `Args`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   |           ^^ ----
 help: add missing generic argument
    |
 LL |     println!("{:?}",(vfnfer[0] as dyn Fn<Args>)(3));
index 5828e027b590312123168886eae1c2fc317ecf0a..1f50b06a0e4c553fc5b39160878ca3bd22c0d560 100644 (file)
@@ -5,7 +5,7 @@ LL |     type Next = <GetNext<T::Next> as Next>::Next;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_23122_2`)
-note: required for `GetNext<<<<<<... as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` to implement `Next`
+note: required for `GetNext<<<<<<<... as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` to implement `Next`
   --> $DIR/issue-23122-2.rs:10:15
    |
 LL | impl<T: Next> Next for GetNext<T> {
index ae8233d5c76e6aa2011bead773b94998c719182c..8f934481d85db6be1d86ae91290db0ab1fc87930 100644 (file)
@@ -9,9 +9,6 @@ LL |     "".chars().fold(|_, _| (), ());
    = help: the trait `FnMut<(_, char)>` is not implemented for `()`
 note: required by a bound in `fold`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         F: FnMut(B, Self::Item) -> B,
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `fold`
 
 error: aborting due to previous error
 
index a42e35c4cad5c922f526b92b65dd202b08612179..0e73a51faed9ac8bf07d4e299f465ab11f114fa3 100644 (file)
@@ -19,8 +19,8 @@ LL |         1 => |c| c + 1,
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |         1 => |c: _| c + 1,
-   |                +++
+LL |         1 => |c: /* Type */| c + 1,
+   |                ++++++++++++
 
 error: aborting due to 2 previous errors
 
index 8f3b2ac73199ccec1afced236ae6f1c0f0452522..50d7f988e194cdcd30d2fc72c9dd6a639eaebcd4 100644 (file)
@@ -4,7 +4,11 @@ error[E0283]: type annotations needed: cannot satisfy `T0: Trait0<'l0>`
 LL | impl <'l0, 'l1, T0> Trait1<'l0, T0> for bool where T0 : Trait0<'l0>, T0 : Trait0<'l1> {}
    |                                                         ^^^^^^^^^^^
    |
-   = note: cannot satisfy `T0: Trait0<'l0>`
+note: multiple `impl`s or `where` clauses satisfying `T0: Trait0<'l0>` found
+  --> $DIR/issue-24424.rs:4:57
+   |
+LL | impl <'l0, 'l1, T0> Trait1<'l0, T0> for bool where T0 : Trait0<'l0>, T0 : Trait0<'l1> {}
+   |                                                         ^^^^^^^^^^^       ^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-26930.rs b/src/test/ui/issues/issue-26930.rs
deleted file mode 100644 (file)
index 707e71b..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// check-pass
-
-extern crate core;
-use core as core_export;
-use self::x::*;
-mod x {}
-
-fn main() {}
index 9a38d49cd0c9624b4cef872e80f2ec750a0f0e11..7a0ca888d7471c3c87d81fa5ab6d5a418dedb47f 100644 (file)
@@ -3,11 +3,9 @@ error[E0530]: match bindings cannot shadow unit variants
    |
 LL |         None @ _ => {}
    |         ^^^^ cannot be named the same as a unit variant
+  --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
    |
-  ::: $SRC_DIR/std/src/prelude/mod.rs:LL:COL
-   |
-LL |     pub use super::v1::*;
-   |             ------------ the unit variant `None` is defined here
+   = note: the unit variant `None` is defined here
 
 error[E0530]: match bindings cannot shadow constants
   --> $DIR/issue-27033.rs:7:9
diff --git a/src/test/ui/issues/issue-29166.rs b/src/test/ui/issues/issue-29166.rs
deleted file mode 100644 (file)
index ca819ba..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// run-pass
-// This test ensures that vec.into_iter does not overconstrain element lifetime.
-
-pub fn main() {
-    original_report();
-    revision_1();
-    revision_2();
-}
-
-fn original_report() {
-    drop(vec![&()].into_iter())
-}
-
-fn revision_1() {
-    // below is what above `vec!` expands into at time of this writing.
-    drop(<[_]>::into_vec(::std::boxed::Box::new([&()])).into_iter())
-}
-
-fn revision_2() {
-    drop((match (Vec::new(), &()) { (mut v, b) => { v.push(b); v } }).into_iter())
-}
diff --git a/src/test/ui/issues/issue-29227.rs b/src/test/ui/issues/issue-29227.rs
deleted file mode 100644 (file)
index e9dfc28..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-// run-pass
-// ignore-tidy-linelength
-
-// Regression test for #29227. The problem here was that MIR
-// construction for these gigantic match expressions was very
-// inefficient.
-
-pub trait CharExt : Sized + Copy {
-    fn is_unicode_uppercase_letter(self) -> bool { false }
-    fn is_unicode_lowercase_letter(self) -> bool { false }
-    fn is_unicode_titlecase_letter(self) -> bool { false }
-    fn is_unicode_modifier_letter(self) -> bool { false }
-    fn is_unicode_other_letter(self) -> bool { false }
-    fn is_unicode_letter_number(self) -> bool { false }
-    fn is_unicode_nonspacing_mark(self) -> bool { false }
-    fn is_unicode_combining_spacing_mark(self) -> bool { false }
-    fn is_unicode_decimal_number(self) -> bool{ false }
-    fn is_unicode_connector_punctiation(self) -> bool { false }
-    fn is_unicode_space_separator(self) -> bool { false }
-
-    fn is_es_identifier_start(self) -> bool { false }
-    fn is_es_identifier_part(self) -> bool { false }
-    fn is_es_whitespace(self) -> bool { false }
-    fn is_es_line_terminator(self) -> bool { false }
-
-    fn is_unicode_letter(self) -> bool {
-        self.is_unicode_uppercase_letter()
-        || self.is_unicode_lowercase_letter()
-        || self.is_unicode_titlecase_letter()
-        || self.is_unicode_modifier_letter()
-        || self.is_unicode_modifier_letter()
-        || self.is_unicode_letter_number()
-    }
-
-}
-
-
-macro_rules! match_char_class {
-    ($thing:expr, $($c:expr),*) => {
-        match $thing {
-            $($c)|* => true,
-            _ => false
-        }
-    }
-}
-
-impl CharExt for char {
-    fn is_unicode_uppercase_letter(self) -> bool {
-        match_char_class!(self,
-            '\u{0041}', '\u{0042}', '\u{0043}', '\u{0044}', '\u{0045}', '\u{0046}', '\u{0047}', '\u{0048}', '\u{0049}', '\u{004A}', '\u{004B}', '\u{004C}', '\u{004D}', '\u{004E}', '\u{004F}', '\u{0050}', '\u{0051}', '\u{0052}', '\u{0053}', '\u{0054}', '\u{0055}', '\u{0056}', '\u{0057}', '\u{0058}', '\u{0059}', '\u{005A}', '\u{00C0}', '\u{00C1}', '\u{00C2}', '\u{00C3}', '\u{00C4}', '\u{00C5}', '\u{00C6}', '\u{00C7}', '\u{00C8}', '\u{00C9}', '\u{00CA}', '\u{00CB}', '\u{00CC}', '\u{00CD}', '\u{00CE}', '\u{00CF}', '\u{00D0}', '\u{00D1}', '\u{00D2}', '\u{00D3}', '\u{00D4}', '\u{00D5}', '\u{00D6}', '\u{00D8}', '\u{00D9}', '\u{00DA}', '\u{00DB}', '\u{00DC}', '\u{00DD}', '\u{00DE}', '\u{0100}', '\u{0102}', '\u{0104}', '\u{0106}', '\u{0108}', '\u{010A}', '\u{010C}', '\u{010E}', '\u{0110}', '\u{0112}', '\u{0114}', '\u{0116}', '\u{0118}', '\u{011A}', '\u{011C}', '\u{011E}', '\u{0120}', '\u{0122}', '\u{0124}', '\u{0126}', '\u{0128}', '\u{012A}', '\u{012C}', '\u{012E}', '\u{0130}', '\u{0132}', '\u{0134}', '\u{0136}', '\u{0139}', '\u{013B}', '\u{013D}', '\u{013F}', '\u{0141}', '\u{0143}', '\u{0145}', '\u{0147}', '\u{014A}', '\u{014C}', '\u{014E}', '\u{0150}', '\u{0152}', '\u{0154}', '\u{0156}', '\u{0158}', '\u{015A}', '\u{015C}', '\u{015E}', '\u{0160}', '\u{0162}', '\u{0164}', '\u{0166}', '\u{0168}', '\u{016A}', '\u{016C}', '\u{016E}', '\u{0170}', '\u{0172}', '\u{0174}', '\u{0176}', '\u{0178}', '\u{0179}', '\u{017B}', '\u{017D}', '\u{0181}', '\u{0182}', '\u{0184}', '\u{0186}', '\u{0187}', '\u{0189}', '\u{018A}', '\u{018B}', '\u{018E}', '\u{018F}', '\u{0190}', '\u{0191}', '\u{0193}', '\u{0194}', '\u{0196}', '\u{0197}', '\u{0198}', '\u{019C}', '\u{019D}', '\u{019F}', '\u{01A0}', '\u{01A2}', '\u{01A4}', '\u{01A6}', '\u{01A7}', '\u{01A9}', '\u{01AC}', '\u{01AE}', '\u{01AF}', '\u{01B1}', '\u{01B2}', '\u{01B3}', '\u{01B5}', '\u{01B7}', '\u{01B8}', '\u{01BC}', '\u{01C4}', '\u{01C7}', '\u{01CA}', '\u{01CD}', '\u{01CF}', '\u{01D1}', '\u{01D3}', '\u{01D5}', '\u{01D7}', '\u{01D9}', '\u{01DB}', '\u{01DE}', '\u{01E0}', '\u{01E2}', '\u{01E4}', '\u{01E6}', '\u{01E8}', '\u{01EA}', '\u{01EC}', '\u{01EE}', '\u{01F1}', '\u{01F4}', '\u{01F6}', '\u{01F7}', '\u{01F8}', '\u{01FA}', '\u{01FC}', '\u{01FE}', '\u{0200}', '\u{0202}', '\u{0204}', '\u{0206}', '\u{0208}', '\u{020A}', '\u{020C}', '\u{020E}', '\u{0210}', '\u{0212}', '\u{0214}', '\u{0216}', '\u{0218}', '\u{021A}', '\u{021C}', '\u{021E}', '\u{0220}', '\u{0222}', '\u{0224}', '\u{0226}', '\u{0228}', '\u{022A}', '\u{022C}', '\u{022E}', '\u{0230}', '\u{0232}', '\u{023A}', '\u{023B}', '\u{023D}', '\u{023E}', '\u{0241}', '\u{0243}', '\u{0244}', '\u{0245}', '\u{0246}', '\u{0248}', '\u{024A}', '\u{024C}', '\u{024E}', '\u{0370}', '\u{0372}', '\u{0376}', '\u{0386}', '\u{0388}', '\u{0389}', '\u{038A}', '\u{038C}', '\u{038E}', '\u{038F}', '\u{0391}', '\u{0392}', '\u{0393}', '\u{0394}', '\u{0395}', '\u{0396}', '\u{0397}', '\u{0398}', '\u{0399}', '\u{039A}', '\u{039B}', '\u{039C}', '\u{039D}', '\u{039E}', '\u{039F}', '\u{03A0}', '\u{03A1}', '\u{03A3}', '\u{03A4}', '\u{03A5}', '\u{03A6}', '\u{03A7}', '\u{03A8}', '\u{03A9}', '\u{03AA}', '\u{03AB}', '\u{03CF}', '\u{03D2}', '\u{03D3}', '\u{03D4}', '\u{03D8}', '\u{03DA}', '\u{03DC}', '\u{03DE}', '\u{03E0}', '\u{03E2}', '\u{03E4}', '\u{03E6}', '\u{03E8}', '\u{03EA}', '\u{03EC}', '\u{03EE}', '\u{03F4}', '\u{03F7}', '\u{03F9}', '\u{03FA}', '\u{03FD}', '\u{03FE}', '\u{03FF}', '\u{0400}', '\u{0401}', '\u{0402}', '\u{0403}', '\u{0404}', '\u{0405}', '\u{0406}', '\u{0407}', '\u{0408}', '\u{0409}', '\u{040A}', '\u{040B}', '\u{040C}', '\u{040D}', '\u{040E}', '\u{040F}', '\u{0410}', '\u{0411}', '\u{0412}', '\u{0413}', '\u{0414}', '\u{0415}', '\u{0416}', '\u{0417}', '\u{0418}', '\u{0419}', '\u{041A}', '\u{041B}', '\u{041C}', '\u{041D}', '\u{041E}', '\u{041F}', '\u{0420}', '\u{0421}', '\u{0422}', '\u{0423}', '\u{0424}', '\u{0425}', '\u{0426}', '\u{0427}', '\u{0428}', '\u{0429}', '\u{042A}', '\u{042B}', '\u{042C}', '\u{042D}', '\u{042E}', '\u{042F}', '\u{0460}', '\u{0462}', '\u{0464}', '\u{0466}', '\u{0468}', '\u{046A}', '\u{046C}', '\u{046E}', '\u{0470}', '\u{0472}', '\u{0474}', '\u{0476}', '\u{0478}', '\u{047A}', '\u{047C}', '\u{047E}', '\u{0480}', '\u{048A}', '\u{048C}', '\u{048E}', '\u{0490}', '\u{0492}', '\u{0494}', '\u{0496}', '\u{0498}', '\u{049A}', '\u{049C}', '\u{049E}', '\u{04A0}', '\u{04A2}', '\u{04A4}', '\u{04A6}', '\u{04A8}', '\u{04AA}', '\u{04AC}', '\u{04AE}', '\u{04B0}', '\u{04B2}', '\u{04B4}', '\u{04B6}', '\u{04B8}', '\u{04BA}', '\u{04BC}', '\u{04BE}', '\u{04C0}', '\u{04C1}', '\u{04C3}', '\u{04C5}', '\u{04C7}', '\u{04C9}', '\u{04CB}', '\u{04CD}', '\u{04D0}', '\u{04D2}', '\u{04D4}', '\u{04D6}', '\u{04D8}', '\u{04DA}', '\u{04DC}', '\u{04DE}', '\u{04E0}', '\u{04E2}', '\u{04E4}', '\u{04E6}', '\u{04E8}', '\u{04EA}', '\u{04EC}', '\u{04EE}', '\u{04F0}', '\u{04F2}', '\u{04F4}', '\u{04F6}', '\u{04F8}', '\u{04FA}', '\u{04FC}', '\u{04FE}', '\u{0500}', '\u{0502}', '\u{0504}', '\u{0506}', '\u{0508}', '\u{050A}', '\u{050C}', '\u{050E}', '\u{0510}', '\u{0512}', '\u{0514}', '\u{0516}', '\u{0518}', '\u{051A}', '\u{051C}', '\u{051E}', '\u{0520}', '\u{0522}', '\u{0531}', '\u{0532}', '\u{0533}', '\u{0534}', '\u{0535}', '\u{0536}', '\u{0537}', '\u{0538}', '\u{0539}', '\u{053A}', '\u{053B}', '\u{053C}', '\u{053D}', '\u{053E}', '\u{053F}', '\u{0540}', '\u{0541}', '\u{0542}', '\u{0543}', '\u{0544}', '\u{0545}', '\u{0546}', '\u{0547}', '\u{0548}', '\u{0549}', '\u{054A}', '\u{054B}', '\u{054C}', '\u{054D}', '\u{054E}', '\u{054F}', '\u{0550}', '\u{0551}', '\u{0552}', '\u{0553}', '\u{0554}', '\u{0555}', '\u{0556}', '\u{10A0}', '\u{10A1}', '\u{10A2}', '\u{10A3}', '\u{10A4}', '\u{10A5}', '\u{10A6}', '\u{10A7}', '\u{10A8}', '\u{10A9}', '\u{10AA}', '\u{10AB}', '\u{10AC}', '\u{10AD}', '\u{10AE}', '\u{10AF}', '\u{10B0}', '\u{10B1}', '\u{10B2}', '\u{10B3}', '\u{10B4}', '\u{10B5}', '\u{10B6}', '\u{10B7}', '\u{10B8}', '\u{10B9}', '\u{10BA}', '\u{10BB}', '\u{10BC}', '\u{10BD}', '\u{10BE}', '\u{10BF}', '\u{10C0}', '\u{10C1}', '\u{10C2}', '\u{10C3}', '\u{10C4}', '\u{10C5}', '\u{1E00}', '\u{1E02}', '\u{1E04}', '\u{1E06}', '\u{1E08}', '\u{1E0A}', '\u{1E0C}', '\u{1E0E}', '\u{1E10}', '\u{1E12}', '\u{1E14}', '\u{1E16}', '\u{1E18}', '\u{1E1A}', '\u{1E1C}', '\u{1E1E}', '\u{1E20}', '\u{1E22}', '\u{1E24}', '\u{1E26}', '\u{1E28}', '\u{1E2A}', '\u{1E2C}', '\u{1E2E}', '\u{1E30}', '\u{1E32}', '\u{1E34}', '\u{1E36}', '\u{1E38}', '\u{1E3A}', '\u{1E3C}', '\u{1E3E}', '\u{1E40}', '\u{1E42}', '\u{1E44}', '\u{1E46}', '\u{1E48}', '\u{1E4A}', '\u{1E4C}', '\u{1E4E}', '\u{1E50}', '\u{1E52}', '\u{1E54}', '\u{1E56}', '\u{1E58}', '\u{1E5A}', '\u{1E5C}', '\u{1E5E}', '\u{1E60}', '\u{1E62}', '\u{1E64}', '\u{1E66}', '\u{1E68}', '\u{1E6A}', '\u{1E6C}', '\u{1E6E}', '\u{1E70}', '\u{1E72}', '\u{1E74}', '\u{1E76}', '\u{1E78}', '\u{1E7A}', '\u{1E7C}', '\u{1E7E}', '\u{1E80}', '\u{1E82}', '\u{1E84}', '\u{1E86}', '\u{1E88}', '\u{1E8A}', '\u{1E8C}', '\u{1E8E}', '\u{1E90}', '\u{1E92}', '\u{1E94}', '\u{1E9E}', '\u{1EA0}', '\u{1EA2}', '\u{1EA4}', '\u{1EA6}', '\u{1EA8}', '\u{1EAA}', '\u{1EAC}', '\u{1EAE}', '\u{1EB0}', '\u{1EB2}', '\u{1EB4}', '\u{1EB6}', '\u{1EB8}', '\u{1EBA}', '\u{1EBC}', '\u{1EBE}', '\u{1EC0}', '\u{1EC2}', '\u{1EC4}', '\u{1EC6}', '\u{1EC8}', '\u{1ECA}', '\u{1ECC}', '\u{1ECE}', '\u{1ED0}', '\u{1ED2}', '\u{1ED4}', '\u{1ED6}', '\u{1ED8}', '\u{1EDA}', '\u{1EDC}', '\u{1EDE}', '\u{1EE0}', '\u{1EE2}', '\u{1EE4}', '\u{1EE6}', '\u{1EE8}', '\u{1EEA}', '\u{1EEC}', '\u{1EEE}', '\u{1EF0}', '\u{1EF2}', '\u{1EF4}', '\u{1EF6}', '\u{1EF8}', '\u{1EFA}', '\u{1EFC}', '\u{1EFE}', '\u{1F08}', '\u{1F09}', '\u{1F0A}', '\u{1F0B}', '\u{1F0C}', '\u{1F0D}', '\u{1F0E}', '\u{1F0F}', '\u{1F18}', '\u{1F19}', '\u{1F1A}', '\u{1F1B}', '\u{1F1C}', '\u{1F1D}', '\u{1F28}', '\u{1F29}', '\u{1F2A}', '\u{1F2B}', '\u{1F2C}', '\u{1F2D}', '\u{1F2E}', '\u{1F2F}', '\u{1F38}', '\u{1F39}', '\u{1F3A}', '\u{1F3B}', '\u{1F3C}', '\u{1F3D}', '\u{1F3E}', '\u{1F3F}', '\u{1F48}', '\u{1F49}', '\u{1F4A}', '\u{1F4B}', '\u{1F4C}', '\u{1F4D}', '\u{1F59}', '\u{1F5B}', '\u{1F5D}', '\u{1F5F}', '\u{1F68}', '\u{1F69}', '\u{1F6A}', '\u{1F6B}', '\u{1F6C}', '\u{1F6D}', '\u{1F6E}', '\u{1F6F}', '\u{1FB8}', '\u{1FB9}', '\u{1FBA}', '\u{1FBB}', '\u{1FC8}', '\u{1FC9}', '\u{1FCA}', '\u{1FCB}', '\u{1FD8}', '\u{1FD9}', '\u{1FDA}', '\u{1FDB}', '\u{1FE8}', '\u{1FE9}', '\u{1FEA}', '\u{1FEB}', '\u{1FEC}', '\u{1FF8}', '\u{1FF9}', '\u{1FFA}', '\u{1FFB}', '\u{2102}', '\u{2107}', '\u{210B}', '\u{210C}', '\u{210D}', '\u{2110}', '\u{2111}', '\u{2112}', '\u{2115}', '\u{2119}', '\u{211A}', '\u{211B}', '\u{211C}', '\u{211D}', '\u{2124}', '\u{2126}', '\u{2128}', '\u{212A}', '\u{212B}', '\u{212C}', '\u{212D}', '\u{2130}', '\u{2131}', '\u{2132}', '\u{2133}', '\u{213E}', '\u{213F}', '\u{2145}', '\u{2183}', '\u{2C00}', '\u{2C01}', '\u{2C02}', '\u{2C03}', '\u{2C04}', '\u{2C05}', '\u{2C06}', '\u{2C07}', '\u{2C08}', '\u{2C09}', '\u{2C0A}', '\u{2C0B}', '\u{2C0C}', '\u{2C0D}', '\u{2C0E}', '\u{2C0F}', '\u{2C10}', '\u{2C11}', '\u{2C12}', '\u{2C13}', '\u{2C14}', '\u{2C15}', '\u{2C16}', '\u{2C17}', '\u{2C18}', '\u{2C19}', '\u{2C1A}', '\u{2C1B}', '\u{2C1C}', '\u{2C1D}', '\u{2C1E}', '\u{2C1F}', '\u{2C20}', '\u{2C21}', '\u{2C22}', '\u{2C23}', '\u{2C24}', '\u{2C25}', '\u{2C26}', '\u{2C27}', '\u{2C28}', '\u{2C29}', '\u{2C2A}', '\u{2C2B}', '\u{2C2C}', '\u{2C2D}', '\u{2C2E}', '\u{2C60}', '\u{2C62}', '\u{2C63}', '\u{2C64}', '\u{2C67}', '\u{2C69}', '\u{2C6B}', '\u{2C6D}', '\u{2C6E}', '\u{2C6F}', '\u{2C72}', '\u{2C75}', '\u{2C80}', '\u{2C82}', '\u{2C84}', '\u{2C86}', '\u{2C88}', '\u{2C8A}', '\u{2C8C}', '\u{2C8E}', '\u{2C90}', '\u{2C92}', '\u{2C94}', '\u{2C96}', '\u{2C98}', '\u{2C9A}', '\u{2C9C}', '\u{2C9E}', '\u{2CA0}', '\u{2CA2}', '\u{2CA4}', '\u{2CA6}', '\u{2CA8}', '\u{2CAA}', '\u{2CAC}', '\u{2CAE}', '\u{2CB0}', '\u{2CB2}', '\u{2CB4}', '\u{2CB6}', '\u{2CB8}', '\u{2CBA}', '\u{2CBC}', '\u{2CBE}', '\u{2CC0}', '\u{2CC2}', '\u{2CC4}', '\u{2CC6}', '\u{2CC8}', '\u{2CCA}', '\u{2CCC}', '\u{2CCE}', '\u{2CD0}', '\u{2CD2}', '\u{2CD4}', '\u{2CD6}', '\u{2CD8}', '\u{2CDA}', '\u{2CDC}', '\u{2CDE}', '\u{2CE0}', '\u{2CE2}', '\u{A640}', '\u{A642}', '\u{A644}', '\u{A646}', '\u{A648}', '\u{A64A}', '\u{A64C}', '\u{A64E}', '\u{A650}', '\u{A652}', '\u{A654}', '\u{A656}', '\u{A658}', '\u{A65A}', '\u{A65C}', '\u{A65E}', '\u{A662}', '\u{A664}', '\u{A666}', '\u{A668}', '\u{A66A}', '\u{A66C}', '\u{A680}', '\u{A682}', '\u{A684}', '\u{A686}', '\u{A688}', '\u{A68A}', '\u{A68C}', '\u{A68E}', '\u{A690}', '\u{A692}', '\u{A694}', '\u{A696}', '\u{A722}', '\u{A724}', '\u{A726}', '\u{A728}', '\u{A72A}', '\u{A72C}', '\u{A72E}', '\u{A732}', '\u{A734}', '\u{A736}', '\u{A738}', '\u{A73A}', '\u{A73C}', '\u{A73E}', '\u{A740}', '\u{A742}', '\u{A744}', '\u{A746}', '\u{A748}', '\u{A74A}', '\u{A74C}', '\u{A74E}', '\u{A750}', '\u{A752}', '\u{A754}', '\u{A756}', '\u{A758}', '\u{A75A}', '\u{A75C}', '\u{A75E}', '\u{A760}', '\u{A762}', '\u{A764}', '\u{A766}', '\u{A768}', '\u{A76A}', '\u{A76C}', '\u{A76E}', '\u{A779}', '\u{A77B}', '\u{A77D}', '\u{A77E}', '\u{A780}', '\u{A782}', '\u{A784}', '\u{A786}', '\u{A78B}', '\u{FF21}', '\u{FF22}', '\u{FF23}', '\u{FF24}', '\u{FF25}', '\u{FF26}', '\u{FF27}', '\u{FF28}', '\u{FF29}', '\u{FF2A}', '\u{FF2B}', '\u{FF2C}', '\u{FF2D}', '\u{FF2E}', '\u{FF2F}', '\u{FF30}', '\u{FF31}', '\u{FF32}', '\u{FF33}', '\u{FF34}', '\u{FF35}', '\u{FF36}', '\u{FF37}', '\u{FF38}', '\u{FF39}', '\u{FF3A}')
-    }
-
-    fn is_unicode_lowercase_letter(self) -> bool {
-        match_char_class!(self,
-            '\u{0061}', '\u{0062}', '\u{0063}', '\u{0064}', '\u{0065}', '\u{0066}', '\u{0067}', '\u{0068}', '\u{0069}', '\u{006A}', '\u{006B}', '\u{006C}', '\u{006D}', '\u{006E}', '\u{006F}', '\u{0070}', '\u{0071}', '\u{0072}', '\u{0073}', '\u{0074}', '\u{0075}', '\u{0076}', '\u{0077}', '\u{0078}', '\u{0079}', '\u{007A}', '\u{00AA}', '\u{00B5}', '\u{00BA}', '\u{00DF}', '\u{00E0}', '\u{00E1}', '\u{00E2}', '\u{00E3}', '\u{00E4}', '\u{00E5}', '\u{00E6}', '\u{00E7}', '\u{00E8}', '\u{00E9}', '\u{00EA}', '\u{00EB}', '\u{00EC}', '\u{00ED}', '\u{00EE}', '\u{00EF}', '\u{00F0}', '\u{00F1}', '\u{00F2}', '\u{00F3}', '\u{00F4}', '\u{00F5}', '\u{00F6}', '\u{00F8}', '\u{00F9}', '\u{00FA}', '\u{00FB}', '\u{00FC}', '\u{00FD}', '\u{00FE}', '\u{00FF}', '\u{0101}', '\u{0103}', '\u{0105}', '\u{0107}', '\u{0109}', '\u{010B}', '\u{010D}', '\u{010F}', '\u{0111}', '\u{0113}', '\u{0115}', '\u{0117}', '\u{0119}', '\u{011B}', '\u{011D}', '\u{011F}', '\u{0121}', '\u{0123}', '\u{0125}', '\u{0127}', '\u{0129}', '\u{012B}', '\u{012D}', '\u{012F}', '\u{0131}', '\u{0133}', '\u{0135}', '\u{0137}', '\u{0138}', '\u{013A}', '\u{013C}', '\u{013E}', '\u{0140}', '\u{0142}', '\u{0144}', '\u{0146}', '\u{0148}', '\u{0149}', '\u{014B}', '\u{014D}', '\u{014F}', '\u{0151}', '\u{0153}', '\u{0155}', '\u{0157}', '\u{0159}', '\u{015B}', '\u{015D}', '\u{015F}', '\u{0161}', '\u{0163}', '\u{0165}', '\u{0167}', '\u{0169}', '\u{016B}', '\u{016D}', '\u{016F}', '\u{0171}', '\u{0173}', '\u{0175}', '\u{0177}', '\u{017A}', '\u{017C}', '\u{017E}', '\u{017F}', '\u{0180}', '\u{0183}', '\u{0185}', '\u{0188}', '\u{018C}', '\u{018D}', '\u{0192}', '\u{0195}', '\u{0199}', '\u{019A}', '\u{019B}', '\u{019E}', '\u{01A1}', '\u{01A3}', '\u{01A5}', '\u{01A8}', '\u{01AA}', '\u{01AB}', '\u{01AD}', '\u{01B0}', '\u{01B4}', '\u{01B6}', '\u{01B9}', '\u{01BA}', '\u{01BD}', '\u{01BE}', '\u{01BF}', '\u{01C6}', '\u{01C9}', '\u{01CC}', '\u{01CE}', '\u{01D0}', '\u{01D2}', '\u{01D4}', '\u{01D6}', '\u{01D8}', '\u{01DA}', '\u{01DC}', '\u{01DD}', '\u{01DF}', '\u{01E1}', '\u{01E3}', '\u{01E5}', '\u{01E7}', '\u{01E9}', '\u{01EB}', '\u{01ED}', '\u{01EF}', '\u{01F0}', '\u{01F3}', '\u{01F5}', '\u{01F9}', '\u{01FB}', '\u{01FD}', '\u{01FF}', '\u{0201}', '\u{0203}', '\u{0205}', '\u{0207}', '\u{0209}', '\u{020B}', '\u{020D}', '\u{020F}', '\u{0211}', '\u{0213}', '\u{0215}', '\u{0217}', '\u{0219}', '\u{021B}', '\u{021D}', '\u{021F}', '\u{0221}', '\u{0223}', '\u{0225}', '\u{0227}', '\u{0229}', '\u{022B}', '\u{022D}', '\u{022F}', '\u{0231}', '\u{0233}', '\u{0234}', '\u{0235}', '\u{0236}', '\u{0237}', '\u{0238}', '\u{0239}', '\u{023C}', '\u{023F}', '\u{0240}', '\u{0242}', '\u{0247}', '\u{0249}', '\u{024B}', '\u{024D}', '\u{024F}', '\u{0250}', '\u{0251}', '\u{0252}', '\u{0253}', '\u{0254}', '\u{0255}', '\u{0256}', '\u{0257}', '\u{0258}', '\u{0259}', '\u{025A}', '\u{025B}', '\u{025C}', '\u{025D}', '\u{025E}', '\u{025F}', '\u{0260}', '\u{0261}', '\u{0262}', '\u{0263}', '\u{0264}', '\u{0265}', '\u{0266}', '\u{0267}', '\u{0268}', '\u{0269}', '\u{026A}', '\u{026B}', '\u{026C}', '\u{026D}', '\u{026E}', '\u{026F}', '\u{0270}', '\u{0271}', '\u{0272}', '\u{0273}', '\u{0274}', '\u{0275}', '\u{0276}', '\u{0277}', '\u{0278}', '\u{0279}', '\u{027A}', '\u{027B}', '\u{027C}', '\u{027D}', '\u{027E}', '\u{027F}', '\u{0280}', '\u{0281}', '\u{0282}', '\u{0283}', '\u{0284}', '\u{0285}', '\u{0286}', '\u{0287}', '\u{0288}', '\u{0289}', '\u{028A}', '\u{028B}', '\u{028C}', '\u{028D}', '\u{028E}', '\u{028F}', '\u{0290}', '\u{0291}', '\u{0292}', '\u{0293}', '\u{0295}', '\u{0296}', '\u{0297}', '\u{0298}', '\u{0299}', '\u{029A}', '\u{029B}', '\u{029C}', '\u{029D}', '\u{029E}', '\u{029F}', '\u{02A0}', '\u{02A1}', '\u{02A2}', '\u{02A3}', '\u{02A4}', '\u{02A5}', '\u{02A6}', '\u{02A7}', '\u{02A8}', '\u{02A9}', '\u{02AA}', '\u{02AB}', '\u{02AC}', '\u{02AD}', '\u{02AE}', '\u{02AF}', '\u{0371}', '\u{0373}', '\u{0377}', '\u{037B}', '\u{037C}', '\u{037D}', '\u{0390}', '\u{03AC}', '\u{03AD}', '\u{03AE}', '\u{03AF}', '\u{03B0}', '\u{03B1}', '\u{03B2}', '\u{03B3}', '\u{03B4}', '\u{03B5}', '\u{03B6}', '\u{03B7}', '\u{03B8}', '\u{03B9}', '\u{03BA}', '\u{03BB}', '\u{03BC}', '\u{03BD}', '\u{03BE}', '\u{03BF}', '\u{03C0}', '\u{03C1}', '\u{03C2}', '\u{03C3}', '\u{03C4}', '\u{03C5}', '\u{03C6}', '\u{03C7}', '\u{03C8}', '\u{03C9}', '\u{03CA}', '\u{03CB}', '\u{03CC}', '\u{03CD}', '\u{03CE}', '\u{03D0}', '\u{03D1}', '\u{03D5}', '\u{03D6}', '\u{03D7}', '\u{03D9}', '\u{03DB}', '\u{03DD}', '\u{03DF}', '\u{03E1}', '\u{03E3}', '\u{03E5}', '\u{03E7}', '\u{03E9}', '\u{03EB}', '\u{03ED}', '\u{03EF}', '\u{03F0}', '\u{03F1}', '\u{03F2}', '\u{03F3}', '\u{03F5}', '\u{03F8}', '\u{03FB}', '\u{03FC}', '\u{0430}', '\u{0431}', '\u{0432}', '\u{0433}', '\u{0434}', '\u{0435}', '\u{0436}', '\u{0437}', '\u{0438}', '\u{0439}', '\u{043A}', '\u{043B}', '\u{043C}', '\u{043D}', '\u{043E}', '\u{043F}', '\u{0440}', '\u{0441}', '\u{0442}', '\u{0443}', '\u{0444}', '\u{0445}', '\u{0446}', '\u{0447}', '\u{0448}', '\u{0449}', '\u{044A}', '\u{044B}', '\u{044C}', '\u{044D}', '\u{044E}', '\u{044F}', '\u{0450}', '\u{0451}', '\u{0452}', '\u{0453}', '\u{0454}', '\u{0455}', '\u{0456}', '\u{0457}', '\u{0458}', '\u{0459}', '\u{045A}', '\u{045B}', '\u{045C}', '\u{045D}', '\u{045E}', '\u{045F}', '\u{0461}', '\u{0463}', '\u{0465}', '\u{0467}', '\u{0469}', '\u{046B}', '\u{046D}', '\u{046F}', '\u{0471}', '\u{0473}', '\u{0475}', '\u{0477}', '\u{0479}', '\u{047B}', '\u{047D}', '\u{047F}', '\u{0481}', '\u{048B}', '\u{048D}', '\u{048F}', '\u{0491}', '\u{0493}', '\u{0495}', '\u{0497}', '\u{0499}', '\u{049B}', '\u{049D}', '\u{049F}', '\u{04A1}', '\u{04A3}', '\u{04A5}', '\u{04A7}', '\u{04A9}', '\u{04AB}', '\u{04AD}', '\u{04AF}', '\u{04B1}', '\u{04B3}', '\u{04B5}', '\u{04B7}', '\u{04B9}', '\u{04BB}', '\u{04BD}', '\u{04BF}', '\u{04C2}', '\u{04C4}', '\u{04C6}', '\u{04C8}', '\u{04CA}', '\u{04CC}', '\u{04CE}', '\u{04CF}', '\u{04D1}', '\u{04D3}', '\u{04D5}', '\u{04D7}', '\u{04D9}', '\u{04DB}', '\u{04DD}', '\u{04DF}', '\u{04E1}', '\u{04E3}', '\u{04E5}', '\u{04E7}', '\u{04E9}', '\u{04EB}', '\u{04ED}', '\u{04EF}', '\u{04F1}', '\u{04F3}', '\u{04F5}', '\u{04F7}', '\u{04F9}', '\u{04FB}', '\u{04FD}', '\u{04FF}', '\u{0501}', '\u{0503}', '\u{0505}', '\u{0507}', '\u{0509}', '\u{050B}', '\u{050D}', '\u{050F}', '\u{0511}', '\u{0513}', '\u{0515}', '\u{0517}', '\u{0519}', '\u{051B}', '\u{051D}', '\u{051F}', '\u{0521}', '\u{0523}', '\u{0561}', '\u{0562}', '\u{0563}', '\u{0564}', '\u{0565}', '\u{0566}', '\u{0567}', '\u{0568}', '\u{0569}', '\u{056A}', '\u{056B}', '\u{056C}', '\u{056D}', '\u{056E}', '\u{056F}', '\u{0570}', '\u{0571}', '\u{0572}', '\u{0573}', '\u{0574}', '\u{0575}', '\u{0576}', '\u{0577}', '\u{0578}', '\u{0579}', '\u{057A}', '\u{057B}', '\u{057C}', '\u{057D}', '\u{057E}', '\u{057F}', '\u{0580}', '\u{0581}', '\u{0582}', '\u{0583}', '\u{0584}', '\u{0585}', '\u{0586}', '\u{0587}', '\u{1D00}', '\u{1D01}', '\u{1D02}', '\u{1D03}', '\u{1D04}', '\u{1D05}', '\u{1D06}', '\u{1D07}', '\u{1D08}', '\u{1D09}', '\u{1D0A}', '\u{1D0B}', '\u{1D0C}', '\u{1D0D}', '\u{1D0E}', '\u{1D0F}', '\u{1D10}', '\u{1D11}', '\u{1D12}', '\u{1D13}', '\u{1D14}', '\u{1D15}', '\u{1D16}', '\u{1D17}', '\u{1D18}', '\u{1D19}', '\u{1D1A}', '\u{1D1B}', '\u{1D1C}', '\u{1D1D}', '\u{1D1E}', '\u{1D1F}', '\u{1D20}', '\u{1D21}', '\u{1D22}', '\u{1D23}', '\u{1D24}', '\u{1D25}', '\u{1D26}', '\u{1D27}', '\u{1D28}', '\u{1D29}', '\u{1D2A}', '\u{1D2B}', '\u{1D62}', '\u{1D63}', '\u{1D64}', '\u{1D65}', '\u{1D66}', '\u{1D67}', '\u{1D68}', '\u{1D69}', '\u{1D6A}', '\u{1D6B}', '\u{1D6C}', '\u{1D6D}', '\u{1D6E}', '\u{1D6F}', '\u{1D70}', '\u{1D71}', '\u{1D72}', '\u{1D73}', '\u{1D74}', '\u{1D75}', '\u{1D76}', '\u{1D77}', '\u{1D79}', '\u{1D7A}', '\u{1D7B}', '\u{1D7C}', '\u{1D7D}', '\u{1D7E}', '\u{1D7F}', '\u{1D80}', '\u{1D81}', '\u{1D82}', '\u{1D83}', '\u{1D84}', '\u{1D85}', '\u{1D86}', '\u{1D87}', '\u{1D88}', '\u{1D89}', '\u{1D8A}', '\u{1D8B}', '\u{1D8C}', '\u{1D8D}', '\u{1D8E}', '\u{1D8F}', '\u{1D90}', '\u{1D91}', '\u{1D92}', '\u{1D93}', '\u{1D94}', '\u{1D95}', '\u{1D96}', '\u{1D97}', '\u{1D98}', '\u{1D99}', '\u{1D9A}', '\u{1E01}', '\u{1E03}', '\u{1E05}', '\u{1E07}', '\u{1E09}', '\u{1E0B}', '\u{1E0D}', '\u{1E0F}', '\u{1E11}', '\u{1E13}', '\u{1E15}', '\u{1E17}', '\u{1E19}', '\u{1E1B}', '\u{1E1D}', '\u{1E1F}', '\u{1E21}', '\u{1E23}', '\u{1E25}', '\u{1E27}', '\u{1E29}', '\u{1E2B}', '\u{1E2D}', '\u{1E2F}', '\u{1E31}', '\u{1E33}', '\u{1E35}', '\u{1E37}', '\u{1E39}', '\u{1E3B}', '\u{1E3D}', '\u{1E3F}', '\u{1E41}', '\u{1E43}', '\u{1E45}', '\u{1E47}', '\u{1E49}', '\u{1E4B}', '\u{1E4D}', '\u{1E4F}', '\u{1E51}', '\u{1E53}', '\u{1E55}', '\u{1E57}', '\u{1E59}', '\u{1E5B}', '\u{1E5D}', '\u{1E5F}', '\u{1E61}', '\u{1E63}', '\u{1E65}', '\u{1E67}', '\u{1E69}', '\u{1E6B}', '\u{1E6D}', '\u{1E6F}', '\u{1E71}', '\u{1E73}', '\u{1E75}', '\u{1E77}', '\u{1E79}', '\u{1E7B}', '\u{1E7D}', '\u{1E7F}', '\u{1E81}', '\u{1E83}', '\u{1E85}', '\u{1E87}', '\u{1E89}', '\u{1E8B}', '\u{1E8D}', '\u{1E8F}', '\u{1E91}', '\u{1E93}', '\u{1E95}', '\u{1E96}', '\u{1E97}', '\u{1E98}', '\u{1E99}', '\u{1E9A}', '\u{1E9B}', '\u{1E9C}', '\u{1E9D}', '\u{1E9F}', '\u{1EA1}', '\u{1EA3}', '\u{1EA5}', '\u{1EA7}', '\u{1EA9}', '\u{1EAB}', '\u{1EAD}', '\u{1EAF}', '\u{1EB1}', '\u{1EB3}', '\u{1EB5}', '\u{1EB7}', '\u{1EB9}', '\u{1EBB}', '\u{1EBD}', '\u{1EBF}', '\u{1EC1}', '\u{1EC3}', '\u{1EC5}', '\u{1EC7}', '\u{1EC9}', '\u{1ECB}', '\u{1ECD}', '\u{1ECF}', '\u{1ED1}', '\u{1ED3}', '\u{1ED5}', '\u{1ED7}', '\u{1ED9}', '\u{1EDB}', '\u{1EDD}', '\u{1EDF}', '\u{1EE1}', '\u{1EE3}', '\u{1EE5}', '\u{1EE7}', '\u{1EE9}', '\u{1EEB}', '\u{1EED}', '\u{1EEF}', '\u{1EF1}', '\u{1EF3}', '\u{1EF5}', '\u{1EF7}', '\u{1EF9}', '\u{1EFB}', '\u{1EFD}', '\u{1EFF}', '\u{1F00}', '\u{1F01}', '\u{1F02}', '\u{1F03}', '\u{1F04}', '\u{1F05}', '\u{1F06}', '\u{1F07}', '\u{1F10}', '\u{1F11}', '\u{1F12}', '\u{1F13}', '\u{1F14}', '\u{1F15}', '\u{1F20}', '\u{1F21}', '\u{1F22}', '\u{1F23}', '\u{1F24}', '\u{1F25}', '\u{1F26}', '\u{1F27}', '\u{1F30}', '\u{1F31}', '\u{1F32}', '\u{1F33}', '\u{1F34}', '\u{1F35}', '\u{1F36}', '\u{1F37}', '\u{1F40}', '\u{1F41}', '\u{1F42}', '\u{1F43}', '\u{1F44}', '\u{1F45}', '\u{1F50}', '\u{1F51}', '\u{1F52}', '\u{1F53}', '\u{1F54}', '\u{1F55}', '\u{1F56}', '\u{1F57}', '\u{1F60}', '\u{1F61}', '\u{1F62}', '\u{1F63}', '\u{1F64}', '\u{1F65}', '\u{1F66}', '\u{1F67}', '\u{1F70}', '\u{1F71}', '\u{1F72}', '\u{1F73}', '\u{1F74}', '\u{1F75}', '\u{1F76}', '\u{1F77}', '\u{1F78}', '\u{1F79}', '\u{1F7A}', '\u{1F7B}', '\u{1F7C}', '\u{1F7D}', '\u{1F80}', '\u{1F81}', '\u{1F82}', '\u{1F83}', '\u{1F84}', '\u{1F85}', '\u{1F86}', '\u{1F87}', '\u{1F90}', '\u{1F91}', '\u{1F92}', '\u{1F93}', '\u{1F94}', '\u{1F95}', '\u{1F96}', '\u{1F97}', '\u{1FA0}', '\u{1FA1}', '\u{1FA2}', '\u{1FA3}', '\u{1FA4}', '\u{1FA5}', '\u{1FA6}', '\u{1FA7}', '\u{1FB0}', '\u{1FB1}', '\u{1FB2}', '\u{1FB3}', '\u{1FB4}', '\u{1FB6}', '\u{1FB7}', '\u{1FBE}', '\u{1FC2}', '\u{1FC3}', '\u{1FC4}', '\u{1FC6}', '\u{1FC7}', '\u{1FD0}', '\u{1FD1}', '\u{1FD2}', '\u{1FD3}', '\u{1FD6}', '\u{1FD7}', '\u{1FE0}', '\u{1FE1}', '\u{1FE2}', '\u{1FE3}', '\u{1FE4}', '\u{1FE5}', '\u{1FE6}', '\u{1FE7}', '\u{1FF2}', '\u{1FF3}', '\u{1FF4}', '\u{1FF6}', '\u{1FF7}', '\u{2071}', '\u{207F}', '\u{210A}', '\u{210E}', '\u{210F}', '\u{2113}', '\u{212F}', '\u{2134}', '\u{2139}', '\u{213C}', '\u{213D}', '\u{2146}', '\u{2147}', '\u{2148}', '\u{2149}', '\u{214E}', '\u{2184}', '\u{2C30}', '\u{2C31}', '\u{2C32}', '\u{2C33}', '\u{2C34}', '\u{2C35}', '\u{2C36}', '\u{2C37}', '\u{2C38}', '\u{2C39}', '\u{2C3A}', '\u{2C3B}', '\u{2C3C}', '\u{2C3D}', '\u{2C3E}', '\u{2C3F}', '\u{2C40}', '\u{2C41}', '\u{2C42}', '\u{2C43}', '\u{2C44}', '\u{2C45}', '\u{2C46}', '\u{2C47}', '\u{2C48}', '\u{2C49}', '\u{2C4A}', '\u{2C4B}', '\u{2C4C}', '\u{2C4D}', '\u{2C4E}', '\u{2C4F}', '\u{2C50}', '\u{2C51}', '\u{2C52}', '\u{2C53}', '\u{2C54}', '\u{2C55}', '\u{2C56}', '\u{2C57}', '\u{2C58}', '\u{2C59}', '\u{2C5A}', '\u{2C5B}', '\u{2C5C}', '\u{2C5D}', '\u{2C5E}', '\u{2C61}', '\u{2C65}', '\u{2C66}', '\u{2C68}', '\u{2C6A}', '\u{2C6C}', '\u{2C71}', '\u{2C73}', '\u{2C74}', '\u{2C76}', '\u{2C77}', '\u{2C78}', '\u{2C79}', '\u{2C7A}', '\u{2C7B}', '\u{2C7C}', '\u{2C81}', '\u{2C83}', '\u{2C85}', '\u{2C87}', '\u{2C89}', '\u{2C8B}', '\u{2C8D}', '\u{2C8F}', '\u{2C91}', '\u{2C93}', '\u{2C95}', '\u{2C97}', '\u{2C99}', '\u{2C9B}', '\u{2C9D}', '\u{2C9F}', '\u{2CA1}', '\u{2CA3}', '\u{2CA5}', '\u{2CA7}', '\u{2CA9}', '\u{2CAB}', '\u{2CAD}', '\u{2CAF}', '\u{2CB1}', '\u{2CB3}', '\u{2CB5}', '\u{2CB7}', '\u{2CB9}', '\u{2CBB}', '\u{2CBD}', '\u{2CBF}', '\u{2CC1}', '\u{2CC3}', '\u{2CC5}', '\u{2CC7}', '\u{2CC9}', '\u{2CCB}', '\u{2CCD}', '\u{2CCF}', '\u{2CD1}', '\u{2CD3}', '\u{2CD5}', '\u{2CD7}', '\u{2CD9}', '\u{2CDB}', '\u{2CDD}', '\u{2CDF}', '\u{2CE1}', '\u{2CE3}', '\u{2CE4}', '\u{2D00}', '\u{2D01}', '\u{2D02}', '\u{2D03}', '\u{2D04}', '\u{2D05}', '\u{2D06}', '\u{2D07}', '\u{2D08}', '\u{2D09}', '\u{2D0A}', '\u{2D0B}', '\u{2D0C}', '\u{2D0D}', '\u{2D0E}', '\u{2D0F}', '\u{2D10}', '\u{2D11}', '\u{2D12}', '\u{2D13}', '\u{2D14}', '\u{2D15}', '\u{2D16}', '\u{2D17}', '\u{2D18}', '\u{2D19}', '\u{2D1A}', '\u{2D1B}', '\u{2D1C}', '\u{2D1D}', '\u{2D1E}', '\u{2D1F}', '\u{2D20}', '\u{2D21}', '\u{2D22}', '\u{2D23}', '\u{2D24}', '\u{2D25}', '\u{A641}', '\u{A643}', '\u{A645}', '\u{A647}', '\u{A649}', '\u{A64B}', '\u{A64D}', '\u{A64F}', '\u{A651}', '\u{A653}', '\u{A655}', '\u{A657}', '\u{A659}', '\u{A65B}', '\u{A65D}', '\u{A65F}', '\u{A663}', '\u{A665}', '\u{A667}', '\u{A669}', '\u{A66B}', '\u{A66D}', '\u{A681}', '\u{A683}', '\u{A685}', '\u{A687}', '\u{A689}', '\u{A68B}', '\u{A68D}', '\u{A68F}', '\u{A691}', '\u{A693}', '\u{A695}', '\u{A697}', '\u{A723}', '\u{A725}', '\u{A727}', '\u{A729}', '\u{A72B}', '\u{A72D}', '\u{A72F}', '\u{A730}', '\u{A731}', '\u{A733}', '\u{A735}', '\u{A737}', '\u{A739}', '\u{A73B}', '\u{A73D}', '\u{A73F}', '\u{A741}', '\u{A743}', '\u{A745}', '\u{A747}', '\u{A749}', '\u{A74B}', '\u{A74D}', '\u{A74F}', '\u{A751}', '\u{A753}', '\u{A755}', '\u{A757}', '\u{A759}', '\u{A75B}', '\u{A75D}', '\u{A75F}', '\u{A761}', '\u{A763}', '\u{A765}', '\u{A767}', '\u{A769}', '\u{A76B}', '\u{A76D}', '\u{A76F}', '\u{A771}', '\u{A772}', '\u{A773}', '\u{A774}', '\u{A775}', '\u{A776}', '\u{A777}', '\u{A778}', '\u{A77A}', '\u{A77C}', '\u{A77F}', '\u{A781}', '\u{A783}', '\u{A785}', '\u{A787}', '\u{A78C}', '\u{FB00}', '\u{FB01}', '\u{FB02}', '\u{FB03}', '\u{FB04}', '\u{FB05}', '\u{FB06}', '\u{FB13}', '\u{FB14}', '\u{FB15}', '\u{FB16}', '\u{FB17}', '\u{FF41}', '\u{FF42}', '\u{FF43}', '\u{FF44}', '\u{FF45}', '\u{FF46}', '\u{FF47}', '\u{FF48}', '\u{FF49}', '\u{FF4A}', '\u{FF4B}', '\u{FF4C}', '\u{FF4D}', '\u{FF4E}', '\u{FF4F}', '\u{FF50}', '\u{FF51}', '\u{FF52}', '\u{FF53}', '\u{FF54}', '\u{FF55}', '\u{FF56}', '\u{FF57}', '\u{FF58}', '\u{FF59}', '\u{FF5A}')
-
-    }
-
-    fn is_unicode_titlecase_letter(self) -> bool {
-        match_char_class!(self,
-            '\u{01C5}', '\u{01C8}', '\u{01CB}', '\u{01F2}', '\u{1F88}', '\u{1F89}', '\u{1F8A}', '\u{1F8B}', '\u{1F8C}', '\u{1F8D}', '\u{1F8E}', '\u{1F8F}', '\u{1F98}', '\u{1F99}', '\u{1F9A}', '\u{1F9B}', '\u{1F9C}', '\u{1F9D}', '\u{1F9E}', '\u{1F9F}', '\u{1FA8}', '\u{1FA9}', '\u{1FAA}', '\u{1FAB}', '\u{1FAC}', '\u{1FAD}', '\u{1FAE}', '\u{1FAF}', '\u{1FBC}', '\u{1FCC}')
-    }
-
-    fn is_unicode_modifier_letter(self) -> bool {
-        match_char_class!(self,
-            '\u{02B0}', '\u{02B1}', '\u{02B2}', '\u{02B3}', '\u{02B4}', '\u{02B5}', '\u{02B6}', '\u{02B7}', '\u{02B8}', '\u{02B9}', '\u{02BA}', '\u{02BB}', '\u{02BC}', '\u{02BD}', '\u{02BE}', '\u{02BF}', '\u{02C0}', '\u{02C1}', '\u{02C6}', '\u{02C7}', '\u{02C8}', '\u{02C9}', '\u{02CA}', '\u{02CB}', '\u{02CC}', '\u{02CD}', '\u{02CE}', '\u{02CF}', '\u{02D0}', '\u{02D1}', '\u{02E0}', '\u{02E1}', '\u{02E2}', '\u{02E3}', '\u{02E4}', '\u{02EC}', '\u{02EE}', '\u{0374}', '\u{037A}', '\u{0559}', '\u{0640}', '\u{06E5}', '\u{06E6}', '\u{07F4}', '\u{07F5}', '\u{07FA}', '\u{0971}', '\u{0E46}', '\u{0EC6}', '\u{10FC}', '\u{17D7}', '\u{1843}', '\u{1C78}', '\u{1C79}', '\u{1C7A}', '\u{1C7B}', '\u{1C7C}', '\u{1C7D}', '\u{1D2C}', '\u{1D2D}', '\u{1D2E}', '\u{1D2F}', '\u{1D30}', '\u{1D31}', '\u{1D32}', '\u{1D33}', '\u{1D34}', '\u{1D35}', '\u{1D36}', '\u{1D37}', '\u{1D38}', '\u{1D39}', '\u{1D3A}', '\u{1D3B}', '\u{1D3C}', '\u{1D3D}', '\u{1D3E}', '\u{1D3F}', '\u{1D40}', '\u{1D41}', '\u{1D42}', '\u{1D43}', '\u{1D44}', '\u{1D45}', '\u{1D46}', '\u{1D47}', '\u{1D48}', '\u{1D49}', '\u{1D4A}', '\u{1D4B}', '\u{1D4C}', '\u{1D4D}', '\u{1D4E}', '\u{1D4F}', '\u{1D50}', '\u{1D51}', '\u{1D52}', '\u{1D53}', '\u{1D54}', '\u{1D55}', '\u{1D56}', '\u{1D57}', '\u{1D58}', '\u{1D59}', '\u{1D5A}', '\u{1D5B}', '\u{1D5C}', '\u{1D5D}', '\u{1D5E}', '\u{1D5F}', '\u{1D60}', '\u{1D61}', '\u{1D78}', '\u{1D9B}', '\u{1D9C}', '\u{1D9D}', '\u{1D9E}', '\u{1D9F}', '\u{1DA0}', '\u{1DA1}', '\u{1DA2}', '\u{1DA3}', '\u{1DA4}', '\u{1DA5}', '\u{1DA6}', '\u{1DA7}', '\u{1DA8}', '\u{1DA9}', '\u{1DAA}', '\u{1DAB}', '\u{1DAC}', '\u{1DAD}', '\u{1DAE}', '\u{1DAF}', '\u{1DB0}', '\u{1DB1}', '\u{1DB2}', '\u{1DB3}', '\u{1DB4}', '\u{1DB5}', '\u{1DB6}', '\u{1DB7}', '\u{1DB8}', '\u{1DB9}', '\u{1DBA}', '\u{1DBB}', '\u{1DBC}', '\u{1DBD}', '\u{1DBE}', '\u{1DBF}', '\u{2090}', '\u{2091}', '\u{2092}', '\u{2093}', '\u{2094}', '\u{2C7D}', '\u{2D6F}', '\u{2E2F}', '\u{3005}', '\u{3031}', '\u{3032}', '\u{3033}', '\u{3034}', '\u{3035}', '\u{303B}', '\u{309D}', '\u{309E}', '\u{30FC}', '\u{30FD}', '\u{30FE}', '\u{A015}', '\u{A60C}', '\u{A67F}', '\u{A717}', '\u{A718}', '\u{A719}', '\u{A71A}', '\u{A71B}', '\u{A71C}', '\u{A71D}', '\u{A71E}', '\u{A71F}', '\u{A770}', '\u{A788}', '\u{FF70}', '\u{FF9E}', '\u{FF9F}')
-    }
-
-    fn is_unicode_other_letter(self) -> bool {
-        match_char_class!(self,
-             '\u{01BB}', '\u{01C0}', '\u{01C1}', '\u{01C2}', '\u{01C3}', '\u{0294}', '\u{05D0}', '\u{05D1}', '\u{05D2}', '\u{05D3}', '\u{05D4}', '\u{05D5}', '\u{05D6}', '\u{05D7}', '\u{05D8}', '\u{05D9}', '\u{05DA}', '\u{05DB}', '\u{05DC}', '\u{05DD}', '\u{05DE}', '\u{05DF}', '\u{05E0}', '\u{05E1}', '\u{05E2}', '\u{05E3}', '\u{05E4}', '\u{05E5}', '\u{05E6}', '\u{05E7}', '\u{05E8}', '\u{05E9}', '\u{05EA}', '\u{05F0}', '\u{05F1}', '\u{05F2}', '\u{0621}', '\u{0622}', '\u{0623}', '\u{0624}', '\u{0625}', '\u{0626}', '\u{0627}', '\u{0628}', '\u{0629}', '\u{062A}', '\u{062B}', '\u{062C}', '\u{062D}', '\u{062E}', '\u{062F}', '\u{0630}', '\u{0631}', '\u{0632}', '\u{0633}', '\u{0634}', '\u{0635}', '\u{0636}', '\u{0637}', '\u{0638}', '\u{0639}', '\u{063A}', '\u{063B}', '\u{063C}', '\u{063D}', '\u{063E}', '\u{063F}', '\u{0641}', '\u{0642}', '\u{0643}', '\u{0644}', '\u{0645}', '\u{0646}', '\u{0647}', '\u{0648}', '\u{0649}', '\u{064A}', '\u{066E}', '\u{066F}', '\u{0671}', '\u{0672}', '\u{0673}', '\u{0674}', '\u{0675}', '\u{0676}', '\u{0677}', '\u{0678}', '\u{0679}', '\u{067A}', '\u{067B}', '\u{067C}', '\u{067D}', '\u{067E}', '\u{067F}', '\u{0680}', '\u{0681}', '\u{0682}', '\u{0683}', '\u{0684}', '\u{0685}', '\u{0686}', '\u{0687}', '\u{0688}', '\u{0689}', '\u{068A}', '\u{068B}', '\u{068C}', '\u{068D}', '\u{068E}', '\u{068F}', '\u{0690}', '\u{0691}', '\u{0692}', '\u{0693}', '\u{0694}', '\u{0695}', '\u{0696}', '\u{0697}', '\u{0698}', '\u{0699}', '\u{069A}', '\u{069B}', '\u{069C}', '\u{069D}', '\u{069E}', '\u{069F}', '\u{06A0}', '\u{06A1}', '\u{06A2}', '\u{06A3}', '\u{06A4}', '\u{06A5}', '\u{06A6}', '\u{06A7}', '\u{06A8}', '\u{06A9}', '\u{06AA}', '\u{06AB}', '\u{06AC}', '\u{06AD}', '\u{06AE}', '\u{06AF}', '\u{06B0}', '\u{06B1}', '\u{06B2}', '\u{06B3}', '\u{06B4}', '\u{06B5}', '\u{06B6}', '\u{06B7}', '\u{06B8}', '\u{06B9}', '\u{06BA}', '\u{06BB}', '\u{06BC}', '\u{06BD}', '\u{06BE}', '\u{06BF}', '\u{06C0}', '\u{06C1}', '\u{06C2}', '\u{06C3}', '\u{06C4}', '\u{06C5}', '\u{06C6}', '\u{06C7}', '\u{06C8}', '\u{06C9}', '\u{06CA}', '\u{06CB}', '\u{06CC}', '\u{06CD}', '\u{06CE}', '\u{06CF}', '\u{06D0}', '\u{06D1}', '\u{06D2}', '\u{06D3}', '\u{06D5}', '\u{06EE}', '\u{06EF}', '\u{06FA}', '\u{06FB}', '\u{06FC}', '\u{06FF}', '\u{0710}', '\u{0712}', '\u{0713}', '\u{0714}', '\u{0715}', '\u{0716}', '\u{0717}', '\u{0718}', '\u{0719}', '\u{071A}', '\u{071B}', '\u{071C}', '\u{071D}', '\u{071E}', '\u{071F}', '\u{0720}', '\u{0721}', '\u{0722}', '\u{0723}', '\u{0724}', '\u{0725}', '\u{0726}', '\u{0727}', '\u{0728}', '\u{0729}', '\u{072A}', '\u{072B}', '\u{072C}', '\u{072D}', '\u{072E}', '\u{072F}', '\u{074D}', '\u{074E}', '\u{074F}', '\u{0750}', '\u{0751}', '\u{0752}', '\u{0753}', '\u{0754}', '\u{0755}', '\u{0756}', '\u{0757}', '\u{0758}', '\u{0759}', '\u{075A}', '\u{075B}', '\u{075C}', '\u{075D}', '\u{075E}', '\u{075F}', '\u{0760}', '\u{0761}', '\u{0762}', '\u{0763}', '\u{0764}', '\u{0765}', '\u{0766}', '\u{0767}', '\u{0768}', '\u{0769}', '\u{076A}', '\u{076B}', '\u{076C}', '\u{076D}', '\u{076E}', '\u{076F}', '\u{0770}', '\u{0771}', '\u{0772}', '\u{0773}', '\u{0774}', '\u{0775}', '\u{0776}', '\u{0777}', '\u{0778}', '\u{0779}', '\u{077A}', '\u{077B}', '\u{077C}', '\u{077D}', '\u{077E}', '\u{077F}', '\u{0780}', '\u{0781}', '\u{0782}', '\u{0783}', '\u{0784}', '\u{0785}', '\u{0786}', '\u{0787}', '\u{0788}', '\u{0789}', '\u{078A}', '\u{078B}', '\u{078C}', '\u{078D}', '\u{078E}', '\u{078F}', '\u{0790}', '\u{0791}', '\u{0792}', '\u{0793}', '\u{0794}', '\u{0795}', '\u{0796}', '\u{0797}', '\u{0798}', '\u{0799}', '\u{079A}', '\u{079B}', '\u{079C}', '\u{079D}', '\u{079E}', '\u{079F}', '\u{07A0}', '\u{07A1}', '\u{07A2}', '\u{07A3}', '\u{07A4}', '\u{07A5}', '\u{07B1}', '\u{07CA}', '\u{07CB}', '\u{07CC}', '\u{07CD}', '\u{07CE}', '\u{07CF}', '\u{07D0}', '\u{07D1}', '\u{07D2}', '\u{07D3}', '\u{07D4}', '\u{07D5}', '\u{07D6}', '\u{07D7}', '\u{07D8}', '\u{07D9}', '\u{07DA}', '\u{07DB}', '\u{07DC}', '\u{07DD}', '\u{07DE}', '\u{07DF}', '\u{07E0}', '\u{07E1}', '\u{07E2}', '\u{07E3}', '\u{07E4}', '\u{07E5}', '\u{07E6}', '\u{07E7}', '\u{07E8}', '\u{07E9}', '\u{07EA}', '\u{0904}', '\u{0905}', '\u{0906}', '\u{0907}', '\u{0908}', '\u{0909}', '\u{090A}', '\u{090B}', '\u{090C}', '\u{090D}', '\u{090E}', '\u{090F}', '\u{0910}', '\u{0911}', '\u{0912}', '\u{0913}', '\u{0914}', '\u{0915}', '\u{0916}', '\u{0917}', '\u{0918}', '\u{0919}', '\u{091A}', '\u{091B}', '\u{091C}', '\u{091D}', '\u{091E}', '\u{091F}', '\u{0920}', '\u{0921}', '\u{0922}', '\u{0923}', '\u{0924}', '\u{0925}', '\u{0926}', '\u{0927}', '\u{0928}', '\u{0929}', '\u{092A}', '\u{092B}', '\u{092C}', '\u{092D}', '\u{092E}', '\u{092F}', '\u{0930}', '\u{0931}', '\u{0932}', '\u{0933}', '\u{0934}', '\u{0935}', '\u{0936}', '\u{0937}', '\u{0938}', '\u{0939}', '\u{093D}', '\u{0950}', '\u{0958}', '\u{0959}', '\u{095A}', '\u{095B}', '\u{095C}', '\u{095D}', '\u{095E}', '\u{095F}', '\u{0960}', '\u{0961}', '\u{0972}', '\u{097B}', '\u{097C}', '\u{097D}', '\u{097E}', '\u{097F}', '\u{0985}', '\u{0986}', '\u{0987}', '\u{0988}', '\u{0989}', '\u{098A}', '\u{098B}', '\u{098C}', '\u{098F}', '\u{0990}', '\u{0993}', '\u{0994}', '\u{0995}', '\u{0996}', '\u{0997}', '\u{0998}', '\u{0999}', '\u{099A}', '\u{099B}', '\u{099C}', '\u{099D}', '\u{099E}', '\u{099F}', '\u{09A0}', '\u{09A1}', '\u{09A2}', '\u{09A3}', '\u{09A4}', '\u{09A5}', '\u{09A6}', '\u{09A7}', '\u{09A8}', '\u{09AA}', '\u{09AB}', '\u{09AC}', '\u{09AD}', '\u{09AE}', '\u{09AF}', '\u{09B0}', '\u{09B2}', '\u{09B6}', '\u{09B7}', '\u{09B8}', '\u{09B9}', '\u{09BD}', '\u{09CE}', '\u{09DC}', '\u{09DD}', '\u{09DF}', '\u{09E0}', '\u{09E1}', '\u{09F0}', '\u{09F1}', '\u{0A05}', '\u{0A06}', '\u{0A07}', '\u{0A08}', '\u{0A09}', '\u{0A0A}', '\u{0A0F}', '\u{0A10}', '\u{0A13}', '\u{0A14}', '\u{0A15}', '\u{0A16}', '\u{0A17}', '\u{0A18}', '\u{0A19}', '\u{0A1A}', '\u{0A1B}', '\u{0A1C}', '\u{0A1D}', '\u{0A1E}', '\u{0A1F}', '\u{0A20}', '\u{0A21}', '\u{0A22}', '\u{0A23}', '\u{0A24}', '\u{0A25}', '\u{0A26}', '\u{0A27}', '\u{0A28}', '\u{0A2A}', '\u{0A2B}', '\u{0A2C}', '\u{0A2D}', '\u{0A2E}', '\u{0A2F}', '\u{0A30}', '\u{0A32}', '\u{0A33}', '\u{0A35}', '\u{0A36}', '\u{0A38}', '\u{0A39}', '\u{0A59}', '\u{0A5A}', '\u{0A5B}', '\u{0A5C}', '\u{0A5E}', '\u{0A72}', '\u{0A73}', '\u{0A74}', '\u{0A85}', '\u{0A86}', '\u{0A87}', '\u{0A88}', '\u{0A89}', '\u{0A8A}', '\u{0A8B}', '\u{0A8C}', '\u{0A8D}', '\u{0A8F}', '\u{0A90}', '\u{0A91}', '\u{0A93}', '\u{0A94}', '\u{0A95}', '\u{0A96}', '\u{0A97}', '\u{0A98}', '\u{0A99}', '\u{0A9A}', '\u{0A9B}', '\u{0A9C}', '\u{0A9D}', '\u{0A9E}', '\u{0A9F}', '\u{0AA0}', '\u{0AA1}', '\u{0AA2}', '\u{0AA3}', '\u{0AA4}', '\u{0AA5}', '\u{0AA6}', '\u{0AA7}', '\u{0AA8}', '\u{0AAA}', '\u{0AAB}', '\u{0AAC}', '\u{0AAD}', '\u{0AAE}', '\u{0AAF}', '\u{0AB0}', '\u{0AB2}', '\u{0AB3}', '\u{0AB5}', '\u{0AB6}', '\u{0AB7}', '\u{0AB8}', '\u{0AB9}', '\u{0ABD}', '\u{0AD0}', '\u{0AE0}', '\u{0AE1}', '\u{0B05}', '\u{0B06}', '\u{0B07}', '\u{0B08}', '\u{0B09}', '\u{0B0A}', '\u{0B0B}', '\u{0B0C}', '\u{0B0F}', '\u{0B10}', '\u{0B13}', '\u{0B14}', '\u{0B15}', '\u{0B16}', '\u{0B17}', '\u{0B18}', '\u{0B19}', '\u{0B1A}', '\u{0B1B}', '\u{0B1C}', '\u{0B1D}', '\u{0B1E}', '\u{0B1F}', '\u{0B20}', '\u{0B21}', '\u{0B22}', '\u{0B23}', '\u{0B24}', '\u{0B25}', '\u{0B26}', '\u{0B27}', '\u{0B28}', '\u{0B2A}', '\u{0B2B}', '\u{0B2C}', '\u{0B2D}', '\u{0B2E}', '\u{0B2F}', '\u{0B30}', '\u{0B32}', '\u{0B33}', '\u{0B35}', '\u{0B36}', '\u{0B37}', '\u{0B38}', '\u{0B39}', '\u{0B3D}', '\u{0B5C}', '\u{0B5D}', '\u{0B5F}', '\u{0B60}', '\u{0B61}', '\u{0B71}', '\u{0B83}', '\u{0B85}', '\u{0B86}', '\u{0B87}', '\u{0B88}', '\u{0B89}', '\u{0B8A}', '\u{0B8E}', '\u{0B8F}', '\u{0B90}', '\u{0B92}', '\u{0B93}', '\u{0B94}', '\u{0B95}', '\u{0B99}', '\u{0B9A}', '\u{0B9C}', '\u{0B9E}', '\u{0B9F}', '\u{0BA3}', '\u{0BA4}', '\u{0BA8}', '\u{0BA9}', '\u{0BAA}', '\u{0BAE}', '\u{0BAF}', '\u{0BB0}', '\u{0BB1}', '\u{0BB2}', '\u{0BB3}', '\u{0BB4}', '\u{0BB5}', '\u{0BB6}', '\u{0BB7}', '\u{0BB8}', '\u{0BB9}', '\u{0BD0}', '\u{0C05}', '\u{0C06}', '\u{0C07}', '\u{0C08}', '\u{0C09}', '\u{0C0A}', '\u{0C0B}', '\u{0C0C}', '\u{0C0E}', '\u{0C0F}', '\u{0C10}', '\u{0C12}', '\u{0C13}', '\u{0C14}', '\u{0C15}', '\u{0C16}', '\u{0C17}', '\u{0C18}', '\u{0C19}', '\u{0C1A}', '\u{0C1B}', '\u{0C1C}', '\u{0C1D}', '\u{0C1E}', '\u{0C1F}', '\u{0C20}', '\u{0C21}', '\u{0C22}', '\u{0C23}', '\u{0C24}', '\u{0C25}', '\u{0C26}', '\u{0C27}', '\u{0C28}', '\u{0C2A}', '\u{0C2B}', '\u{0C2C}', '\u{0C2D}', '\u{0C2E}', '\u{0C2F}', '\u{0C30}', '\u{0C31}', '\u{0C32}', '\u{0C33}', '\u{0C35}', '\u{0C36}', '\u{0C37}', '\u{0C38}', '\u{0C39}', '\u{0C3D}', '\u{0C58}', '\u{0C59}', '\u{0C60}', '\u{0C61}', '\u{0C85}', '\u{0C86}', '\u{0C87}', '\u{0C88}', '\u{0C89}', '\u{0C8A}', '\u{0C8B}', '\u{0C8C}', '\u{0C8E}', '\u{0C8F}', '\u{0C90}', '\u{0C92}', '\u{0C93}', '\u{0C94}', '\u{0C95}', '\u{0C96}', '\u{0C97}', '\u{0C98}', '\u{0C99}', '\u{0C9A}', '\u{0C9B}', '\u{0C9C}', '\u{0C9D}', '\u{0C9E}', '\u{0C9F}', '\u{0CA0}', '\u{0CA1}', '\u{0CA2}', '\u{0CA3}', '\u{0CA4}', '\u{0CA5}', '\u{0CA6}', '\u{0CA7}', '\u{0CA8}', '\u{0CAA}', '\u{0CAB}', '\u{0CAC}', '\u{0CAD}', '\u{0CAE}', '\u{0CAF}', '\u{0CB0}', '\u{0CB1}', '\u{0CB2}', '\u{0CB3}', '\u{0CB5}', '\u{0CB6}', '\u{0CB7}', '\u{0CB8}', '\u{0CB9}', '\u{0CBD}', '\u{0CDE}', '\u{0CE0}', '\u{0CE1}', '\u{0D05}', '\u{0D06}', '\u{0D07}', '\u{0D08}', '\u{0D09}', '\u{0D0A}', '\u{0D0B}', '\u{0D0C}', '\u{0D0E}', '\u{0D0F}', '\u{0D10}', '\u{0D12}', '\u{0D13}', '\u{0D14}', '\u{0D15}', '\u{0D16}', '\u{0D17}', '\u{0D18}', '\u{0D19}', '\u{0D1A}', '\u{0D1B}', '\u{0D1C}', '\u{0D1D}', '\u{0D1E}', '\u{0D1F}', '\u{0D20}', '\u{0D21}', '\u{0D22}', '\u{0D23}', '\u{0D24}', '\u{0D25}', '\u{0D26}', '\u{0D27}', '\u{0D28}', '\u{0D2A}', '\u{0D2B}', '\u{0D2C}', '\u{0D2D}', '\u{0D2E}', '\u{0D2F}', '\u{0D30}', '\u{0D31}', '\u{0D32}', '\u{0D33}', '\u{0D34}', '\u{0D35}', '\u{0D36}', '\u{0D37}', '\u{0D38}', '\u{0D39}', '\u{0D3D}', '\u{0D60}', '\u{0D61}', '\u{0D7A}', '\u{0D7B}', '\u{0D7C}', '\u{0D7D}', '\u{0D7E}', '\u{0D7F}', '\u{0D85}', '\u{0D86}', '\u{0D87}', '\u{0D88}', '\u{0D89}', '\u{0D8A}', '\u{0D8B}', '\u{0D8C}', '\u{0D8D}', '\u{0D8E}', '\u{0D8F}', '\u{0D90}', '\u{0D91}', '\u{0D92}', '\u{0D93}', '\u{0D94}', '\u{0D95}', '\u{0D96}', '\u{0D9A}', '\u{0D9B}', '\u{0D9C}', '\u{0D9D}', '\u{0D9E}', '\u{0D9F}', '\u{0DA0}', '\u{0DA1}', '\u{0DA2}', '\u{0DA3}', '\u{0DA4}', '\u{0DA5}', '\u{0DA6}', '\u{0DA7}', '\u{0DA8}', '\u{0DA9}', '\u{0DAA}', '\u{0DAB}', '\u{0DAC}', '\u{0DAD}', '\u{0DAE}', '\u{0DAF}', '\u{0DB0}', '\u{0DB1}', '\u{0DB3}', '\u{0DB4}', '\u{0DB5}', '\u{0DB6}', '\u{0DB7}', '\u{0DB8}', '\u{0DB9}', '\u{0DBA}', '\u{0DBB}', '\u{0DBD}', '\u{0DC0}', '\u{0DC1}', '\u{0DC2}', '\u{0DC3}', '\u{0DC4}', '\u{0DC5}', '\u{0DC6}', '\u{0E01}', '\u{0E02}', '\u{0E03}', '\u{0E04}', '\u{0E05}', '\u{0E06}', '\u{0E07}', '\u{0E08}', '\u{0E09}', '\u{0E0A}', '\u{0E0B}', '\u{0E0C}', '\u{0E0D}', '\u{0E0E}', '\u{0E0F}', '\u{0E10}', '\u{0E11}', '\u{0E12}', '\u{0E13}', '\u{0E14}', '\u{0E15}', '\u{0E16}', '\u{0E17}', '\u{0E18}', '\u{0E19}', '\u{0E1A}', '\u{0E1B}', '\u{0E1C}', '\u{0E1D}', '\u{0E1E}', '\u{0E1F}', '\u{0E20}', '\u{0E21}', '\u{0E22}', '\u{0E23}', '\u{0E24}', '\u{0E25}', '\u{0E26}', '\u{0E27}', '\u{0E28}', '\u{0E29}', '\u{0E2A}', '\u{0E2B}', '\u{0E2C}', '\u{0E2D}', '\u{0E2E}', '\u{0E2F}', '\u{0E30}', '\u{0E32}', '\u{0E33}', '\u{0E40}', '\u{0E41}', '\u{0E42}', '\u{0E43}', '\u{0E44}', '\u{0E45}', '\u{0E81}', '\u{0E82}', '\u{0E84}', '\u{0E87}', '\u{0E88}', '\u{0E8A}', '\u{0E8D}', '\u{0E94}', '\u{0E95}', '\u{0E96}', '\u{0E97}', '\u{0E99}', '\u{0E9A}', '\u{0E9B}', '\u{0E9C}', '\u{0E9D}', '\u{0E9E}', '\u{0E9F}', '\u{0EA1}', '\u{0EA2}', '\u{0EA3}', '\u{0EA5}', '\u{0EA7}', '\u{0EAA}', '\u{0EAB}', '\u{0EAD}', '\u{0EAE}', '\u{0EAF}', '\u{0EB0}', '\u{0EB2}', '\u{0EB3}', '\u{0EBD}', '\u{0EC0}', '\u{0EC1}', '\u{0EC2}', '\u{0EC3}', '\u{0EC4}', '\u{0EDC}', '\u{0EDD}', '\u{0F00}', '\u{0F40}', '\u{0F41}', '\u{0F42}', '\u{0F43}', '\u{0F44}', '\u{0F45}', '\u{0F46}', '\u{0F47}', '\u{0F49}', '\u{0F4A}', '\u{0F4B}', '\u{0F4C}', '\u{0F4D}', '\u{0F4E}', '\u{0F4F}', '\u{0F50}', '\u{0F51}', '\u{0F52}', '\u{0F53}', '\u{0F54}', '\u{0F55}', '\u{0F56}', '\u{0F57}', '\u{0F58}', '\u{0F59}', '\u{0F5A}', '\u{0F5B}', '\u{0F5C}', '\u{0F5D}', '\u{0F5E}', '\u{0F5F}', '\u{0F60}', '\u{0F61}', '\u{0F62}', '\u{0F63}', '\u{0F64}', '\u{0F65}', '\u{0F66}', '\u{0F67}', '\u{0F68}', '\u{0F69}', '\u{0F6A}', '\u{0F6B}', '\u{0F6C}', '\u{0F88}', '\u{0F89}', '\u{0F8A}', '\u{0F8B}', '\u{1000}', '\u{1001}', '\u{1002}', '\u{1003}', '\u{1004}', '\u{1005}', '\u{1006}', '\u{1007}', '\u{1008}', '\u{1009}', '\u{100A}', '\u{100B}', '\u{100C}', '\u{100D}', '\u{100E}', '\u{100F}', '\u{1010}', '\u{1011}', '\u{1012}', '\u{1013}', '\u{1014}', '\u{1015}', '\u{1016}', '\u{1017}', '\u{1018}', '\u{1019}', '\u{101A}', '\u{101B}', '\u{101C}', '\u{101D}', '\u{101E}', '\u{101F}', '\u{1020}', '\u{1021}', '\u{1022}', '\u{1023}', '\u{1024}', '\u{1025}', '\u{1026}', '\u{1027}', '\u{1028}', '\u{1029}', '\u{102A}', '\u{103F}', '\u{1050}', '\u{1051}', '\u{1052}', '\u{1053}', '\u{1054}', '\u{1055}', '\u{105A}', '\u{105B}', '\u{105C}', '\u{105D}', '\u{1061}', '\u{1065}', '\u{1066}', '\u{106E}', '\u{106F}', '\u{1070}', '\u{1075}', '\u{1076}', '\u{1077}', '\u{1078}', '\u{1079}', '\u{107A}', '\u{107B}', '\u{107C}', '\u{107D}', '\u{107E}', '\u{107F}', '\u{1080}', '\u{1081}', '\u{108E}', '\u{10D0}', '\u{10D1}', '\u{10D2}', '\u{10D3}', '\u{10D4}', '\u{10D5}', '\u{10D6}', '\u{10D7}', '\u{10D8}', '\u{10D9}', '\u{10DA}', '\u{10DB}', '\u{10DC}', '\u{10DD}', '\u{10DE}', '\u{10DF}', '\u{10E0}', '\u{10E1}', '\u{10E2}', '\u{10E3}', '\u{10E4}', '\u{10E5}', '\u{10E6}', '\u{10E7}', '\u{10E8}', '\u{10E9}', '\u{10EA}', '\u{10EB}', '\u{10EC}', '\u{10ED}', '\u{10EE}', '\u{10EF}', '\u{10F0}', '\u{10F1}', '\u{10F2}', '\u{10F3}', '\u{10F4}', '\u{10F5}', '\u{10F6}', '\u{10F7}', '\u{10F8}', '\u{10F9}', '\u{10FA}', '\u{1100}', '\u{1101}', '\u{1102}', '\u{1103}', '\u{1104}', '\u{1105}', '\u{1106}', '\u{1107}', '\u{1108}', '\u{1109}', '\u{110A}', '\u{110B}', '\u{110C}', '\u{110D}', '\u{110E}', '\u{110F}', '\u{1110}', '\u{1111}', '\u{1112}', '\u{1113}', '\u{1114}', '\u{1115}', '\u{1116}', '\u{1117}', '\u{1118}', '\u{1119}', '\u{111A}', '\u{111B}', '\u{111C}', '\u{111D}', '\u{111E}', '\u{111F}', '\u{1120}', '\u{1121}', '\u{1122}', '\u{1123}', '\u{1124}', '\u{1125}', '\u{1126}', '\u{1127}', '\u{1128}', '\u{1129}', '\u{112A}', '\u{112B}', '\u{112C}', '\u{112D}', '\u{112E}', '\u{112F}', '\u{1130}', '\u{1131}', '\u{1132}', '\u{1133}', '\u{1134}', '\u{1135}', '\u{1136}', '\u{1137}', '\u{1138}', '\u{1139}', '\u{113A}', '\u{113B}', '\u{113C}', '\u{113D}', '\u{113E}', '\u{113F}', '\u{1140}', '\u{1141}', '\u{1142}', '\u{1143}', '\u{1144}', '\u{1145}', '\u{1146}', '\u{1147}', '\u{1148}', '\u{1149}', '\u{114A}', '\u{114B}', '\u{114C}', '\u{114D}', '\u{114E}', '\u{114F}', '\u{1150}', '\u{1151}', '\u{1152}', '\u{1153}', '\u{1154}', '\u{1155}', '\u{1156}', '\u{1157}', '\u{1158}', '\u{1159}', '\u{115F}', '\u{1160}', '\u{1161}', '\u{1162}', '\u{1163}', '\u{1164}', '\u{1165}', '\u{1166}', '\u{1167}', '\u{1168}', '\u{1169}', '\u{116A}', '\u{116B}', '\u{116C}', '\u{116D}', '\u{116E}', '\u{116F}', '\u{1170}', '\u{1171}', '\u{1172}', '\u{1173}', '\u{1174}', '\u{1175}', '\u{1176}', '\u{1177}', '\u{1178}', '\u{1179}', '\u{117A}', '\u{117B}', '\u{117C}', '\u{117D}', '\u{117E}', '\u{117F}', '\u{1180}', '\u{1181}', '\u{1182}', '\u{1183}', '\u{1184}', '\u{1185}', '\u{1186}', '\u{1187}', '\u{1188}', '\u{1189}', '\u{118A}', '\u{118B}', '\u{118C}', '\u{118D}', '\u{118E}', '\u{118F}', '\u{1190}', '\u{1191}', '\u{1192}', '\u{1193}', '\u{1194}', '\u{1195}', '\u{1196}', '\u{1197}', '\u{1198}', '\u{1199}', '\u{119A}', '\u{119B}', '\u{119C}', '\u{119D}', '\u{119E}', '\u{119F}', '\u{11A0}', '\u{11A1}', '\u{11A2}', '\u{11A8}', '\u{11A9}', '\u{11AA}', '\u{11AB}', '\u{11AC}', '\u{11AD}', '\u{11AE}', '\u{11AF}', '\u{11B0}', '\u{11B1}', '\u{11B2}', '\u{11B3}', '\u{11B4}', '\u{11B5}', '\u{11B6}', '\u{11B7}', '\u{11B8}', '\u{11B9}', '\u{11BA}', '\u{11BB}', '\u{11BC}', '\u{11BD}', '\u{11BE}', '\u{11BF}', '\u{11C0}', '\u{11C1}', '\u{11C2}', '\u{11C3}', '\u{11C4}', '\u{11C5}', '\u{11C6}', '\u{11C7}', '\u{11C8}', '\u{11C9}', '\u{11CA}', '\u{11CB}', '\u{11CC}', '\u{11CD}', '\u{11CE}', '\u{11CF}', '\u{11D0}', '\u{11D1}', '\u{11D2}', '\u{11D3}', '\u{11D4}', '\u{11D5}', '\u{11D6}', '\u{11D7}', '\u{11D8}', '\u{11D9}', '\u{11DA}', '\u{11DB}', '\u{11DC}', '\u{11DD}', '\u{11DE}', '\u{11DF}', '\u{11E0}', '\u{11E1}', '\u{11E2}', '\u{11E3}', '\u{11E4}', '\u{11E5}', '\u{11E6}', '\u{11E7}', '\u{11E8}', '\u{11E9}', '\u{11EA}', '\u{11EB}', '\u{11EC}', '\u{11ED}', '\u{11EE}', '\u{11EF}', '\u{11F0}', '\u{11F1}', '\u{11F2}', '\u{11F3}', '\u{11F4}', '\u{11F5}', '\u{11F6}', '\u{11F7}', '\u{11F8}', '\u{11F9}', '\u{1200}', '\u{1201}', '\u{1202}', '\u{1203}', '\u{1204}', '\u{1205}', '\u{1206}', '\u{1207}', '\u{1208}', '\u{1209}', '\u{120A}', '\u{120B}', '\u{120C}', '\u{120D}', '\u{120E}', '\u{120F}', '\u{1210}', '\u{1211}', '\u{1212}', '\u{1213}', '\u{1214}', '\u{1215}', '\u{1216}', '\u{1217}', '\u{1218}', '\u{1219}', '\u{121A}', '\u{121B}', '\u{121C}', '\u{121D}', '\u{121E}', '\u{121F}', '\u{1220}', '\u{1221}', '\u{1222}', '\u{1223}', '\u{1224}', '\u{1225}', '\u{1226}', '\u{1227}', '\u{1228}', '\u{1229}', '\u{122A}', '\u{122B}', '\u{122C}', '\u{122D}', '\u{122E}', '\u{122F}', '\u{1230}', '\u{1231}', '\u{1232}', '\u{1233}', '\u{1234}', '\u{1235}', '\u{1236}', '\u{1237}', '\u{1238}', '\u{1239}', '\u{123A}', '\u{123B}', '\u{123C}', '\u{123D}', '\u{123E}', '\u{123F}', '\u{1240}', '\u{1241}', '\u{1242}', '\u{1243}', '\u{1244}', '\u{1245}', '\u{1246}', '\u{1247}', '\u{1248}', '\u{124A}', '\u{124B}', '\u{124C}', '\u{124D}', '\u{1250}', '\u{1251}', '\u{1252}', '\u{1253}', '\u{1254}', '\u{1255}', '\u{1256}', '\u{1258}', '\u{125A}', '\u{125B}', '\u{125C}', '\u{125D}', '\u{1260}', '\u{1261}', '\u{1262}', '\u{1263}', '\u{1264}', '\u{1265}', '\u{1266}', '\u{1267}', '\u{1268}', '\u{1269}', '\u{126A}', '\u{126B}', '\u{126C}', '\u{126D}', '\u{126E}', '\u{126F}', '\u{1270}', '\u{1271}', '\u{1272}', '\u{1273}', '\u{1274}', '\u{1275}', '\u{1276}', '\u{1277}', '\u{1278}', '\u{1279}', '\u{127A}', '\u{127B}', '\u{127C}', '\u{127D}', '\u{127E}', '\u{127F}', '\u{1280}', '\u{1281}', '\u{1282}', '\u{1283}', '\u{1284}', '\u{1285}', '\u{1286}', '\u{1287}', '\u{1288}', '\u{128A}', '\u{128B}', '\u{128C}', '\u{128D}', '\u{1290}', '\u{1291}', '\u{1292}', '\u{1293}', '\u{1294}', '\u{1295}', '\u{1296}', '\u{1297}', '\u{1298}', '\u{1299}', '\u{129A}', '\u{129B}', '\u{129C}', '\u{129D}', '\u{129E}', '\u{129F}', '\u{12A0}', '\u{12A1}', '\u{12A2}', '\u{12A3}', '\u{12A4}', '\u{12A5}', '\u{12A6}', '\u{12A7}', '\u{12A8}', '\u{12A9}', '\u{12AA}', '\u{12AB}', '\u{12AC}', '\u{12AD}', '\u{12AE}', '\u{12AF}', '\u{12B0}', '\u{12B2}', '\u{12B3}', '\u{12B4}', '\u{12B5}', '\u{12B8}', '\u{12B9}', '\u{12BA}', '\u{12BB}', '\u{12BC}', '\u{12BD}', '\u{12BE}', '\u{12C0}', '\u{12C2}', '\u{12C3}', '\u{12C4}', '\u{12C5}', '\u{12C8}', '\u{12C9}', '\u{12CA}', '\u{12CB}', '\u{12CC}', '\u{12CD}', '\u{12CE}', '\u{12CF}', '\u{12D0}', '\u{12D1}', '\u{12D2}', '\u{12D3}', '\u{12D4}', '\u{12D5}', '\u{12D6}', '\u{12D8}', '\u{12D9}', '\u{12DA}', '\u{12DB}', '\u{12DC}', '\u{12DD}', '\u{12DE}', '\u{12DF}', '\u{12E0}', '\u{12E1}', '\u{12E2}', '\u{12E3}', '\u{12E4}', '\u{12E5}', '\u{12E6}', '\u{12E7}', '\u{12E8}', '\u{12E9}', '\u{12EA}', '\u{12EB}', '\u{12EC}', '\u{12ED}', '\u{12EE}', '\u{12EF}', '\u{12F0}', '\u{12F1}', '\u{12F2}', '\u{12F3}', '\u{12F4}', '\u{12F5}', '\u{12F6}', '\u{12F7}', '\u{12F8}', '\u{12F9}', '\u{12FA}', '\u{12FB}', '\u{12FC}', '\u{12FD}', '\u{12FE}', '\u{12FF}', '\u{1300}', '\u{1301}', '\u{1302}', '\u{1303}', '\u{1304}', '\u{1305}', '\u{1306}', '\u{1307}', '\u{1308}', '\u{1309}', '\u{130A}', '\u{130B}', '\u{130C}', '\u{130D}', '\u{130E}', '\u{130F}', '\u{1310}', '\u{1312}', '\u{1313}', '\u{1314}', '\u{1315}', '\u{1318}', '\u{1319}', '\u{131A}', '\u{131B}', '\u{131C}', '\u{131D}', '\u{131E}', '\u{131F}', '\u{1320}', '\u{1321}', '\u{1322}', '\u{1323}', '\u{1324}', '\u{1325}', '\u{1326}', '\u{1327}', '\u{1328}', '\u{1329}', '\u{132A}', '\u{132B}', '\u{132C}', '\u{132D}', '\u{132E}', '\u{132F}', '\u{1330}', '\u{1331}', '\u{1332}', '\u{1333}', '\u{1334}', '\u{1335}', '\u{1336}', '\u{1337}', '\u{1338}', '\u{1339}', '\u{133A}', '\u{133B}', '\u{133C}', '\u{133D}', '\u{133E}', '\u{133F}', '\u{1340}', '\u{1341}', '\u{1342}', '\u{1343}', '\u{1344}', '\u{1345}', '\u{1346}', '\u{1347}', '\u{1348}', '\u{1349}', '\u{134A}', '\u{134B}', '\u{134C}', '\u{134D}', '\u{134E}', '\u{134F}', '\u{1350}', '\u{1351}', '\u{1352}', '\u{1353}', '\u{1354}', '\u{1355}', '\u{1356}', '\u{1357}', '\u{1358}', '\u{1359}', '\u{135A}', '\u{1380}', '\u{1381}', '\u{1382}', '\u{1383}', '\u{1384}', '\u{1385}', '\u{1386}', '\u{1387}', '\u{1388}', '\u{1389}', '\u{138A}', '\u{138B}', '\u{138C}', '\u{138D}', '\u{138E}', '\u{138F}', '\u{13A0}', '\u{13A1}', '\u{13A2}', '\u{13A3}', '\u{13A4}', '\u{13A5}', '\u{13A6}', '\u{13A7}', '\u{13A8}', '\u{13A9}', '\u{13AA}', '\u{13AB}', '\u{13AC}', '\u{13AD}', '\u{13AE}', '\u{13AF}', '\u{13B0}', '\u{13B1}', '\u{13B2}', '\u{13B3}', '\u{13B4}', '\u{13B5}', '\u{13B6}', '\u{13B7}', '\u{13B8}', '\u{13B9}', '\u{13BA}', '\u{13BB}', '\u{13BC}', '\u{13BD}', '\u{13BE}', '\u{13BF}', '\u{13C0}', '\u{13C1}', '\u{13C2}', '\u{13C3}', '\u{13C4}', '\u{13C5}', '\u{13C6}', '\u{13C7}', '\u{13C8}', '\u{13C9}', '\u{13CA}', '\u{13CB}', '\u{13CC}', '\u{13CD}', '\u{13CE}', '\u{13CF}', '\u{13D0}', '\u{13D1}', '\u{13D2}', '\u{13D3}', '\u{13D4}', '\u{13D5}', '\u{13D6}', '\u{13D7}', '\u{13D8}', '\u{13D9}', '\u{13DA}', '\u{13DB}', '\u{13DC}', '\u{13DD}', '\u{13DE}', '\u{13DF}', '\u{13E0}', '\u{13E1}', '\u{13E2}', '\u{13E3}', '\u{13E4}', '\u{13E5}', '\u{13E6}', '\u{13E7}', '\u{13E8}', '\u{13E9}', '\u{13EA}', '\u{13EB}', '\u{13EC}', '\u{13ED}', '\u{13EE}', '\u{13EF}', '\u{13F0}', '\u{13F1}', '\u{13F2}', '\u{13F3}', '\u{13F4}', '\u{1401}', '\u{1402}', '\u{1403}', '\u{1404}', '\u{1405}', '\u{1406}', '\u{1407}', '\u{1408}', '\u{1409}', '\u{140A}', '\u{140B}', '\u{140C}', '\u{140D}', '\u{140E}', '\u{140F}', '\u{1410}', '\u{1411}', '\u{1412}', '\u{1413}', '\u{1414}', '\u{1415}', '\u{1416}', '\u{1417}', '\u{1418}', '\u{1419}', '\u{141A}', '\u{141B}', '\u{141C}', '\u{141D}', '\u{141E}', '\u{141F}', '\u{1420}', '\u{1421}', '\u{1422}', '\u{1423}', '\u{1424}', '\u{1425}', '\u{1426}', '\u{1427}', '\u{1428}', '\u{1429}', '\u{142A}', '\u{142B}', '\u{142C}', '\u{142D}', '\u{142E}', '\u{142F}', '\u{1430}', '\u{1431}', '\u{1432}', '\u{1433}', '\u{1434}', '\u{1435}', '\u{1436}', '\u{1437}', '\u{1438}', '\u{1439}', '\u{143A}', '\u{143B}', '\u{143C}', '\u{143D}', '\u{143E}', '\u{143F}', '\u{1440}', '\u{1441}', '\u{1442}', '\u{1443}', '\u{1444}', '\u{1445}', '\u{1446}', '\u{1447}', '\u{1448}', '\u{1449}', '\u{144A}', '\u{144B}', '\u{144C}', '\u{144D}', '\u{144E}', '\u{144F}', '\u{1450}', '\u{1451}', '\u{1452}', '\u{1453}', '\u{1454}', '\u{1455}', '\u{1456}', '\u{1457}', '\u{1458}', '\u{1459}', '\u{145A}', '\u{145B}', '\u{145C}', '\u{145D}', '\u{145E}', '\u{145F}', '\u{1460}', '\u{1461}', '\u{1462}', '\u{1463}', '\u{1464}', '\u{1465}', '\u{1466}', '\u{1467}', '\u{1468}', '\u{1469}', '\u{146A}', '\u{146B}', '\u{146C}', '\u{146D}', '\u{146E}', '\u{146F}', '\u{1470}', '\u{1471}', '\u{1472}', '\u{1473}', '\u{1474}', '\u{1475}', '\u{1476}', '\u{1477}', '\u{1478}', '\u{1479}', '\u{147A}', '\u{147B}', '\u{147C}', '\u{147D}', '\u{147E}', '\u{147F}', '\u{1480}', '\u{1481}', '\u{1482}', '\u{1483}', '\u{1484}', '\u{1485}', '\u{1486}', '\u{1487}', '\u{1488}', '\u{1489}', '\u{148A}', '\u{148B}', '\u{148C}', '\u{148D}', '\u{148E}', '\u{148F}', '\u{1490}', '\u{1491}', '\u{1492}', '\u{1493}', '\u{1494}', '\u{1495}', '\u{1496}', '\u{1497}', '\u{1498}', '\u{1499}', '\u{149A}', '\u{149B}', '\u{149C}', '\u{149D}', '\u{149E}', '\u{149F}', '\u{14A0}', '\u{14A1}', '\u{14A2}', '\u{14A3}', '\u{14A4}', '\u{14A5}', '\u{14A6}', '\u{14A7}', '\u{14A8}', '\u{14A9}', '\u{14AA}', '\u{14AB}', '\u{14AC}', '\u{14AD}', '\u{14AE}', '\u{14AF}', '\u{14B0}', '\u{14B1}', '\u{14B2}', '\u{14B3}', '\u{14B4}', '\u{14B5}', '\u{14B6}', '\u{14B7}', '\u{14B8}', '\u{14B9}', '\u{14BA}', '\u{14BB}', '\u{14BC}', '\u{14BD}', '\u{14BE}', '\u{14BF}', '\u{14C0}', '\u{14C1}', '\u{14C2}', '\u{14C3}', '\u{14C4}', '\u{14C5}', '\u{14C6}', '\u{14C7}', '\u{14C8}', '\u{14C9}', '\u{14CA}', '\u{14CB}', '\u{14CC}', '\u{14CD}', '\u{14CE}', '\u{14CF}', '\u{14D0}', '\u{14D1}', '\u{14D2}', '\u{14D3}', '\u{14D4}', '\u{14D5}', '\u{14D6}', '\u{14D7}', '\u{14D8}', '\u{14D9}', '\u{14DA}', '\u{14DB}', '\u{14DC}', '\u{14DD}', '\u{14DE}', '\u{14DF}', '\u{14E0}', '\u{14E1}', '\u{14E2}', '\u{14E3}', '\u{14E4}', '\u{14E5}', '\u{14E6}', '\u{14E7}', '\u{14E8}', '\u{14E9}', '\u{14EA}', '\u{14EB}', '\u{14EC}', '\u{14ED}', '\u{14EE}', '\u{14EF}', '\u{14F0}', '\u{14F1}', '\u{14F2}', '\u{14F3}', '\u{14F4}', '\u{14F5}', '\u{14F6}', '\u{14F7}', '\u{14F8}', '\u{14F9}', '\u{14FA}', '\u{14FB}', '\u{14FC}', '\u{14FD}', '\u{14FE}', '\u{14FF}', '\u{1500}', '\u{1501}', '\u{1502}', '\u{1503}', '\u{1504}', '\u{1505}', '\u{1506}', '\u{1507}', '\u{1508}', '\u{1509}', '\u{150A}', '\u{150B}', '\u{150C}', '\u{150D}', '\u{150E}', '\u{150F}', '\u{1510}', '\u{1511}', '\u{1512}', '\u{1513}', '\u{1514}', '\u{1515}', '\u{1516}', '\u{1517}', '\u{1518}', '\u{1519}', '\u{151A}', '\u{151B}', '\u{151C}', '\u{151D}', '\u{151E}', '\u{151F}', '\u{1520}', '\u{1521}', '\u{1522}', '\u{1523}', '\u{1524}', '\u{1525}', '\u{1526}', '\u{1527}', '\u{1528}', '\u{1529}', '\u{152A}', '\u{152B}', '\u{152C}', '\u{152D}', '\u{152E}', '\u{152F}', '\u{1530}', '\u{1531}', '\u{1532}', '\u{1533}', '\u{1534}', '\u{1535}', '\u{1536}', '\u{1537}', '\u{1538}', '\u{1539}', '\u{153A}', '\u{153B}', '\u{153C}', '\u{153D}', '\u{153E}', '\u{153F}', '\u{1540}', '\u{1541}', '\u{1542}', '\u{1543}', '\u{1544}', '\u{1545}', '\u{1546}', '\u{1547}', '\u{1548}', '\u{1549}', '\u{154A}', '\u{154B}', '\u{154C}', '\u{154D}', '\u{154E}', '\u{154F}', '\u{1550}', '\u{1551}', '\u{1552}', '\u{1553}', '\u{1554}', '\u{1555}', '\u{1556}', '\u{1557}', '\u{1558}', '\u{1559}', '\u{155A}', '\u{155B}', '\u{155C}', '\u{155D}', '\u{155E}', '\u{155F}', '\u{1560}', '\u{1561}', '\u{1562}', '\u{1563}', '\u{1564}', '\u{1565}', '\u{1566}', '\u{1567}', '\u{1568}', '\u{1569}', '\u{156A}', '\u{156B}', '\u{156C}', '\u{156D}', '\u{156E}', '\u{156F}', '\u{1570}', '\u{1571}', '\u{1572}', '\u{1573}', '\u{1574}', '\u{1575}', '\u{1576}', '\u{1577}', '\u{1578}', '\u{1579}', '\u{157A}', '\u{157B}', '\u{157C}', '\u{157D}', '\u{157E}', '\u{157F}', '\u{1580}', '\u{1581}', '\u{1582}', '\u{1583}', '\u{1584}', '\u{1585}', '\u{1586}', '\u{1587}', '\u{1588}', '\u{1589}', '\u{158A}', '\u{158B}', '\u{158C}', '\u{158D}', '\u{158E}', '\u{158F}', '\u{1590}', '\u{1591}', '\u{1592}', '\u{1593}', '\u{1594}', '\u{1595}', '\u{1596}', '\u{1597}', '\u{1598}', '\u{1599}', '\u{159A}', '\u{159B}', '\u{159C}', '\u{159D}', '\u{159E}', '\u{159F}', '\u{15A0}', '\u{15A1}', '\u{15A2}', '\u{15A3}', '\u{15A4}', '\u{15A5}', '\u{15A6}', '\u{15A7}', '\u{15A8}', '\u{15A9}', '\u{15AA}', '\u{15AB}', '\u{15AC}', '\u{15AD}', '\u{15AE}', '\u{15AF}', '\u{15B0}', '\u{15B1}', '\u{15B2}', '\u{15B3}', '\u{15B4}', '\u{15B5}', '\u{15B6}', '\u{15B7}', '\u{15B8}', '\u{15B9}', '\u{15BA}', '\u{15BB}', '\u{15BC}', '\u{15BD}', '\u{15BE}', '\u{15BF}', '\u{15C0}', '\u{15C1}', '\u{15C2}', '\u{15C3}', '\u{15C4}', '\u{15C5}', '\u{15C6}', '\u{15C7}', '\u{15C8}', '\u{15C9}', '\u{15CA}', '\u{15CB}', '\u{15CC}', '\u{15CD}', '\u{15CE}', '\u{15CF}', '\u{15D0}', '\u{15D1}', '\u{15D2}', '\u{15D3}', '\u{15D4}', '\u{15D5}', '\u{15D6}', '\u{15D7}', '\u{15D8}', '\u{15D9}', '\u{15DA}', '\u{15DB}', '\u{15DC}', '\u{15DD}', '\u{15DE}', '\u{15DF}', '\u{15E0}', '\u{15E1}', '\u{15E2}', '\u{15E3}', '\u{15E4}', '\u{15E5}', '\u{15E6}', '\u{15E7}', '\u{15E8}', '\u{15E9}', '\u{15EA}', '\u{15EB}', '\u{15EC}', '\u{15ED}', '\u{15EE}', '\u{15EF}', '\u{15F0}', '\u{15F1}', '\u{15F2}', '\u{15F3}', '\u{15F4}', '\u{15F5}', '\u{15F6}', '\u{15F7}', '\u{15F8}', '\u{15F9}', '\u{15FA}', '\u{15FB}', '\u{15FC}', '\u{15FD}', '\u{15FE}', '\u{15FF}', '\u{1600}', '\u{1601}', '\u{1602}', '\u{1603}', '\u{1604}', '\u{1605}', '\u{1606}', '\u{1607}', '\u{1608}', '\u{1609}', '\u{160A}', '\u{160B}', '\u{160C}', '\u{160D}', '\u{160E}', '\u{160F}', '\u{1610}', '\u{1611}', '\u{1612}', '\u{1613}', '\u{1614}', '\u{1615}', '\u{1616}', '\u{1617}', '\u{1618}', '\u{1619}', '\u{161A}', '\u{161B}', '\u{161C}', '\u{161D}', '\u{161E}', '\u{161F}', '\u{1620}', '\u{1621}', '\u{1622}', '\u{1623}', '\u{1624}', '\u{1625}', '\u{1626}', '\u{1627}', '\u{1628}', '\u{1629}', '\u{162A}', '\u{162B}', '\u{162C}', '\u{162D}', '\u{162E}', '\u{162F}', '\u{1630}', '\u{1631}', '\u{1632}', '\u{1633}', '\u{1634}', '\u{1635}', '\u{1636}', '\u{1637}', '\u{1638}', '\u{1639}', '\u{163A}', '\u{163B}', '\u{163C}', '\u{163D}', '\u{163E}', '\u{163F}', '\u{1640}', '\u{1641}', '\u{1642}', '\u{1643}', '\u{1644}', '\u{1645}', '\u{1646}', '\u{1647}', '\u{1648}', '\u{1649}', '\u{164A}', '\u{164B}', '\u{164C}', '\u{164D}', '\u{164E}', '\u{164F}', '\u{1650}', '\u{1651}', '\u{1652}', '\u{1653}', '\u{1654}', '\u{1655}', '\u{1656}', '\u{1657}', '\u{1658}', '\u{1659}', '\u{165A}', '\u{165B}', '\u{165C}', '\u{165D}', '\u{165E}', '\u{165F}', '\u{1660}', '\u{1661}', '\u{1662}', '\u{1663}', '\u{1664}', '\u{1665}', '\u{1666}', '\u{1667}', '\u{1668}', '\u{1669}', '\u{166A}', '\u{166B}', '\u{166C}', '\u{166F}', '\u{1670}', '\u{1671}', '\u{1672}', '\u{1673}', '\u{1674}', '\u{1675}', '\u{1676}', '\u{1681}', '\u{1682}', '\u{1683}', '\u{1684}', '\u{1685}', '\u{1686}', '\u{1687}', '\u{1688}', '\u{1689}', '\u{168A}', '\u{168B}', '\u{168C}', '\u{168D}', '\u{168E}', '\u{168F}', '\u{1690}', '\u{1691}', '\u{1692}', '\u{1693}', '\u{1694}', '\u{1695}', '\u{1696}', '\u{1697}', '\u{1698}', '\u{1699}', '\u{169A}', '\u{16A0}', '\u{16A1}', '\u{16A2}', '\u{16A3}', '\u{16A4}', '\u{16A5}', '\u{16A6}', '\u{16A7}', '\u{16A8}', '\u{16A9}', '\u{16AA}', '\u{16AB}', '\u{16AC}', '\u{16AD}', '\u{16AE}', '\u{16AF}', '\u{16B0}', '\u{16B1}', '\u{16B2}', '\u{16B3}', '\u{16B4}', '\u{16B5}', '\u{16B6}', '\u{16B7}', '\u{16B8}', '\u{16B9}', '\u{16BA}', '\u{16BB}', '\u{16BC}', '\u{16BD}', '\u{16BE}', '\u{16BF}', '\u{16C0}', '\u{16C1}', '\u{16C2}', '\u{16C3}', '\u{16C4}', '\u{16C5}', '\u{16C6}', '\u{16C7}', '\u{16C8}', '\u{16C9}', '\u{16CA}', '\u{16CB}', '\u{16CC}', '\u{16CD}', '\u{16CE}', '\u{16CF}', '\u{16D0}', '\u{16D1}', '\u{16D2}', '\u{16D3}', '\u{16D4}', '\u{16D5}', '\u{16D6}', '\u{16D7}', '\u{16D8}', '\u{16D9}', '\u{16DA}', '\u{16DB}', '\u{16DC}', '\u{16DD}', '\u{16DE}', '\u{16DF}', '\u{16E0}', '\u{16E1}', '\u{16E2}', '\u{16E3}', '\u{16E4}', '\u{16E5}', '\u{16E6}', '\u{16E7}', '\u{16E8}', '\u{16E9}', '\u{16EA}', '\u{1700}', '\u{1701}', '\u{1702}', '\u{1703}', '\u{1704}', '\u{1705}', '\u{1706}', '\u{1707}', '\u{1708}', '\u{1709}', '\u{170A}', '\u{170B}', '\u{170C}', '\u{170E}', '\u{170F}', '\u{1710}', '\u{1711}', '\u{1720}', '\u{1721}', '\u{1722}', '\u{1723}', '\u{1724}', '\u{1725}', '\u{1726}', '\u{1727}', '\u{1728}', '\u{1729}', '\u{172A}', '\u{172B}', '\u{172C}', '\u{172D}', '\u{172E}', '\u{172F}', '\u{1730}', '\u{1731}', '\u{1740}', '\u{1741}', '\u{1742}', '\u{1743}', '\u{1744}', '\u{1745}', '\u{1746}', '\u{1747}', '\u{1748}', '\u{1749}', '\u{174A}', '\u{174B}', '\u{174C}', '\u{174D}', '\u{174E}', '\u{174F}', '\u{1750}', '\u{1751}', '\u{1760}', '\u{1761}', '\u{1762}', '\u{1763}', '\u{1764}', '\u{1765}', '\u{1766}', '\u{1767}', '\u{1768}', '\u{1769}', '\u{176A}', '\u{176B}', '\u{176C}', '\u{176E}', '\u{176F}', '\u{1770}', '\u{1780}', '\u{1781}', '\u{1782}', '\u{1783}', '\u{1784}', '\u{1785}', '\u{1786}', '\u{1787}', '\u{1788}', '\u{1789}', '\u{178A}', '\u{178B}', '\u{178C}', '\u{178D}', '\u{178E}', '\u{178F}', '\u{1790}', '\u{1791}', '\u{1792}', '\u{1793}', '\u{1794}', '\u{1795}', '\u{1796}', '\u{1797}', '\u{1798}', '\u{1799}', '\u{179A}', '\u{179B}', '\u{179C}', '\u{179D}', '\u{179E}', '\u{179F}', '\u{17A0}', '\u{17A1}', '\u{17A2}', '\u{17A3}', '\u{17A4}', '\u{17A5}', '\u{17A6}', '\u{17A7}', '\u{17A8}', '\u{17A9}', '\u{17AA}', '\u{17AB}', '\u{17AC}', '\u{17AD}', '\u{17AE}', '\u{17AF}', '\u{17B0}', '\u{17B1}', '\u{17B2}', '\u{17B3}', '\u{17DC}', '\u{1820}', '\u{1821}', '\u{1822}', '\u{1823}', '\u{1824}', '\u{1825}', '\u{1826}', '\u{1827}', '\u{1828}', '\u{1829}', '\u{182A}', '\u{182B}', '\u{182C}', '\u{182D}', '\u{182E}', '\u{182F}', '\u{1830}', '\u{1831}', '\u{1832}', '\u{1833}', '\u{1834}', '\u{1835}', '\u{1836}', '\u{1837}', '\u{1838}', '\u{1839}', '\u{183A}', '\u{183B}', '\u{183C}', '\u{183D}', '\u{183E}', '\u{183F}', '\u{1840}', '\u{1841}', '\u{1842}', '\u{1844}', '\u{1845}', '\u{1846}', '\u{1847}', '\u{1848}', '\u{1849}', '\u{184A}', '\u{184B}', '\u{184C}', '\u{184D}', '\u{184E}', '\u{184F}', '\u{1850}', '\u{1851}', '\u{1852}', '\u{1853}', '\u{1854}', '\u{1855}', '\u{1856}', '\u{1857}', '\u{1858}', '\u{1859}', '\u{185A}', '\u{185B}', '\u{185C}', '\u{185D}', '\u{185E}', '\u{185F}', '\u{1860}', '\u{1861}', '\u{1862}', '\u{1863}', '\u{1864}', '\u{1865}', '\u{1866}', '\u{1867}', '\u{1868}', '\u{1869}', '\u{186A}', '\u{186B}', '\u{186C}', '\u{186D}', '\u{186E}', '\u{186F}', '\u{1870}', '\u{1871}', '\u{1872}', '\u{1873}', '\u{1874}', '\u{1875}', '\u{1876}', '\u{1877}', '\u{1880}', '\u{1881}', '\u{1882}', '\u{1883}', '\u{1884}', '\u{1885}', '\u{1886}', '\u{1887}', '\u{1888}', '\u{1889}', '\u{188A}', '\u{188B}', '\u{188C}', '\u{188D}', '\u{188E}', '\u{188F}', '\u{1890}', '\u{1891}', '\u{1892}', '\u{1893}', '\u{1894}', '\u{1895}', '\u{1896}', '\u{1897}', '\u{1898}', '\u{1899}', '\u{189A}', '\u{189B}', '\u{189C}', '\u{189D}', '\u{189E}', '\u{189F}', '\u{18A0}', '\u{18A1}', '\u{18A2}', '\u{18A3}', '\u{18A4}', '\u{18A5}', '\u{18A6}', '\u{18A7}', '\u{18A8}', '\u{18AA}', '\u{1900}', '\u{1901}', '\u{1902}', '\u{1903}', '\u{1904}', '\u{1905}', '\u{1906}', '\u{1907}', '\u{1908}', '\u{1909}', '\u{190A}', '\u{190B}', '\u{190C}', '\u{190D}', '\u{190E}', '\u{190F}', '\u{1910}', '\u{1911}', '\u{1912}', '\u{1913}', '\u{1914}', '\u{1915}', '\u{1916}', '\u{1917}', '\u{1918}', '\u{1919}', '\u{191A}', '\u{191B}', '\u{191C}', '\u{1950}', '\u{1951}', '\u{1952}', '\u{1953}', '\u{1954}', '\u{1955}', '\u{1956}', '\u{1957}', '\u{1958}', '\u{1959}', '\u{195A}', '\u{195B}', '\u{195C}', '\u{195D}', '\u{195E}', '\u{195F}', '\u{1960}', '\u{1961}', '\u{1962}', '\u{1963}', '\u{1964}', '\u{1965}', '\u{1966}', '\u{1967}', '\u{1968}', '\u{1969}', '\u{196A}', '\u{196B}', '\u{196C}', '\u{196D}', '\u{1970}', '\u{1971}', '\u{1972}', '\u{1973}', '\u{1974}', '\u{1980}', '\u{1981}', '\u{1982}', '\u{1983}', '\u{1984}', '\u{1985}', '\u{1986}', '\u{1987}', '\u{1988}', '\u{1989}', '\u{198A}', '\u{198B}', '\u{198C}', '\u{198D}', '\u{198E}', '\u{198F}', '\u{1990}', '\u{1991}', '\u{1992}', '\u{1993}', '\u{1994}', '\u{1995}', '\u{1996}', '\u{1997}', '\u{1998}', '\u{1999}', '\u{199A}', '\u{199B}', '\u{199C}', '\u{199D}', '\u{199E}', '\u{199F}', '\u{19A0}', '\u{19A1}', '\u{19A2}', '\u{19A3}', '\u{19A4}', '\u{19A5}', '\u{19A6}', '\u{19A7}', '\u{19A8}', '\u{19A9}', '\u{19C1}', '\u{19C2}', '\u{19C3}', '\u{19C4}', '\u{19C5}', '\u{19C6}', '\u{19C7}', '\u{1A00}', '\u{1A01}', '\u{1A02}', '\u{1A03}', '\u{1A04}', '\u{1A05}', '\u{1A06}', '\u{1A07}', '\u{1A08}', '\u{1A09}', '\u{1A0A}', '\u{1A0B}', '\u{1A0C}', '\u{1A0D}', '\u{1A0E}', '\u{1A0F}', '\u{1A10}', '\u{1A11}', '\u{1A12}', '\u{1A13}', '\u{1A14}', '\u{1A15}', '\u{1A16}', '\u{1B05}', '\u{1B06}', '\u{1B07}', '\u{1B08}', '\u{1B09}', '\u{1B0A}', '\u{1B0B}', '\u{1B0C}', '\u{1B0D}', '\u{1B0E}', '\u{1B0F}', '\u{1B10}', '\u{1B11}', '\u{1B12}', '\u{1B13}', '\u{1B14}', '\u{1B15}', '\u{1B16}', '\u{1B17}', '\u{1B18}', '\u{1B19}', '\u{1B1A}', '\u{1B1B}', '\u{1B1C}', '\u{1B1D}', '\u{1B1E}', '\u{1B1F}', '\u{1B20}', '\u{1B21}', '\u{1B22}', '\u{1B23}', '\u{1B24}', '\u{1B25}', '\u{1B26}', '\u{1B27}', '\u{1B28}', '\u{1B29}', '\u{1B2A}', '\u{1B2B}', '\u{1B2C}', '\u{1B2D}', '\u{1B2E}', '\u{1B2F}', '\u{1B30}', '\u{1B31}', '\u{1B32}', '\u{1B33}', '\u{1B45}', '\u{1B46}', '\u{1B47}', '\u{1B48}', '\u{1B49}', '\u{1B4A}', '\u{1B4B}', '\u{1B83}', '\u{1B84}', '\u{1B85}', '\u{1B86}', '\u{1B87}', '\u{1B88}', '\u{1B89}', '\u{1B8A}', '\u{1B8B}', '\u{1B8C}', '\u{1B8D}', '\u{1B8E}', '\u{1B8F}', '\u{1B90}', '\u{1B91}', '\u{1B92}', '\u{1B93}', '\u{1B94}', '\u{1B95}', '\u{1B96}', '\u{1B97}', '\u{1B98}', '\u{1B99}', '\u{1B9A}', '\u{1B9B}', '\u{1B9C}', '\u{1B9D}', '\u{1B9E}', '\u{1B9F}', '\u{1BA0}', '\u{1BAE}', '\u{1BAF}', '\u{1C00}', '\u{1C01}', '\u{1C02}', '\u{1C03}', '\u{1C04}', '\u{1C05}', '\u{1C06}', '\u{1C07}', '\u{1C08}', '\u{1C09}', '\u{1C0A}', '\u{1C0B}', '\u{1C0C}', '\u{1C0D}', '\u{1C0E}', '\u{1C0F}', '\u{1C10}', '\u{1C11}', '\u{1C12}', '\u{1C13}', '\u{1C14}', '\u{1C15}', '\u{1C16}', '\u{1C17}', '\u{1C18}', '\u{1C19}', '\u{1C1A}', '\u{1C1B}', '\u{1C1C}', '\u{1C1D}', '\u{1C1E}', '\u{1C1F}', '\u{1C20}', '\u{1C21}', '\u{1C22}', '\u{1C23}', '\u{1C4D}', '\u{1C4E}', '\u{1C4F}', '\u{1C5A}', '\u{1C5B}', '\u{1C5C}', '\u{1C5D}', '\u{1C5E}', '\u{1C5F}', '\u{1C60}', '\u{1C61}', '\u{1C62}', '\u{1C63}', '\u{1C64}', '\u{1C65}', '\u{1C66}', '\u{1C67}', '\u{1C68}', '\u{1C69}', '\u{1C6A}', '\u{1C6B}', '\u{1C6C}', '\u{1C6D}', '\u{1C6E}', '\u{1C6F}', '\u{1C70}', '\u{1C71}', '\u{1C72}', '\u{1C73}', '\u{1C74}', '\u{1C75}', '\u{1C76}', '\u{1C77}', '\u{2135}', '\u{2136}', '\u{2137}', '\u{2138}', '\u{2D30}', '\u{2D31}', '\u{2D32}', '\u{2D33}', '\u{2D34}', '\u{2D35}', '\u{2D36}', '\u{2D37}', '\u{2D38}', '\u{2D39}', '\u{2D3A}', '\u{2D3B}', '\u{2D3C}', '\u{2D3D}', '\u{2D3E}', '\u{2D3F}', '\u{2D40}', '\u{2D41}', '\u{2D42}', '\u{2D43}', '\u{2D44}', '\u{2D45}', '\u{2D46}', '\u{2D47}', '\u{2D48}', '\u{2D49}', '\u{2D4A}', '\u{2D4B}', '\u{2D4C}', '\u{2D4D}', '\u{2D4E}', '\u{2D4F}', '\u{2D50}', '\u{2D51}', '\u{2D52}', '\u{2D53}', '\u{2D54}', '\u{2D55}', '\u{2D56}', '\u{2D57}', '\u{2D58}', '\u{2D59}', '\u{2D5A}', '\u{2D5B}', '\u{2D5C}', '\u{2D5D}', '\u{2D5E}', '\u{2D5F}', '\u{2D60}', '\u{2D61}', '\u{2D62}', '\u{2D63}', '\u{2D64}', '\u{2D65}', '\u{2D80}', '\u{2D81}', '\u{2D82}', '\u{2D83}', '\u{2D84}', '\u{2D85}', '\u{2D86}', '\u{2D87}', '\u{2D88}', '\u{2D89}', '\u{2D8A}', '\u{2D8B}', '\u{2D8C}', '\u{2D8D}', '\u{2D8E}', '\u{2D8F}', '\u{2D90}', '\u{2D91}', '\u{2D92}', '\u{2D93}', '\u{2D94}', '\u{2D95}', '\u{2D96}', '\u{2DA0}', '\u{2DA1}', '\u{2DA2}', '\u{2DA3}', '\u{2DA4}', '\u{2DA5}', '\u{2DA6}', '\u{2DA8}', '\u{2DA9}', '\u{2DAA}', '\u{2DAB}', '\u{2DAC}', '\u{2DAD}', '\u{2DAE}', '\u{2DB0}', '\u{2DB1}', '\u{2DB2}', '\u{2DB3}', '\u{2DB4}', '\u{2DB5}', '\u{2DB6}', '\u{2DB8}', '\u{2DB9}', '\u{2DBA}', '\u{2DBB}', '\u{2DBC}', '\u{2DBD}', '\u{2DBE}', '\u{2DC0}', '\u{2DC1}', '\u{2DC2}', '\u{2DC3}', '\u{2DC4}', '\u{2DC5}', '\u{2DC6}', '\u{2DC8}', '\u{2DC9}', '\u{2DCA}', '\u{2DCB}', '\u{2DCC}', '\u{2DCD}', '\u{2DCE}', '\u{2DD0}', '\u{2DD1}', '\u{2DD2}', '\u{2DD3}', '\u{2DD4}', '\u{2DD5}', '\u{2DD6}', '\u{2DD8}', '\u{2DD9}', '\u{2DDA}', '\u{2DDB}', '\u{2DDC}', '\u{2DDD}', '\u{2DDE}', '\u{3006}', '\u{303C}', '\u{3041}', '\u{3042}', '\u{3043}', '\u{3044}', '\u{3045}', '\u{3046}', '\u{3047}', '\u{3048}', '\u{3049}', '\u{304A}', '\u{304B}', '\u{304C}', '\u{304D}', '\u{304E}', '\u{304F}', '\u{3050}', '\u{3051}', '\u{3052}', '\u{3053}', '\u{3054}', '\u{3055}', '\u{3056}', '\u{3057}', '\u{3058}', '\u{3059}', '\u{305A}', '\u{305B}', '\u{305C}', '\u{305D}', '\u{305E}', '\u{305F}', '\u{3060}', '\u{3061}', '\u{3062}', '\u{3063}', '\u{3064}', '\u{3065}', '\u{3066}', '\u{3067}', '\u{3068}', '\u{3069}', '\u{306A}', '\u{306B}', '\u{306C}', '\u{306D}', '\u{306E}', '\u{306F}', '\u{3070}', '\u{3071}', '\u{3072}', '\u{3073}', '\u{3074}', '\u{3075}', '\u{3076}', '\u{3077}', '\u{3078}', '\u{3079}', '\u{307A}', '\u{307B}', '\u{307C}', '\u{307D}', '\u{307E}', '\u{307F}', '\u{3080}', '\u{3081}', '\u{3082}', '\u{3083}', '\u{3084}', '\u{3085}', '\u{3086}', '\u{3087}', '\u{3088}', '\u{3089}', '\u{308A}', '\u{308B}', '\u{308C}', '\u{308D}', '\u{308E}', '\u{308F}', '\u{3090}', '\u{3091}', '\u{3092}', '\u{3093}', '\u{3094}', '\u{3095}', '\u{3096}', '\u{309F}', '\u{30A1}', '\u{30A2}', '\u{30A3}', '\u{30A4}', '\u{30A5}', '\u{30A6}', '\u{30A7}', '\u{30A8}', '\u{30A9}', '\u{30AA}', '\u{30AB}', '\u{30AC}', '\u{30AD}', '\u{30AE}', '\u{30AF}', '\u{30B0}', '\u{30B1}', '\u{30B2}', '\u{30B3}', '\u{30B4}', '\u{30B5}', '\u{30B6}', '\u{30B7}', '\u{30B8}', '\u{30B9}', '\u{30BA}', '\u{30BB}', '\u{30BC}', '\u{30BD}', '\u{30BE}', '\u{30BF}', '\u{30C0}', '\u{30C1}', '\u{30C2}', '\u{30C3}', '\u{30C4}', '\u{30C5}', '\u{30C6}', '\u{30C7}', '\u{30C8}', '\u{30C9}', '\u{30CA}', '\u{30CB}', '\u{30CC}', '\u{30CD}', '\u{30CE}', '\u{30CF}', '\u{30D0}', '\u{30D1}', '\u{30D2}', '\u{30D3}', '\u{30D4}', '\u{30D5}', '\u{30D6}', '\u{30D7}', '\u{30D8}', '\u{30D9}', '\u{30DA}', '\u{30DB}', '\u{30DC}', '\u{30DD}', '\u{30DE}', '\u{30DF}', '\u{30E0}', '\u{30E1}', '\u{30E2}', '\u{30E3}', '\u{30E4}', '\u{30E5}', '\u{30E6}', '\u{30E7}', '\u{30E8}', '\u{30E9}', '\u{30EA}', '\u{30EB}', '\u{30EC}', '\u{30ED}', '\u{30EE}', '\u{30EF}', '\u{30F0}', '\u{30F1}', '\u{30F2}', '\u{30F3}', '\u{30F4}', '\u{30F5}', '\u{30F6}', '\u{30F7}', '\u{30F8}', '\u{30F9}', '\u{30FA}', '\u{30FF}', '\u{3105}', '\u{3106}', '\u{3107}', '\u{3108}', '\u{3109}', '\u{310A}', '\u{310B}', '\u{310C}', '\u{310D}', '\u{310E}', '\u{310F}', '\u{3110}', '\u{3111}', '\u{3112}', '\u{3113}', '\u{3114}', '\u{3115}', '\u{3116}', '\u{3117}', '\u{3118}', '\u{3119}', '\u{311A}', '\u{311B}', '\u{311C}', '\u{311D}', '\u{311E}', '\u{311F}', '\u{3120}', '\u{3121}', '\u{3122}', '\u{3123}', '\u{3124}', '\u{3125}', '\u{3126}', '\u{3127}', '\u{3128}', '\u{3129}', '\u{312A}', '\u{312B}', '\u{312C}', '\u{312D}', '\u{3131}', '\u{3132}', '\u{3133}', '\u{3134}', '\u{3135}', '\u{3136}', '\u{3137}', '\u{3138}', '\u{3139}', '\u{313A}', '\u{313B}', '\u{313C}', '\u{313D}', '\u{313E}', '\u{313F}', '\u{3140}', '\u{3141}', '\u{3142}', '\u{3143}', '\u{3144}', '\u{3145}', '\u{3146}', '\u{3147}', '\u{3148}', '\u{3149}', '\u{314A}', '\u{314B}', '\u{314C}', '\u{314D}', '\u{314E}', '\u{314F}', '\u{3150}', '\u{3151}', '\u{3152}', '\u{3153}', '\u{3154}', '\u{3155}', '\u{3156}', '\u{3157}', '\u{3158}', '\u{3159}', '\u{315A}', '\u{315B}', '\u{315C}', '\u{315D}', '\u{315E}', '\u{315F}', '\u{3160}', '\u{3161}', '\u{3162}', '\u{3163}', '\u{3164}', '\u{3165}', '\u{3166}', '\u{3167}', '\u{3168}', '\u{3169}', '\u{316A}', '\u{316B}', '\u{316C}', '\u{316D}', '\u{316E}', '\u{316F}', '\u{3170}', '\u{3171}', '\u{3172}', '\u{3173}', '\u{3174}', '\u{3175}', '\u{3176}', '\u{3177}', '\u{3178}', '\u{3179}', '\u{317A}', '\u{317B}', '\u{317C}', '\u{317D}', '\u{317E}', '\u{317F}', '\u{3180}', '\u{3181}', '\u{3182}', '\u{3183}', '\u{3184}', '\u{3185}', '\u{3186}', '\u{3187}', '\u{3188}', '\u{3189}', '\u{318A}', '\u{318B}', '\u{318C}', '\u{318D}', '\u{318E}', '\u{31A0}', '\u{31A1}', '\u{31A2}', '\u{31A3}', '\u{31A4}', '\u{31A5}', '\u{31A6}', '\u{31A7}', '\u{31A8}', '\u{31A9}', '\u{31AA}', '\u{31AB}', '\u{31AC}', '\u{31AD}', '\u{31AE}', '\u{31AF}', '\u{31B0}', '\u{31B1}', '\u{31B2}', '\u{31B3}', '\u{31B4}', '\u{31B5}', '\u{31B6}', '\u{31B7}', '\u{31F0}', '\u{31F1}', '\u{31F2}', '\u{31F3}', '\u{31F4}', '\u{31F5}', '\u{31F6}', '\u{31F7}', '\u{31F8}', '\u{31F9}', '\u{31FA}', '\u{31FB}', '\u{31FC}', '\u{31FD}', '\u{31FE}', '\u{31FF}', '\u{3400}', '\u{4DB5}', '\u{4E00}', '\u{9FC3}', '\u{A000}', '\u{A001}', '\u{A002}', '\u{A003}', '\u{A004}', '\u{A005}', '\u{A006}', '\u{A007}', '\u{A008}', '\u{A009}', '\u{A00A}', '\u{A00B}', '\u{A00C}', '\u{A00D}', '\u{A00E}', '\u{A00F}', '\u{A010}', '\u{A011}', '\u{A012}', '\u{A013}', '\u{A014}', '\u{A016}', '\u{A017}', '\u{A018}', '\u{A019}', '\u{A01A}', '\u{A01B}', '\u{A01C}', '\u{A01D}', '\u{A01E}', '\u{A01F}', '\u{A020}', '\u{A021}', '\u{A022}', '\u{A023}', '\u{A024}', '\u{A025}', '\u{A026}', '\u{A027}', '\u{A028}', '\u{A029}', '\u{A02A}', '\u{A02B}', '\u{A02C}', '\u{A02D}', '\u{A02E}', '\u{A02F}', '\u{A030}', '\u{A031}', '\u{A032}', '\u{A033}', '\u{A034}', '\u{A035}', '\u{A036}', '\u{A037}', '\u{A038}', '\u{A039}', '\u{A03A}', '\u{A03B}', '\u{A03C}', '\u{A03D}', '\u{A03E}', '\u{A03F}', '\u{A040}', '\u{A041}', '\u{A042}', '\u{A043}', '\u{A044}', '\u{A045}', '\u{A046}', '\u{A047}', '\u{A048}', '\u{A049}', '\u{A04A}', '\u{A04B}', '\u{A04C}', '\u{A04D}', '\u{A04E}', '\u{A04F}', '\u{A050}', '\u{A051}', '\u{A052}', '\u{A053}', '\u{A054}', '\u{A055}', '\u{A056}', '\u{A057}', '\u{A058}', '\u{A059}', '\u{A05A}', '\u{A05B}', '\u{A05C}', '\u{A05D}', '\u{A05E}', '\u{A05F}', '\u{A060}', '\u{A061}', '\u{A062}', '\u{A063}', '\u{A064}', '\u{A065}', '\u{A066}', '\u{A067}', '\u{A068}', '\u{A069}', '\u{A06A}', '\u{A06B}', '\u{A06C}', '\u{A06D}', '\u{A06E}', '\u{A06F}', '\u{A070}', '\u{A071}', '\u{A072}', '\u{A073}', '\u{A074}', '\u{A075}', '\u{A076}', '\u{A077}', '\u{A078}', '\u{A079}', '\u{A07A}', '\u{A07B}', '\u{A07C}', '\u{A07D}', '\u{A07E}', '\u{A07F}', '\u{A080}', '\u{A081}', '\u{A082}', '\u{A083}', '\u{A084}', '\u{A085}', '\u{A086}', '\u{A087}', '\u{A088}', '\u{A089}', '\u{A08A}', '\u{A08B}', '\u{A08C}', '\u{A08D}', '\u{A08E}', '\u{A08F}', '\u{A090}', '\u{A091}', '\u{A092}', '\u{A093}', '\u{A094}', '\u{A095}', '\u{A096}', '\u{A097}', '\u{A098}', '\u{A099}', '\u{A09A}', '\u{A09B}', '\u{A09C}', '\u{A09D}', '\u{A09E}', '\u{A09F}', '\u{A0A0}', '\u{A0A1}', '\u{A0A2}', '\u{A0A3}', '\u{A0A4}', '\u{A0A5}', '\u{A0A6}', '\u{A0A7}', '\u{A0A8}', '\u{A0A9}', '\u{A0AA}', '\u{A0AB}', '\u{A0AC}', '\u{A0AD}', '\u{A0AE}', '\u{A0AF}', '\u{A0B0}', '\u{A0B1}', '\u{A0B2}', '\u{A0B3}', '\u{A0B4}', '\u{A0B5}', '\u{A0B6}', '\u{A0B7}', '\u{A0B8}', '\u{A0B9}', '\u{A0BA}', '\u{A0BB}', '\u{A0BC}', '\u{A0BD}', '\u{A0BE}', '\u{A0BF}', '\u{A0C0}', '\u{A0C1}', '\u{A0C2}', '\u{A0C3}', '\u{A0C4}', '\u{A0C5}', '\u{A0C6}', '\u{A0C7}', '\u{A0C8}', '\u{A0C9}', '\u{A0CA}', '\u{A0CB}', '\u{A0CC}', '\u{A0CD}', '\u{A0CE}', '\u{A0CF}', '\u{A0D0}', '\u{A0D1}', '\u{A0D2}', '\u{A0D3}', '\u{A0D4}', '\u{A0D5}', '\u{A0D6}', '\u{A0D7}', '\u{A0D8}', '\u{A0D9}', '\u{A0DA}', '\u{A0DB}', '\u{A0DC}', '\u{A0DD}', '\u{A0DE}', '\u{A0DF}', '\u{A0E0}', '\u{A0E1}', '\u{A0E2}', '\u{A0E3}', '\u{A0E4}', '\u{A0E5}', '\u{A0E6}', '\u{A0E7}', '\u{A0E8}', '\u{A0E9}', '\u{A0EA}', '\u{A0EB}', '\u{A0EC}', '\u{A0ED}', '\u{A0EE}', '\u{A0EF}', '\u{A0F0}', '\u{A0F1}', '\u{A0F2}', '\u{A0F3}', '\u{A0F4}', '\u{A0F5}', '\u{A0F6}', '\u{A0F7}', '\u{A0F8}', '\u{A0F9}', '\u{A0FA}', '\u{A0FB}', '\u{A0FC}', '\u{A0FD}', '\u{A0FE}', '\u{A0FF}', '\u{A100}', '\u{A101}', '\u{A102}', '\u{A103}', '\u{A104}', '\u{A105}', '\u{A106}', '\u{A107}', '\u{A108}', '\u{A109}', '\u{A10A}', '\u{A10B}', '\u{A10C}', '\u{A10D}', '\u{A10E}', '\u{A10F}', '\u{A110}', '\u{A111}', '\u{A112}', '\u{A113}', '\u{A114}', '\u{A115}', '\u{A116}', '\u{A117}', '\u{A118}', '\u{A119}', '\u{A11A}', '\u{A11B}', '\u{A11C}', '\u{A11D}', '\u{A11E}', '\u{A11F}', '\u{A120}', '\u{A121}', '\u{A122}', '\u{A123}', '\u{A124}', '\u{A125}', '\u{A126}', '\u{A127}', '\u{A128}', '\u{A129}', '\u{A12A}', '\u{A12B}', '\u{A12C}', '\u{A12D}', '\u{A12E}', '\u{A12F}', '\u{A130}', '\u{A131}', '\u{A132}', '\u{A133}', '\u{A134}', '\u{A135}', '\u{A136}', '\u{A137}', '\u{A138}', '\u{A139}', '\u{A13A}', '\u{A13B}', '\u{A13C}', '\u{A13D}', '\u{A13E}', '\u{A13F}', '\u{A140}', '\u{A141}', '\u{A142}', '\u{A143}', '\u{A144}', '\u{A145}', '\u{A146}', '\u{A147}', '\u{A148}', '\u{A149}', '\u{A14A}', '\u{A14B}', '\u{A14C}', '\u{A14D}', '\u{A14E}', '\u{A14F}', '\u{A150}', '\u{A151}', '\u{A152}', '\u{A153}', '\u{A154}', '\u{A155}', '\u{A156}', '\u{A157}', '\u{A158}', '\u{A159}', '\u{A15A}', '\u{A15B}', '\u{A15C}', '\u{A15D}', '\u{A15E}', '\u{A15F}', '\u{A160}', '\u{A161}', '\u{A162}', '\u{A163}', '\u{A164}', '\u{A165}', '\u{A166}', '\u{A167}', '\u{A168}', '\u{A169}', '\u{A16A}', '\u{A16B}', '\u{A16C}', '\u{A16D}', '\u{A16E}', '\u{A16F}', '\u{A170}', '\u{A171}', '\u{A172}', '\u{A173}', '\u{A174}', '\u{A175}', '\u{A176}', '\u{A177}', '\u{A178}', '\u{A179}', '\u{A17A}', '\u{A17B}', '\u{A17C}', '\u{A17D}', '\u{A17E}', '\u{A17F}', '\u{A180}', '\u{A181}', '\u{A182}', '\u{A183}', '\u{A184}', '\u{A185}', '\u{A186}', '\u{A187}', '\u{A188}', '\u{A189}', '\u{A18A}', '\u{A18B}', '\u{A18C}', '\u{A18D}', '\u{A18E}', '\u{A18F}', '\u{A190}', '\u{A191}', '\u{A192}', '\u{A193}', '\u{A194}', '\u{A195}', '\u{A196}', '\u{A197}', '\u{A198}', '\u{A199}', '\u{A19A}', '\u{A19B}', '\u{A19C}', '\u{A19D}', '\u{A19E}', '\u{A19F}', '\u{A1A0}', '\u{A1A1}', '\u{A1A2}', '\u{A1A3}', '\u{A1A4}', '\u{A1A5}', '\u{A1A6}', '\u{A1A7}', '\u{A1A8}', '\u{A1A9}', '\u{A1AA}', '\u{A1AB}', '\u{A1AC}', '\u{A1AD}', '\u{A1AE}', '\u{A1AF}')
-    }
-
-    fn is_unicode_letter_number(self) -> bool {
-        match_char_class!(self,
-            '\u{16EE}', '\u{16EF}', '\u{16F0}', '\u{2160}', '\u{2161}', '\u{2162}', '\u{2163}', '\u{2164}', '\u{2165}', '\u{2166}', '\u{2167}', '\u{2168}', '\u{2169}', '\u{216A}', '\u{216B}', '\u{216C}', '\u{216D}', '\u{216E}', '\u{216F}', '\u{2170}', '\u{2171}', '\u{2172}', '\u{2173}', '\u{2174}', '\u{2175}', '\u{2176}', '\u{2177}', '\u{2178}', '\u{2179}', '\u{217A}', '\u{217B}', '\u{217C}', '\u{217D}', '\u{217E}', '\u{217F}', '\u{2180}', '\u{2181}', '\u{2182}', '\u{2185}', '\u{2186}', '\u{2187}', '\u{2188}', '\u{3007}', '\u{3021}', '\u{3022}', '\u{3023}', '\u{3024}', '\u{3025}', '\u{3026}', '\u{3027}', '\u{3028}', '\u{3029}', '\u{3038}', '\u{3039}', '\u{303A}')
-    }
-
-    fn is_unicode_nonspacing_mark(self) -> bool {
-        match_char_class!(self,
-            '\u{0300}', '\u{0301}', '\u{0302}', '\u{0303}', '\u{0304}', '\u{0305}', '\u{0306}', '\u{0307}', '\u{0308}', '\u{0309}', '\u{030A}', '\u{030B}', '\u{030C}', '\u{030D}', '\u{030E}', '\u{030F}', '\u{0310}', '\u{0311}', '\u{0312}', '\u{0313}', '\u{0314}', '\u{0315}', '\u{0316}', '\u{0317}', '\u{0318}', '\u{0319}', '\u{031A}', '\u{031B}', '\u{031C}', '\u{031D}', '\u{031E}', '\u{031F}', '\u{0320}', '\u{0321}', '\u{0322}', '\u{0323}', '\u{0324}', '\u{0325}', '\u{0326}', '\u{0327}', '\u{0328}', '\u{0329}', '\u{032A}', '\u{032B}', '\u{032C}', '\u{032D}', '\u{032E}', '\u{032F}', '\u{0330}', '\u{0331}', '\u{0332}', '\u{0333}', '\u{0334}', '\u{0335}', '\u{0336}', '\u{0337}', '\u{0338}', '\u{0339}', '\u{033A}', '\u{033B}', '\u{033C}', '\u{033D}', '\u{033E}', '\u{033F}', '\u{0340}', '\u{0341}', '\u{0342}', '\u{0343}', '\u{0344}', '\u{0345}', '\u{0346}', '\u{0347}', '\u{0348}', '\u{0349}', '\u{034A}', '\u{034B}', '\u{034C}', '\u{034D}', '\u{034E}', '\u{034F}', '\u{0350}', '\u{0351}', '\u{0352}', '\u{0353}', '\u{0354}', '\u{0355}', '\u{0356}', '\u{0357}', '\u{0358}', '\u{0359}', '\u{035A}', '\u{035B}', '\u{035C}', '\u{035D}', '\u{035E}', '\u{035F}', '\u{0360}', '\u{0361}', '\u{0362}', '\u{0363}', '\u{0364}', '\u{0365}', '\u{0366}', '\u{0367}', '\u{0368}', '\u{0369}', '\u{036A}', '\u{036B}', '\u{036C}', '\u{036D}', '\u{036E}', '\u{036F}', '\u{0483}', '\u{0484}', '\u{0485}', '\u{0486}', '\u{0487}', '\u{0591}', '\u{0592}', '\u{0593}', '\u{0594}', '\u{0595}', '\u{0596}', '\u{0597}', '\u{0598}', '\u{0599}', '\u{059A}', '\u{059B}', '\u{059C}', '\u{059D}', '\u{059E}', '\u{059F}', '\u{05A0}', '\u{05A1}', '\u{05A2}', '\u{05A3}', '\u{05A4}', '\u{05A5}', '\u{05A6}', '\u{05A7}', '\u{05A8}', '\u{05A9}', '\u{05AA}', '\u{05AB}', '\u{05AC}', '\u{05AD}', '\u{05AE}', '\u{05AF}', '\u{05B0}', '\u{05B1}', '\u{05B2}', '\u{05B3}', '\u{05B4}', '\u{05B5}', '\u{05B6}', '\u{05B7}', '\u{05B8}', '\u{05B9}', '\u{05BA}', '\u{05BB}', '\u{05BC}', '\u{05BD}', '\u{05BF}', '\u{05C1}', '\u{05C2}', '\u{05C4}', '\u{05C5}', '\u{05C7}', '\u{0610}', '\u{0611}', '\u{0612}', '\u{0613}', '\u{0614}', '\u{0615}', '\u{0616}', '\u{0617}', '\u{0618}', '\u{0619}', '\u{061A}', '\u{064B}', '\u{064C}', '\u{064D}', '\u{064E}', '\u{064F}', '\u{0650}', '\u{0651}', '\u{0652}', '\u{0653}', '\u{0654}', '\u{0655}', '\u{0656}', '\u{0657}', '\u{0658}', '\u{0659}', '\u{065A}', '\u{065B}', '\u{065C}', '\u{065D}', '\u{065E}', '\u{0670}', '\u{06D6}', '\u{06D7}', '\u{06D8}', '\u{06D9}', '\u{06DA}', '\u{06DB}', '\u{06DC}', '\u{06DF}', '\u{06E0}', '\u{06E1}', '\u{06E2}', '\u{06E3}', '\u{06E4}', '\u{06E7}', '\u{06E8}', '\u{06EA}', '\u{06EB}', '\u{06EC}', '\u{06ED}', '\u{0711}', '\u{0730}', '\u{0731}', '\u{0732}', '\u{0733}', '\u{0734}', '\u{0735}', '\u{0736}', '\u{0737}', '\u{0738}', '\u{0739}', '\u{073A}', '\u{073B}', '\u{073C}', '\u{073D}', '\u{073E}', '\u{073F}', '\u{0740}', '\u{0741}', '\u{0742}', '\u{0743}', '\u{0744}', '\u{0745}', '\u{0746}', '\u{0747}', '\u{0748}', '\u{0749}', '\u{074A}', '\u{07A6}', '\u{07A7}', '\u{07A8}', '\u{07A9}', '\u{07AA}', '\u{07AB}', '\u{07AC}', '\u{07AD}', '\u{07AE}', '\u{07AF}', '\u{07B0}', '\u{07EB}', '\u{07EC}', '\u{07ED}', '\u{07EE}', '\u{07EF}', '\u{07F0}', '\u{07F1}', '\u{07F2}', '\u{07F3}', '\u{0901}', '\u{0902}', '\u{093C}', '\u{0941}', '\u{0942}', '\u{0943}', '\u{0944}', '\u{0945}', '\u{0946}', '\u{0947}', '\u{0948}', '\u{094D}', '\u{0951}', '\u{0952}', '\u{0953}', '\u{0954}', '\u{0962}', '\u{0963}', '\u{0981}', '\u{09BC}', '\u{09C1}', '\u{09C2}', '\u{09C3}', '\u{09C4}', '\u{09CD}', '\u{09E2}', '\u{09E3}', '\u{0A01}', '\u{0A02}', '\u{0A3C}', '\u{0A41}', '\u{0A42}', '\u{0A47}', '\u{0A48}', '\u{0A4B}', '\u{0A4C}', '\u{0A4D}', '\u{0A51}', '\u{0A70}', '\u{0A71}', '\u{0A75}', '\u{0A81}', '\u{0A82}', '\u{0ABC}', '\u{0AC1}', '\u{0AC2}', '\u{0AC3}', '\u{0AC4}', '\u{0AC5}', '\u{0AC7}', '\u{0AC8}', '\u{0ACD}', '\u{0AE2}', '\u{0AE3}', '\u{0B01}', '\u{0B3C}', '\u{0B3F}', '\u{0B41}', '\u{0B42}', '\u{0B43}', '\u{0B44}', '\u{0B4D}', '\u{0B56}', '\u{0B62}', '\u{0B63}', '\u{0B82}', '\u{0BC0}', '\u{0BCD}', '\u{0C3E}', '\u{0C3F}', '\u{0C40}', '\u{0C46}', '\u{0C47}', '\u{0C48}', '\u{0C4A}', '\u{0C4B}', '\u{0C4C}', '\u{0C4D}', '\u{0C55}', '\u{0C56}', '\u{0C62}', '\u{0C63}', '\u{0CBC}', '\u{0CBF}', '\u{0CC6}', '\u{0CCC}', '\u{0CCD}', '\u{0CE2}', '\u{0CE3}', '\u{0D41}', '\u{0D42}', '\u{0D43}', '\u{0D44}', '\u{0D4D}', '\u{0D62}', '\u{0D63}', '\u{0DCA}', '\u{0DD2}', '\u{0DD3}', '\u{0DD4}', '\u{0DD6}', '\u{0E31}', '\u{0E34}', '\u{0E35}', '\u{0E36}', '\u{0E37}', '\u{0E38}', '\u{0E39}', '\u{0E3A}', '\u{0E47}', '\u{0E48}', '\u{0E49}', '\u{0E4A}', '\u{0E4B}', '\u{0E4C}', '\u{0E4D}', '\u{0E4E}', '\u{0EB1}', '\u{0EB4}', '\u{0EB5}', '\u{0EB6}', '\u{0EB7}', '\u{0EB8}', '\u{0EB9}', '\u{0EBB}', '\u{0EBC}', '\u{0EC8}', '\u{0EC9}', '\u{0ECA}', '\u{0ECB}', '\u{0ECC}', '\u{0ECD}', '\u{0F18}', '\u{0F19}', '\u{0F35}', '\u{0F37}', '\u{0F39}', '\u{0F71}', '\u{0F72}', '\u{0F73}', '\u{0F74}', '\u{0F75}', '\u{0F76}', '\u{0F77}', '\u{0F78}', '\u{0F79}', '\u{0F7A}', '\u{0F7B}', '\u{0F7C}', '\u{0F7D}', '\u{0F7E}', '\u{0F80}', '\u{0F81}', '\u{0F82}', '\u{0F83}', '\u{0F84}', '\u{0F86}', '\u{0F87}', '\u{0F90}', '\u{0F91}', '\u{0F92}', '\u{0F93}', '\u{0F94}', '\u{0F95}', '\u{0F96}', '\u{0F97}', '\u{0F99}', '\u{0F9A}', '\u{0F9B}', '\u{0F9C}', '\u{0F9D}', '\u{0F9E}', '\u{0F9F}', '\u{0FA0}', '\u{0FA1}', '\u{0FA2}', '\u{0FA3}', '\u{0FA4}', '\u{0FA5}', '\u{0FA6}', '\u{0FA7}', '\u{0FA8}', '\u{0FA9}', '\u{0FAA}', '\u{0FAB}', '\u{0FAC}', '\u{0FAD}', '\u{0FAE}', '\u{0FAF}', '\u{0FB0}', '\u{0FB1}', '\u{0FB2}', '\u{0FB3}', '\u{0FB4}', '\u{0FB5}', '\u{0FB6}', '\u{0FB7}', '\u{0FB8}', '\u{0FB9}', '\u{0FBA}', '\u{0FBB}', '\u{0FBC}', '\u{0FC6}', '\u{102D}', '\u{102E}', '\u{102F}', '\u{1030}', '\u{1032}', '\u{1033}', '\u{1034}', '\u{1035}', '\u{1036}', '\u{1037}', '\u{1039}', '\u{103A}', '\u{103D}', '\u{103E}', '\u{1058}', '\u{1059}', '\u{105E}', '\u{105F}', '\u{1060}', '\u{1071}', '\u{1072}', '\u{1073}', '\u{1074}', '\u{1082}', '\u{1085}', '\u{1086}', '\u{108D}', '\u{135F}', '\u{1712}', '\u{1713}', '\u{1714}', '\u{1732}', '\u{1733}', '\u{1734}', '\u{1752}', '\u{1753}', '\u{1772}', '\u{1773}', '\u{17B7}', '\u{17B8}', '\u{17B9}', '\u{17BA}', '\u{17BB}', '\u{17BC}', '\u{17BD}', '\u{17C6}', '\u{17C9}', '\u{17CA}', '\u{17CB}', '\u{17CC}', '\u{17CD}', '\u{17CE}', '\u{17CF}', '\u{17D0}', '\u{17D1}', '\u{17D2}', '\u{17D3}', '\u{17DD}', '\u{180B}', '\u{180C}', '\u{180D}', '\u{18A9}', '\u{1920}', '\u{1921}', '\u{1922}', '\u{1927}', '\u{1928}', '\u{1932}', '\u{1939}', '\u{193A}', '\u{193B}', '\u{1A17}', '\u{1A18}', '\u{1B00}', '\u{1B01}', '\u{1B02}', '\u{1B03}', '\u{1B34}', '\u{1B36}', '\u{1B37}', '\u{1B38}', '\u{1B39}', '\u{1B3A}', '\u{1B3C}', '\u{1B42}', '\u{1B6B}', '\u{1B6C}', '\u{1B6D}', '\u{1B6E}', '\u{1B6F}', '\u{1B70}', '\u{1B71}', '\u{1B72}', '\u{1B73}', '\u{1B80}', '\u{1B81}', '\u{1BA2}', '\u{1BA3}', '\u{1BA4}', '\u{1BA5}', '\u{1BA8}', '\u{1BA9}', '\u{1C2C}', '\u{1C2D}', '\u{1C2E}', '\u{1C2F}', '\u{1C30}', '\u{1C31}', '\u{1C32}', '\u{1C33}', '\u{1C36}', '\u{1C37}', '\u{1DC0}', '\u{1DC1}', '\u{1DC2}', '\u{1DC3}', '\u{1DC4}', '\u{1DC5}', '\u{1DC6}', '\u{1DC7}', '\u{1DC8}', '\u{1DC9}', '\u{1DCA}', '\u{1DCB}', '\u{1DCC}', '\u{1DCD}', '\u{1DCE}', '\u{1DCF}', '\u{1DD0}', '\u{1DD1}', '\u{1DD2}', '\u{1DD3}', '\u{1DD4}', '\u{1DD5}', '\u{1DD6}', '\u{1DD7}', '\u{1DD8}', '\u{1DD9}', '\u{1DDA}', '\u{1DDB}', '\u{1DDC}', '\u{1DDD}', '\u{1DDE}', '\u{1DDF}', '\u{1DE0}', '\u{1DE1}', '\u{1DE2}', '\u{1DE3}', '\u{1DE4}', '\u{1DE5}', '\u{1DE6}', '\u{1DFE}', '\u{1DFF}', '\u{20D0}', '\u{20D1}', '\u{20D2}', '\u{20D3}', '\u{20D4}', '\u{20D5}', '\u{20D6}', '\u{20D7}', '\u{20D8}', '\u{20D9}', '\u{20DA}', '\u{20DB}', '\u{20DC}', '\u{20E1}', '\u{20E5}', '\u{20E6}', '\u{20E7}', '\u{20E8}', '\u{20E9}', '\u{20EA}', '\u{20EB}', '\u{20EC}', '\u{20ED}', '\u{20EE}', '\u{20EF}', '\u{20F0}', '\u{2DE0}', '\u{2DE1}', '\u{2DE2}', '\u{2DE3}', '\u{2DE4}', '\u{2DE5}', '\u{2DE6}', '\u{2DE7}', '\u{2DE8}', '\u{2DE9}', '\u{2DEA}', '\u{2DEB}', '\u{2DEC}', '\u{2DED}', '\u{2DEE}', '\u{2DEF}', '\u{2DF0}', '\u{2DF1}', '\u{2DF2}', '\u{2DF3}', '\u{2DF4}', '\u{2DF5}', '\u{2DF6}', '\u{2DF7}', '\u{2DF8}', '\u{2DF9}', '\u{2DFA}', '\u{2DFB}', '\u{2DFC}', '\u{2DFD}', '\u{2DFE}', '\u{2DFF}', '\u{302A}', '\u{302B}', '\u{302C}', '\u{302D}', '\u{302E}', '\u{302F}', '\u{3099}', '\u{309A}', '\u{A66F}', '\u{A67C}', '\u{A67D}', '\u{A802}', '\u{A806}', '\u{A80B}', '\u{A825}', '\u{A826}', '\u{A8C4}', '\u{A926}', '\u{A927}', '\u{A928}', '\u{A929}', '\u{A92A}', '\u{A92B}', '\u{A92C}', '\u{A92D}', '\u{A947}', '\u{A948}', '\u{A949}', '\u{A94A}', '\u{A94B}', '\u{A94C}', '\u{A94D}', '\u{A94E}', '\u{A94F}', '\u{A950}', '\u{A951}', '\u{AA29}', '\u{AA2A}', '\u{AA2B}', '\u{AA2C}', '\u{AA2D}', '\u{AA2E}', '\u{AA31}', '\u{AA32}', '\u{AA35}', '\u{AA36}', '\u{AA43}', '\u{AA4C}', '\u{FB1E}', '\u{FE00}', '\u{FE01}', '\u{FE02}', '\u{FE03}', '\u{FE04}', '\u{FE05}', '\u{FE06}', '\u{FE07}', '\u{FE08}', '\u{FE09}', '\u{FE0A}', '\u{FE0B}', '\u{FE0C}', '\u{FE0D}', '\u{FE0E}', '\u{FE0F}', '\u{FE20}', '\u{FE21}', '\u{FE22}', '\u{FE23}', '\u{FE24}', '\u{FE25}', '\u{FE26}',              '\u{01BB}', '\u{01C0}', '\u{01C1}', '\u{01C2}', '\u{01C3}', '\u{0294}', '\u{05D0}', '\u{05D1}', '\u{05D2}', '\u{05D3}', '\u{05D4}', '\u{05D5}', '\u{05D6}', '\u{05D7}', '\u{05D8}', '\u{05D9}', '\u{05DA}', '\u{05DB}', '\u{05DC}', '\u{05DD}', '\u{05DE}', '\u{05DF}', '\u{05E0}', '\u{05E1}', '\u{05E2}', '\u{05E3}', '\u{05E4}', '\u{05E5}', '\u{05E6}', '\u{05E7}', '\u{05E8}', '\u{05E9}', '\u{05EA}', '\u{05F0}', '\u{05F1}', '\u{05F2}', '\u{0621}', '\u{0622}', '\u{0623}', '\u{0624}', '\u{0625}', '\u{0626}', '\u{0627}', '\u{0628}', '\u{0629}', '\u{062A}', '\u{062B}', '\u{062C}', '\u{062D}', '\u{062E}', '\u{062F}', '\u{0630}', '\u{0631}', '\u{0632}', '\u{0633}', '\u{0634}', '\u{0635}', '\u{0636}', '\u{0637}', '\u{0638}', '\u{0639}', '\u{063A}', '\u{063B}', '\u{063C}', '\u{063D}', '\u{063E}', '\u{063F}', '\u{0641}', '\u{0642}', '\u{0643}', '\u{0644}', '\u{0645}', '\u{0646}', '\u{0647}', '\u{0648}', '\u{0649}', '\u{064A}', '\u{066E}', '\u{066F}', '\u{0671}', '\u{0672}', '\u{0673}', '\u{0674}', '\u{0675}', '\u{0676}', '\u{0677}', '\u{0678}', '\u{0679}', '\u{067A}', '\u{067B}', '\u{067C}', '\u{067D}', '\u{067E}', '\u{067F}', '\u{0680}', '\u{0681}', '\u{0682}', '\u{0683}', '\u{0684}', '\u{0685}', '\u{0686}', '\u{0687}', '\u{0688}', '\u{0689}', '\u{068A}', '\u{068B}', '\u{068C}', '\u{068D}', '\u{068E}', '\u{068F}', '\u{0690}', '\u{0691}', '\u{0692}', '\u{0693}', '\u{0694}', '\u{0695}', '\u{0696}', '\u{0697}', '\u{0698}', '\u{0699}', '\u{069A}', '\u{069B}', '\u{069C}', '\u{069D}', '\u{069E}', '\u{069F}', '\u{06A0}', '\u{06A1}', '\u{06A2}', '\u{06A3}', '\u{06A4}', '\u{06A5}', '\u{06A6}', '\u{06A7}', '\u{06A8}', '\u{06A9}', '\u{06AA}', '\u{06AB}', '\u{06AC}', '\u{06AD}', '\u{06AE}', '\u{06AF}', '\u{06B0}', '\u{06B1}', '\u{06B2}', '\u{06B3}', '\u{06B4}', '\u{06B5}', '\u{06B6}', '\u{06B7}', '\u{06B8}', '\u{06B9}', '\u{06BA}', '\u{06BB}', '\u{06BC}', '\u{06BD}', '\u{06BE}', '\u{06BF}', '\u{06C0}', '\u{06C1}', '\u{06C2}', '\u{06C3}', '\u{06C4}', '\u{06C5}', '\u{06C6}', '\u{06C7}', '\u{06C8}', '\u{06C9}', '\u{06CA}', '\u{06CB}', '\u{06CC}', '\u{06CD}', '\u{06CE}', '\u{06CF}', '\u{06D0}', '\u{06D1}', '\u{06D2}', '\u{06D3}', '\u{06D5}', '\u{06EE}', '\u{06EF}', '\u{06FA}', '\u{06FB}', '\u{06FC}', '\u{06FF}', '\u{0710}', '\u{0712}', '\u{0713}', '\u{0714}', '\u{0715}', '\u{0716}', '\u{0717}', '\u{0718}', '\u{0719}', '\u{071A}', '\u{071B}', '\u{071C}', '\u{071D}', '\u{071E}', '\u{071F}', '\u{0720}', '\u{0721}', '\u{0722}', '\u{0723}', '\u{0724}', '\u{0725}', '\u{0726}', '\u{0727}', '\u{0728}', '\u{0729}', '\u{072A}', '\u{072B}', '\u{072C}', '\u{072D}', '\u{072E}', '\u{072F}', '\u{074D}', '\u{074E}', '\u{074F}', '\u{0750}', '\u{0751}', '\u{0752}', '\u{0753}', '\u{0754}', '\u{0755}', '\u{0756}', '\u{0757}', '\u{0758}', '\u{0759}', '\u{075A}', '\u{075B}', '\u{075C}', '\u{075D}', '\u{075E}', '\u{075F}', '\u{0760}', '\u{0761}', '\u{0762}', '\u{0763}', '\u{0764}', '\u{0765}', '\u{0766}', '\u{0767}', '\u{0768}', '\u{0769}', '\u{076A}', '\u{076B}', '\u{076C}', '\u{076D}', '\u{076E}', '\u{076F}', '\u{0770}', '\u{0771}', '\u{0772}', '\u{0773}', '\u{0774}', '\u{0775}', '\u{0776}', '\u{0777}', '\u{0778}', '\u{0779}', '\u{077A}', '\u{077B}', '\u{077C}', '\u{077D}', '\u{077E}', '\u{077F}', '\u{0780}', '\u{0781}', '\u{0782}', '\u{0783}', '\u{0784}', '\u{0785}', '\u{0786}', '\u{0787}', '\u{0788}', '\u{0789}', '\u{078A}', '\u{078B}', '\u{078C}', '\u{078D}', '\u{078E}', '\u{078F}', '\u{0790}', '\u{0791}', '\u{0792}', '\u{0793}', '\u{0794}', '\u{0795}', '\u{0796}', '\u{0797}', '\u{0798}', '\u{0799}', '\u{079A}', '\u{079B}', '\u{079C}', '\u{079D}', '\u{079E}', '\u{079F}', '\u{07A0}', '\u{07A1}', '\u{07A2}', '\u{07A3}', '\u{07A4}', '\u{07A5}', '\u{07B1}', '\u{07CA}', '\u{07CB}', '\u{07CC}', '\u{07CD}', '\u{07CE}', '\u{07CF}', '\u{07D0}', '\u{07D1}', '\u{07D2}', '\u{07D3}', '\u{07D4}', '\u{07D5}', '\u{07D6}', '\u{07D7}', '\u{07D8}', '\u{07D9}', '\u{07DA}', '\u{07DB}', '\u{07DC}', '\u{07DD}', '\u{07DE}', '\u{07DF}', '\u{07E0}', '\u{07E1}', '\u{07E2}', '\u{07E3}', '\u{07E4}', '\u{07E5}', '\u{07E6}', '\u{07E7}', '\u{07E8}', '\u{07E9}', '\u{07EA}', '\u{0904}', '\u{0905}', '\u{0906}', '\u{0907}', '\u{0908}', '\u{0909}', '\u{090A}', '\u{090B}', '\u{090C}', '\u{090D}', '\u{090E}', '\u{090F}', '\u{0910}', '\u{0911}', '\u{0912}', '\u{0913}', '\u{0914}', '\u{0915}', '\u{0916}', '\u{0917}', '\u{0918}', '\u{0919}', '\u{091A}', '\u{091B}', '\u{091C}', '\u{091D}', '\u{091E}', '\u{091F}', '\u{0920}', '\u{0921}', '\u{0922}', '\u{0923}', '\u{0924}', '\u{0925}', '\u{0926}', '\u{0927}', '\u{0928}', '\u{0929}', '\u{092A}', '\u{092B}', '\u{092C}', '\u{092D}', '\u{092E}', '\u{092F}', '\u{0930}', '\u{0931}', '\u{0932}', '\u{0933}', '\u{0934}', '\u{0935}', '\u{0936}', '\u{0937}', '\u{0938}', '\u{0939}', '\u{093D}', '\u{0950}', '\u{0958}', '\u{0959}', '\u{095A}', '\u{095B}', '\u{095C}', '\u{095D}', '\u{095E}', '\u{095F}', '\u{0960}', '\u{0961}', '\u{0972}', '\u{097B}', '\u{097C}', '\u{097D}', '\u{097E}', '\u{097F}', '\u{0985}', '\u{0986}', '\u{0987}', '\u{0988}', '\u{0989}', '\u{098A}', '\u{098B}', '\u{098C}', '\u{098F}', '\u{0990}', '\u{0993}', '\u{0994}', '\u{0995}', '\u{0996}', '\u{0997}', '\u{0998}', '\u{0999}', '\u{099A}', '\u{099B}', '\u{099C}', '\u{099D}', '\u{099E}', '\u{099F}', '\u{09A0}', '\u{09A1}', '\u{09A2}', '\u{09A3}', '\u{09A4}', '\u{09A5}', '\u{09A6}', '\u{09A7}', '\u{09A8}', '\u{09AA}', '\u{09AB}', '\u{09AC}', '\u{09AD}', '\u{09AE}', '\u{09AF}', '\u{09B0}', '\u{09B2}', '\u{09B6}', '\u{09B7}', '\u{09B8}', '\u{09B9}', '\u{09BD}', '\u{09CE}', '\u{09DC}', '\u{09DD}', '\u{09DF}', '\u{09E0}', '\u{09E1}', '\u{09F0}', '\u{09F1}', '\u{0A05}', '\u{0A06}', '\u{0A07}', '\u{0A08}', '\u{0A09}', '\u{0A0A}', '\u{0A0F}', '\u{0A10}', '\u{0A13}', '\u{0A14}', '\u{0A15}', '\u{0A16}', '\u{0A17}', '\u{0A18}', '\u{0A19}', '\u{0A1A}', '\u{0A1B}', '\u{0A1C}', '\u{0A1D}', '\u{0A1E}', '\u{0A1F}', '\u{0A20}', '\u{0A21}', '\u{0A22}', '\u{0A23}', '\u{0A24}', '\u{0A25}', '\u{0A26}', '\u{0A27}', '\u{0A28}', '\u{0A2A}', '\u{0A2B}', '\u{0A2C}', '\u{0A2D}', '\u{0A2E}', '\u{0A2F}', '\u{0A30}', '\u{0A32}', '\u{0A33}', '\u{0A35}', '\u{0A36}', '\u{0A38}', '\u{0A39}', '\u{0A59}', '\u{0A5A}', '\u{0A5B}', '\u{0A5C}', '\u{0A5E}', '\u{0A72}', '\u{0A73}', '\u{0A74}', '\u{0A85}', '\u{0A86}', '\u{0A87}', '\u{0A88}', '\u{0A89}', '\u{0A8A}', '\u{0A8B}', '\u{0A8C}', '\u{0A8D}', '\u{0A8F}', '\u{0A90}', '\u{0A91}', '\u{0A93}', '\u{0A94}', '\u{0A95}', '\u{0A96}', '\u{0A97}', '\u{0A98}', '\u{0A99}', '\u{0A9A}', '\u{0A9B}', '\u{0A9C}', '\u{0A9D}', '\u{0A9E}', '\u{0A9F}', '\u{0AA0}', '\u{0AA1}', '\u{0AA2}', '\u{0AA3}', '\u{0AA4}', '\u{0AA5}', '\u{0AA6}', '\u{0AA7}', '\u{0AA8}', '\u{0AAA}', '\u{0AAB}', '\u{0AAC}', '\u{0AAD}', '\u{0AAE}', '\u{0AAF}', '\u{0AB0}', '\u{0AB2}', '\u{0AB3}', '\u{0AB5}', '\u{0AB6}', '\u{0AB7}', '\u{0AB8}', '\u{0AB9}', '\u{0ABD}', '\u{0AD0}', '\u{0AE0}', '\u{0AE1}', '\u{0B05}', '\u{0B06}', '\u{0B07}', '\u{0B08}', '\u{0B09}', '\u{0B0A}', '\u{0B0B}', '\u{0B0C}', '\u{0B0F}', '\u{0B10}', '\u{0B13}', '\u{0B14}', '\u{0B15}', '\u{0B16}', '\u{0B17}', '\u{0B18}', '\u{0B19}', '\u{0B1A}', '\u{0B1B}', '\u{0B1C}', '\u{0B1D}', '\u{0B1E}', '\u{0B1F}', '\u{0B20}', '\u{0B21}', '\u{0B22}', '\u{0B23}', '\u{0B24}', '\u{0B25}', '\u{0B26}', '\u{0B27}', '\u{0B28}', '\u{0B2A}', '\u{0B2B}', '\u{0B2C}', '\u{0B2D}', '\u{0B2E}', '\u{0B2F}', '\u{0B30}', '\u{0B32}', '\u{0B33}', '\u{0B35}', '\u{0B36}', '\u{0B37}', '\u{0B38}', '\u{0B39}', '\u{0B3D}', '\u{0B5C}', '\u{0B5D}', '\u{0B5F}', '\u{0B60}', '\u{0B61}', '\u{0B71}', '\u{0B83}', '\u{0B85}', '\u{0B86}', '\u{0B87}', '\u{0B88}', '\u{0B89}', '\u{0B8A}', '\u{0B8E}', '\u{0B8F}', '\u{0B90}', '\u{0B92}', '\u{0B93}', '\u{0B94}', '\u{0B95}', '\u{0B99}', '\u{0B9A}', '\u{0B9C}', '\u{0B9E}', '\u{0B9F}', '\u{0BA3}', '\u{0BA4}', '\u{0BA8}', '\u{0BA9}', '\u{0BAA}', '\u{0BAE}', '\u{0BAF}', '\u{0BB0}', '\u{0BB1}', '\u{0BB2}', '\u{0BB3}', '\u{0BB4}', '\u{0BB5}', '\u{0BB6}', '\u{0BB7}', '\u{0BB8}', '\u{0BB9}', '\u{0BD0}', '\u{0C05}', '\u{0C06}', '\u{0C07}', '\u{0C08}', '\u{0C09}', '\u{0C0A}', '\u{0C0B}', '\u{0C0C}', '\u{0C0E}', '\u{0C0F}', '\u{0C10}', '\u{0C12}', '\u{0C13}', '\u{0C14}', '\u{0C15}', '\u{0C16}', '\u{0C17}', '\u{0C18}', '\u{0C19}', '\u{0C1A}', '\u{0C1B}', '\u{0C1C}', '\u{0C1D}', '\u{0C1E}', '\u{0C1F}', '\u{0C20}', '\u{0C21}', '\u{0C22}', '\u{0C23}', '\u{0C24}', '\u{0C25}', '\u{0C26}', '\u{0C27}', '\u{0C28}', '\u{0C2A}', '\u{0C2B}', '\u{0C2C}', '\u{0C2D}', '\u{0C2E}', '\u{0C2F}', '\u{0C30}', '\u{0C31}', '\u{0C32}', '\u{0C33}', '\u{0C35}', '\u{0C36}', '\u{0C37}', '\u{0C38}', '\u{0C39}', '\u{0C3D}', '\u{0C58}', '\u{0C59}', '\u{0C60}', '\u{0C61}', '\u{0C85}', '\u{0C86}', '\u{0C87}', '\u{0C88}', '\u{0C89}', '\u{0C8A}', '\u{0C8B}', '\u{0C8C}', '\u{0C8E}', '\u{0C8F}', '\u{0C90}', '\u{0C92}', '\u{0C93}', '\u{0C94}', '\u{0C95}', '\u{0C96}', '\u{0C97}', '\u{0C98}', '\u{0C99}', '\u{0C9A}', '\u{0C9B}', '\u{0C9C}', '\u{0C9D}', '\u{0C9E}', '\u{0C9F}', '\u{0CA0}', '\u{0CA1}', '\u{0CA2}', '\u{0CA3}', '\u{0CA4}', '\u{0CA5}', '\u{0CA6}', '\u{0CA7}', '\u{0CA8}', '\u{0CAA}', '\u{0CAB}', '\u{0CAC}', '\u{0CAD}', '\u{0CAE}', '\u{0CAF}', '\u{0CB0}', '\u{0CB1}', '\u{0CB2}', '\u{0CB3}', '\u{0CB5}', '\u{0CB6}', '\u{0CB7}', '\u{0CB8}', '\u{0CB9}', '\u{0CBD}', '\u{0CDE}', '\u{0CE0}', '\u{0CE1}', '\u{0D05}', '\u{0D06}', '\u{0D07}', '\u{0D08}', '\u{0D09}', '\u{0D0A}', '\u{0D0B}', '\u{0D0C}', '\u{0D0E}', '\u{0D0F}', '\u{0D10}', '\u{0D12}', '\u{0D13}', '\u{0D14}', '\u{0D15}', '\u{0D16}', '\u{0D17}', '\u{0D18}', '\u{0D19}', '\u{0D1A}', '\u{0D1B}', '\u{0D1C}', '\u{0D1D}', '\u{0D1E}', '\u{0D1F}', '\u{0D20}', '\u{0D21}', '\u{0D22}', '\u{0D23}', '\u{0D24}', '\u{0D25}', '\u{0D26}', '\u{0D27}', '\u{0D28}', '\u{0D2A}', '\u{0D2B}', '\u{0D2C}', '\u{0D2D}', '\u{0D2E}', '\u{0D2F}', '\u{0D30}', '\u{0D31}', '\u{0D32}', '\u{0D33}', '\u{0D34}', '\u{0D35}', '\u{0D36}', '\u{0D37}', '\u{0D38}', '\u{0D39}', '\u{0D3D}', '\u{0D60}', '\u{0D61}', '\u{0D7A}', '\u{0D7B}', '\u{0D7C}', '\u{0D7D}', '\u{0D7E}', '\u{0D7F}', '\u{0D85}', '\u{0D86}', '\u{0D87}', '\u{0D88}', '\u{0D89}', '\u{0D8A}', '\u{0D8B}', '\u{0D8C}', '\u{0D8D}', '\u{0D8E}', '\u{0D8F}', '\u{0D90}', '\u{0D91}', '\u{0D92}', '\u{0D93}', '\u{0D94}', '\u{0D95}', '\u{0D96}', '\u{0D9A}', '\u{0D9B}', '\u{0D9C}', '\u{0D9D}', '\u{0D9E}', '\u{0D9F}', '\u{0DA0}', '\u{0DA1}', '\u{0DA2}', '\u{0DA3}', '\u{0DA4}', '\u{0DA5}', '\u{0DA6}', '\u{0DA7}', '\u{0DA8}', '\u{0DA9}', '\u{0DAA}', '\u{0DAB}', '\u{0DAC}', '\u{0DAD}', '\u{0DAE}', '\u{0DAF}', '\u{0DB0}', '\u{0DB1}', '\u{0DB3}', '\u{0DB4}', '\u{0DB5}', '\u{0DB6}', '\u{0DB7}', '\u{0DB8}', '\u{0DB9}', '\u{0DBA}', '\u{0DBB}', '\u{0DBD}', '\u{0DC0}', '\u{0DC1}', '\u{0DC2}', '\u{0DC3}', '\u{0DC4}', '\u{0DC5}', '\u{0DC6}', '\u{0E01}', '\u{0E02}', '\u{0E03}', '\u{0E04}', '\u{0E05}', '\u{0E06}', '\u{0E07}', '\u{0E08}', '\u{0E09}', '\u{0E0A}', '\u{0E0B}', '\u{0E0C}', '\u{0E0D}', '\u{0E0E}', '\u{0E0F}', '\u{0E10}', '\u{0E11}', '\u{0E12}', '\u{0E13}', '\u{0E14}', '\u{0E15}', '\u{0E16}', '\u{0E17}', '\u{0E18}', '\u{0E19}', '\u{0E1A}', '\u{0E1B}', '\u{0E1C}', '\u{0E1D}', '\u{0E1E}', '\u{0E1F}', '\u{0E20}', '\u{0E21}', '\u{0E22}', '\u{0E23}', '\u{0E24}', '\u{0E25}', '\u{0E26}', '\u{0E27}', '\u{0E28}', '\u{0E29}', '\u{0E2A}', '\u{0E2B}', '\u{0E2C}', '\u{0E2D}', '\u{0E2E}', '\u{0E2F}', '\u{0E30}', '\u{0E32}', '\u{0E33}', '\u{0E40}', '\u{0E41}', '\u{0E42}', '\u{0E43}', '\u{0E44}', '\u{0E45}', '\u{0E81}', '\u{0E82}', '\u{0E84}', '\u{0E87}', '\u{0E88}', '\u{0E8A}', '\u{0E8D}', '\u{0E94}', '\u{0E95}', '\u{0E96}', '\u{0E97}', '\u{0E99}', '\u{0E9A}', '\u{0E9B}', '\u{0E9C}', '\u{0E9D}', '\u{0E9E}', '\u{0E9F}', '\u{0EA1}', '\u{0EA2}', '\u{0EA3}', '\u{0EA5}', '\u{0EA7}', '\u{0EAA}', '\u{0EAB}', '\u{0EAD}', '\u{0EAE}', '\u{0EAF}', '\u{0EB0}', '\u{0EB2}', '\u{0EB3}', '\u{0EBD}', '\u{0EC0}', '\u{0EC1}', '\u{0EC2}', '\u{0EC3}', '\u{0EC4}', '\u{0EDC}', '\u{0EDD}', '\u{0F00}', '\u{0F40}', '\u{0F41}', '\u{0F42}', '\u{0F43}', '\u{0F44}', '\u{0F45}', '\u{0F46}', '\u{0F47}', '\u{0F49}', '\u{0F4A}', '\u{0F4B}', '\u{0F4C}', '\u{0F4D}', '\u{0F4E}', '\u{0F4F}', '\u{0F50}', '\u{0F51}', '\u{0F52}', '\u{0F53}', '\u{0F54}', '\u{0F55}', '\u{0F56}', '\u{0F57}', '\u{0F58}', '\u{0F59}', '\u{0F5A}', '\u{0F5B}', '\u{0F5C}', '\u{0F5D}', '\u{0F5E}', '\u{0F5F}', '\u{0F60}', '\u{0F61}', '\u{0F62}', '\u{0F63}', '\u{0F64}', '\u{0F65}', '\u{0F66}', '\u{0F67}', '\u{0F68}', '\u{0F69}', '\u{0F6A}', '\u{0F6B}', '\u{0F6C}', '\u{0F88}', '\u{0F89}', '\u{0F8A}', '\u{0F8B}', '\u{1000}', '\u{1001}', '\u{1002}', '\u{1003}', '\u{1004}', '\u{1005}', '\u{1006}', '\u{1007}', '\u{1008}', '\u{1009}', '\u{100A}', '\u{100B}', '\u{100C}', '\u{100D}', '\u{100E}', '\u{100F}', '\u{1010}', '\u{1011}', '\u{1012}', '\u{1013}', '\u{1014}', '\u{1015}', '\u{1016}', '\u{1017}', '\u{1018}', '\u{1019}', '\u{101A}', '\u{101B}', '\u{101C}', '\u{101D}', '\u{101E}', '\u{101F}', '\u{1020}', '\u{1021}', '\u{1022}', '\u{1023}', '\u{1024}', '\u{1025}', '\u{1026}', '\u{1027}', '\u{1028}', '\u{1029}', '\u{102A}', '\u{103F}', '\u{1050}', '\u{1051}', '\u{1052}', '\u{1053}', '\u{1054}', '\u{1055}', '\u{105A}', '\u{105B}', '\u{105C}', '\u{105D}', '\u{1061}', '\u{1065}', '\u{1066}', '\u{106E}', '\u{106F}', '\u{1070}', '\u{1075}', '\u{1076}', '\u{1077}', '\u{1078}', '\u{1079}', '\u{107A}', '\u{107B}', '\u{107C}', '\u{107D}', '\u{107E}', '\u{107F}', '\u{1080}', '\u{1081}', '\u{108E}', '\u{10D0}', '\u{10D1}', '\u{10D2}', '\u{10D3}', '\u{10D4}', '\u{10D5}', '\u{10D6}', '\u{10D7}', '\u{10D8}', '\u{10D9}', '\u{10DA}', '\u{10DB}', '\u{10DC}', '\u{10DD}', '\u{10DE}', '\u{10DF}', '\u{10E0}', '\u{10E1}', '\u{10E2}', '\u{10E3}', '\u{10E4}', '\u{10E5}', '\u{10E6}', '\u{10E7}', '\u{10E8}', '\u{10E9}', '\u{10EA}', '\u{10EB}', '\u{10EC}', '\u{10ED}', '\u{10EE}', '\u{10EF}', '\u{10F0}', '\u{10F1}', '\u{10F2}', '\u{10F3}', '\u{10F4}', '\u{10F5}', '\u{10F6}', '\u{10F7}', '\u{10F8}', '\u{10F9}', '\u{10FA}', '\u{1100}', '\u{1101}', '\u{1102}', '\u{1103}', '\u{1104}', '\u{1105}', '\u{1106}', '\u{1107}', '\u{1108}', '\u{1109}', '\u{110A}', '\u{110B}', '\u{110C}', '\u{110D}', '\u{110E}', '\u{110F}', '\u{1110}', '\u{1111}', '\u{1112}', '\u{1113}', '\u{1114}', '\u{1115}', '\u{1116}', '\u{1117}', '\u{1118}', '\u{1119}', '\u{111A}', '\u{111B}', '\u{111C}', '\u{111D}', '\u{111E}', '\u{111F}', '\u{1120}', '\u{1121}', '\u{1122}', '\u{1123}', '\u{1124}', '\u{1125}', '\u{1126}', '\u{1127}', '\u{1128}', '\u{1129}', '\u{112A}', '\u{112B}', '\u{112C}', '\u{112D}', '\u{112E}', '\u{112F}', '\u{1130}', '\u{1131}', '\u{1132}', '\u{1133}', '\u{1134}', '\u{1135}', '\u{1136}', '\u{1137}', '\u{1138}', '\u{1139}', '\u{113A}', '\u{113B}', '\u{113C}', '\u{113D}', '\u{113E}', '\u{113F}', '\u{1140}', '\u{1141}', '\u{1142}', '\u{1143}', '\u{1144}', '\u{1145}', '\u{1146}', '\u{1147}', '\u{1148}', '\u{1149}', '\u{114A}', '\u{114B}', '\u{114C}', '\u{114D}', '\u{114E}', '\u{114F}', '\u{1150}', '\u{1151}', '\u{1152}', '\u{1153}', '\u{1154}', '\u{1155}', '\u{1156}', '\u{1157}', '\u{1158}', '\u{1159}', '\u{115F}', '\u{1160}', '\u{1161}', '\u{1162}', '\u{1163}', '\u{1164}', '\u{1165}', '\u{1166}', '\u{1167}', '\u{1168}', '\u{1169}', '\u{116A}', '\u{116B}', '\u{116C}', '\u{116D}', '\u{116E}', '\u{116F}', '\u{1170}', '\u{1171}', '\u{1172}', '\u{1173}', '\u{1174}', '\u{1175}', '\u{1176}', '\u{1177}', '\u{1178}', '\u{1179}', '\u{117A}', '\u{117B}', '\u{117C}', '\u{117D}', '\u{117E}', '\u{117F}', '\u{1180}', '\u{1181}', '\u{1182}', '\u{1183}', '\u{1184}', '\u{1185}', '\u{1186}', '\u{1187}', '\u{1188}', '\u{1189}', '\u{118A}', '\u{118B}', '\u{118C}', '\u{118D}', '\u{118E}', '\u{118F}', '\u{1190}', '\u{1191}', '\u{1192}', '\u{1193}', '\u{1194}', '\u{1195}', '\u{1196}', '\u{1197}', '\u{1198}', '\u{1199}', '\u{119A}', '\u{119B}', '\u{119C}', '\u{119D}', '\u{119E}', '\u{119F}', '\u{11A0}', '\u{11A1}', '\u{11A2}', '\u{11A8}', '\u{11A9}', '\u{11AA}', '\u{11AB}', '\u{11AC}', '\u{11AD}', '\u{11AE}', '\u{11AF}', '\u{11B0}', '\u{11B1}', '\u{11B2}', '\u{11B3}', '\u{11B4}', '\u{11B5}', '\u{11B6}', '\u{11B7}', '\u{11B8}', '\u{11B9}', '\u{11BA}', '\u{11BB}', '\u{11BC}', '\u{11BD}', '\u{11BE}', '\u{11BF}', '\u{11C0}', '\u{11C1}', '\u{11C2}', '\u{11C3}', '\u{11C4}', '\u{11C5}', '\u{11C6}', '\u{11C7}', '\u{11C8}', '\u{11C9}', '\u{11CA}', '\u{11CB}', '\u{11CC}', '\u{11CD}', '\u{11CE}', '\u{11CF}', '\u{11D0}', '\u{11D1}', '\u{11D2}', '\u{11D3}', '\u{11D4}', '\u{11D5}', '\u{11D6}', '\u{11D7}', '\u{11D8}', '\u{11D9}', '\u{11DA}', '\u{11DB}', '\u{11DC}', '\u{11DD}', '\u{11DE}', '\u{11DF}', '\u{11E0}', '\u{11E1}', '\u{11E2}', '\u{11E3}', '\u{11E4}', '\u{11E5}', '\u{11E6}', '\u{11E7}', '\u{11E8}', '\u{11E9}', '\u{11EA}', '\u{11EB}', '\u{11EC}', '\u{11ED}', '\u{11EE}', '\u{11EF}', '\u{11F0}', '\u{11F1}', '\u{11F2}', '\u{11F3}', '\u{11F4}', '\u{11F5}', '\u{11F6}', '\u{11F7}', '\u{11F8}', '\u{11F9}', '\u{1200}', '\u{1201}', '\u{1202}', '\u{1203}', '\u{1204}', '\u{1205}', '\u{1206}', '\u{1207}', '\u{1208}', '\u{1209}', '\u{120A}', '\u{120B}', '\u{120C}', '\u{120D}', '\u{120E}', '\u{120F}', '\u{1210}', '\u{1211}', '\u{1212}', '\u{1213}', '\u{1214}', '\u{1215}', '\u{1216}', '\u{1217}', '\u{1218}', '\u{1219}', '\u{121A}', '\u{121B}', '\u{121C}', '\u{121D}', '\u{121E}', '\u{121F}', '\u{1220}', '\u{1221}', '\u{1222}', '\u{1223}', '\u{1224}', '\u{1225}', '\u{1226}', '\u{1227}', '\u{1228}', '\u{1229}', '\u{122A}', '\u{122B}', '\u{122C}', '\u{122D}', '\u{122E}', '\u{122F}', '\u{1230}', '\u{1231}', '\u{1232}', '\u{1233}', '\u{1234}', '\u{1235}', '\u{1236}', '\u{1237}', '\u{1238}', '\u{1239}', '\u{123A}', '\u{123B}', '\u{123C}', '\u{123D}', '\u{123E}', '\u{123F}', '\u{1240}', '\u{1241}', '\u{1242}', '\u{1243}', '\u{1244}', '\u{1245}', '\u{1246}', '\u{1247}', '\u{1248}', '\u{124A}', '\u{124B}', '\u{124C}', '\u{124D}', '\u{1250}', '\u{1251}', '\u{1252}', '\u{1253}', '\u{1254}', '\u{1255}', '\u{1256}', '\u{1258}', '\u{125A}', '\u{125B}', '\u{125C}', '\u{125D}', '\u{1260}', '\u{1261}', '\u{1262}', '\u{1263}', '\u{1264}', '\u{1265}', '\u{1266}', '\u{1267}', '\u{1268}', '\u{1269}', '\u{126A}', '\u{126B}', '\u{126C}', '\u{126D}', '\u{126E}', '\u{126F}', '\u{1270}', '\u{1271}', '\u{1272}', '\u{1273}', '\u{1274}', '\u{1275}', '\u{1276}', '\u{1277}', '\u{1278}', '\u{1279}', '\u{127A}', '\u{127B}', '\u{127C}', '\u{127D}', '\u{127E}', '\u{127F}', '\u{1280}', '\u{1281}', '\u{1282}', '\u{1283}', '\u{1284}', '\u{1285}', '\u{1286}', '\u{1287}', '\u{1288}', '\u{128A}', '\u{128B}', '\u{128C}', '\u{128D}', '\u{1290}', '\u{1291}', '\u{1292}', '\u{1293}', '\u{1294}', '\u{1295}', '\u{1296}', '\u{1297}', '\u{1298}', '\u{1299}', '\u{129A}', '\u{129B}', '\u{129C}', '\u{129D}', '\u{129E}', '\u{129F}', '\u{12A0}', '\u{12A1}', '\u{12A2}', '\u{12A3}', '\u{12A4}', '\u{12A5}', '\u{12A6}', '\u{12A7}', '\u{12A8}', '\u{12A9}', '\u{12AA}', '\u{12AB}', '\u{12AC}', '\u{12AD}', '\u{12AE}', '\u{12AF}', '\u{12B0}', '\u{12B2}', '\u{12B3}', '\u{12B4}', '\u{12B5}', '\u{12B8}', '\u{12B9}', '\u{12BA}', '\u{12BB}', '\u{12BC}', '\u{12BD}', '\u{12BE}', '\u{12C0}', '\u{12C2}', '\u{12C3}', '\u{12C4}', '\u{12C5}', '\u{12C8}', '\u{12C9}', '\u{12CA}', '\u{12CB}', '\u{12CC}', '\u{12CD}', '\u{12CE}', '\u{12CF}', '\u{12D0}', '\u{12D1}', '\u{12D2}', '\u{12D3}', '\u{12D4}', '\u{12D5}', '\u{12D6}', '\u{12D8}', '\u{12D9}', '\u{12DA}', '\u{12DB}', '\u{12DC}', '\u{12DD}', '\u{12DE}', '\u{12DF}', '\u{12E0}', '\u{12E1}', '\u{12E2}', '\u{12E3}', '\u{12E4}', '\u{12E5}', '\u{12E6}', '\u{12E7}', '\u{12E8}', '\u{12E9}', '\u{12EA}', '\u{12EB}', '\u{12EC}', '\u{12ED}', '\u{12EE}', '\u{12EF}', '\u{12F0}', '\u{12F1}', '\u{12F2}', '\u{12F3}', '\u{12F4}', '\u{12F5}', '\u{12F6}', '\u{12F7}', '\u{12F8}', '\u{12F9}', '\u{12FA}', '\u{12FB}', '\u{12FC}', '\u{12FD}', '\u{12FE}', '\u{12FF}', '\u{1300}', '\u{1301}', '\u{1302}', '\u{1303}', '\u{1304}', '\u{1305}', '\u{1306}', '\u{1307}', '\u{1308}', '\u{1309}', '\u{130A}', '\u{130B}', '\u{130C}', '\u{130D}', '\u{130E}', '\u{130F}', '\u{1310}', '\u{1312}', '\u{1313}', '\u{1314}', '\u{1315}', '\u{1318}', '\u{1319}', '\u{131A}', '\u{131B}', '\u{131C}', '\u{131D}', '\u{131E}', '\u{131F}', '\u{1320}', '\u{1321}', '\u{1322}', '\u{1323}', '\u{1324}', '\u{1325}', '\u{1326}', '\u{1327}', '\u{1328}', '\u{1329}', '\u{132A}', '\u{132B}', '\u{132C}', '\u{132D}', '\u{132E}', '\u{132F}', '\u{1330}', '\u{1331}', '\u{1332}', '\u{1333}', '\u{1334}', '\u{1335}', '\u{1336}', '\u{1337}', '\u{1338}', '\u{1339}', '\u{133A}', '\u{133B}', '\u{133C}', '\u{133D}', '\u{133E}', '\u{133F}', '\u{1340}', '\u{1341}', '\u{1342}', '\u{1343}', '\u{1344}', '\u{1345}', '\u{1346}', '\u{1347}', '\u{1348}', '\u{1349}', '\u{134A}', '\u{134B}', '\u{134C}', '\u{134D}', '\u{134E}', '\u{134F}', '\u{1350}', '\u{1351}', '\u{1352}', '\u{1353}', '\u{1354}', '\u{1355}', '\u{1356}', '\u{1357}', '\u{1358}', '\u{1359}', '\u{135A}', '\u{1380}', '\u{1381}', '\u{1382}', '\u{1383}', '\u{1384}', '\u{1385}', '\u{1386}', '\u{1387}', '\u{1388}', '\u{1389}', '\u{138A}', '\u{138B}', '\u{138C}', '\u{138D}', '\u{138E}', '\u{138F}', '\u{13A0}', '\u{13A1}', '\u{13A2}', '\u{13A3}', '\u{13A4}', '\u{13A5}', '\u{13A6}', '\u{13A7}', '\u{13A8}', '\u{13A9}', '\u{13AA}', '\u{13AB}', '\u{13AC}', '\u{13AD}', '\u{13AE}', '\u{13AF}', '\u{13B0}', '\u{13B1}', '\u{13B2}', '\u{13B3}', '\u{13B4}', '\u{13B5}', '\u{13B6}', '\u{13B7}', '\u{13B8}', '\u{13B9}', '\u{13BA}', '\u{13BB}', '\u{13BC}', '\u{13BD}', '\u{13BE}', '\u{13BF}', '\u{13C0}', '\u{13C1}', '\u{13C2}', '\u{13C3}', '\u{13C4}', '\u{13C5}', '\u{13C6}', '\u{13C7}', '\u{13C8}', '\u{13C9}', '\u{13CA}', '\u{13CB}', '\u{13CC}', '\u{13CD}', '\u{13CE}', '\u{13CF}', '\u{13D0}', '\u{13D1}', '\u{13D2}', '\u{13D3}', '\u{13D4}', '\u{13D5}', '\u{13D6}', '\u{13D7}', '\u{13D8}', '\u{13D9}', '\u{13DA}', '\u{13DB}', '\u{13DC}', '\u{13DD}', '\u{13DE}', '\u{13DF}', '\u{13E0}', '\u{13E1}', '\u{13E2}', '\u{13E3}', '\u{13E4}', '\u{13E5}', '\u{13E6}', '\u{13E7}', '\u{13E8}', '\u{13E9}', '\u{13EA}', '\u{13EB}', '\u{13EC}', '\u{13ED}', '\u{13EE}', '\u{13EF}', '\u{13F0}', '\u{13F1}', '\u{13F2}', '\u{13F3}', '\u{13F4}', '\u{1401}', '\u{1402}', '\u{1403}', '\u{1404}', '\u{1405}', '\u{1406}', '\u{1407}', '\u{1408}', '\u{1409}', '\u{140A}', '\u{140B}', '\u{140C}', '\u{140D}', '\u{140E}', '\u{140F}', '\u{1410}', '\u{1411}', '\u{1412}', '\u{1413}', '\u{1414}', '\u{1415}', '\u{1416}', '\u{1417}', '\u{1418}', '\u{1419}', '\u{141A}', '\u{141B}', '\u{141C}', '\u{141D}', '\u{141E}', '\u{141F}', '\u{1420}', '\u{1421}', '\u{1422}', '\u{1423}', '\u{1424}', '\u{1425}', '\u{1426}', '\u{1427}', '\u{1428}', '\u{1429}', '\u{142A}', '\u{142B}', '\u{142C}', '\u{142D}', '\u{142E}', '\u{142F}', '\u{1430}', '\u{1431}', '\u{1432}', '\u{1433}', '\u{1434}', '\u{1435}', '\u{1436}', '\u{1437}', '\u{1438}', '\u{1439}', '\u{143A}', '\u{143B}', '\u{143C}', '\u{143D}', '\u{143E}', '\u{143F}', '\u{1440}', '\u{1441}', '\u{1442}', '\u{1443}', '\u{1444}', '\u{1445}', '\u{1446}', '\u{1447}', '\u{1448}', '\u{1449}', '\u{144A}', '\u{144B}', '\u{144C}', '\u{144D}', '\u{144E}', '\u{144F}', '\u{1450}', '\u{1451}', '\u{1452}', '\u{1453}', '\u{1454}', '\u{1455}', '\u{1456}', '\u{1457}', '\u{1458}', '\u{1459}', '\u{145A}', '\u{145B}', '\u{145C}', '\u{145D}', '\u{145E}', '\u{145F}', '\u{1460}', '\u{1461}', '\u{1462}', '\u{1463}', '\u{1464}', '\u{1465}', '\u{1466}', '\u{1467}', '\u{1468}', '\u{1469}', '\u{146A}', '\u{146B}', '\u{146C}', '\u{146D}', '\u{146E}', '\u{146F}', '\u{1470}', '\u{1471}', '\u{1472}', '\u{1473}', '\u{1474}', '\u{1475}', '\u{1476}', '\u{1477}', '\u{1478}', '\u{1479}', '\u{147A}', '\u{147B}', '\u{147C}', '\u{147D}', '\u{147E}', '\u{147F}', '\u{1480}', '\u{1481}', '\u{1482}', '\u{1483}', '\u{1484}', '\u{1485}', '\u{1486}', '\u{1487}', '\u{1488}', '\u{1489}', '\u{148A}', '\u{148B}', '\u{148C}', '\u{148D}', '\u{148E}', '\u{148F}', '\u{1490}', '\u{1491}', '\u{1492}', '\u{1493}', '\u{1494}', '\u{1495}', '\u{1496}', '\u{1497}', '\u{1498}', '\u{1499}', '\u{149A}', '\u{149B}', '\u{149C}', '\u{149D}', '\u{149E}', '\u{149F}', '\u{14A0}', '\u{14A1}', '\u{14A2}', '\u{14A3}', '\u{14A4}', '\u{14A5}', '\u{14A6}', '\u{14A7}', '\u{14A8}', '\u{14A9}', '\u{14AA}', '\u{14AB}', '\u{14AC}', '\u{14AD}', '\u{14AE}', '\u{14AF}', '\u{14B0}', '\u{14B1}', '\u{14B2}', '\u{14B3}', '\u{14B4}', '\u{14B5}', '\u{14B6}', '\u{14B7}', '\u{14B8}', '\u{14B9}', '\u{14BA}', '\u{14BB}', '\u{14BC}', '\u{14BD}', '\u{14BE}', '\u{14BF}', '\u{14C0}', '\u{14C1}', '\u{14C2}', '\u{14C3}', '\u{14C4}', '\u{14C5}', '\u{14C6}', '\u{14C7}', '\u{14C8}', '\u{14C9}', '\u{14CA}', '\u{14CB}', '\u{14CC}', '\u{14CD}', '\u{14CE}', '\u{14CF}', '\u{14D0}', '\u{14D1}', '\u{14D2}', '\u{14D3}', '\u{14D4}', '\u{14D5}', '\u{14D6}', '\u{14D7}', '\u{14D8}', '\u{14D9}', '\u{14DA}', '\u{14DB}', '\u{14DC}', '\u{14DD}', '\u{14DE}', '\u{14DF}', '\u{14E0}', '\u{14E1}', '\u{14E2}', '\u{14E3}', '\u{14E4}', '\u{14E5}', '\u{14E6}', '\u{14E7}', '\u{14E8}', '\u{14E9}', '\u{14EA}', '\u{14EB}', '\u{14EC}', '\u{14ED}', '\u{14EE}', '\u{14EF}', '\u{14F0}', '\u{14F1}', '\u{14F2}', '\u{14F3}', '\u{14F4}', '\u{14F5}', '\u{14F6}', '\u{14F7}', '\u{14F8}', '\u{14F9}', '\u{14FA}', '\u{14FB}', '\u{14FC}', '\u{14FD}', '\u{14FE}', '\u{14FF}', '\u{1500}', '\u{1501}', '\u{1502}', '\u{1503}', '\u{1504}', '\u{1505}', '\u{1506}', '\u{1507}', '\u{1508}', '\u{1509}', '\u{150A}', '\u{150B}', '\u{150C}', '\u{150D}', '\u{150E}', '\u{150F}', '\u{1510}', '\u{1511}', '\u{1512}', '\u{1513}', '\u{1514}', '\u{1515}', '\u{1516}', '\u{1517}', '\u{1518}', '\u{1519}', '\u{151A}', '\u{151B}', '\u{151C}', '\u{151D}', '\u{151E}', '\u{151F}', '\u{1520}', '\u{1521}', '\u{1522}', '\u{1523}', '\u{1524}', '\u{1525}', '\u{1526}', '\u{1527}', '\u{1528}', '\u{1529}', '\u{152A}', '\u{152B}', '\u{152C}', '\u{152D}', '\u{152E}', '\u{152F}', '\u{1530}', '\u{1531}', '\u{1532}', '\u{1533}', '\u{1534}', '\u{1535}', '\u{1536}', '\u{1537}', '\u{1538}', '\u{1539}', '\u{153A}', '\u{153B}', '\u{153C}', '\u{153D}', '\u{153E}', '\u{153F}', '\u{1540}', '\u{1541}', '\u{1542}', '\u{1543}', '\u{1544}', '\u{1545}', '\u{1546}', '\u{1547}', '\u{1548}', '\u{1549}', '\u{154A}', '\u{154B}', '\u{154C}', '\u{154D}', '\u{154E}', '\u{154F}', '\u{1550}', '\u{1551}', '\u{1552}', '\u{1553}', '\u{1554}', '\u{1555}', '\u{1556}', '\u{1557}', '\u{1558}', '\u{1559}', '\u{155A}', '\u{155B}', '\u{155C}', '\u{155D}', '\u{155E}', '\u{155F}', '\u{1560}', '\u{1561}', '\u{1562}', '\u{1563}', '\u{1564}', '\u{1565}', '\u{1566}', '\u{1567}', '\u{1568}', '\u{1569}', '\u{156A}', '\u{156B}', '\u{156C}', '\u{156D}', '\u{156E}', '\u{156F}', '\u{1570}', '\u{1571}', '\u{1572}', '\u{1573}', '\u{1574}', '\u{1575}', '\u{1576}', '\u{1577}', '\u{1578}', '\u{1579}', '\u{157A}', '\u{157B}', '\u{157C}', '\u{157D}', '\u{157E}', '\u{157F}', '\u{1580}', '\u{1581}', '\u{1582}', '\u{1583}', '\u{1584}', '\u{1585}', '\u{1586}', '\u{1587}', '\u{1588}', '\u{1589}', '\u{158A}', '\u{158B}', '\u{158C}', '\u{158D}', '\u{158E}', '\u{158F}', '\u{1590}', '\u{1591}', '\u{1592}', '\u{1593}', '\u{1594}', '\u{1595}', '\u{1596}', '\u{1597}', '\u{1598}', '\u{1599}', '\u{159A}', '\u{159B}', '\u{159C}', '\u{159D}', '\u{159E}', '\u{159F}', '\u{15A0}', '\u{15A1}', '\u{15A2}', '\u{15A3}', '\u{15A4}', '\u{15A5}', '\u{15A6}', '\u{15A7}', '\u{15A8}', '\u{15A9}', '\u{15AA}', '\u{15AB}', '\u{15AC}', '\u{15AD}', '\u{15AE}', '\u{15AF}', '\u{15B0}', '\u{15B1}', '\u{15B2}', '\u{15B3}', '\u{15B4}', '\u{15B5}', '\u{15B6}', '\u{15B7}', '\u{15B8}', '\u{15B9}', '\u{15BA}', '\u{15BB}', '\u{15BC}', '\u{15BD}', '\u{15BE}', '\u{15BF}', '\u{15C0}', '\u{15C1}', '\u{15C2}', '\u{15C3}', '\u{15C4}', '\u{15C5}', '\u{15C6}', '\u{15C7}', '\u{15C8}', '\u{15C9}', '\u{15CA}', '\u{15CB}', '\u{15CC}', '\u{15CD}', '\u{15CE}', '\u{15CF}', '\u{15D0}', '\u{15D1}', '\u{15D2}', '\u{15D3}', '\u{15D4}', '\u{15D5}', '\u{15D6}', '\u{15D7}', '\u{15D8}', '\u{15D9}', '\u{15DA}', '\u{15DB}', '\u{15DC}', '\u{15DD}', '\u{15DE}', '\u{15DF}', '\u{15E0}', '\u{15E1}', '\u{15E2}', '\u{15E3}', '\u{15E4}', '\u{15E5}', '\u{15E6}', '\u{15E7}', '\u{15E8}', '\u{15E9}', '\u{15EA}', '\u{15EB}', '\u{15EC}', '\u{15ED}', '\u{15EE}', '\u{15EF}', '\u{15F0}', '\u{15F1}', '\u{15F2}', '\u{15F3}', '\u{15F4}', '\u{15F5}', '\u{15F6}', '\u{15F7}', '\u{15F8}', '\u{15F9}', '\u{15FA}', '\u{15FB}', '\u{15FC}', '\u{15FD}', '\u{15FE}', '\u{15FF}', '\u{1600}', '\u{1601}', '\u{1602}', '\u{1603}', '\u{1604}', '\u{1605}', '\u{1606}', '\u{1607}', '\u{1608}', '\u{1609}', '\u{160A}', '\u{160B}', '\u{160C}', '\u{160D}', '\u{160E}', '\u{160F}', '\u{1610}', '\u{1611}', '\u{1612}', '\u{1613}', '\u{1614}', '\u{1615}', '\u{1616}', '\u{1617}', '\u{1618}', '\u{1619}', '\u{161A}', '\u{161B}', '\u{161C}', '\u{161D}', '\u{161E}', '\u{161F}', '\u{1620}', '\u{1621}', '\u{1622}', '\u{1623}', '\u{1624}', '\u{1625}', '\u{1626}', '\u{1627}', '\u{1628}', '\u{1629}', '\u{162A}', '\u{162B}', '\u{162C}', '\u{162D}', '\u{162E}', '\u{162F}', '\u{1630}', '\u{1631}', '\u{1632}', '\u{1633}', '\u{1634}', '\u{1635}', '\u{1636}', '\u{1637}', '\u{1638}', '\u{1639}', '\u{163A}', '\u{163B}', '\u{163C}', '\u{163D}', '\u{163E}', '\u{163F}', '\u{1640}', '\u{1641}', '\u{1642}', '\u{1643}', '\u{1644}', '\u{1645}', '\u{1646}', '\u{1647}', '\u{1648}', '\u{1649}', '\u{164A}', '\u{164B}', '\u{164C}', '\u{164D}', '\u{164E}', '\u{164F}', '\u{1650}', '\u{1651}', '\u{1652}', '\u{1653}', '\u{1654}', '\u{1655}', '\u{1656}', '\u{1657}', '\u{1658}', '\u{1659}', '\u{165A}', '\u{165B}', '\u{165C}', '\u{165D}', '\u{165E}', '\u{165F}', '\u{1660}', '\u{1661}', '\u{1662}', '\u{1663}', '\u{1664}', '\u{1665}', '\u{1666}', '\u{1667}', '\u{1668}', '\u{1669}', '\u{166A}', '\u{166B}', '\u{166C}', '\u{166F}', '\u{1670}', '\u{1671}', '\u{1672}', '\u{1673}', '\u{1674}', '\u{1675}', '\u{1676}', '\u{1681}', '\u{1682}', '\u{1683}', '\u{1684}', '\u{1685}', '\u{1686}', '\u{1687}', '\u{1688}', '\u{1689}', '\u{168A}', '\u{168B}', '\u{168C}', '\u{168D}', '\u{168E}', '\u{168F}', '\u{1690}', '\u{1691}', '\u{1692}', '\u{1693}', '\u{1694}', '\u{1695}', '\u{1696}', '\u{1697}', '\u{1698}', '\u{1699}', '\u{169A}', '\u{16A0}', '\u{16A1}', '\u{16A2}', '\u{16A3}', '\u{16A4}', '\u{16A5}', '\u{16A6}', '\u{16A7}', '\u{16A8}', '\u{16A9}', '\u{16AA}', '\u{16AB}', '\u{16AC}', '\u{16AD}', '\u{16AE}', '\u{16AF}', '\u{16B0}', '\u{16B1}', '\u{16B2}', '\u{16B3}', '\u{16B4}', '\u{16B5}', '\u{16B6}', '\u{16B7}', '\u{16B8}', '\u{16B9}', '\u{16BA}', '\u{16BB}', '\u{16BC}', '\u{16BD}', '\u{16BE}', '\u{16BF}', '\u{16C0}', '\u{16C1}', '\u{16C2}', '\u{16C3}', '\u{16C4}', '\u{16C5}', '\u{16C6}', '\u{16C7}', '\u{16C8}', '\u{16C9}', '\u{16CA}', '\u{16CB}', '\u{16CC}', '\u{16CD}', '\u{16CE}', '\u{16CF}', '\u{16D0}', '\u{16D1}', '\u{16D2}', '\u{16D3}', '\u{16D4}', '\u{16D5}', '\u{16D6}', '\u{16D7}', '\u{16D8}', '\u{16D9}', '\u{16DA}', '\u{16DB}', '\u{16DC}', '\u{16DD}', '\u{16DE}', '\u{16DF}', '\u{16E0}', '\u{16E1}', '\u{16E2}', '\u{16E3}', '\u{16E4}', '\u{16E5}', '\u{16E6}', '\u{16E7}', '\u{16E8}', '\u{16E9}', '\u{16EA}', '\u{1700}', '\u{1701}', '\u{1702}', '\u{1703}', '\u{1704}', '\u{1705}', '\u{1706}', '\u{1707}', '\u{1708}', '\u{1709}', '\u{170A}', '\u{170B}', '\u{170C}', '\u{170E}', '\u{170F}', '\u{1710}', '\u{1711}', '\u{1720}', '\u{1721}', '\u{1722}', '\u{1723}', '\u{1724}', '\u{1725}', '\u{1726}', '\u{1727}', '\u{1728}', '\u{1729}', '\u{172A}', '\u{172B}', '\u{172C}', '\u{172D}', '\u{172E}', '\u{172F}', '\u{1730}', '\u{1731}', '\u{1740}', '\u{1741}', '\u{1742}', '\u{1743}', '\u{1744}', '\u{1745}', '\u{1746}', '\u{1747}', '\u{1748}', '\u{1749}', '\u{174A}', '\u{174B}', '\u{174C}', '\u{174D}', '\u{174E}', '\u{174F}', '\u{1750}', '\u{1751}', '\u{1760}', '\u{1761}', '\u{1762}', '\u{1763}', '\u{1764}', '\u{1765}', '\u{1766}', '\u{1767}', '\u{1768}', '\u{1769}', '\u{176A}', '\u{176B}', '\u{176C}', '\u{176E}', '\u{176F}', '\u{1770}', '\u{1780}', '\u{1781}', '\u{1782}', '\u{1783}', '\u{1784}', '\u{1785}', '\u{1786}', '\u{1787}', '\u{1788}', '\u{1789}', '\u{178A}', '\u{178B}', '\u{178C}', '\u{178D}', '\u{178E}', '\u{178F}', '\u{1790}', '\u{1791}', '\u{1792}', '\u{1793}', '\u{1794}', '\u{1795}', '\u{1796}', '\u{1797}', '\u{1798}', '\u{1799}', '\u{179A}', '\u{179B}', '\u{179C}', '\u{179D}', '\u{179E}', '\u{179F}', '\u{17A0}', '\u{17A1}', '\u{17A2}', '\u{17A3}', '\u{17A4}', '\u{17A5}', '\u{17A6}', '\u{17A7}', '\u{17A8}', '\u{17A9}', '\u{17AA}', '\u{17AB}', '\u{17AC}', '\u{17AD}', '\u{17AE}', '\u{17AF}', '\u{17B0}', '\u{17B1}', '\u{17B2}', '\u{17B3}', '\u{17DC}', '\u{1820}', '\u{1821}', '\u{1822}', '\u{1823}', '\u{1824}', '\u{1825}', '\u{1826}', '\u{1827}', '\u{1828}', '\u{1829}', '\u{182A}', '\u{182B}', '\u{182C}', '\u{182D}', '\u{182E}', '\u{182F}', '\u{1830}', '\u{1831}', '\u{1832}', '\u{1833}', '\u{1834}', '\u{1835}', '\u{1836}', '\u{1837}', '\u{1838}', '\u{1839}', '\u{183A}', '\u{183B}', '\u{183C}', '\u{183D}', '\u{183E}', '\u{183F}', '\u{1840}', '\u{1841}', '\u{1842}', '\u{1844}', '\u{1845}', '\u{1846}', '\u{1847}', '\u{1848}', '\u{1849}', '\u{184A}', '\u{184B}', '\u{184C}', '\u{184D}', '\u{184E}', '\u{184F}', '\u{1850}', '\u{1851}', '\u{1852}', '\u{1853}', '\u{1854}', '\u{1855}', '\u{1856}', '\u{1857}', '\u{1858}', '\u{1859}', '\u{185A}', '\u{185B}', '\u{185C}', '\u{185D}', '\u{185E}', '\u{185F}', '\u{1860}', '\u{1861}', '\u{1862}', '\u{1863}', '\u{1864}', '\u{1865}', '\u{1866}', '\u{1867}', '\u{1868}', '\u{1869}', '\u{186A}', '\u{186B}', '\u{186C}', '\u{186D}', '\u{186E}', '\u{186F}', '\u{1870}', '\u{1871}', '\u{1872}', '\u{1873}', '\u{1874}', '\u{1875}', '\u{1876}', '\u{1877}', '\u{1880}', '\u{1881}', '\u{1882}', '\u{1883}', '\u{1884}', '\u{1885}', '\u{1886}', '\u{1887}', '\u{1888}', '\u{1889}', '\u{188A}', '\u{188B}', '\u{188C}', '\u{188D}', '\u{188E}', '\u{188F}', '\u{1890}', '\u{1891}', '\u{1892}', '\u{1893}', '\u{1894}', '\u{1895}', '\u{1896}', '\u{1897}', '\u{1898}', '\u{1899}', '\u{189A}', '\u{189B}', '\u{189C}', '\u{189D}', '\u{189E}', '\u{189F}', '\u{18A0}', '\u{18A1}', '\u{18A2}', '\u{18A3}', '\u{18A4}', '\u{18A5}', '\u{18A6}', '\u{18A7}', '\u{18A8}', '\u{18AA}', '\u{1900}', '\u{1901}', '\u{1902}', '\u{1903}', '\u{1904}', '\u{1905}', '\u{1906}', '\u{1907}', '\u{1908}', '\u{1909}', '\u{190A}', '\u{190B}', '\u{190C}', '\u{190D}', '\u{190E}', '\u{190F}', '\u{1910}', '\u{1911}', '\u{1912}', '\u{1913}', '\u{1914}', '\u{1915}', '\u{1916}', '\u{1917}', '\u{1918}', '\u{1919}', '\u{191A}', '\u{191B}', '\u{191C}', '\u{1950}', '\u{1951}', '\u{1952}', '\u{1953}', '\u{1954}', '\u{1955}', '\u{1956}', '\u{1957}', '\u{1958}', '\u{1959}', '\u{195A}', '\u{195B}', '\u{195C}', '\u{195D}', '\u{195E}', '\u{195F}', '\u{1960}', '\u{1961}', '\u{1962}', '\u{1963}', '\u{1964}', '\u{1965}', '\u{1966}', '\u{1967}', '\u{1968}', '\u{1969}', '\u{196A}', '\u{196B}', '\u{196C}', '\u{196D}', '\u{1970}', '\u{1971}', '\u{1972}', '\u{1973}', '\u{1974}', '\u{1980}', '\u{1981}', '\u{1982}', '\u{1983}', '\u{1984}', '\u{1985}', '\u{1986}', '\u{1987}', '\u{1988}', '\u{1989}', '\u{198A}', '\u{198B}', '\u{198C}', '\u{198D}', '\u{198E}', '\u{198F}', '\u{1990}', '\u{1991}', '\u{1992}', '\u{1993}', '\u{1994}', '\u{1995}', '\u{1996}', '\u{1997}', '\u{1998}', '\u{1999}', '\u{199A}', '\u{199B}', '\u{199C}', '\u{199D}', '\u{199E}', '\u{199F}', '\u{19A0}', '\u{19A1}', '\u{19A2}', '\u{19A3}', '\u{19A4}', '\u{19A5}', '\u{19A6}', '\u{19A7}', '\u{19A8}', '\u{19A9}', '\u{19C1}', '\u{19C2}', '\u{19C3}', '\u{19C4}', '\u{19C5}', '\u{19C6}', '\u{19C7}', '\u{1A00}', '\u{1A01}', '\u{1A02}', '\u{1A03}', '\u{1A04}', '\u{1A05}', '\u{1A06}', '\u{1A07}', '\u{1A08}', '\u{1A09}', '\u{1A0A}', '\u{1A0B}', '\u{1A0C}', '\u{1A0D}', '\u{1A0E}', '\u{1A0F}', '\u{1A10}', '\u{1A11}', '\u{1A12}', '\u{1A13}', '\u{1A14}', '\u{1A15}', '\u{1A16}', '\u{1B05}', '\u{1B06}', '\u{1B07}', '\u{1B08}', '\u{1B09}', '\u{1B0A}', '\u{1B0B}', '\u{1B0C}', '\u{1B0D}', '\u{1B0E}', '\u{1B0F}', '\u{1B10}', '\u{1B11}', '\u{1B12}', '\u{1B13}', '\u{1B14}', '\u{1B15}', '\u{1B16}', '\u{1B17}', '\u{1B18}', '\u{1B19}', '\u{1B1A}', '\u{1B1B}', '\u{1B1C}', '\u{1B1D}', '\u{1B1E}', '\u{1B1F}', '\u{1B20}', '\u{1B21}', '\u{1B22}', '\u{1B23}', '\u{1B24}', '\u{1B25}', '\u{1B26}', '\u{1B27}', '\u{1B28}', '\u{1B29}', '\u{1B2A}', '\u{1B2B}', '\u{1B2C}', '\u{1B2D}', '\u{1B2E}', '\u{1B2F}', '\u{1B30}', '\u{1B31}', '\u{1B32}', '\u{1B33}', '\u{1B45}', '\u{1B46}', '\u{1B47}', '\u{1B48}', '\u{1B49}', '\u{1B4A}', '\u{1B4B}', '\u{1B83}', '\u{1B84}', '\u{1B85}', '\u{1B86}', '\u{1B87}', '\u{1B88}', '\u{1B89}', '\u{1B8A}', '\u{1B8B}', '\u{1B8C}', '\u{1B8D}', '\u{1B8E}', '\u{1B8F}', '\u{1B90}', '\u{1B91}', '\u{1B92}', '\u{1B93}', '\u{1B94}', '\u{1B95}', '\u{1B96}', '\u{1B97}', '\u{1B98}', '\u{1B99}', '\u{1B9A}', '\u{1B9B}', '\u{1B9C}', '\u{1B9D}', '\u{1B9E}', '\u{1B9F}', '\u{1BA0}', '\u{1BAE}', '\u{1BAF}', '\u{1C00}', '\u{1C01}', '\u{1C02}', '\u{1C03}', '\u{1C04}', '\u{1C05}', '\u{1C06}', '\u{1C07}', '\u{1C08}', '\u{1C09}', '\u{1C0A}', '\u{1C0B}', '\u{1C0C}', '\u{1C0D}', '\u{1C0E}', '\u{1C0F}', '\u{1C10}', '\u{1C11}', '\u{1C12}', '\u{1C13}', '\u{1C14}', '\u{1C15}', '\u{1C16}', '\u{1C17}', '\u{1C18}', '\u{1C19}', '\u{1C1A}', '\u{1C1B}', '\u{1C1C}', '\u{1C1D}', '\u{1C1E}', '\u{1C1F}', '\u{1C20}', '\u{1C21}', '\u{1C22}', '\u{1C23}', '\u{1C4D}', '\u{1C4E}', '\u{1C4F}', '\u{1C5A}', '\u{1C5B}', '\u{1C5C}', '\u{1C5D}', '\u{1C5E}', '\u{1C5F}', '\u{1C60}', '\u{1C61}', '\u{1C62}', '\u{1C63}', '\u{1C64}', '\u{1C65}', '\u{1C66}', '\u{1C67}', '\u{1C68}', '\u{1C69}', '\u{1C6A}', '\u{1C6B}', '\u{1C6C}', '\u{1C6D}', '\u{1C6E}', '\u{1C6F}', '\u{1C70}', '\u{1C71}', '\u{1C72}', '\u{1C73}', '\u{1C74}', '\u{1C75}', '\u{1C76}', '\u{1C77}', '\u{2135}', '\u{2136}', '\u{2137}', '\u{2138}', '\u{2D30}', '\u{2D31}', '\u{2D32}', '\u{2D33}', '\u{2D34}', '\u{2D35}', '\u{2D36}', '\u{2D37}', '\u{2D38}', '\u{2D39}', '\u{2D3A}', '\u{2D3B}', '\u{2D3C}', '\u{2D3D}', '\u{2D3E}', '\u{2D3F}', '\u{2D40}', '\u{2D41}', '\u{2D42}', '\u{2D43}', '\u{2D44}', '\u{2D45}', '\u{2D46}', '\u{2D47}', '\u{2D48}', '\u{2D49}', '\u{2D4A}', '\u{2D4B}', '\u{2D4C}', '\u{2D4D}', '\u{2D4E}', '\u{2D4F}', '\u{2D50}', '\u{2D51}', '\u{2D52}', '\u{2D53}', '\u{2D54}', '\u{2D55}', '\u{2D56}', '\u{2D57}', '\u{2D58}', '\u{2D59}', '\u{2D5A}', '\u{2D5B}', '\u{2D5C}', '\u{2D5D}', '\u{2D5E}', '\u{2D5F}', '\u{2D60}', '\u{2D61}', '\u{2D62}', '\u{2D63}', '\u{2D64}', '\u{2D65}', '\u{2D80}', '\u{2D81}', '\u{2D82}', '\u{2D83}', '\u{2D84}', '\u{2D85}', '\u{2D86}', '\u{2D87}', '\u{2D88}', '\u{2D89}', '\u{2D8A}', '\u{2D8B}', '\u{2D8C}', '\u{2D8D}', '\u{2D8E}', '\u{2D8F}', '\u{2D90}', '\u{2D91}', '\u{2D92}', '\u{2D93}', '\u{2D94}', '\u{2D95}', '\u{2D96}', '\u{2DA0}', '\u{2DA1}', '\u{2DA2}', '\u{2DA3}', '\u{2DA4}', '\u{2DA5}', '\u{2DA6}', '\u{2DA8}', '\u{2DA9}', '\u{2DAA}', '\u{2DAB}', '\u{2DAC}', '\u{2DAD}', '\u{2DAE}', '\u{2DB0}', '\u{2DB1}', '\u{2DB2}', '\u{2DB3}', '\u{2DB4}', '\u{2DB5}', '\u{2DB6}', '\u{2DB8}', '\u{2DB9}', '\u{2DBA}', '\u{2DBB}', '\u{2DBC}', '\u{2DBD}', '\u{2DBE}', '\u{2DC0}', '\u{2DC1}', '\u{2DC2}', '\u{2DC3}', '\u{2DC4}', '\u{2DC5}', '\u{2DC6}', '\u{2DC8}', '\u{2DC9}', '\u{2DCA}', '\u{2DCB}', '\u{2DCC}', '\u{2DCD}', '\u{2DCE}', '\u{2DD0}', '\u{2DD1}', '\u{2DD2}', '\u{2DD3}', '\u{2DD4}', '\u{2DD5}', '\u{2DD6}', '\u{2DD8}', '\u{2DD9}', '\u{2DDA}', '\u{2DDB}', '\u{2DDC}', '\u{2DDD}', '\u{2DDE}', '\u{3006}', '\u{303C}', '\u{3041}', '\u{3042}', '\u{3043}', '\u{3044}', '\u{3045}', '\u{3046}', '\u{3047}', '\u{3048}', '\u{3049}', '\u{304A}', '\u{304B}', '\u{304C}', '\u{304D}', '\u{304E}', '\u{304F}', '\u{3050}', '\u{3051}', '\u{3052}', '\u{3053}', '\u{3054}', '\u{3055}', '\u{3056}', '\u{3057}', '\u{3058}', '\u{3059}', '\u{305A}', '\u{305B}', '\u{305C}', '\u{305D}', '\u{305E}', '\u{305F}', '\u{3060}', '\u{3061}', '\u{3062}', '\u{3063}', '\u{3064}', '\u{3065}', '\u{3066}', '\u{3067}', '\u{3068}', '\u{3069}', '\u{306A}', '\u{306B}', '\u{306C}', '\u{306D}', '\u{306E}', '\u{306F}', '\u{3070}', '\u{3071}', '\u{3072}', '\u{3073}', '\u{3074}', '\u{3075}', '\u{3076}', '\u{3077}', '\u{3078}', '\u{3079}', '\u{307A}', '\u{307B}', '\u{307C}', '\u{307D}', '\u{307E}', '\u{307F}', '\u{3080}', '\u{3081}', '\u{3082}', '\u{3083}', '\u{3084}', '\u{3085}', '\u{3086}', '\u{3087}', '\u{3088}', '\u{3089}', '\u{308A}', '\u{308B}', '\u{308C}', '\u{308D}', '\u{308E}', '\u{308F}', '\u{3090}', '\u{3091}', '\u{3092}', '\u{3093}', '\u{3094}', '\u{3095}', '\u{3096}', '\u{309F}', '\u{30A1}', '\u{30A2}', '\u{30A3}', '\u{30A4}', '\u{30A5}', '\u{30A6}', '\u{30A7}', '\u{30A8}', '\u{30A9}', '\u{30AA}', '\u{30AB}', '\u{30AC}', '\u{30AD}', '\u{30AE}', '\u{30AF}', '\u{30B0}', '\u{30B1}', '\u{30B2}', '\u{30B3}', '\u{30B4}', '\u{30B5}', '\u{30B6}', '\u{30B7}', '\u{30B8}', '\u{30B9}', '\u{30BA}', '\u{30BB}', '\u{30BC}', '\u{30BD}', '\u{30BE}', '\u{30BF}', '\u{30C0}', '\u{30C1}', '\u{30C2}', '\u{30C3}', '\u{30C4}', '\u{30C5}', '\u{30C6}', '\u{30C7}', '\u{30C8}', '\u{30C9}', '\u{30CA}', '\u{30CB}', '\u{30CC}', '\u{30CD}', '\u{30CE}', '\u{30CF}', '\u{30D0}', '\u{30D1}', '\u{30D2}', '\u{30D3}', '\u{30D4}', '\u{30D5}', '\u{30D6}', '\u{30D7}', '\u{30D8}', '\u{30D9}', '\u{30DA}', '\u{30DB}', '\u{30DC}', '\u{30DD}', '\u{30DE}', '\u{30DF}', '\u{30E0}', '\u{30E1}', '\u{30E2}', '\u{30E3}', '\u{30E4}', '\u{30E5}', '\u{30E6}', '\u{30E7}', '\u{30E8}', '\u{30E9}', '\u{30EA}', '\u{30EB}', '\u{30EC}', '\u{30ED}', '\u{30EE}', '\u{30EF}', '\u{30F0}', '\u{30F1}', '\u{30F2}', '\u{30F3}', '\u{30F4}', '\u{30F5}', '\u{30F6}', '\u{30F7}', '\u{30F8}', '\u{30F9}', '\u{30FA}', '\u{30FF}', '\u{3105}', '\u{3106}', '\u{3107}', '\u{3108}', '\u{3109}', '\u{310A}', '\u{310B}', '\u{310C}', '\u{310D}', '\u{310E}', '\u{310F}', '\u{3110}', '\u{3111}', '\u{3112}', '\u{3113}', '\u{3114}', '\u{3115}', '\u{3116}', '\u{3117}', '\u{3118}', '\u{3119}', '\u{311A}', '\u{311B}', '\u{311C}', '\u{311D}', '\u{311E}', '\u{311F}', '\u{3120}', '\u{3121}', '\u{3122}', '\u{3123}', '\u{3124}', '\u{3125}', '\u{3126}', '\u{3127}', '\u{3128}', '\u{3129}', '\u{312A}', '\u{312B}', '\u{312C}', '\u{312D}', '\u{3131}', '\u{3132}', '\u{3133}', '\u{3134}', '\u{3135}', '\u{3136}', '\u{3137}', '\u{3138}', '\u{3139}', '\u{313A}', '\u{313B}', '\u{313C}', '\u{313D}', '\u{313E}', '\u{313F}', '\u{3140}', '\u{3141}', '\u{3142}', '\u{3143}', '\u{3144}', '\u{3145}', '\u{3146}', '\u{3147}', '\u{3148}', '\u{3149}', '\u{314A}', '\u{314B}', '\u{314C}', '\u{314D}', '\u{314E}', '\u{314F}', '\u{3150}', '\u{3151}', '\u{3152}', '\u{3153}', '\u{3154}', '\u{3155}', '\u{3156}', '\u{3157}', '\u{3158}', '\u{3159}', '\u{315A}', '\u{315B}', '\u{315C}', '\u{315D}', '\u{315E}', '\u{315F}', '\u{3160}', '\u{3161}', '\u{3162}', '\u{3163}', '\u{3164}', '\u{3165}', '\u{3166}', '\u{3167}', '\u{3168}', '\u{3169}', '\u{316A}', '\u{316B}', '\u{316C}', '\u{316D}', '\u{316E}', '\u{316F}', '\u{3170}', '\u{3171}', '\u{3172}', '\u{3173}', '\u{3174}', '\u{3175}', '\u{3176}', '\u{3177}', '\u{3178}', '\u{3179}', '\u{317A}', '\u{317B}', '\u{317C}', '\u{317D}', '\u{317E}', '\u{317F}', '\u{3180}', '\u{3181}', '\u{3182}', '\u{3183}', '\u{3184}', '\u{3185}', '\u{3186}', '\u{3187}', '\u{3188}', '\u{3189}', '\u{318A}', '\u{318B}', '\u{318C}', '\u{318D}', '\u{318E}', '\u{31A0}', '\u{31A1}', '\u{31A2}', '\u{31A3}', '\u{31A4}', '\u{31A5}', '\u{31A6}', '\u{31A7}', '\u{31A8}', '\u{31A9}', '\u{31AA}', '\u{31AB}', '\u{31AC}', '\u{31AD}', '\u{31AE}', '\u{31AF}', '\u{31B0}', '\u{31B1}', '\u{31B2}', '\u{31B3}', '\u{31B4}', '\u{31B5}', '\u{31B6}', '\u{31B7}', '\u{31F0}', '\u{31F1}', '\u{31F2}', '\u{31F3}', '\u{31F4}', '\u{31F5}', '\u{31F6}', '\u{31F7}', '\u{31F8}', '\u{31F9}', '\u{31FA}', '\u{31FB}', '\u{31FC}', '\u{31FD}', '\u{31FE}', '\u{31FF}', '\u{3400}', '\u{4DB5}', '\u{4E00}', '\u{9FC3}', '\u{A000}', '\u{A001}', '\u{A002}', '\u{A003}', '\u{A004}', '\u{A005}', '\u{A006}', '\u{A007}', '\u{A008}', '\u{A009}', '\u{A00A}', '\u{A00B}', '\u{A00C}', '\u{A00D}', '\u{A00E}', '\u{A00F}', '\u{A010}', '\u{A011}', '\u{A012}', '\u{A013}', '\u{A014}', '\u{A016}', '\u{A017}', '\u{A018}', '\u{A019}', '\u{A01A}', '\u{A01B}', '\u{A01C}', '\u{A01D}', '\u{A01E}', '\u{A01F}', '\u{A020}', '\u{A021}', '\u{A022}', '\u{A023}', '\u{A024}', '\u{A025}', '\u{A026}', '\u{A027}', '\u{A028}', '\u{A029}', '\u{A02A}', '\u{A02B}', '\u{A02C}', '\u{A02D}', '\u{A02E}', '\u{A02F}', '\u{A030}', '\u{A031}', '\u{A032}', '\u{A033}', '\u{A034}', '\u{A035}', '\u{A036}', '\u{A037}', '\u{A038}', '\u{A039}', '\u{A03A}', '\u{A03B}', '\u{A03C}', '\u{A03D}', '\u{A03E}', '\u{A03F}', '\u{A040}', '\u{A041}', '\u{A042}', '\u{A043}', '\u{A044}', '\u{A045}', '\u{A046}', '\u{A047}', '\u{A048}', '\u{A049}', '\u{A04A}', '\u{A04B}', '\u{A04C}', '\u{A04D}', '\u{A04E}', '\u{A04F}', '\u{A050}', '\u{A051}', '\u{A052}', '\u{A053}', '\u{A054}', '\u{A055}', '\u{A056}', '\u{A057}', '\u{A058}', '\u{A059}', '\u{A05A}', '\u{A05B}', '\u{A05C}', '\u{A05D}', '\u{A05E}', '\u{A05F}', '\u{A060}', '\u{A061}', '\u{A062}', '\u{A063}', '\u{A064}', '\u{A065}', '\u{A066}', '\u{A067}', '\u{A068}', '\u{A069}', '\u{A06A}', '\u{A06B}', '\u{A06C}', '\u{A06D}', '\u{A06E}', '\u{A06F}', '\u{A070}', '\u{A071}', '\u{A072}', '\u{A073}', '\u{A074}', '\u{A075}', '\u{A076}', '\u{A077}', '\u{A078}', '\u{A079}', '\u{A07A}', '\u{A07B}', '\u{A07C}', '\u{A07D}', '\u{A07E}', '\u{A07F}', '\u{A080}', '\u{A081}', '\u{A082}', '\u{A083}', '\u{A084}', '\u{A085}', '\u{A086}', '\u{A087}', '\u{A088}', '\u{A089}', '\u{A08A}', '\u{A08B}', '\u{A08C}', '\u{A08D}', '\u{A08E}', '\u{A08F}', '\u{A090}', '\u{A091}', '\u{A092}', '\u{A093}', '\u{A094}', '\u{A095}', '\u{A096}', '\u{A097}', '\u{A098}', '\u{A099}', '\u{A09A}', '\u{A09B}', '\u{A09C}', '\u{A09D}', '\u{A09E}', '\u{A09F}', '\u{A0A0}', '\u{A0A1}', '\u{A0A2}', '\u{A0A3}', '\u{A0A4}', '\u{A0A5}', '\u{A0A6}', '\u{A0A7}', '\u{A0A8}', '\u{A0A9}', '\u{A0AA}', '\u{A0AB}', '\u{A0AC}', '\u{A0AD}', '\u{A0AE}', '\u{A0AF}', '\u{A0B0}', '\u{A0B1}', '\u{A0B2}', '\u{A0B3}', '\u{A0B4}', '\u{A0B5}', '\u{A0B6}', '\u{A0B7}', '\u{A0B8}', '\u{A0B9}', '\u{A0BA}', '\u{A0BB}', '\u{A0BC}', '\u{A0BD}', '\u{A0BE}', '\u{A0BF}', '\u{A0C0}', '\u{A0C1}', '\u{A0C2}', '\u{A0C3}', '\u{A0C4}', '\u{A0C5}', '\u{A0C6}', '\u{A0C7}', '\u{A0C8}', '\u{A0C9}', '\u{A0CA}', '\u{A0CB}', '\u{A0CC}', '\u{A0CD}', '\u{A0CE}', '\u{A0CF}', '\u{A0D0}', '\u{A0D1}', '\u{A0D2}', '\u{A0D3}', '\u{A0D4}', '\u{A0D5}', '\u{A0D6}', '\u{A0D7}', '\u{A0D8}', '\u{A0D9}', '\u{A0DA}', '\u{A0DB}', '\u{A0DC}', '\u{A0DD}', '\u{A0DE}', '\u{A0DF}', '\u{A0E0}', '\u{A0E1}', '\u{A0E2}', '\u{A0E3}', '\u{A0E4}', '\u{A0E5}', '\u{A0E6}', '\u{A0E7}', '\u{A0E8}', '\u{A0E9}', '\u{A0EA}', '\u{A0EB}', '\u{A0EC}', '\u{A0ED}', '\u{A0EE}', '\u{A0EF}', '\u{A0F0}', '\u{A0F1}', '\u{A0F2}', '\u{A0F3}', '\u{A0F4}', '\u{A0F5}', '\u{A0F6}', '\u{A0F7}', '\u{A0F8}', '\u{A0F9}', '\u{A0FA}', '\u{A0FB}', '\u{A0FC}', '\u{A0FD}', '\u{A0FE}', '\u{A0FF}', '\u{A100}', '\u{A101}', '\u{A102}', '\u{A103}', '\u{A104}', '\u{A105}', '\u{A106}', '\u{A107}', '\u{A108}', '\u{A109}', '\u{A10A}', '\u{A10B}', '\u{A10C}', '\u{A10D}', '\u{A10E}', '\u{A10F}', '\u{A110}', '\u{A111}', '\u{A112}', '\u{A113}', '\u{A114}', '\u{A115}', '\u{A116}', '\u{A117}', '\u{A118}', '\u{A119}', '\u{A11A}', '\u{A11B}', '\u{A11C}', '\u{A11D}', '\u{A11E}', '\u{A11F}', '\u{A120}', '\u{A121}', '\u{A122}', '\u{A123}', '\u{A124}', '\u{A125}', '\u{A126}', '\u{A127}', '\u{A128}', '\u{A129}', '\u{A12A}', '\u{A12B}', '\u{A12C}', '\u{A12D}', '\u{A12E}', '\u{A12F}', '\u{A130}', '\u{A131}', '\u{A132}', '\u{A133}', '\u{A134}', '\u{A135}', '\u{A136}', '\u{A137}', '\u{A138}', '\u{A139}', '\u{A13A}', '\u{A13B}', '\u{A13C}', '\u{A13D}', '\u{A13E}', '\u{A13F}', '\u{A140}', '\u{A141}', '\u{A142}', '\u{A143}', '\u{A144}', '\u{A145}', '\u{A146}', '\u{A147}', '\u{A148}', '\u{A149}', '\u{A14A}', '\u{A14B}', '\u{A14C}', '\u{A14D}', '\u{A14E}', '\u{A14F}', '\u{A150}', '\u{A151}', '\u{A152}', '\u{A153}', '\u{A154}', '\u{A155}', '\u{A156}', '\u{A157}', '\u{A158}', '\u{A159}', '\u{A15A}', '\u{A15B}', '\u{A15C}', '\u{A15D}', '\u{A15E}', '\u{A15F}', '\u{A160}', '\u{A161}', '\u{A162}', '\u{A163}', '\u{A164}', '\u{A165}', '\u{A166}', '\u{A167}', '\u{A168}', '\u{A169}', '\u{A16A}', '\u{A16B}', '\u{A16C}', '\u{A16D}', '\u{A16E}', '\u{A16F}', '\u{A170}', '\u{A171}', '\u{A172}', '\u{A173}', '\u{A174}', '\u{A175}', '\u{A176}', '\u{A177}', '\u{A178}', '\u{A179}', '\u{A17A}', '\u{A17B}', '\u{A17C}', '\u{A17D}', '\u{A17E}', '\u{A17F}', '\u{A180}', '\u{A181}', '\u{A182}', '\u{A183}', '\u{A184}', '\u{A185}', '\u{A186}', '\u{A187}', '\u{A188}', '\u{A189}', '\u{A18A}', '\u{A18B}', '\u{A18C}', '\u{A18D}', '\u{A18E}', '\u{A18F}', '\u{A190}', '\u{A191}', '\u{A192}', '\u{A193}', '\u{A194}', '\u{A195}', '\u{A196}', '\u{A197}', '\u{A198}', '\u{A199}', '\u{A19A}', '\u{A19B}', '\u{A19C}', '\u{A19D}', '\u{A19E}', '\u{A19F}', '\u{A1A0}', '\u{A1A1}', '\u{A1A2}', '\u{A1A3}', '\u{A1A4}', '\u{A1A5}', '\u{A1A6}', '\u{A1A7}', '\u{A1A8}', '\u{A1A9}', '\u{A1AA}', '\u{A1AB}', '\u{A1AC}', '\u{A1AD}', '\u{A1AE}', '\u{A1AF}')
-    }
-
-    fn is_unicode_combining_spacing_mark(self) -> bool {
-        match_char_class!(self,
-            '\u{0903}', '\u{093E}', '\u{093F}', '\u{0940}', '\u{0949}', '\u{094A}', '\u{094B}', '\u{094C}', '\u{0982}', '\u{0983}', '\u{09BE}', '\u{09BF}', '\u{09C0}', '\u{09C7}', '\u{09C8}', '\u{09CB}', '\u{09CC}', '\u{09D7}', '\u{0A03}', '\u{0A3E}', '\u{0A3F}', '\u{0A40}', '\u{0A83}', '\u{0ABE}', '\u{0ABF}', '\u{0AC0}', '\u{0AC9}', '\u{0ACB}', '\u{0ACC}', '\u{0B02}', '\u{0B03}', '\u{0B3E}', '\u{0B40}', '\u{0B47}', '\u{0B48}', '\u{0B4B}', '\u{0B4C}', '\u{0B57}', '\u{0BBE}', '\u{0BBF}', '\u{0BC1}', '\u{0BC2}', '\u{0BC6}', '\u{0BC7}', '\u{0BC8}', '\u{0BCA}', '\u{0BCB}', '\u{0BCC}', '\u{0BD7}', '\u{0C01}', '\u{0C02}', '\u{0C03}', '\u{0C41}', '\u{0C42}', '\u{0C43}', '\u{0C44}', '\u{0C82}', '\u{0C83}', '\u{0CBE}', '\u{0CC0}', '\u{0CC1}', '\u{0CC2}', '\u{0CC3}', '\u{0CC4}', '\u{0CC7}', '\u{0CC8}', '\u{0CCA}', '\u{0CCB}', '\u{0CD5}', '\u{0CD6}', '\u{0D02}', '\u{0D03}', '\u{0D3E}', '\u{0D3F}', '\u{0D40}', '\u{0D46}', '\u{0D47}', '\u{0D48}', '\u{0D4A}', '\u{0D4B}', '\u{0D4C}', '\u{0D57}', '\u{0D82}', '\u{0D83}', '\u{0DCF}', '\u{0DD0}', '\u{0DD1}', '\u{0DD8}', '\u{0DD9}', '\u{0DDA}', '\u{0DDB}', '\u{0DDC}', '\u{0DDD}', '\u{0DDE}', '\u{0DDF}', '\u{0DF2}', '\u{0DF3}', '\u{0F3E}', '\u{0F3F}', '\u{0F7F}', '\u{102B}', '\u{102C}', '\u{1031}', '\u{1038}', '\u{103B}', '\u{103C}', '\u{1056}', '\u{1057}', '\u{1062}', '\u{1063}', '\u{1064}', '\u{1067}', '\u{1068}', '\u{1069}', '\u{106A}', '\u{106B}', '\u{106C}', '\u{106D}', '\u{1083}', '\u{1084}', '\u{1087}', '\u{1088}', '\u{1089}', '\u{108A}', '\u{108B}', '\u{108C}', '\u{108F}', '\u{17B6}', '\u{17BE}', '\u{17BF}', '\u{17C0}', '\u{17C1}', '\u{17C2}', '\u{17C3}', '\u{17C4}', '\u{17C5}', '\u{17C7}', '\u{17C8}', '\u{1923}', '\u{1924}', '\u{1925}', '\u{1926}', '\u{1929}', '\u{192A}', '\u{192B}', '\u{1930}', '\u{1931}', '\u{1933}', '\u{1934}', '\u{1935}', '\u{1936}', '\u{1937}', '\u{1938}', '\u{19B0}', '\u{19B1}', '\u{19B2}', '\u{19B3}', '\u{19B4}', '\u{19B5}', '\u{19B6}', '\u{19B7}', '\u{19B8}', '\u{19B9}', '\u{19BA}', '\u{19BB}', '\u{19BC}', '\u{19BD}', '\u{19BE}', '\u{19BF}', '\u{19C0}', '\u{19C8}', '\u{19C9}', '\u{1A19}', '\u{1A1A}', '\u{1A1B}', '\u{1B04}', '\u{1B35}', '\u{1B3B}', '\u{1B3D}', '\u{1B3E}', '\u{1B3F}', '\u{1B40}', '\u{1B41}', '\u{1B43}', '\u{1B44}', '\u{1B82}', '\u{1BA1}', '\u{1BA6}', '\u{1BA7}', '\u{1BAA}', '\u{1C24}', '\u{1C25}', '\u{1C26}', '\u{1C27}', '\u{1C28}', '\u{1C29}', '\u{1C2A}', '\u{1C2B}', '\u{1C34}', '\u{1C35}', '\u{A823}', '\u{A824}', '\u{A827}', '\u{A880}', '\u{A881}', '\u{A8B4}', '\u{A8B5}', '\u{A8B6}', '\u{A8B7}', '\u{A8B8}', '\u{A8B9}', '\u{A8BA}', '\u{A8BB}', '\u{A8BC}', '\u{A8BD}', '\u{A8BE}', '\u{A8BF}', '\u{A8C0}', '\u{A8C1}', '\u{A8C2}', '\u{A8C3}', '\u{A952}', '\u{A953}', '\u{AA2F}', '\u{AA30}', '\u{AA33}', '\u{AA34}', '\u{AA4D}')
-    }
-
-    fn is_unicode_decimal_number(self) -> bool {
-        match_char_class!(self,
-            '\u{0030}', '\u{0031}', '\u{0032}', '\u{0033}', '\u{0034}', '\u{0035}', '\u{0036}', '\u{0037}', '\u{0038}', '\u{0039}', '\u{0660}', '\u{0661}', '\u{0662}', '\u{0663}', '\u{0664}', '\u{0665}', '\u{0666}', '\u{0667}', '\u{0668}', '\u{0669}', '\u{06F0}', '\u{06F1}', '\u{06F2}', '\u{06F3}', '\u{06F4}', '\u{06F5}', '\u{06F6}', '\u{06F7}', '\u{06F8}', '\u{06F9}', '\u{07C0}', '\u{07C1}', '\u{07C2}', '\u{07C3}', '\u{07C4}', '\u{07C5}', '\u{07C6}', '\u{07C7}', '\u{07C8}', '\u{07C9}', '\u{0966}', '\u{0967}', '\u{0968}', '\u{0969}', '\u{096A}', '\u{096B}', '\u{096C}', '\u{096D}', '\u{096E}', '\u{096F}', '\u{09E6}', '\u{09E7}', '\u{09E8}', '\u{09E9}', '\u{09EA}', '\u{09EB}', '\u{09EC}', '\u{09ED}', '\u{09EE}', '\u{09EF}', '\u{0A66}', '\u{0A67}', '\u{0A68}', '\u{0A69}', '\u{0A6A}', '\u{0A6B}', '\u{0A6C}', '\u{0A6D}', '\u{0A6E}', '\u{0A6F}', '\u{0AE6}', '\u{0AE7}', '\u{0AE8}', '\u{0AE9}', '\u{0AEA}', '\u{0AEB}', '\u{0AEC}', '\u{0AED}', '\u{0AEE}', '\u{0AEF}', '\u{0B66}', '\u{0B67}', '\u{0B68}', '\u{0B69}', '\u{0B6A}', '\u{0B6B}', '\u{0B6C}', '\u{0B6D}', '\u{0B6E}', '\u{0B6F}', '\u{0BE6}', '\u{0BE7}', '\u{0BE8}', '\u{0BE9}', '\u{0BEA}', '\u{0BEB}', '\u{0BEC}', '\u{0BED}', '\u{0BEE}', '\u{0BEF}', '\u{0C66}', '\u{0C67}', '\u{0C68}', '\u{0C69}', '\u{0C6A}', '\u{0C6B}', '\u{0C6C}', '\u{0C6D}', '\u{0C6E}', '\u{0C6F}', '\u{0CE6}', '\u{0CE7}', '\u{0CE8}', '\u{0CE9}', '\u{0CEA}', '\u{0CEB}', '\u{0CEC}', '\u{0CED}', '\u{0CEE}', '\u{0CEF}', '\u{0D66}', '\u{0D67}', '\u{0D68}', '\u{0D69}', '\u{0D6A}', '\u{0D6B}', '\u{0D6C}', '\u{0D6D}', '\u{0D6E}', '\u{0D6F}', '\u{0E50}', '\u{0E51}', '\u{0E52}', '\u{0E53}', '\u{0E54}', '\u{0E55}', '\u{0E56}', '\u{0E57}', '\u{0E58}', '\u{0E59}', '\u{0ED0}', '\u{0ED1}', '\u{0ED2}', '\u{0ED3}', '\u{0ED4}', '\u{0ED5}', '\u{0ED6}', '\u{0ED7}', '\u{0ED8}', '\u{0ED9}', '\u{0F20}', '\u{0F21}', '\u{0F22}', '\u{0F23}', '\u{0F24}', '\u{0F25}', '\u{0F26}', '\u{0F27}', '\u{0F28}', '\u{0F29}', '\u{1040}', '\u{1041}', '\u{1042}', '\u{1043}', '\u{1044}', '\u{1045}', '\u{1046}', '\u{1047}', '\u{1048}', '\u{1049}', '\u{1090}', '\u{1091}', '\u{1092}', '\u{1093}', '\u{1094}', '\u{1095}', '\u{1096}', '\u{1097}', '\u{1098}', '\u{1099}', '\u{17E0}', '\u{17E1}', '\u{17E2}', '\u{17E3}', '\u{17E4}', '\u{17E5}', '\u{17E6}', '\u{17E7}', '\u{17E8}', '\u{17E9}', '\u{1810}', '\u{1811}', '\u{1812}', '\u{1813}', '\u{1814}', '\u{1815}', '\u{1816}', '\u{1817}', '\u{1818}', '\u{1819}', '\u{1946}', '\u{1947}', '\u{1948}', '\u{1949}', '\u{194A}', '\u{194B}', '\u{194C}', '\u{194D}', '\u{194E}', '\u{194F}', '\u{19D0}', '\u{19D1}', '\u{19D2}', '\u{19D3}', '\u{19D4}', '\u{19D5}', '\u{19D6}', '\u{19D7}', '\u{19D8}', '\u{19D9}', '\u{1B50}', '\u{1B51}', '\u{1B52}', '\u{1B53}', '\u{1B54}', '\u{1B55}', '\u{1B56}', '\u{1B57}', '\u{1B58}', '\u{1B59}', '\u{1BB0}', '\u{1BB1}', '\u{1BB2}', '\u{1BB3}', '\u{1BB4}', '\u{1BB5}', '\u{1BB6}', '\u{1BB7}', '\u{1BB8}', '\u{1BB9}', '\u{1C40}', '\u{1C41}', '\u{1C42}', '\u{1C43}', '\u{1C44}', '\u{1C45}', '\u{1C46}', '\u{1C47}', '\u{1C48}', '\u{1C49}', '\u{1C50}', '\u{1C51}', '\u{1C52}', '\u{1C53}', '\u{1C54}', '\u{1C55}', '\u{1C56}', '\u{1C57}', '\u{1C58}', '\u{1C59}', '\u{A620}', '\u{A621}', '\u{A622}', '\u{A623}', '\u{A624}', '\u{A625}', '\u{A626}', '\u{A627}', '\u{A628}', '\u{A629}', '\u{A8D0}', '\u{A8D1}', '\u{A8D2}', '\u{A8D3}', '\u{A8D4}', '\u{A8D5}', '\u{A8D6}', '\u{A8D7}', '\u{A8D8}', '\u{A8D9}', '\u{A900}', '\u{A901}', '\u{A902}', '\u{A903}', '\u{A904}', '\u{A905}', '\u{A906}', '\u{A907}', '\u{A908}', '\u{A909}', '\u{AA50}', '\u{AA51}', '\u{AA52}', '\u{AA53}', '\u{AA54}', '\u{AA55}', '\u{AA56}', '\u{AA57}', '\u{AA58}', '\u{AA59}', '\u{FF10}', '\u{FF11}', '\u{FF12}', '\u{FF13}', '\u{FF14}', '\u{FF15}', '\u{FF16}', '\u{FF17}', '\u{FF18}', '\u{FF19}')
-    }
-
-    fn is_unicode_connector_punctiation(self) -> bool {
-        match_char_class!(self,
-            '\u{005F}', '\u{203F}', '\u{2040}', '\u{2054}', '\u{FE33}', '\u{FE34}', '\u{FE4D}', '\u{FE4E}', '\u{FE4F}', '\u{FF3F}')
-    }
-
-    fn is_unicode_space_separator(self) -> bool {
-        match_char_class!(self,
-            '\u{0020}', '\u{00A0}', '\u{1680}', '\u{2000}', '\u{2001}', '\u{2002}', '\u{2003}', '\u{2004}', '\u{2005}', '\u{2006}', '\u{2007}', '\u{2008}', '\u{2009}', '\u{200A}', '\u{202F}', '\u{205F}', '\u{3000}')
-    }
-
-    fn is_es_identifier_start(self) -> bool {
-        match self {
-            '$' | '_' | '\\' => true,
-            c if c.is_unicode_letter() => true,
-            _ => false
-        }
-    }
-
-    // see section 7.6
-    fn is_es_identifier_part(self) -> bool {
-        match self {
-            '\u{200C}' | '\u{200D}' => true,
-            c if c.is_es_identifier_start() => true,
-            c if c.is_unicode_combining_spacing_mark() => true,
-            c if c.is_unicode_nonspacing_mark() => true,
-            c if c.is_unicode_decimal_number() => true,
-            c if c.is_unicode_connector_punctiation() => true,
-            _ => false
-        }
-    }
-
-    fn is_es_whitespace(self) -> bool {
-        match self {
-            '\t' | '\u{000B}' | '\u{000C}' | '\u{0020}' | '\u{00A0}' | '\u{FEFF}' => true,
-            c => c.is_unicode_space_separator()
-        }
-    }
-
-    fn is_es_line_terminator(self) -> bool {
-        match self {
-            '\n' | '\r' | '\u{2028}' | '\u{2029}' => true,
-            _ => false
-        }
-    }
-}
-
-fn main() {
-
-}
index e9d934332f171f6402a5f296c5bc780903aef40a..7808cbf8aa10840644bb7e85e8c9a81045adb8fc 100644 (file)
@@ -1,8 +1,8 @@
-error[E0599]: no function or associated item named `new_undirected` found for struct `issue_30123_aux::Graph<i32, i32>` in the current scope
+error[E0599]: no function or associated item named `new_undirected` found for struct `Graph<i32, i32>` in the current scope
   --> $DIR/issue-30123.rs:7:33
    |
 LL |     let ug = Graph::<i32, i32>::new_undirected();
-   |                                 ^^^^^^^^^^^^^^ function or associated item not found in `issue_30123_aux::Graph<i32, i32>`
+   |                                 ^^^^^^^^^^^^^^ function or associated item not found in `Graph<i32, i32>`
    |
    = note: the function or associated item was found for
            - `issue_30123_aux::Graph<N, E, Undirected>`
index a4c455ca1927e3fc225c5b09bf56dd344b46511c..2b142f688ecb9dcc8b844d6840767393999bc579 100644 (file)
@@ -9,9 +9,6 @@ LL | |     });
    |
 note: associated function defined here
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn fold<B, F>(mut self, init: B, mut f: F) -> B
-   |        ^^^^
 help: provide the argument
    |
 LL ~     needlesArr.iter().fold(|x, y| {
index 04efa27189b746e533439c6548818dc7d1e4b17d..f678df5b42b60d927cf4386889a745d7a553e73a 100644 (file)
@@ -4,12 +4,11 @@ pub fn get_tok(it: &mut IntoIter<u8>) {
     let mut found_e = false;
 
     let temp: Vec<u8> = it
-        //~^ ERROR to be an iterator that yields `&_`, but it yields `u8`
         .take_while(|&x| {
             found_e = true;
             false
         })
-        .cloned()
+        .cloned() //~ ERROR to be an iterator that yields `&_`, but it yields `u8`
         .collect(); //~ ERROR the method
 }
 
index e3334eef3ad7f6c5e9bfd11af0f66495fc54a059..f3be99f9bcb4b3e09efcd9029b355d188c5ba5ec 100644 (file)
@@ -1,46 +1,43 @@
-error[E0271]: expected `TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>` to be an iterator that yields `&_`, but it yields `u8`
-  --> $DIR/issue-31173.rs:6:25
+error[E0271]: expected `TakeWhile<&mut IntoIter<u8>, [closure@issue-31173.rs:7:21]>` to be an iterator that yields `&_`, but it yields `u8`
+  --> $DIR/issue-31173.rs:11:10
    |
-LL |       let temp: Vec<u8> = it
-   |  _________________________^
-LL | |
-LL | |         .take_while(|&x| {
-LL | |             found_e = true;
-LL | |             false
-LL | |         })
-   | |__________^ expected reference, found `u8`
-LL |           .cloned()
-   |            ------ required by a bound introduced by this call
+LL |         .cloned()
+   |          ^^^^^^ expected reference, found `u8`
    |
    = note: expected reference `&_`
                    found type `u8`
+note: the method call chain might not have had the expected associated types
+  --> $DIR/issue-31173.rs:3:20
+   |
+LL |   pub fn get_tok(it: &mut IntoIter<u8>) {
+   |                      ^^^^^^^^^^^^^^^^^ `Iterator::Item` is `u8` here
+...
+LL |           .take_while(|&x| {
+   |  __________-
+LL | |             found_e = true;
+LL | |             false
+LL | |         })
+   | |__________- `Iterator::Item` remains `u8` here
 note: required by a bound in `cloned`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         Self: Sized + Iterator<Item = &'a T>,
-   |                                ^^^^^^^^^^^^ required by this bound in `cloned`
 
-error[E0599]: the method `collect` exists for struct `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>`, but its trait bounds were not satisfied
-  --> $DIR/issue-31173.rs:13:10
+error[E0599]: the method `collect` exists for struct `Cloned<TakeWhile<&mut IntoIter<u8>, [closure@issue-31173.rs:7:21]>>`, but its trait bounds were not satisfied
+  --> $DIR/issue-31173.rs:12:10
    |
 LL |         .collect();
-   |          ^^^^^^^ method cannot be called on `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>` due to unsatisfied trait bounds
-   |
-  ::: $SRC_DIR/core/src/iter/adapters/take_while.rs:LL:COL
-   |
-LL | pub struct TakeWhile<I, P> {
-   | -------------------------- doesn't satisfy `<_ as Iterator>::Item = &_`
+   |          ^^^^^^^ method cannot be called due to unsatisfied trait bounds
+  --> $SRC_DIR/core/src/iter/adapters/take_while.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/iter/adapters/cloned.rs:LL:COL
+   = note: doesn't satisfy `<_ as Iterator>::Item = &_`
+  --> $SRC_DIR/core/src/iter/adapters/cloned.rs:LL:COL
    |
-LL | pub struct Cloned<I> {
-   | -------------------- doesn't satisfy `_: Iterator`
+   = note: doesn't satisfy `_: Iterator`
    |
    = note: the following trait bounds were not satisfied:
-           `<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]> as Iterator>::Item = &_`
-           which is required by `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>: Iterator`
-           `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>: Iterator`
-           which is required by `&mut Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>: Iterator`
+           `<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]> as Iterator>::Item = &_`
+           which is required by `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>: Iterator`
+           `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>: Iterator`
+           which is required by `&mut Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>: Iterator`
 
 error: aborting due to 2 previous errors
 
index 5a758c7002b92b6a54deb76a08a8fed43667611a..b8362499b2d0aae7aa06c2c96410d6a8e130450b 100644 (file)
@@ -6,11 +6,9 @@ LL |         #[derive_Clone]
 ...
 LL | foo!();
    | ------ in this macro invocation
+  --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-   |
-LL |     pub macro derive_const($item:item) {
-   |     ---------------------- similarly named attribute macro `derive_const` defined here
+   = note: similarly named attribute macro `derive_const` defined here
    |
    = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
 
@@ -19,11 +17,9 @@ error: cannot find attribute `derive_Clone` in this scope
    |
 LL |     #[derive_Clone]
    |       ^^^^^^^^^^^^ help: an attribute macro with a similar name exists: `derive_const`
+  --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-   |
-LL |     pub macro derive_const($item:item) {
-   |     ---------------------- similarly named attribute macro `derive_const` defined here
+   = note: similarly named attribute macro `derive_const` defined here
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-33575.rs b/src/test/ui/issues/issue-33575.rs
deleted file mode 100644 (file)
index de544af..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-fn main() {
-    let baz = ().foo(); //~ ERROR no method named `foo` found
-    <i32 as std::str::FromStr>::from_str(&baz); // No complaints about `str` being unsized
-}
diff --git a/src/test/ui/issues/issue-33575.stderr b/src/test/ui/issues/issue-33575.stderr
deleted file mode 100644 (file)
index bbd8042..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0599]: no method named `foo` found for unit type `()` in the current scope
-  --> $DIR/issue-33575.rs:2:18
-   |
-LL |     let baz = ().foo();
-   |                  ^^^ method not found in `()`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0599`.
index 8430e85df871514f1269f49b6c7b9bccfe2b6efa..e3b6dcf55a7448296ea39c39de2c428b40e59ff2 100644 (file)
@@ -3,7 +3,7 @@
 use std::collections::HashMap;
 
 fn main() {
-    for _ in HashMap::new().iter().cloned() {} //~ ERROR expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
-    //~^ ERROR expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
-    //~| ERROR expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
+    for _ in HashMap::new().iter().cloned() {} //~ ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
+    //~^ ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
+    //~| ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
 }
index 691b8f88f4ed54c87d6e65b5f9c1614d81e73a34..668eaabca4c463d450fbe59ed71e04280dd0c1e4 100644 (file)
@@ -1,20 +1,22 @@
-error[E0271]: expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
-  --> $DIR/issue-33941.rs:6:14
+error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
+  --> $DIR/issue-33941.rs:6:36
    |
 LL |     for _ in HashMap::new().iter().cloned() {}
-   |              ^^^^^^^^^^^^^^^^^^^^^ ------ required by a bound introduced by this call
-   |              |
-   |              expected reference, found tuple
+   |                                    ^^^^^^ expected reference, found tuple
    |
    = note: expected reference `&_`
                   found tuple `(&_, &_)`
+note: the method call chain might not have had the expected associated types
+  --> $DIR/issue-33941.rs:6:29
+   |
+LL |     for _ in HashMap::new().iter().cloned() {}
+   |              -------------- ^^^^^^ `Iterator::Item` is `(&_, &_)` here
+   |              |
+   |              this expression has type `HashMap<_, _>`
 note: required by a bound in `cloned`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         Self: Sized + Iterator<Item = &'a T>,
-   |                                ^^^^^^^^^^^^ required by this bound in `cloned`
 
-error[E0271]: expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
+error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
   --> $DIR/issue-33941.rs:6:14
    |
 LL |     for _ in HashMap::new().iter().cloned() {}
@@ -25,7 +27,7 @@ LL |     for _ in HashMap::new().iter().cloned() {}
    = note: required for `Cloned<std::collections::hash_map::Iter<'_, _, _>>` to implement `Iterator`
    = note: required for `Cloned<std::collections::hash_map::Iter<'_, _, _>>` to implement `IntoIterator`
 
-error[E0271]: expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
+error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
   --> $DIR/issue-33941.rs:6:14
    |
 LL |     for _ in HashMap::new().iter().cloned() {}
index 72082f0cd17287650dbb42d4a341c419ab782df0..9d2c315e4dbca92721686334dc03c64e4135aa47 100644 (file)
@@ -13,20 +13,25 @@ LL |     let sr: Vec<(u32, _, _)> = vec![];
    |                            +
 
 error[E0277]: a value of type `Vec<(u32, _, _)>` cannot be built from an iterator over elements of type `()`
-  --> $DIR/issue-34334.rs:5:33
+  --> $DIR/issue-34334.rs:5:87
    |
 LL |     let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
-   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
-   |                                 |
-   |                                 value of type `Vec<(u32, _, _)>` cannot be built from `std::iter::Iterator<Item=()>`
+   |                                                                                       ^^^^^^^ value of type `Vec<(u32, _, _)>` cannot be built from `std::iter::Iterator<Item=()>`
    |
    = help: the trait `FromIterator<()>` is not implemented for `Vec<(u32, _, _)>`
    = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+note: the method call chain might not have had the expected associated types
+  --> $DIR/issue-34334.rs:5:43
+   |
+LL |     let sr: Vec<(u32, _, _) = vec![];
+   |                               ------ this expression has type `Vec<(_, _, _)>`
+...
+LL |     let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
+   |                                    ------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Iterator::Item` changed to `()` here
+   |                                    |
+   |                                    `Iterator::Item` is `&(_, _, _)` here
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
 
 error: aborting due to 2 previous errors
 
index 045819061c1b044e196240b28e544f1eb0e86c1d..f2bf22227dbe47d787a16de1b781b7fd74927122 100644 (file)
@@ -13,7 +13,7 @@ LL |         };
 LL |         x.zero()
    |         ^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `x`
+note: `Foo::zero` takes ownership of the receiver `self`, which moves `x`
   --> $DIR/issue-34721.rs:4:13
    |
 LL |     fn zero(self) -> Self;
diff --git a/src/test/ui/issues/issue-37515.rs b/src/test/ui/issues/issue-37515.rs
deleted file mode 100644 (file)
index b3a870d..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// check-pass
-
-#![warn(unused)]
-
-type Z = dyn for<'x> Send;
-//~^ WARN type alias `Z` is never used
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-37515.stderr b/src/test/ui/issues/issue-37515.stderr
deleted file mode 100644 (file)
index f1e83ca..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-warning: type alias `Z` is never used
-  --> $DIR/issue-37515.rs:5:6
-   |
-LL | type Z = dyn for<'x> Send;
-   |      ^
-   |
-note: the lint level is defined here
-  --> $DIR/issue-37515.rs:3:9
-   |
-LL | #![warn(unused)]
-   |         ^^^^^^
-   = note: `#[warn(dead_code)]` implied by `#[warn(unused)]`
-
-warning: 1 warning emitted
-
diff --git a/src/test/ui/issues/issue-38404.rs b/src/test/ui/issues/issue-38404.rs
deleted file mode 100644 (file)
index 1a92acc..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-trait A<T>: std::ops::Add<Self> + Sized {}
-trait B<T>: A<T> {}
-trait C<T>: A<dyn B<T, Output=usize>> {}
-//~^ ERROR the trait `B` cannot be made into an object
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-38404.stderr b/src/test/ui/issues/issue-38404.stderr
deleted file mode 100644 (file)
index d7721d7..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0038]: the trait `B` cannot be made into an object
-  --> $DIR/issue-38404.rs:3:15
-   |
-LL | trait C<T>: A<dyn B<T, Output=usize>> {}
-   |               ^^^^^^^^^^^^^^^^^^^^^^ `B` cannot be made into an object
-   |
-note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-  --> $DIR/issue-38404.rs:1:13
-   |
-LL | trait A<T>: std::ops::Add<Self> + Sized {}
-   |             ^^^^^^^^^^^^^^^^^^^ ...because it uses `Self` as a type parameter
-LL | trait B<T>: A<T> {}
-   |       - this trait cannot be made into an object...
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0038`.
index 23090c1ed7866ce448e5f19427d7009be18f6d97..4d505784b86548137db79c04bdb22298b3f03433 100644 (file)
@@ -12,9 +12,6 @@ LL |     let a = std::sys::imp::process::process_common::StdioPipes { ..panic!()
    |
 note: the module `sys` is defined here
   --> $SRC_DIR/std/src/lib.rs:LL:COL
-   |
-LL | mod sys;
-   | ^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-39616.rs b/src/test/ui/issues/issue-39616.rs
deleted file mode 100644 (file)
index 46b5aa3..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-fn foo(a: [0; 1]) {} //~ ERROR expected type, found `0`
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-39616.stderr b/src/test/ui/issues/issue-39616.stderr
deleted file mode 100644 (file)
index 393d1f2..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: expected type, found `0`
-  --> $DIR/issue-39616.rs:1:12
-   |
-LL | fn foo(a: [0; 1]) {}
-   |            ^ expected type
-
-error: aborting due to previous error
-
index 0a5a6b80e9b23999993a8b464a33c0c2fa27958f..e15eed6561234e91db2f6e3ab7133a630db45881 100644 (file)
@@ -2,10 +2,12 @@ error[E0507]: cannot move out of index of `Vec<String>`
   --> $DIR/issue-40402-1.rs:9:13
    |
 LL |     let e = f.v[0];
-   |             ^^^^^^
-   |             |
-   |             move occurs because value has type `String`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&f.v[0]`
+   |             ^^^^^^ move occurs because value has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     let e = &f.v[0];
+   |             +
 
 error: aborting due to previous error
 
index b6049f967ff406060e00cf45c3ecd80395178d61..1bc554efb5c3d5bfacf56e398ee2fc2a072a749d 100644 (file)
@@ -2,12 +2,16 @@ error[E0507]: cannot move out of index of `Vec<(String, String)>`
   --> $DIR/issue-40402-2.rs:5:18
    |
 LL |     let (a, b) = x[0];
-   |          -  -    ^^^^ help: consider borrowing here: `&x[0]`
+   |          -  -    ^^^^
    |          |  |
    |          |  ...and here
    |          data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider borrowing here
+   |
+LL |     let (a, b) = &x[0];
+   |                  +
 
 error: aborting due to previous error
 
index fd694df30457ec11998188b8c0d61946cfaab133..00c375f8d2acfaad1da084e0f1b1e5a43c87b9e3 100644 (file)
@@ -5,7 +5,7 @@ LL | pub struct Iterate<T, F> {
    | ------------------------ method `iter` not found for this struct
 ...
 LL |     println!("{:?}", a.iter().take(10).collect::<Vec<usize>>());
-   |                        ^^^^ method not found in `Iterate<{integer}, [closure@$DIR/issue-41880.rs:26:24: 26:27]>`
+   |                        ^^^^ method not found in `Iterate<{integer}, [closure@issue-41880.rs:26:24]>`
 
 error: aborting due to previous error
 
index 6fe151622433a83050286b46287dd1d5d0b2b1b5..3ca6a2957e14b91768b6c421dc222634f5886677 100644 (file)
@@ -23,6 +23,10 @@ LL | pub fn f(_: dyn ToString) {}
    |
    = help: the trait `Sized` is not implemented for `(dyn ToString + 'static)`
    = help: unsized fn params are gated as an unstable feature
+help: you can use `impl Trait` as the argument type
+   |
+LL | pub fn f(_: impl ToString) {}
+   |             ~~~~
 help: function arguments must have a statically known size, borrowed types always have a known size
    |
 LL | pub fn f(_: &dyn ToString) {}
diff --git a/src/test/ui/issues/issue-42954.fixed b/src/test/ui/issues/issue-42954.fixed
deleted file mode 100644 (file)
index a73054c..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// run-rustfix
-
-#![allow(unused_must_use, unused_comparisons)]
-
-macro_rules! is_plainly_printable {
-    ($i: ident) => {
-        ($i as u32) < 0 //~ `<` is interpreted as a start of generic arguments
-    };
-}
-
-fn main() {
-    let c = 'a';
-    is_plainly_printable!(c);
-}
diff --git a/src/test/ui/issues/issue-42954.rs b/src/test/ui/issues/issue-42954.rs
deleted file mode 100644 (file)
index 5f9b0e3..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// run-rustfix
-
-#![allow(unused_must_use, unused_comparisons)]
-
-macro_rules! is_plainly_printable {
-    ($i: ident) => {
-        $i as u32 < 0 //~ `<` is interpreted as a start of generic arguments
-    };
-}
-
-fn main() {
-    let c = 'a';
-    is_plainly_printable!(c);
-}
diff --git a/src/test/ui/issues/issue-42954.stderr b/src/test/ui/issues/issue-42954.stderr
deleted file mode 100644 (file)
index 396a919..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-error: `<` is interpreted as a start of generic arguments for `u32`, not a comparison
-  --> $DIR/issue-42954.rs:7:19
-   |
-LL |         $i as u32 < 0
-   |                   ^ - interpreted as generic arguments
-   |                   |
-   |                   not interpreted as comparison
-...
-LL |     is_plainly_printable!(c);
-   |     ------------------------ in this macro invocation
-   |
-   = note: this error originates in the macro `is_plainly_printable` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: try comparing the cast value
-   |
-LL |         ($i as u32) < 0
-   |         +         +
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-46845.rs b/src/test/ui/issues/issue-46845.rs
deleted file mode 100644 (file)
index fc85b25..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-// run-pass
-// To work around #46855
-// compile-flags: -Z mir-opt-level=0
-// Regression test for the inhabitedness of unions with uninhabited variants, issue #46845
-
-use std::mem;
-
-#[derive(Copy, Clone)]
-enum Never { }
-
-// A single uninhabited variant shouldn't make the whole union uninhabited.
-union Foo {
-    a: u64,
-    _b: Never
-}
-
-// If all the variants are uninhabited, however, the union should be uninhabited.
-// NOTE(#49298) the union being uninhabited shouldn't change its size.
-union Bar {
-    _a: (Never, u64),
-    _b: (u64, Never)
-}
-
-fn main() {
-    assert_eq!(mem::size_of::<Foo>(), 8);
-    // See the note on `Bar`'s definition for why this isn't `0`.
-    assert_eq!(mem::size_of::<Bar>(), 8);
-
-    let f = [Foo { a: 42 }, Foo { a: 10 }];
-    println!("{}", unsafe { f[0].a });
-    assert_eq!(unsafe { f[1].a }, 10);
-}
index 2bd24f08c1e51d0efb6cb4c272b6dc12d1e19c50..c7e9af70e64a791e6fcaa489dfbab558c203846f 100644 (file)
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/issue-47486.rs:2:10
    |
 LL |     () < std::mem::size_of::<_>();
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `usize`
+   |     --   ^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `usize`
+   |     |
+   |     expected because this is `()`
 
 error[E0282]: type annotations needed
   --> $DIR/issue-47486.rs:3:11
index 7fd36676df8c17c15d84ab81d3609bd13661f8bb..da3e62e35dc81b804a35254dfe8f9797e619606c 100644 (file)
@@ -10,9 +10,6 @@ LL |     b"".starts_with(stringify!(foo))
               found reference `&'static str`
 note: associated function defined here
   --> $SRC_DIR/core/src/slice/mod.rs:LL:COL
-   |
-LL |     pub fn starts_with(&self, needle: &[T]) -> bool
-   |            ^^^^^^^^^^^
    = note: this error originates in the macro `stringify` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-49257.rs b/src/test/ui/issues/issue-49257.rs
deleted file mode 100644 (file)
index a7fa19d..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// Test for #49257:
-// emits good diagnostics for `..` pattern fragments not in the last position.
-
-#![allow(unused)]
-
-struct Point { x: u8, y: u8 }
-
-fn main() {
-    let p = Point { x: 0, y: 0 };
-    let Point { .., y, } = p; //~ ERROR expected `}`, found `,`
-    let Point { .., y } = p; //~ ERROR expected `}`, found `,`
-    let Point { .., } = p; //~ ERROR expected `}`, found `,`
-    let Point { .. } = p;
-}
diff --git a/src/test/ui/issues/issue-49257.stderr b/src/test/ui/issues/issue-49257.stderr
deleted file mode 100644 (file)
index 846467f..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-error: expected `}`, found `,`
-  --> $DIR/issue-49257.rs:10:19
-   |
-LL |     let Point { .., y, } = p;
-   |                 --^
-   |                 | |
-   |                 | expected `}`
-   |                 `..` must be at the end and cannot have a trailing comma
-   |
-help: move the `..` to the end of the field list
-   |
-LL -     let Point { .., y, } = p;
-LL +     let Point { y, .. } = p;
-   |
-
-error: expected `}`, found `,`
-  --> $DIR/issue-49257.rs:11:19
-   |
-LL |     let Point { .., y } = p;
-   |                 --^
-   |                 | |
-   |                 | expected `}`
-   |                 `..` must be at the end and cannot have a trailing comma
-   |
-help: move the `..` to the end of the field list
-   |
-LL -     let Point { .., y } = p;
-LL +     let Point { y , .. } = p;
-   |
-
-error: expected `}`, found `,`
-  --> $DIR/issue-49257.rs:12:19
-   |
-LL |     let Point { .., } = p;
-   |                 --^
-   |                 | |
-   |                 | expected `}`
-   |                 | help: remove this comma
-   |                 `..` must be at the end and cannot have a trailing comma
-
-error: aborting due to 3 previous errors
-
diff --git a/src/test/ui/issues/issue-50480.rs b/src/test/ui/issues/issue-50480.rs
deleted file mode 100644 (file)
index 10597ca..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#[derive(Clone, Copy)]
-//~^ ERROR the trait `Copy` may not be implemented for this type
-struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
-//~^ ERROR cannot find type `NotDefined` in this scope
-//~| ERROR cannot find type `NotDefined` in this scope
-//~| ERROR cannot find type `N` in this scope
-//~| ERROR cannot find type `N` in this scope
-//~| ERROR `i32` is not an iterator
-
-#[derive(Clone, Copy)]
-//~^ ERROR the trait `Copy` may not be implemented for this type
-struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
-//~^ ERROR cannot find type `NotDefined` in this scope
-//~| ERROR cannot find type `N` in this scope
-//~| ERROR `i32` is not an iterator
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-50480.stderr b/src/test/ui/issues/issue-50480.stderr
deleted file mode 100644 (file)
index 0bb1f9a..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-error[E0412]: cannot find type `N` in this scope
-  --> $DIR/issue-50480.rs:3:12
-   |
-LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
-   |           -^ not found in this scope
-   |           |
-   |           help: you might be missing a type parameter: `<N>`
-
-error[E0412]: cannot find type `NotDefined` in this scope
-  --> $DIR/issue-50480.rs:3:15
-   |
-LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
-   |               ^^^^^^^^^^ not found in this scope
-
-error[E0412]: cannot find type `N` in this scope
-  --> $DIR/issue-50480.rs:3:12
-   |
-LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
-   |           -^ not found in this scope
-   |           |
-   |           help: you might be missing a type parameter: `<N>`
-
-error[E0412]: cannot find type `NotDefined` in this scope
-  --> $DIR/issue-50480.rs:3:15
-   |
-LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
-   |           -   ^^^^^^^^^^ not found in this scope
-   |           |
-   |           help: you might be missing a type parameter: `<NotDefined>`
-
-error[E0412]: cannot find type `N` in this scope
-  --> $DIR/issue-50480.rs:12:18
-   |
-LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
-   |            -     ^
-   |            |
-   |            similarly named type parameter `T` defined here
-   |
-help: a type parameter with a similar name exists
-   |
-LL | struct Bar<T>(T, T, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
-   |                  ~
-help: you might be missing a type parameter
-   |
-LL | struct Bar<T, N>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
-   |             +++
-
-error[E0412]: cannot find type `NotDefined` in this scope
-  --> $DIR/issue-50480.rs:12:21
-   |
-LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
-   |                     ^^^^^^^^^^ not found in this scope
-
-error[E0277]: `i32` is not an iterator
-  --> $DIR/issue-50480.rs:3:27
-   |
-LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
-   |                           ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator
-   |
-   = help: the trait `Iterator` is not implemented for `i32`
-   = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
-
-error[E0204]: the trait `Copy` may not be implemented for this type
-  --> $DIR/issue-50480.rs:1:17
-   |
-LL | #[derive(Clone, Copy)]
-   |                 ^^^^
-LL |
-LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
-   |                                                    --------  ------ this field does not implement `Copy`
-   |                                                    |
-   |                                                    this field does not implement `Copy`
-   |
-   = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error[E0277]: `i32` is not an iterator
-  --> $DIR/issue-50480.rs:12:33
-   |
-LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
-   |                                 ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator
-   |
-   = help: the trait `Iterator` is not implemented for `i32`
-   = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
-
-error[E0204]: the trait `Copy` may not be implemented for this type
-  --> $DIR/issue-50480.rs:10:17
-   |
-LL | #[derive(Clone, Copy)]
-   |                 ^^^^
-LL |
-LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
-   |                                                          --------  ------ this field does not implement `Copy`
-   |                                                          |
-   |                                                          this field does not implement `Copy`
-   |
-   = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to 10 previous errors
-
-Some errors have detailed explanations: E0204, E0277, E0412.
-For more information about an error, try `rustc --explain E0204`.
index 44ec626dea5fc7f2fc6248451a00c32d74eaf903..d8a833a86f511a7c9636baa4fb6c20a2efd29eee 100644 (file)
@@ -13,9 +13,6 @@ LL |     let _: Box<F> = Box::new(|| ());
    = help: every closure has a distinct type and so could not always match the caller-chosen type of parameter `F`
 note: associated function defined here
   --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
-   |
-LL |     pub fn new(x: T) -> Self {
-   |            ^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-51301.rs b/src/test/ui/issues/issue-51301.rs
deleted file mode 100644 (file)
index 7e0a519..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-use std::any::TypeId;
-use std::collections::HashMap;
-use std::hash::Hash;
-
-trait State {
-    type EventType;
-    fn get_type_id_of_state(&self) -> TypeId;
-}
-
-struct StateMachine<EventType: Hash + Eq> {
-    current_state: Box<dyn State<EventType = EventType>>,
-    transition_table:
-        HashMap<TypeId, HashMap<EventType, fn() -> Box<dyn State<EventType = EventType>>>>,
-}
-
-impl<EventType: Hash + Eq> StateMachine<EventType> {
-    fn inner_process_event(&mut self, event: EventType) -> Result<(), i8> {
-        let new_state_creation_function = self
-            .transition_table
-            .iter()
-            .find(|(&event_typeid, _)| event_typeid == self.current_state.get_type_id_of_state())
-            .ok_or(1)?
-            .1
-            .iter()
-            .find(|(&event_type, _)| event == event_type)
-            //~^ ERROR cannot move out of a shared reference
-            .ok_or(2)?
-            .1;
-
-        self.current_state = new_state_creation_function();
-        Ok(())
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-51301.stderr b/src/test/ui/issues/issue-51301.stderr
deleted file mode 100644 (file)
index f3decf7..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0507]: cannot move out of a shared reference
-  --> $DIR/issue-51301.rs:25:20
-   |
-LL |             .find(|(&event_type, _)| event == event_type)
-   |                    ^^----------^^^^
-   |                      |
-   |                      data moved here
-   |                      move occurs because `event_type` has type `EventType`, which does not implement the `Copy` trait
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/issues/issue-51848.rs b/src/test/ui/issues/issue-51848.rs
deleted file mode 100644 (file)
index 4792bdd..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-// In case of macro expansion, the errors should be matched using the deepest callsite in the
-// macro call stack whose span is in the current file
-
-macro_rules! macro_with_error {
-    ( ) => {
-        println!("{"); //~ ERROR invalid
-    };
-}
-
-fn foo() {
-
-}
-
-fn main() {
-    macro_with_error!();
-    //^ In case of a local macro we want the error to be matched in the macro definition, not here
-
-    println!("}"); //~ ERROR invalid
-    //^ In case of an external macro we want the error to be matched here
-}
diff --git a/src/test/ui/issues/issue-51848.stderr b/src/test/ui/issues/issue-51848.stderr
deleted file mode 100644 (file)
index c25bedf..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-error: invalid format string: expected `'}'` but string was terminated
-  --> $DIR/issue-51848.rs:6:20
-   |
-LL |         println!("{");
-   |                   -^ expected `'}'` in format string
-   |                   |
-   |                   because of this opening brace
-...
-LL |     macro_with_error!();
-   |     ------------------- in this macro invocation
-   |
-   = note: if you intended to print `{`, you can escape it using `{{`
-   = note: this error originates in the macro `macro_with_error` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: invalid format string: unmatched `}` found
-  --> $DIR/issue-51848.rs:18:15
-   |
-LL |     println!("}");
-   |               ^ unmatched `}` in format string
-   |
-   = note: if you intended to print `}`, you can escape it using `}}`
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/issues/issue-5353.rs b/src/test/ui/issues/issue-5353.rs
deleted file mode 100644 (file)
index 1d6813d..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// check-pass
-#![allow(dead_code)]
-// pretty-expanded FIXME #23616
-
-const INVALID_ENUM : u32 = 0;
-const INVALID_VALUE : u32 = 1;
-
-fn gl_err_str(err: u32) -> String
-{
-  match err
-  {
-    INVALID_ENUM => { "Invalid enum".to_string() },
-    INVALID_VALUE => { "Invalid value".to_string() },
-    _ => { "Unknown error".to_string() }
-  }
-}
-
-pub fn main() {}
index 8a20a60853a63a3e952988cb055779c786cd8fc9..ffff403e0d4656508d4dbdbf3c4e7b32f6bb749f 100644 (file)
@@ -6,6 +6,10 @@ LL |     r: dyn A + 'static
    |
    = help: the trait `Sized` is not implemented for `(dyn A + 'static)`
    = help: unsized fn params are gated as an unstable feature
+help: you can use `impl Trait` as the argument type
+   |
+LL |     r: impl A + 'static
+   |        ~~~~
 help: function arguments must have a statically known size, borrowed types always have a known size
    |
 LL |     r: &dyn A + 'static
index e5b671d7b7ab0b71bbf6e871864094dd35c6ed2a..3aaf5fb3f3e3a56ad455db915356733b45482d61 100644 (file)
@@ -9,11 +9,8 @@ LL |     for l in bad_letters {
 LL |     bad_letters.push('s');
    |     ^^^^^^^^^^^^^^^^^^^^^ value borrowed here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `bad_letters`
+note: `into_iter` takes ownership of the receiver `self`, which moves `bad_letters`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 help: consider iterating over a slice of the `Vec<char>`'s content to avoid moving into the `for` loop
    |
 LL |     for l in &bad_letters {
index ef178bbd155388f94e8b832d5c48c2a6bb65ade4..386ac794d7db32f77e643edb15d9e599a69d6cad 100644 (file)
@@ -10,11 +10,8 @@ LL |     let _closure = || orig;
    |                    |
    |                    value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `orig`
+note: `into_iter` takes ownership of the receiver `self`, which moves `orig`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 help: consider iterating over a slice of the `Vec<bool>`'s content to avoid moving into the `for` loop
    |
 LL |     for _val in &orig {}
index 2de15037650825da8c9abd1ba74b69f1ae523fc7..cec482a53baa91b3e962056d017c836247f8742a 100644 (file)
@@ -1,34 +1,39 @@
 error[E0277]: a value of type `Vec<f64>` cannot be built from an iterator over elements of type `&f64`
-  --> $DIR/issue-66923-show-error-for-correct-call.rs:8:24
+  --> $DIR/issue-66923-show-error-for-correct-call.rs:8:39
    |
 LL |     let x2: Vec<f64> = x1.into_iter().collect();
-   |                        ^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
-   |                        |
-   |                        value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
+   |                                       ^^^^^^^ value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
    |
    = help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>`
    = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+note: the method call chain might not have had the expected associated types
+  --> $DIR/issue-66923-show-error-for-correct-call.rs:8:27
+   |
+LL |     let x1: &[f64] = &v;
+   |                      -- this expression has type `&Vec<f64>`
+LL |     let x2: Vec<f64> = x1.into_iter().collect();
+   |                           ^^^^^^^^^^^ `Iterator::Item` is `&f64` here
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
 
 error[E0277]: a value of type `Vec<f64>` cannot be built from an iterator over elements of type `&f64`
-  --> $DIR/issue-66923-show-error-for-correct-call.rs:12:14
+  --> $DIR/issue-66923-show-error-for-correct-call.rs:12:29
    |
 LL |     let x3 = x1.into_iter().collect::<Vec<f64>>();
-   |              ^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
-   |              |
-   |              value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
+   |                             ^^^^^^^ value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
    |
    = help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>`
    = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+note: the method call chain might not have had the expected associated types
+  --> $DIR/issue-66923-show-error-for-correct-call.rs:12:17
+   |
+LL |     let x1: &[f64] = &v;
+   |                      -- this expression has type `&Vec<f64>`
+...
+LL |     let x3 = x1.into_iter().collect::<Vec<f64>>();
+   |                 ^^^^^^^^^^^ `Iterator::Item` is `&f64` here
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
 
 error: aborting due to 2 previous errors
 
index f1ab0ad26d7084353d96d0dd5421ce21f666fa42..c983026995b20b8b91992006de95ee9071f7d770 100644 (file)
@@ -3,11 +3,9 @@ error[E0412]: cannot find type `Fo` in this scope
    |
 LL | impl Fo {
    |      ^^ help: a trait with a similar name exists: `Fn`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   | -------------------------------------- similarly named trait `Fn` defined here
+   = note: similarly named trait `Fn` defined here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-77002.rs b/src/test/ui/issues/issue-77002.rs
deleted file mode 100644 (file)
index 0c37346..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// compile-flags: -Zmir-opt-level=3 -Copt-level=0
-// run-pass
-
-type M = [i64; 2];
-
-fn f(a: &M) -> M {
-    let mut b: M = M::default();
-    b[0] = a[0] * a[0];
-    b
-}
-
-fn main() {
-    let mut a: M = [1, 1];
-    a = f(&a);
-    assert_eq!(a[0], 1);
-}
index 767571cddbeea954c660cf9fe5f632bc0e1035be..572414df2bf9d6af0b37498610f95f9529cf0060 100644 (file)
@@ -10,11 +10,8 @@ LL |     for n in v {
 LL |     for n in v {
    |              ^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `v`
+note: `into_iter` takes ownership of the receiver `self`, which moves `v`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 help: consider creating a fresh reborrow of `v` here
    |
 LL |     for n in &mut *v {
index 4c424999b754d5e867f0e402da5b3f318b1f33f0..99d0d9bd735532bfc8a299ba1a7d9cde7a42dc0d 100644 (file)
@@ -3,5 +3,4 @@ fn main() {
     //~^ ERROR an array of type `[u32; 10]` cannot be built directly from an iterator
     //~| NOTE try collecting into a `Vec<{integer}>`, then using `.try_into()`
     //~| NOTE required by a bound in `collect`
-    //~| NOTE required by a bound introduced by this call
 }
index a23a36a88abb336dd24a54ec7ce3f41c9654ee90..e38745cc10e1f3840e1081acc2e500700d827d15 100644 (file)
@@ -1,17 +1,12 @@
 error[E0277]: an array of type `[u32; 10]` cannot be built directly from an iterator
-  --> $DIR/collect-into-array.rs:2:31
+  --> $DIR/collect-into-array.rs:2:39
    |
 LL |     let whatever: [u32; 10] = (0..10).collect();
-   |                               ^^^^^^^ ------- required by a bound introduced by this call
-   |                               |
-   |                               try collecting into a `Vec<{integer}>`, then using `.try_into()`
+   |                                       ^^^^^^^ try collecting into a `Vec<{integer}>`, then using `.try_into()`
    |
    = help: the trait `FromIterator<{integer}>` is not implemented for `[u32; 10]`
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
 
 error: aborting due to previous error
 
index 09832c260d04e82e5e64d0ccc510bf49ae6a42a6..5a8aacb1a6df0bc392290c051c300d638525cb7f 100644 (file)
@@ -13,6 +13,5 @@ fn main() {
     //~| NOTE all local variables must have a statically known size
     //~| NOTE doesn't have a size known at compile-time
     //~| NOTE doesn't have a size known at compile-time
-    //~| NOTE required by a bound introduced by this call
     process_slice(&some_generated_vec);
 }
index bc152467ce3a5c5d94d1c06ca790ec3793a38492..29fff8c51c63be7ca4ee0b096c52f1ee5d522bb5 100644 (file)
@@ -17,24 +17,16 @@ LL |     let some_generated_vec = (0..10).collect();
    = help: the trait `Sized` is not implemented for `[i32]`
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
-   |                ^ required by this bound in `collect`
 
 error[E0277]: a slice of type `[i32]` cannot be built since `[i32]` has no definite size
-  --> $DIR/collect-into-slice.rs:6:30
+  --> $DIR/collect-into-slice.rs:6:38
    |
 LL |     let some_generated_vec = (0..10).collect();
-   |                              ^^^^^^^ ------- required by a bound introduced by this call
-   |                              |
-   |                              try explicitly collecting into a `Vec<{integer}>`
+   |                                      ^^^^^^^ try explicitly collecting into a `Vec<{integer}>`
    |
    = help: the trait `FromIterator<{integer}>` is not implemented for `[i32]`
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/iterators/invalid-iterator-chain.rs b/src/test/ui/iterators/invalid-iterator-chain.rs
new file mode 100644 (file)
index 0000000..ebdf333
--- /dev/null
@@ -0,0 +1,53 @@
+use std::collections::hash_set::Iter;
+use std::collections::HashSet;
+
+fn iter_to_vec<'b, X>(i: Iter<'b, X>) -> Vec<X> {
+    let i = i.map(|x| x.clone());
+    i.collect() //~ ERROR E0277
+}
+
+fn main() {
+    let scores = vec![(0, 0)]
+        .iter()
+        .map(|(a, b)| {
+            a + b;
+        });
+    println!("{}", scores.sum::<i32>()); //~ ERROR E0277
+    println!(
+        "{}",
+        vec![0, 1]
+            .iter()
+            .map(|x| x * 2)
+            .map(|x| x as f64)
+            .map(|x| x as i64)
+            .filter(|x| *x > 0)
+            .map(|x| { x + 1 })
+            .map(|x| { x; })
+            .sum::<i32>(), //~ ERROR E0277
+    );
+    println!(
+        "{}",
+        vec![0, 1]
+            .iter()
+            .map(|x| x * 2)
+            .map(|x| x as f64)
+            .filter(|x| *x > 0.0)
+            .map(|x| { x + 1.0 })
+            .sum::<i32>(), //~ ERROR E0277
+    );
+    println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::<i32>()); //~ ERROR E0277
+    println!("{}", vec![(), ()].iter().sum::<i32>()); //~ ERROR E0277
+    let a = vec![0];
+    let b = a.into_iter();
+    let c = b.map(|x| x + 1);
+    let d = c.filter(|x| *x > 10 );
+    let e = d.map(|x| {
+        x + 1;
+    });
+    let f = e.filter(|_| false);
+    let g: Vec<i32> = f.collect(); //~ ERROR E0277
+
+    let mut s = HashSet::new();
+    s.insert(1u8);
+    println!("{:?}", iter_to_vec(s.iter()));
+}
diff --git a/src/test/ui/iterators/invalid-iterator-chain.stderr b/src/test/ui/iterators/invalid-iterator-chain.stderr
new file mode 100644 (file)
index 0000000..d76a4bf
--- /dev/null
@@ -0,0 +1,176 @@
+error[E0277]: a value of type `Vec<X>` cannot be built from an iterator over elements of type `&X`
+  --> $DIR/invalid-iterator-chain.rs:6:7
+   |
+LL |     i.collect()
+   |       ^^^^^^^ value of type `Vec<X>` cannot be built from `std::iter::Iterator<Item=&X>`
+   |
+   = help: the trait `FromIterator<&X>` is not implemented for `Vec<X>`
+   = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+note: the method call chain might not have had the expected associated types
+  --> $DIR/invalid-iterator-chain.rs:4:26
+   |
+LL | fn iter_to_vec<'b, X>(i: Iter<'b, X>) -> Vec<X> {
+   |                          ^^^^^^^^^^^ `Iterator::Item` is `&X` here
+LL |     let i = i.map(|x| x.clone());
+   |               ------------------ `Iterator::Item` remains `&X` here
+note: required by a bound in `collect`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()`
+  --> $DIR/invalid-iterator-chain.rs:15:27
+   |
+LL |     println!("{}", scores.sum::<i32>());
+   |                           ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=()>`
+   |
+   = help: the trait `Sum<()>` is not implemented for `i32`
+   = help: the following other types implement trait `Sum<A>`:
+             <i32 as Sum<&'a i32>>
+             <i32 as Sum>
+note: the method call chain might not have had the expected associated types
+  --> $DIR/invalid-iterator-chain.rs:12:10
+   |
+LL |       let scores = vec![(0, 0)]
+   |                    ------------ this expression has type `Vec<({integer}, {integer})>`
+LL |           .iter()
+   |            ------ `Iterator::Item` is `&({integer}, {integer})` here
+LL |           .map(|(a, b)| {
+   |  __________^
+LL | |             a + b;
+LL | |         });
+   | |__________^ `Iterator::Item` changed to `()` here
+note: required by a bound in `std::iter::Iterator::sum`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()`
+  --> $DIR/invalid-iterator-chain.rs:26:14
+   |
+LL |             .sum::<i32>(),
+   |              ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=()>`
+   |
+   = help: the trait `Sum<()>` is not implemented for `i32`
+   = help: the following other types implement trait `Sum<A>`:
+             <i32 as Sum<&'a i32>>
+             <i32 as Sum>
+note: the method call chain might not have had the expected associated types
+  --> $DIR/invalid-iterator-chain.rs:20:14
+   |
+LL |         vec![0, 1]
+   |         ---------- this expression has type `Vec<{integer}>`
+LL |             .iter()
+   |              ------ `Iterator::Item` is `&{integer}` here
+LL |             .map(|x| x * 2)
+   |              ^^^^^^^^^^^^^^ `Iterator::Item` changed to `{integer}` here
+LL |             .map(|x| x as f64)
+   |              ----------------- `Iterator::Item` changed to `f64` here
+LL |             .map(|x| x as i64)
+   |              ----------------- `Iterator::Item` changed to `i64` here
+LL |             .filter(|x| *x > 0)
+   |              ------------------ `Iterator::Item` remains `i64` here
+LL |             .map(|x| { x + 1 })
+   |              ------------------ `Iterator::Item` remains `i64` here
+LL |             .map(|x| { x; })
+   |              ^^^^^^^^^^^^^^^ `Iterator::Item` changed to `()` here
+note: required by a bound in `std::iter::Iterator::sum`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `f64`
+  --> $DIR/invalid-iterator-chain.rs:36:14
+   |
+LL |             .sum::<i32>(),
+   |              ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=f64>`
+   |
+   = help: the trait `Sum<f64>` is not implemented for `i32`
+   = help: the following other types implement trait `Sum<A>`:
+             <i32 as Sum<&'a i32>>
+             <i32 as Sum>
+note: the method call chain might not have had the expected associated types
+  --> $DIR/invalid-iterator-chain.rs:32:14
+   |
+LL |         vec![0, 1]
+   |         ---------- this expression has type `Vec<{integer}>`
+LL |             .iter()
+   |              ------ `Iterator::Item` is `&{integer}` here
+LL |             .map(|x| x * 2)
+   |              ^^^^^^^^^^^^^^ `Iterator::Item` changed to `{integer}` here
+LL |             .map(|x| x as f64)
+   |              ^^^^^^^^^^^^^^^^^ `Iterator::Item` changed to `f64` here
+LL |             .filter(|x| *x > 0.0)
+   |              -------------------- `Iterator::Item` remains `f64` here
+LL |             .map(|x| { x + 1.0 })
+   |              -------------------- `Iterator::Item` remains `f64` here
+note: required by a bound in `std::iter::Iterator::sum`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()`
+  --> $DIR/invalid-iterator-chain.rs:38:54
+   |
+LL |     println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::<i32>());
+   |                                                      ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=()>`
+   |
+   = help: the trait `Sum<()>` is not implemented for `i32`
+   = help: the following other types implement trait `Sum<A>`:
+             <i32 as Sum<&'a i32>>
+             <i32 as Sum>
+note: the method call chain might not have had the expected associated types
+  --> $DIR/invalid-iterator-chain.rs:38:38
+   |
+LL |     println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::<i32>());
+   |                    ---------- ------ ^^^^^^^^^^^^^^^ `Iterator::Item` changed to `()` here
+   |                    |          |
+   |                    |          `Iterator::Item` is `&{integer}` here
+   |                    this expression has type `Vec<{integer}>`
+note: required by a bound in `std::iter::Iterator::sum`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `&()`
+  --> $DIR/invalid-iterator-chain.rs:39:40
+   |
+LL |     println!("{}", vec![(), ()].iter().sum::<i32>());
+   |                                        ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=&()>`
+   |
+   = help: the trait `Sum<&()>` is not implemented for `i32`
+   = help: the following other types implement trait `Sum<A>`:
+             <i32 as Sum<&'a i32>>
+             <i32 as Sum>
+note: the method call chain might not have had the expected associated types
+  --> $DIR/invalid-iterator-chain.rs:39:33
+   |
+LL |     println!("{}", vec![(), ()].iter().sum::<i32>());
+   |                    ------------ ^^^^^^ `Iterator::Item` is `&()` here
+   |                    |
+   |                    this expression has type `Vec<()>`
+note: required by a bound in `std::iter::Iterator::sum`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error[E0277]: a value of type `Vec<i32>` cannot be built from an iterator over elements of type `()`
+  --> $DIR/invalid-iterator-chain.rs:48:25
+   |
+LL |     let g: Vec<i32> = f.collect();
+   |                         ^^^^^^^ value of type `Vec<i32>` cannot be built from `std::iter::Iterator<Item=()>`
+   |
+   = help: the trait `FromIterator<()>` is not implemented for `Vec<i32>`
+   = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+note: the method call chain might not have had the expected associated types
+  --> $DIR/invalid-iterator-chain.rs:44:15
+   |
+LL |       let a = vec![0];
+   |               ------- this expression has type `Vec<{integer}>`
+LL |       let b = a.into_iter();
+   |                 ----------- `Iterator::Item` is `{integer}` here
+LL |       let c = b.map(|x| x + 1);
+   |                 -------------- `Iterator::Item` remains `{integer}` here
+LL |       let d = c.filter(|x| *x > 10 );
+   |                 -------------------- `Iterator::Item` remains `{integer}` here
+LL |       let e = d.map(|x| {
+   |  _______________^
+LL | |         x + 1;
+LL | |     });
+   | |______^ `Iterator::Item` changed to `()` here
+LL |       let f = e.filter(|_| false);
+   |                 ----------------- `Iterator::Item` remains `()` here
+note: required by a bound in `collect`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
index afcce5c30ca021f7d53fd95ee0d52ead498b812f..a7d9c481a1a662cbceb90e4a820a47f2c96c9376 100644 (file)
@@ -3,11 +3,9 @@ error[E0599]: `Vec<bool>` is not an iterator
    |
 LL |     vec![true, false].map(|v| !v).collect::<Vec<_>>();
    |                       ^^^ `Vec<bool>` is not an iterator; try calling `.into_iter()` or `.iter()`
+  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
    |
-  ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
-   | ------------------------------------------------------------------------------------------------ doesn't satisfy `Vec<bool>: Iterator`
+   = note: doesn't satisfy `Vec<bool>: Iterator`
    |
    = note: the following trait bounds were not satisfied:
            `Vec<bool>: Iterator`
index 33f82448dd2acd87fd701c178ba088ceede166d0..0b206f31e7b6ebdd1f3c083c63eaa4bb9a947ce9 100644 (file)
@@ -1,17 +1,12 @@
 error[E0277]: a value of type `Bar` cannot be built from an iterator over elements of type `_`
-  --> $DIR/branches.rs:19:9
+  --> $DIR/branches.rs:19:28
    |
 LL |         std::iter::empty().collect()
-   |         ^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
-   |         |
-   |         value of type `Bar` cannot be built from `std::iter::Iterator<Item=_>`
+   |                            ^^^^^^^ value of type `Bar` cannot be built from `std::iter::Iterator<Item=_>`
    |
    = help: the trait `FromIterator<_>` is not implemented for `Bar`
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
 
 error: aborting due to previous error
 
index 420104e526d9b8dbb889f23550535e6ca56cf5b7..fe2631f9474205a617c9398f0cfb5709aa8875f4 100644 (file)
@@ -6,8 +6,8 @@ LL |         |s| s.len()
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |         |s: _| s.len()
-   |           +++
+LL |         |s: /* Type */| s.len()
+   |           ++++++++++++
 
 error[E0282]: type annotations needed
   --> $DIR/branches3.rs:15:10
@@ -17,8 +17,8 @@ LL |         |s| s.len()
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |         |s: _| s.len()
-   |           +++
+LL |         |s: /* Type */| s.len()
+   |           ++++++++++++
 
 error[E0282]: type annotations needed
   --> $DIR/branches3.rs:23:10
@@ -28,8 +28,8 @@ LL |         |s| s.len()
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |         |s: _| s.len()
-   |           +++
+LL |         |s: /* Type */| s.len()
+   |           ++++++++++++
 
 error[E0282]: type annotations needed
   --> $DIR/branches3.rs:30:10
@@ -39,8 +39,8 @@ LL |         |s| s.len()
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |         |s: _| s.len()
-   |           +++
+LL |         |s: /* Type */| s.len()
+   |           ++++++++++++
 
 error: aborting due to 4 previous errors
 
index 57978edf2bf0505fc9397326d8f8a3149abd874b..d8ac39a4f27a37869e5b72fab32d9d38730e42a3 100644 (file)
@@ -1,32 +1,22 @@
 error[E0277]: a value of type `Foo` cannot be built from an iterator over elements of type `_`
-  --> $DIR/recursion4.rs:10:9
+  --> $DIR/recursion4.rs:10:28
    |
 LL |     x = std::iter::empty().collect();
-   |         ^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
-   |         |
-   |         value of type `Foo` cannot be built from `std::iter::Iterator<Item=_>`
+   |                            ^^^^^^^ value of type `Foo` cannot be built from `std::iter::Iterator<Item=_>`
    |
    = help: the trait `FromIterator<_>` is not implemented for `Foo`
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
 
 error[E0277]: a value of type `impl Debug` cannot be built from an iterator over elements of type `_`
-  --> $DIR/recursion4.rs:19:9
+  --> $DIR/recursion4.rs:19:28
    |
 LL |     x = std::iter::empty().collect();
-   |         ^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
-   |         |
-   |         value of type `impl Debug` cannot be built from `std::iter::Iterator<Item=_>`
+   |                            ^^^^^^^ value of type `impl Debug` cannot be built from `std::iter::Iterator<Item=_>`
    |
    = help: the trait `FromIterator<_>` is not implemented for `impl Debug`
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
 
 error: aborting due to 2 previous errors
 
index addcd798f4ffb8f54cfa21d2345e7969138caf6b..bf78a079cdfa9fd766e270a488ae65ac63c299a0 100644 (file)
@@ -12,7 +12,7 @@ error[E0308]: mismatched types
 LL |         let Bar(z) = x;
    |             ^^^^^^   - this expression has type `&mut irrefutable::Foo`
    |             |
-   |             expected struct `irrefutable::Foo`, found struct `irrefutable::Bar`
+   |             expected struct `Foo`, found struct `Bar`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/lifetimes/conflicting-bounds.rs b/src/test/ui/lifetimes/conflicting-bounds.rs
new file mode 100644 (file)
index 0000000..f37f163
--- /dev/null
@@ -0,0 +1,11 @@
+//~ type annotations needed: cannot satisfy `Self: Gen<'source>`
+
+pub trait Gen<'source> {
+    type Output;
+
+    fn gen<T>(&self) -> T
+    where
+        Self: for<'s> Gen<'s, Output = T>;
+}
+
+fn main() {}
diff --git a/src/test/ui/lifetimes/conflicting-bounds.stderr b/src/test/ui/lifetimes/conflicting-bounds.stderr
new file mode 100644 (file)
index 0000000..42aa393
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0283]: type annotations needed: cannot satisfy `Self: Gen<'source>`
+   |
+note: multiple `impl`s or `where` clauses satisfying `Self: Gen<'source>` found
+  --> $DIR/conflicting-bounds.rs:3:1
+   |
+LL | pub trait Gen<'source> {
+   | ^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |         Self: for<'s> Gen<'s, Output = T>;
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0283`.
index 5832c4d173c10245c4574f5c47a058be2ad345eb..3d4208031cd06b9879de3326b066a2b0a81bec8a 100644 (file)
@@ -4,7 +4,16 @@ error[E0283]: type annotations needed: cannot satisfy `&'a (): Foo`
 LL |     &'a (): Foo,
    |             ^^^
    |
-   = note: cannot satisfy `&'a (): Foo`
+note: multiple `impl`s or `where` clauses satisfying `&'a (): Foo` found
+  --> $DIR/issue-34979.rs:2:1
+   |
+LL | impl<'a, T> Foo for &'a T {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     &'a (): Foo,
+   |             ^^^
+LL |     &'static (): Foo;
+   |                  ^^^
 
 error: aborting due to previous error
 
index e35f9f14c7ecc0215ffa4ad4e7092a1ed7536093..f455dcb06f79dc97aa9e3072699154a3bb8121e5 100644 (file)
@@ -1,13 +1,13 @@
 error[E0080]: values of the type `[u8; SIZE]` are too big for the current architecture
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
    |
-LL |     intrinsics::size_of::<T>()
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ inside `std::mem::size_of::<[u8; SIZE]>` at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-  ::: $DIR/issue-55878.rs:7:26
+note: inside `std::mem::size_of::<[u8; SIZE]>`
+  --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+note: inside `main`
+  --> $DIR/issue-55878.rs:7:26
    |
 LL |     println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>());
-   |                          ---------------------------------------------- inside `main` at $DIR/issue-55878.rs:7:26
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 note: erroneous constant used
   --> $DIR/issue-55878.rs:7:26
diff --git a/src/test/ui/linkage-attr/auxiliary/def_external.rs b/src/test/ui/linkage-attr/auxiliary/def_external.rs
new file mode 100644 (file)
index 0000000..2300930
--- /dev/null
@@ -0,0 +1,5 @@
+#![feature(linkage)]
+#![crate_type = "lib"]
+
+#[linkage="external"]
+pub static EXTERN: u32 = 0;
diff --git a/src/test/ui/linkage-attr/auxiliary/def_illtyped_external.rs b/src/test/ui/linkage-attr/auxiliary/def_illtyped_external.rs
deleted file mode 100644 (file)
index 2300930..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#![feature(linkage)]
-#![crate_type = "lib"]
-
-#[linkage="external"]
-pub static EXTERN: u32 = 0;
diff --git a/src/test/ui/linkage-attr/linkage-import.rs b/src/test/ui/linkage-attr/linkage-import.rs
new file mode 100644 (file)
index 0000000..f754ddc
--- /dev/null
@@ -0,0 +1,8 @@
+// build-pass
+// aux-build:def_external.rs
+
+extern crate def_external as dep;
+
+fn main() {
+    println!("{:p}", &dep::EXTERN);
+}
diff --git a/src/test/ui/linkage-attr/linkage-requires-raw-ptr.rs b/src/test/ui/linkage-attr/linkage-requires-raw-ptr.rs
deleted file mode 100644 (file)
index 93afc53..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// rust-lang/rust#59548: We used to ICE when trying to use a static
-// with a type that violated its own `#[linkage]`.
-
-// build-fail
-// aux-build:def_illtyped_external.rs
-
-extern crate def_illtyped_external as dep;
-
-fn main() {
-    println!("{:p}", &dep::EXTERN);
-}
diff --git a/src/test/ui/linkage-attr/linkage-requires-raw-ptr.stderr b/src/test/ui/linkage-attr/linkage-requires-raw-ptr.stderr
deleted file mode 100644 (file)
index 5abbe74..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: must have type `*const T` or `*mut T` due to `#[linkage]` attribute
-  --> $DIR/auxiliary/def_illtyped_external.rs:5:1
-   |
-LL | pub static EXTERN: u32 = 0;
-   | ^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
index a7be1985286a1373dcefaf3994e0d991b62403cf..aa42874f7ba8a64767d80708e2282fb1e349d88c 100644 (file)
@@ -1,16 +1,11 @@
-// FIXME https://github.com/rust-lang/rust/issues/59774
-
-// build-fail
-// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> ""
-// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> ""
-// ignore-sgx no weak linkages permitted
+// check-fail
 
 #![feature(linkage)]
 
 extern "C" {
     #[linkage = "extern_weak"]
     static foo: i32;
-//~^ ERROR: must have type `*const T` or `*mut T` due to `#[linkage]` attribute
+//~^ ERROR: invalid type for variable with `#[linkage]` attribute
 }
 
 fn main() {
index a6ac0aad077874d6b70ce71adced4dab7bad5e65..7265f711fd01643ca2020957052fadab196312d4 100644 (file)
@@ -1,8 +1,9 @@
-error: must have type `*const T` or `*mut T` due to `#[linkage]` attribute
-  --> $DIR/linkage2.rs:12:5
+error[E0791]: invalid type for variable with `#[linkage]` attribute
+  --> $DIR/linkage2.rs:7:5
    |
 LL |     static foo: i32;
    |     ^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0791`.
index 5370660d6c185ecc51db76349bce46394cd410a4..48fd4169da7c975aedc0bd24c0040d30c4d98f6c 100644 (file)
@@ -604,9 +604,6 @@ LL |         let _val: Result<i32, i32> = mem::uninitialized();
    |
 note: enums with multiple inhabited variants have to be initialized to a variant
   --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   | ^^^^^^^^^^^^^^^^^^^^^
 
 error: the type `&i32` does not permit zero-initialization
   --> $DIR/invalid_value.rs:152:34
index 9f4360e676382859b177b169a17f2f0c9f938385..747c38b800764a36a3f786d3fc76565fe3ffe0ac 100644 (file)
@@ -108,9 +108,6 @@ LL |     VEC.push(0);
    = note: the mutable reference will refer to this temporary, not the original `const` item
 note: mutable reference created due to call to this method
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL |     pub fn push(&mut self, value: T) {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: `const` item defined here
   --> $DIR/lint-const-item-mutation.rs:31:1
    |
diff --git a/src/test/ui/lint/lint-missing-copy-implementations-allow.rs b/src/test/ui/lint/lint-missing-copy-implementations-allow.rs
new file mode 100644 (file)
index 0000000..051a905
--- /dev/null
@@ -0,0 +1,35 @@
+// check-pass
+#![deny(missing_copy_implementations)]
+
+// Don't recommend implementing Copy on something stateful like an iterator.
+pub struct MyIterator {
+    num: u8,
+}
+
+impl Iterator for MyIterator {
+    type Item = u8;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        todo!()
+    }
+}
+
+pub struct Handle {
+    inner: *mut (),
+}
+
+pub struct Handle2 {
+    inner: *const (),
+}
+
+pub enum MaybeHandle {
+    Ptr(*mut ()),
+}
+
+pub union UnionHandle {
+    ptr: *mut (),
+}
+
+pub struct Array([u8; 2048]);
+
+fn main() {}
index b590fa697adb3dd17c846c0d3d554d21019fedc3..d4e88aa26436162160ff0ccc02e3b169e9b4de17 100644 (file)
@@ -20,19 +20,19 @@ fn main() {
 
     match foo::Foo::Foo {
         Foo => {}
-//~^ ERROR variable `Foo` should have a snake case name
-//~^^ WARN `Foo` is named the same as one of the variants of the type `Foo`
-//~^^^ WARN unused variable: `Foo`
+    //~^ ERROR variable `Foo` should have a snake case name
+    //~^^ WARN `Foo` is named the same as one of the variants of the type `foo::Foo`
+    //~^^^ WARN unused variable: `Foo`
     }
 
     let Foo = foo::Foo::Foo;
     //~^ ERROR variable `Foo` should have a snake case name
-    //~^^ WARN `Foo` is named the same as one of the variants of the type `Foo`
+    //~^^ WARN `Foo` is named the same as one of the variants of the type `foo::Foo`
     //~^^^ WARN unused variable: `Foo`
 
     fn in_param(Foo: foo::Foo) {}
     //~^ ERROR variable `Foo` should have a snake case name
-    //~^^ WARN `Foo` is named the same as one of the variants of the type `Foo`
+    //~^^ WARN `Foo` is named the same as one of the variants of the type `foo::Foo`
     //~^^^ WARN unused variable: `Foo`
 
     test(1);
index 71b24a835bcd9c18f41139646eaa8b8f9a5450fe..d476d856e24c59b060ccdd85be6ff1c681e4180a 100644 (file)
@@ -1,22 +1,22 @@
-warning[E0170]: pattern binding `Foo` is named the same as one of the variants of the type `Foo`
+warning[E0170]: pattern binding `Foo` is named the same as one of the variants of the type `foo::Foo`
   --> $DIR/lint-uppercase-variables.rs:22:9
    |
 LL |         Foo => {}
-   |         ^^^ help: to match on the variant, qualify the path: `Foo::Foo`
+   |         ^^^ help: to match on the variant, qualify the path: `foo::Foo::Foo`
    |
    = note: `#[warn(bindings_with_variant_name)]` on by default
 
-warning[E0170]: pattern binding `Foo` is named the same as one of the variants of the type `Foo`
+warning[E0170]: pattern binding `Foo` is named the same as one of the variants of the type `foo::Foo`
   --> $DIR/lint-uppercase-variables.rs:28:9
    |
 LL |     let Foo = foo::Foo::Foo;
-   |         ^^^ help: to match on the variant, qualify the path: `Foo::Foo`
+   |         ^^^ help: to match on the variant, qualify the path: `foo::Foo::Foo`
 
-warning[E0170]: pattern binding `Foo` is named the same as one of the variants of the type `Foo`
+warning[E0170]: pattern binding `Foo` is named the same as one of the variants of the type `foo::Foo`
   --> $DIR/lint-uppercase-variables.rs:33:17
    |
 LL |     fn in_param(Foo: foo::Foo) {}
-   |                 ^^^ help: to match on the variant, qualify the path: `Foo::Foo`
+   |                 ^^^ help: to match on the variant, qualify the path: `foo::Foo::Foo`
 
 warning: unused variable: `Foo`
   --> $DIR/lint-uppercase-variables.rs:22:9
index 0b3fe9371f7758a63a2fbd098d3007583031f0e0..71ebaea8ed2c185cc296dab497d1e0eb638e96e5 100644 (file)
@@ -1,6 +1,6 @@
 // run-rustfix
 
-#![feature(box_patterns, stmt_expr_attributes)]
+#![feature(box_patterns, stmt_expr_attributes, yeet_expr)]
 
 #![allow(
     dead_code,
@@ -25,6 +25,13 @@ fn _no_lint_attr() {
     let _x = #[allow(dead_code)] (1 + 2);
 }
 
+fn _no_lint_yeet() -> Result<(), ()> {
+    #[allow(unreachable_code)]
+    if (do yeet) {}
+
+    Ok(())
+}
+
 // Don't lint in these cases (#64106).
 fn or_patterns_no_lint() {
     match Box::new(0) {
index 1e78ec5f7d95de02d7483ffe4e20097066a1ed12..28b662dd0242c8715c7ba5e8e22d34426f8537a4 100644 (file)
@@ -1,6 +1,6 @@
 // run-rustfix
 
-#![feature(box_patterns, stmt_expr_attributes)]
+#![feature(box_patterns, stmt_expr_attributes, yeet_expr)]
 
 #![allow(
     dead_code,
@@ -25,6 +25,13 @@ fn _no_lint_attr() {
     let _x = #[allow(dead_code)] (1 + 2);
 }
 
+fn _no_lint_yeet() -> Result<(), ()> {
+    #[allow(unreachable_code)]
+    if (do yeet) {}
+
+    Ok(())
+}
+
 // Don't lint in these cases (#64106).
 fn or_patterns_no_lint() {
     match Box::new(0) {
index c73884663c8f5adf06e6b8d3036a5c58aafe8cbf..a5e69e6d9385cc9db896856f81550bd1ce9cbf9c 100644 (file)
@@ -76,7 +76,7 @@ LL +     let _ = |a: u8| 0;
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:49:12
+  --> $DIR/issue-54538-unused-parens-lint.rs:56:12
    |
 LL |     if let (0 | 1) = 0 {}
    |            ^     ^
@@ -88,7 +88,7 @@ LL +     if let 0 | 1 = 0 {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:50:13
+  --> $DIR/issue-54538-unused-parens-lint.rs:57:13
    |
 LL |     if let ((0 | 1),) = (0,) {}
    |             ^     ^
@@ -100,7 +100,7 @@ LL +     if let (0 | 1,) = (0,) {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:51:13
+  --> $DIR/issue-54538-unused-parens-lint.rs:58:13
    |
 LL |     if let [(0 | 1)] = [0] {}
    |             ^     ^
@@ -112,7 +112,7 @@ LL +     if let [0 | 1] = [0] {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:52:16
+  --> $DIR/issue-54538-unused-parens-lint.rs:59:16
    |
 LL |     if let 0 | (1 | 2) = 0 {}
    |                ^     ^
@@ -124,7 +124,7 @@ LL +     if let 0 | 1 | 2 = 0 {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:54:15
+  --> $DIR/issue-54538-unused-parens-lint.rs:61:15
    |
 LL |     if let TS((0 | 1)) = TS(0) {}
    |               ^     ^
@@ -136,7 +136,7 @@ LL +     if let TS(0 | 1) = TS(0) {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:56:20
+  --> $DIR/issue-54538-unused-parens-lint.rs:63:20
    |
 LL |     if let NS { f: (0 | 1) } = (NS { f: 0 }) {}
    |                    ^     ^
@@ -148,7 +148,7 @@ LL +     if let NS { f: 0 | 1 } = (NS { f: 0 }) {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:66:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:73:9
    |
 LL |         (_) => {}
    |         ^ ^
@@ -160,7 +160,7 @@ LL +         _ => {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:67:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:74:9
    |
 LL |         (y) => {}
    |         ^ ^
@@ -172,7 +172,7 @@ LL +         y => {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:68:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:75:9
    |
 LL |         (ref r) => {}
    |         ^     ^
@@ -184,7 +184,7 @@ LL +         ref r => {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:69:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:76:9
    |
 LL |         (e @ 1...2) => {}
    |         ^         ^
@@ -196,7 +196,7 @@ LL +         e @ 1...2 => {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:75:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:82:9
    |
 LL |         (e @ &(1...2)) => {}
    |         ^            ^
@@ -208,7 +208,7 @@ LL +         e @ &(1...2) => {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:76:10
+  --> $DIR/issue-54538-unused-parens-lint.rs:83:10
    |
 LL |         &(_) => {}
    |          ^ ^
@@ -220,7 +220,7 @@ LL +         &_ => {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:87:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:94:9
    |
 LL |         (_) => {}
    |         ^ ^
@@ -232,7 +232,7 @@ LL +         _ => {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:88:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:95:9
    |
 LL |         (y) => {}
    |         ^ ^
@@ -244,7 +244,7 @@ LL +         y => {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:89:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:96:9
    |
 LL |         (ref r) => {}
    |         ^     ^
@@ -256,7 +256,7 @@ LL +         ref r => {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:90:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:97:9
    |
 LL |         (e @ 1..=2) => {}
    |         ^         ^
@@ -268,7 +268,7 @@ LL +         e @ 1..=2 => {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:96:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:103:9
    |
 LL |         (e @ &(1..=2)) => {}
    |         ^            ^
@@ -280,7 +280,7 @@ LL +         e @ &(1..=2) => {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:97:10
+  --> $DIR/issue-54538-unused-parens-lint.rs:104:10
    |
 LL |         &(_) => {}
    |          ^ ^
index 57d76016c4539d3e8ff8f0623af847d73ae30a08..e6a60d7bc4072378f2cf91a1e01e95f258d02a55 100644 (file)
@@ -9,11 +9,8 @@ LL |     for y in x {
 LL |     let z = x;
    |             ^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `x`
+note: `into_iter` takes ownership of the receiver `self`, which moves `x`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 help: consider iterating over a slice of the `Vec<S>`'s content to avoid moving into the `for` loop
    |
 LL |     for y in &x {
diff --git a/src/test/ui/lto/auxiliary/thinlto-dylib.rs b/src/test/ui/lto/auxiliary/thinlto-dylib.rs
new file mode 100644 (file)
index 0000000..9d17c35
--- /dev/null
@@ -0,0 +1,23 @@
+// Auxiliary crate for test issue-105637: the LTOed dylib which had duplicate symbols from libstd,
+// breaking the panic hook feature.
+//
+// This simulates the `rustc_driver` crate, and the main crate simulates rustc's main binary hooking
+// into this driver.
+
+// compile-flags: -Zdylib-lto -C lto=thin
+
+use std::panic;
+
+pub fn main() {
+    // Install the hook we want to see executed
+    panic::set_hook(Box::new(|_| {
+        eprintln!("LTOed auxiliary crate panic hook");
+    }));
+
+    // Trigger the panic hook with an ICE
+    run_compiler();
+}
+
+fn run_compiler() {
+    panic!("ICEing");
+}
diff --git a/src/test/ui/lto/issue-105637.rs b/src/test/ui/lto/issue-105637.rs
new file mode 100644 (file)
index 0000000..0d9f0be
--- /dev/null
@@ -0,0 +1,28 @@
+// Regression test for issue #105637: `-Zdylib-lto` with LTO duplicated symbols from other dylibs,
+// in this case from libstd.
+//
+// That manifested as both `rustc_driver` and rustc's "main" (`compiler/rustc`) having their own
+// `std::panicking::HOOK` static, and the hook in rustc's main (the default stdlib's) being executed
+// when rustc ICEs, instead of the overriden hook from `rustc_driver` (which also displays the query
+// stack and information on how to open a GH issue for the encountered ICE).
+//
+// In this test, we reproduce this setup by installing a panic hook in both the main and an LTOed
+// dylib: the last hook set should be the one being executed, the dylib's.
+
+// aux-build: thinlto-dylib.rs
+// run-fail
+// check-run-results
+
+extern crate thinlto_dylib;
+
+use std::panic;
+
+fn main() {
+    // We don't want to see this panic hook executed
+    std::panic::set_hook(Box::new(|_| {
+        eprintln!("main crate panic hook");
+    }));
+
+    // Have the LTOed dylib install its own hook and panic, we want to see its hook executed.
+    thinlto_dylib::main();
+}
diff --git a/src/test/ui/lto/issue-105637.run.stderr b/src/test/ui/lto/issue-105637.run.stderr
new file mode 100644 (file)
index 0000000..43388e7
--- /dev/null
@@ -0,0 +1 @@
+LTOed auxiliary crate panic hook
index 03ecc4b4418c61aa25f065301dfd25f89ad619e2..287cd7d67044eb824eba79c53b7c89130d356c27 100644 (file)
@@ -12,11 +12,6 @@ LL |     };
    |     |
    |     `mutex` dropped here while still borrowed
    |
-help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
-  --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
-   |
-LL |         $dst.write_fmt($crate::format_args!($($arg)*));
-   |                                                       +
 
 error[E0597]: `mutex` does not live long enough
   --> $DIR/format-args-temporaries-in-write.rs:47:29
@@ -32,11 +27,6 @@ LL |     };
    |     |
    |     `mutex` dropped here while still borrowed
    |
-help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
-  --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
-   |
-LL |         $dst.write_fmt($crate::format_args_nl!($($arg)*));
-   |                                                          +
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/macros/issue-42954.fixed b/src/test/ui/macros/issue-42954.fixed
new file mode 100644 (file)
index 0000000..a73054c
--- /dev/null
@@ -0,0 +1,14 @@
+// run-rustfix
+
+#![allow(unused_must_use, unused_comparisons)]
+
+macro_rules! is_plainly_printable {
+    ($i: ident) => {
+        ($i as u32) < 0 //~ `<` is interpreted as a start of generic arguments
+    };
+}
+
+fn main() {
+    let c = 'a';
+    is_plainly_printable!(c);
+}
diff --git a/src/test/ui/macros/issue-42954.rs b/src/test/ui/macros/issue-42954.rs
new file mode 100644 (file)
index 0000000..5f9b0e3
--- /dev/null
@@ -0,0 +1,14 @@
+// run-rustfix
+
+#![allow(unused_must_use, unused_comparisons)]
+
+macro_rules! is_plainly_printable {
+    ($i: ident) => {
+        $i as u32 < 0 //~ `<` is interpreted as a start of generic arguments
+    };
+}
+
+fn main() {
+    let c = 'a';
+    is_plainly_printable!(c);
+}
diff --git a/src/test/ui/macros/issue-42954.stderr b/src/test/ui/macros/issue-42954.stderr
new file mode 100644 (file)
index 0000000..396a919
--- /dev/null
@@ -0,0 +1,19 @@
+error: `<` is interpreted as a start of generic arguments for `u32`, not a comparison
+  --> $DIR/issue-42954.rs:7:19
+   |
+LL |         $i as u32 < 0
+   |                   ^ - interpreted as generic arguments
+   |                   |
+   |                   not interpreted as comparison
+...
+LL |     is_plainly_printable!(c);
+   |     ------------------------ in this macro invocation
+   |
+   = note: this error originates in the macro `is_plainly_printable` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: try comparing the cast value
+   |
+LL |         ($i as u32) < 0
+   |         +         +
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/macros/issue-51848.rs b/src/test/ui/macros/issue-51848.rs
new file mode 100644 (file)
index 0000000..4792bdd
--- /dev/null
@@ -0,0 +1,20 @@
+// In case of macro expansion, the errors should be matched using the deepest callsite in the
+// macro call stack whose span is in the current file
+
+macro_rules! macro_with_error {
+    ( ) => {
+        println!("{"); //~ ERROR invalid
+    };
+}
+
+fn foo() {
+
+}
+
+fn main() {
+    macro_with_error!();
+    //^ In case of a local macro we want the error to be matched in the macro definition, not here
+
+    println!("}"); //~ ERROR invalid
+    //^ In case of an external macro we want the error to be matched here
+}
diff --git a/src/test/ui/macros/issue-51848.stderr b/src/test/ui/macros/issue-51848.stderr
new file mode 100644 (file)
index 0000000..c25bedf
--- /dev/null
@@ -0,0 +1,24 @@
+error: invalid format string: expected `'}'` but string was terminated
+  --> $DIR/issue-51848.rs:6:20
+   |
+LL |         println!("{");
+   |                   -^ expected `'}'` in format string
+   |                   |
+   |                   because of this opening brace
+...
+LL |     macro_with_error!();
+   |     ------------------- in this macro invocation
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+   = note: this error originates in the macro `macro_with_error` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: invalid format string: unmatched `}` found
+  --> $DIR/issue-51848.rs:18:15
+   |
+LL |     println!("}");
+   |               ^ unmatched `}` in format string
+   |
+   = note: if you intended to print `}`, you can escape it using `}}`
+
+error: aborting due to 2 previous errors
+
index 1023189eaa30fc7e43d688bbb6f4a5735182f2fd..36aba8aa08a0b18a95c35a0187a8c569e2e55f8c 100644 (file)
@@ -5,11 +5,13 @@ LL |         assert_eq!("B", "B");
    |         ^^^^^^^^^
 ...
 LL |     foo!()
-   |     ------- help: you might be missing a semicolon here: `;`
-   |     |
-   |     caused by the macro expansion here
+   |     ------ caused by the macro expansion here
    |
    = note: the usage of `foo!` is likely invalid in expression context
+help: you might be missing a semicolon here
+   |
+LL |     foo!();
+   |           +
 
 warning: trailing semicolon in macro used in expression position
   --> $DIR/macro-in-expression-context.rs:5:29
index 3e8cfb3f0e97fba429aca99931f3de4959c64d86..d7c8aaae22e1e1cf0e4ff3d74488ee324c58443a 100644 (file)
@@ -3,11 +3,9 @@ error: cannot find macro `printlx` in this scope
    |
 LL |     printlx!("oh noes!");
    |     ^^^^^^^ help: a macro with a similar name exists: `println`
+  --> $SRC_DIR/std/src/macros.rs:LL:COL
    |
-  ::: $SRC_DIR/std/src/macros.rs:LL:COL
-   |
-LL | macro_rules! println {
-   | -------------------- similarly named macro `println` defined here
+   = note: similarly named macro `println` defined here
 
 error: aborting due to previous error
 
index 70900a6bc81d3a1468003c2dda68f9781d1fc505..f1c3512bc9b8ee39fba96b9bf7b545e84d5ca1cc 100644 (file)
@@ -3,11 +3,9 @@ error: cannot find macro `inline` in this scope
    |
 LL |     inline!();
    |     ^^^^^^ help: a macro with a similar name exists: `line`
+  --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-   |
-LL |     macro_rules! line {
-   |     ----------------- similarly named macro `line` defined here
+   = note: similarly named macro `line` defined here
    |
    = note: `inline` is in scope, but it is an attribute: `#[inline]`
 
index 8f9dba16578eb9b4ad184f86c3f6b4f575c7359c..22f54e04e54c3dc118db8bef42677a0309d58d2e 100644 (file)
@@ -7,9 +7,6 @@ LL | macro_rules! unknown { () => () }
 error[E0773]: attempted to define built-in macro more than once
   --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
    |
-LL |     macro_rules! line {
-   |     ^^^^^^^^^^^^^^^^^
-   |
 note: previously defined here
   --> $DIR/unknown-builtin.rs:9:1
    |
index 803883460f08f4074adf2752a500673820a37b2c..6ff6fbabb4a5f3ac04ccdaae843f7b9a233310e2 100644 (file)
@@ -24,9 +24,6 @@ LL | #[derive(Copy(Bad))]
    |
 note: required by a bound in `Copy`
   --> $SRC_DIR/core/src/marker.rs:LL:COL
-   |
-LL | pub trait Copy: Clone {
-   |                 ^^^^^ required by this bound in `Copy`
    = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `Test1` with `#[derive(Clone)]`
    |
@@ -41,9 +38,6 @@ LL | #[derive(Copy="bad")]
    |
 note: required by a bound in `Copy`
   --> $SRC_DIR/core/src/marker.rs:LL:COL
-   |
-LL | pub trait Copy: Clone {
-   |                 ^^^^^ required by this bound in `Copy`
    = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `Test2` with `#[derive(Clone)]`
    |
index 9eadb88a8ba814d6ce7b6fa01365f3f2571c0ac8..e3b501b2fd558c42ad720ba709aac0abf2d327d1 100644 (file)
@@ -6,8 +6,8 @@ LL |     let x = match () {
    |
 help: consider giving `x` an explicit type
    |
-LL |     let x: _ = match () {
-   |          +++
+LL |     let x: /* Type */ = match () {
+   |          ++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/methods/issues/issue-105732.rs b/src/test/ui/methods/issues/issue-105732.rs
new file mode 100644 (file)
index 0000000..98b7a8d
--- /dev/null
@@ -0,0 +1,13 @@
+#![feature(auto_traits)]
+
+auto trait Foo {
+    fn g(&self); //~ ERROR auto traits cannot have associated items
+}
+
+trait Bar {
+    fn f(&self) {
+        self.g(); //~ ERROR the method `g` exists for reference `&Self`, but its trait bounds were not satisfied
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/methods/issues/issue-105732.stderr b/src/test/ui/methods/issues/issue-105732.stderr
new file mode 100644 (file)
index 0000000..fb2bdf4
--- /dev/null
@@ -0,0 +1,28 @@
+error[E0380]: auto traits cannot have associated items
+  --> $DIR/issue-105732.rs:4:8
+   |
+LL | auto trait Foo {
+   |            --- auto trait cannot have associated items
+LL |     fn g(&self);
+   |     ---^-------- help: remove these associated items
+
+error[E0599]: the method `g` exists for reference `&Self`, but its trait bounds were not satisfied
+  --> $DIR/issue-105732.rs:9:14
+   |
+LL |         self.g();
+   |              ^
+   |
+   = note: the following trait bounds were not satisfied:
+           `Self: Foo`
+           which is required by `&Self: Foo`
+           `&Self: Foo`
+   = help: items from traits can only be used if the type parameter is bounded by the trait
+help: the following trait defines an item `g`, perhaps you need to add a supertrait for it:
+   |
+LL | trait Bar: Foo {
+   |          +++++
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0380, E0599.
+For more information about an error, try `rustc --explain E0380`.
index 070cd3054369b686b5f2e5cdb12ccfe78d8cd5e9..8d7b32e025a0864cfb60454c6eb0e2f3b3737de9 100644 (file)
@@ -57,7 +57,7 @@ error[E0308]: mismatched types
   --> $DIR/issue-90315.rs:28:8
    |
 LL |     if 1..(end + 1).is_empty() {
-   |        ^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+   |        ^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<{integer}>`
@@ -77,7 +77,7 @@ error[E0308]: mismatched types
   --> $DIR/issue-90315.rs:34:8
    |
 LL |     if 1..(end + 1).is_sorted() {
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<{integer}>`
@@ -97,7 +97,7 @@ error[E0308]: mismatched types
   --> $DIR/issue-90315.rs:40:21
    |
 LL |     let _res: i32 = 3..6.take(2).sum();
-   |               ---   ^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `std::ops::Range`
+   |               ---   ^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `Range`
    |               |
    |               expected due to this
    |
@@ -119,7 +119,7 @@ error[E0308]: mismatched types
   --> $DIR/issue-90315.rs:45:21
    |
 LL |     let _sum: i32 = 3..6.sum();
-   |               ---   ^^^^^^^^^^ expected `i32`, found struct `std::ops::Range`
+   |               ---   ^^^^^^^^^^ expected `i32`, found struct `Range`
    |               |
    |               expected due to this
    |
@@ -158,7 +158,7 @@ error[E0308]: mismatched types
   --> $DIR/issue-90315.rs:62:8
    |
 LL |     if 1..end.error_method() {
-   |        ^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+   |        ^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<{integer}>`
index a4ffb864dad9cb3848684ef77fa542e1ef4a386d..3f4e647491eb7390efc4ba288ba0a788b0bd2484 100644 (file)
@@ -61,11 +61,8 @@ LL |      .take()
    = note: the following trait bounds were not satisfied:
            `Foo: Iterator`
            which is required by `&mut Foo: Iterator`
-note: the following trait must be implemented
+note: the trait `Iterator` must be implemented
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL | pub trait Iterator {
-   | ^^^^^^^^^^^^^^^^^^
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `take`, perhaps you need to implement it:
            candidate #1: `Iterator`
index 62f20d6d50c040019439f817f08e9d198945e014..25ad360b329aad8ecba8dbf4591f15c8a572f1e9 100644 (file)
@@ -11,11 +11,9 @@ warning: cannot specify lifetime arguments explicitly if late bound lifetime par
    |
 LL |     0.clone::<'a>();
    |               ^^
+  --> $SRC_DIR/core/src/clone.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL |     fn clone(&self) -> Self;
-   |              - the late bound lifetime parameter is introduced here
+   = note: the late bound lifetime parameter is introduced here
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
index fc42d1a4dcd08136374b9ab6203cd4de854dbd23..8846efba871b9cd1f845b86b58dfbaa5a0880d1b 100644 (file)
@@ -23,7 +23,7 @@ error[E0599]: no method named `extend` found for struct `Map` in the current sco
   --> $DIR/method-not-found-generic-arg-elision.rs:87:29
    |
 LL |     v.iter().map(|x| x * x).extend(std::iter::once(100));
-   |                             ^^^^^^ method not found in `Map<std::slice::Iter<'_, i32>, [closure@$DIR/method-not-found-generic-arg-elision.rs:87:18: 87:21]>`
+   |                             ^^^^^^ method not found in `Map<Iter<'_, i32>, [closure@method-not-found-generic-arg-elision.rs:87:18]>`
 
 error[E0599]: no method named `method` found for struct `Wrapper<bool>` in the current scope
   --> $DIR/method-not-found-generic-arg-elision.rs:90:13
diff --git a/src/test/ui/mir/field-projection-invariant.rs b/src/test/ui/mir/field-projection-invariant.rs
new file mode 100644 (file)
index 0000000..b5d6add
--- /dev/null
@@ -0,0 +1,24 @@
+// build-pass
+struct Inv<'a>(&'a mut &'a ());
+enum Foo<T> {
+    Bar,
+    Var(T),
+}
+type Supertype = Foo<for<'a> fn(Inv<'a>, Inv<'a>)>;
+
+fn foo(x: Foo<for<'a, 'b> fn(Inv<'a>, Inv<'b>)>) {
+    match x {
+        Supertype::Bar => {}
+        Supertype::Var(x) => {}
+    }
+}
+
+fn foo_nested(x: Foo<Foo<for<'a, 'b> fn(Inv<'a>, Inv<'b>)>>) {
+    match x {
+        Foo::Bar => {}
+        Foo::Var(Supertype::Bar) => {}
+        Foo::Var(Supertype::Var(x)) => {}
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/mir/field-ty-ascription-enums.rs b/src/test/ui/mir/field-ty-ascription-enums.rs
new file mode 100644 (file)
index 0000000..179af61
--- /dev/null
@@ -0,0 +1,15 @@
+// build-pass
+
+enum Foo<T> {
+    Var(T),
+} // `T` is covariant.
+
+fn foo<'b>(x: Foo<for<'a> fn(&'a ())>) {
+    let Foo::Var(x): Foo<fn(&'b ())> = x;
+}
+
+fn foo_nested<'b>(x: Foo<Foo<for<'a> fn(&'a ())>>) {
+    let Foo::Var(Foo::Var(x)): Foo<Foo<fn(&'b ())>> = x;
+}
+
+fn main() {}
diff --git a/src/test/ui/mir/field-ty-ascription.rs b/src/test/ui/mir/field-ty-ascription.rs
new file mode 100644 (file)
index 0000000..178c791
--- /dev/null
@@ -0,0 +1,37 @@
+// build-pass
+
+struct Foo<T>(T); // `T` is covariant.
+
+struct Bar<T> {
+    x: T,
+} // `T` is covariant.
+
+fn bar<'b>(x: Bar<for<'a> fn(&'a ())>) {
+    let Bar { x }: Bar<fn(&'b ())> = x;
+}
+
+fn bar_nested<'b>(x: Bar<Bar<for<'a> fn(&'a ())>>) {
+    let Bar { x: Bar { x } }: Bar<Bar<fn(&'b ())>> = x;
+}
+
+fn bar_foo_nested<'b>(x: Bar<Foo<for<'a> fn(&'a ())>>) {
+    let Bar { x: Foo ( x ) }: Bar<Foo<fn(&'b ())>> = x;
+}
+
+fn foo<'b>(x: Foo<for<'a> fn(&'a ())>) {
+    let Foo(y): Foo<fn(&'b ())> = x;
+}
+
+fn foo_nested<'b>(x: Foo<Foo<for<'a> fn(&'a ())>>) {
+    let Foo(Foo(y)): Foo<Foo<fn(&'b ())>> = x;
+}
+
+fn tuple<'b>(x: (u32, for<'a> fn(&'a ()))) {
+    let (_, y): (u32, fn(&'b ())) = x;
+}
+
+fn tuple_nested<'b>(x: (u32, (u32, for<'a> fn(&'a ())))) {
+    let (_, (_, y)): (u32, (u32, fn(&'b ()))) = x;
+}
+
+fn main() {}
diff --git a/src/test/ui/mir/issue-29227.rs b/src/test/ui/mir/issue-29227.rs
new file mode 100644 (file)
index 0000000..e9dfc28
--- /dev/null
@@ -0,0 +1,142 @@
+// run-pass
+// ignore-tidy-linelength
+
+// Regression test for #29227. The problem here was that MIR
+// construction for these gigantic match expressions was very
+// inefficient.
+
+pub trait CharExt : Sized + Copy {
+    fn is_unicode_uppercase_letter(self) -> bool { false }
+    fn is_unicode_lowercase_letter(self) -> bool { false }
+    fn is_unicode_titlecase_letter(self) -> bool { false }
+    fn is_unicode_modifier_letter(self) -> bool { false }
+    fn is_unicode_other_letter(self) -> bool { false }
+    fn is_unicode_letter_number(self) -> bool { false }
+    fn is_unicode_nonspacing_mark(self) -> bool { false }
+    fn is_unicode_combining_spacing_mark(self) -> bool { false }
+    fn is_unicode_decimal_number(self) -> bool{ false }
+    fn is_unicode_connector_punctiation(self) -> bool { false }
+    fn is_unicode_space_separator(self) -> bool { false }
+
+    fn is_es_identifier_start(self) -> bool { false }
+    fn is_es_identifier_part(self) -> bool { false }
+    fn is_es_whitespace(self) -> bool { false }
+    fn is_es_line_terminator(self) -> bool { false }
+
+    fn is_unicode_letter(self) -> bool {
+        self.is_unicode_uppercase_letter()
+        || self.is_unicode_lowercase_letter()
+        || self.is_unicode_titlecase_letter()
+        || self.is_unicode_modifier_letter()
+        || self.is_unicode_modifier_letter()
+        || self.is_unicode_letter_number()
+    }
+
+}
+
+
+macro_rules! match_char_class {
+    ($thing:expr, $($c:expr),*) => {
+        match $thing {
+            $($c)|* => true,
+            _ => false
+        }
+    }
+}
+
+impl CharExt for char {
+    fn is_unicode_uppercase_letter(self) -> bool {
+        match_char_class!(self,
+            '\u{0041}', '\u{0042}', '\u{0043}', '\u{0044}', '\u{0045}', '\u{0046}', '\u{0047}', '\u{0048}', '\u{0049}', '\u{004A}', '\u{004B}', '\u{004C}', '\u{004D}', '\u{004E}', '\u{004F}', '\u{0050}', '\u{0051}', '\u{0052}', '\u{0053}', '\u{0054}', '\u{0055}', '\u{0056}', '\u{0057}', '\u{0058}', '\u{0059}', '\u{005A}', '\u{00C0}', '\u{00C1}', '\u{00C2}', '\u{00C3}', '\u{00C4}', '\u{00C5}', '\u{00C6}', '\u{00C7}', '\u{00C8}', '\u{00C9}', '\u{00CA}', '\u{00CB}', '\u{00CC}', '\u{00CD}', '\u{00CE}', '\u{00CF}', '\u{00D0}', '\u{00D1}', '\u{00D2}', '\u{00D3}', '\u{00D4}', '\u{00D5}', '\u{00D6}', '\u{00D8}', '\u{00D9}', '\u{00DA}', '\u{00DB}', '\u{00DC}', '\u{00DD}', '\u{00DE}', '\u{0100}', '\u{0102}', '\u{0104}', '\u{0106}', '\u{0108}', '\u{010A}', '\u{010C}', '\u{010E}', '\u{0110}', '\u{0112}', '\u{0114}', '\u{0116}', '\u{0118}', '\u{011A}', '\u{011C}', '\u{011E}', '\u{0120}', '\u{0122}', '\u{0124}', '\u{0126}', '\u{0128}', '\u{012A}', '\u{012C}', '\u{012E}', '\u{0130}', '\u{0132}', '\u{0134}', '\u{0136}', '\u{0139}', '\u{013B}', '\u{013D}', '\u{013F}', '\u{0141}', '\u{0143}', '\u{0145}', '\u{0147}', '\u{014A}', '\u{014C}', '\u{014E}', '\u{0150}', '\u{0152}', '\u{0154}', '\u{0156}', '\u{0158}', '\u{015A}', '\u{015C}', '\u{015E}', '\u{0160}', '\u{0162}', '\u{0164}', '\u{0166}', '\u{0168}', '\u{016A}', '\u{016C}', '\u{016E}', '\u{0170}', '\u{0172}', '\u{0174}', '\u{0176}', '\u{0178}', '\u{0179}', '\u{017B}', '\u{017D}', '\u{0181}', '\u{0182}', '\u{0184}', '\u{0186}', '\u{0187}', '\u{0189}', '\u{018A}', '\u{018B}', '\u{018E}', '\u{018F}', '\u{0190}', '\u{0191}', '\u{0193}', '\u{0194}', '\u{0196}', '\u{0197}', '\u{0198}', '\u{019C}', '\u{019D}', '\u{019F}', '\u{01A0}', '\u{01A2}', '\u{01A4}', '\u{01A6}', '\u{01A7}', '\u{01A9}', '\u{01AC}', '\u{01AE}', '\u{01AF}', '\u{01B1}', '\u{01B2}', '\u{01B3}', '\u{01B5}', '\u{01B7}', '\u{01B8}', '\u{01BC}', '\u{01C4}', '\u{01C7}', '\u{01CA}', '\u{01CD}', '\u{01CF}', '\u{01D1}', '\u{01D3}', '\u{01D5}', '\u{01D7}', '\u{01D9}', '\u{01DB}', '\u{01DE}', '\u{01E0}', '\u{01E2}', '\u{01E4}', '\u{01E6}', '\u{01E8}', '\u{01EA}', '\u{01EC}', '\u{01EE}', '\u{01F1}', '\u{01F4}', '\u{01F6}', '\u{01F7}', '\u{01F8}', '\u{01FA}', '\u{01FC}', '\u{01FE}', '\u{0200}', '\u{0202}', '\u{0204}', '\u{0206}', '\u{0208}', '\u{020A}', '\u{020C}', '\u{020E}', '\u{0210}', '\u{0212}', '\u{0214}', '\u{0216}', '\u{0218}', '\u{021A}', '\u{021C}', '\u{021E}', '\u{0220}', '\u{0222}', '\u{0224}', '\u{0226}', '\u{0228}', '\u{022A}', '\u{022C}', '\u{022E}', '\u{0230}', '\u{0232}', '\u{023A}', '\u{023B}', '\u{023D}', '\u{023E}', '\u{0241}', '\u{0243}', '\u{0244}', '\u{0245}', '\u{0246}', '\u{0248}', '\u{024A}', '\u{024C}', '\u{024E}', '\u{0370}', '\u{0372}', '\u{0376}', '\u{0386}', '\u{0388}', '\u{0389}', '\u{038A}', '\u{038C}', '\u{038E}', '\u{038F}', '\u{0391}', '\u{0392}', '\u{0393}', '\u{0394}', '\u{0395}', '\u{0396}', '\u{0397}', '\u{0398}', '\u{0399}', '\u{039A}', '\u{039B}', '\u{039C}', '\u{039D}', '\u{039E}', '\u{039F}', '\u{03A0}', '\u{03A1}', '\u{03A3}', '\u{03A4}', '\u{03A5}', '\u{03A6}', '\u{03A7}', '\u{03A8}', '\u{03A9}', '\u{03AA}', '\u{03AB}', '\u{03CF}', '\u{03D2}', '\u{03D3}', '\u{03D4}', '\u{03D8}', '\u{03DA}', '\u{03DC}', '\u{03DE}', '\u{03E0}', '\u{03E2}', '\u{03E4}', '\u{03E6}', '\u{03E8}', '\u{03EA}', '\u{03EC}', '\u{03EE}', '\u{03F4}', '\u{03F7}', '\u{03F9}', '\u{03FA}', '\u{03FD}', '\u{03FE}', '\u{03FF}', '\u{0400}', '\u{0401}', '\u{0402}', '\u{0403}', '\u{0404}', '\u{0405}', '\u{0406}', '\u{0407}', '\u{0408}', '\u{0409}', '\u{040A}', '\u{040B}', '\u{040C}', '\u{040D}', '\u{040E}', '\u{040F}', '\u{0410}', '\u{0411}', '\u{0412}', '\u{0413}', '\u{0414}', '\u{0415}', '\u{0416}', '\u{0417}', '\u{0418}', '\u{0419}', '\u{041A}', '\u{041B}', '\u{041C}', '\u{041D}', '\u{041E}', '\u{041F}', '\u{0420}', '\u{0421}', '\u{0422}', '\u{0423}', '\u{0424}', '\u{0425}', '\u{0426}', '\u{0427}', '\u{0428}', '\u{0429}', '\u{042A}', '\u{042B}', '\u{042C}', '\u{042D}', '\u{042E}', '\u{042F}', '\u{0460}', '\u{0462}', '\u{0464}', '\u{0466}', '\u{0468}', '\u{046A}', '\u{046C}', '\u{046E}', '\u{0470}', '\u{0472}', '\u{0474}', '\u{0476}', '\u{0478}', '\u{047A}', '\u{047C}', '\u{047E}', '\u{0480}', '\u{048A}', '\u{048C}', '\u{048E}', '\u{0490}', '\u{0492}', '\u{0494}', '\u{0496}', '\u{0498}', '\u{049A}', '\u{049C}', '\u{049E}', '\u{04A0}', '\u{04A2}', '\u{04A4}', '\u{04A6}', '\u{04A8}', '\u{04AA}', '\u{04AC}', '\u{04AE}', '\u{04B0}', '\u{04B2}', '\u{04B4}', '\u{04B6}', '\u{04B8}', '\u{04BA}', '\u{04BC}', '\u{04BE}', '\u{04C0}', '\u{04C1}', '\u{04C3}', '\u{04C5}', '\u{04C7}', '\u{04C9}', '\u{04CB}', '\u{04CD}', '\u{04D0}', '\u{04D2}', '\u{04D4}', '\u{04D6}', '\u{04D8}', '\u{04DA}', '\u{04DC}', '\u{04DE}', '\u{04E0}', '\u{04E2}', '\u{04E4}', '\u{04E6}', '\u{04E8}', '\u{04EA}', '\u{04EC}', '\u{04EE}', '\u{04F0}', '\u{04F2}', '\u{04F4}', '\u{04F6}', '\u{04F8}', '\u{04FA}', '\u{04FC}', '\u{04FE}', '\u{0500}', '\u{0502}', '\u{0504}', '\u{0506}', '\u{0508}', '\u{050A}', '\u{050C}', '\u{050E}', '\u{0510}', '\u{0512}', '\u{0514}', '\u{0516}', '\u{0518}', '\u{051A}', '\u{051C}', '\u{051E}', '\u{0520}', '\u{0522}', '\u{0531}', '\u{0532}', '\u{0533}', '\u{0534}', '\u{0535}', '\u{0536}', '\u{0537}', '\u{0538}', '\u{0539}', '\u{053A}', '\u{053B}', '\u{053C}', '\u{053D}', '\u{053E}', '\u{053F}', '\u{0540}', '\u{0541}', '\u{0542}', '\u{0543}', '\u{0544}', '\u{0545}', '\u{0546}', '\u{0547}', '\u{0548}', '\u{0549}', '\u{054A}', '\u{054B}', '\u{054C}', '\u{054D}', '\u{054E}', '\u{054F}', '\u{0550}', '\u{0551}', '\u{0552}', '\u{0553}', '\u{0554}', '\u{0555}', '\u{0556}', '\u{10A0}', '\u{10A1}', '\u{10A2}', '\u{10A3}', '\u{10A4}', '\u{10A5}', '\u{10A6}', '\u{10A7}', '\u{10A8}', '\u{10A9}', '\u{10AA}', '\u{10AB}', '\u{10AC}', '\u{10AD}', '\u{10AE}', '\u{10AF}', '\u{10B0}', '\u{10B1}', '\u{10B2}', '\u{10B3}', '\u{10B4}', '\u{10B5}', '\u{10B6}', '\u{10B7}', '\u{10B8}', '\u{10B9}', '\u{10BA}', '\u{10BB}', '\u{10BC}', '\u{10BD}', '\u{10BE}', '\u{10BF}', '\u{10C0}', '\u{10C1}', '\u{10C2}', '\u{10C3}', '\u{10C4}', '\u{10C5}', '\u{1E00}', '\u{1E02}', '\u{1E04}', '\u{1E06}', '\u{1E08}', '\u{1E0A}', '\u{1E0C}', '\u{1E0E}', '\u{1E10}', '\u{1E12}', '\u{1E14}', '\u{1E16}', '\u{1E18}', '\u{1E1A}', '\u{1E1C}', '\u{1E1E}', '\u{1E20}', '\u{1E22}', '\u{1E24}', '\u{1E26}', '\u{1E28}', '\u{1E2A}', '\u{1E2C}', '\u{1E2E}', '\u{1E30}', '\u{1E32}', '\u{1E34}', '\u{1E36}', '\u{1E38}', '\u{1E3A}', '\u{1E3C}', '\u{1E3E}', '\u{1E40}', '\u{1E42}', '\u{1E44}', '\u{1E46}', '\u{1E48}', '\u{1E4A}', '\u{1E4C}', '\u{1E4E}', '\u{1E50}', '\u{1E52}', '\u{1E54}', '\u{1E56}', '\u{1E58}', '\u{1E5A}', '\u{1E5C}', '\u{1E5E}', '\u{1E60}', '\u{1E62}', '\u{1E64}', '\u{1E66}', '\u{1E68}', '\u{1E6A}', '\u{1E6C}', '\u{1E6E}', '\u{1E70}', '\u{1E72}', '\u{1E74}', '\u{1E76}', '\u{1E78}', '\u{1E7A}', '\u{1E7C}', '\u{1E7E}', '\u{1E80}', '\u{1E82}', '\u{1E84}', '\u{1E86}', '\u{1E88}', '\u{1E8A}', '\u{1E8C}', '\u{1E8E}', '\u{1E90}', '\u{1E92}', '\u{1E94}', '\u{1E9E}', '\u{1EA0}', '\u{1EA2}', '\u{1EA4}', '\u{1EA6}', '\u{1EA8}', '\u{1EAA}', '\u{1EAC}', '\u{1EAE}', '\u{1EB0}', '\u{1EB2}', '\u{1EB4}', '\u{1EB6}', '\u{1EB8}', '\u{1EBA}', '\u{1EBC}', '\u{1EBE}', '\u{1EC0}', '\u{1EC2}', '\u{1EC4}', '\u{1EC6}', '\u{1EC8}', '\u{1ECA}', '\u{1ECC}', '\u{1ECE}', '\u{1ED0}', '\u{1ED2}', '\u{1ED4}', '\u{1ED6}', '\u{1ED8}', '\u{1EDA}', '\u{1EDC}', '\u{1EDE}', '\u{1EE0}', '\u{1EE2}', '\u{1EE4}', '\u{1EE6}', '\u{1EE8}', '\u{1EEA}', '\u{1EEC}', '\u{1EEE}', '\u{1EF0}', '\u{1EF2}', '\u{1EF4}', '\u{1EF6}', '\u{1EF8}', '\u{1EFA}', '\u{1EFC}', '\u{1EFE}', '\u{1F08}', '\u{1F09}', '\u{1F0A}', '\u{1F0B}', '\u{1F0C}', '\u{1F0D}', '\u{1F0E}', '\u{1F0F}', '\u{1F18}', '\u{1F19}', '\u{1F1A}', '\u{1F1B}', '\u{1F1C}', '\u{1F1D}', '\u{1F28}', '\u{1F29}', '\u{1F2A}', '\u{1F2B}', '\u{1F2C}', '\u{1F2D}', '\u{1F2E}', '\u{1F2F}', '\u{1F38}', '\u{1F39}', '\u{1F3A}', '\u{1F3B}', '\u{1F3C}', '\u{1F3D}', '\u{1F3E}', '\u{1F3F}', '\u{1F48}', '\u{1F49}', '\u{1F4A}', '\u{1F4B}', '\u{1F4C}', '\u{1F4D}', '\u{1F59}', '\u{1F5B}', '\u{1F5D}', '\u{1F5F}', '\u{1F68}', '\u{1F69}', '\u{1F6A}', '\u{1F6B}', '\u{1F6C}', '\u{1F6D}', '\u{1F6E}', '\u{1F6F}', '\u{1FB8}', '\u{1FB9}', '\u{1FBA}', '\u{1FBB}', '\u{1FC8}', '\u{1FC9}', '\u{1FCA}', '\u{1FCB}', '\u{1FD8}', '\u{1FD9}', '\u{1FDA}', '\u{1FDB}', '\u{1FE8}', '\u{1FE9}', '\u{1FEA}', '\u{1FEB}', '\u{1FEC}', '\u{1FF8}', '\u{1FF9}', '\u{1FFA}', '\u{1FFB}', '\u{2102}', '\u{2107}', '\u{210B}', '\u{210C}', '\u{210D}', '\u{2110}', '\u{2111}', '\u{2112}', '\u{2115}', '\u{2119}', '\u{211A}', '\u{211B}', '\u{211C}', '\u{211D}', '\u{2124}', '\u{2126}', '\u{2128}', '\u{212A}', '\u{212B}', '\u{212C}', '\u{212D}', '\u{2130}', '\u{2131}', '\u{2132}', '\u{2133}', '\u{213E}', '\u{213F}', '\u{2145}', '\u{2183}', '\u{2C00}', '\u{2C01}', '\u{2C02}', '\u{2C03}', '\u{2C04}', '\u{2C05}', '\u{2C06}', '\u{2C07}', '\u{2C08}', '\u{2C09}', '\u{2C0A}', '\u{2C0B}', '\u{2C0C}', '\u{2C0D}', '\u{2C0E}', '\u{2C0F}', '\u{2C10}', '\u{2C11}', '\u{2C12}', '\u{2C13}', '\u{2C14}', '\u{2C15}', '\u{2C16}', '\u{2C17}', '\u{2C18}', '\u{2C19}', '\u{2C1A}', '\u{2C1B}', '\u{2C1C}', '\u{2C1D}', '\u{2C1E}', '\u{2C1F}', '\u{2C20}', '\u{2C21}', '\u{2C22}', '\u{2C23}', '\u{2C24}', '\u{2C25}', '\u{2C26}', '\u{2C27}', '\u{2C28}', '\u{2C29}', '\u{2C2A}', '\u{2C2B}', '\u{2C2C}', '\u{2C2D}', '\u{2C2E}', '\u{2C60}', '\u{2C62}', '\u{2C63}', '\u{2C64}', '\u{2C67}', '\u{2C69}', '\u{2C6B}', '\u{2C6D}', '\u{2C6E}', '\u{2C6F}', '\u{2C72}', '\u{2C75}', '\u{2C80}', '\u{2C82}', '\u{2C84}', '\u{2C86}', '\u{2C88}', '\u{2C8A}', '\u{2C8C}', '\u{2C8E}', '\u{2C90}', '\u{2C92}', '\u{2C94}', '\u{2C96}', '\u{2C98}', '\u{2C9A}', '\u{2C9C}', '\u{2C9E}', '\u{2CA0}', '\u{2CA2}', '\u{2CA4}', '\u{2CA6}', '\u{2CA8}', '\u{2CAA}', '\u{2CAC}', '\u{2CAE}', '\u{2CB0}', '\u{2CB2}', '\u{2CB4}', '\u{2CB6}', '\u{2CB8}', '\u{2CBA}', '\u{2CBC}', '\u{2CBE}', '\u{2CC0}', '\u{2CC2}', '\u{2CC4}', '\u{2CC6}', '\u{2CC8}', '\u{2CCA}', '\u{2CCC}', '\u{2CCE}', '\u{2CD0}', '\u{2CD2}', '\u{2CD4}', '\u{2CD6}', '\u{2CD8}', '\u{2CDA}', '\u{2CDC}', '\u{2CDE}', '\u{2CE0}', '\u{2CE2}', '\u{A640}', '\u{A642}', '\u{A644}', '\u{A646}', '\u{A648}', '\u{A64A}', '\u{A64C}', '\u{A64E}', '\u{A650}', '\u{A652}', '\u{A654}', '\u{A656}', '\u{A658}', '\u{A65A}', '\u{A65C}', '\u{A65E}', '\u{A662}', '\u{A664}', '\u{A666}', '\u{A668}', '\u{A66A}', '\u{A66C}', '\u{A680}', '\u{A682}', '\u{A684}', '\u{A686}', '\u{A688}', '\u{A68A}', '\u{A68C}', '\u{A68E}', '\u{A690}', '\u{A692}', '\u{A694}', '\u{A696}', '\u{A722}', '\u{A724}', '\u{A726}', '\u{A728}', '\u{A72A}', '\u{A72C}', '\u{A72E}', '\u{A732}', '\u{A734}', '\u{A736}', '\u{A738}', '\u{A73A}', '\u{A73C}', '\u{A73E}', '\u{A740}', '\u{A742}', '\u{A744}', '\u{A746}', '\u{A748}', '\u{A74A}', '\u{A74C}', '\u{A74E}', '\u{A750}', '\u{A752}', '\u{A754}', '\u{A756}', '\u{A758}', '\u{A75A}', '\u{A75C}', '\u{A75E}', '\u{A760}', '\u{A762}', '\u{A764}', '\u{A766}', '\u{A768}', '\u{A76A}', '\u{A76C}', '\u{A76E}', '\u{A779}', '\u{A77B}', '\u{A77D}', '\u{A77E}', '\u{A780}', '\u{A782}', '\u{A784}', '\u{A786}', '\u{A78B}', '\u{FF21}', '\u{FF22}', '\u{FF23}', '\u{FF24}', '\u{FF25}', '\u{FF26}', '\u{FF27}', '\u{FF28}', '\u{FF29}', '\u{FF2A}', '\u{FF2B}', '\u{FF2C}', '\u{FF2D}', '\u{FF2E}', '\u{FF2F}', '\u{FF30}', '\u{FF31}', '\u{FF32}', '\u{FF33}', '\u{FF34}', '\u{FF35}', '\u{FF36}', '\u{FF37}', '\u{FF38}', '\u{FF39}', '\u{FF3A}')
+    }
+
+    fn is_unicode_lowercase_letter(self) -> bool {
+        match_char_class!(self,
+            '\u{0061}', '\u{0062}', '\u{0063}', '\u{0064}', '\u{0065}', '\u{0066}', '\u{0067}', '\u{0068}', '\u{0069}', '\u{006A}', '\u{006B}', '\u{006C}', '\u{006D}', '\u{006E}', '\u{006F}', '\u{0070}', '\u{0071}', '\u{0072}', '\u{0073}', '\u{0074}', '\u{0075}', '\u{0076}', '\u{0077}', '\u{0078}', '\u{0079}', '\u{007A}', '\u{00AA}', '\u{00B5}', '\u{00BA}', '\u{00DF}', '\u{00E0}', '\u{00E1}', '\u{00E2}', '\u{00E3}', '\u{00E4}', '\u{00E5}', '\u{00E6}', '\u{00E7}', '\u{00E8}', '\u{00E9}', '\u{00EA}', '\u{00EB}', '\u{00EC}', '\u{00ED}', '\u{00EE}', '\u{00EF}', '\u{00F0}', '\u{00F1}', '\u{00F2}', '\u{00F3}', '\u{00F4}', '\u{00F5}', '\u{00F6}', '\u{00F8}', '\u{00F9}', '\u{00FA}', '\u{00FB}', '\u{00FC}', '\u{00FD}', '\u{00FE}', '\u{00FF}', '\u{0101}', '\u{0103}', '\u{0105}', '\u{0107}', '\u{0109}', '\u{010B}', '\u{010D}', '\u{010F}', '\u{0111}', '\u{0113}', '\u{0115}', '\u{0117}', '\u{0119}', '\u{011B}', '\u{011D}', '\u{011F}', '\u{0121}', '\u{0123}', '\u{0125}', '\u{0127}', '\u{0129}', '\u{012B}', '\u{012D}', '\u{012F}', '\u{0131}', '\u{0133}', '\u{0135}', '\u{0137}', '\u{0138}', '\u{013A}', '\u{013C}', '\u{013E}', '\u{0140}', '\u{0142}', '\u{0144}', '\u{0146}', '\u{0148}', '\u{0149}', '\u{014B}', '\u{014D}', '\u{014F}', '\u{0151}', '\u{0153}', '\u{0155}', '\u{0157}', '\u{0159}', '\u{015B}', '\u{015D}', '\u{015F}', '\u{0161}', '\u{0163}', '\u{0165}', '\u{0167}', '\u{0169}', '\u{016B}', '\u{016D}', '\u{016F}', '\u{0171}', '\u{0173}', '\u{0175}', '\u{0177}', '\u{017A}', '\u{017C}', '\u{017E}', '\u{017F}', '\u{0180}', '\u{0183}', '\u{0185}', '\u{0188}', '\u{018C}', '\u{018D}', '\u{0192}', '\u{0195}', '\u{0199}', '\u{019A}', '\u{019B}', '\u{019E}', '\u{01A1}', '\u{01A3}', '\u{01A5}', '\u{01A8}', '\u{01AA}', '\u{01AB}', '\u{01AD}', '\u{01B0}', '\u{01B4}', '\u{01B6}', '\u{01B9}', '\u{01BA}', '\u{01BD}', '\u{01BE}', '\u{01BF}', '\u{01C6}', '\u{01C9}', '\u{01CC}', '\u{01CE}', '\u{01D0}', '\u{01D2}', '\u{01D4}', '\u{01D6}', '\u{01D8}', '\u{01DA}', '\u{01DC}', '\u{01DD}', '\u{01DF}', '\u{01E1}', '\u{01E3}', '\u{01E5}', '\u{01E7}', '\u{01E9}', '\u{01EB}', '\u{01ED}', '\u{01EF}', '\u{01F0}', '\u{01F3}', '\u{01F5}', '\u{01F9}', '\u{01FB}', '\u{01FD}', '\u{01FF}', '\u{0201}', '\u{0203}', '\u{0205}', '\u{0207}', '\u{0209}', '\u{020B}', '\u{020D}', '\u{020F}', '\u{0211}', '\u{0213}', '\u{0215}', '\u{0217}', '\u{0219}', '\u{021B}', '\u{021D}', '\u{021F}', '\u{0221}', '\u{0223}', '\u{0225}', '\u{0227}', '\u{0229}', '\u{022B}', '\u{022D}', '\u{022F}', '\u{0231}', '\u{0233}', '\u{0234}', '\u{0235}', '\u{0236}', '\u{0237}', '\u{0238}', '\u{0239}', '\u{023C}', '\u{023F}', '\u{0240}', '\u{0242}', '\u{0247}', '\u{0249}', '\u{024B}', '\u{024D}', '\u{024F}', '\u{0250}', '\u{0251}', '\u{0252}', '\u{0253}', '\u{0254}', '\u{0255}', '\u{0256}', '\u{0257}', '\u{0258}', '\u{0259}', '\u{025A}', '\u{025B}', '\u{025C}', '\u{025D}', '\u{025E}', '\u{025F}', '\u{0260}', '\u{0261}', '\u{0262}', '\u{0263}', '\u{0264}', '\u{0265}', '\u{0266}', '\u{0267}', '\u{0268}', '\u{0269}', '\u{026A}', '\u{026B}', '\u{026C}', '\u{026D}', '\u{026E}', '\u{026F}', '\u{0270}', '\u{0271}', '\u{0272}', '\u{0273}', '\u{0274}', '\u{0275}', '\u{0276}', '\u{0277}', '\u{0278}', '\u{0279}', '\u{027A}', '\u{027B}', '\u{027C}', '\u{027D}', '\u{027E}', '\u{027F}', '\u{0280}', '\u{0281}', '\u{0282}', '\u{0283}', '\u{0284}', '\u{0285}', '\u{0286}', '\u{0287}', '\u{0288}', '\u{0289}', '\u{028A}', '\u{028B}', '\u{028C}', '\u{028D}', '\u{028E}', '\u{028F}', '\u{0290}', '\u{0291}', '\u{0292}', '\u{0293}', '\u{0295}', '\u{0296}', '\u{0297}', '\u{0298}', '\u{0299}', '\u{029A}', '\u{029B}', '\u{029C}', '\u{029D}', '\u{029E}', '\u{029F}', '\u{02A0}', '\u{02A1}', '\u{02A2}', '\u{02A3}', '\u{02A4}', '\u{02A5}', '\u{02A6}', '\u{02A7}', '\u{02A8}', '\u{02A9}', '\u{02AA}', '\u{02AB}', '\u{02AC}', '\u{02AD}', '\u{02AE}', '\u{02AF}', '\u{0371}', '\u{0373}', '\u{0377}', '\u{037B}', '\u{037C}', '\u{037D}', '\u{0390}', '\u{03AC}', '\u{03AD}', '\u{03AE}', '\u{03AF}', '\u{03B0}', '\u{03B1}', '\u{03B2}', '\u{03B3}', '\u{03B4}', '\u{03B5}', '\u{03B6}', '\u{03B7}', '\u{03B8}', '\u{03B9}', '\u{03BA}', '\u{03BB}', '\u{03BC}', '\u{03BD}', '\u{03BE}', '\u{03BF}', '\u{03C0}', '\u{03C1}', '\u{03C2}', '\u{03C3}', '\u{03C4}', '\u{03C5}', '\u{03C6}', '\u{03C7}', '\u{03C8}', '\u{03C9}', '\u{03CA}', '\u{03CB}', '\u{03CC}', '\u{03CD}', '\u{03CE}', '\u{03D0}', '\u{03D1}', '\u{03D5}', '\u{03D6}', '\u{03D7}', '\u{03D9}', '\u{03DB}', '\u{03DD}', '\u{03DF}', '\u{03E1}', '\u{03E3}', '\u{03E5}', '\u{03E7}', '\u{03E9}', '\u{03EB}', '\u{03ED}', '\u{03EF}', '\u{03F0}', '\u{03F1}', '\u{03F2}', '\u{03F3}', '\u{03F5}', '\u{03F8}', '\u{03FB}', '\u{03FC}', '\u{0430}', '\u{0431}', '\u{0432}', '\u{0433}', '\u{0434}', '\u{0435}', '\u{0436}', '\u{0437}', '\u{0438}', '\u{0439}', '\u{043A}', '\u{043B}', '\u{043C}', '\u{043D}', '\u{043E}', '\u{043F}', '\u{0440}', '\u{0441}', '\u{0442}', '\u{0443}', '\u{0444}', '\u{0445}', '\u{0446}', '\u{0447}', '\u{0448}', '\u{0449}', '\u{044A}', '\u{044B}', '\u{044C}', '\u{044D}', '\u{044E}', '\u{044F}', '\u{0450}', '\u{0451}', '\u{0452}', '\u{0453}', '\u{0454}', '\u{0455}', '\u{0456}', '\u{0457}', '\u{0458}', '\u{0459}', '\u{045A}', '\u{045B}', '\u{045C}', '\u{045D}', '\u{045E}', '\u{045F}', '\u{0461}', '\u{0463}', '\u{0465}', '\u{0467}', '\u{0469}', '\u{046B}', '\u{046D}', '\u{046F}', '\u{0471}', '\u{0473}', '\u{0475}', '\u{0477}', '\u{0479}', '\u{047B}', '\u{047D}', '\u{047F}', '\u{0481}', '\u{048B}', '\u{048D}', '\u{048F}', '\u{0491}', '\u{0493}', '\u{0495}', '\u{0497}', '\u{0499}', '\u{049B}', '\u{049D}', '\u{049F}', '\u{04A1}', '\u{04A3}', '\u{04A5}', '\u{04A7}', '\u{04A9}', '\u{04AB}', '\u{04AD}', '\u{04AF}', '\u{04B1}', '\u{04B3}', '\u{04B5}', '\u{04B7}', '\u{04B9}', '\u{04BB}', '\u{04BD}', '\u{04BF}', '\u{04C2}', '\u{04C4}', '\u{04C6}', '\u{04C8}', '\u{04CA}', '\u{04CC}', '\u{04CE}', '\u{04CF}', '\u{04D1}', '\u{04D3}', '\u{04D5}', '\u{04D7}', '\u{04D9}', '\u{04DB}', '\u{04DD}', '\u{04DF}', '\u{04E1}', '\u{04E3}', '\u{04E5}', '\u{04E7}', '\u{04E9}', '\u{04EB}', '\u{04ED}', '\u{04EF}', '\u{04F1}', '\u{04F3}', '\u{04F5}', '\u{04F7}', '\u{04F9}', '\u{04FB}', '\u{04FD}', '\u{04FF}', '\u{0501}', '\u{0503}', '\u{0505}', '\u{0507}', '\u{0509}', '\u{050B}', '\u{050D}', '\u{050F}', '\u{0511}', '\u{0513}', '\u{0515}', '\u{0517}', '\u{0519}', '\u{051B}', '\u{051D}', '\u{051F}', '\u{0521}', '\u{0523}', '\u{0561}', '\u{0562}', '\u{0563}', '\u{0564}', '\u{0565}', '\u{0566}', '\u{0567}', '\u{0568}', '\u{0569}', '\u{056A}', '\u{056B}', '\u{056C}', '\u{056D}', '\u{056E}', '\u{056F}', '\u{0570}', '\u{0571}', '\u{0572}', '\u{0573}', '\u{0574}', '\u{0575}', '\u{0576}', '\u{0577}', '\u{0578}', '\u{0579}', '\u{057A}', '\u{057B}', '\u{057C}', '\u{057D}', '\u{057E}', '\u{057F}', '\u{0580}', '\u{0581}', '\u{0582}', '\u{0583}', '\u{0584}', '\u{0585}', '\u{0586}', '\u{0587}', '\u{1D00}', '\u{1D01}', '\u{1D02}', '\u{1D03}', '\u{1D04}', '\u{1D05}', '\u{1D06}', '\u{1D07}', '\u{1D08}', '\u{1D09}', '\u{1D0A}', '\u{1D0B}', '\u{1D0C}', '\u{1D0D}', '\u{1D0E}', '\u{1D0F}', '\u{1D10}', '\u{1D11}', '\u{1D12}', '\u{1D13}', '\u{1D14}', '\u{1D15}', '\u{1D16}', '\u{1D17}', '\u{1D18}', '\u{1D19}', '\u{1D1A}', '\u{1D1B}', '\u{1D1C}', '\u{1D1D}', '\u{1D1E}', '\u{1D1F}', '\u{1D20}', '\u{1D21}', '\u{1D22}', '\u{1D23}', '\u{1D24}', '\u{1D25}', '\u{1D26}', '\u{1D27}', '\u{1D28}', '\u{1D29}', '\u{1D2A}', '\u{1D2B}', '\u{1D62}', '\u{1D63}', '\u{1D64}', '\u{1D65}', '\u{1D66}', '\u{1D67}', '\u{1D68}', '\u{1D69}', '\u{1D6A}', '\u{1D6B}', '\u{1D6C}', '\u{1D6D}', '\u{1D6E}', '\u{1D6F}', '\u{1D70}', '\u{1D71}', '\u{1D72}', '\u{1D73}', '\u{1D74}', '\u{1D75}', '\u{1D76}', '\u{1D77}', '\u{1D79}', '\u{1D7A}', '\u{1D7B}', '\u{1D7C}', '\u{1D7D}', '\u{1D7E}', '\u{1D7F}', '\u{1D80}', '\u{1D81}', '\u{1D82}', '\u{1D83}', '\u{1D84}', '\u{1D85}', '\u{1D86}', '\u{1D87}', '\u{1D88}', '\u{1D89}', '\u{1D8A}', '\u{1D8B}', '\u{1D8C}', '\u{1D8D}', '\u{1D8E}', '\u{1D8F}', '\u{1D90}', '\u{1D91}', '\u{1D92}', '\u{1D93}', '\u{1D94}', '\u{1D95}', '\u{1D96}', '\u{1D97}', '\u{1D98}', '\u{1D99}', '\u{1D9A}', '\u{1E01}', '\u{1E03}', '\u{1E05}', '\u{1E07}', '\u{1E09}', '\u{1E0B}', '\u{1E0D}', '\u{1E0F}', '\u{1E11}', '\u{1E13}', '\u{1E15}', '\u{1E17}', '\u{1E19}', '\u{1E1B}', '\u{1E1D}', '\u{1E1F}', '\u{1E21}', '\u{1E23}', '\u{1E25}', '\u{1E27}', '\u{1E29}', '\u{1E2B}', '\u{1E2D}', '\u{1E2F}', '\u{1E31}', '\u{1E33}', '\u{1E35}', '\u{1E37}', '\u{1E39}', '\u{1E3B}', '\u{1E3D}', '\u{1E3F}', '\u{1E41}', '\u{1E43}', '\u{1E45}', '\u{1E47}', '\u{1E49}', '\u{1E4B}', '\u{1E4D}', '\u{1E4F}', '\u{1E51}', '\u{1E53}', '\u{1E55}', '\u{1E57}', '\u{1E59}', '\u{1E5B}', '\u{1E5D}', '\u{1E5F}', '\u{1E61}', '\u{1E63}', '\u{1E65}', '\u{1E67}', '\u{1E69}', '\u{1E6B}', '\u{1E6D}', '\u{1E6F}', '\u{1E71}', '\u{1E73}', '\u{1E75}', '\u{1E77}', '\u{1E79}', '\u{1E7B}', '\u{1E7D}', '\u{1E7F}', '\u{1E81}', '\u{1E83}', '\u{1E85}', '\u{1E87}', '\u{1E89}', '\u{1E8B}', '\u{1E8D}', '\u{1E8F}', '\u{1E91}', '\u{1E93}', '\u{1E95}', '\u{1E96}', '\u{1E97}', '\u{1E98}', '\u{1E99}', '\u{1E9A}', '\u{1E9B}', '\u{1E9C}', '\u{1E9D}', '\u{1E9F}', '\u{1EA1}', '\u{1EA3}', '\u{1EA5}', '\u{1EA7}', '\u{1EA9}', '\u{1EAB}', '\u{1EAD}', '\u{1EAF}', '\u{1EB1}', '\u{1EB3}', '\u{1EB5}', '\u{1EB7}', '\u{1EB9}', '\u{1EBB}', '\u{1EBD}', '\u{1EBF}', '\u{1EC1}', '\u{1EC3}', '\u{1EC5}', '\u{1EC7}', '\u{1EC9}', '\u{1ECB}', '\u{1ECD}', '\u{1ECF}', '\u{1ED1}', '\u{1ED3}', '\u{1ED5}', '\u{1ED7}', '\u{1ED9}', '\u{1EDB}', '\u{1EDD}', '\u{1EDF}', '\u{1EE1}', '\u{1EE3}', '\u{1EE5}', '\u{1EE7}', '\u{1EE9}', '\u{1EEB}', '\u{1EED}', '\u{1EEF}', '\u{1EF1}', '\u{1EF3}', '\u{1EF5}', '\u{1EF7}', '\u{1EF9}', '\u{1EFB}', '\u{1EFD}', '\u{1EFF}', '\u{1F00}', '\u{1F01}', '\u{1F02}', '\u{1F03}', '\u{1F04}', '\u{1F05}', '\u{1F06}', '\u{1F07}', '\u{1F10}', '\u{1F11}', '\u{1F12}', '\u{1F13}', '\u{1F14}', '\u{1F15}', '\u{1F20}', '\u{1F21}', '\u{1F22}', '\u{1F23}', '\u{1F24}', '\u{1F25}', '\u{1F26}', '\u{1F27}', '\u{1F30}', '\u{1F31}', '\u{1F32}', '\u{1F33}', '\u{1F34}', '\u{1F35}', '\u{1F36}', '\u{1F37}', '\u{1F40}', '\u{1F41}', '\u{1F42}', '\u{1F43}', '\u{1F44}', '\u{1F45}', '\u{1F50}', '\u{1F51}', '\u{1F52}', '\u{1F53}', '\u{1F54}', '\u{1F55}', '\u{1F56}', '\u{1F57}', '\u{1F60}', '\u{1F61}', '\u{1F62}', '\u{1F63}', '\u{1F64}', '\u{1F65}', '\u{1F66}', '\u{1F67}', '\u{1F70}', '\u{1F71}', '\u{1F72}', '\u{1F73}', '\u{1F74}', '\u{1F75}', '\u{1F76}', '\u{1F77}', '\u{1F78}', '\u{1F79}', '\u{1F7A}', '\u{1F7B}', '\u{1F7C}', '\u{1F7D}', '\u{1F80}', '\u{1F81}', '\u{1F82}', '\u{1F83}', '\u{1F84}', '\u{1F85}', '\u{1F86}', '\u{1F87}', '\u{1F90}', '\u{1F91}', '\u{1F92}', '\u{1F93}', '\u{1F94}', '\u{1F95}', '\u{1F96}', '\u{1F97}', '\u{1FA0}', '\u{1FA1}', '\u{1FA2}', '\u{1FA3}', '\u{1FA4}', '\u{1FA5}', '\u{1FA6}', '\u{1FA7}', '\u{1FB0}', '\u{1FB1}', '\u{1FB2}', '\u{1FB3}', '\u{1FB4}', '\u{1FB6}', '\u{1FB7}', '\u{1FBE}', '\u{1FC2}', '\u{1FC3}', '\u{1FC4}', '\u{1FC6}', '\u{1FC7}', '\u{1FD0}', '\u{1FD1}', '\u{1FD2}', '\u{1FD3}', '\u{1FD6}', '\u{1FD7}', '\u{1FE0}', '\u{1FE1}', '\u{1FE2}', '\u{1FE3}', '\u{1FE4}', '\u{1FE5}', '\u{1FE6}', '\u{1FE7}', '\u{1FF2}', '\u{1FF3}', '\u{1FF4}', '\u{1FF6}', '\u{1FF7}', '\u{2071}', '\u{207F}', '\u{210A}', '\u{210E}', '\u{210F}', '\u{2113}', '\u{212F}', '\u{2134}', '\u{2139}', '\u{213C}', '\u{213D}', '\u{2146}', '\u{2147}', '\u{2148}', '\u{2149}', '\u{214E}', '\u{2184}', '\u{2C30}', '\u{2C31}', '\u{2C32}', '\u{2C33}', '\u{2C34}', '\u{2C35}', '\u{2C36}', '\u{2C37}', '\u{2C38}', '\u{2C39}', '\u{2C3A}', '\u{2C3B}', '\u{2C3C}', '\u{2C3D}', '\u{2C3E}', '\u{2C3F}', '\u{2C40}', '\u{2C41}', '\u{2C42}', '\u{2C43}', '\u{2C44}', '\u{2C45}', '\u{2C46}', '\u{2C47}', '\u{2C48}', '\u{2C49}', '\u{2C4A}', '\u{2C4B}', '\u{2C4C}', '\u{2C4D}', '\u{2C4E}', '\u{2C4F}', '\u{2C50}', '\u{2C51}', '\u{2C52}', '\u{2C53}', '\u{2C54}', '\u{2C55}', '\u{2C56}', '\u{2C57}', '\u{2C58}', '\u{2C59}', '\u{2C5A}', '\u{2C5B}', '\u{2C5C}', '\u{2C5D}', '\u{2C5E}', '\u{2C61}', '\u{2C65}', '\u{2C66}', '\u{2C68}', '\u{2C6A}', '\u{2C6C}', '\u{2C71}', '\u{2C73}', '\u{2C74}', '\u{2C76}', '\u{2C77}', '\u{2C78}', '\u{2C79}', '\u{2C7A}', '\u{2C7B}', '\u{2C7C}', '\u{2C81}', '\u{2C83}', '\u{2C85}', '\u{2C87}', '\u{2C89}', '\u{2C8B}', '\u{2C8D}', '\u{2C8F}', '\u{2C91}', '\u{2C93}', '\u{2C95}', '\u{2C97}', '\u{2C99}', '\u{2C9B}', '\u{2C9D}', '\u{2C9F}', '\u{2CA1}', '\u{2CA3}', '\u{2CA5}', '\u{2CA7}', '\u{2CA9}', '\u{2CAB}', '\u{2CAD}', '\u{2CAF}', '\u{2CB1}', '\u{2CB3}', '\u{2CB5}', '\u{2CB7}', '\u{2CB9}', '\u{2CBB}', '\u{2CBD}', '\u{2CBF}', '\u{2CC1}', '\u{2CC3}', '\u{2CC5}', '\u{2CC7}', '\u{2CC9}', '\u{2CCB}', '\u{2CCD}', '\u{2CCF}', '\u{2CD1}', '\u{2CD3}', '\u{2CD5}', '\u{2CD7}', '\u{2CD9}', '\u{2CDB}', '\u{2CDD}', '\u{2CDF}', '\u{2CE1}', '\u{2CE3}', '\u{2CE4}', '\u{2D00}', '\u{2D01}', '\u{2D02}', '\u{2D03}', '\u{2D04}', '\u{2D05}', '\u{2D06}', '\u{2D07}', '\u{2D08}', '\u{2D09}', '\u{2D0A}', '\u{2D0B}', '\u{2D0C}', '\u{2D0D}', '\u{2D0E}', '\u{2D0F}', '\u{2D10}', '\u{2D11}', '\u{2D12}', '\u{2D13}', '\u{2D14}', '\u{2D15}', '\u{2D16}', '\u{2D17}', '\u{2D18}', '\u{2D19}', '\u{2D1A}', '\u{2D1B}', '\u{2D1C}', '\u{2D1D}', '\u{2D1E}', '\u{2D1F}', '\u{2D20}', '\u{2D21}', '\u{2D22}', '\u{2D23}', '\u{2D24}', '\u{2D25}', '\u{A641}', '\u{A643}', '\u{A645}', '\u{A647}', '\u{A649}', '\u{A64B}', '\u{A64D}', '\u{A64F}', '\u{A651}', '\u{A653}', '\u{A655}', '\u{A657}', '\u{A659}', '\u{A65B}', '\u{A65D}', '\u{A65F}', '\u{A663}', '\u{A665}', '\u{A667}', '\u{A669}', '\u{A66B}', '\u{A66D}', '\u{A681}', '\u{A683}', '\u{A685}', '\u{A687}', '\u{A689}', '\u{A68B}', '\u{A68D}', '\u{A68F}', '\u{A691}', '\u{A693}', '\u{A695}', '\u{A697}', '\u{A723}', '\u{A725}', '\u{A727}', '\u{A729}', '\u{A72B}', '\u{A72D}', '\u{A72F}', '\u{A730}', '\u{A731}', '\u{A733}', '\u{A735}', '\u{A737}', '\u{A739}', '\u{A73B}', '\u{A73D}', '\u{A73F}', '\u{A741}', '\u{A743}', '\u{A745}', '\u{A747}', '\u{A749}', '\u{A74B}', '\u{A74D}', '\u{A74F}', '\u{A751}', '\u{A753}', '\u{A755}', '\u{A757}', '\u{A759}', '\u{A75B}', '\u{A75D}', '\u{A75F}', '\u{A761}', '\u{A763}', '\u{A765}', '\u{A767}', '\u{A769}', '\u{A76B}', '\u{A76D}', '\u{A76F}', '\u{A771}', '\u{A772}', '\u{A773}', '\u{A774}', '\u{A775}', '\u{A776}', '\u{A777}', '\u{A778}', '\u{A77A}', '\u{A77C}', '\u{A77F}', '\u{A781}', '\u{A783}', '\u{A785}', '\u{A787}', '\u{A78C}', '\u{FB00}', '\u{FB01}', '\u{FB02}', '\u{FB03}', '\u{FB04}', '\u{FB05}', '\u{FB06}', '\u{FB13}', '\u{FB14}', '\u{FB15}', '\u{FB16}', '\u{FB17}', '\u{FF41}', '\u{FF42}', '\u{FF43}', '\u{FF44}', '\u{FF45}', '\u{FF46}', '\u{FF47}', '\u{FF48}', '\u{FF49}', '\u{FF4A}', '\u{FF4B}', '\u{FF4C}', '\u{FF4D}', '\u{FF4E}', '\u{FF4F}', '\u{FF50}', '\u{FF51}', '\u{FF52}', '\u{FF53}', '\u{FF54}', '\u{FF55}', '\u{FF56}', '\u{FF57}', '\u{FF58}', '\u{FF59}', '\u{FF5A}')
+
+    }
+
+    fn is_unicode_titlecase_letter(self) -> bool {
+        match_char_class!(self,
+            '\u{01C5}', '\u{01C8}', '\u{01CB}', '\u{01F2}', '\u{1F88}', '\u{1F89}', '\u{1F8A}', '\u{1F8B}', '\u{1F8C}', '\u{1F8D}', '\u{1F8E}', '\u{1F8F}', '\u{1F98}', '\u{1F99}', '\u{1F9A}', '\u{1F9B}', '\u{1F9C}', '\u{1F9D}', '\u{1F9E}', '\u{1F9F}', '\u{1FA8}', '\u{1FA9}', '\u{1FAA}', '\u{1FAB}', '\u{1FAC}', '\u{1FAD}', '\u{1FAE}', '\u{1FAF}', '\u{1FBC}', '\u{1FCC}')
+    }
+
+    fn is_unicode_modifier_letter(self) -> bool {
+        match_char_class!(self,
+            '\u{02B0}', '\u{02B1}', '\u{02B2}', '\u{02B3}', '\u{02B4}', '\u{02B5}', '\u{02B6}', '\u{02B7}', '\u{02B8}', '\u{02B9}', '\u{02BA}', '\u{02BB}', '\u{02BC}', '\u{02BD}', '\u{02BE}', '\u{02BF}', '\u{02C0}', '\u{02C1}', '\u{02C6}', '\u{02C7}', '\u{02C8}', '\u{02C9}', '\u{02CA}', '\u{02CB}', '\u{02CC}', '\u{02CD}', '\u{02CE}', '\u{02CF}', '\u{02D0}', '\u{02D1}', '\u{02E0}', '\u{02E1}', '\u{02E2}', '\u{02E3}', '\u{02E4}', '\u{02EC}', '\u{02EE}', '\u{0374}', '\u{037A}', '\u{0559}', '\u{0640}', '\u{06E5}', '\u{06E6}', '\u{07F4}', '\u{07F5}', '\u{07FA}', '\u{0971}', '\u{0E46}', '\u{0EC6}', '\u{10FC}', '\u{17D7}', '\u{1843}', '\u{1C78}', '\u{1C79}', '\u{1C7A}', '\u{1C7B}', '\u{1C7C}', '\u{1C7D}', '\u{1D2C}', '\u{1D2D}', '\u{1D2E}', '\u{1D2F}', '\u{1D30}', '\u{1D31}', '\u{1D32}', '\u{1D33}', '\u{1D34}', '\u{1D35}', '\u{1D36}', '\u{1D37}', '\u{1D38}', '\u{1D39}', '\u{1D3A}', '\u{1D3B}', '\u{1D3C}', '\u{1D3D}', '\u{1D3E}', '\u{1D3F}', '\u{1D40}', '\u{1D41}', '\u{1D42}', '\u{1D43}', '\u{1D44}', '\u{1D45}', '\u{1D46}', '\u{1D47}', '\u{1D48}', '\u{1D49}', '\u{1D4A}', '\u{1D4B}', '\u{1D4C}', '\u{1D4D}', '\u{1D4E}', '\u{1D4F}', '\u{1D50}', '\u{1D51}', '\u{1D52}', '\u{1D53}', '\u{1D54}', '\u{1D55}', '\u{1D56}', '\u{1D57}', '\u{1D58}', '\u{1D59}', '\u{1D5A}', '\u{1D5B}', '\u{1D5C}', '\u{1D5D}', '\u{1D5E}', '\u{1D5F}', '\u{1D60}', '\u{1D61}', '\u{1D78}', '\u{1D9B}', '\u{1D9C}', '\u{1D9D}', '\u{1D9E}', '\u{1D9F}', '\u{1DA0}', '\u{1DA1}', '\u{1DA2}', '\u{1DA3}', '\u{1DA4}', '\u{1DA5}', '\u{1DA6}', '\u{1DA7}', '\u{1DA8}', '\u{1DA9}', '\u{1DAA}', '\u{1DAB}', '\u{1DAC}', '\u{1DAD}', '\u{1DAE}', '\u{1DAF}', '\u{1DB0}', '\u{1DB1}', '\u{1DB2}', '\u{1DB3}', '\u{1DB4}', '\u{1DB5}', '\u{1DB6}', '\u{1DB7}', '\u{1DB8}', '\u{1DB9}', '\u{1DBA}', '\u{1DBB}', '\u{1DBC}', '\u{1DBD}', '\u{1DBE}', '\u{1DBF}', '\u{2090}', '\u{2091}', '\u{2092}', '\u{2093}', '\u{2094}', '\u{2C7D}', '\u{2D6F}', '\u{2E2F}', '\u{3005}', '\u{3031}', '\u{3032}', '\u{3033}', '\u{3034}', '\u{3035}', '\u{303B}', '\u{309D}', '\u{309E}', '\u{30FC}', '\u{30FD}', '\u{30FE}', '\u{A015}', '\u{A60C}', '\u{A67F}', '\u{A717}', '\u{A718}', '\u{A719}', '\u{A71A}', '\u{A71B}', '\u{A71C}', '\u{A71D}', '\u{A71E}', '\u{A71F}', '\u{A770}', '\u{A788}', '\u{FF70}', '\u{FF9E}', '\u{FF9F}')
+    }
+
+    fn is_unicode_other_letter(self) -> bool {
+        match_char_class!(self,
+             '\u{01BB}', '\u{01C0}', '\u{01C1}', '\u{01C2}', '\u{01C3}', '\u{0294}', '\u{05D0}', '\u{05D1}', '\u{05D2}', '\u{05D3}', '\u{05D4}', '\u{05D5}', '\u{05D6}', '\u{05D7}', '\u{05D8}', '\u{05D9}', '\u{05DA}', '\u{05DB}', '\u{05DC}', '\u{05DD}', '\u{05DE}', '\u{05DF}', '\u{05E0}', '\u{05E1}', '\u{05E2}', '\u{05E3}', '\u{05E4}', '\u{05E5}', '\u{05E6}', '\u{05E7}', '\u{05E8}', '\u{05E9}', '\u{05EA}', '\u{05F0}', '\u{05F1}', '\u{05F2}', '\u{0621}', '\u{0622}', '\u{0623}', '\u{0624}', '\u{0625}', '\u{0626}', '\u{0627}', '\u{0628}', '\u{0629}', '\u{062A}', '\u{062B}', '\u{062C}', '\u{062D}', '\u{062E}', '\u{062F}', '\u{0630}', '\u{0631}', '\u{0632}', '\u{0633}', '\u{0634}', '\u{0635}', '\u{0636}', '\u{0637}', '\u{0638}', '\u{0639}', '\u{063A}', '\u{063B}', '\u{063C}', '\u{063D}', '\u{063E}', '\u{063F}', '\u{0641}', '\u{0642}', '\u{0643}', '\u{0644}', '\u{0645}', '\u{0646}', '\u{0647}', '\u{0648}', '\u{0649}', '\u{064A}', '\u{066E}', '\u{066F}', '\u{0671}', '\u{0672}', '\u{0673}', '\u{0674}', '\u{0675}', '\u{0676}', '\u{0677}', '\u{0678}', '\u{0679}', '\u{067A}', '\u{067B}', '\u{067C}', '\u{067D}', '\u{067E}', '\u{067F}', '\u{0680}', '\u{0681}', '\u{0682}', '\u{0683}', '\u{0684}', '\u{0685}', '\u{0686}', '\u{0687}', '\u{0688}', '\u{0689}', '\u{068A}', '\u{068B}', '\u{068C}', '\u{068D}', '\u{068E}', '\u{068F}', '\u{0690}', '\u{0691}', '\u{0692}', '\u{0693}', '\u{0694}', '\u{0695}', '\u{0696}', '\u{0697}', '\u{0698}', '\u{0699}', '\u{069A}', '\u{069B}', '\u{069C}', '\u{069D}', '\u{069E}', '\u{069F}', '\u{06A0}', '\u{06A1}', '\u{06A2}', '\u{06A3}', '\u{06A4}', '\u{06A5}', '\u{06A6}', '\u{06A7}', '\u{06A8}', '\u{06A9}', '\u{06AA}', '\u{06AB}', '\u{06AC}', '\u{06AD}', '\u{06AE}', '\u{06AF}', '\u{06B0}', '\u{06B1}', '\u{06B2}', '\u{06B3}', '\u{06B4}', '\u{06B5}', '\u{06B6}', '\u{06B7}', '\u{06B8}', '\u{06B9}', '\u{06BA}', '\u{06BB}', '\u{06BC}', '\u{06BD}', '\u{06BE}', '\u{06BF}', '\u{06C0}', '\u{06C1}', '\u{06C2}', '\u{06C3}', '\u{06C4}', '\u{06C5}', '\u{06C6}', '\u{06C7}', '\u{06C8}', '\u{06C9}', '\u{06CA}', '\u{06CB}', '\u{06CC}', '\u{06CD}', '\u{06CE}', '\u{06CF}', '\u{06D0}', '\u{06D1}', '\u{06D2}', '\u{06D3}', '\u{06D5}', '\u{06EE}', '\u{06EF}', '\u{06FA}', '\u{06FB}', '\u{06FC}', '\u{06FF}', '\u{0710}', '\u{0712}', '\u{0713}', '\u{0714}', '\u{0715}', '\u{0716}', '\u{0717}', '\u{0718}', '\u{0719}', '\u{071A}', '\u{071B}', '\u{071C}', '\u{071D}', '\u{071E}', '\u{071F}', '\u{0720}', '\u{0721}', '\u{0722}', '\u{0723}', '\u{0724}', '\u{0725}', '\u{0726}', '\u{0727}', '\u{0728}', '\u{0729}', '\u{072A}', '\u{072B}', '\u{072C}', '\u{072D}', '\u{072E}', '\u{072F}', '\u{074D}', '\u{074E}', '\u{074F}', '\u{0750}', '\u{0751}', '\u{0752}', '\u{0753}', '\u{0754}', '\u{0755}', '\u{0756}', '\u{0757}', '\u{0758}', '\u{0759}', '\u{075A}', '\u{075B}', '\u{075C}', '\u{075D}', '\u{075E}', '\u{075F}', '\u{0760}', '\u{0761}', '\u{0762}', '\u{0763}', '\u{0764}', '\u{0765}', '\u{0766}', '\u{0767}', '\u{0768}', '\u{0769}', '\u{076A}', '\u{076B}', '\u{076C}', '\u{076D}', '\u{076E}', '\u{076F}', '\u{0770}', '\u{0771}', '\u{0772}', '\u{0773}', '\u{0774}', '\u{0775}', '\u{0776}', '\u{0777}', '\u{0778}', '\u{0779}', '\u{077A}', '\u{077B}', '\u{077C}', '\u{077D}', '\u{077E}', '\u{077F}', '\u{0780}', '\u{0781}', '\u{0782}', '\u{0783}', '\u{0784}', '\u{0785}', '\u{0786}', '\u{0787}', '\u{0788}', '\u{0789}', '\u{078A}', '\u{078B}', '\u{078C}', '\u{078D}', '\u{078E}', '\u{078F}', '\u{0790}', '\u{0791}', '\u{0792}', '\u{0793}', '\u{0794}', '\u{0795}', '\u{0796}', '\u{0797}', '\u{0798}', '\u{0799}', '\u{079A}', '\u{079B}', '\u{079C}', '\u{079D}', '\u{079E}', '\u{079F}', '\u{07A0}', '\u{07A1}', '\u{07A2}', '\u{07A3}', '\u{07A4}', '\u{07A5}', '\u{07B1}', '\u{07CA}', '\u{07CB}', '\u{07CC}', '\u{07CD}', '\u{07CE}', '\u{07CF}', '\u{07D0}', '\u{07D1}', '\u{07D2}', '\u{07D3}', '\u{07D4}', '\u{07D5}', '\u{07D6}', '\u{07D7}', '\u{07D8}', '\u{07D9}', '\u{07DA}', '\u{07DB}', '\u{07DC}', '\u{07DD}', '\u{07DE}', '\u{07DF}', '\u{07E0}', '\u{07E1}', '\u{07E2}', '\u{07E3}', '\u{07E4}', '\u{07E5}', '\u{07E6}', '\u{07E7}', '\u{07E8}', '\u{07E9}', '\u{07EA}', '\u{0904}', '\u{0905}', '\u{0906}', '\u{0907}', '\u{0908}', '\u{0909}', '\u{090A}', '\u{090B}', '\u{090C}', '\u{090D}', '\u{090E}', '\u{090F}', '\u{0910}', '\u{0911}', '\u{0912}', '\u{0913}', '\u{0914}', '\u{0915}', '\u{0916}', '\u{0917}', '\u{0918}', '\u{0919}', '\u{091A}', '\u{091B}', '\u{091C}', '\u{091D}', '\u{091E}', '\u{091F}', '\u{0920}', '\u{0921}', '\u{0922}', '\u{0923}', '\u{0924}', '\u{0925}', '\u{0926}', '\u{0927}', '\u{0928}', '\u{0929}', '\u{092A}', '\u{092B}', '\u{092C}', '\u{092D}', '\u{092E}', '\u{092F}', '\u{0930}', '\u{0931}', '\u{0932}', '\u{0933}', '\u{0934}', '\u{0935}', '\u{0936}', '\u{0937}', '\u{0938}', '\u{0939}', '\u{093D}', '\u{0950}', '\u{0958}', '\u{0959}', '\u{095A}', '\u{095B}', '\u{095C}', '\u{095D}', '\u{095E}', '\u{095F}', '\u{0960}', '\u{0961}', '\u{0972}', '\u{097B}', '\u{097C}', '\u{097D}', '\u{097E}', '\u{097F}', '\u{0985}', '\u{0986}', '\u{0987}', '\u{0988}', '\u{0989}', '\u{098A}', '\u{098B}', '\u{098C}', '\u{098F}', '\u{0990}', '\u{0993}', '\u{0994}', '\u{0995}', '\u{0996}', '\u{0997}', '\u{0998}', '\u{0999}', '\u{099A}', '\u{099B}', '\u{099C}', '\u{099D}', '\u{099E}', '\u{099F}', '\u{09A0}', '\u{09A1}', '\u{09A2}', '\u{09A3}', '\u{09A4}', '\u{09A5}', '\u{09A6}', '\u{09A7}', '\u{09A8}', '\u{09AA}', '\u{09AB}', '\u{09AC}', '\u{09AD}', '\u{09AE}', '\u{09AF}', '\u{09B0}', '\u{09B2}', '\u{09B6}', '\u{09B7}', '\u{09B8}', '\u{09B9}', '\u{09BD}', '\u{09CE}', '\u{09DC}', '\u{09DD}', '\u{09DF}', '\u{09E0}', '\u{09E1}', '\u{09F0}', '\u{09F1}', '\u{0A05}', '\u{0A06}', '\u{0A07}', '\u{0A08}', '\u{0A09}', '\u{0A0A}', '\u{0A0F}', '\u{0A10}', '\u{0A13}', '\u{0A14}', '\u{0A15}', '\u{0A16}', '\u{0A17}', '\u{0A18}', '\u{0A19}', '\u{0A1A}', '\u{0A1B}', '\u{0A1C}', '\u{0A1D}', '\u{0A1E}', '\u{0A1F}', '\u{0A20}', '\u{0A21}', '\u{0A22}', '\u{0A23}', '\u{0A24}', '\u{0A25}', '\u{0A26}', '\u{0A27}', '\u{0A28}', '\u{0A2A}', '\u{0A2B}', '\u{0A2C}', '\u{0A2D}', '\u{0A2E}', '\u{0A2F}', '\u{0A30}', '\u{0A32}', '\u{0A33}', '\u{0A35}', '\u{0A36}', '\u{0A38}', '\u{0A39}', '\u{0A59}', '\u{0A5A}', '\u{0A5B}', '\u{0A5C}', '\u{0A5E}', '\u{0A72}', '\u{0A73}', '\u{0A74}', '\u{0A85}', '\u{0A86}', '\u{0A87}', '\u{0A88}', '\u{0A89}', '\u{0A8A}', '\u{0A8B}', '\u{0A8C}', '\u{0A8D}', '\u{0A8F}', '\u{0A90}', '\u{0A91}', '\u{0A93}', '\u{0A94}', '\u{0A95}', '\u{0A96}', '\u{0A97}', '\u{0A98}', '\u{0A99}', '\u{0A9A}', '\u{0A9B}', '\u{0A9C}', '\u{0A9D}', '\u{0A9E}', '\u{0A9F}', '\u{0AA0}', '\u{0AA1}', '\u{0AA2}', '\u{0AA3}', '\u{0AA4}', '\u{0AA5}', '\u{0AA6}', '\u{0AA7}', '\u{0AA8}', '\u{0AAA}', '\u{0AAB}', '\u{0AAC}', '\u{0AAD}', '\u{0AAE}', '\u{0AAF}', '\u{0AB0}', '\u{0AB2}', '\u{0AB3}', '\u{0AB5}', '\u{0AB6}', '\u{0AB7}', '\u{0AB8}', '\u{0AB9}', '\u{0ABD}', '\u{0AD0}', '\u{0AE0}', '\u{0AE1}', '\u{0B05}', '\u{0B06}', '\u{0B07}', '\u{0B08}', '\u{0B09}', '\u{0B0A}', '\u{0B0B}', '\u{0B0C}', '\u{0B0F}', '\u{0B10}', '\u{0B13}', '\u{0B14}', '\u{0B15}', '\u{0B16}', '\u{0B17}', '\u{0B18}', '\u{0B19}', '\u{0B1A}', '\u{0B1B}', '\u{0B1C}', '\u{0B1D}', '\u{0B1E}', '\u{0B1F}', '\u{0B20}', '\u{0B21}', '\u{0B22}', '\u{0B23}', '\u{0B24}', '\u{0B25}', '\u{0B26}', '\u{0B27}', '\u{0B28}', '\u{0B2A}', '\u{0B2B}', '\u{0B2C}', '\u{0B2D}', '\u{0B2E}', '\u{0B2F}', '\u{0B30}', '\u{0B32}', '\u{0B33}', '\u{0B35}', '\u{0B36}', '\u{0B37}', '\u{0B38}', '\u{0B39}', '\u{0B3D}', '\u{0B5C}', '\u{0B5D}', '\u{0B5F}', '\u{0B60}', '\u{0B61}', '\u{0B71}', '\u{0B83}', '\u{0B85}', '\u{0B86}', '\u{0B87}', '\u{0B88}', '\u{0B89}', '\u{0B8A}', '\u{0B8E}', '\u{0B8F}', '\u{0B90}', '\u{0B92}', '\u{0B93}', '\u{0B94}', '\u{0B95}', '\u{0B99}', '\u{0B9A}', '\u{0B9C}', '\u{0B9E}', '\u{0B9F}', '\u{0BA3}', '\u{0BA4}', '\u{0BA8}', '\u{0BA9}', '\u{0BAA}', '\u{0BAE}', '\u{0BAF}', '\u{0BB0}', '\u{0BB1}', '\u{0BB2}', '\u{0BB3}', '\u{0BB4}', '\u{0BB5}', '\u{0BB6}', '\u{0BB7}', '\u{0BB8}', '\u{0BB9}', '\u{0BD0}', '\u{0C05}', '\u{0C06}', '\u{0C07}', '\u{0C08}', '\u{0C09}', '\u{0C0A}', '\u{0C0B}', '\u{0C0C}', '\u{0C0E}', '\u{0C0F}', '\u{0C10}', '\u{0C12}', '\u{0C13}', '\u{0C14}', '\u{0C15}', '\u{0C16}', '\u{0C17}', '\u{0C18}', '\u{0C19}', '\u{0C1A}', '\u{0C1B}', '\u{0C1C}', '\u{0C1D}', '\u{0C1E}', '\u{0C1F}', '\u{0C20}', '\u{0C21}', '\u{0C22}', '\u{0C23}', '\u{0C24}', '\u{0C25}', '\u{0C26}', '\u{0C27}', '\u{0C28}', '\u{0C2A}', '\u{0C2B}', '\u{0C2C}', '\u{0C2D}', '\u{0C2E}', '\u{0C2F}', '\u{0C30}', '\u{0C31}', '\u{0C32}', '\u{0C33}', '\u{0C35}', '\u{0C36}', '\u{0C37}', '\u{0C38}', '\u{0C39}', '\u{0C3D}', '\u{0C58}', '\u{0C59}', '\u{0C60}', '\u{0C61}', '\u{0C85}', '\u{0C86}', '\u{0C87}', '\u{0C88}', '\u{0C89}', '\u{0C8A}', '\u{0C8B}', '\u{0C8C}', '\u{0C8E}', '\u{0C8F}', '\u{0C90}', '\u{0C92}', '\u{0C93}', '\u{0C94}', '\u{0C95}', '\u{0C96}', '\u{0C97}', '\u{0C98}', '\u{0C99}', '\u{0C9A}', '\u{0C9B}', '\u{0C9C}', '\u{0C9D}', '\u{0C9E}', '\u{0C9F}', '\u{0CA0}', '\u{0CA1}', '\u{0CA2}', '\u{0CA3}', '\u{0CA4}', '\u{0CA5}', '\u{0CA6}', '\u{0CA7}', '\u{0CA8}', '\u{0CAA}', '\u{0CAB}', '\u{0CAC}', '\u{0CAD}', '\u{0CAE}', '\u{0CAF}', '\u{0CB0}', '\u{0CB1}', '\u{0CB2}', '\u{0CB3}', '\u{0CB5}', '\u{0CB6}', '\u{0CB7}', '\u{0CB8}', '\u{0CB9}', '\u{0CBD}', '\u{0CDE}', '\u{0CE0}', '\u{0CE1}', '\u{0D05}', '\u{0D06}', '\u{0D07}', '\u{0D08}', '\u{0D09}', '\u{0D0A}', '\u{0D0B}', '\u{0D0C}', '\u{0D0E}', '\u{0D0F}', '\u{0D10}', '\u{0D12}', '\u{0D13}', '\u{0D14}', '\u{0D15}', '\u{0D16}', '\u{0D17}', '\u{0D18}', '\u{0D19}', '\u{0D1A}', '\u{0D1B}', '\u{0D1C}', '\u{0D1D}', '\u{0D1E}', '\u{0D1F}', '\u{0D20}', '\u{0D21}', '\u{0D22}', '\u{0D23}', '\u{0D24}', '\u{0D25}', '\u{0D26}', '\u{0D27}', '\u{0D28}', '\u{0D2A}', '\u{0D2B}', '\u{0D2C}', '\u{0D2D}', '\u{0D2E}', '\u{0D2F}', '\u{0D30}', '\u{0D31}', '\u{0D32}', '\u{0D33}', '\u{0D34}', '\u{0D35}', '\u{0D36}', '\u{0D37}', '\u{0D38}', '\u{0D39}', '\u{0D3D}', '\u{0D60}', '\u{0D61}', '\u{0D7A}', '\u{0D7B}', '\u{0D7C}', '\u{0D7D}', '\u{0D7E}', '\u{0D7F}', '\u{0D85}', '\u{0D86}', '\u{0D87}', '\u{0D88}', '\u{0D89}', '\u{0D8A}', '\u{0D8B}', '\u{0D8C}', '\u{0D8D}', '\u{0D8E}', '\u{0D8F}', '\u{0D90}', '\u{0D91}', '\u{0D92}', '\u{0D93}', '\u{0D94}', '\u{0D95}', '\u{0D96}', '\u{0D9A}', '\u{0D9B}', '\u{0D9C}', '\u{0D9D}', '\u{0D9E}', '\u{0D9F}', '\u{0DA0}', '\u{0DA1}', '\u{0DA2}', '\u{0DA3}', '\u{0DA4}', '\u{0DA5}', '\u{0DA6}', '\u{0DA7}', '\u{0DA8}', '\u{0DA9}', '\u{0DAA}', '\u{0DAB}', '\u{0DAC}', '\u{0DAD}', '\u{0DAE}', '\u{0DAF}', '\u{0DB0}', '\u{0DB1}', '\u{0DB3}', '\u{0DB4}', '\u{0DB5}', '\u{0DB6}', '\u{0DB7}', '\u{0DB8}', '\u{0DB9}', '\u{0DBA}', '\u{0DBB}', '\u{0DBD}', '\u{0DC0}', '\u{0DC1}', '\u{0DC2}', '\u{0DC3}', '\u{0DC4}', '\u{0DC5}', '\u{0DC6}', '\u{0E01}', '\u{0E02}', '\u{0E03}', '\u{0E04}', '\u{0E05}', '\u{0E06}', '\u{0E07}', '\u{0E08}', '\u{0E09}', '\u{0E0A}', '\u{0E0B}', '\u{0E0C}', '\u{0E0D}', '\u{0E0E}', '\u{0E0F}', '\u{0E10}', '\u{0E11}', '\u{0E12}', '\u{0E13}', '\u{0E14}', '\u{0E15}', '\u{0E16}', '\u{0E17}', '\u{0E18}', '\u{0E19}', '\u{0E1A}', '\u{0E1B}', '\u{0E1C}', '\u{0E1D}', '\u{0E1E}', '\u{0E1F}', '\u{0E20}', '\u{0E21}', '\u{0E22}', '\u{0E23}', '\u{0E24}', '\u{0E25}', '\u{0E26}', '\u{0E27}', '\u{0E28}', '\u{0E29}', '\u{0E2A}', '\u{0E2B}', '\u{0E2C}', '\u{0E2D}', '\u{0E2E}', '\u{0E2F}', '\u{0E30}', '\u{0E32}', '\u{0E33}', '\u{0E40}', '\u{0E41}', '\u{0E42}', '\u{0E43}', '\u{0E44}', '\u{0E45}', '\u{0E81}', '\u{0E82}', '\u{0E84}', '\u{0E87}', '\u{0E88}', '\u{0E8A}', '\u{0E8D}', '\u{0E94}', '\u{0E95}', '\u{0E96}', '\u{0E97}', '\u{0E99}', '\u{0E9A}', '\u{0E9B}', '\u{0E9C}', '\u{0E9D}', '\u{0E9E}', '\u{0E9F}', '\u{0EA1}', '\u{0EA2}', '\u{0EA3}', '\u{0EA5}', '\u{0EA7}', '\u{0EAA}', '\u{0EAB}', '\u{0EAD}', '\u{0EAE}', '\u{0EAF}', '\u{0EB0}', '\u{0EB2}', '\u{0EB3}', '\u{0EBD}', '\u{0EC0}', '\u{0EC1}', '\u{0EC2}', '\u{0EC3}', '\u{0EC4}', '\u{0EDC}', '\u{0EDD}', '\u{0F00}', '\u{0F40}', '\u{0F41}', '\u{0F42}', '\u{0F43}', '\u{0F44}', '\u{0F45}', '\u{0F46}', '\u{0F47}', '\u{0F49}', '\u{0F4A}', '\u{0F4B}', '\u{0F4C}', '\u{0F4D}', '\u{0F4E}', '\u{0F4F}', '\u{0F50}', '\u{0F51}', '\u{0F52}', '\u{0F53}', '\u{0F54}', '\u{0F55}', '\u{0F56}', '\u{0F57}', '\u{0F58}', '\u{0F59}', '\u{0F5A}', '\u{0F5B}', '\u{0F5C}', '\u{0F5D}', '\u{0F5E}', '\u{0F5F}', '\u{0F60}', '\u{0F61}', '\u{0F62}', '\u{0F63}', '\u{0F64}', '\u{0F65}', '\u{0F66}', '\u{0F67}', '\u{0F68}', '\u{0F69}', '\u{0F6A}', '\u{0F6B}', '\u{0F6C}', '\u{0F88}', '\u{0F89}', '\u{0F8A}', '\u{0F8B}', '\u{1000}', '\u{1001}', '\u{1002}', '\u{1003}', '\u{1004}', '\u{1005}', '\u{1006}', '\u{1007}', '\u{1008}', '\u{1009}', '\u{100A}', '\u{100B}', '\u{100C}', '\u{100D}', '\u{100E}', '\u{100F}', '\u{1010}', '\u{1011}', '\u{1012}', '\u{1013}', '\u{1014}', '\u{1015}', '\u{1016}', '\u{1017}', '\u{1018}', '\u{1019}', '\u{101A}', '\u{101B}', '\u{101C}', '\u{101D}', '\u{101E}', '\u{101F}', '\u{1020}', '\u{1021}', '\u{1022}', '\u{1023}', '\u{1024}', '\u{1025}', '\u{1026}', '\u{1027}', '\u{1028}', '\u{1029}', '\u{102A}', '\u{103F}', '\u{1050}', '\u{1051}', '\u{1052}', '\u{1053}', '\u{1054}', '\u{1055}', '\u{105A}', '\u{105B}', '\u{105C}', '\u{105D}', '\u{1061}', '\u{1065}', '\u{1066}', '\u{106E}', '\u{106F}', '\u{1070}', '\u{1075}', '\u{1076}', '\u{1077}', '\u{1078}', '\u{1079}', '\u{107A}', '\u{107B}', '\u{107C}', '\u{107D}', '\u{107E}', '\u{107F}', '\u{1080}', '\u{1081}', '\u{108E}', '\u{10D0}', '\u{10D1}', '\u{10D2}', '\u{10D3}', '\u{10D4}', '\u{10D5}', '\u{10D6}', '\u{10D7}', '\u{10D8}', '\u{10D9}', '\u{10DA}', '\u{10DB}', '\u{10DC}', '\u{10DD}', '\u{10DE}', '\u{10DF}', '\u{10E0}', '\u{10E1}', '\u{10E2}', '\u{10E3}', '\u{10E4}', '\u{10E5}', '\u{10E6}', '\u{10E7}', '\u{10E8}', '\u{10E9}', '\u{10EA}', '\u{10EB}', '\u{10EC}', '\u{10ED}', '\u{10EE}', '\u{10EF}', '\u{10F0}', '\u{10F1}', '\u{10F2}', '\u{10F3}', '\u{10F4}', '\u{10F5}', '\u{10F6}', '\u{10F7}', '\u{10F8}', '\u{10F9}', '\u{10FA}', '\u{1100}', '\u{1101}', '\u{1102}', '\u{1103}', '\u{1104}', '\u{1105}', '\u{1106}', '\u{1107}', '\u{1108}', '\u{1109}', '\u{110A}', '\u{110B}', '\u{110C}', '\u{110D}', '\u{110E}', '\u{110F}', '\u{1110}', '\u{1111}', '\u{1112}', '\u{1113}', '\u{1114}', '\u{1115}', '\u{1116}', '\u{1117}', '\u{1118}', '\u{1119}', '\u{111A}', '\u{111B}', '\u{111C}', '\u{111D}', '\u{111E}', '\u{111F}', '\u{1120}', '\u{1121}', '\u{1122}', '\u{1123}', '\u{1124}', '\u{1125}', '\u{1126}', '\u{1127}', '\u{1128}', '\u{1129}', '\u{112A}', '\u{112B}', '\u{112C}', '\u{112D}', '\u{112E}', '\u{112F}', '\u{1130}', '\u{1131}', '\u{1132}', '\u{1133}', '\u{1134}', '\u{1135}', '\u{1136}', '\u{1137}', '\u{1138}', '\u{1139}', '\u{113A}', '\u{113B}', '\u{113C}', '\u{113D}', '\u{113E}', '\u{113F}', '\u{1140}', '\u{1141}', '\u{1142}', '\u{1143}', '\u{1144}', '\u{1145}', '\u{1146}', '\u{1147}', '\u{1148}', '\u{1149}', '\u{114A}', '\u{114B}', '\u{114C}', '\u{114D}', '\u{114E}', '\u{114F}', '\u{1150}', '\u{1151}', '\u{1152}', '\u{1153}', '\u{1154}', '\u{1155}', '\u{1156}', '\u{1157}', '\u{1158}', '\u{1159}', '\u{115F}', '\u{1160}', '\u{1161}', '\u{1162}', '\u{1163}', '\u{1164}', '\u{1165}', '\u{1166}', '\u{1167}', '\u{1168}', '\u{1169}', '\u{116A}', '\u{116B}', '\u{116C}', '\u{116D}', '\u{116E}', '\u{116F}', '\u{1170}', '\u{1171}', '\u{1172}', '\u{1173}', '\u{1174}', '\u{1175}', '\u{1176}', '\u{1177}', '\u{1178}', '\u{1179}', '\u{117A}', '\u{117B}', '\u{117C}', '\u{117D}', '\u{117E}', '\u{117F}', '\u{1180}', '\u{1181}', '\u{1182}', '\u{1183}', '\u{1184}', '\u{1185}', '\u{1186}', '\u{1187}', '\u{1188}', '\u{1189}', '\u{118A}', '\u{118B}', '\u{118C}', '\u{118D}', '\u{118E}', '\u{118F}', '\u{1190}', '\u{1191}', '\u{1192}', '\u{1193}', '\u{1194}', '\u{1195}', '\u{1196}', '\u{1197}', '\u{1198}', '\u{1199}', '\u{119A}', '\u{119B}', '\u{119C}', '\u{119D}', '\u{119E}', '\u{119F}', '\u{11A0}', '\u{11A1}', '\u{11A2}', '\u{11A8}', '\u{11A9}', '\u{11AA}', '\u{11AB}', '\u{11AC}', '\u{11AD}', '\u{11AE}', '\u{11AF}', '\u{11B0}', '\u{11B1}', '\u{11B2}', '\u{11B3}', '\u{11B4}', '\u{11B5}', '\u{11B6}', '\u{11B7}', '\u{11B8}', '\u{11B9}', '\u{11BA}', '\u{11BB}', '\u{11BC}', '\u{11BD}', '\u{11BE}', '\u{11BF}', '\u{11C0}', '\u{11C1}', '\u{11C2}', '\u{11C3}', '\u{11C4}', '\u{11C5}', '\u{11C6}', '\u{11C7}', '\u{11C8}', '\u{11C9}', '\u{11CA}', '\u{11CB}', '\u{11CC}', '\u{11CD}', '\u{11CE}', '\u{11CF}', '\u{11D0}', '\u{11D1}', '\u{11D2}', '\u{11D3}', '\u{11D4}', '\u{11D5}', '\u{11D6}', '\u{11D7}', '\u{11D8}', '\u{11D9}', '\u{11DA}', '\u{11DB}', '\u{11DC}', '\u{11DD}', '\u{11DE}', '\u{11DF}', '\u{11E0}', '\u{11E1}', '\u{11E2}', '\u{11E3}', '\u{11E4}', '\u{11E5}', '\u{11E6}', '\u{11E7}', '\u{11E8}', '\u{11E9}', '\u{11EA}', '\u{11EB}', '\u{11EC}', '\u{11ED}', '\u{11EE}', '\u{11EF}', '\u{11F0}', '\u{11F1}', '\u{11F2}', '\u{11F3}', '\u{11F4}', '\u{11F5}', '\u{11F6}', '\u{11F7}', '\u{11F8}', '\u{11F9}', '\u{1200}', '\u{1201}', '\u{1202}', '\u{1203}', '\u{1204}', '\u{1205}', '\u{1206}', '\u{1207}', '\u{1208}', '\u{1209}', '\u{120A}', '\u{120B}', '\u{120C}', '\u{120D}', '\u{120E}', '\u{120F}', '\u{1210}', '\u{1211}', '\u{1212}', '\u{1213}', '\u{1214}', '\u{1215}', '\u{1216}', '\u{1217}', '\u{1218}', '\u{1219}', '\u{121A}', '\u{121B}', '\u{121C}', '\u{121D}', '\u{121E}', '\u{121F}', '\u{1220}', '\u{1221}', '\u{1222}', '\u{1223}', '\u{1224}', '\u{1225}', '\u{1226}', '\u{1227}', '\u{1228}', '\u{1229}', '\u{122A}', '\u{122B}', '\u{122C}', '\u{122D}', '\u{122E}', '\u{122F}', '\u{1230}', '\u{1231}', '\u{1232}', '\u{1233}', '\u{1234}', '\u{1235}', '\u{1236}', '\u{1237}', '\u{1238}', '\u{1239}', '\u{123A}', '\u{123B}', '\u{123C}', '\u{123D}', '\u{123E}', '\u{123F}', '\u{1240}', '\u{1241}', '\u{1242}', '\u{1243}', '\u{1244}', '\u{1245}', '\u{1246}', '\u{1247}', '\u{1248}', '\u{124A}', '\u{124B}', '\u{124C}', '\u{124D}', '\u{1250}', '\u{1251}', '\u{1252}', '\u{1253}', '\u{1254}', '\u{1255}', '\u{1256}', '\u{1258}', '\u{125A}', '\u{125B}', '\u{125C}', '\u{125D}', '\u{1260}', '\u{1261}', '\u{1262}', '\u{1263}', '\u{1264}', '\u{1265}', '\u{1266}', '\u{1267}', '\u{1268}', '\u{1269}', '\u{126A}', '\u{126B}', '\u{126C}', '\u{126D}', '\u{126E}', '\u{126F}', '\u{1270}', '\u{1271}', '\u{1272}', '\u{1273}', '\u{1274}', '\u{1275}', '\u{1276}', '\u{1277}', '\u{1278}', '\u{1279}', '\u{127A}', '\u{127B}', '\u{127C}', '\u{127D}', '\u{127E}', '\u{127F}', '\u{1280}', '\u{1281}', '\u{1282}', '\u{1283}', '\u{1284}', '\u{1285}', '\u{1286}', '\u{1287}', '\u{1288}', '\u{128A}', '\u{128B}', '\u{128C}', '\u{128D}', '\u{1290}', '\u{1291}', '\u{1292}', '\u{1293}', '\u{1294}', '\u{1295}', '\u{1296}', '\u{1297}', '\u{1298}', '\u{1299}', '\u{129A}', '\u{129B}', '\u{129C}', '\u{129D}', '\u{129E}', '\u{129F}', '\u{12A0}', '\u{12A1}', '\u{12A2}', '\u{12A3}', '\u{12A4}', '\u{12A5}', '\u{12A6}', '\u{12A7}', '\u{12A8}', '\u{12A9}', '\u{12AA}', '\u{12AB}', '\u{12AC}', '\u{12AD}', '\u{12AE}', '\u{12AF}', '\u{12B0}', '\u{12B2}', '\u{12B3}', '\u{12B4}', '\u{12B5}', '\u{12B8}', '\u{12B9}', '\u{12BA}', '\u{12BB}', '\u{12BC}', '\u{12BD}', '\u{12BE}', '\u{12C0}', '\u{12C2}', '\u{12C3}', '\u{12C4}', '\u{12C5}', '\u{12C8}', '\u{12C9}', '\u{12CA}', '\u{12CB}', '\u{12CC}', '\u{12CD}', '\u{12CE}', '\u{12CF}', '\u{12D0}', '\u{12D1}', '\u{12D2}', '\u{12D3}', '\u{12D4}', '\u{12D5}', '\u{12D6}', '\u{12D8}', '\u{12D9}', '\u{12DA}', '\u{12DB}', '\u{12DC}', '\u{12DD}', '\u{12DE}', '\u{12DF}', '\u{12E0}', '\u{12E1}', '\u{12E2}', '\u{12E3}', '\u{12E4}', '\u{12E5}', '\u{12E6}', '\u{12E7}', '\u{12E8}', '\u{12E9}', '\u{12EA}', '\u{12EB}', '\u{12EC}', '\u{12ED}', '\u{12EE}', '\u{12EF}', '\u{12F0}', '\u{12F1}', '\u{12F2}', '\u{12F3}', '\u{12F4}', '\u{12F5}', '\u{12F6}', '\u{12F7}', '\u{12F8}', '\u{12F9}', '\u{12FA}', '\u{12FB}', '\u{12FC}', '\u{12FD}', '\u{12FE}', '\u{12FF}', '\u{1300}', '\u{1301}', '\u{1302}', '\u{1303}', '\u{1304}', '\u{1305}', '\u{1306}', '\u{1307}', '\u{1308}', '\u{1309}', '\u{130A}', '\u{130B}', '\u{130C}', '\u{130D}', '\u{130E}', '\u{130F}', '\u{1310}', '\u{1312}', '\u{1313}', '\u{1314}', '\u{1315}', '\u{1318}', '\u{1319}', '\u{131A}', '\u{131B}', '\u{131C}', '\u{131D}', '\u{131E}', '\u{131F}', '\u{1320}', '\u{1321}', '\u{1322}', '\u{1323}', '\u{1324}', '\u{1325}', '\u{1326}', '\u{1327}', '\u{1328}', '\u{1329}', '\u{132A}', '\u{132B}', '\u{132C}', '\u{132D}', '\u{132E}', '\u{132F}', '\u{1330}', '\u{1331}', '\u{1332}', '\u{1333}', '\u{1334}', '\u{1335}', '\u{1336}', '\u{1337}', '\u{1338}', '\u{1339}', '\u{133A}', '\u{133B}', '\u{133C}', '\u{133D}', '\u{133E}', '\u{133F}', '\u{1340}', '\u{1341}', '\u{1342}', '\u{1343}', '\u{1344}', '\u{1345}', '\u{1346}', '\u{1347}', '\u{1348}', '\u{1349}', '\u{134A}', '\u{134B}', '\u{134C}', '\u{134D}', '\u{134E}', '\u{134F}', '\u{1350}', '\u{1351}', '\u{1352}', '\u{1353}', '\u{1354}', '\u{1355}', '\u{1356}', '\u{1357}', '\u{1358}', '\u{1359}', '\u{135A}', '\u{1380}', '\u{1381}', '\u{1382}', '\u{1383}', '\u{1384}', '\u{1385}', '\u{1386}', '\u{1387}', '\u{1388}', '\u{1389}', '\u{138A}', '\u{138B}', '\u{138C}', '\u{138D}', '\u{138E}', '\u{138F}', '\u{13A0}', '\u{13A1}', '\u{13A2}', '\u{13A3}', '\u{13A4}', '\u{13A5}', '\u{13A6}', '\u{13A7}', '\u{13A8}', '\u{13A9}', '\u{13AA}', '\u{13AB}', '\u{13AC}', '\u{13AD}', '\u{13AE}', '\u{13AF}', '\u{13B0}', '\u{13B1}', '\u{13B2}', '\u{13B3}', '\u{13B4}', '\u{13B5}', '\u{13B6}', '\u{13B7}', '\u{13B8}', '\u{13B9}', '\u{13BA}', '\u{13BB}', '\u{13BC}', '\u{13BD}', '\u{13BE}', '\u{13BF}', '\u{13C0}', '\u{13C1}', '\u{13C2}', '\u{13C3}', '\u{13C4}', '\u{13C5}', '\u{13C6}', '\u{13C7}', '\u{13C8}', '\u{13C9}', '\u{13CA}', '\u{13CB}', '\u{13CC}', '\u{13CD}', '\u{13CE}', '\u{13CF}', '\u{13D0}', '\u{13D1}', '\u{13D2}', '\u{13D3}', '\u{13D4}', '\u{13D5}', '\u{13D6}', '\u{13D7}', '\u{13D8}', '\u{13D9}', '\u{13DA}', '\u{13DB}', '\u{13DC}', '\u{13DD}', '\u{13DE}', '\u{13DF}', '\u{13E0}', '\u{13E1}', '\u{13E2}', '\u{13E3}', '\u{13E4}', '\u{13E5}', '\u{13E6}', '\u{13E7}', '\u{13E8}', '\u{13E9}', '\u{13EA}', '\u{13EB}', '\u{13EC}', '\u{13ED}', '\u{13EE}', '\u{13EF}', '\u{13F0}', '\u{13F1}', '\u{13F2}', '\u{13F3}', '\u{13F4}', '\u{1401}', '\u{1402}', '\u{1403}', '\u{1404}', '\u{1405}', '\u{1406}', '\u{1407}', '\u{1408}', '\u{1409}', '\u{140A}', '\u{140B}', '\u{140C}', '\u{140D}', '\u{140E}', '\u{140F}', '\u{1410}', '\u{1411}', '\u{1412}', '\u{1413}', '\u{1414}', '\u{1415}', '\u{1416}', '\u{1417}', '\u{1418}', '\u{1419}', '\u{141A}', '\u{141B}', '\u{141C}', '\u{141D}', '\u{141E}', '\u{141F}', '\u{1420}', '\u{1421}', '\u{1422}', '\u{1423}', '\u{1424}', '\u{1425}', '\u{1426}', '\u{1427}', '\u{1428}', '\u{1429}', '\u{142A}', '\u{142B}', '\u{142C}', '\u{142D}', '\u{142E}', '\u{142F}', '\u{1430}', '\u{1431}', '\u{1432}', '\u{1433}', '\u{1434}', '\u{1435}', '\u{1436}', '\u{1437}', '\u{1438}', '\u{1439}', '\u{143A}', '\u{143B}', '\u{143C}', '\u{143D}', '\u{143E}', '\u{143F}', '\u{1440}', '\u{1441}', '\u{1442}', '\u{1443}', '\u{1444}', '\u{1445}', '\u{1446}', '\u{1447}', '\u{1448}', '\u{1449}', '\u{144A}', '\u{144B}', '\u{144C}', '\u{144D}', '\u{144E}', '\u{144F}', '\u{1450}', '\u{1451}', '\u{1452}', '\u{1453}', '\u{1454}', '\u{1455}', '\u{1456}', '\u{1457}', '\u{1458}', '\u{1459}', '\u{145A}', '\u{145B}', '\u{145C}', '\u{145D}', '\u{145E}', '\u{145F}', '\u{1460}', '\u{1461}', '\u{1462}', '\u{1463}', '\u{1464}', '\u{1465}', '\u{1466}', '\u{1467}', '\u{1468}', '\u{1469}', '\u{146A}', '\u{146B}', '\u{146C}', '\u{146D}', '\u{146E}', '\u{146F}', '\u{1470}', '\u{1471}', '\u{1472}', '\u{1473}', '\u{1474}', '\u{1475}', '\u{1476}', '\u{1477}', '\u{1478}', '\u{1479}', '\u{147A}', '\u{147B}', '\u{147C}', '\u{147D}', '\u{147E}', '\u{147F}', '\u{1480}', '\u{1481}', '\u{1482}', '\u{1483}', '\u{1484}', '\u{1485}', '\u{1486}', '\u{1487}', '\u{1488}', '\u{1489}', '\u{148A}', '\u{148B}', '\u{148C}', '\u{148D}', '\u{148E}', '\u{148F}', '\u{1490}', '\u{1491}', '\u{1492}', '\u{1493}', '\u{1494}', '\u{1495}', '\u{1496}', '\u{1497}', '\u{1498}', '\u{1499}', '\u{149A}', '\u{149B}', '\u{149C}', '\u{149D}', '\u{149E}', '\u{149F}', '\u{14A0}', '\u{14A1}', '\u{14A2}', '\u{14A3}', '\u{14A4}', '\u{14A5}', '\u{14A6}', '\u{14A7}', '\u{14A8}', '\u{14A9}', '\u{14AA}', '\u{14AB}', '\u{14AC}', '\u{14AD}', '\u{14AE}', '\u{14AF}', '\u{14B0}', '\u{14B1}', '\u{14B2}', '\u{14B3}', '\u{14B4}', '\u{14B5}', '\u{14B6}', '\u{14B7}', '\u{14B8}', '\u{14B9}', '\u{14BA}', '\u{14BB}', '\u{14BC}', '\u{14BD}', '\u{14BE}', '\u{14BF}', '\u{14C0}', '\u{14C1}', '\u{14C2}', '\u{14C3}', '\u{14C4}', '\u{14C5}', '\u{14C6}', '\u{14C7}', '\u{14C8}', '\u{14C9}', '\u{14CA}', '\u{14CB}', '\u{14CC}', '\u{14CD}', '\u{14CE}', '\u{14CF}', '\u{14D0}', '\u{14D1}', '\u{14D2}', '\u{14D3}', '\u{14D4}', '\u{14D5}', '\u{14D6}', '\u{14D7}', '\u{14D8}', '\u{14D9}', '\u{14DA}', '\u{14DB}', '\u{14DC}', '\u{14DD}', '\u{14DE}', '\u{14DF}', '\u{14E0}', '\u{14E1}', '\u{14E2}', '\u{14E3}', '\u{14E4}', '\u{14E5}', '\u{14E6}', '\u{14E7}', '\u{14E8}', '\u{14E9}', '\u{14EA}', '\u{14EB}', '\u{14EC}', '\u{14ED}', '\u{14EE}', '\u{14EF}', '\u{14F0}', '\u{14F1}', '\u{14F2}', '\u{14F3}', '\u{14F4}', '\u{14F5}', '\u{14F6}', '\u{14F7}', '\u{14F8}', '\u{14F9}', '\u{14FA}', '\u{14FB}', '\u{14FC}', '\u{14FD}', '\u{14FE}', '\u{14FF}', '\u{1500}', '\u{1501}', '\u{1502}', '\u{1503}', '\u{1504}', '\u{1505}', '\u{1506}', '\u{1507}', '\u{1508}', '\u{1509}', '\u{150A}', '\u{150B}', '\u{150C}', '\u{150D}', '\u{150E}', '\u{150F}', '\u{1510}', '\u{1511}', '\u{1512}', '\u{1513}', '\u{1514}', '\u{1515}', '\u{1516}', '\u{1517}', '\u{1518}', '\u{1519}', '\u{151A}', '\u{151B}', '\u{151C}', '\u{151D}', '\u{151E}', '\u{151F}', '\u{1520}', '\u{1521}', '\u{1522}', '\u{1523}', '\u{1524}', '\u{1525}', '\u{1526}', '\u{1527}', '\u{1528}', '\u{1529}', '\u{152A}', '\u{152B}', '\u{152C}', '\u{152D}', '\u{152E}', '\u{152F}', '\u{1530}', '\u{1531}', '\u{1532}', '\u{1533}', '\u{1534}', '\u{1535}', '\u{1536}', '\u{1537}', '\u{1538}', '\u{1539}', '\u{153A}', '\u{153B}', '\u{153C}', '\u{153D}', '\u{153E}', '\u{153F}', '\u{1540}', '\u{1541}', '\u{1542}', '\u{1543}', '\u{1544}', '\u{1545}', '\u{1546}', '\u{1547}', '\u{1548}', '\u{1549}', '\u{154A}', '\u{154B}', '\u{154C}', '\u{154D}', '\u{154E}', '\u{154F}', '\u{1550}', '\u{1551}', '\u{1552}', '\u{1553}', '\u{1554}', '\u{1555}', '\u{1556}', '\u{1557}', '\u{1558}', '\u{1559}', '\u{155A}', '\u{155B}', '\u{155C}', '\u{155D}', '\u{155E}', '\u{155F}', '\u{1560}', '\u{1561}', '\u{1562}', '\u{1563}', '\u{1564}', '\u{1565}', '\u{1566}', '\u{1567}', '\u{1568}', '\u{1569}', '\u{156A}', '\u{156B}', '\u{156C}', '\u{156D}', '\u{156E}', '\u{156F}', '\u{1570}', '\u{1571}', '\u{1572}', '\u{1573}', '\u{1574}', '\u{1575}', '\u{1576}', '\u{1577}', '\u{1578}', '\u{1579}', '\u{157A}', '\u{157B}', '\u{157C}', '\u{157D}', '\u{157E}', '\u{157F}', '\u{1580}', '\u{1581}', '\u{1582}', '\u{1583}', '\u{1584}', '\u{1585}', '\u{1586}', '\u{1587}', '\u{1588}', '\u{1589}', '\u{158A}', '\u{158B}', '\u{158C}', '\u{158D}', '\u{158E}', '\u{158F}', '\u{1590}', '\u{1591}', '\u{1592}', '\u{1593}', '\u{1594}', '\u{1595}', '\u{1596}', '\u{1597}', '\u{1598}', '\u{1599}', '\u{159A}', '\u{159B}', '\u{159C}', '\u{159D}', '\u{159E}', '\u{159F}', '\u{15A0}', '\u{15A1}', '\u{15A2}', '\u{15A3}', '\u{15A4}', '\u{15A5}', '\u{15A6}', '\u{15A7}', '\u{15A8}', '\u{15A9}', '\u{15AA}', '\u{15AB}', '\u{15AC}', '\u{15AD}', '\u{15AE}', '\u{15AF}', '\u{15B0}', '\u{15B1}', '\u{15B2}', '\u{15B3}', '\u{15B4}', '\u{15B5}', '\u{15B6}', '\u{15B7}', '\u{15B8}', '\u{15B9}', '\u{15BA}', '\u{15BB}', '\u{15BC}', '\u{15BD}', '\u{15BE}', '\u{15BF}', '\u{15C0}', '\u{15C1}', '\u{15C2}', '\u{15C3}', '\u{15C4}', '\u{15C5}', '\u{15C6}', '\u{15C7}', '\u{15C8}', '\u{15C9}', '\u{15CA}', '\u{15CB}', '\u{15CC}', '\u{15CD}', '\u{15CE}', '\u{15CF}', '\u{15D0}', '\u{15D1}', '\u{15D2}', '\u{15D3}', '\u{15D4}', '\u{15D5}', '\u{15D6}', '\u{15D7}', '\u{15D8}', '\u{15D9}', '\u{15DA}', '\u{15DB}', '\u{15DC}', '\u{15DD}', '\u{15DE}', '\u{15DF}', '\u{15E0}', '\u{15E1}', '\u{15E2}', '\u{15E3}', '\u{15E4}', '\u{15E5}', '\u{15E6}', '\u{15E7}', '\u{15E8}', '\u{15E9}', '\u{15EA}', '\u{15EB}', '\u{15EC}', '\u{15ED}', '\u{15EE}', '\u{15EF}', '\u{15F0}', '\u{15F1}', '\u{15F2}', '\u{15F3}', '\u{15F4}', '\u{15F5}', '\u{15F6}', '\u{15F7}', '\u{15F8}', '\u{15F9}', '\u{15FA}', '\u{15FB}', '\u{15FC}', '\u{15FD}', '\u{15FE}', '\u{15FF}', '\u{1600}', '\u{1601}', '\u{1602}', '\u{1603}', '\u{1604}', '\u{1605}', '\u{1606}', '\u{1607}', '\u{1608}', '\u{1609}', '\u{160A}', '\u{160B}', '\u{160C}', '\u{160D}', '\u{160E}', '\u{160F}', '\u{1610}', '\u{1611}', '\u{1612}', '\u{1613}', '\u{1614}', '\u{1615}', '\u{1616}', '\u{1617}', '\u{1618}', '\u{1619}', '\u{161A}', '\u{161B}', '\u{161C}', '\u{161D}', '\u{161E}', '\u{161F}', '\u{1620}', '\u{1621}', '\u{1622}', '\u{1623}', '\u{1624}', '\u{1625}', '\u{1626}', '\u{1627}', '\u{1628}', '\u{1629}', '\u{162A}', '\u{162B}', '\u{162C}', '\u{162D}', '\u{162E}', '\u{162F}', '\u{1630}', '\u{1631}', '\u{1632}', '\u{1633}', '\u{1634}', '\u{1635}', '\u{1636}', '\u{1637}', '\u{1638}', '\u{1639}', '\u{163A}', '\u{163B}', '\u{163C}', '\u{163D}', '\u{163E}', '\u{163F}', '\u{1640}', '\u{1641}', '\u{1642}', '\u{1643}', '\u{1644}', '\u{1645}', '\u{1646}', '\u{1647}', '\u{1648}', '\u{1649}', '\u{164A}', '\u{164B}', '\u{164C}', '\u{164D}', '\u{164E}', '\u{164F}', '\u{1650}', '\u{1651}', '\u{1652}', '\u{1653}', '\u{1654}', '\u{1655}', '\u{1656}', '\u{1657}', '\u{1658}', '\u{1659}', '\u{165A}', '\u{165B}', '\u{165C}', '\u{165D}', '\u{165E}', '\u{165F}', '\u{1660}', '\u{1661}', '\u{1662}', '\u{1663}', '\u{1664}', '\u{1665}', '\u{1666}', '\u{1667}', '\u{1668}', '\u{1669}', '\u{166A}', '\u{166B}', '\u{166C}', '\u{166F}', '\u{1670}', '\u{1671}', '\u{1672}', '\u{1673}', '\u{1674}', '\u{1675}', '\u{1676}', '\u{1681}', '\u{1682}', '\u{1683}', '\u{1684}', '\u{1685}', '\u{1686}', '\u{1687}', '\u{1688}', '\u{1689}', '\u{168A}', '\u{168B}', '\u{168C}', '\u{168D}', '\u{168E}', '\u{168F}', '\u{1690}', '\u{1691}', '\u{1692}', '\u{1693}', '\u{1694}', '\u{1695}', '\u{1696}', '\u{1697}', '\u{1698}', '\u{1699}', '\u{169A}', '\u{16A0}', '\u{16A1}', '\u{16A2}', '\u{16A3}', '\u{16A4}', '\u{16A5}', '\u{16A6}', '\u{16A7}', '\u{16A8}', '\u{16A9}', '\u{16AA}', '\u{16AB}', '\u{16AC}', '\u{16AD}', '\u{16AE}', '\u{16AF}', '\u{16B0}', '\u{16B1}', '\u{16B2}', '\u{16B3}', '\u{16B4}', '\u{16B5}', '\u{16B6}', '\u{16B7}', '\u{16B8}', '\u{16B9}', '\u{16BA}', '\u{16BB}', '\u{16BC}', '\u{16BD}', '\u{16BE}', '\u{16BF}', '\u{16C0}', '\u{16C1}', '\u{16C2}', '\u{16C3}', '\u{16C4}', '\u{16C5}', '\u{16C6}', '\u{16C7}', '\u{16C8}', '\u{16C9}', '\u{16CA}', '\u{16CB}', '\u{16CC}', '\u{16CD}', '\u{16CE}', '\u{16CF}', '\u{16D0}', '\u{16D1}', '\u{16D2}', '\u{16D3}', '\u{16D4}', '\u{16D5}', '\u{16D6}', '\u{16D7}', '\u{16D8}', '\u{16D9}', '\u{16DA}', '\u{16DB}', '\u{16DC}', '\u{16DD}', '\u{16DE}', '\u{16DF}', '\u{16E0}', '\u{16E1}', '\u{16E2}', '\u{16E3}', '\u{16E4}', '\u{16E5}', '\u{16E6}', '\u{16E7}', '\u{16E8}', '\u{16E9}', '\u{16EA}', '\u{1700}', '\u{1701}', '\u{1702}', '\u{1703}', '\u{1704}', '\u{1705}', '\u{1706}', '\u{1707}', '\u{1708}', '\u{1709}', '\u{170A}', '\u{170B}', '\u{170C}', '\u{170E}', '\u{170F}', '\u{1710}', '\u{1711}', '\u{1720}', '\u{1721}', '\u{1722}', '\u{1723}', '\u{1724}', '\u{1725}', '\u{1726}', '\u{1727}', '\u{1728}', '\u{1729}', '\u{172A}', '\u{172B}', '\u{172C}', '\u{172D}', '\u{172E}', '\u{172F}', '\u{1730}', '\u{1731}', '\u{1740}', '\u{1741}', '\u{1742}', '\u{1743}', '\u{1744}', '\u{1745}', '\u{1746}', '\u{1747}', '\u{1748}', '\u{1749}', '\u{174A}', '\u{174B}', '\u{174C}', '\u{174D}', '\u{174E}', '\u{174F}', '\u{1750}', '\u{1751}', '\u{1760}', '\u{1761}', '\u{1762}', '\u{1763}', '\u{1764}', '\u{1765}', '\u{1766}', '\u{1767}', '\u{1768}', '\u{1769}', '\u{176A}', '\u{176B}', '\u{176C}', '\u{176E}', '\u{176F}', '\u{1770}', '\u{1780}', '\u{1781}', '\u{1782}', '\u{1783}', '\u{1784}', '\u{1785}', '\u{1786}', '\u{1787}', '\u{1788}', '\u{1789}', '\u{178A}', '\u{178B}', '\u{178C}', '\u{178D}', '\u{178E}', '\u{178F}', '\u{1790}', '\u{1791}', '\u{1792}', '\u{1793}', '\u{1794}', '\u{1795}', '\u{1796}', '\u{1797}', '\u{1798}', '\u{1799}', '\u{179A}', '\u{179B}', '\u{179C}', '\u{179D}', '\u{179E}', '\u{179F}', '\u{17A0}', '\u{17A1}', '\u{17A2}', '\u{17A3}', '\u{17A4}', '\u{17A5}', '\u{17A6}', '\u{17A7}', '\u{17A8}', '\u{17A9}', '\u{17AA}', '\u{17AB}', '\u{17AC}', '\u{17AD}', '\u{17AE}', '\u{17AF}', '\u{17B0}', '\u{17B1}', '\u{17B2}', '\u{17B3}', '\u{17DC}', '\u{1820}', '\u{1821}', '\u{1822}', '\u{1823}', '\u{1824}', '\u{1825}', '\u{1826}', '\u{1827}', '\u{1828}', '\u{1829}', '\u{182A}', '\u{182B}', '\u{182C}', '\u{182D}', '\u{182E}', '\u{182F}', '\u{1830}', '\u{1831}', '\u{1832}', '\u{1833}', '\u{1834}', '\u{1835}', '\u{1836}', '\u{1837}', '\u{1838}', '\u{1839}', '\u{183A}', '\u{183B}', '\u{183C}', '\u{183D}', '\u{183E}', '\u{183F}', '\u{1840}', '\u{1841}', '\u{1842}', '\u{1844}', '\u{1845}', '\u{1846}', '\u{1847}', '\u{1848}', '\u{1849}', '\u{184A}', '\u{184B}', '\u{184C}', '\u{184D}', '\u{184E}', '\u{184F}', '\u{1850}', '\u{1851}', '\u{1852}', '\u{1853}', '\u{1854}', '\u{1855}', '\u{1856}', '\u{1857}', '\u{1858}', '\u{1859}', '\u{185A}', '\u{185B}', '\u{185C}', '\u{185D}', '\u{185E}', '\u{185F}', '\u{1860}', '\u{1861}', '\u{1862}', '\u{1863}', '\u{1864}', '\u{1865}', '\u{1866}', '\u{1867}', '\u{1868}', '\u{1869}', '\u{186A}', '\u{186B}', '\u{186C}', '\u{186D}', '\u{186E}', '\u{186F}', '\u{1870}', '\u{1871}', '\u{1872}', '\u{1873}', '\u{1874}', '\u{1875}', '\u{1876}', '\u{1877}', '\u{1880}', '\u{1881}', '\u{1882}', '\u{1883}', '\u{1884}', '\u{1885}', '\u{1886}', '\u{1887}', '\u{1888}', '\u{1889}', '\u{188A}', '\u{188B}', '\u{188C}', '\u{188D}', '\u{188E}', '\u{188F}', '\u{1890}', '\u{1891}', '\u{1892}', '\u{1893}', '\u{1894}', '\u{1895}', '\u{1896}', '\u{1897}', '\u{1898}', '\u{1899}', '\u{189A}', '\u{189B}', '\u{189C}', '\u{189D}', '\u{189E}', '\u{189F}', '\u{18A0}', '\u{18A1}', '\u{18A2}', '\u{18A3}', '\u{18A4}', '\u{18A5}', '\u{18A6}', '\u{18A7}', '\u{18A8}', '\u{18AA}', '\u{1900}', '\u{1901}', '\u{1902}', '\u{1903}', '\u{1904}', '\u{1905}', '\u{1906}', '\u{1907}', '\u{1908}', '\u{1909}', '\u{190A}', '\u{190B}', '\u{190C}', '\u{190D}', '\u{190E}', '\u{190F}', '\u{1910}', '\u{1911}', '\u{1912}', '\u{1913}', '\u{1914}', '\u{1915}', '\u{1916}', '\u{1917}', '\u{1918}', '\u{1919}', '\u{191A}', '\u{191B}', '\u{191C}', '\u{1950}', '\u{1951}', '\u{1952}', '\u{1953}', '\u{1954}', '\u{1955}', '\u{1956}', '\u{1957}', '\u{1958}', '\u{1959}', '\u{195A}', '\u{195B}', '\u{195C}', '\u{195D}', '\u{195E}', '\u{195F}', '\u{1960}', '\u{1961}', '\u{1962}', '\u{1963}', '\u{1964}', '\u{1965}', '\u{1966}', '\u{1967}', '\u{1968}', '\u{1969}', '\u{196A}', '\u{196B}', '\u{196C}', '\u{196D}', '\u{1970}', '\u{1971}', '\u{1972}', '\u{1973}', '\u{1974}', '\u{1980}', '\u{1981}', '\u{1982}', '\u{1983}', '\u{1984}', '\u{1985}', '\u{1986}', '\u{1987}', '\u{1988}', '\u{1989}', '\u{198A}', '\u{198B}', '\u{198C}', '\u{198D}', '\u{198E}', '\u{198F}', '\u{1990}', '\u{1991}', '\u{1992}', '\u{1993}', '\u{1994}', '\u{1995}', '\u{1996}', '\u{1997}', '\u{1998}', '\u{1999}', '\u{199A}', '\u{199B}', '\u{199C}', '\u{199D}', '\u{199E}', '\u{199F}', '\u{19A0}', '\u{19A1}', '\u{19A2}', '\u{19A3}', '\u{19A4}', '\u{19A5}', '\u{19A6}', '\u{19A7}', '\u{19A8}', '\u{19A9}', '\u{19C1}', '\u{19C2}', '\u{19C3}', '\u{19C4}', '\u{19C5}', '\u{19C6}', '\u{19C7}', '\u{1A00}', '\u{1A01}', '\u{1A02}', '\u{1A03}', '\u{1A04}', '\u{1A05}', '\u{1A06}', '\u{1A07}', '\u{1A08}', '\u{1A09}', '\u{1A0A}', '\u{1A0B}', '\u{1A0C}', '\u{1A0D}', '\u{1A0E}', '\u{1A0F}', '\u{1A10}', '\u{1A11}', '\u{1A12}', '\u{1A13}', '\u{1A14}', '\u{1A15}', '\u{1A16}', '\u{1B05}', '\u{1B06}', '\u{1B07}', '\u{1B08}', '\u{1B09}', '\u{1B0A}', '\u{1B0B}', '\u{1B0C}', '\u{1B0D}', '\u{1B0E}', '\u{1B0F}', '\u{1B10}', '\u{1B11}', '\u{1B12}', '\u{1B13}', '\u{1B14}', '\u{1B15}', '\u{1B16}', '\u{1B17}', '\u{1B18}', '\u{1B19}', '\u{1B1A}', '\u{1B1B}', '\u{1B1C}', '\u{1B1D}', '\u{1B1E}', '\u{1B1F}', '\u{1B20}', '\u{1B21}', '\u{1B22}', '\u{1B23}', '\u{1B24}', '\u{1B25}', '\u{1B26}', '\u{1B27}', '\u{1B28}', '\u{1B29}', '\u{1B2A}', '\u{1B2B}', '\u{1B2C}', '\u{1B2D}', '\u{1B2E}', '\u{1B2F}', '\u{1B30}', '\u{1B31}', '\u{1B32}', '\u{1B33}', '\u{1B45}', '\u{1B46}', '\u{1B47}', '\u{1B48}', '\u{1B49}', '\u{1B4A}', '\u{1B4B}', '\u{1B83}', '\u{1B84}', '\u{1B85}', '\u{1B86}', '\u{1B87}', '\u{1B88}', '\u{1B89}', '\u{1B8A}', '\u{1B8B}', '\u{1B8C}', '\u{1B8D}', '\u{1B8E}', '\u{1B8F}', '\u{1B90}', '\u{1B91}', '\u{1B92}', '\u{1B93}', '\u{1B94}', '\u{1B95}', '\u{1B96}', '\u{1B97}', '\u{1B98}', '\u{1B99}', '\u{1B9A}', '\u{1B9B}', '\u{1B9C}', '\u{1B9D}', '\u{1B9E}', '\u{1B9F}', '\u{1BA0}', '\u{1BAE}', '\u{1BAF}', '\u{1C00}', '\u{1C01}', '\u{1C02}', '\u{1C03}', '\u{1C04}', '\u{1C05}', '\u{1C06}', '\u{1C07}', '\u{1C08}', '\u{1C09}', '\u{1C0A}', '\u{1C0B}', '\u{1C0C}', '\u{1C0D}', '\u{1C0E}', '\u{1C0F}', '\u{1C10}', '\u{1C11}', '\u{1C12}', '\u{1C13}', '\u{1C14}', '\u{1C15}', '\u{1C16}', '\u{1C17}', '\u{1C18}', '\u{1C19}', '\u{1C1A}', '\u{1C1B}', '\u{1C1C}', '\u{1C1D}', '\u{1C1E}', '\u{1C1F}', '\u{1C20}', '\u{1C21}', '\u{1C22}', '\u{1C23}', '\u{1C4D}', '\u{1C4E}', '\u{1C4F}', '\u{1C5A}', '\u{1C5B}', '\u{1C5C}', '\u{1C5D}', '\u{1C5E}', '\u{1C5F}', '\u{1C60}', '\u{1C61}', '\u{1C62}', '\u{1C63}', '\u{1C64}', '\u{1C65}', '\u{1C66}', '\u{1C67}', '\u{1C68}', '\u{1C69}', '\u{1C6A}', '\u{1C6B}', '\u{1C6C}', '\u{1C6D}', '\u{1C6E}', '\u{1C6F}', '\u{1C70}', '\u{1C71}', '\u{1C72}', '\u{1C73}', '\u{1C74}', '\u{1C75}', '\u{1C76}', '\u{1C77}', '\u{2135}', '\u{2136}', '\u{2137}', '\u{2138}', '\u{2D30}', '\u{2D31}', '\u{2D32}', '\u{2D33}', '\u{2D34}', '\u{2D35}', '\u{2D36}', '\u{2D37}', '\u{2D38}', '\u{2D39}', '\u{2D3A}', '\u{2D3B}', '\u{2D3C}', '\u{2D3D}', '\u{2D3E}', '\u{2D3F}', '\u{2D40}', '\u{2D41}', '\u{2D42}', '\u{2D43}', '\u{2D44}', '\u{2D45}', '\u{2D46}', '\u{2D47}', '\u{2D48}', '\u{2D49}', '\u{2D4A}', '\u{2D4B}', '\u{2D4C}', '\u{2D4D}', '\u{2D4E}', '\u{2D4F}', '\u{2D50}', '\u{2D51}', '\u{2D52}', '\u{2D53}', '\u{2D54}', '\u{2D55}', '\u{2D56}', '\u{2D57}', '\u{2D58}', '\u{2D59}', '\u{2D5A}', '\u{2D5B}', '\u{2D5C}', '\u{2D5D}', '\u{2D5E}', '\u{2D5F}', '\u{2D60}', '\u{2D61}', '\u{2D62}', '\u{2D63}', '\u{2D64}', '\u{2D65}', '\u{2D80}', '\u{2D81}', '\u{2D82}', '\u{2D83}', '\u{2D84}', '\u{2D85}', '\u{2D86}', '\u{2D87}', '\u{2D88}', '\u{2D89}', '\u{2D8A}', '\u{2D8B}', '\u{2D8C}', '\u{2D8D}', '\u{2D8E}', '\u{2D8F}', '\u{2D90}', '\u{2D91}', '\u{2D92}', '\u{2D93}', '\u{2D94}', '\u{2D95}', '\u{2D96}', '\u{2DA0}', '\u{2DA1}', '\u{2DA2}', '\u{2DA3}', '\u{2DA4}', '\u{2DA5}', '\u{2DA6}', '\u{2DA8}', '\u{2DA9}', '\u{2DAA}', '\u{2DAB}', '\u{2DAC}', '\u{2DAD}', '\u{2DAE}', '\u{2DB0}', '\u{2DB1}', '\u{2DB2}', '\u{2DB3}', '\u{2DB4}', '\u{2DB5}', '\u{2DB6}', '\u{2DB8}', '\u{2DB9}', '\u{2DBA}', '\u{2DBB}', '\u{2DBC}', '\u{2DBD}', '\u{2DBE}', '\u{2DC0}', '\u{2DC1}', '\u{2DC2}', '\u{2DC3}', '\u{2DC4}', '\u{2DC5}', '\u{2DC6}', '\u{2DC8}', '\u{2DC9}', '\u{2DCA}', '\u{2DCB}', '\u{2DCC}', '\u{2DCD}', '\u{2DCE}', '\u{2DD0}', '\u{2DD1}', '\u{2DD2}', '\u{2DD3}', '\u{2DD4}', '\u{2DD5}', '\u{2DD6}', '\u{2DD8}', '\u{2DD9}', '\u{2DDA}', '\u{2DDB}', '\u{2DDC}', '\u{2DDD}', '\u{2DDE}', '\u{3006}', '\u{303C}', '\u{3041}', '\u{3042}', '\u{3043}', '\u{3044}', '\u{3045}', '\u{3046}', '\u{3047}', '\u{3048}', '\u{3049}', '\u{304A}', '\u{304B}', '\u{304C}', '\u{304D}', '\u{304E}', '\u{304F}', '\u{3050}', '\u{3051}', '\u{3052}', '\u{3053}', '\u{3054}', '\u{3055}', '\u{3056}', '\u{3057}', '\u{3058}', '\u{3059}', '\u{305A}', '\u{305B}', '\u{305C}', '\u{305D}', '\u{305E}', '\u{305F}', '\u{3060}', '\u{3061}', '\u{3062}', '\u{3063}', '\u{3064}', '\u{3065}', '\u{3066}', '\u{3067}', '\u{3068}', '\u{3069}', '\u{306A}', '\u{306B}', '\u{306C}', '\u{306D}', '\u{306E}', '\u{306F}', '\u{3070}', '\u{3071}', '\u{3072}', '\u{3073}', '\u{3074}', '\u{3075}', '\u{3076}', '\u{3077}', '\u{3078}', '\u{3079}', '\u{307A}', '\u{307B}', '\u{307C}', '\u{307D}', '\u{307E}', '\u{307F}', '\u{3080}', '\u{3081}', '\u{3082}', '\u{3083}', '\u{3084}', '\u{3085}', '\u{3086}', '\u{3087}', '\u{3088}', '\u{3089}', '\u{308A}', '\u{308B}', '\u{308C}', '\u{308D}', '\u{308E}', '\u{308F}', '\u{3090}', '\u{3091}', '\u{3092}', '\u{3093}', '\u{3094}', '\u{3095}', '\u{3096}', '\u{309F}', '\u{30A1}', '\u{30A2}', '\u{30A3}', '\u{30A4}', '\u{30A5}', '\u{30A6}', '\u{30A7}', '\u{30A8}', '\u{30A9}', '\u{30AA}', '\u{30AB}', '\u{30AC}', '\u{30AD}', '\u{30AE}', '\u{30AF}', '\u{30B0}', '\u{30B1}', '\u{30B2}', '\u{30B3}', '\u{30B4}', '\u{30B5}', '\u{30B6}', '\u{30B7}', '\u{30B8}', '\u{30B9}', '\u{30BA}', '\u{30BB}', '\u{30BC}', '\u{30BD}', '\u{30BE}', '\u{30BF}', '\u{30C0}', '\u{30C1}', '\u{30C2}', '\u{30C3}', '\u{30C4}', '\u{30C5}', '\u{30C6}', '\u{30C7}', '\u{30C8}', '\u{30C9}', '\u{30CA}', '\u{30CB}', '\u{30CC}', '\u{30CD}', '\u{30CE}', '\u{30CF}', '\u{30D0}', '\u{30D1}', '\u{30D2}', '\u{30D3}', '\u{30D4}', '\u{30D5}', '\u{30D6}', '\u{30D7}', '\u{30D8}', '\u{30D9}', '\u{30DA}', '\u{30DB}', '\u{30DC}', '\u{30DD}', '\u{30DE}', '\u{30DF}', '\u{30E0}', '\u{30E1}', '\u{30E2}', '\u{30E3}', '\u{30E4}', '\u{30E5}', '\u{30E6}', '\u{30E7}', '\u{30E8}', '\u{30E9}', '\u{30EA}', '\u{30EB}', '\u{30EC}', '\u{30ED}', '\u{30EE}', '\u{30EF}', '\u{30F0}', '\u{30F1}', '\u{30F2}', '\u{30F3}', '\u{30F4}', '\u{30F5}', '\u{30F6}', '\u{30F7}', '\u{30F8}', '\u{30F9}', '\u{30FA}', '\u{30FF}', '\u{3105}', '\u{3106}', '\u{3107}', '\u{3108}', '\u{3109}', '\u{310A}', '\u{310B}', '\u{310C}', '\u{310D}', '\u{310E}', '\u{310F}', '\u{3110}', '\u{3111}', '\u{3112}', '\u{3113}', '\u{3114}', '\u{3115}', '\u{3116}', '\u{3117}', '\u{3118}', '\u{3119}', '\u{311A}', '\u{311B}', '\u{311C}', '\u{311D}', '\u{311E}', '\u{311F}', '\u{3120}', '\u{3121}', '\u{3122}', '\u{3123}', '\u{3124}', '\u{3125}', '\u{3126}', '\u{3127}', '\u{3128}', '\u{3129}', '\u{312A}', '\u{312B}', '\u{312C}', '\u{312D}', '\u{3131}', '\u{3132}', '\u{3133}', '\u{3134}', '\u{3135}', '\u{3136}', '\u{3137}', '\u{3138}', '\u{3139}', '\u{313A}', '\u{313B}', '\u{313C}', '\u{313D}', '\u{313E}', '\u{313F}', '\u{3140}', '\u{3141}', '\u{3142}', '\u{3143}', '\u{3144}', '\u{3145}', '\u{3146}', '\u{3147}', '\u{3148}', '\u{3149}', '\u{314A}', '\u{314B}', '\u{314C}', '\u{314D}', '\u{314E}', '\u{314F}', '\u{3150}', '\u{3151}', '\u{3152}', '\u{3153}', '\u{3154}', '\u{3155}', '\u{3156}', '\u{3157}', '\u{3158}', '\u{3159}', '\u{315A}', '\u{315B}', '\u{315C}', '\u{315D}', '\u{315E}', '\u{315F}', '\u{3160}', '\u{3161}', '\u{3162}', '\u{3163}', '\u{3164}', '\u{3165}', '\u{3166}', '\u{3167}', '\u{3168}', '\u{3169}', '\u{316A}', '\u{316B}', '\u{316C}', '\u{316D}', '\u{316E}', '\u{316F}', '\u{3170}', '\u{3171}', '\u{3172}', '\u{3173}', '\u{3174}', '\u{3175}', '\u{3176}', '\u{3177}', '\u{3178}', '\u{3179}', '\u{317A}', '\u{317B}', '\u{317C}', '\u{317D}', '\u{317E}', '\u{317F}', '\u{3180}', '\u{3181}', '\u{3182}', '\u{3183}', '\u{3184}', '\u{3185}', '\u{3186}', '\u{3187}', '\u{3188}', '\u{3189}', '\u{318A}', '\u{318B}', '\u{318C}', '\u{318D}', '\u{318E}', '\u{31A0}', '\u{31A1}', '\u{31A2}', '\u{31A3}', '\u{31A4}', '\u{31A5}', '\u{31A6}', '\u{31A7}', '\u{31A8}', '\u{31A9}', '\u{31AA}', '\u{31AB}', '\u{31AC}', '\u{31AD}', '\u{31AE}', '\u{31AF}', '\u{31B0}', '\u{31B1}', '\u{31B2}', '\u{31B3}', '\u{31B4}', '\u{31B5}', '\u{31B6}', '\u{31B7}', '\u{31F0}', '\u{31F1}', '\u{31F2}', '\u{31F3}', '\u{31F4}', '\u{31F5}', '\u{31F6}', '\u{31F7}', '\u{31F8}', '\u{31F9}', '\u{31FA}', '\u{31FB}', '\u{31FC}', '\u{31FD}', '\u{31FE}', '\u{31FF}', '\u{3400}', '\u{4DB5}', '\u{4E00}', '\u{9FC3}', '\u{A000}', '\u{A001}', '\u{A002}', '\u{A003}', '\u{A004}', '\u{A005}', '\u{A006}', '\u{A007}', '\u{A008}', '\u{A009}', '\u{A00A}', '\u{A00B}', '\u{A00C}', '\u{A00D}', '\u{A00E}', '\u{A00F}', '\u{A010}', '\u{A011}', '\u{A012}', '\u{A013}', '\u{A014}', '\u{A016}', '\u{A017}', '\u{A018}', '\u{A019}', '\u{A01A}', '\u{A01B}', '\u{A01C}', '\u{A01D}', '\u{A01E}', '\u{A01F}', '\u{A020}', '\u{A021}', '\u{A022}', '\u{A023}', '\u{A024}', '\u{A025}', '\u{A026}', '\u{A027}', '\u{A028}', '\u{A029}', '\u{A02A}', '\u{A02B}', '\u{A02C}', '\u{A02D}', '\u{A02E}', '\u{A02F}', '\u{A030}', '\u{A031}', '\u{A032}', '\u{A033}', '\u{A034}', '\u{A035}', '\u{A036}', '\u{A037}', '\u{A038}', '\u{A039}', '\u{A03A}', '\u{A03B}', '\u{A03C}', '\u{A03D}', '\u{A03E}', '\u{A03F}', '\u{A040}', '\u{A041}', '\u{A042}', '\u{A043}', '\u{A044}', '\u{A045}', '\u{A046}', '\u{A047}', '\u{A048}', '\u{A049}', '\u{A04A}', '\u{A04B}', '\u{A04C}', '\u{A04D}', '\u{A04E}', '\u{A04F}', '\u{A050}', '\u{A051}', '\u{A052}', '\u{A053}', '\u{A054}', '\u{A055}', '\u{A056}', '\u{A057}', '\u{A058}', '\u{A059}', '\u{A05A}', '\u{A05B}', '\u{A05C}', '\u{A05D}', '\u{A05E}', '\u{A05F}', '\u{A060}', '\u{A061}', '\u{A062}', '\u{A063}', '\u{A064}', '\u{A065}', '\u{A066}', '\u{A067}', '\u{A068}', '\u{A069}', '\u{A06A}', '\u{A06B}', '\u{A06C}', '\u{A06D}', '\u{A06E}', '\u{A06F}', '\u{A070}', '\u{A071}', '\u{A072}', '\u{A073}', '\u{A074}', '\u{A075}', '\u{A076}', '\u{A077}', '\u{A078}', '\u{A079}', '\u{A07A}', '\u{A07B}', '\u{A07C}', '\u{A07D}', '\u{A07E}', '\u{A07F}', '\u{A080}', '\u{A081}', '\u{A082}', '\u{A083}', '\u{A084}', '\u{A085}', '\u{A086}', '\u{A087}', '\u{A088}', '\u{A089}', '\u{A08A}', '\u{A08B}', '\u{A08C}', '\u{A08D}', '\u{A08E}', '\u{A08F}', '\u{A090}', '\u{A091}', '\u{A092}', '\u{A093}', '\u{A094}', '\u{A095}', '\u{A096}', '\u{A097}', '\u{A098}', '\u{A099}', '\u{A09A}', '\u{A09B}', '\u{A09C}', '\u{A09D}', '\u{A09E}', '\u{A09F}', '\u{A0A0}', '\u{A0A1}', '\u{A0A2}', '\u{A0A3}', '\u{A0A4}', '\u{A0A5}', '\u{A0A6}', '\u{A0A7}', '\u{A0A8}', '\u{A0A9}', '\u{A0AA}', '\u{A0AB}', '\u{A0AC}', '\u{A0AD}', '\u{A0AE}', '\u{A0AF}', '\u{A0B0}', '\u{A0B1}', '\u{A0B2}', '\u{A0B3}', '\u{A0B4}', '\u{A0B5}', '\u{A0B6}', '\u{A0B7}', '\u{A0B8}', '\u{A0B9}', '\u{A0BA}', '\u{A0BB}', '\u{A0BC}', '\u{A0BD}', '\u{A0BE}', '\u{A0BF}', '\u{A0C0}', '\u{A0C1}', '\u{A0C2}', '\u{A0C3}', '\u{A0C4}', '\u{A0C5}', '\u{A0C6}', '\u{A0C7}', '\u{A0C8}', '\u{A0C9}', '\u{A0CA}', '\u{A0CB}', '\u{A0CC}', '\u{A0CD}', '\u{A0CE}', '\u{A0CF}', '\u{A0D0}', '\u{A0D1}', '\u{A0D2}', '\u{A0D3}', '\u{A0D4}', '\u{A0D5}', '\u{A0D6}', '\u{A0D7}', '\u{A0D8}', '\u{A0D9}', '\u{A0DA}', '\u{A0DB}', '\u{A0DC}', '\u{A0DD}', '\u{A0DE}', '\u{A0DF}', '\u{A0E0}', '\u{A0E1}', '\u{A0E2}', '\u{A0E3}', '\u{A0E4}', '\u{A0E5}', '\u{A0E6}', '\u{A0E7}', '\u{A0E8}', '\u{A0E9}', '\u{A0EA}', '\u{A0EB}', '\u{A0EC}', '\u{A0ED}', '\u{A0EE}', '\u{A0EF}', '\u{A0F0}', '\u{A0F1}', '\u{A0F2}', '\u{A0F3}', '\u{A0F4}', '\u{A0F5}', '\u{A0F6}', '\u{A0F7}', '\u{A0F8}', '\u{A0F9}', '\u{A0FA}', '\u{A0FB}', '\u{A0FC}', '\u{A0FD}', '\u{A0FE}', '\u{A0FF}', '\u{A100}', '\u{A101}', '\u{A102}', '\u{A103}', '\u{A104}', '\u{A105}', '\u{A106}', '\u{A107}', '\u{A108}', '\u{A109}', '\u{A10A}', '\u{A10B}', '\u{A10C}', '\u{A10D}', '\u{A10E}', '\u{A10F}', '\u{A110}', '\u{A111}', '\u{A112}', '\u{A113}', '\u{A114}', '\u{A115}', '\u{A116}', '\u{A117}', '\u{A118}', '\u{A119}', '\u{A11A}', '\u{A11B}', '\u{A11C}', '\u{A11D}', '\u{A11E}', '\u{A11F}', '\u{A120}', '\u{A121}', '\u{A122}', '\u{A123}', '\u{A124}', '\u{A125}', '\u{A126}', '\u{A127}', '\u{A128}', '\u{A129}', '\u{A12A}', '\u{A12B}', '\u{A12C}', '\u{A12D}', '\u{A12E}', '\u{A12F}', '\u{A130}', '\u{A131}', '\u{A132}', '\u{A133}', '\u{A134}', '\u{A135}', '\u{A136}', '\u{A137}', '\u{A138}', '\u{A139}', '\u{A13A}', '\u{A13B}', '\u{A13C}', '\u{A13D}', '\u{A13E}', '\u{A13F}', '\u{A140}', '\u{A141}', '\u{A142}', '\u{A143}', '\u{A144}', '\u{A145}', '\u{A146}', '\u{A147}', '\u{A148}', '\u{A149}', '\u{A14A}', '\u{A14B}', '\u{A14C}', '\u{A14D}', '\u{A14E}', '\u{A14F}', '\u{A150}', '\u{A151}', '\u{A152}', '\u{A153}', '\u{A154}', '\u{A155}', '\u{A156}', '\u{A157}', '\u{A158}', '\u{A159}', '\u{A15A}', '\u{A15B}', '\u{A15C}', '\u{A15D}', '\u{A15E}', '\u{A15F}', '\u{A160}', '\u{A161}', '\u{A162}', '\u{A163}', '\u{A164}', '\u{A165}', '\u{A166}', '\u{A167}', '\u{A168}', '\u{A169}', '\u{A16A}', '\u{A16B}', '\u{A16C}', '\u{A16D}', '\u{A16E}', '\u{A16F}', '\u{A170}', '\u{A171}', '\u{A172}', '\u{A173}', '\u{A174}', '\u{A175}', '\u{A176}', '\u{A177}', '\u{A178}', '\u{A179}', '\u{A17A}', '\u{A17B}', '\u{A17C}', '\u{A17D}', '\u{A17E}', '\u{A17F}', '\u{A180}', '\u{A181}', '\u{A182}', '\u{A183}', '\u{A184}', '\u{A185}', '\u{A186}', '\u{A187}', '\u{A188}', '\u{A189}', '\u{A18A}', '\u{A18B}', '\u{A18C}', '\u{A18D}', '\u{A18E}', '\u{A18F}', '\u{A190}', '\u{A191}', '\u{A192}', '\u{A193}', '\u{A194}', '\u{A195}', '\u{A196}', '\u{A197}', '\u{A198}', '\u{A199}', '\u{A19A}', '\u{A19B}', '\u{A19C}', '\u{A19D}', '\u{A19E}', '\u{A19F}', '\u{A1A0}', '\u{A1A1}', '\u{A1A2}', '\u{A1A3}', '\u{A1A4}', '\u{A1A5}', '\u{A1A6}', '\u{A1A7}', '\u{A1A8}', '\u{A1A9}', '\u{A1AA}', '\u{A1AB}', '\u{A1AC}', '\u{A1AD}', '\u{A1AE}', '\u{A1AF}')
+    }
+
+    fn is_unicode_letter_number(self) -> bool {
+        match_char_class!(self,
+            '\u{16EE}', '\u{16EF}', '\u{16F0}', '\u{2160}', '\u{2161}', '\u{2162}', '\u{2163}', '\u{2164}', '\u{2165}', '\u{2166}', '\u{2167}', '\u{2168}', '\u{2169}', '\u{216A}', '\u{216B}', '\u{216C}', '\u{216D}', '\u{216E}', '\u{216F}', '\u{2170}', '\u{2171}', '\u{2172}', '\u{2173}', '\u{2174}', '\u{2175}', '\u{2176}', '\u{2177}', '\u{2178}', '\u{2179}', '\u{217A}', '\u{217B}', '\u{217C}', '\u{217D}', '\u{217E}', '\u{217F}', '\u{2180}', '\u{2181}', '\u{2182}', '\u{2185}', '\u{2186}', '\u{2187}', '\u{2188}', '\u{3007}', '\u{3021}', '\u{3022}', '\u{3023}', '\u{3024}', '\u{3025}', '\u{3026}', '\u{3027}', '\u{3028}', '\u{3029}', '\u{3038}', '\u{3039}', '\u{303A}')
+    }
+
+    fn is_unicode_nonspacing_mark(self) -> bool {
+        match_char_class!(self,
+            '\u{0300}', '\u{0301}', '\u{0302}', '\u{0303}', '\u{0304}', '\u{0305}', '\u{0306}', '\u{0307}', '\u{0308}', '\u{0309}', '\u{030A}', '\u{030B}', '\u{030C}', '\u{030D}', '\u{030E}', '\u{030F}', '\u{0310}', '\u{0311}', '\u{0312}', '\u{0313}', '\u{0314}', '\u{0315}', '\u{0316}', '\u{0317}', '\u{0318}', '\u{0319}', '\u{031A}', '\u{031B}', '\u{031C}', '\u{031D}', '\u{031E}', '\u{031F}', '\u{0320}', '\u{0321}', '\u{0322}', '\u{0323}', '\u{0324}', '\u{0325}', '\u{0326}', '\u{0327}', '\u{0328}', '\u{0329}', '\u{032A}', '\u{032B}', '\u{032C}', '\u{032D}', '\u{032E}', '\u{032F}', '\u{0330}', '\u{0331}', '\u{0332}', '\u{0333}', '\u{0334}', '\u{0335}', '\u{0336}', '\u{0337}', '\u{0338}', '\u{0339}', '\u{033A}', '\u{033B}', '\u{033C}', '\u{033D}', '\u{033E}', '\u{033F}', '\u{0340}', '\u{0341}', '\u{0342}', '\u{0343}', '\u{0344}', '\u{0345}', '\u{0346}', '\u{0347}', '\u{0348}', '\u{0349}', '\u{034A}', '\u{034B}', '\u{034C}', '\u{034D}', '\u{034E}', '\u{034F}', '\u{0350}', '\u{0351}', '\u{0352}', '\u{0353}', '\u{0354}', '\u{0355}', '\u{0356}', '\u{0357}', '\u{0358}', '\u{0359}', '\u{035A}', '\u{035B}', '\u{035C}', '\u{035D}', '\u{035E}', '\u{035F}', '\u{0360}', '\u{0361}', '\u{0362}', '\u{0363}', '\u{0364}', '\u{0365}', '\u{0366}', '\u{0367}', '\u{0368}', '\u{0369}', '\u{036A}', '\u{036B}', '\u{036C}', '\u{036D}', '\u{036E}', '\u{036F}', '\u{0483}', '\u{0484}', '\u{0485}', '\u{0486}', '\u{0487}', '\u{0591}', '\u{0592}', '\u{0593}', '\u{0594}', '\u{0595}', '\u{0596}', '\u{0597}', '\u{0598}', '\u{0599}', '\u{059A}', '\u{059B}', '\u{059C}', '\u{059D}', '\u{059E}', '\u{059F}', '\u{05A0}', '\u{05A1}', '\u{05A2}', '\u{05A3}', '\u{05A4}', '\u{05A5}', '\u{05A6}', '\u{05A7}', '\u{05A8}', '\u{05A9}', '\u{05AA}', '\u{05AB}', '\u{05AC}', '\u{05AD}', '\u{05AE}', '\u{05AF}', '\u{05B0}', '\u{05B1}', '\u{05B2}', '\u{05B3}', '\u{05B4}', '\u{05B5}', '\u{05B6}', '\u{05B7}', '\u{05B8}', '\u{05B9}', '\u{05BA}', '\u{05BB}', '\u{05BC}', '\u{05BD}', '\u{05BF}', '\u{05C1}', '\u{05C2}', '\u{05C4}', '\u{05C5}', '\u{05C7}', '\u{0610}', '\u{0611}', '\u{0612}', '\u{0613}', '\u{0614}', '\u{0615}', '\u{0616}', '\u{0617}', '\u{0618}', '\u{0619}', '\u{061A}', '\u{064B}', '\u{064C}', '\u{064D}', '\u{064E}', '\u{064F}', '\u{0650}', '\u{0651}', '\u{0652}', '\u{0653}', '\u{0654}', '\u{0655}', '\u{0656}', '\u{0657}', '\u{0658}', '\u{0659}', '\u{065A}', '\u{065B}', '\u{065C}', '\u{065D}', '\u{065E}', '\u{0670}', '\u{06D6}', '\u{06D7}', '\u{06D8}', '\u{06D9}', '\u{06DA}', '\u{06DB}', '\u{06DC}', '\u{06DF}', '\u{06E0}', '\u{06E1}', '\u{06E2}', '\u{06E3}', '\u{06E4}', '\u{06E7}', '\u{06E8}', '\u{06EA}', '\u{06EB}', '\u{06EC}', '\u{06ED}', '\u{0711}', '\u{0730}', '\u{0731}', '\u{0732}', '\u{0733}', '\u{0734}', '\u{0735}', '\u{0736}', '\u{0737}', '\u{0738}', '\u{0739}', '\u{073A}', '\u{073B}', '\u{073C}', '\u{073D}', '\u{073E}', '\u{073F}', '\u{0740}', '\u{0741}', '\u{0742}', '\u{0743}', '\u{0744}', '\u{0745}', '\u{0746}', '\u{0747}', '\u{0748}', '\u{0749}', '\u{074A}', '\u{07A6}', '\u{07A7}', '\u{07A8}', '\u{07A9}', '\u{07AA}', '\u{07AB}', '\u{07AC}', '\u{07AD}', '\u{07AE}', '\u{07AF}', '\u{07B0}', '\u{07EB}', '\u{07EC}', '\u{07ED}', '\u{07EE}', '\u{07EF}', '\u{07F0}', '\u{07F1}', '\u{07F2}', '\u{07F3}', '\u{0901}', '\u{0902}', '\u{093C}', '\u{0941}', '\u{0942}', '\u{0943}', '\u{0944}', '\u{0945}', '\u{0946}', '\u{0947}', '\u{0948}', '\u{094D}', '\u{0951}', '\u{0952}', '\u{0953}', '\u{0954}', '\u{0962}', '\u{0963}', '\u{0981}', '\u{09BC}', '\u{09C1}', '\u{09C2}', '\u{09C3}', '\u{09C4}', '\u{09CD}', '\u{09E2}', '\u{09E3}', '\u{0A01}', '\u{0A02}', '\u{0A3C}', '\u{0A41}', '\u{0A42}', '\u{0A47}', '\u{0A48}', '\u{0A4B}', '\u{0A4C}', '\u{0A4D}', '\u{0A51}', '\u{0A70}', '\u{0A71}', '\u{0A75}', '\u{0A81}', '\u{0A82}', '\u{0ABC}', '\u{0AC1}', '\u{0AC2}', '\u{0AC3}', '\u{0AC4}', '\u{0AC5}', '\u{0AC7}', '\u{0AC8}', '\u{0ACD}', '\u{0AE2}', '\u{0AE3}', '\u{0B01}', '\u{0B3C}', '\u{0B3F}', '\u{0B41}', '\u{0B42}', '\u{0B43}', '\u{0B44}', '\u{0B4D}', '\u{0B56}', '\u{0B62}', '\u{0B63}', '\u{0B82}', '\u{0BC0}', '\u{0BCD}', '\u{0C3E}', '\u{0C3F}', '\u{0C40}', '\u{0C46}', '\u{0C47}', '\u{0C48}', '\u{0C4A}', '\u{0C4B}', '\u{0C4C}', '\u{0C4D}', '\u{0C55}', '\u{0C56}', '\u{0C62}', '\u{0C63}', '\u{0CBC}', '\u{0CBF}', '\u{0CC6}', '\u{0CCC}', '\u{0CCD}', '\u{0CE2}', '\u{0CE3}', '\u{0D41}', '\u{0D42}', '\u{0D43}', '\u{0D44}', '\u{0D4D}', '\u{0D62}', '\u{0D63}', '\u{0DCA}', '\u{0DD2}', '\u{0DD3}', '\u{0DD4}', '\u{0DD6}', '\u{0E31}', '\u{0E34}', '\u{0E35}', '\u{0E36}', '\u{0E37}', '\u{0E38}', '\u{0E39}', '\u{0E3A}', '\u{0E47}', '\u{0E48}', '\u{0E49}', '\u{0E4A}', '\u{0E4B}', '\u{0E4C}', '\u{0E4D}', '\u{0E4E}', '\u{0EB1}', '\u{0EB4}', '\u{0EB5}', '\u{0EB6}', '\u{0EB7}', '\u{0EB8}', '\u{0EB9}', '\u{0EBB}', '\u{0EBC}', '\u{0EC8}', '\u{0EC9}', '\u{0ECA}', '\u{0ECB}', '\u{0ECC}', '\u{0ECD}', '\u{0F18}', '\u{0F19}', '\u{0F35}', '\u{0F37}', '\u{0F39}', '\u{0F71}', '\u{0F72}', '\u{0F73}', '\u{0F74}', '\u{0F75}', '\u{0F76}', '\u{0F77}', '\u{0F78}', '\u{0F79}', '\u{0F7A}', '\u{0F7B}', '\u{0F7C}', '\u{0F7D}', '\u{0F7E}', '\u{0F80}', '\u{0F81}', '\u{0F82}', '\u{0F83}', '\u{0F84}', '\u{0F86}', '\u{0F87}', '\u{0F90}', '\u{0F91}', '\u{0F92}', '\u{0F93}', '\u{0F94}', '\u{0F95}', '\u{0F96}', '\u{0F97}', '\u{0F99}', '\u{0F9A}', '\u{0F9B}', '\u{0F9C}', '\u{0F9D}', '\u{0F9E}', '\u{0F9F}', '\u{0FA0}', '\u{0FA1}', '\u{0FA2}', '\u{0FA3}', '\u{0FA4}', '\u{0FA5}', '\u{0FA6}', '\u{0FA7}', '\u{0FA8}', '\u{0FA9}', '\u{0FAA}', '\u{0FAB}', '\u{0FAC}', '\u{0FAD}', '\u{0FAE}', '\u{0FAF}', '\u{0FB0}', '\u{0FB1}', '\u{0FB2}', '\u{0FB3}', '\u{0FB4}', '\u{0FB5}', '\u{0FB6}', '\u{0FB7}', '\u{0FB8}', '\u{0FB9}', '\u{0FBA}', '\u{0FBB}', '\u{0FBC}', '\u{0FC6}', '\u{102D}', '\u{102E}', '\u{102F}', '\u{1030}', '\u{1032}', '\u{1033}', '\u{1034}', '\u{1035}', '\u{1036}', '\u{1037}', '\u{1039}', '\u{103A}', '\u{103D}', '\u{103E}', '\u{1058}', '\u{1059}', '\u{105E}', '\u{105F}', '\u{1060}', '\u{1071}', '\u{1072}', '\u{1073}', '\u{1074}', '\u{1082}', '\u{1085}', '\u{1086}', '\u{108D}', '\u{135F}', '\u{1712}', '\u{1713}', '\u{1714}', '\u{1732}', '\u{1733}', '\u{1734}', '\u{1752}', '\u{1753}', '\u{1772}', '\u{1773}', '\u{17B7}', '\u{17B8}', '\u{17B9}', '\u{17BA}', '\u{17BB}', '\u{17BC}', '\u{17BD}', '\u{17C6}', '\u{17C9}', '\u{17CA}', '\u{17CB}', '\u{17CC}', '\u{17CD}', '\u{17CE}', '\u{17CF}', '\u{17D0}', '\u{17D1}', '\u{17D2}', '\u{17D3}', '\u{17DD}', '\u{180B}', '\u{180C}', '\u{180D}', '\u{18A9}', '\u{1920}', '\u{1921}', '\u{1922}', '\u{1927}', '\u{1928}', '\u{1932}', '\u{1939}', '\u{193A}', '\u{193B}', '\u{1A17}', '\u{1A18}', '\u{1B00}', '\u{1B01}', '\u{1B02}', '\u{1B03}', '\u{1B34}', '\u{1B36}', '\u{1B37}', '\u{1B38}', '\u{1B39}', '\u{1B3A}', '\u{1B3C}', '\u{1B42}', '\u{1B6B}', '\u{1B6C}', '\u{1B6D}', '\u{1B6E}', '\u{1B6F}', '\u{1B70}', '\u{1B71}', '\u{1B72}', '\u{1B73}', '\u{1B80}', '\u{1B81}', '\u{1BA2}', '\u{1BA3}', '\u{1BA4}', '\u{1BA5}', '\u{1BA8}', '\u{1BA9}', '\u{1C2C}', '\u{1C2D}', '\u{1C2E}', '\u{1C2F}', '\u{1C30}', '\u{1C31}', '\u{1C32}', '\u{1C33}', '\u{1C36}', '\u{1C37}', '\u{1DC0}', '\u{1DC1}', '\u{1DC2}', '\u{1DC3}', '\u{1DC4}', '\u{1DC5}', '\u{1DC6}', '\u{1DC7}', '\u{1DC8}', '\u{1DC9}', '\u{1DCA}', '\u{1DCB}', '\u{1DCC}', '\u{1DCD}', '\u{1DCE}', '\u{1DCF}', '\u{1DD0}', '\u{1DD1}', '\u{1DD2}', '\u{1DD3}', '\u{1DD4}', '\u{1DD5}', '\u{1DD6}', '\u{1DD7}', '\u{1DD8}', '\u{1DD9}', '\u{1DDA}', '\u{1DDB}', '\u{1DDC}', '\u{1DDD}', '\u{1DDE}', '\u{1DDF}', '\u{1DE0}', '\u{1DE1}', '\u{1DE2}', '\u{1DE3}', '\u{1DE4}', '\u{1DE5}', '\u{1DE6}', '\u{1DFE}', '\u{1DFF}', '\u{20D0}', '\u{20D1}', '\u{20D2}', '\u{20D3}', '\u{20D4}', '\u{20D5}', '\u{20D6}', '\u{20D7}', '\u{20D8}', '\u{20D9}', '\u{20DA}', '\u{20DB}', '\u{20DC}', '\u{20E1}', '\u{20E5}', '\u{20E6}', '\u{20E7}', '\u{20E8}', '\u{20E9}', '\u{20EA}', '\u{20EB}', '\u{20EC}', '\u{20ED}', '\u{20EE}', '\u{20EF}', '\u{20F0}', '\u{2DE0}', '\u{2DE1}', '\u{2DE2}', '\u{2DE3}', '\u{2DE4}', '\u{2DE5}', '\u{2DE6}', '\u{2DE7}', '\u{2DE8}', '\u{2DE9}', '\u{2DEA}', '\u{2DEB}', '\u{2DEC}', '\u{2DED}', '\u{2DEE}', '\u{2DEF}', '\u{2DF0}', '\u{2DF1}', '\u{2DF2}', '\u{2DF3}', '\u{2DF4}', '\u{2DF5}', '\u{2DF6}', '\u{2DF7}', '\u{2DF8}', '\u{2DF9}', '\u{2DFA}', '\u{2DFB}', '\u{2DFC}', '\u{2DFD}', '\u{2DFE}', '\u{2DFF}', '\u{302A}', '\u{302B}', '\u{302C}', '\u{302D}', '\u{302E}', '\u{302F}', '\u{3099}', '\u{309A}', '\u{A66F}', '\u{A67C}', '\u{A67D}', '\u{A802}', '\u{A806}', '\u{A80B}', '\u{A825}', '\u{A826}', '\u{A8C4}', '\u{A926}', '\u{A927}', '\u{A928}', '\u{A929}', '\u{A92A}', '\u{A92B}', '\u{A92C}', '\u{A92D}', '\u{A947}', '\u{A948}', '\u{A949}', '\u{A94A}', '\u{A94B}', '\u{A94C}', '\u{A94D}', '\u{A94E}', '\u{A94F}', '\u{A950}', '\u{A951}', '\u{AA29}', '\u{AA2A}', '\u{AA2B}', '\u{AA2C}', '\u{AA2D}', '\u{AA2E}', '\u{AA31}', '\u{AA32}', '\u{AA35}', '\u{AA36}', '\u{AA43}', '\u{AA4C}', '\u{FB1E}', '\u{FE00}', '\u{FE01}', '\u{FE02}', '\u{FE03}', '\u{FE04}', '\u{FE05}', '\u{FE06}', '\u{FE07}', '\u{FE08}', '\u{FE09}', '\u{FE0A}', '\u{FE0B}', '\u{FE0C}', '\u{FE0D}', '\u{FE0E}', '\u{FE0F}', '\u{FE20}', '\u{FE21}', '\u{FE22}', '\u{FE23}', '\u{FE24}', '\u{FE25}', '\u{FE26}',              '\u{01BB}', '\u{01C0}', '\u{01C1}', '\u{01C2}', '\u{01C3}', '\u{0294}', '\u{05D0}', '\u{05D1}', '\u{05D2}', '\u{05D3}', '\u{05D4}', '\u{05D5}', '\u{05D6}', '\u{05D7}', '\u{05D8}', '\u{05D9}', '\u{05DA}', '\u{05DB}', '\u{05DC}', '\u{05DD}', '\u{05DE}', '\u{05DF}', '\u{05E0}', '\u{05E1}', '\u{05E2}', '\u{05E3}', '\u{05E4}', '\u{05E5}', '\u{05E6}', '\u{05E7}', '\u{05E8}', '\u{05E9}', '\u{05EA}', '\u{05F0}', '\u{05F1}', '\u{05F2}', '\u{0621}', '\u{0622}', '\u{0623}', '\u{0624}', '\u{0625}', '\u{0626}', '\u{0627}', '\u{0628}', '\u{0629}', '\u{062A}', '\u{062B}', '\u{062C}', '\u{062D}', '\u{062E}', '\u{062F}', '\u{0630}', '\u{0631}', '\u{0632}', '\u{0633}', '\u{0634}', '\u{0635}', '\u{0636}', '\u{0637}', '\u{0638}', '\u{0639}', '\u{063A}', '\u{063B}', '\u{063C}', '\u{063D}', '\u{063E}', '\u{063F}', '\u{0641}', '\u{0642}', '\u{0643}', '\u{0644}', '\u{0645}', '\u{0646}', '\u{0647}', '\u{0648}', '\u{0649}', '\u{064A}', '\u{066E}', '\u{066F}', '\u{0671}', '\u{0672}', '\u{0673}', '\u{0674}', '\u{0675}', '\u{0676}', '\u{0677}', '\u{0678}', '\u{0679}', '\u{067A}', '\u{067B}', '\u{067C}', '\u{067D}', '\u{067E}', '\u{067F}', '\u{0680}', '\u{0681}', '\u{0682}', '\u{0683}', '\u{0684}', '\u{0685}', '\u{0686}', '\u{0687}', '\u{0688}', '\u{0689}', '\u{068A}', '\u{068B}', '\u{068C}', '\u{068D}', '\u{068E}', '\u{068F}', '\u{0690}', '\u{0691}', '\u{0692}', '\u{0693}', '\u{0694}', '\u{0695}', '\u{0696}', '\u{0697}', '\u{0698}', '\u{0699}', '\u{069A}', '\u{069B}', '\u{069C}', '\u{069D}', '\u{069E}', '\u{069F}', '\u{06A0}', '\u{06A1}', '\u{06A2}', '\u{06A3}', '\u{06A4}', '\u{06A5}', '\u{06A6}', '\u{06A7}', '\u{06A8}', '\u{06A9}', '\u{06AA}', '\u{06AB}', '\u{06AC}', '\u{06AD}', '\u{06AE}', '\u{06AF}', '\u{06B0}', '\u{06B1}', '\u{06B2}', '\u{06B3}', '\u{06B4}', '\u{06B5}', '\u{06B6}', '\u{06B7}', '\u{06B8}', '\u{06B9}', '\u{06BA}', '\u{06BB}', '\u{06BC}', '\u{06BD}', '\u{06BE}', '\u{06BF}', '\u{06C0}', '\u{06C1}', '\u{06C2}', '\u{06C3}', '\u{06C4}', '\u{06C5}', '\u{06C6}', '\u{06C7}', '\u{06C8}', '\u{06C9}', '\u{06CA}', '\u{06CB}', '\u{06CC}', '\u{06CD}', '\u{06CE}', '\u{06CF}', '\u{06D0}', '\u{06D1}', '\u{06D2}', '\u{06D3}', '\u{06D5}', '\u{06EE}', '\u{06EF}', '\u{06FA}', '\u{06FB}', '\u{06FC}', '\u{06FF}', '\u{0710}', '\u{0712}', '\u{0713}', '\u{0714}', '\u{0715}', '\u{0716}', '\u{0717}', '\u{0718}', '\u{0719}', '\u{071A}', '\u{071B}', '\u{071C}', '\u{071D}', '\u{071E}', '\u{071F}', '\u{0720}', '\u{0721}', '\u{0722}', '\u{0723}', '\u{0724}', '\u{0725}', '\u{0726}', '\u{0727}', '\u{0728}', '\u{0729}', '\u{072A}', '\u{072B}', '\u{072C}', '\u{072D}', '\u{072E}', '\u{072F}', '\u{074D}', '\u{074E}', '\u{074F}', '\u{0750}', '\u{0751}', '\u{0752}', '\u{0753}', '\u{0754}', '\u{0755}', '\u{0756}', '\u{0757}', '\u{0758}', '\u{0759}', '\u{075A}', '\u{075B}', '\u{075C}', '\u{075D}', '\u{075E}', '\u{075F}', '\u{0760}', '\u{0761}', '\u{0762}', '\u{0763}', '\u{0764}', '\u{0765}', '\u{0766}', '\u{0767}', '\u{0768}', '\u{0769}', '\u{076A}', '\u{076B}', '\u{076C}', '\u{076D}', '\u{076E}', '\u{076F}', '\u{0770}', '\u{0771}', '\u{0772}', '\u{0773}', '\u{0774}', '\u{0775}', '\u{0776}', '\u{0777}', '\u{0778}', '\u{0779}', '\u{077A}', '\u{077B}', '\u{077C}', '\u{077D}', '\u{077E}', '\u{077F}', '\u{0780}', '\u{0781}', '\u{0782}', '\u{0783}', '\u{0784}', '\u{0785}', '\u{0786}', '\u{0787}', '\u{0788}', '\u{0789}', '\u{078A}', '\u{078B}', '\u{078C}', '\u{078D}', '\u{078E}', '\u{078F}', '\u{0790}', '\u{0791}', '\u{0792}', '\u{0793}', '\u{0794}', '\u{0795}', '\u{0796}', '\u{0797}', '\u{0798}', '\u{0799}', '\u{079A}', '\u{079B}', '\u{079C}', '\u{079D}', '\u{079E}', '\u{079F}', '\u{07A0}', '\u{07A1}', '\u{07A2}', '\u{07A3}', '\u{07A4}', '\u{07A5}', '\u{07B1}', '\u{07CA}', '\u{07CB}', '\u{07CC}', '\u{07CD}', '\u{07CE}', '\u{07CF}', '\u{07D0}', '\u{07D1}', '\u{07D2}', '\u{07D3}', '\u{07D4}', '\u{07D5}', '\u{07D6}', '\u{07D7}', '\u{07D8}', '\u{07D9}', '\u{07DA}', '\u{07DB}', '\u{07DC}', '\u{07DD}', '\u{07DE}', '\u{07DF}', '\u{07E0}', '\u{07E1}', '\u{07E2}', '\u{07E3}', '\u{07E4}', '\u{07E5}', '\u{07E6}', '\u{07E7}', '\u{07E8}', '\u{07E9}', '\u{07EA}', '\u{0904}', '\u{0905}', '\u{0906}', '\u{0907}', '\u{0908}', '\u{0909}', '\u{090A}', '\u{090B}', '\u{090C}', '\u{090D}', '\u{090E}', '\u{090F}', '\u{0910}', '\u{0911}', '\u{0912}', '\u{0913}', '\u{0914}', '\u{0915}', '\u{0916}', '\u{0917}', '\u{0918}', '\u{0919}', '\u{091A}', '\u{091B}', '\u{091C}', '\u{091D}', '\u{091E}', '\u{091F}', '\u{0920}', '\u{0921}', '\u{0922}', '\u{0923}', '\u{0924}', '\u{0925}', '\u{0926}', '\u{0927}', '\u{0928}', '\u{0929}', '\u{092A}', '\u{092B}', '\u{092C}', '\u{092D}', '\u{092E}', '\u{092F}', '\u{0930}', '\u{0931}', '\u{0932}', '\u{0933}', '\u{0934}', '\u{0935}', '\u{0936}', '\u{0937}', '\u{0938}', '\u{0939}', '\u{093D}', '\u{0950}', '\u{0958}', '\u{0959}', '\u{095A}', '\u{095B}', '\u{095C}', '\u{095D}', '\u{095E}', '\u{095F}', '\u{0960}', '\u{0961}', '\u{0972}', '\u{097B}', '\u{097C}', '\u{097D}', '\u{097E}', '\u{097F}', '\u{0985}', '\u{0986}', '\u{0987}', '\u{0988}', '\u{0989}', '\u{098A}', '\u{098B}', '\u{098C}', '\u{098F}', '\u{0990}', '\u{0993}', '\u{0994}', '\u{0995}', '\u{0996}', '\u{0997}', '\u{0998}', '\u{0999}', '\u{099A}', '\u{099B}', '\u{099C}', '\u{099D}', '\u{099E}', '\u{099F}', '\u{09A0}', '\u{09A1}', '\u{09A2}', '\u{09A3}', '\u{09A4}', '\u{09A5}', '\u{09A6}', '\u{09A7}', '\u{09A8}', '\u{09AA}', '\u{09AB}', '\u{09AC}', '\u{09AD}', '\u{09AE}', '\u{09AF}', '\u{09B0}', '\u{09B2}', '\u{09B6}', '\u{09B7}', '\u{09B8}', '\u{09B9}', '\u{09BD}', '\u{09CE}', '\u{09DC}', '\u{09DD}', '\u{09DF}', '\u{09E0}', '\u{09E1}', '\u{09F0}', '\u{09F1}', '\u{0A05}', '\u{0A06}', '\u{0A07}', '\u{0A08}', '\u{0A09}', '\u{0A0A}', '\u{0A0F}', '\u{0A10}', '\u{0A13}', '\u{0A14}', '\u{0A15}', '\u{0A16}', '\u{0A17}', '\u{0A18}', '\u{0A19}', '\u{0A1A}', '\u{0A1B}', '\u{0A1C}', '\u{0A1D}', '\u{0A1E}', '\u{0A1F}', '\u{0A20}', '\u{0A21}', '\u{0A22}', '\u{0A23}', '\u{0A24}', '\u{0A25}', '\u{0A26}', '\u{0A27}', '\u{0A28}', '\u{0A2A}', '\u{0A2B}', '\u{0A2C}', '\u{0A2D}', '\u{0A2E}', '\u{0A2F}', '\u{0A30}', '\u{0A32}', '\u{0A33}', '\u{0A35}', '\u{0A36}', '\u{0A38}', '\u{0A39}', '\u{0A59}', '\u{0A5A}', '\u{0A5B}', '\u{0A5C}', '\u{0A5E}', '\u{0A72}', '\u{0A73}', '\u{0A74}', '\u{0A85}', '\u{0A86}', '\u{0A87}', '\u{0A88}', '\u{0A89}', '\u{0A8A}', '\u{0A8B}', '\u{0A8C}', '\u{0A8D}', '\u{0A8F}', '\u{0A90}', '\u{0A91}', '\u{0A93}', '\u{0A94}', '\u{0A95}', '\u{0A96}', '\u{0A97}', '\u{0A98}', '\u{0A99}', '\u{0A9A}', '\u{0A9B}', '\u{0A9C}', '\u{0A9D}', '\u{0A9E}', '\u{0A9F}', '\u{0AA0}', '\u{0AA1}', '\u{0AA2}', '\u{0AA3}', '\u{0AA4}', '\u{0AA5}', '\u{0AA6}', '\u{0AA7}', '\u{0AA8}', '\u{0AAA}', '\u{0AAB}', '\u{0AAC}', '\u{0AAD}', '\u{0AAE}', '\u{0AAF}', '\u{0AB0}', '\u{0AB2}', '\u{0AB3}', '\u{0AB5}', '\u{0AB6}', '\u{0AB7}', '\u{0AB8}', '\u{0AB9}', '\u{0ABD}', '\u{0AD0}', '\u{0AE0}', '\u{0AE1}', '\u{0B05}', '\u{0B06}', '\u{0B07}', '\u{0B08}', '\u{0B09}', '\u{0B0A}', '\u{0B0B}', '\u{0B0C}', '\u{0B0F}', '\u{0B10}', '\u{0B13}', '\u{0B14}', '\u{0B15}', '\u{0B16}', '\u{0B17}', '\u{0B18}', '\u{0B19}', '\u{0B1A}', '\u{0B1B}', '\u{0B1C}', '\u{0B1D}', '\u{0B1E}', '\u{0B1F}', '\u{0B20}', '\u{0B21}', '\u{0B22}', '\u{0B23}', '\u{0B24}', '\u{0B25}', '\u{0B26}', '\u{0B27}', '\u{0B28}', '\u{0B2A}', '\u{0B2B}', '\u{0B2C}', '\u{0B2D}', '\u{0B2E}', '\u{0B2F}', '\u{0B30}', '\u{0B32}', '\u{0B33}', '\u{0B35}', '\u{0B36}', '\u{0B37}', '\u{0B38}', '\u{0B39}', '\u{0B3D}', '\u{0B5C}', '\u{0B5D}', '\u{0B5F}', '\u{0B60}', '\u{0B61}', '\u{0B71}', '\u{0B83}', '\u{0B85}', '\u{0B86}', '\u{0B87}', '\u{0B88}', '\u{0B89}', '\u{0B8A}', '\u{0B8E}', '\u{0B8F}', '\u{0B90}', '\u{0B92}', '\u{0B93}', '\u{0B94}', '\u{0B95}', '\u{0B99}', '\u{0B9A}', '\u{0B9C}', '\u{0B9E}', '\u{0B9F}', '\u{0BA3}', '\u{0BA4}', '\u{0BA8}', '\u{0BA9}', '\u{0BAA}', '\u{0BAE}', '\u{0BAF}', '\u{0BB0}', '\u{0BB1}', '\u{0BB2}', '\u{0BB3}', '\u{0BB4}', '\u{0BB5}', '\u{0BB6}', '\u{0BB7}', '\u{0BB8}', '\u{0BB9}', '\u{0BD0}', '\u{0C05}', '\u{0C06}', '\u{0C07}', '\u{0C08}', '\u{0C09}', '\u{0C0A}', '\u{0C0B}', '\u{0C0C}', '\u{0C0E}', '\u{0C0F}', '\u{0C10}', '\u{0C12}', '\u{0C13}', '\u{0C14}', '\u{0C15}', '\u{0C16}', '\u{0C17}', '\u{0C18}', '\u{0C19}', '\u{0C1A}', '\u{0C1B}', '\u{0C1C}', '\u{0C1D}', '\u{0C1E}', '\u{0C1F}', '\u{0C20}', '\u{0C21}', '\u{0C22}', '\u{0C23}', '\u{0C24}', '\u{0C25}', '\u{0C26}', '\u{0C27}', '\u{0C28}', '\u{0C2A}', '\u{0C2B}', '\u{0C2C}', '\u{0C2D}', '\u{0C2E}', '\u{0C2F}', '\u{0C30}', '\u{0C31}', '\u{0C32}', '\u{0C33}', '\u{0C35}', '\u{0C36}', '\u{0C37}', '\u{0C38}', '\u{0C39}', '\u{0C3D}', '\u{0C58}', '\u{0C59}', '\u{0C60}', '\u{0C61}', '\u{0C85}', '\u{0C86}', '\u{0C87}', '\u{0C88}', '\u{0C89}', '\u{0C8A}', '\u{0C8B}', '\u{0C8C}', '\u{0C8E}', '\u{0C8F}', '\u{0C90}', '\u{0C92}', '\u{0C93}', '\u{0C94}', '\u{0C95}', '\u{0C96}', '\u{0C97}', '\u{0C98}', '\u{0C99}', '\u{0C9A}', '\u{0C9B}', '\u{0C9C}', '\u{0C9D}', '\u{0C9E}', '\u{0C9F}', '\u{0CA0}', '\u{0CA1}', '\u{0CA2}', '\u{0CA3}', '\u{0CA4}', '\u{0CA5}', '\u{0CA6}', '\u{0CA7}', '\u{0CA8}', '\u{0CAA}', '\u{0CAB}', '\u{0CAC}', '\u{0CAD}', '\u{0CAE}', '\u{0CAF}', '\u{0CB0}', '\u{0CB1}', '\u{0CB2}', '\u{0CB3}', '\u{0CB5}', '\u{0CB6}', '\u{0CB7}', '\u{0CB8}', '\u{0CB9}', '\u{0CBD}', '\u{0CDE}', '\u{0CE0}', '\u{0CE1}', '\u{0D05}', '\u{0D06}', '\u{0D07}', '\u{0D08}', '\u{0D09}', '\u{0D0A}', '\u{0D0B}', '\u{0D0C}', '\u{0D0E}', '\u{0D0F}', '\u{0D10}', '\u{0D12}', '\u{0D13}', '\u{0D14}', '\u{0D15}', '\u{0D16}', '\u{0D17}', '\u{0D18}', '\u{0D19}', '\u{0D1A}', '\u{0D1B}', '\u{0D1C}', '\u{0D1D}', '\u{0D1E}', '\u{0D1F}', '\u{0D20}', '\u{0D21}', '\u{0D22}', '\u{0D23}', '\u{0D24}', '\u{0D25}', '\u{0D26}', '\u{0D27}', '\u{0D28}', '\u{0D2A}', '\u{0D2B}', '\u{0D2C}', '\u{0D2D}', '\u{0D2E}', '\u{0D2F}', '\u{0D30}', '\u{0D31}', '\u{0D32}', '\u{0D33}', '\u{0D34}', '\u{0D35}', '\u{0D36}', '\u{0D37}', '\u{0D38}', '\u{0D39}', '\u{0D3D}', '\u{0D60}', '\u{0D61}', '\u{0D7A}', '\u{0D7B}', '\u{0D7C}', '\u{0D7D}', '\u{0D7E}', '\u{0D7F}', '\u{0D85}', '\u{0D86}', '\u{0D87}', '\u{0D88}', '\u{0D89}', '\u{0D8A}', '\u{0D8B}', '\u{0D8C}', '\u{0D8D}', '\u{0D8E}', '\u{0D8F}', '\u{0D90}', '\u{0D91}', '\u{0D92}', '\u{0D93}', '\u{0D94}', '\u{0D95}', '\u{0D96}', '\u{0D9A}', '\u{0D9B}', '\u{0D9C}', '\u{0D9D}', '\u{0D9E}', '\u{0D9F}', '\u{0DA0}', '\u{0DA1}', '\u{0DA2}', '\u{0DA3}', '\u{0DA4}', '\u{0DA5}', '\u{0DA6}', '\u{0DA7}', '\u{0DA8}', '\u{0DA9}', '\u{0DAA}', '\u{0DAB}', '\u{0DAC}', '\u{0DAD}', '\u{0DAE}', '\u{0DAF}', '\u{0DB0}', '\u{0DB1}', '\u{0DB3}', '\u{0DB4}', '\u{0DB5}', '\u{0DB6}', '\u{0DB7}', '\u{0DB8}', '\u{0DB9}', '\u{0DBA}', '\u{0DBB}', '\u{0DBD}', '\u{0DC0}', '\u{0DC1}', '\u{0DC2}', '\u{0DC3}', '\u{0DC4}', '\u{0DC5}', '\u{0DC6}', '\u{0E01}', '\u{0E02}', '\u{0E03}', '\u{0E04}', '\u{0E05}', '\u{0E06}', '\u{0E07}', '\u{0E08}', '\u{0E09}', '\u{0E0A}', '\u{0E0B}', '\u{0E0C}', '\u{0E0D}', '\u{0E0E}', '\u{0E0F}', '\u{0E10}', '\u{0E11}', '\u{0E12}', '\u{0E13}', '\u{0E14}', '\u{0E15}', '\u{0E16}', '\u{0E17}', '\u{0E18}', '\u{0E19}', '\u{0E1A}', '\u{0E1B}', '\u{0E1C}', '\u{0E1D}', '\u{0E1E}', '\u{0E1F}', '\u{0E20}', '\u{0E21}', '\u{0E22}', '\u{0E23}', '\u{0E24}', '\u{0E25}', '\u{0E26}', '\u{0E27}', '\u{0E28}', '\u{0E29}', '\u{0E2A}', '\u{0E2B}', '\u{0E2C}', '\u{0E2D}', '\u{0E2E}', '\u{0E2F}', '\u{0E30}', '\u{0E32}', '\u{0E33}', '\u{0E40}', '\u{0E41}', '\u{0E42}', '\u{0E43}', '\u{0E44}', '\u{0E45}', '\u{0E81}', '\u{0E82}', '\u{0E84}', '\u{0E87}', '\u{0E88}', '\u{0E8A}', '\u{0E8D}', '\u{0E94}', '\u{0E95}', '\u{0E96}', '\u{0E97}', '\u{0E99}', '\u{0E9A}', '\u{0E9B}', '\u{0E9C}', '\u{0E9D}', '\u{0E9E}', '\u{0E9F}', '\u{0EA1}', '\u{0EA2}', '\u{0EA3}', '\u{0EA5}', '\u{0EA7}', '\u{0EAA}', '\u{0EAB}', '\u{0EAD}', '\u{0EAE}', '\u{0EAF}', '\u{0EB0}', '\u{0EB2}', '\u{0EB3}', '\u{0EBD}', '\u{0EC0}', '\u{0EC1}', '\u{0EC2}', '\u{0EC3}', '\u{0EC4}', '\u{0EDC}', '\u{0EDD}', '\u{0F00}', '\u{0F40}', '\u{0F41}', '\u{0F42}', '\u{0F43}', '\u{0F44}', '\u{0F45}', '\u{0F46}', '\u{0F47}', '\u{0F49}', '\u{0F4A}', '\u{0F4B}', '\u{0F4C}', '\u{0F4D}', '\u{0F4E}', '\u{0F4F}', '\u{0F50}', '\u{0F51}', '\u{0F52}', '\u{0F53}', '\u{0F54}', '\u{0F55}', '\u{0F56}', '\u{0F57}', '\u{0F58}', '\u{0F59}', '\u{0F5A}', '\u{0F5B}', '\u{0F5C}', '\u{0F5D}', '\u{0F5E}', '\u{0F5F}', '\u{0F60}', '\u{0F61}', '\u{0F62}', '\u{0F63}', '\u{0F64}', '\u{0F65}', '\u{0F66}', '\u{0F67}', '\u{0F68}', '\u{0F69}', '\u{0F6A}', '\u{0F6B}', '\u{0F6C}', '\u{0F88}', '\u{0F89}', '\u{0F8A}', '\u{0F8B}', '\u{1000}', '\u{1001}', '\u{1002}', '\u{1003}', '\u{1004}', '\u{1005}', '\u{1006}', '\u{1007}', '\u{1008}', '\u{1009}', '\u{100A}', '\u{100B}', '\u{100C}', '\u{100D}', '\u{100E}', '\u{100F}', '\u{1010}', '\u{1011}', '\u{1012}', '\u{1013}', '\u{1014}', '\u{1015}', '\u{1016}', '\u{1017}', '\u{1018}', '\u{1019}', '\u{101A}', '\u{101B}', '\u{101C}', '\u{101D}', '\u{101E}', '\u{101F}', '\u{1020}', '\u{1021}', '\u{1022}', '\u{1023}', '\u{1024}', '\u{1025}', '\u{1026}', '\u{1027}', '\u{1028}', '\u{1029}', '\u{102A}', '\u{103F}', '\u{1050}', '\u{1051}', '\u{1052}', '\u{1053}', '\u{1054}', '\u{1055}', '\u{105A}', '\u{105B}', '\u{105C}', '\u{105D}', '\u{1061}', '\u{1065}', '\u{1066}', '\u{106E}', '\u{106F}', '\u{1070}', '\u{1075}', '\u{1076}', '\u{1077}', '\u{1078}', '\u{1079}', '\u{107A}', '\u{107B}', '\u{107C}', '\u{107D}', '\u{107E}', '\u{107F}', '\u{1080}', '\u{1081}', '\u{108E}', '\u{10D0}', '\u{10D1}', '\u{10D2}', '\u{10D3}', '\u{10D4}', '\u{10D5}', '\u{10D6}', '\u{10D7}', '\u{10D8}', '\u{10D9}', '\u{10DA}', '\u{10DB}', '\u{10DC}', '\u{10DD}', '\u{10DE}', '\u{10DF}', '\u{10E0}', '\u{10E1}', '\u{10E2}', '\u{10E3}', '\u{10E4}', '\u{10E5}', '\u{10E6}', '\u{10E7}', '\u{10E8}', '\u{10E9}', '\u{10EA}', '\u{10EB}', '\u{10EC}', '\u{10ED}', '\u{10EE}', '\u{10EF}', '\u{10F0}', '\u{10F1}', '\u{10F2}', '\u{10F3}', '\u{10F4}', '\u{10F5}', '\u{10F6}', '\u{10F7}', '\u{10F8}', '\u{10F9}', '\u{10FA}', '\u{1100}', '\u{1101}', '\u{1102}', '\u{1103}', '\u{1104}', '\u{1105}', '\u{1106}', '\u{1107}', '\u{1108}', '\u{1109}', '\u{110A}', '\u{110B}', '\u{110C}', '\u{110D}', '\u{110E}', '\u{110F}', '\u{1110}', '\u{1111}', '\u{1112}', '\u{1113}', '\u{1114}', '\u{1115}', '\u{1116}', '\u{1117}', '\u{1118}', '\u{1119}', '\u{111A}', '\u{111B}', '\u{111C}', '\u{111D}', '\u{111E}', '\u{111F}', '\u{1120}', '\u{1121}', '\u{1122}', '\u{1123}', '\u{1124}', '\u{1125}', '\u{1126}', '\u{1127}', '\u{1128}', '\u{1129}', '\u{112A}', '\u{112B}', '\u{112C}', '\u{112D}', '\u{112E}', '\u{112F}', '\u{1130}', '\u{1131}', '\u{1132}', '\u{1133}', '\u{1134}', '\u{1135}', '\u{1136}', '\u{1137}', '\u{1138}', '\u{1139}', '\u{113A}', '\u{113B}', '\u{113C}', '\u{113D}', '\u{113E}', '\u{113F}', '\u{1140}', '\u{1141}', '\u{1142}', '\u{1143}', '\u{1144}', '\u{1145}', '\u{1146}', '\u{1147}', '\u{1148}', '\u{1149}', '\u{114A}', '\u{114B}', '\u{114C}', '\u{114D}', '\u{114E}', '\u{114F}', '\u{1150}', '\u{1151}', '\u{1152}', '\u{1153}', '\u{1154}', '\u{1155}', '\u{1156}', '\u{1157}', '\u{1158}', '\u{1159}', '\u{115F}', '\u{1160}', '\u{1161}', '\u{1162}', '\u{1163}', '\u{1164}', '\u{1165}', '\u{1166}', '\u{1167}', '\u{1168}', '\u{1169}', '\u{116A}', '\u{116B}', '\u{116C}', '\u{116D}', '\u{116E}', '\u{116F}', '\u{1170}', '\u{1171}', '\u{1172}', '\u{1173}', '\u{1174}', '\u{1175}', '\u{1176}', '\u{1177}', '\u{1178}', '\u{1179}', '\u{117A}', '\u{117B}', '\u{117C}', '\u{117D}', '\u{117E}', '\u{117F}', '\u{1180}', '\u{1181}', '\u{1182}', '\u{1183}', '\u{1184}', '\u{1185}', '\u{1186}', '\u{1187}', '\u{1188}', '\u{1189}', '\u{118A}', '\u{118B}', '\u{118C}', '\u{118D}', '\u{118E}', '\u{118F}', '\u{1190}', '\u{1191}', '\u{1192}', '\u{1193}', '\u{1194}', '\u{1195}', '\u{1196}', '\u{1197}', '\u{1198}', '\u{1199}', '\u{119A}', '\u{119B}', '\u{119C}', '\u{119D}', '\u{119E}', '\u{119F}', '\u{11A0}', '\u{11A1}', '\u{11A2}', '\u{11A8}', '\u{11A9}', '\u{11AA}', '\u{11AB}', '\u{11AC}', '\u{11AD}', '\u{11AE}', '\u{11AF}', '\u{11B0}', '\u{11B1}', '\u{11B2}', '\u{11B3}', '\u{11B4}', '\u{11B5}', '\u{11B6}', '\u{11B7}', '\u{11B8}', '\u{11B9}', '\u{11BA}', '\u{11BB}', '\u{11BC}', '\u{11BD}', '\u{11BE}', '\u{11BF}', '\u{11C0}', '\u{11C1}', '\u{11C2}', '\u{11C3}', '\u{11C4}', '\u{11C5}', '\u{11C6}', '\u{11C7}', '\u{11C8}', '\u{11C9}', '\u{11CA}', '\u{11CB}', '\u{11CC}', '\u{11CD}', '\u{11CE}', '\u{11CF}', '\u{11D0}', '\u{11D1}', '\u{11D2}', '\u{11D3}', '\u{11D4}', '\u{11D5}', '\u{11D6}', '\u{11D7}', '\u{11D8}', '\u{11D9}', '\u{11DA}', '\u{11DB}', '\u{11DC}', '\u{11DD}', '\u{11DE}', '\u{11DF}', '\u{11E0}', '\u{11E1}', '\u{11E2}', '\u{11E3}', '\u{11E4}', '\u{11E5}', '\u{11E6}', '\u{11E7}', '\u{11E8}', '\u{11E9}', '\u{11EA}', '\u{11EB}', '\u{11EC}', '\u{11ED}', '\u{11EE}', '\u{11EF}', '\u{11F0}', '\u{11F1}', '\u{11F2}', '\u{11F3}', '\u{11F4}', '\u{11F5}', '\u{11F6}', '\u{11F7}', '\u{11F8}', '\u{11F9}', '\u{1200}', '\u{1201}', '\u{1202}', '\u{1203}', '\u{1204}', '\u{1205}', '\u{1206}', '\u{1207}', '\u{1208}', '\u{1209}', '\u{120A}', '\u{120B}', '\u{120C}', '\u{120D}', '\u{120E}', '\u{120F}', '\u{1210}', '\u{1211}', '\u{1212}', '\u{1213}', '\u{1214}', '\u{1215}', '\u{1216}', '\u{1217}', '\u{1218}', '\u{1219}', '\u{121A}', '\u{121B}', '\u{121C}', '\u{121D}', '\u{121E}', '\u{121F}', '\u{1220}', '\u{1221}', '\u{1222}', '\u{1223}', '\u{1224}', '\u{1225}', '\u{1226}', '\u{1227}', '\u{1228}', '\u{1229}', '\u{122A}', '\u{122B}', '\u{122C}', '\u{122D}', '\u{122E}', '\u{122F}', '\u{1230}', '\u{1231}', '\u{1232}', '\u{1233}', '\u{1234}', '\u{1235}', '\u{1236}', '\u{1237}', '\u{1238}', '\u{1239}', '\u{123A}', '\u{123B}', '\u{123C}', '\u{123D}', '\u{123E}', '\u{123F}', '\u{1240}', '\u{1241}', '\u{1242}', '\u{1243}', '\u{1244}', '\u{1245}', '\u{1246}', '\u{1247}', '\u{1248}', '\u{124A}', '\u{124B}', '\u{124C}', '\u{124D}', '\u{1250}', '\u{1251}', '\u{1252}', '\u{1253}', '\u{1254}', '\u{1255}', '\u{1256}', '\u{1258}', '\u{125A}', '\u{125B}', '\u{125C}', '\u{125D}', '\u{1260}', '\u{1261}', '\u{1262}', '\u{1263}', '\u{1264}', '\u{1265}', '\u{1266}', '\u{1267}', '\u{1268}', '\u{1269}', '\u{126A}', '\u{126B}', '\u{126C}', '\u{126D}', '\u{126E}', '\u{126F}', '\u{1270}', '\u{1271}', '\u{1272}', '\u{1273}', '\u{1274}', '\u{1275}', '\u{1276}', '\u{1277}', '\u{1278}', '\u{1279}', '\u{127A}', '\u{127B}', '\u{127C}', '\u{127D}', '\u{127E}', '\u{127F}', '\u{1280}', '\u{1281}', '\u{1282}', '\u{1283}', '\u{1284}', '\u{1285}', '\u{1286}', '\u{1287}', '\u{1288}', '\u{128A}', '\u{128B}', '\u{128C}', '\u{128D}', '\u{1290}', '\u{1291}', '\u{1292}', '\u{1293}', '\u{1294}', '\u{1295}', '\u{1296}', '\u{1297}', '\u{1298}', '\u{1299}', '\u{129A}', '\u{129B}', '\u{129C}', '\u{129D}', '\u{129E}', '\u{129F}', '\u{12A0}', '\u{12A1}', '\u{12A2}', '\u{12A3}', '\u{12A4}', '\u{12A5}', '\u{12A6}', '\u{12A7}', '\u{12A8}', '\u{12A9}', '\u{12AA}', '\u{12AB}', '\u{12AC}', '\u{12AD}', '\u{12AE}', '\u{12AF}', '\u{12B0}', '\u{12B2}', '\u{12B3}', '\u{12B4}', '\u{12B5}', '\u{12B8}', '\u{12B9}', '\u{12BA}', '\u{12BB}', '\u{12BC}', '\u{12BD}', '\u{12BE}', '\u{12C0}', '\u{12C2}', '\u{12C3}', '\u{12C4}', '\u{12C5}', '\u{12C8}', '\u{12C9}', '\u{12CA}', '\u{12CB}', '\u{12CC}', '\u{12CD}', '\u{12CE}', '\u{12CF}', '\u{12D0}', '\u{12D1}', '\u{12D2}', '\u{12D3}', '\u{12D4}', '\u{12D5}', '\u{12D6}', '\u{12D8}', '\u{12D9}', '\u{12DA}', '\u{12DB}', '\u{12DC}', '\u{12DD}', '\u{12DE}', '\u{12DF}', '\u{12E0}', '\u{12E1}', '\u{12E2}', '\u{12E3}', '\u{12E4}', '\u{12E5}', '\u{12E6}', '\u{12E7}', '\u{12E8}', '\u{12E9}', '\u{12EA}', '\u{12EB}', '\u{12EC}', '\u{12ED}', '\u{12EE}', '\u{12EF}', '\u{12F0}', '\u{12F1}', '\u{12F2}', '\u{12F3}', '\u{12F4}', '\u{12F5}', '\u{12F6}', '\u{12F7}', '\u{12F8}', '\u{12F9}', '\u{12FA}', '\u{12FB}', '\u{12FC}', '\u{12FD}', '\u{12FE}', '\u{12FF}', '\u{1300}', '\u{1301}', '\u{1302}', '\u{1303}', '\u{1304}', '\u{1305}', '\u{1306}', '\u{1307}', '\u{1308}', '\u{1309}', '\u{130A}', '\u{130B}', '\u{130C}', '\u{130D}', '\u{130E}', '\u{130F}', '\u{1310}', '\u{1312}', '\u{1313}', '\u{1314}', '\u{1315}', '\u{1318}', '\u{1319}', '\u{131A}', '\u{131B}', '\u{131C}', '\u{131D}', '\u{131E}', '\u{131F}', '\u{1320}', '\u{1321}', '\u{1322}', '\u{1323}', '\u{1324}', '\u{1325}', '\u{1326}', '\u{1327}', '\u{1328}', '\u{1329}', '\u{132A}', '\u{132B}', '\u{132C}', '\u{132D}', '\u{132E}', '\u{132F}', '\u{1330}', '\u{1331}', '\u{1332}', '\u{1333}', '\u{1334}', '\u{1335}', '\u{1336}', '\u{1337}', '\u{1338}', '\u{1339}', '\u{133A}', '\u{133B}', '\u{133C}', '\u{133D}', '\u{133E}', '\u{133F}', '\u{1340}', '\u{1341}', '\u{1342}', '\u{1343}', '\u{1344}', '\u{1345}', '\u{1346}', '\u{1347}', '\u{1348}', '\u{1349}', '\u{134A}', '\u{134B}', '\u{134C}', '\u{134D}', '\u{134E}', '\u{134F}', '\u{1350}', '\u{1351}', '\u{1352}', '\u{1353}', '\u{1354}', '\u{1355}', '\u{1356}', '\u{1357}', '\u{1358}', '\u{1359}', '\u{135A}', '\u{1380}', '\u{1381}', '\u{1382}', '\u{1383}', '\u{1384}', '\u{1385}', '\u{1386}', '\u{1387}', '\u{1388}', '\u{1389}', '\u{138A}', '\u{138B}', '\u{138C}', '\u{138D}', '\u{138E}', '\u{138F}', '\u{13A0}', '\u{13A1}', '\u{13A2}', '\u{13A3}', '\u{13A4}', '\u{13A5}', '\u{13A6}', '\u{13A7}', '\u{13A8}', '\u{13A9}', '\u{13AA}', '\u{13AB}', '\u{13AC}', '\u{13AD}', '\u{13AE}', '\u{13AF}', '\u{13B0}', '\u{13B1}', '\u{13B2}', '\u{13B3}', '\u{13B4}', '\u{13B5}', '\u{13B6}', '\u{13B7}', '\u{13B8}', '\u{13B9}', '\u{13BA}', '\u{13BB}', '\u{13BC}', '\u{13BD}', '\u{13BE}', '\u{13BF}', '\u{13C0}', '\u{13C1}', '\u{13C2}', '\u{13C3}', '\u{13C4}', '\u{13C5}', '\u{13C6}', '\u{13C7}', '\u{13C8}', '\u{13C9}', '\u{13CA}', '\u{13CB}', '\u{13CC}', '\u{13CD}', '\u{13CE}', '\u{13CF}', '\u{13D0}', '\u{13D1}', '\u{13D2}', '\u{13D3}', '\u{13D4}', '\u{13D5}', '\u{13D6}', '\u{13D7}', '\u{13D8}', '\u{13D9}', '\u{13DA}', '\u{13DB}', '\u{13DC}', '\u{13DD}', '\u{13DE}', '\u{13DF}', '\u{13E0}', '\u{13E1}', '\u{13E2}', '\u{13E3}', '\u{13E4}', '\u{13E5}', '\u{13E6}', '\u{13E7}', '\u{13E8}', '\u{13E9}', '\u{13EA}', '\u{13EB}', '\u{13EC}', '\u{13ED}', '\u{13EE}', '\u{13EF}', '\u{13F0}', '\u{13F1}', '\u{13F2}', '\u{13F3}', '\u{13F4}', '\u{1401}', '\u{1402}', '\u{1403}', '\u{1404}', '\u{1405}', '\u{1406}', '\u{1407}', '\u{1408}', '\u{1409}', '\u{140A}', '\u{140B}', '\u{140C}', '\u{140D}', '\u{140E}', '\u{140F}', '\u{1410}', '\u{1411}', '\u{1412}', '\u{1413}', '\u{1414}', '\u{1415}', '\u{1416}', '\u{1417}', '\u{1418}', '\u{1419}', '\u{141A}', '\u{141B}', '\u{141C}', '\u{141D}', '\u{141E}', '\u{141F}', '\u{1420}', '\u{1421}', '\u{1422}', '\u{1423}', '\u{1424}', '\u{1425}', '\u{1426}', '\u{1427}', '\u{1428}', '\u{1429}', '\u{142A}', '\u{142B}', '\u{142C}', '\u{142D}', '\u{142E}', '\u{142F}', '\u{1430}', '\u{1431}', '\u{1432}', '\u{1433}', '\u{1434}', '\u{1435}', '\u{1436}', '\u{1437}', '\u{1438}', '\u{1439}', '\u{143A}', '\u{143B}', '\u{143C}', '\u{143D}', '\u{143E}', '\u{143F}', '\u{1440}', '\u{1441}', '\u{1442}', '\u{1443}', '\u{1444}', '\u{1445}', '\u{1446}', '\u{1447}', '\u{1448}', '\u{1449}', '\u{144A}', '\u{144B}', '\u{144C}', '\u{144D}', '\u{144E}', '\u{144F}', '\u{1450}', '\u{1451}', '\u{1452}', '\u{1453}', '\u{1454}', '\u{1455}', '\u{1456}', '\u{1457}', '\u{1458}', '\u{1459}', '\u{145A}', '\u{145B}', '\u{145C}', '\u{145D}', '\u{145E}', '\u{145F}', '\u{1460}', '\u{1461}', '\u{1462}', '\u{1463}', '\u{1464}', '\u{1465}', '\u{1466}', '\u{1467}', '\u{1468}', '\u{1469}', '\u{146A}', '\u{146B}', '\u{146C}', '\u{146D}', '\u{146E}', '\u{146F}', '\u{1470}', '\u{1471}', '\u{1472}', '\u{1473}', '\u{1474}', '\u{1475}', '\u{1476}', '\u{1477}', '\u{1478}', '\u{1479}', '\u{147A}', '\u{147B}', '\u{147C}', '\u{147D}', '\u{147E}', '\u{147F}', '\u{1480}', '\u{1481}', '\u{1482}', '\u{1483}', '\u{1484}', '\u{1485}', '\u{1486}', '\u{1487}', '\u{1488}', '\u{1489}', '\u{148A}', '\u{148B}', '\u{148C}', '\u{148D}', '\u{148E}', '\u{148F}', '\u{1490}', '\u{1491}', '\u{1492}', '\u{1493}', '\u{1494}', '\u{1495}', '\u{1496}', '\u{1497}', '\u{1498}', '\u{1499}', '\u{149A}', '\u{149B}', '\u{149C}', '\u{149D}', '\u{149E}', '\u{149F}', '\u{14A0}', '\u{14A1}', '\u{14A2}', '\u{14A3}', '\u{14A4}', '\u{14A5}', '\u{14A6}', '\u{14A7}', '\u{14A8}', '\u{14A9}', '\u{14AA}', '\u{14AB}', '\u{14AC}', '\u{14AD}', '\u{14AE}', '\u{14AF}', '\u{14B0}', '\u{14B1}', '\u{14B2}', '\u{14B3}', '\u{14B4}', '\u{14B5}', '\u{14B6}', '\u{14B7}', '\u{14B8}', '\u{14B9}', '\u{14BA}', '\u{14BB}', '\u{14BC}', '\u{14BD}', '\u{14BE}', '\u{14BF}', '\u{14C0}', '\u{14C1}', '\u{14C2}', '\u{14C3}', '\u{14C4}', '\u{14C5}', '\u{14C6}', '\u{14C7}', '\u{14C8}', '\u{14C9}', '\u{14CA}', '\u{14CB}', '\u{14CC}', '\u{14CD}', '\u{14CE}', '\u{14CF}', '\u{14D0}', '\u{14D1}', '\u{14D2}', '\u{14D3}', '\u{14D4}', '\u{14D5}', '\u{14D6}', '\u{14D7}', '\u{14D8}', '\u{14D9}', '\u{14DA}', '\u{14DB}', '\u{14DC}', '\u{14DD}', '\u{14DE}', '\u{14DF}', '\u{14E0}', '\u{14E1}', '\u{14E2}', '\u{14E3}', '\u{14E4}', '\u{14E5}', '\u{14E6}', '\u{14E7}', '\u{14E8}', '\u{14E9}', '\u{14EA}', '\u{14EB}', '\u{14EC}', '\u{14ED}', '\u{14EE}', '\u{14EF}', '\u{14F0}', '\u{14F1}', '\u{14F2}', '\u{14F3}', '\u{14F4}', '\u{14F5}', '\u{14F6}', '\u{14F7}', '\u{14F8}', '\u{14F9}', '\u{14FA}', '\u{14FB}', '\u{14FC}', '\u{14FD}', '\u{14FE}', '\u{14FF}', '\u{1500}', '\u{1501}', '\u{1502}', '\u{1503}', '\u{1504}', '\u{1505}', '\u{1506}', '\u{1507}', '\u{1508}', '\u{1509}', '\u{150A}', '\u{150B}', '\u{150C}', '\u{150D}', '\u{150E}', '\u{150F}', '\u{1510}', '\u{1511}', '\u{1512}', '\u{1513}', '\u{1514}', '\u{1515}', '\u{1516}', '\u{1517}', '\u{1518}', '\u{1519}', '\u{151A}', '\u{151B}', '\u{151C}', '\u{151D}', '\u{151E}', '\u{151F}', '\u{1520}', '\u{1521}', '\u{1522}', '\u{1523}', '\u{1524}', '\u{1525}', '\u{1526}', '\u{1527}', '\u{1528}', '\u{1529}', '\u{152A}', '\u{152B}', '\u{152C}', '\u{152D}', '\u{152E}', '\u{152F}', '\u{1530}', '\u{1531}', '\u{1532}', '\u{1533}', '\u{1534}', '\u{1535}', '\u{1536}', '\u{1537}', '\u{1538}', '\u{1539}', '\u{153A}', '\u{153B}', '\u{153C}', '\u{153D}', '\u{153E}', '\u{153F}', '\u{1540}', '\u{1541}', '\u{1542}', '\u{1543}', '\u{1544}', '\u{1545}', '\u{1546}', '\u{1547}', '\u{1548}', '\u{1549}', '\u{154A}', '\u{154B}', '\u{154C}', '\u{154D}', '\u{154E}', '\u{154F}', '\u{1550}', '\u{1551}', '\u{1552}', '\u{1553}', '\u{1554}', '\u{1555}', '\u{1556}', '\u{1557}', '\u{1558}', '\u{1559}', '\u{155A}', '\u{155B}', '\u{155C}', '\u{155D}', '\u{155E}', '\u{155F}', '\u{1560}', '\u{1561}', '\u{1562}', '\u{1563}', '\u{1564}', '\u{1565}', '\u{1566}', '\u{1567}', '\u{1568}', '\u{1569}', '\u{156A}', '\u{156B}', '\u{156C}', '\u{156D}', '\u{156E}', '\u{156F}', '\u{1570}', '\u{1571}', '\u{1572}', '\u{1573}', '\u{1574}', '\u{1575}', '\u{1576}', '\u{1577}', '\u{1578}', '\u{1579}', '\u{157A}', '\u{157B}', '\u{157C}', '\u{157D}', '\u{157E}', '\u{157F}', '\u{1580}', '\u{1581}', '\u{1582}', '\u{1583}', '\u{1584}', '\u{1585}', '\u{1586}', '\u{1587}', '\u{1588}', '\u{1589}', '\u{158A}', '\u{158B}', '\u{158C}', '\u{158D}', '\u{158E}', '\u{158F}', '\u{1590}', '\u{1591}', '\u{1592}', '\u{1593}', '\u{1594}', '\u{1595}', '\u{1596}', '\u{1597}', '\u{1598}', '\u{1599}', '\u{159A}', '\u{159B}', '\u{159C}', '\u{159D}', '\u{159E}', '\u{159F}', '\u{15A0}', '\u{15A1}', '\u{15A2}', '\u{15A3}', '\u{15A4}', '\u{15A5}', '\u{15A6}', '\u{15A7}', '\u{15A8}', '\u{15A9}', '\u{15AA}', '\u{15AB}', '\u{15AC}', '\u{15AD}', '\u{15AE}', '\u{15AF}', '\u{15B0}', '\u{15B1}', '\u{15B2}', '\u{15B3}', '\u{15B4}', '\u{15B5}', '\u{15B6}', '\u{15B7}', '\u{15B8}', '\u{15B9}', '\u{15BA}', '\u{15BB}', '\u{15BC}', '\u{15BD}', '\u{15BE}', '\u{15BF}', '\u{15C0}', '\u{15C1}', '\u{15C2}', '\u{15C3}', '\u{15C4}', '\u{15C5}', '\u{15C6}', '\u{15C7}', '\u{15C8}', '\u{15C9}', '\u{15CA}', '\u{15CB}', '\u{15CC}', '\u{15CD}', '\u{15CE}', '\u{15CF}', '\u{15D0}', '\u{15D1}', '\u{15D2}', '\u{15D3}', '\u{15D4}', '\u{15D5}', '\u{15D6}', '\u{15D7}', '\u{15D8}', '\u{15D9}', '\u{15DA}', '\u{15DB}', '\u{15DC}', '\u{15DD}', '\u{15DE}', '\u{15DF}', '\u{15E0}', '\u{15E1}', '\u{15E2}', '\u{15E3}', '\u{15E4}', '\u{15E5}', '\u{15E6}', '\u{15E7}', '\u{15E8}', '\u{15E9}', '\u{15EA}', '\u{15EB}', '\u{15EC}', '\u{15ED}', '\u{15EE}', '\u{15EF}', '\u{15F0}', '\u{15F1}', '\u{15F2}', '\u{15F3}', '\u{15F4}', '\u{15F5}', '\u{15F6}', '\u{15F7}', '\u{15F8}', '\u{15F9}', '\u{15FA}', '\u{15FB}', '\u{15FC}', '\u{15FD}', '\u{15FE}', '\u{15FF}', '\u{1600}', '\u{1601}', '\u{1602}', '\u{1603}', '\u{1604}', '\u{1605}', '\u{1606}', '\u{1607}', '\u{1608}', '\u{1609}', '\u{160A}', '\u{160B}', '\u{160C}', '\u{160D}', '\u{160E}', '\u{160F}', '\u{1610}', '\u{1611}', '\u{1612}', '\u{1613}', '\u{1614}', '\u{1615}', '\u{1616}', '\u{1617}', '\u{1618}', '\u{1619}', '\u{161A}', '\u{161B}', '\u{161C}', '\u{161D}', '\u{161E}', '\u{161F}', '\u{1620}', '\u{1621}', '\u{1622}', '\u{1623}', '\u{1624}', '\u{1625}', '\u{1626}', '\u{1627}', '\u{1628}', '\u{1629}', '\u{162A}', '\u{162B}', '\u{162C}', '\u{162D}', '\u{162E}', '\u{162F}', '\u{1630}', '\u{1631}', '\u{1632}', '\u{1633}', '\u{1634}', '\u{1635}', '\u{1636}', '\u{1637}', '\u{1638}', '\u{1639}', '\u{163A}', '\u{163B}', '\u{163C}', '\u{163D}', '\u{163E}', '\u{163F}', '\u{1640}', '\u{1641}', '\u{1642}', '\u{1643}', '\u{1644}', '\u{1645}', '\u{1646}', '\u{1647}', '\u{1648}', '\u{1649}', '\u{164A}', '\u{164B}', '\u{164C}', '\u{164D}', '\u{164E}', '\u{164F}', '\u{1650}', '\u{1651}', '\u{1652}', '\u{1653}', '\u{1654}', '\u{1655}', '\u{1656}', '\u{1657}', '\u{1658}', '\u{1659}', '\u{165A}', '\u{165B}', '\u{165C}', '\u{165D}', '\u{165E}', '\u{165F}', '\u{1660}', '\u{1661}', '\u{1662}', '\u{1663}', '\u{1664}', '\u{1665}', '\u{1666}', '\u{1667}', '\u{1668}', '\u{1669}', '\u{166A}', '\u{166B}', '\u{166C}', '\u{166F}', '\u{1670}', '\u{1671}', '\u{1672}', '\u{1673}', '\u{1674}', '\u{1675}', '\u{1676}', '\u{1681}', '\u{1682}', '\u{1683}', '\u{1684}', '\u{1685}', '\u{1686}', '\u{1687}', '\u{1688}', '\u{1689}', '\u{168A}', '\u{168B}', '\u{168C}', '\u{168D}', '\u{168E}', '\u{168F}', '\u{1690}', '\u{1691}', '\u{1692}', '\u{1693}', '\u{1694}', '\u{1695}', '\u{1696}', '\u{1697}', '\u{1698}', '\u{1699}', '\u{169A}', '\u{16A0}', '\u{16A1}', '\u{16A2}', '\u{16A3}', '\u{16A4}', '\u{16A5}', '\u{16A6}', '\u{16A7}', '\u{16A8}', '\u{16A9}', '\u{16AA}', '\u{16AB}', '\u{16AC}', '\u{16AD}', '\u{16AE}', '\u{16AF}', '\u{16B0}', '\u{16B1}', '\u{16B2}', '\u{16B3}', '\u{16B4}', '\u{16B5}', '\u{16B6}', '\u{16B7}', '\u{16B8}', '\u{16B9}', '\u{16BA}', '\u{16BB}', '\u{16BC}', '\u{16BD}', '\u{16BE}', '\u{16BF}', '\u{16C0}', '\u{16C1}', '\u{16C2}', '\u{16C3}', '\u{16C4}', '\u{16C5}', '\u{16C6}', '\u{16C7}', '\u{16C8}', '\u{16C9}', '\u{16CA}', '\u{16CB}', '\u{16CC}', '\u{16CD}', '\u{16CE}', '\u{16CF}', '\u{16D0}', '\u{16D1}', '\u{16D2}', '\u{16D3}', '\u{16D4}', '\u{16D5}', '\u{16D6}', '\u{16D7}', '\u{16D8}', '\u{16D9}', '\u{16DA}', '\u{16DB}', '\u{16DC}', '\u{16DD}', '\u{16DE}', '\u{16DF}', '\u{16E0}', '\u{16E1}', '\u{16E2}', '\u{16E3}', '\u{16E4}', '\u{16E5}', '\u{16E6}', '\u{16E7}', '\u{16E8}', '\u{16E9}', '\u{16EA}', '\u{1700}', '\u{1701}', '\u{1702}', '\u{1703}', '\u{1704}', '\u{1705}', '\u{1706}', '\u{1707}', '\u{1708}', '\u{1709}', '\u{170A}', '\u{170B}', '\u{170C}', '\u{170E}', '\u{170F}', '\u{1710}', '\u{1711}', '\u{1720}', '\u{1721}', '\u{1722}', '\u{1723}', '\u{1724}', '\u{1725}', '\u{1726}', '\u{1727}', '\u{1728}', '\u{1729}', '\u{172A}', '\u{172B}', '\u{172C}', '\u{172D}', '\u{172E}', '\u{172F}', '\u{1730}', '\u{1731}', '\u{1740}', '\u{1741}', '\u{1742}', '\u{1743}', '\u{1744}', '\u{1745}', '\u{1746}', '\u{1747}', '\u{1748}', '\u{1749}', '\u{174A}', '\u{174B}', '\u{174C}', '\u{174D}', '\u{174E}', '\u{174F}', '\u{1750}', '\u{1751}', '\u{1760}', '\u{1761}', '\u{1762}', '\u{1763}', '\u{1764}', '\u{1765}', '\u{1766}', '\u{1767}', '\u{1768}', '\u{1769}', '\u{176A}', '\u{176B}', '\u{176C}', '\u{176E}', '\u{176F}', '\u{1770}', '\u{1780}', '\u{1781}', '\u{1782}', '\u{1783}', '\u{1784}', '\u{1785}', '\u{1786}', '\u{1787}', '\u{1788}', '\u{1789}', '\u{178A}', '\u{178B}', '\u{178C}', '\u{178D}', '\u{178E}', '\u{178F}', '\u{1790}', '\u{1791}', '\u{1792}', '\u{1793}', '\u{1794}', '\u{1795}', '\u{1796}', '\u{1797}', '\u{1798}', '\u{1799}', '\u{179A}', '\u{179B}', '\u{179C}', '\u{179D}', '\u{179E}', '\u{179F}', '\u{17A0}', '\u{17A1}', '\u{17A2}', '\u{17A3}', '\u{17A4}', '\u{17A5}', '\u{17A6}', '\u{17A7}', '\u{17A8}', '\u{17A9}', '\u{17AA}', '\u{17AB}', '\u{17AC}', '\u{17AD}', '\u{17AE}', '\u{17AF}', '\u{17B0}', '\u{17B1}', '\u{17B2}', '\u{17B3}', '\u{17DC}', '\u{1820}', '\u{1821}', '\u{1822}', '\u{1823}', '\u{1824}', '\u{1825}', '\u{1826}', '\u{1827}', '\u{1828}', '\u{1829}', '\u{182A}', '\u{182B}', '\u{182C}', '\u{182D}', '\u{182E}', '\u{182F}', '\u{1830}', '\u{1831}', '\u{1832}', '\u{1833}', '\u{1834}', '\u{1835}', '\u{1836}', '\u{1837}', '\u{1838}', '\u{1839}', '\u{183A}', '\u{183B}', '\u{183C}', '\u{183D}', '\u{183E}', '\u{183F}', '\u{1840}', '\u{1841}', '\u{1842}', '\u{1844}', '\u{1845}', '\u{1846}', '\u{1847}', '\u{1848}', '\u{1849}', '\u{184A}', '\u{184B}', '\u{184C}', '\u{184D}', '\u{184E}', '\u{184F}', '\u{1850}', '\u{1851}', '\u{1852}', '\u{1853}', '\u{1854}', '\u{1855}', '\u{1856}', '\u{1857}', '\u{1858}', '\u{1859}', '\u{185A}', '\u{185B}', '\u{185C}', '\u{185D}', '\u{185E}', '\u{185F}', '\u{1860}', '\u{1861}', '\u{1862}', '\u{1863}', '\u{1864}', '\u{1865}', '\u{1866}', '\u{1867}', '\u{1868}', '\u{1869}', '\u{186A}', '\u{186B}', '\u{186C}', '\u{186D}', '\u{186E}', '\u{186F}', '\u{1870}', '\u{1871}', '\u{1872}', '\u{1873}', '\u{1874}', '\u{1875}', '\u{1876}', '\u{1877}', '\u{1880}', '\u{1881}', '\u{1882}', '\u{1883}', '\u{1884}', '\u{1885}', '\u{1886}', '\u{1887}', '\u{1888}', '\u{1889}', '\u{188A}', '\u{188B}', '\u{188C}', '\u{188D}', '\u{188E}', '\u{188F}', '\u{1890}', '\u{1891}', '\u{1892}', '\u{1893}', '\u{1894}', '\u{1895}', '\u{1896}', '\u{1897}', '\u{1898}', '\u{1899}', '\u{189A}', '\u{189B}', '\u{189C}', '\u{189D}', '\u{189E}', '\u{189F}', '\u{18A0}', '\u{18A1}', '\u{18A2}', '\u{18A3}', '\u{18A4}', '\u{18A5}', '\u{18A6}', '\u{18A7}', '\u{18A8}', '\u{18AA}', '\u{1900}', '\u{1901}', '\u{1902}', '\u{1903}', '\u{1904}', '\u{1905}', '\u{1906}', '\u{1907}', '\u{1908}', '\u{1909}', '\u{190A}', '\u{190B}', '\u{190C}', '\u{190D}', '\u{190E}', '\u{190F}', '\u{1910}', '\u{1911}', '\u{1912}', '\u{1913}', '\u{1914}', '\u{1915}', '\u{1916}', '\u{1917}', '\u{1918}', '\u{1919}', '\u{191A}', '\u{191B}', '\u{191C}', '\u{1950}', '\u{1951}', '\u{1952}', '\u{1953}', '\u{1954}', '\u{1955}', '\u{1956}', '\u{1957}', '\u{1958}', '\u{1959}', '\u{195A}', '\u{195B}', '\u{195C}', '\u{195D}', '\u{195E}', '\u{195F}', '\u{1960}', '\u{1961}', '\u{1962}', '\u{1963}', '\u{1964}', '\u{1965}', '\u{1966}', '\u{1967}', '\u{1968}', '\u{1969}', '\u{196A}', '\u{196B}', '\u{196C}', '\u{196D}', '\u{1970}', '\u{1971}', '\u{1972}', '\u{1973}', '\u{1974}', '\u{1980}', '\u{1981}', '\u{1982}', '\u{1983}', '\u{1984}', '\u{1985}', '\u{1986}', '\u{1987}', '\u{1988}', '\u{1989}', '\u{198A}', '\u{198B}', '\u{198C}', '\u{198D}', '\u{198E}', '\u{198F}', '\u{1990}', '\u{1991}', '\u{1992}', '\u{1993}', '\u{1994}', '\u{1995}', '\u{1996}', '\u{1997}', '\u{1998}', '\u{1999}', '\u{199A}', '\u{199B}', '\u{199C}', '\u{199D}', '\u{199E}', '\u{199F}', '\u{19A0}', '\u{19A1}', '\u{19A2}', '\u{19A3}', '\u{19A4}', '\u{19A5}', '\u{19A6}', '\u{19A7}', '\u{19A8}', '\u{19A9}', '\u{19C1}', '\u{19C2}', '\u{19C3}', '\u{19C4}', '\u{19C5}', '\u{19C6}', '\u{19C7}', '\u{1A00}', '\u{1A01}', '\u{1A02}', '\u{1A03}', '\u{1A04}', '\u{1A05}', '\u{1A06}', '\u{1A07}', '\u{1A08}', '\u{1A09}', '\u{1A0A}', '\u{1A0B}', '\u{1A0C}', '\u{1A0D}', '\u{1A0E}', '\u{1A0F}', '\u{1A10}', '\u{1A11}', '\u{1A12}', '\u{1A13}', '\u{1A14}', '\u{1A15}', '\u{1A16}', '\u{1B05}', '\u{1B06}', '\u{1B07}', '\u{1B08}', '\u{1B09}', '\u{1B0A}', '\u{1B0B}', '\u{1B0C}', '\u{1B0D}', '\u{1B0E}', '\u{1B0F}', '\u{1B10}', '\u{1B11}', '\u{1B12}', '\u{1B13}', '\u{1B14}', '\u{1B15}', '\u{1B16}', '\u{1B17}', '\u{1B18}', '\u{1B19}', '\u{1B1A}', '\u{1B1B}', '\u{1B1C}', '\u{1B1D}', '\u{1B1E}', '\u{1B1F}', '\u{1B20}', '\u{1B21}', '\u{1B22}', '\u{1B23}', '\u{1B24}', '\u{1B25}', '\u{1B26}', '\u{1B27}', '\u{1B28}', '\u{1B29}', '\u{1B2A}', '\u{1B2B}', '\u{1B2C}', '\u{1B2D}', '\u{1B2E}', '\u{1B2F}', '\u{1B30}', '\u{1B31}', '\u{1B32}', '\u{1B33}', '\u{1B45}', '\u{1B46}', '\u{1B47}', '\u{1B48}', '\u{1B49}', '\u{1B4A}', '\u{1B4B}', '\u{1B83}', '\u{1B84}', '\u{1B85}', '\u{1B86}', '\u{1B87}', '\u{1B88}', '\u{1B89}', '\u{1B8A}', '\u{1B8B}', '\u{1B8C}', '\u{1B8D}', '\u{1B8E}', '\u{1B8F}', '\u{1B90}', '\u{1B91}', '\u{1B92}', '\u{1B93}', '\u{1B94}', '\u{1B95}', '\u{1B96}', '\u{1B97}', '\u{1B98}', '\u{1B99}', '\u{1B9A}', '\u{1B9B}', '\u{1B9C}', '\u{1B9D}', '\u{1B9E}', '\u{1B9F}', '\u{1BA0}', '\u{1BAE}', '\u{1BAF}', '\u{1C00}', '\u{1C01}', '\u{1C02}', '\u{1C03}', '\u{1C04}', '\u{1C05}', '\u{1C06}', '\u{1C07}', '\u{1C08}', '\u{1C09}', '\u{1C0A}', '\u{1C0B}', '\u{1C0C}', '\u{1C0D}', '\u{1C0E}', '\u{1C0F}', '\u{1C10}', '\u{1C11}', '\u{1C12}', '\u{1C13}', '\u{1C14}', '\u{1C15}', '\u{1C16}', '\u{1C17}', '\u{1C18}', '\u{1C19}', '\u{1C1A}', '\u{1C1B}', '\u{1C1C}', '\u{1C1D}', '\u{1C1E}', '\u{1C1F}', '\u{1C20}', '\u{1C21}', '\u{1C22}', '\u{1C23}', '\u{1C4D}', '\u{1C4E}', '\u{1C4F}', '\u{1C5A}', '\u{1C5B}', '\u{1C5C}', '\u{1C5D}', '\u{1C5E}', '\u{1C5F}', '\u{1C60}', '\u{1C61}', '\u{1C62}', '\u{1C63}', '\u{1C64}', '\u{1C65}', '\u{1C66}', '\u{1C67}', '\u{1C68}', '\u{1C69}', '\u{1C6A}', '\u{1C6B}', '\u{1C6C}', '\u{1C6D}', '\u{1C6E}', '\u{1C6F}', '\u{1C70}', '\u{1C71}', '\u{1C72}', '\u{1C73}', '\u{1C74}', '\u{1C75}', '\u{1C76}', '\u{1C77}', '\u{2135}', '\u{2136}', '\u{2137}', '\u{2138}', '\u{2D30}', '\u{2D31}', '\u{2D32}', '\u{2D33}', '\u{2D34}', '\u{2D35}', '\u{2D36}', '\u{2D37}', '\u{2D38}', '\u{2D39}', '\u{2D3A}', '\u{2D3B}', '\u{2D3C}', '\u{2D3D}', '\u{2D3E}', '\u{2D3F}', '\u{2D40}', '\u{2D41}', '\u{2D42}', '\u{2D43}', '\u{2D44}', '\u{2D45}', '\u{2D46}', '\u{2D47}', '\u{2D48}', '\u{2D49}', '\u{2D4A}', '\u{2D4B}', '\u{2D4C}', '\u{2D4D}', '\u{2D4E}', '\u{2D4F}', '\u{2D50}', '\u{2D51}', '\u{2D52}', '\u{2D53}', '\u{2D54}', '\u{2D55}', '\u{2D56}', '\u{2D57}', '\u{2D58}', '\u{2D59}', '\u{2D5A}', '\u{2D5B}', '\u{2D5C}', '\u{2D5D}', '\u{2D5E}', '\u{2D5F}', '\u{2D60}', '\u{2D61}', '\u{2D62}', '\u{2D63}', '\u{2D64}', '\u{2D65}', '\u{2D80}', '\u{2D81}', '\u{2D82}', '\u{2D83}', '\u{2D84}', '\u{2D85}', '\u{2D86}', '\u{2D87}', '\u{2D88}', '\u{2D89}', '\u{2D8A}', '\u{2D8B}', '\u{2D8C}', '\u{2D8D}', '\u{2D8E}', '\u{2D8F}', '\u{2D90}', '\u{2D91}', '\u{2D92}', '\u{2D93}', '\u{2D94}', '\u{2D95}', '\u{2D96}', '\u{2DA0}', '\u{2DA1}', '\u{2DA2}', '\u{2DA3}', '\u{2DA4}', '\u{2DA5}', '\u{2DA6}', '\u{2DA8}', '\u{2DA9}', '\u{2DAA}', '\u{2DAB}', '\u{2DAC}', '\u{2DAD}', '\u{2DAE}', '\u{2DB0}', '\u{2DB1}', '\u{2DB2}', '\u{2DB3}', '\u{2DB4}', '\u{2DB5}', '\u{2DB6}', '\u{2DB8}', '\u{2DB9}', '\u{2DBA}', '\u{2DBB}', '\u{2DBC}', '\u{2DBD}', '\u{2DBE}', '\u{2DC0}', '\u{2DC1}', '\u{2DC2}', '\u{2DC3}', '\u{2DC4}', '\u{2DC5}', '\u{2DC6}', '\u{2DC8}', '\u{2DC9}', '\u{2DCA}', '\u{2DCB}', '\u{2DCC}', '\u{2DCD}', '\u{2DCE}', '\u{2DD0}', '\u{2DD1}', '\u{2DD2}', '\u{2DD3}', '\u{2DD4}', '\u{2DD5}', '\u{2DD6}', '\u{2DD8}', '\u{2DD9}', '\u{2DDA}', '\u{2DDB}', '\u{2DDC}', '\u{2DDD}', '\u{2DDE}', '\u{3006}', '\u{303C}', '\u{3041}', '\u{3042}', '\u{3043}', '\u{3044}', '\u{3045}', '\u{3046}', '\u{3047}', '\u{3048}', '\u{3049}', '\u{304A}', '\u{304B}', '\u{304C}', '\u{304D}', '\u{304E}', '\u{304F}', '\u{3050}', '\u{3051}', '\u{3052}', '\u{3053}', '\u{3054}', '\u{3055}', '\u{3056}', '\u{3057}', '\u{3058}', '\u{3059}', '\u{305A}', '\u{305B}', '\u{305C}', '\u{305D}', '\u{305E}', '\u{305F}', '\u{3060}', '\u{3061}', '\u{3062}', '\u{3063}', '\u{3064}', '\u{3065}', '\u{3066}', '\u{3067}', '\u{3068}', '\u{3069}', '\u{306A}', '\u{306B}', '\u{306C}', '\u{306D}', '\u{306E}', '\u{306F}', '\u{3070}', '\u{3071}', '\u{3072}', '\u{3073}', '\u{3074}', '\u{3075}', '\u{3076}', '\u{3077}', '\u{3078}', '\u{3079}', '\u{307A}', '\u{307B}', '\u{307C}', '\u{307D}', '\u{307E}', '\u{307F}', '\u{3080}', '\u{3081}', '\u{3082}', '\u{3083}', '\u{3084}', '\u{3085}', '\u{3086}', '\u{3087}', '\u{3088}', '\u{3089}', '\u{308A}', '\u{308B}', '\u{308C}', '\u{308D}', '\u{308E}', '\u{308F}', '\u{3090}', '\u{3091}', '\u{3092}', '\u{3093}', '\u{3094}', '\u{3095}', '\u{3096}', '\u{309F}', '\u{30A1}', '\u{30A2}', '\u{30A3}', '\u{30A4}', '\u{30A5}', '\u{30A6}', '\u{30A7}', '\u{30A8}', '\u{30A9}', '\u{30AA}', '\u{30AB}', '\u{30AC}', '\u{30AD}', '\u{30AE}', '\u{30AF}', '\u{30B0}', '\u{30B1}', '\u{30B2}', '\u{30B3}', '\u{30B4}', '\u{30B5}', '\u{30B6}', '\u{30B7}', '\u{30B8}', '\u{30B9}', '\u{30BA}', '\u{30BB}', '\u{30BC}', '\u{30BD}', '\u{30BE}', '\u{30BF}', '\u{30C0}', '\u{30C1}', '\u{30C2}', '\u{30C3}', '\u{30C4}', '\u{30C5}', '\u{30C6}', '\u{30C7}', '\u{30C8}', '\u{30C9}', '\u{30CA}', '\u{30CB}', '\u{30CC}', '\u{30CD}', '\u{30CE}', '\u{30CF}', '\u{30D0}', '\u{30D1}', '\u{30D2}', '\u{30D3}', '\u{30D4}', '\u{30D5}', '\u{30D6}', '\u{30D7}', '\u{30D8}', '\u{30D9}', '\u{30DA}', '\u{30DB}', '\u{30DC}', '\u{30DD}', '\u{30DE}', '\u{30DF}', '\u{30E0}', '\u{30E1}', '\u{30E2}', '\u{30E3}', '\u{30E4}', '\u{30E5}', '\u{30E6}', '\u{30E7}', '\u{30E8}', '\u{30E9}', '\u{30EA}', '\u{30EB}', '\u{30EC}', '\u{30ED}', '\u{30EE}', '\u{30EF}', '\u{30F0}', '\u{30F1}', '\u{30F2}', '\u{30F3}', '\u{30F4}', '\u{30F5}', '\u{30F6}', '\u{30F7}', '\u{30F8}', '\u{30F9}', '\u{30FA}', '\u{30FF}', '\u{3105}', '\u{3106}', '\u{3107}', '\u{3108}', '\u{3109}', '\u{310A}', '\u{310B}', '\u{310C}', '\u{310D}', '\u{310E}', '\u{310F}', '\u{3110}', '\u{3111}', '\u{3112}', '\u{3113}', '\u{3114}', '\u{3115}', '\u{3116}', '\u{3117}', '\u{3118}', '\u{3119}', '\u{311A}', '\u{311B}', '\u{311C}', '\u{311D}', '\u{311E}', '\u{311F}', '\u{3120}', '\u{3121}', '\u{3122}', '\u{3123}', '\u{3124}', '\u{3125}', '\u{3126}', '\u{3127}', '\u{3128}', '\u{3129}', '\u{312A}', '\u{312B}', '\u{312C}', '\u{312D}', '\u{3131}', '\u{3132}', '\u{3133}', '\u{3134}', '\u{3135}', '\u{3136}', '\u{3137}', '\u{3138}', '\u{3139}', '\u{313A}', '\u{313B}', '\u{313C}', '\u{313D}', '\u{313E}', '\u{313F}', '\u{3140}', '\u{3141}', '\u{3142}', '\u{3143}', '\u{3144}', '\u{3145}', '\u{3146}', '\u{3147}', '\u{3148}', '\u{3149}', '\u{314A}', '\u{314B}', '\u{314C}', '\u{314D}', '\u{314E}', '\u{314F}', '\u{3150}', '\u{3151}', '\u{3152}', '\u{3153}', '\u{3154}', '\u{3155}', '\u{3156}', '\u{3157}', '\u{3158}', '\u{3159}', '\u{315A}', '\u{315B}', '\u{315C}', '\u{315D}', '\u{315E}', '\u{315F}', '\u{3160}', '\u{3161}', '\u{3162}', '\u{3163}', '\u{3164}', '\u{3165}', '\u{3166}', '\u{3167}', '\u{3168}', '\u{3169}', '\u{316A}', '\u{316B}', '\u{316C}', '\u{316D}', '\u{316E}', '\u{316F}', '\u{3170}', '\u{3171}', '\u{3172}', '\u{3173}', '\u{3174}', '\u{3175}', '\u{3176}', '\u{3177}', '\u{3178}', '\u{3179}', '\u{317A}', '\u{317B}', '\u{317C}', '\u{317D}', '\u{317E}', '\u{317F}', '\u{3180}', '\u{3181}', '\u{3182}', '\u{3183}', '\u{3184}', '\u{3185}', '\u{3186}', '\u{3187}', '\u{3188}', '\u{3189}', '\u{318A}', '\u{318B}', '\u{318C}', '\u{318D}', '\u{318E}', '\u{31A0}', '\u{31A1}', '\u{31A2}', '\u{31A3}', '\u{31A4}', '\u{31A5}', '\u{31A6}', '\u{31A7}', '\u{31A8}', '\u{31A9}', '\u{31AA}', '\u{31AB}', '\u{31AC}', '\u{31AD}', '\u{31AE}', '\u{31AF}', '\u{31B0}', '\u{31B1}', '\u{31B2}', '\u{31B3}', '\u{31B4}', '\u{31B5}', '\u{31B6}', '\u{31B7}', '\u{31F0}', '\u{31F1}', '\u{31F2}', '\u{31F3}', '\u{31F4}', '\u{31F5}', '\u{31F6}', '\u{31F7}', '\u{31F8}', '\u{31F9}', '\u{31FA}', '\u{31FB}', '\u{31FC}', '\u{31FD}', '\u{31FE}', '\u{31FF}', '\u{3400}', '\u{4DB5}', '\u{4E00}', '\u{9FC3}', '\u{A000}', '\u{A001}', '\u{A002}', '\u{A003}', '\u{A004}', '\u{A005}', '\u{A006}', '\u{A007}', '\u{A008}', '\u{A009}', '\u{A00A}', '\u{A00B}', '\u{A00C}', '\u{A00D}', '\u{A00E}', '\u{A00F}', '\u{A010}', '\u{A011}', '\u{A012}', '\u{A013}', '\u{A014}', '\u{A016}', '\u{A017}', '\u{A018}', '\u{A019}', '\u{A01A}', '\u{A01B}', '\u{A01C}', '\u{A01D}', '\u{A01E}', '\u{A01F}', '\u{A020}', '\u{A021}', '\u{A022}', '\u{A023}', '\u{A024}', '\u{A025}', '\u{A026}', '\u{A027}', '\u{A028}', '\u{A029}', '\u{A02A}', '\u{A02B}', '\u{A02C}', '\u{A02D}', '\u{A02E}', '\u{A02F}', '\u{A030}', '\u{A031}', '\u{A032}', '\u{A033}', '\u{A034}', '\u{A035}', '\u{A036}', '\u{A037}', '\u{A038}', '\u{A039}', '\u{A03A}', '\u{A03B}', '\u{A03C}', '\u{A03D}', '\u{A03E}', '\u{A03F}', '\u{A040}', '\u{A041}', '\u{A042}', '\u{A043}', '\u{A044}', '\u{A045}', '\u{A046}', '\u{A047}', '\u{A048}', '\u{A049}', '\u{A04A}', '\u{A04B}', '\u{A04C}', '\u{A04D}', '\u{A04E}', '\u{A04F}', '\u{A050}', '\u{A051}', '\u{A052}', '\u{A053}', '\u{A054}', '\u{A055}', '\u{A056}', '\u{A057}', '\u{A058}', '\u{A059}', '\u{A05A}', '\u{A05B}', '\u{A05C}', '\u{A05D}', '\u{A05E}', '\u{A05F}', '\u{A060}', '\u{A061}', '\u{A062}', '\u{A063}', '\u{A064}', '\u{A065}', '\u{A066}', '\u{A067}', '\u{A068}', '\u{A069}', '\u{A06A}', '\u{A06B}', '\u{A06C}', '\u{A06D}', '\u{A06E}', '\u{A06F}', '\u{A070}', '\u{A071}', '\u{A072}', '\u{A073}', '\u{A074}', '\u{A075}', '\u{A076}', '\u{A077}', '\u{A078}', '\u{A079}', '\u{A07A}', '\u{A07B}', '\u{A07C}', '\u{A07D}', '\u{A07E}', '\u{A07F}', '\u{A080}', '\u{A081}', '\u{A082}', '\u{A083}', '\u{A084}', '\u{A085}', '\u{A086}', '\u{A087}', '\u{A088}', '\u{A089}', '\u{A08A}', '\u{A08B}', '\u{A08C}', '\u{A08D}', '\u{A08E}', '\u{A08F}', '\u{A090}', '\u{A091}', '\u{A092}', '\u{A093}', '\u{A094}', '\u{A095}', '\u{A096}', '\u{A097}', '\u{A098}', '\u{A099}', '\u{A09A}', '\u{A09B}', '\u{A09C}', '\u{A09D}', '\u{A09E}', '\u{A09F}', '\u{A0A0}', '\u{A0A1}', '\u{A0A2}', '\u{A0A3}', '\u{A0A4}', '\u{A0A5}', '\u{A0A6}', '\u{A0A7}', '\u{A0A8}', '\u{A0A9}', '\u{A0AA}', '\u{A0AB}', '\u{A0AC}', '\u{A0AD}', '\u{A0AE}', '\u{A0AF}', '\u{A0B0}', '\u{A0B1}', '\u{A0B2}', '\u{A0B3}', '\u{A0B4}', '\u{A0B5}', '\u{A0B6}', '\u{A0B7}', '\u{A0B8}', '\u{A0B9}', '\u{A0BA}', '\u{A0BB}', '\u{A0BC}', '\u{A0BD}', '\u{A0BE}', '\u{A0BF}', '\u{A0C0}', '\u{A0C1}', '\u{A0C2}', '\u{A0C3}', '\u{A0C4}', '\u{A0C5}', '\u{A0C6}', '\u{A0C7}', '\u{A0C8}', '\u{A0C9}', '\u{A0CA}', '\u{A0CB}', '\u{A0CC}', '\u{A0CD}', '\u{A0CE}', '\u{A0CF}', '\u{A0D0}', '\u{A0D1}', '\u{A0D2}', '\u{A0D3}', '\u{A0D4}', '\u{A0D5}', '\u{A0D6}', '\u{A0D7}', '\u{A0D8}', '\u{A0D9}', '\u{A0DA}', '\u{A0DB}', '\u{A0DC}', '\u{A0DD}', '\u{A0DE}', '\u{A0DF}', '\u{A0E0}', '\u{A0E1}', '\u{A0E2}', '\u{A0E3}', '\u{A0E4}', '\u{A0E5}', '\u{A0E6}', '\u{A0E7}', '\u{A0E8}', '\u{A0E9}', '\u{A0EA}', '\u{A0EB}', '\u{A0EC}', '\u{A0ED}', '\u{A0EE}', '\u{A0EF}', '\u{A0F0}', '\u{A0F1}', '\u{A0F2}', '\u{A0F3}', '\u{A0F4}', '\u{A0F5}', '\u{A0F6}', '\u{A0F7}', '\u{A0F8}', '\u{A0F9}', '\u{A0FA}', '\u{A0FB}', '\u{A0FC}', '\u{A0FD}', '\u{A0FE}', '\u{A0FF}', '\u{A100}', '\u{A101}', '\u{A102}', '\u{A103}', '\u{A104}', '\u{A105}', '\u{A106}', '\u{A107}', '\u{A108}', '\u{A109}', '\u{A10A}', '\u{A10B}', '\u{A10C}', '\u{A10D}', '\u{A10E}', '\u{A10F}', '\u{A110}', '\u{A111}', '\u{A112}', '\u{A113}', '\u{A114}', '\u{A115}', '\u{A116}', '\u{A117}', '\u{A118}', '\u{A119}', '\u{A11A}', '\u{A11B}', '\u{A11C}', '\u{A11D}', '\u{A11E}', '\u{A11F}', '\u{A120}', '\u{A121}', '\u{A122}', '\u{A123}', '\u{A124}', '\u{A125}', '\u{A126}', '\u{A127}', '\u{A128}', '\u{A129}', '\u{A12A}', '\u{A12B}', '\u{A12C}', '\u{A12D}', '\u{A12E}', '\u{A12F}', '\u{A130}', '\u{A131}', '\u{A132}', '\u{A133}', '\u{A134}', '\u{A135}', '\u{A136}', '\u{A137}', '\u{A138}', '\u{A139}', '\u{A13A}', '\u{A13B}', '\u{A13C}', '\u{A13D}', '\u{A13E}', '\u{A13F}', '\u{A140}', '\u{A141}', '\u{A142}', '\u{A143}', '\u{A144}', '\u{A145}', '\u{A146}', '\u{A147}', '\u{A148}', '\u{A149}', '\u{A14A}', '\u{A14B}', '\u{A14C}', '\u{A14D}', '\u{A14E}', '\u{A14F}', '\u{A150}', '\u{A151}', '\u{A152}', '\u{A153}', '\u{A154}', '\u{A155}', '\u{A156}', '\u{A157}', '\u{A158}', '\u{A159}', '\u{A15A}', '\u{A15B}', '\u{A15C}', '\u{A15D}', '\u{A15E}', '\u{A15F}', '\u{A160}', '\u{A161}', '\u{A162}', '\u{A163}', '\u{A164}', '\u{A165}', '\u{A166}', '\u{A167}', '\u{A168}', '\u{A169}', '\u{A16A}', '\u{A16B}', '\u{A16C}', '\u{A16D}', '\u{A16E}', '\u{A16F}', '\u{A170}', '\u{A171}', '\u{A172}', '\u{A173}', '\u{A174}', '\u{A175}', '\u{A176}', '\u{A177}', '\u{A178}', '\u{A179}', '\u{A17A}', '\u{A17B}', '\u{A17C}', '\u{A17D}', '\u{A17E}', '\u{A17F}', '\u{A180}', '\u{A181}', '\u{A182}', '\u{A183}', '\u{A184}', '\u{A185}', '\u{A186}', '\u{A187}', '\u{A188}', '\u{A189}', '\u{A18A}', '\u{A18B}', '\u{A18C}', '\u{A18D}', '\u{A18E}', '\u{A18F}', '\u{A190}', '\u{A191}', '\u{A192}', '\u{A193}', '\u{A194}', '\u{A195}', '\u{A196}', '\u{A197}', '\u{A198}', '\u{A199}', '\u{A19A}', '\u{A19B}', '\u{A19C}', '\u{A19D}', '\u{A19E}', '\u{A19F}', '\u{A1A0}', '\u{A1A1}', '\u{A1A2}', '\u{A1A3}', '\u{A1A4}', '\u{A1A5}', '\u{A1A6}', '\u{A1A7}', '\u{A1A8}', '\u{A1A9}', '\u{A1AA}', '\u{A1AB}', '\u{A1AC}', '\u{A1AD}', '\u{A1AE}', '\u{A1AF}')
+    }
+
+    fn is_unicode_combining_spacing_mark(self) -> bool {
+        match_char_class!(self,
+            '\u{0903}', '\u{093E}', '\u{093F}', '\u{0940}', '\u{0949}', '\u{094A}', '\u{094B}', '\u{094C}', '\u{0982}', '\u{0983}', '\u{09BE}', '\u{09BF}', '\u{09C0}', '\u{09C7}', '\u{09C8}', '\u{09CB}', '\u{09CC}', '\u{09D7}', '\u{0A03}', '\u{0A3E}', '\u{0A3F}', '\u{0A40}', '\u{0A83}', '\u{0ABE}', '\u{0ABF}', '\u{0AC0}', '\u{0AC9}', '\u{0ACB}', '\u{0ACC}', '\u{0B02}', '\u{0B03}', '\u{0B3E}', '\u{0B40}', '\u{0B47}', '\u{0B48}', '\u{0B4B}', '\u{0B4C}', '\u{0B57}', '\u{0BBE}', '\u{0BBF}', '\u{0BC1}', '\u{0BC2}', '\u{0BC6}', '\u{0BC7}', '\u{0BC8}', '\u{0BCA}', '\u{0BCB}', '\u{0BCC}', '\u{0BD7}', '\u{0C01}', '\u{0C02}', '\u{0C03}', '\u{0C41}', '\u{0C42}', '\u{0C43}', '\u{0C44}', '\u{0C82}', '\u{0C83}', '\u{0CBE}', '\u{0CC0}', '\u{0CC1}', '\u{0CC2}', '\u{0CC3}', '\u{0CC4}', '\u{0CC7}', '\u{0CC8}', '\u{0CCA}', '\u{0CCB}', '\u{0CD5}', '\u{0CD6}', '\u{0D02}', '\u{0D03}', '\u{0D3E}', '\u{0D3F}', '\u{0D40}', '\u{0D46}', '\u{0D47}', '\u{0D48}', '\u{0D4A}', '\u{0D4B}', '\u{0D4C}', '\u{0D57}', '\u{0D82}', '\u{0D83}', '\u{0DCF}', '\u{0DD0}', '\u{0DD1}', '\u{0DD8}', '\u{0DD9}', '\u{0DDA}', '\u{0DDB}', '\u{0DDC}', '\u{0DDD}', '\u{0DDE}', '\u{0DDF}', '\u{0DF2}', '\u{0DF3}', '\u{0F3E}', '\u{0F3F}', '\u{0F7F}', '\u{102B}', '\u{102C}', '\u{1031}', '\u{1038}', '\u{103B}', '\u{103C}', '\u{1056}', '\u{1057}', '\u{1062}', '\u{1063}', '\u{1064}', '\u{1067}', '\u{1068}', '\u{1069}', '\u{106A}', '\u{106B}', '\u{106C}', '\u{106D}', '\u{1083}', '\u{1084}', '\u{1087}', '\u{1088}', '\u{1089}', '\u{108A}', '\u{108B}', '\u{108C}', '\u{108F}', '\u{17B6}', '\u{17BE}', '\u{17BF}', '\u{17C0}', '\u{17C1}', '\u{17C2}', '\u{17C3}', '\u{17C4}', '\u{17C5}', '\u{17C7}', '\u{17C8}', '\u{1923}', '\u{1924}', '\u{1925}', '\u{1926}', '\u{1929}', '\u{192A}', '\u{192B}', '\u{1930}', '\u{1931}', '\u{1933}', '\u{1934}', '\u{1935}', '\u{1936}', '\u{1937}', '\u{1938}', '\u{19B0}', '\u{19B1}', '\u{19B2}', '\u{19B3}', '\u{19B4}', '\u{19B5}', '\u{19B6}', '\u{19B7}', '\u{19B8}', '\u{19B9}', '\u{19BA}', '\u{19BB}', '\u{19BC}', '\u{19BD}', '\u{19BE}', '\u{19BF}', '\u{19C0}', '\u{19C8}', '\u{19C9}', '\u{1A19}', '\u{1A1A}', '\u{1A1B}', '\u{1B04}', '\u{1B35}', '\u{1B3B}', '\u{1B3D}', '\u{1B3E}', '\u{1B3F}', '\u{1B40}', '\u{1B41}', '\u{1B43}', '\u{1B44}', '\u{1B82}', '\u{1BA1}', '\u{1BA6}', '\u{1BA7}', '\u{1BAA}', '\u{1C24}', '\u{1C25}', '\u{1C26}', '\u{1C27}', '\u{1C28}', '\u{1C29}', '\u{1C2A}', '\u{1C2B}', '\u{1C34}', '\u{1C35}', '\u{A823}', '\u{A824}', '\u{A827}', '\u{A880}', '\u{A881}', '\u{A8B4}', '\u{A8B5}', '\u{A8B6}', '\u{A8B7}', '\u{A8B8}', '\u{A8B9}', '\u{A8BA}', '\u{A8BB}', '\u{A8BC}', '\u{A8BD}', '\u{A8BE}', '\u{A8BF}', '\u{A8C0}', '\u{A8C1}', '\u{A8C2}', '\u{A8C3}', '\u{A952}', '\u{A953}', '\u{AA2F}', '\u{AA30}', '\u{AA33}', '\u{AA34}', '\u{AA4D}')
+    }
+
+    fn is_unicode_decimal_number(self) -> bool {
+        match_char_class!(self,
+            '\u{0030}', '\u{0031}', '\u{0032}', '\u{0033}', '\u{0034}', '\u{0035}', '\u{0036}', '\u{0037}', '\u{0038}', '\u{0039}', '\u{0660}', '\u{0661}', '\u{0662}', '\u{0663}', '\u{0664}', '\u{0665}', '\u{0666}', '\u{0667}', '\u{0668}', '\u{0669}', '\u{06F0}', '\u{06F1}', '\u{06F2}', '\u{06F3}', '\u{06F4}', '\u{06F5}', '\u{06F6}', '\u{06F7}', '\u{06F8}', '\u{06F9}', '\u{07C0}', '\u{07C1}', '\u{07C2}', '\u{07C3}', '\u{07C4}', '\u{07C5}', '\u{07C6}', '\u{07C7}', '\u{07C8}', '\u{07C9}', '\u{0966}', '\u{0967}', '\u{0968}', '\u{0969}', '\u{096A}', '\u{096B}', '\u{096C}', '\u{096D}', '\u{096E}', '\u{096F}', '\u{09E6}', '\u{09E7}', '\u{09E8}', '\u{09E9}', '\u{09EA}', '\u{09EB}', '\u{09EC}', '\u{09ED}', '\u{09EE}', '\u{09EF}', '\u{0A66}', '\u{0A67}', '\u{0A68}', '\u{0A69}', '\u{0A6A}', '\u{0A6B}', '\u{0A6C}', '\u{0A6D}', '\u{0A6E}', '\u{0A6F}', '\u{0AE6}', '\u{0AE7}', '\u{0AE8}', '\u{0AE9}', '\u{0AEA}', '\u{0AEB}', '\u{0AEC}', '\u{0AED}', '\u{0AEE}', '\u{0AEF}', '\u{0B66}', '\u{0B67}', '\u{0B68}', '\u{0B69}', '\u{0B6A}', '\u{0B6B}', '\u{0B6C}', '\u{0B6D}', '\u{0B6E}', '\u{0B6F}', '\u{0BE6}', '\u{0BE7}', '\u{0BE8}', '\u{0BE9}', '\u{0BEA}', '\u{0BEB}', '\u{0BEC}', '\u{0BED}', '\u{0BEE}', '\u{0BEF}', '\u{0C66}', '\u{0C67}', '\u{0C68}', '\u{0C69}', '\u{0C6A}', '\u{0C6B}', '\u{0C6C}', '\u{0C6D}', '\u{0C6E}', '\u{0C6F}', '\u{0CE6}', '\u{0CE7}', '\u{0CE8}', '\u{0CE9}', '\u{0CEA}', '\u{0CEB}', '\u{0CEC}', '\u{0CED}', '\u{0CEE}', '\u{0CEF}', '\u{0D66}', '\u{0D67}', '\u{0D68}', '\u{0D69}', '\u{0D6A}', '\u{0D6B}', '\u{0D6C}', '\u{0D6D}', '\u{0D6E}', '\u{0D6F}', '\u{0E50}', '\u{0E51}', '\u{0E52}', '\u{0E53}', '\u{0E54}', '\u{0E55}', '\u{0E56}', '\u{0E57}', '\u{0E58}', '\u{0E59}', '\u{0ED0}', '\u{0ED1}', '\u{0ED2}', '\u{0ED3}', '\u{0ED4}', '\u{0ED5}', '\u{0ED6}', '\u{0ED7}', '\u{0ED8}', '\u{0ED9}', '\u{0F20}', '\u{0F21}', '\u{0F22}', '\u{0F23}', '\u{0F24}', '\u{0F25}', '\u{0F26}', '\u{0F27}', '\u{0F28}', '\u{0F29}', '\u{1040}', '\u{1041}', '\u{1042}', '\u{1043}', '\u{1044}', '\u{1045}', '\u{1046}', '\u{1047}', '\u{1048}', '\u{1049}', '\u{1090}', '\u{1091}', '\u{1092}', '\u{1093}', '\u{1094}', '\u{1095}', '\u{1096}', '\u{1097}', '\u{1098}', '\u{1099}', '\u{17E0}', '\u{17E1}', '\u{17E2}', '\u{17E3}', '\u{17E4}', '\u{17E5}', '\u{17E6}', '\u{17E7}', '\u{17E8}', '\u{17E9}', '\u{1810}', '\u{1811}', '\u{1812}', '\u{1813}', '\u{1814}', '\u{1815}', '\u{1816}', '\u{1817}', '\u{1818}', '\u{1819}', '\u{1946}', '\u{1947}', '\u{1948}', '\u{1949}', '\u{194A}', '\u{194B}', '\u{194C}', '\u{194D}', '\u{194E}', '\u{194F}', '\u{19D0}', '\u{19D1}', '\u{19D2}', '\u{19D3}', '\u{19D4}', '\u{19D5}', '\u{19D6}', '\u{19D7}', '\u{19D8}', '\u{19D9}', '\u{1B50}', '\u{1B51}', '\u{1B52}', '\u{1B53}', '\u{1B54}', '\u{1B55}', '\u{1B56}', '\u{1B57}', '\u{1B58}', '\u{1B59}', '\u{1BB0}', '\u{1BB1}', '\u{1BB2}', '\u{1BB3}', '\u{1BB4}', '\u{1BB5}', '\u{1BB6}', '\u{1BB7}', '\u{1BB8}', '\u{1BB9}', '\u{1C40}', '\u{1C41}', '\u{1C42}', '\u{1C43}', '\u{1C44}', '\u{1C45}', '\u{1C46}', '\u{1C47}', '\u{1C48}', '\u{1C49}', '\u{1C50}', '\u{1C51}', '\u{1C52}', '\u{1C53}', '\u{1C54}', '\u{1C55}', '\u{1C56}', '\u{1C57}', '\u{1C58}', '\u{1C59}', '\u{A620}', '\u{A621}', '\u{A622}', '\u{A623}', '\u{A624}', '\u{A625}', '\u{A626}', '\u{A627}', '\u{A628}', '\u{A629}', '\u{A8D0}', '\u{A8D1}', '\u{A8D2}', '\u{A8D3}', '\u{A8D4}', '\u{A8D5}', '\u{A8D6}', '\u{A8D7}', '\u{A8D8}', '\u{A8D9}', '\u{A900}', '\u{A901}', '\u{A902}', '\u{A903}', '\u{A904}', '\u{A905}', '\u{A906}', '\u{A907}', '\u{A908}', '\u{A909}', '\u{AA50}', '\u{AA51}', '\u{AA52}', '\u{AA53}', '\u{AA54}', '\u{AA55}', '\u{AA56}', '\u{AA57}', '\u{AA58}', '\u{AA59}', '\u{FF10}', '\u{FF11}', '\u{FF12}', '\u{FF13}', '\u{FF14}', '\u{FF15}', '\u{FF16}', '\u{FF17}', '\u{FF18}', '\u{FF19}')
+    }
+
+    fn is_unicode_connector_punctiation(self) -> bool {
+        match_char_class!(self,
+            '\u{005F}', '\u{203F}', '\u{2040}', '\u{2054}', '\u{FE33}', '\u{FE34}', '\u{FE4D}', '\u{FE4E}', '\u{FE4F}', '\u{FF3F}')
+    }
+
+    fn is_unicode_space_separator(self) -> bool {
+        match_char_class!(self,
+            '\u{0020}', '\u{00A0}', '\u{1680}', '\u{2000}', '\u{2001}', '\u{2002}', '\u{2003}', '\u{2004}', '\u{2005}', '\u{2006}', '\u{2007}', '\u{2008}', '\u{2009}', '\u{200A}', '\u{202F}', '\u{205F}', '\u{3000}')
+    }
+
+    fn is_es_identifier_start(self) -> bool {
+        match self {
+            '$' | '_' | '\\' => true,
+            c if c.is_unicode_letter() => true,
+            _ => false
+        }
+    }
+
+    // see section 7.6
+    fn is_es_identifier_part(self) -> bool {
+        match self {
+            '\u{200C}' | '\u{200D}' => true,
+            c if c.is_es_identifier_start() => true,
+            c if c.is_unicode_combining_spacing_mark() => true,
+            c if c.is_unicode_nonspacing_mark() => true,
+            c if c.is_unicode_decimal_number() => true,
+            c if c.is_unicode_connector_punctiation() => true,
+            _ => false
+        }
+    }
+
+    fn is_es_whitespace(self) -> bool {
+        match self {
+            '\t' | '\u{000B}' | '\u{000C}' | '\u{0020}' | '\u{00A0}' | '\u{FEFF}' => true,
+            c => c.is_unicode_space_separator()
+        }
+    }
+
+    fn is_es_line_terminator(self) -> bool {
+        match self {
+            '\n' | '\r' | '\u{2028}' | '\u{2029}' => true,
+            _ => false
+        }
+    }
+}
+
+fn main() {
+
+}
diff --git a/src/test/ui/mir/issue-46845.rs b/src/test/ui/mir/issue-46845.rs
new file mode 100644 (file)
index 0000000..fc85b25
--- /dev/null
@@ -0,0 +1,32 @@
+// run-pass
+// To work around #46855
+// compile-flags: -Z mir-opt-level=0
+// Regression test for the inhabitedness of unions with uninhabited variants, issue #46845
+
+use std::mem;
+
+#[derive(Copy, Clone)]
+enum Never { }
+
+// A single uninhabited variant shouldn't make the whole union uninhabited.
+union Foo {
+    a: u64,
+    _b: Never
+}
+
+// If all the variants are uninhabited, however, the union should be uninhabited.
+// NOTE(#49298) the union being uninhabited shouldn't change its size.
+union Bar {
+    _a: (Never, u64),
+    _b: (u64, Never)
+}
+
+fn main() {
+    assert_eq!(mem::size_of::<Foo>(), 8);
+    // See the note on `Bar`'s definition for why this isn't `0`.
+    assert_eq!(mem::size_of::<Bar>(), 8);
+
+    let f = [Foo { a: 42 }, Foo { a: 10 }];
+    println!("{}", unsafe { f[0].a });
+    assert_eq!(unsafe { f[1].a }, 10);
+}
diff --git a/src/test/ui/mir/issue-77002.rs b/src/test/ui/mir/issue-77002.rs
new file mode 100644 (file)
index 0000000..0c37346
--- /dev/null
@@ -0,0 +1,16 @@
+// compile-flags: -Zmir-opt-level=3 -Copt-level=0
+// run-pass
+
+type M = [i64; 2];
+
+fn f(a: &M) -> M {
+    let mut b: M = M::default();
+    b[0] = a[0] * a[0];
+    b
+}
+
+fn main() {
+    let mut a: M = [1, 1];
+    a = f(&a);
+    assert_eq!(a[0], 1);
+}
diff --git a/src/test/ui/mir/issue-95978-validator-lifetime-comparison.rs b/src/test/ui/mir/issue-95978-validator-lifetime-comparison.rs
deleted file mode 100644 (file)
index cd6c5bf..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// check-pass
-// compile-flags: -Zvalidate-mir
-
-fn foo(_a: &str) {}
-
-fn main() {
-    let x = foo as fn(&'static str);
-
-    let _ = x == foo;
-}
diff --git a/src/test/ui/mir/validate/issue-95978-validator-lifetime-comparison.rs b/src/test/ui/mir/validate/issue-95978-validator-lifetime-comparison.rs
new file mode 100644 (file)
index 0000000..cd6c5bf
--- /dev/null
@@ -0,0 +1,10 @@
+// check-pass
+// compile-flags: -Zvalidate-mir
+
+fn foo(_a: &str) {}
+
+fn main() {
+    let x = foo as fn(&'static str);
+
+    let _ = x == foo;
+}
diff --git a/src/test/ui/mir/validate/needs-reveal-all.rs b/src/test/ui/mir/validate/needs-reveal-all.rs
new file mode 100644 (file)
index 0000000..3852daf
--- /dev/null
@@ -0,0 +1,52 @@
+// Regression test for #105009. the issue here was that even after the `RevealAll` pass,
+// `validate` still used `Reveal::UserFacing`. This meant that it now ends up comparing
+// opaque types with their revealed version, resulting in an ICE.
+//
+// We're using these flags to run the `RevealAll` pass while making it less likely to
+// accidentally removing the assignment from `Foo<fn_ptr>` to `Foo<fn_def>`.
+
+// compile-flags: -Zinline_mir=yes -Zmir-opt-level=0 -Zvalidate-mir
+// run-pass
+
+use std::hint::black_box;
+
+trait Func {
+    type Ret: Id;
+}
+
+trait Id {
+    type Assoc;
+}
+impl Id for u32 {
+    type Assoc = u32;
+}
+impl Id for i32 {
+    type Assoc = i32;
+}
+
+impl<F: FnOnce() -> R, R: Id> Func for F {
+    type Ret = R;
+}
+
+fn bar() -> impl Copy + Id {
+    0u32
+}
+
+struct Foo<T: Func> {
+    _func: T,
+    value: Option<<<T as Func>::Ret as Id>::Assoc>,
+}
+
+fn main() {
+    let mut fn_def = black_box(Foo {
+        _func: bar,
+        value: None,
+    });
+    let fn_ptr = black_box(Foo {
+        _func: bar as fn() -> _,
+        value: None,
+    });
+
+    fn_def.value = fn_ptr.value;
+    black_box(fn_def);
+}
index ffd95b48ac2b72992ba581014f459a8becfc47df..2393791a9b2a81106ad423e13de7bb2f245282ff 100644 (file)
@@ -11,11 +11,8 @@ note: an implementation of `AddAssign<_>` might be missing for `Foo`
    |
 LL | struct Foo;
    | ^^^^^^^^^^ must implement `AddAssign<_>`
-note: the following trait must be implemented
+note: the trait `AddAssign` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait AddAssign<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index a02ec819838833dc2920fdc10ea9e5d380f97ba7..2ecab9f024a123a2de0b9d45eac0b9846ddfb9e8 100644 (file)
@@ -128,9 +128,6 @@ LL | fn foo() {}
    |
 note: required by a bound in `map`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         F: FnMut(Self::Item) -> B,
-   |            ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map`
 
 error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 3 distinct arguments
   --> $DIR/closure-arg-count.rs:27:57
@@ -144,9 +141,6 @@ LL |     let _it = vec![1, 2, 3].into_iter().enumerate().map(bar);
    |
 note: required by a bound in `map`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         F: FnMut(Self::Item) -> B,
-   |            ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map`
 
 error[E0593]: function is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments
   --> $DIR/closure-arg-count.rs:29:57
@@ -161,9 +155,6 @@ LL | fn qux(x: usize, y: usize) {}
    |
 note: required by a bound in `map`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         F: FnMut(Self::Item) -> B,
-   |            ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map`
 
 error[E0593]: function is expected to take 1 argument, but it takes 2 arguments
   --> $DIR/closure-arg-count.rs:32:45
@@ -175,9 +166,6 @@ LL |     let _it = vec![1, 2, 3].into_iter().map(usize::checked_add);
    |
 note: required by a bound in `map`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         F: FnMut(Self::Item) -> B,
-   |            ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map`
 
 error[E0593]: function is expected to take 0 arguments, but it takes 1 argument
   --> $DIR/closure-arg-count.rs:35:10
index 92d545b7366e38a6740788ca4aa1e6de613d58a9..fab9b7edc0cc5a38bb0c6ab566171b51fa5a4b62 100644 (file)
@@ -2,17 +2,16 @@ error[E0631]: type mismatch in closure arguments
   --> $DIR/closure-arg-type-mismatch.rs:3:14
    |
 LL |     a.iter().map(|_: (u32, u32)| 45);
-   |              ^^^ --------------- found signature defined here
-   |              |
+   |              ^^^ ---------------
+   |              |   |   |
+   |              |   |   help: consider borrowing the argument: `&(u32, u32)`
+   |              |   found signature defined here
    |              expected due to this
    |
    = note: expected closure signature `fn(&(u32, u32)) -> _`
               found closure signature `fn((u32, u32)) -> _`
 note: required by a bound in `map`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         F: FnMut(Self::Item) -> B,
-   |            ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map`
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/closure-arg-type-mismatch.rs:4:14
@@ -26,9 +25,6 @@ LL |     a.iter().map(|_: &(u16, u16)| 45);
               found closure signature `for<'a> fn(&'a (u16, u16)) -> _`
 note: required by a bound in `map`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         F: FnMut(Self::Item) -> B,
-   |            ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map`
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/closure-arg-type-mismatch.rs:5:14
@@ -42,9 +38,6 @@ LL |     a.iter().map(|_: (u16, u16)| 45);
               found closure signature `fn((u16, u16)) -> _`
 note: required by a bound in `map`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         F: FnMut(Self::Item) -> B,
-   |            ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map`
 
 error: aborting due to 3 previous errors
 
index 5ea9bcfc122cb31df5cd24b3c9467a8672d01adb..680aff1726f9f905e056c800fad7a27206bfa5f5 100644 (file)
@@ -13,9 +13,6 @@ LL |         Some(true)
                         found type `bool` (`bool`)
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^
 
 error: aborting due to previous error
 
index 906001ca1e09ee026b7d5fef1f02482310244bc4..72fb0e4d774312780cb81e6e5f8fc1617f0d8113 100644 (file)
@@ -2,31 +2,28 @@ error[E0631]: type mismatch in closure arguments
   --> $DIR/issue-36053-2.rs:7:32
    |
 LL |     once::<&str>("str").fuse().filter(|a: &str| true).count();
-   |                                ^^^^^^ --------- found signature defined here
-   |                                |
+   |                                ^^^^^^ ---------
+   |                                |      |   |
+   |                                |      |   help: consider borrowing the argument: `&&str`
+   |                                |      found signature defined here
    |                                expected due to this
    |
    = note: expected closure signature `for<'a> fn(&'a &str) -> _`
               found closure signature `for<'a> fn(&'a str) -> _`
 note: required by a bound in `filter`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         P: FnMut(&Self::Item) -> bool,
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `filter`
 
-error[E0599]: the method `count` exists for struct `Filter<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:48]>`, but its trait bounds were not satisfied
+error[E0599]: the method `count` exists for struct `Filter<Fuse<Once<&str>>, [closure@issue-36053-2.rs:7:39]>`, but its trait bounds were not satisfied
   --> $DIR/issue-36053-2.rs:7:55
    |
 LL |     once::<&str>("str").fuse().filter(|a: &str| true).count();
-   |                                       ---------       ^^^^^ method cannot be called on `Filter<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:48]>` due to unsatisfied trait bounds
+   |                                       ---------       ^^^^^ method cannot be called due to unsatisfied trait bounds
    |                                       |
    |                                       doesn't satisfy `<_ as FnOnce<(&&str,)>>::Output = bool`
    |                                       doesn't satisfy `_: FnMut<(&&str,)>`
+  --> $SRC_DIR/core/src/iter/adapters/filter.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/iter/adapters/filter.rs:LL:COL
-   |
-LL | pub struct Filter<I, P> {
-   | ----------------------- doesn't satisfy `_: Iterator`
+   = note: doesn't satisfy `_: Iterator`
    |
    = note: the following trait bounds were not satisfied:
            `<[closure@$DIR/issue-36053-2.rs:7:39: 7:48] as FnOnce<(&&str,)>>::Output = bool`
index d596b4a69f34a89c1c352dab236708feb6da91a4..a5f38dd53666151a272d2893d6c2447b0895f5e8 100644 (file)
@@ -10,9 +10,6 @@ LL |         None::<()>.map(Self::f);
    |
 note: required by a bound in `Option::<T>::map`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |         F: ~const FnOnce(T) -> U,
-   |            ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Option::<T>::map`
 
 error: aborting due to previous error
 
index 8b8563684014dbf633909ab7825dcf7c52cffac8..d9d408844d0a49140737ca05f8007dfa68541174 100644 (file)
@@ -11,9 +11,6 @@ LL |         self.foo.map(Foo::new)
    |
 note: required by a bound in `Option::<T>::map`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |         F: ~const FnOnce(T) -> U,
-   |            ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Option::<T>::map`
 
 error[E0593]: function is expected to take 0 arguments, but it takes 1 argument
   --> $DIR/issue-47706.rs:27:9
index 94a9c97576f674b186ef8d7c14f12441860191c5..b75c7a99fdd334c98fc8d956c9310233a24fc7d0 100644 (file)
@@ -14,11 +14,9 @@ error: `impl` item signature doesn't match `trait` item signature
    |
 LL |     fn next(&mut self) -> Option<IteratorChunk<T, S>> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'1, T, S>>`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |     fn next(&mut self) -> Option<Self::Item>;
-   |     ----------------------------------------- expected `fn(&'1 mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'static, T, S>>`
+   = note: expected `fn(&'1 mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'static, T, S>>`
    |
    = note: expected `fn(&'1 mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'static, T, S>>`
               found `fn(&'1 mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'1, T, S>>`
index 36748fae13c9413fae09d3b016b6ed0776b460fa..d3b7525072ff4748addf112f24b185d8ac0e0238 100644 (file)
@@ -1,18 +1,13 @@
 error[E0277]: `Foo` doesn't implement `Debug`
-  --> $DIR/method-help-unsatisfied-bound.rs:5:5
+  --> $DIR/method-help-unsatisfied-bound.rs:5:7
    |
 LL |     a.unwrap();
-   |     ^ ------ required by a bound introduced by this call
-   |     |
-   |     `Foo` cannot be formatted using `{:?}`
+   |       ^^^^^^ `Foo` cannot be formatted using `{:?}`
    |
    = help: the trait `Debug` is not implemented for `Foo`
    = note: add `#[derive(Debug)]` to `Foo` or manually `impl Debug for Foo`
 note: required by a bound in `Result::<T, E>::unwrap`
   --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |         E: fmt::Debug,
-   |            ^^^^^^^^^^ required by this bound in `Result::<T, E>::unwrap`
 help: consider annotating `Foo` with `#[derive(Debug)]`
    |
 LL | #[derive(Debug)]
index e65ae58d4ce96ab55d5db11fc6c64c0d9b5de25c..46a383325526db3371d9a1eb99bf66d534fa1f4e 100644 (file)
@@ -9,9 +9,6 @@ LL |     Some(42_u8)
    = note: enum `std::option::Option` and enum `Option` have similar names, but are actually distinct types
 note: enum `std::option::Option` is defined in crate `core`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL | pub enum Option<T> {
-   | ^^^^^^^^^^^^^^^^^^
 note: enum `Option` is defined in the current crate
   --> $DIR/similar_paths.rs:1:1
    |
index e8eb8d263ec795d068e71d14ef464dc56020a7e4..fdd92cbfc44370ba06c3c492ca72851eb9c5b294 100644 (file)
@@ -42,7 +42,7 @@ error[E0308]: mismatched types
   --> $DIR/wrap-suggestion-privacy.rs:22:17
    |
 LL |     needs_ready(Some(0));
-   |     ----------- ^^^^^^^ expected struct `std::future::Ready`, found enum `Option`
+   |     ----------- ^^^^^^^ expected struct `Ready`, found enum `Option`
    |     |
    |     arguments to this function are incorrect
    |
diff --git a/src/test/ui/missing/missing-alloc_error_handler.rs b/src/test/ui/missing/missing-alloc_error_handler.rs
deleted file mode 100644 (file)
index 4d378f0..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// compile-flags: -C panic=abort
-// no-prefer-dynamic
-
-#![no_std]
-#![crate_type = "staticlib"]
-#![feature(alloc_error_handler)]
-
-#[panic_handler]
-fn panic(_: &core::panic::PanicInfo) -> ! {
-    loop {}
-}
-
-extern crate alloc;
-
-#[global_allocator]
-static A: MyAlloc = MyAlloc;
-
-struct MyAlloc;
-
-unsafe impl core::alloc::GlobalAlloc for MyAlloc {
-    unsafe fn alloc(&self, _: core::alloc::Layout) -> *mut u8 { 0 as _ }
-    unsafe fn dealloc(&self, _: *mut u8, _: core::alloc::Layout) {}
-}
diff --git a/src/test/ui/missing/missing-alloc_error_handler.stderr b/src/test/ui/missing/missing-alloc_error_handler.stderr
deleted file mode 100644 (file)
index 995fa7c..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-error: `#[alloc_error_handler]` function required, but not found
-
-note: use `#![feature(default_alloc_error_handler)]` for a default error handler
-
-error: aborting due to previous error
-
index 6e4a4e5ba22c100872731b44911e34d57d260fd1..c5159471fe3e405bf9775d8ca1eb16f39433840f 100644 (file)
@@ -5,11 +5,16 @@ LL |     match x {
    |           ^
 LL |
 LL |         &Some(_y) => (),
-   |         ---------
-   |         |     |
-   |         |     data moved here
-   |         |     move occurs because `_y` has type `Box<i32>`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `Some(_y)`
+   |               --
+   |               |
+   |               data moved here
+   |               move occurs because `_y` has type `Box<i32>`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -         &Some(_y) => (),
+LL +         Some(_y) => (),
+   |
 
 error: aborting due to previous error
 
index c13dc58826eb83bfa27ff49b2575db210dd877ee..b3f95ee192a565e85a6bc7647068168fd46e203f 100644 (file)
@@ -6,11 +6,8 @@ LL |     val.0.into_iter().next();
 LL |     val.0;
    |     ^^^^^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `val.0`
+note: `into_iter` takes ownership of the receiver `self`, which moves `val.0`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
    = note: move occurs because `val.0` has type `Vec<bool>`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `foo`
@@ -23,7 +20,7 @@ LL |     foo.use_self();
 LL |     foo;
    |     ^^^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `foo`
+note: `Foo::use_self` takes ownership of the receiver `self`, which moves `foo`
   --> $DIR/move-fn-self-receiver.rs:13:17
    |
 LL |     fn use_self(self) {}
@@ -49,7 +46,7 @@ LL |     boxed_foo.use_box_self();
 LL |     boxed_foo;
    |     ^^^^^^^^^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `boxed_foo`
+note: `Foo::use_box_self` takes ownership of the receiver `self`, which moves `boxed_foo`
   --> $DIR/move-fn-self-receiver.rs:14:21
    |
 LL |     fn use_box_self(self: Box<Self>) {}
@@ -65,7 +62,7 @@ LL |     pin_box_foo.use_pin_box_self();
 LL |     pin_box_foo;
    |     ^^^^^^^^^^^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `pin_box_foo`
+note: `Foo::use_pin_box_self` takes ownership of the receiver `self`, which moves `pin_box_foo`
   --> $DIR/move-fn-self-receiver.rs:15:25
    |
 LL |     fn use_pin_box_self(self: Pin<Box<Self>>) {}
@@ -91,7 +88,7 @@ LL |     rc_foo.use_rc_self();
 LL |     rc_foo;
    |     ^^^^^^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `rc_foo`
+note: `Foo::use_rc_self` takes ownership of the receiver `self`, which moves `rc_foo`
   --> $DIR/move-fn-self-receiver.rs:16:20
    |
 LL |     fn use_rc_self(self: Rc<Self>) {}
@@ -113,9 +110,6 @@ LL |     foo_add;
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL |     fn add(self, rhs: Rhs) -> Self::Output;
-   |            ^^^^
 
 error[E0382]: use of moved value: `implicit_into_iter`
   --> $DIR/move-fn-self-receiver.rs:63:5
@@ -157,7 +151,7 @@ LL |     for _val in container.custom_into_iter() {}
 LL |     container;
    |     ^^^^^^^^^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `container`
+note: `Container::custom_into_iter` takes ownership of the receiver `self`, which moves `container`
   --> $DIR/move-fn-self-receiver.rs:23:25
    |
 LL |     fn custom_into_iter(self) -> impl Iterator<Item = bool> {
index 0caa0b83a4c7cbe00939ab4cc0ed8a43ec7de3db..26d4996d6cb1d7dc18b578eab8071f9fca446abf 100644 (file)
@@ -2,45 +2,61 @@ error[E0508]: cannot move out of type `[D; 4]`, a non-copy array
   --> $DIR/move-out-of-array-ref.rs:8:24
    |
 LL |     let [_, e, _, _] = *a;
-   |             -          ^^
-   |             |          |
-   |             |          cannot move out of here
-   |             |          help: consider borrowing here: `&*a`
+   |             -          ^^ cannot move out of here
+   |             |
    |             data moved here
    |             move occurs because `e` has type `D`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let [_, e, _, _] = *a;
+LL +     let [_, e, _, _] = a;
+   |
 
 error[E0508]: cannot move out of type `[D; 4]`, a non-copy array
   --> $DIR/move-out-of-array-ref.rs:13:27
    |
 LL |     let [_, s @ .. , _] = *a;
-   |             -             ^^
-   |             |             |
-   |             |             cannot move out of here
-   |             |             help: consider borrowing here: `&*a`
+   |             -             ^^ cannot move out of here
+   |             |
    |             data moved here
    |             move occurs because `s` has type `[D; 2]`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let [_, s @ .. , _] = *a;
+LL +     let [_, s @ .. , _] = a;
+   |
 
 error[E0508]: cannot move out of type `[D; 4]`, a non-copy array
   --> $DIR/move-out-of-array-ref.rs:18:24
    |
 LL |     let [_, e, _, _] = *a;
-   |             -          ^^
-   |             |          |
-   |             |          cannot move out of here
-   |             |          help: consider borrowing here: `&*a`
+   |             -          ^^ cannot move out of here
+   |             |
    |             data moved here
    |             move occurs because `e` has type `D`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let [_, e, _, _] = *a;
+LL +     let [_, e, _, _] = a;
+   |
 
 error[E0508]: cannot move out of type `[D; 4]`, a non-copy array
   --> $DIR/move-out-of-array-ref.rs:23:27
    |
 LL |     let [_, s @ .. , _] = *a;
-   |             -             ^^
-   |             |             |
-   |             |             cannot move out of here
-   |             |             help: consider borrowing here: `&*a`
+   |             -             ^^ cannot move out of here
+   |             |
    |             data moved here
    |             move occurs because `s` has type `[D; 2]`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let [_, s @ .. , _] = *a;
+LL +     let [_, s @ .. , _] = a;
+   |
 
 error: aborting due to 4 previous errors
 
index ce5ddb3e183b10ed1ca113fe70ca8aa6baa21ac1..5a0357cf567da1e86140d5638d5ab64fb410b658 100644 (file)
@@ -8,6 +8,11 @@ LL |         box [a] => {},
    |              |
    |              data moved here
    |              move occurs because `a` has type `A`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         box [ref a] => {},
+   |              +++
 
 error: aborting due to previous error
 
index 59c02d42bf17ebe844771f6b20b27b313be15fed..2f7394fbfd36ceba4c381151f17ab6e3460744a4 100644 (file)
@@ -1,5 +1,6 @@
 #![feature(unsized_locals)]
 //~^ WARN the feature `unsized_locals` is incomplete
+#![allow(unused)]
 
 struct A;
 #[derive(Clone, Copy)]
index 46357ce6f2eacaaf80828bb0183554baa9c6a74a..b46854cd6b4584390f90b0be37a6e752a602e575 100644 (file)
@@ -8,7 +8,7 @@ LL | #![feature(unsized_locals)]
    = note: `#[warn(incomplete_features)]` on by default
 
 error[E0508]: cannot move out of type `[A]`, a non-copy slice
-  --> $DIR/move-out-of-slice-2.rs:10:11
+  --> $DIR/move-out-of-slice-2.rs:11:11
    |
 LL |     match *a {
    |           ^^ cannot move out of here
@@ -18,9 +18,14 @@ LL |         [a @ ..] => {}
    |          |
    |          data moved here
    |          move occurs because `a` has type `[A]`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         [ref a @ ..] => {}
+   |          +++
 
 error[E0508]: cannot move out of type `[A]`, a non-copy slice
-  --> $DIR/move-out-of-slice-2.rs:16:11
+  --> $DIR/move-out-of-slice-2.rs:17:11
    |
 LL |     match *b {
    |           ^^ cannot move out of here
@@ -30,9 +35,14 @@ LL |         [_, _, b @ .., _] => {}
    |                |
    |                data moved here
    |                move occurs because `b` has type `[A]`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         [_, _, ref b @ .., _] => {}
+   |                +++
 
 error[E0508]: cannot move out of type `[C]`, a non-copy slice
-  --> $DIR/move-out-of-slice-2.rs:24:11
+  --> $DIR/move-out-of-slice-2.rs:25:11
    |
 LL |     match *c {
    |           ^^ cannot move out of here
@@ -42,9 +52,14 @@ LL |         [c @ ..] => {}
    |          |
    |          data moved here
    |          move occurs because `c` has type `[C]`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         [ref c @ ..] => {}
+   |          +++
 
 error[E0508]: cannot move out of type `[C]`, a non-copy slice
-  --> $DIR/move-out-of-slice-2.rs:30:11
+  --> $DIR/move-out-of-slice-2.rs:31:11
    |
 LL |     match *d {
    |           ^^ cannot move out of here
@@ -54,6 +69,11 @@ LL |         [_, _, d @ .., _] => {}
    |                |
    |                data moved here
    |                move occurs because `d` has type `[C]`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         [_, _, ref d @ .., _] => {}
+   |                +++
 
 error: aborting due to 4 previous errors; 1 warning emitted
 
index a49ee31b46622c8570e21cd0969b656e176437d3..0b1a623a01345d75294e7bbe31faf28963421782 100644 (file)
@@ -8,11 +8,8 @@ LL |     consume(x.into_iter().next().unwrap());
 LL |     touch(&x[0]);
    |            ^ value borrowed here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `x`
+note: `into_iter` takes ownership of the receiver `self`, which moves `x`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 help: consider cloning the value if the performance cost is acceptable
    |
 LL |     consume(x.clone().into_iter().next().unwrap());
index 5ed91a0d5596340888162fbf5dcef12579104f49..df09ababa5a01f2718d12830aeaa82f944fab49d 100644 (file)
@@ -2,13 +2,18 @@ error[E0507]: cannot move out of `hellothere.x` as enum variant `Bar` which is b
   --> $DIR/moves-based-on-type-block-bad.rs:22:19
    |
 LL |             match hellothere.x {
-   |                   ^^^^^^^^^^^^ help: consider borrowing here: `&hellothere.x`
+   |                   ^^^^^^^^^^^^
 LL |                 box E::Foo(_) => {}
 LL |                 box E::Bar(x) => println!("{}", x.to_string()),
    |                            -
    |                            |
    |                            data moved here
    |                            move occurs because `x` has type `Box<isize>`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |             match &hellothere.x {
+   |                   +
 
 error: aborting due to previous error
 
index 838b1282cb4ed883de4561af3c7104e08b719655..ae76889f104c89a80910e73028a8675818094e8d 100644 (file)
@@ -160,11 +160,8 @@ LL |     let _y = x.into_iter().next().unwrap();
 LL |     touch(&x);
    |           ^^ value borrowed here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `x`
+note: `into_iter` takes ownership of the receiver `self`, which moves `x`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 help: consider cloning the value if the performance cost is acceptable
    |
 LL |     let _y = x.clone().into_iter().next().unwrap();
@@ -180,11 +177,8 @@ LL |     let _y = [x.into_iter().next().unwrap(); 1];
 LL |     touch(&x);
    |           ^^ value borrowed here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `x`
+note: `into_iter` takes ownership of the receiver `self`, which moves `x`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 help: consider cloning the value if the performance cost is acceptable
    |
 LL |     let _y = [x.clone().into_iter().next().unwrap(); 1];
index 45cf3723483f3a05f0ca60546bc6c949bb7df68a..a0f790dba15ed21adddebbcb5daf9faa8cd909ef 100644 (file)
@@ -1,4 +1,4 @@
-error[E0271]: expected `[closure@$DIR/fallback-closure-wrap.rs:18:40: 18:47]` to be a closure that returns `()`, but it returns `!`
+error[E0271]: expected `[closure@fallback-closure-wrap.rs:18:40]` to be a closure that returns `()`, but it returns `!`
   --> $DIR/fallback-closure-wrap.rs:18:31
    |
 LL |       let error = Closure::wrap(Box::new(move || {
index 6dc039fc35db7c3294c82b065ec17706d83dfc81..2db1cc4b776905e8fdb3c0086602a1057a91e607 100644 (file)
@@ -5,7 +5,7 @@ LL |     foo(panic!())
    |     --- ^^^^^^^^
    |     |   |
    |     |   the trait `T` is not implemented for `()`
-   |     |   this tail expression is of type `_`
+   |     |   this tail expression is of type `()`
    |     required by a bound introduced by this call
    |
 note: required by a bound in `foo`
index 0910e9ad77a846a00e90a4a53b43f89998855eec..de5c9c5601635eedef6cc14e9900d98d61414691 100644 (file)
@@ -46,9 +46,6 @@ LL |     [(); { for _ in 0usize.. {}; 0}];
    |
 note: impl defined here, but it is not `const`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL | impl<I: Iterator> const IntoIterator for I {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: calls in constants are limited to constant functions, tuple structs and tuple variants
 
 error[E0658]: mutable references are not allowed in constants
index 168cf2f83535d3558848392d29d3c6632edf9e40..e148b983e8e9da2836c479cc0bfd21ee3b872b8f 100644 (file)
@@ -26,9 +26,6 @@ LL |     0.....{loop{}1};
             found struct `RangeTo<{integer}>`
 note: associated function defined here
   --> $SRC_DIR/core/src/ops/range.rs:LL:COL
-   |
-LL |     pub const fn new(start: Idx, end: Idx) -> Self {
-   |                  ^^^
 
 error: aborting due to 2 previous errors
 
index 56a5cdff073e48aceffb69519776de9c0ed680c9..0dc5c08ea5f08d76ffe34d4b550e0075a836e91b 100644 (file)
@@ -2,28 +2,37 @@ error[E0507]: cannot move out of `*r` which is behind a shared reference
   --> $DIR/cannot-move-block-spans.rs:5:15
    |
 LL |     let x = { *r };
-   |               ^^
-   |               |
-   |               move occurs because `*r` has type `String`, which does not implement the `Copy` trait
-   |               help: consider borrowing here: `&*r`
+   |               ^^ move occurs because `*r` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let x = { *r };
+LL +     let x = { r };
+   |
 
 error[E0507]: cannot move out of `*r` which is behind a shared reference
   --> $DIR/cannot-move-block-spans.rs:6:22
    |
 LL |     let y = unsafe { *r };
-   |                      ^^
-   |                      |
-   |                      move occurs because `*r` has type `String`, which does not implement the `Copy` trait
-   |                      help: consider borrowing here: `&*r`
+   |                      ^^ move occurs because `*r` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let y = unsafe { *r };
+LL +     let y = unsafe { r };
+   |
 
 error[E0507]: cannot move out of `*r` which is behind a shared reference
   --> $DIR/cannot-move-block-spans.rs:7:26
    |
 LL |     let z = loop { break *r; };
-   |                          ^^
-   |                          |
-   |                          move occurs because `*r` has type `String`, which does not implement the `Copy` trait
-   |                          help: consider borrowing here: `&*r`
+   |                          ^^ move occurs because `*r` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let z = loop { break *r; };
+LL +     let z = loop { break r; };
+   |
 
 error[E0508]: cannot move out of type `[String; 2]`, a non-copy array
   --> $DIR/cannot-move-block-spans.rs:11:15
@@ -33,7 +42,11 @@ LL |     let x = { arr[0] };
    |               |
    |               cannot move out of here
    |               move occurs because `arr[_]` has type `String`, which does not implement the `Copy` trait
-   |               help: consider borrowing here: `&arr[0]`
+   |
+help: consider borrowing here
+   |
+LL |     let x = { &arr[0] };
+   |               +
 
 error[E0508]: cannot move out of type `[String; 2]`, a non-copy array
   --> $DIR/cannot-move-block-spans.rs:12:22
@@ -43,7 +56,11 @@ LL |     let y = unsafe { arr[0] };
    |                      |
    |                      cannot move out of here
    |                      move occurs because `arr[_]` has type `String`, which does not implement the `Copy` trait
-   |                      help: consider borrowing here: `&arr[0]`
+   |
+help: consider borrowing here
+   |
+LL |     let y = unsafe { &arr[0] };
+   |                      +
 
 error[E0508]: cannot move out of type `[String; 2]`, a non-copy array
   --> $DIR/cannot-move-block-spans.rs:13:26
@@ -53,34 +70,47 @@ LL |     let z = loop { break arr[0]; };
    |                          |
    |                          cannot move out of here
    |                          move occurs because `arr[_]` has type `String`, which does not implement the `Copy` trait
-   |                          help: consider borrowing here: `&arr[0]`
+   |
+help: consider borrowing here
+   |
+LL |     let z = loop { break &arr[0]; };
+   |                          +
 
 error[E0507]: cannot move out of `*r` which is behind a shared reference
   --> $DIR/cannot-move-block-spans.rs:17:38
    |
 LL |     let x = { let mut u = 0; u += 1; *r };
-   |                                      ^^
-   |                                      |
-   |                                      move occurs because `*r` has type `String`, which does not implement the `Copy` trait
-   |                                      help: consider borrowing here: `&*r`
+   |                                      ^^ move occurs because `*r` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let x = { let mut u = 0; u += 1; *r };
+LL +     let x = { let mut u = 0; u += 1; r };
+   |
 
 error[E0507]: cannot move out of `*r` which is behind a shared reference
   --> $DIR/cannot-move-block-spans.rs:18:45
    |
 LL |     let y = unsafe { let mut u = 0; u += 1; *r };
-   |                                             ^^
-   |                                             |
-   |                                             move occurs because `*r` has type `String`, which does not implement the `Copy` trait
-   |                                             help: consider borrowing here: `&*r`
+   |                                             ^^ move occurs because `*r` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let y = unsafe { let mut u = 0; u += 1; *r };
+LL +     let y = unsafe { let mut u = 0; u += 1; r };
+   |
 
 error[E0507]: cannot move out of `*r` which is behind a shared reference
   --> $DIR/cannot-move-block-spans.rs:19:49
    |
 LL |     let z = loop { let mut u = 0; u += 1; break *r; u += 2; };
-   |                                                 ^^
-   |                                                 |
-   |                                                 move occurs because `*r` has type `String`, which does not implement the `Copy` trait
-   |                                                 help: consider borrowing here: `&*r`
+   |                                                 ^^ move occurs because `*r` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let z = loop { let mut u = 0; u += 1; break *r; u += 2; };
+LL +     let z = loop { let mut u = 0; u += 1; break r; u += 2; };
+   |
 
 error: aborting due to 9 previous errors
 
index c0a17a67ee269771867b0903945dd9b55717c06d..7f9cbc3c30a92a9ddabcc689bcbb159685ff5acc 100644 (file)
@@ -36,7 +36,11 @@ LL |     let p = s.url; p
    |             |
    |             cannot move out of here
    |             move occurs because `s.url` has type `&mut String`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&s.url`
+   |
+help: consider borrowing here
+   |
+LL |     let p = &s.url; p
+   |             +
 
 error: aborting due to 4 previous errors
 
index b03fcf70babe25850fcc3d068e15a4e282b63dda..58b8aa31d4c2d26c5c140de80b8c1d6ca28fb192 100644 (file)
@@ -2,10 +2,13 @@ error[E0507]: cannot move out of `*a` which is behind a shared reference
   --> $DIR/move-errors.rs:6:13
    |
 LL |     let b = *a;
-   |             ^^
-   |             |
-   |             move occurs because `*a` has type `A`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&*a`
+   |             ^^ move occurs because `*a` has type `A`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let b = *a;
+LL +     let b = a;
+   |
 
 error[E0508]: cannot move out of type `[A; 1]`, a non-copy array
   --> $DIR/move-errors.rs:12:13
@@ -15,25 +18,35 @@ LL |     let b = a[0];
    |             |
    |             cannot move out of here
    |             move occurs because `a[_]` has type `A`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&a[0]`
+   |
+help: consider borrowing here
+   |
+LL |     let b = &a[0];
+   |             +
 
 error[E0507]: cannot move out of `**r` which is behind a shared reference
   --> $DIR/move-errors.rs:19:13
    |
 LL |     let s = **r;
-   |             ^^^
-   |             |
-   |             move occurs because `**r` has type `A`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&**r`
+   |             ^^^ move occurs because `**r` has type `A`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let s = **r;
+LL +     let s = *r;
+   |
 
 error[E0507]: cannot move out of an `Rc`
   --> $DIR/move-errors.rs:27:13
    |
 LL |     let s = *r;
-   |             ^^
-   |             |
-   |             move occurs because value has type `A`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&*r`
+   |             ^^ move occurs because value has type `A`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let s = *r;
+LL +     let s = r;
+   |
 
 error[E0508]: cannot move out of type `[A; 1]`, a non-copy array
   --> $DIR/move-errors.rs:32:13
@@ -43,16 +56,26 @@ LL |     let a = [A("".to_string())][0];
    |             |
    |             cannot move out of here
    |             move occurs because value has type `A`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&[A("".to_string())][0]`
+   |
+help: consider borrowing here
+   |
+LL |     let a = &[A("".to_string())][0];
+   |             +
 
 error[E0507]: cannot move out of `a` which is behind a shared reference
   --> $DIR/move-errors.rs:38:16
    |
 LL |     let A(s) = *a;
-   |           -    ^^ help: consider borrowing here: `&*a`
+   |           -    ^^
    |           |
    |           data moved here
    |           move occurs because `s` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let A(s) = *a;
+LL +     let A(s) = a;
+   |
 
 error[E0509]: cannot move out of type `D`, which implements the `Drop` trait
   --> $DIR/move-errors.rs:44:19
@@ -62,6 +85,11 @@ LL |     let C(D(s)) = c;
    |             |
    |             data moved here
    |             move occurs because `s` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     let C(D(ref s)) = c;
+   |             +++
 
 error[E0507]: cannot move out of `*a` which is behind a shared reference
   --> $DIR/move-errors.rs:51:9
@@ -73,10 +101,7 @@ error[E0508]: cannot move out of type `[B; 1]`, a non-copy array
   --> $DIR/move-errors.rs:74:11
    |
 LL |     match x[0] {
-   |           ^^^^
-   |           |
-   |           cannot move out of here
-   |           help: consider borrowing here: `&x[0]`
+   |           ^^^^ cannot move out of here
 LL |
 LL |         B::U(d) => (),
    |              - data moved here
@@ -84,6 +109,10 @@ LL |         B::V(s) => (),
    |              - ...and here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider borrowing here
+   |
+LL |     match &x[0] {
+   |           +
 
 error[E0509]: cannot move out of type `D`, which implements the `Drop` trait
   --> $DIR/move-errors.rs:83:11
@@ -96,6 +125,11 @@ LL |         B::U(D(s)) => (),
    |                |
    |                data moved here
    |                move occurs because `s` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         B::U(D(ref s)) => (),
+   |                +++
 
 error[E0509]: cannot move out of type `D`, which implements the `Drop` trait
   --> $DIR/move-errors.rs:92:11
@@ -108,6 +142,11 @@ LL |         (D(s), &t) => (),
    |            |
    |            data moved here
    |            move occurs because `s` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         (D(ref s), &t) => (),
+   |            +++
 
 error[E0507]: cannot move out of `*x.1` which is behind a shared reference
   --> $DIR/move-errors.rs:92:11
@@ -120,6 +159,11 @@ LL |         (D(s), &t) => (),
    |                 |
    |                 data moved here
    |                 move occurs because `t` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         (D(s), &ref t) => (),
+   |                 +++
 
 error[E0509]: cannot move out of type `F`, which implements the `Drop` trait
   --> $DIR/move-errors.rs:102:11
@@ -133,18 +177,32 @@ LL |         F(s, mut t) => (),
    |           data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider borrowing the pattern binding
+   |
+LL |         F(ref s, mut t) => (),
+   |           +++
+help: consider borrowing the pattern binding
+   |
+LL |         F(s, ref mut t) => (),
+   |              +++
 
 error[E0507]: cannot move out of `x` as enum variant `Err` which is behind a shared reference
   --> $DIR/move-errors.rs:110:11
    |
 LL |     match *x {
-   |           ^^ help: consider borrowing here: `&*x`
+   |           ^^
 LL |
 LL |         Ok(s) | Err(s) => (),
    |            -
    |            |
    |            data moved here
    |            move occurs because `s` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     match *x {
+LL +     match x {
+   |
 
 error: aborting due to 14 previous errors
 
index 9ae41e78c227dc769e9b2bde8ea00f4a6dcb6131..296e1fb3f26fe01319e36320608ee1c6365f6536 100644 (file)
@@ -13,11 +13,6 @@ LL |     assert_eq!((*arc_v)[2], 3);
    |                ^^^^^^^^ value borrowed here after move
    |
    = note: borrow occurs due to deref coercion to `Vec<i32>`
-note: deref defined here
-  --> $SRC_DIR/alloc/src/sync.rs:LL:COL
-   |
-LL |     type Target = T;
-   |     ^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 564b05854740ccfc6b63771872fc52337c71d500..bcd481c33f361b374b7ee26aea00c8ce50a99a9e 100644 (file)
@@ -13,11 +13,6 @@ LL |     assert_eq!((*arc_v)[2], 3);
    |                ^^^^^^^^ value borrowed here after move
    |
    = note: borrow occurs due to deref coercion to `Vec<i32>`
-note: deref defined here
-  --> $SRC_DIR/alloc/src/sync.rs:LL:COL
-   |
-LL |     type Target = T;
-   |     ^^^^^^^^^^^
 
 error: aborting due to previous error
 
index c864b93dbbbe17aef49193dbc69acc3f43930b30..75561f4119aa543d432b53da3df5bdf2957a5074 100644 (file)
@@ -31,9 +31,6 @@ LL |     thread::spawn(move|| {
    |                   ^^^^^^
 note: required by a bound in `spawn`
   --> $SRC_DIR/std/src/thread/mod.rs:LL:COL
-   |
-LL |     F: Send + 'static,
-   |        ^^^^ required by this bound in `spawn`
 
 error: aborting due to previous error
 
index f61ee661bb7edbe205b97b68bcb99383eca8ae8c..37d94cf0ebd8c515e7c1d1db7fb7a01ad1276c34 100644 (file)
@@ -1,13 +1,11 @@
 error[E0277]: the trait bound `S: Clone` is not satisfied in `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]`
-  --> $DIR/not-clone-closure.rs:11:17
+  --> $DIR/not-clone-closure.rs:11:23
    |
 LL |     let hello = move || {
    |                 ------- within this `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]`
 ...
 LL |     let hello = hello.clone();
-   |                 ^^^^^ ----- required by a bound introduced by this call
-   |                 |
-   |                 within `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]`, the trait `Clone` is not implemented for `S`
+   |                       ^^^^^ within `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]`, the trait `Clone` is not implemented for `S`
    |
 note: required because it's used within this closure
   --> $DIR/not-clone-closure.rs:7:17
index 2f58f164985db92b3fd4f5b8c2b8802c4c902c65..d5213e3f5b690d757baa39a21bcdd17b62f97195 100644 (file)
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:23:16
    |
 LL |         x_u8 > x_u16;
-   |                ^^^^^ expected `u8`, found `u16`
+   |         ----   ^^^^^ expected `u8`, found `u16`
+   |         |
+   |         expected because this is `u8`
    |
 help: you can convert `x_u8` from `u8` to `u16`, matching the type of `x_u16`
    |
@@ -13,7 +15,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:25:16
    |
 LL |         x_u8 > x_u32;
-   |                ^^^^^ expected `u8`, found `u32`
+   |         ----   ^^^^^ expected `u8`, found `u32`
+   |         |
+   |         expected because this is `u8`
    |
 help: you can convert `x_u8` from `u8` to `u32`, matching the type of `x_u32`
    |
@@ -24,7 +28,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:27:16
    |
 LL |         x_u8 > x_u64;
-   |                ^^^^^ expected `u8`, found `u64`
+   |         ----   ^^^^^ expected `u8`, found `u64`
+   |         |
+   |         expected because this is `u8`
    |
 help: you can convert `x_u8` from `u8` to `u64`, matching the type of `x_u64`
    |
@@ -35,7 +41,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:29:16
    |
 LL |         x_u8 > x_u128;
-   |                ^^^^^^ expected `u8`, found `u128`
+   |         ----   ^^^^^^ expected `u8`, found `u128`
+   |         |
+   |         expected because this is `u8`
    |
 help: you can convert `x_u8` from `u8` to `u128`, matching the type of `x_u128`
    |
@@ -46,7 +54,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:31:16
    |
 LL |         x_u8 > x_usize;
-   |                ^^^^^^^ expected `u8`, found `usize`
+   |         ----   ^^^^^^^ expected `u8`, found `usize`
+   |         |
+   |         expected because this is `u8`
    |
 help: you can convert `x_u8` from `u8` to `usize`, matching the type of `x_usize`
    |
@@ -57,7 +67,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:34:17
    |
 LL |         x_u16 > x_u8;
-   |                 ^^^^ expected `u16`, found `u8`
+   |         -----   ^^^^ expected `u16`, found `u8`
+   |         |
+   |         expected because this is `u16`
    |
 help: you can convert a `u8` to a `u16`
    |
@@ -68,7 +80,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:36:17
    |
 LL |         x_u16 > x_u32;
-   |                 ^^^^^ expected `u16`, found `u32`
+   |         -----   ^^^^^ expected `u16`, found `u32`
+   |         |
+   |         expected because this is `u16`
    |
 help: you can convert `x_u16` from `u16` to `u32`, matching the type of `x_u32`
    |
@@ -79,7 +93,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:38:17
    |
 LL |         x_u16 > x_u64;
-   |                 ^^^^^ expected `u16`, found `u64`
+   |         -----   ^^^^^ expected `u16`, found `u64`
+   |         |
+   |         expected because this is `u16`
    |
 help: you can convert `x_u16` from `u16` to `u64`, matching the type of `x_u64`
    |
@@ -90,7 +106,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:40:17
    |
 LL |         x_u16 > x_u128;
-   |                 ^^^^^^ expected `u16`, found `u128`
+   |         -----   ^^^^^^ expected `u16`, found `u128`
+   |         |
+   |         expected because this is `u16`
    |
 help: you can convert `x_u16` from `u16` to `u128`, matching the type of `x_u128`
    |
@@ -101,7 +119,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:42:17
    |
 LL |         x_u16 > x_usize;
-   |                 ^^^^^^^ expected `u16`, found `usize`
+   |         -----   ^^^^^^^ expected `u16`, found `usize`
+   |         |
+   |         expected because this is `u16`
    |
 help: you can convert `x_u16` from `u16` to `usize`, matching the type of `x_usize`
    |
@@ -112,7 +132,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:45:17
    |
 LL |         x_u32 > x_u8;
-   |                 ^^^^ expected `u32`, found `u8`
+   |         -----   ^^^^ expected `u32`, found `u8`
+   |         |
+   |         expected because this is `u32`
    |
 help: you can convert a `u8` to a `u32`
    |
@@ -123,7 +145,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:47:17
    |
 LL |         x_u32 > x_u16;
-   |                 ^^^^^ expected `u32`, found `u16`
+   |         -----   ^^^^^ expected `u32`, found `u16`
+   |         |
+   |         expected because this is `u32`
    |
 help: you can convert a `u16` to a `u32`
    |
@@ -134,7 +158,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:49:17
    |
 LL |         x_u32 > x_u64;
-   |                 ^^^^^ expected `u32`, found `u64`
+   |         -----   ^^^^^ expected `u32`, found `u64`
+   |         |
+   |         expected because this is `u32`
    |
 help: you can convert `x_u32` from `u32` to `u64`, matching the type of `x_u64`
    |
@@ -145,7 +171,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:51:17
    |
 LL |         x_u32 > x_u128;
-   |                 ^^^^^^ expected `u32`, found `u128`
+   |         -----   ^^^^^^ expected `u32`, found `u128`
+   |         |
+   |         expected because this is `u32`
    |
 help: you can convert `x_u32` from `u32` to `u128`, matching the type of `x_u128`
    |
@@ -156,7 +184,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:53:17
    |
 LL |         x_u32 > x_usize;
-   |                 ^^^^^^^ expected `u32`, found `usize`
+   |         -----   ^^^^^^^ expected `u32`, found `usize`
+   |         |
+   |         expected because this is `u32`
    |
 help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit
    |
@@ -167,7 +197,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:56:17
    |
 LL |         x_u64 > x_u8;
-   |                 ^^^^ expected `u64`, found `u8`
+   |         -----   ^^^^ expected `u64`, found `u8`
+   |         |
+   |         expected because this is `u64`
    |
 help: you can convert a `u8` to a `u64`
    |
@@ -178,7 +210,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:58:17
    |
 LL |         x_u64 > x_u16;
-   |                 ^^^^^ expected `u64`, found `u16`
+   |         -----   ^^^^^ expected `u64`, found `u16`
+   |         |
+   |         expected because this is `u64`
    |
 help: you can convert a `u16` to a `u64`
    |
@@ -189,7 +223,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:60:17
    |
 LL |         x_u64 > x_u32;
-   |                 ^^^^^ expected `u64`, found `u32`
+   |         -----   ^^^^^ expected `u64`, found `u32`
+   |         |
+   |         expected because this is `u64`
    |
 help: you can convert a `u32` to a `u64`
    |
@@ -200,7 +236,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:62:17
    |
 LL |         x_u64 > x_u128;
-   |                 ^^^^^^ expected `u64`, found `u128`
+   |         -----   ^^^^^^ expected `u64`, found `u128`
+   |         |
+   |         expected because this is `u64`
    |
 help: you can convert `x_u64` from `u64` to `u128`, matching the type of `x_u128`
    |
@@ -211,7 +249,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:64:17
    |
 LL |         x_u64 > x_usize;
-   |                 ^^^^^^^ expected `u64`, found `usize`
+   |         -----   ^^^^^^^ expected `u64`, found `usize`
+   |         |
+   |         expected because this is `u64`
    |
 help: you can convert a `usize` to a `u64` and panic if the converted value doesn't fit
    |
@@ -222,7 +262,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:67:18
    |
 LL |         x_u128 > x_u8;
-   |                  ^^^^ expected `u128`, found `u8`
+   |         ------   ^^^^ expected `u128`, found `u8`
+   |         |
+   |         expected because this is `u128`
    |
 help: you can convert a `u8` to a `u128`
    |
@@ -233,7 +275,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:69:18
    |
 LL |         x_u128 > x_u16;
-   |                  ^^^^^ expected `u128`, found `u16`
+   |         ------   ^^^^^ expected `u128`, found `u16`
+   |         |
+   |         expected because this is `u128`
    |
 help: you can convert a `u16` to a `u128`
    |
@@ -244,7 +288,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:71:18
    |
 LL |         x_u128 > x_u32;
-   |                  ^^^^^ expected `u128`, found `u32`
+   |         ------   ^^^^^ expected `u128`, found `u32`
+   |         |
+   |         expected because this is `u128`
    |
 help: you can convert a `u32` to a `u128`
    |
@@ -255,7 +301,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:73:18
    |
 LL |         x_u128 > x_u64;
-   |                  ^^^^^ expected `u128`, found `u64`
+   |         ------   ^^^^^ expected `u128`, found `u64`
+   |         |
+   |         expected because this is `u128`
    |
 help: you can convert a `u64` to a `u128`
    |
@@ -266,7 +314,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:75:18
    |
 LL |         x_u128 > x_usize;
-   |                  ^^^^^^^ expected `u128`, found `usize`
+   |         ------   ^^^^^^^ expected `u128`, found `usize`
+   |         |
+   |         expected because this is `u128`
    |
 help: you can convert a `usize` to a `u128` and panic if the converted value doesn't fit
    |
@@ -277,7 +327,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:78:19
    |
 LL |         x_usize > x_u8;
-   |                   ^^^^ expected `usize`, found `u8`
+   |         -------   ^^^^ expected `usize`, found `u8`
+   |         |
+   |         expected because this is `usize`
    |
 help: you can convert a `u8` to a `usize`
    |
@@ -288,7 +340,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:80:19
    |
 LL |         x_usize > x_u16;
-   |                   ^^^^^ expected `usize`, found `u16`
+   |         -------   ^^^^^ expected `usize`, found `u16`
+   |         |
+   |         expected because this is `usize`
    |
 help: you can convert a `u16` to a `usize`
    |
@@ -299,7 +353,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:82:19
    |
 LL |         x_usize > x_u32;
-   |                   ^^^^^ expected `usize`, found `u32`
+   |         -------   ^^^^^ expected `usize`, found `u32`
+   |         |
+   |         expected because this is `usize`
    |
 help: you can convert a `u32` to a `usize` and panic if the converted value doesn't fit
    |
@@ -310,7 +366,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:84:19
    |
 LL |         x_usize > x_u64;
-   |                   ^^^^^ expected `usize`, found `u64`
+   |         -------   ^^^^^ expected `usize`, found `u64`
+   |         |
+   |         expected because this is `usize`
    |
 help: you can convert a `u64` to a `usize` and panic if the converted value doesn't fit
    |
@@ -321,7 +379,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:86:19
    |
 LL |         x_usize > x_u128;
-   |                   ^^^^^^ expected `usize`, found `u128`
+   |         -------   ^^^^^^ expected `usize`, found `u128`
+   |         |
+   |         expected because this is `usize`
    |
 help: you can convert a `u128` to a `usize` and panic if the converted value doesn't fit
    |
@@ -332,7 +392,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:92:16
    |
 LL |         x_i8 > x_i16;
-   |                ^^^^^ expected `i8`, found `i16`
+   |         ----   ^^^^^ expected `i8`, found `i16`
+   |         |
+   |         expected because this is `i8`
    |
 help: you can convert `x_i8` from `i8` to `i16`, matching the type of `x_i16`
    |
@@ -343,7 +405,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:94:16
    |
 LL |         x_i8 > x_i32;
-   |                ^^^^^ expected `i8`, found `i32`
+   |         ----   ^^^^^ expected `i8`, found `i32`
+   |         |
+   |         expected because this is `i8`
    |
 help: you can convert `x_i8` from `i8` to `i32`, matching the type of `x_i32`
    |
@@ -354,7 +418,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:96:16
    |
 LL |         x_i8 > x_i64;
-   |                ^^^^^ expected `i8`, found `i64`
+   |         ----   ^^^^^ expected `i8`, found `i64`
+   |         |
+   |         expected because this is `i8`
    |
 help: you can convert `x_i8` from `i8` to `i64`, matching the type of `x_i64`
    |
@@ -365,7 +431,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:98:16
    |
 LL |         x_i8 > x_i128;
-   |                ^^^^^^ expected `i8`, found `i128`
+   |         ----   ^^^^^^ expected `i8`, found `i128`
+   |         |
+   |         expected because this is `i8`
    |
 help: you can convert `x_i8` from `i8` to `i128`, matching the type of `x_i128`
    |
@@ -376,7 +444,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:100:16
    |
 LL |         x_i8 > x_isize;
-   |                ^^^^^^^ expected `i8`, found `isize`
+   |         ----   ^^^^^^^ expected `i8`, found `isize`
+   |         |
+   |         expected because this is `i8`
    |
 help: you can convert `x_i8` from `i8` to `isize`, matching the type of `x_isize`
    |
@@ -387,7 +457,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:103:17
    |
 LL |         x_i16 > x_i8;
-   |                 ^^^^ expected `i16`, found `i8`
+   |         -----   ^^^^ expected `i16`, found `i8`
+   |         |
+   |         expected because this is `i16`
    |
 help: you can convert an `i8` to an `i16`
    |
@@ -398,7 +470,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:105:17
    |
 LL |         x_i16 > x_i32;
-   |                 ^^^^^ expected `i16`, found `i32`
+   |         -----   ^^^^^ expected `i16`, found `i32`
+   |         |
+   |         expected because this is `i16`
    |
 help: you can convert `x_i16` from `i16` to `i32`, matching the type of `x_i32`
    |
@@ -409,7 +483,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:107:17
    |
 LL |         x_i16 > x_i64;
-   |                 ^^^^^ expected `i16`, found `i64`
+   |         -----   ^^^^^ expected `i16`, found `i64`
+   |         |
+   |         expected because this is `i16`
    |
 help: you can convert `x_i16` from `i16` to `i64`, matching the type of `x_i64`
    |
@@ -420,7 +496,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:109:17
    |
 LL |         x_i16 > x_i128;
-   |                 ^^^^^^ expected `i16`, found `i128`
+   |         -----   ^^^^^^ expected `i16`, found `i128`
+   |         |
+   |         expected because this is `i16`
    |
 help: you can convert `x_i16` from `i16` to `i128`, matching the type of `x_i128`
    |
@@ -431,7 +509,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:111:17
    |
 LL |         x_i16 > x_isize;
-   |                 ^^^^^^^ expected `i16`, found `isize`
+   |         -----   ^^^^^^^ expected `i16`, found `isize`
+   |         |
+   |         expected because this is `i16`
    |
 help: you can convert `x_i16` from `i16` to `isize`, matching the type of `x_isize`
    |
@@ -442,7 +522,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:114:17
    |
 LL |         x_i32 > x_i8;
-   |                 ^^^^ expected `i32`, found `i8`
+   |         -----   ^^^^ expected `i32`, found `i8`
+   |         |
+   |         expected because this is `i32`
    |
 help: you can convert an `i8` to an `i32`
    |
@@ -453,7 +535,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:116:17
    |
 LL |         x_i32 > x_i16;
-   |                 ^^^^^ expected `i32`, found `i16`
+   |         -----   ^^^^^ expected `i32`, found `i16`
+   |         |
+   |         expected because this is `i32`
    |
 help: you can convert an `i16` to an `i32`
    |
@@ -464,7 +548,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:118:17
    |
 LL |         x_i32 > x_i64;
-   |                 ^^^^^ expected `i32`, found `i64`
+   |         -----   ^^^^^ expected `i32`, found `i64`
+   |         |
+   |         expected because this is `i32`
    |
 help: you can convert `x_i32` from `i32` to `i64`, matching the type of `x_i64`
    |
@@ -475,7 +561,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:120:17
    |
 LL |         x_i32 > x_i128;
-   |                 ^^^^^^ expected `i32`, found `i128`
+   |         -----   ^^^^^^ expected `i32`, found `i128`
+   |         |
+   |         expected because this is `i32`
    |
 help: you can convert `x_i32` from `i32` to `i128`, matching the type of `x_i128`
    |
@@ -486,7 +574,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:122:17
    |
 LL |         x_i32 > x_isize;
-   |                 ^^^^^^^ expected `i32`, found `isize`
+   |         -----   ^^^^^^^ expected `i32`, found `isize`
+   |         |
+   |         expected because this is `i32`
    |
 help: you can convert an `isize` to an `i32` and panic if the converted value doesn't fit
    |
@@ -497,7 +587,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:125:17
    |
 LL |         x_i64 > x_i8;
-   |                 ^^^^ expected `i64`, found `i8`
+   |         -----   ^^^^ expected `i64`, found `i8`
+   |         |
+   |         expected because this is `i64`
    |
 help: you can convert an `i8` to an `i64`
    |
@@ -508,7 +600,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:127:17
    |
 LL |         x_i64 > x_i16;
-   |                 ^^^^^ expected `i64`, found `i16`
+   |         -----   ^^^^^ expected `i64`, found `i16`
+   |         |
+   |         expected because this is `i64`
    |
 help: you can convert an `i16` to an `i64`
    |
@@ -519,7 +613,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:129:17
    |
 LL |         x_i64 > x_i32;
-   |                 ^^^^^ expected `i64`, found `i32`
+   |         -----   ^^^^^ expected `i64`, found `i32`
+   |         |
+   |         expected because this is `i64`
    |
 help: you can convert an `i32` to an `i64`
    |
@@ -530,7 +626,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:131:17
    |
 LL |         x_i64 > x_i128;
-   |                 ^^^^^^ expected `i64`, found `i128`
+   |         -----   ^^^^^^ expected `i64`, found `i128`
+   |         |
+   |         expected because this is `i64`
    |
 help: you can convert `x_i64` from `i64` to `i128`, matching the type of `x_i128`
    |
@@ -541,7 +639,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:133:17
    |
 LL |         x_i64 > x_isize;
-   |                 ^^^^^^^ expected `i64`, found `isize`
+   |         -----   ^^^^^^^ expected `i64`, found `isize`
+   |         |
+   |         expected because this is `i64`
    |
 help: you can convert an `isize` to an `i64` and panic if the converted value doesn't fit
    |
@@ -552,7 +652,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:136:18
    |
 LL |         x_i128 > x_i8;
-   |                  ^^^^ expected `i128`, found `i8`
+   |         ------   ^^^^ expected `i128`, found `i8`
+   |         |
+   |         expected because this is `i128`
    |
 help: you can convert an `i8` to an `i128`
    |
@@ -563,7 +665,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:138:18
    |
 LL |         x_i128 > x_i16;
-   |                  ^^^^^ expected `i128`, found `i16`
+   |         ------   ^^^^^ expected `i128`, found `i16`
+   |         |
+   |         expected because this is `i128`
    |
 help: you can convert an `i16` to an `i128`
    |
@@ -574,7 +678,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:140:18
    |
 LL |         x_i128 > x_i32;
-   |                  ^^^^^ expected `i128`, found `i32`
+   |         ------   ^^^^^ expected `i128`, found `i32`
+   |         |
+   |         expected because this is `i128`
    |
 help: you can convert an `i32` to an `i128`
    |
@@ -585,7 +691,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:142:18
    |
 LL |         x_i128 > x_i64;
-   |                  ^^^^^ expected `i128`, found `i64`
+   |         ------   ^^^^^ expected `i128`, found `i64`
+   |         |
+   |         expected because this is `i128`
    |
 help: you can convert an `i64` to an `i128`
    |
@@ -596,7 +704,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:144:18
    |
 LL |         x_i128 > x_isize;
-   |                  ^^^^^^^ expected `i128`, found `isize`
+   |         ------   ^^^^^^^ expected `i128`, found `isize`
+   |         |
+   |         expected because this is `i128`
    |
 help: you can convert an `isize` to an `i128` and panic if the converted value doesn't fit
    |
@@ -607,7 +717,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:147:19
    |
 LL |         x_isize > x_i8;
-   |                   ^^^^ expected `isize`, found `i8`
+   |         -------   ^^^^ expected `isize`, found `i8`
+   |         |
+   |         expected because this is `isize`
    |
 help: you can convert an `i8` to an `isize`
    |
@@ -618,7 +730,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:149:19
    |
 LL |         x_isize > x_i16;
-   |                   ^^^^^ expected `isize`, found `i16`
+   |         -------   ^^^^^ expected `isize`, found `i16`
+   |         |
+   |         expected because this is `isize`
    |
 help: you can convert an `i16` to an `isize`
    |
@@ -629,7 +743,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:151:19
    |
 LL |         x_isize > x_i32;
-   |                   ^^^^^ expected `isize`, found `i32`
+   |         -------   ^^^^^ expected `isize`, found `i32`
+   |         |
+   |         expected because this is `isize`
    |
 help: you can convert an `i32` to an `isize` and panic if the converted value doesn't fit
    |
@@ -640,7 +756,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:153:19
    |
 LL |         x_isize > x_i64;
-   |                   ^^^^^ expected `isize`, found `i64`
+   |         -------   ^^^^^ expected `isize`, found `i64`
+   |         |
+   |         expected because this is `isize`
    |
 help: you can convert an `i64` to an `isize` and panic if the converted value doesn't fit
    |
@@ -651,7 +769,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:155:19
    |
 LL |         x_isize > x_i128;
-   |                   ^^^^^^ expected `isize`, found `i128`
+   |         -------   ^^^^^^ expected `isize`, found `i128`
+   |         |
+   |         expected because this is `isize`
    |
 help: you can convert an `i128` to an `isize` and panic if the converted value doesn't fit
    |
@@ -662,7 +782,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:161:16
    |
 LL |         x_u8 > x_i8;
-   |                ^^^^ expected `u8`, found `i8`
+   |         ----   ^^^^ expected `u8`, found `i8`
+   |         |
+   |         expected because this is `u8`
    |
 help: you can convert an `i8` to a `u8` and panic if the converted value doesn't fit
    |
@@ -673,7 +795,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:163:16
    |
 LL |         x_u8 > x_i16;
-   |                ^^^^^ expected `u8`, found `i16`
+   |         ----   ^^^^^ expected `u8`, found `i16`
+   |         |
+   |         expected because this is `u8`
    |
 help: you can convert `x_u8` from `u8` to `i16`, matching the type of `x_i16`
    |
@@ -684,7 +808,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:165:16
    |
 LL |         x_u8 > x_i32;
-   |                ^^^^^ expected `u8`, found `i32`
+   |         ----   ^^^^^ expected `u8`, found `i32`
+   |         |
+   |         expected because this is `u8`
    |
 help: you can convert `x_u8` from `u8` to `i32`, matching the type of `x_i32`
    |
@@ -695,7 +821,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:167:16
    |
 LL |         x_u8 > x_i64;
-   |                ^^^^^ expected `u8`, found `i64`
+   |         ----   ^^^^^ expected `u8`, found `i64`
+   |         |
+   |         expected because this is `u8`
    |
 help: you can convert `x_u8` from `u8` to `i64`, matching the type of `x_i64`
    |
@@ -706,7 +834,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:169:16
    |
 LL |         x_u8 > x_i128;
-   |                ^^^^^^ expected `u8`, found `i128`
+   |         ----   ^^^^^^ expected `u8`, found `i128`
+   |         |
+   |         expected because this is `u8`
    |
 help: you can convert `x_u8` from `u8` to `i128`, matching the type of `x_i128`
    |
@@ -717,7 +847,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:171:16
    |
 LL |         x_u8 > x_isize;
-   |                ^^^^^^^ expected `u8`, found `isize`
+   |         ----   ^^^^^^^ expected `u8`, found `isize`
+   |         |
+   |         expected because this is `u8`
    |
 help: you can convert `x_u8` from `u8` to `isize`, matching the type of `x_isize`
    |
@@ -728,7 +860,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:174:17
    |
 LL |         x_u16 > x_i8;
-   |                 ^^^^ expected `u16`, found `i8`
+   |         -----   ^^^^ expected `u16`, found `i8`
+   |         |
+   |         expected because this is `u16`
    |
 help: you can convert an `i8` to a `u16` and panic if the converted value doesn't fit
    |
@@ -739,7 +873,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:176:17
    |
 LL |         x_u16 > x_i16;
-   |                 ^^^^^ expected `u16`, found `i16`
+   |         -----   ^^^^^ expected `u16`, found `i16`
+   |         |
+   |         expected because this is `u16`
    |
 help: you can convert an `i16` to a `u16` and panic if the converted value doesn't fit
    |
@@ -750,7 +886,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:178:17
    |
 LL |         x_u16 > x_i32;
-   |                 ^^^^^ expected `u16`, found `i32`
+   |         -----   ^^^^^ expected `u16`, found `i32`
+   |         |
+   |         expected because this is `u16`
    |
 help: you can convert `x_u16` from `u16` to `i32`, matching the type of `x_i32`
    |
@@ -761,7 +899,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:180:17
    |
 LL |         x_u16 > x_i64;
-   |                 ^^^^^ expected `u16`, found `i64`
+   |         -----   ^^^^^ expected `u16`, found `i64`
+   |         |
+   |         expected because this is `u16`
    |
 help: you can convert `x_u16` from `u16` to `i64`, matching the type of `x_i64`
    |
@@ -772,7 +912,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:182:17
    |
 LL |         x_u16 > x_i128;
-   |                 ^^^^^^ expected `u16`, found `i128`
+   |         -----   ^^^^^^ expected `u16`, found `i128`
+   |         |
+   |         expected because this is `u16`
    |
 help: you can convert `x_u16` from `u16` to `i128`, matching the type of `x_i128`
    |
@@ -783,7 +925,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:184:17
    |
 LL |         x_u16 > x_isize;
-   |                 ^^^^^^^ expected `u16`, found `isize`
+   |         -----   ^^^^^^^ expected `u16`, found `isize`
+   |         |
+   |         expected because this is `u16`
    |
 help: you can convert an `isize` to a `u16` and panic if the converted value doesn't fit
    |
@@ -794,7 +938,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:187:17
    |
 LL |         x_u32 > x_i8;
-   |                 ^^^^ expected `u32`, found `i8`
+   |         -----   ^^^^ expected `u32`, found `i8`
+   |         |
+   |         expected because this is `u32`
    |
 help: you can convert an `i8` to a `u32` and panic if the converted value doesn't fit
    |
@@ -805,7 +951,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:189:17
    |
 LL |         x_u32 > x_i16;
-   |                 ^^^^^ expected `u32`, found `i16`
+   |         -----   ^^^^^ expected `u32`, found `i16`
+   |         |
+   |         expected because this is `u32`
    |
 help: you can convert an `i16` to a `u32` and panic if the converted value doesn't fit
    |
@@ -816,7 +964,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:191:17
    |
 LL |         x_u32 > x_i32;
-   |                 ^^^^^ expected `u32`, found `i32`
+   |         -----   ^^^^^ expected `u32`, found `i32`
+   |         |
+   |         expected because this is `u32`
    |
 help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit
    |
@@ -827,7 +977,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:193:17
    |
 LL |         x_u32 > x_i64;
-   |                 ^^^^^ expected `u32`, found `i64`
+   |         -----   ^^^^^ expected `u32`, found `i64`
+   |         |
+   |         expected because this is `u32`
    |
 help: you can convert `x_u32` from `u32` to `i64`, matching the type of `x_i64`
    |
@@ -838,7 +990,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:195:17
    |
 LL |         x_u32 > x_i128;
-   |                 ^^^^^^ expected `u32`, found `i128`
+   |         -----   ^^^^^^ expected `u32`, found `i128`
+   |         |
+   |         expected because this is `u32`
    |
 help: you can convert `x_u32` from `u32` to `i128`, matching the type of `x_i128`
    |
@@ -849,7 +1003,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:197:17
    |
 LL |         x_u32 > x_isize;
-   |                 ^^^^^^^ expected `u32`, found `isize`
+   |         -----   ^^^^^^^ expected `u32`, found `isize`
+   |         |
+   |         expected because this is `u32`
    |
 help: you can convert an `isize` to a `u32` and panic if the converted value doesn't fit
    |
@@ -860,7 +1016,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:200:17
    |
 LL |         x_u64 > x_i8;
-   |                 ^^^^ expected `u64`, found `i8`
+   |         -----   ^^^^ expected `u64`, found `i8`
+   |         |
+   |         expected because this is `u64`
    |
 help: you can convert an `i8` to a `u64` and panic if the converted value doesn't fit
    |
@@ -871,7 +1029,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:202:17
    |
 LL |         x_u64 > x_i16;
-   |                 ^^^^^ expected `u64`, found `i16`
+   |         -----   ^^^^^ expected `u64`, found `i16`
+   |         |
+   |         expected because this is `u64`
    |
 help: you can convert an `i16` to a `u64` and panic if the converted value doesn't fit
    |
@@ -882,7 +1042,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:204:17
    |
 LL |         x_u64 > x_i32;
-   |                 ^^^^^ expected `u64`, found `i32`
+   |         -----   ^^^^^ expected `u64`, found `i32`
+   |         |
+   |         expected because this is `u64`
    |
 help: you can convert an `i32` to a `u64` and panic if the converted value doesn't fit
    |
@@ -893,7 +1055,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:206:17
    |
 LL |         x_u64 > x_i64;
-   |                 ^^^^^ expected `u64`, found `i64`
+   |         -----   ^^^^^ expected `u64`, found `i64`
+   |         |
+   |         expected because this is `u64`
    |
 help: you can convert an `i64` to a `u64` and panic if the converted value doesn't fit
    |
@@ -904,7 +1068,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:208:17
    |
 LL |         x_u64 > x_i128;
-   |                 ^^^^^^ expected `u64`, found `i128`
+   |         -----   ^^^^^^ expected `u64`, found `i128`
+   |         |
+   |         expected because this is `u64`
    |
 help: you can convert `x_u64` from `u64` to `i128`, matching the type of `x_i128`
    |
@@ -915,7 +1081,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:210:17
    |
 LL |         x_u64 > x_isize;
-   |                 ^^^^^^^ expected `u64`, found `isize`
+   |         -----   ^^^^^^^ expected `u64`, found `isize`
+   |         |
+   |         expected because this is `u64`
    |
 help: you can convert an `isize` to a `u64` and panic if the converted value doesn't fit
    |
@@ -926,7 +1094,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:213:18
    |
 LL |         x_u128 > x_i8;
-   |                  ^^^^ expected `u128`, found `i8`
+   |         ------   ^^^^ expected `u128`, found `i8`
+   |         |
+   |         expected because this is `u128`
    |
 help: you can convert an `i8` to a `u128` and panic if the converted value doesn't fit
    |
@@ -937,7 +1107,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:215:18
    |
 LL |         x_u128 > x_i16;
-   |                  ^^^^^ expected `u128`, found `i16`
+   |         ------   ^^^^^ expected `u128`, found `i16`
+   |         |
+   |         expected because this is `u128`
    |
 help: you can convert an `i16` to a `u128` and panic if the converted value doesn't fit
    |
@@ -948,7 +1120,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:217:18
    |
 LL |         x_u128 > x_i32;
-   |                  ^^^^^ expected `u128`, found `i32`
+   |         ------   ^^^^^ expected `u128`, found `i32`
+   |         |
+   |         expected because this is `u128`
    |
 help: you can convert an `i32` to a `u128` and panic if the converted value doesn't fit
    |
@@ -959,7 +1133,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:219:18
    |
 LL |         x_u128 > x_i64;
-   |                  ^^^^^ expected `u128`, found `i64`
+   |         ------   ^^^^^ expected `u128`, found `i64`
+   |         |
+   |         expected because this is `u128`
    |
 help: you can convert an `i64` to a `u128` and panic if the converted value doesn't fit
    |
@@ -970,7 +1146,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:221:18
    |
 LL |         x_u128 > x_i128;
-   |                  ^^^^^^ expected `u128`, found `i128`
+   |         ------   ^^^^^^ expected `u128`, found `i128`
+   |         |
+   |         expected because this is `u128`
    |
 help: you can convert an `i128` to a `u128` and panic if the converted value doesn't fit
    |
@@ -981,7 +1159,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:223:18
    |
 LL |         x_u128 > x_isize;
-   |                  ^^^^^^^ expected `u128`, found `isize`
+   |         ------   ^^^^^^^ expected `u128`, found `isize`
+   |         |
+   |         expected because this is `u128`
    |
 help: you can convert an `isize` to a `u128` and panic if the converted value doesn't fit
    |
@@ -992,7 +1172,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:226:19
    |
 LL |         x_usize > x_i8;
-   |                   ^^^^ expected `usize`, found `i8`
+   |         -------   ^^^^ expected `usize`, found `i8`
+   |         |
+   |         expected because this is `usize`
    |
 help: you can convert an `i8` to a `usize` and panic if the converted value doesn't fit
    |
@@ -1003,7 +1185,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:228:19
    |
 LL |         x_usize > x_i16;
-   |                   ^^^^^ expected `usize`, found `i16`
+   |         -------   ^^^^^ expected `usize`, found `i16`
+   |         |
+   |         expected because this is `usize`
    |
 help: you can convert an `i16` to a `usize` and panic if the converted value doesn't fit
    |
@@ -1014,7 +1198,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:230:19
    |
 LL |         x_usize > x_i32;
-   |                   ^^^^^ expected `usize`, found `i32`
+   |         -------   ^^^^^ expected `usize`, found `i32`
+   |         |
+   |         expected because this is `usize`
    |
 help: you can convert an `i32` to a `usize` and panic if the converted value doesn't fit
    |
@@ -1025,7 +1211,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:232:19
    |
 LL |         x_usize > x_i64;
-   |                   ^^^^^ expected `usize`, found `i64`
+   |         -------   ^^^^^ expected `usize`, found `i64`
+   |         |
+   |         expected because this is `usize`
    |
 help: you can convert an `i64` to a `usize` and panic if the converted value doesn't fit
    |
@@ -1036,7 +1224,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:234:19
    |
 LL |         x_usize > x_i128;
-   |                   ^^^^^^ expected `usize`, found `i128`
+   |         -------   ^^^^^^ expected `usize`, found `i128`
+   |         |
+   |         expected because this is `usize`
    |
 help: you can convert an `i128` to a `usize` and panic if the converted value doesn't fit
    |
@@ -1047,7 +1237,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:236:19
    |
 LL |         x_usize > x_isize;
-   |                   ^^^^^^^ expected `usize`, found `isize`
+   |         -------   ^^^^^^^ expected `usize`, found `isize`
+   |         |
+   |         expected because this is `usize`
    |
 help: you can convert an `isize` to a `usize` and panic if the converted value doesn't fit
    |
@@ -1058,7 +1250,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:242:16
    |
 LL |         x_i8 > x_u8;
-   |                ^^^^ expected `i8`, found `u8`
+   |         ----   ^^^^ expected `i8`, found `u8`
+   |         |
+   |         expected because this is `i8`
    |
 help: you can convert a `u8` to an `i8` and panic if the converted value doesn't fit
    |
@@ -1069,7 +1263,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:244:16
    |
 LL |         x_i8 > x_u16;
-   |                ^^^^^ expected `i8`, found `u16`
+   |         ----   ^^^^^ expected `i8`, found `u16`
+   |         |
+   |         expected because this is `i8`
    |
 help: you can convert a `u16` to an `i8` and panic if the converted value doesn't fit
    |
@@ -1080,7 +1276,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:246:16
    |
 LL |         x_i8 > x_u32;
-   |                ^^^^^ expected `i8`, found `u32`
+   |         ----   ^^^^^ expected `i8`, found `u32`
+   |         |
+   |         expected because this is `i8`
    |
 help: you can convert a `u32` to an `i8` and panic if the converted value doesn't fit
    |
@@ -1091,7 +1289,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:248:16
    |
 LL |         x_i8 > x_u64;
-   |                ^^^^^ expected `i8`, found `u64`
+   |         ----   ^^^^^ expected `i8`, found `u64`
+   |         |
+   |         expected because this is `i8`
    |
 help: you can convert a `u64` to an `i8` and panic if the converted value doesn't fit
    |
@@ -1102,7 +1302,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:250:16
    |
 LL |         x_i8 > x_u128;
-   |                ^^^^^^ expected `i8`, found `u128`
+   |         ----   ^^^^^^ expected `i8`, found `u128`
+   |         |
+   |         expected because this is `i8`
    |
 help: you can convert a `u128` to an `i8` and panic if the converted value doesn't fit
    |
@@ -1113,7 +1315,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:252:16
    |
 LL |         x_i8 > x_usize;
-   |                ^^^^^^^ expected `i8`, found `usize`
+   |         ----   ^^^^^^^ expected `i8`, found `usize`
+   |         |
+   |         expected because this is `i8`
    |
 help: you can convert a `usize` to an `i8` and panic if the converted value doesn't fit
    |
@@ -1124,7 +1328,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:255:17
    |
 LL |         x_i16 > x_u8;
-   |                 ^^^^ expected `i16`, found `u8`
+   |         -----   ^^^^ expected `i16`, found `u8`
+   |         |
+   |         expected because this is `i16`
    |
 help: you can convert a `u8` to an `i16`
    |
@@ -1135,7 +1341,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:257:17
    |
 LL |         x_i16 > x_u16;
-   |                 ^^^^^ expected `i16`, found `u16`
+   |         -----   ^^^^^ expected `i16`, found `u16`
+   |         |
+   |         expected because this is `i16`
    |
 help: you can convert a `u16` to an `i16` and panic if the converted value doesn't fit
    |
@@ -1146,7 +1354,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:259:17
    |
 LL |         x_i16 > x_u32;
-   |                 ^^^^^ expected `i16`, found `u32`
+   |         -----   ^^^^^ expected `i16`, found `u32`
+   |         |
+   |         expected because this is `i16`
    |
 help: you can convert a `u32` to an `i16` and panic if the converted value doesn't fit
    |
@@ -1157,7 +1367,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:261:17
    |
 LL |         x_i16 > x_u64;
-   |                 ^^^^^ expected `i16`, found `u64`
+   |         -----   ^^^^^ expected `i16`, found `u64`
+   |         |
+   |         expected because this is `i16`
    |
 help: you can convert a `u64` to an `i16` and panic if the converted value doesn't fit
    |
@@ -1168,7 +1380,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:263:17
    |
 LL |         x_i16 > x_u128;
-   |                 ^^^^^^ expected `i16`, found `u128`
+   |         -----   ^^^^^^ expected `i16`, found `u128`
+   |         |
+   |         expected because this is `i16`
    |
 help: you can convert a `u128` to an `i16` and panic if the converted value doesn't fit
    |
@@ -1179,7 +1393,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:265:17
    |
 LL |         x_i16 > x_usize;
-   |                 ^^^^^^^ expected `i16`, found `usize`
+   |         -----   ^^^^^^^ expected `i16`, found `usize`
+   |         |
+   |         expected because this is `i16`
    |
 help: you can convert a `usize` to an `i16` and panic if the converted value doesn't fit
    |
@@ -1190,7 +1406,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:268:17
    |
 LL |         x_i32 > x_u8;
-   |                 ^^^^ expected `i32`, found `u8`
+   |         -----   ^^^^ expected `i32`, found `u8`
+   |         |
+   |         expected because this is `i32`
    |
 help: you can convert a `u8` to an `i32`
    |
@@ -1201,7 +1419,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:270:17
    |
 LL |         x_i32 > x_u16;
-   |                 ^^^^^ expected `i32`, found `u16`
+   |         -----   ^^^^^ expected `i32`, found `u16`
+   |         |
+   |         expected because this is `i32`
    |
 help: you can convert a `u16` to an `i32`
    |
@@ -1212,7 +1432,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:272:17
    |
 LL |         x_i32 > x_u32;
-   |                 ^^^^^ expected `i32`, found `u32`
+   |         -----   ^^^^^ expected `i32`, found `u32`
+   |         |
+   |         expected because this is `i32`
    |
 help: you can convert a `u32` to an `i32` and panic if the converted value doesn't fit
    |
@@ -1223,7 +1445,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:274:17
    |
 LL |         x_i32 > x_u64;
-   |                 ^^^^^ expected `i32`, found `u64`
+   |         -----   ^^^^^ expected `i32`, found `u64`
+   |         |
+   |         expected because this is `i32`
    |
 help: you can convert a `u64` to an `i32` and panic if the converted value doesn't fit
    |
@@ -1234,7 +1458,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:276:17
    |
 LL |         x_i32 > x_u128;
-   |                 ^^^^^^ expected `i32`, found `u128`
+   |         -----   ^^^^^^ expected `i32`, found `u128`
+   |         |
+   |         expected because this is `i32`
    |
 help: you can convert a `u128` to an `i32` and panic if the converted value doesn't fit
    |
@@ -1245,7 +1471,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:278:17
    |
 LL |         x_i32 > x_usize;
-   |                 ^^^^^^^ expected `i32`, found `usize`
+   |         -----   ^^^^^^^ expected `i32`, found `usize`
+   |         |
+   |         expected because this is `i32`
    |
 help: you can convert a `usize` to an `i32` and panic if the converted value doesn't fit
    |
@@ -1256,7 +1484,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:281:17
    |
 LL |         x_i64 > x_u8;
-   |                 ^^^^ expected `i64`, found `u8`
+   |         -----   ^^^^ expected `i64`, found `u8`
+   |         |
+   |         expected because this is `i64`
    |
 help: you can convert a `u8` to an `i64`
    |
@@ -1267,7 +1497,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:283:17
    |
 LL |         x_i64 > x_u16;
-   |                 ^^^^^ expected `i64`, found `u16`
+   |         -----   ^^^^^ expected `i64`, found `u16`
+   |         |
+   |         expected because this is `i64`
    |
 help: you can convert a `u16` to an `i64`
    |
@@ -1278,7 +1510,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:285:17
    |
 LL |         x_i64 > x_u32;
-   |                 ^^^^^ expected `i64`, found `u32`
+   |         -----   ^^^^^ expected `i64`, found `u32`
+   |         |
+   |         expected because this is `i64`
    |
 help: you can convert a `u32` to an `i64`
    |
@@ -1289,7 +1523,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:287:17
    |
 LL |         x_i64 > x_u64;
-   |                 ^^^^^ expected `i64`, found `u64`
+   |         -----   ^^^^^ expected `i64`, found `u64`
+   |         |
+   |         expected because this is `i64`
    |
 help: you can convert a `u64` to an `i64` and panic if the converted value doesn't fit
    |
@@ -1300,7 +1536,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:289:17
    |
 LL |         x_i64 > x_u128;
-   |                 ^^^^^^ expected `i64`, found `u128`
+   |         -----   ^^^^^^ expected `i64`, found `u128`
+   |         |
+   |         expected because this is `i64`
    |
 help: you can convert a `u128` to an `i64` and panic if the converted value doesn't fit
    |
@@ -1311,7 +1549,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:291:17
    |
 LL |         x_i64 > x_usize;
-   |                 ^^^^^^^ expected `i64`, found `usize`
+   |         -----   ^^^^^^^ expected `i64`, found `usize`
+   |         |
+   |         expected because this is `i64`
    |
 help: you can convert a `usize` to an `i64` and panic if the converted value doesn't fit
    |
@@ -1322,7 +1562,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:294:18
    |
 LL |         x_i128 > x_u8;
-   |                  ^^^^ expected `i128`, found `u8`
+   |         ------   ^^^^ expected `i128`, found `u8`
+   |         |
+   |         expected because this is `i128`
    |
 help: you can convert a `u8` to an `i128`
    |
@@ -1333,7 +1575,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:296:18
    |
 LL |         x_i128 > x_u16;
-   |                  ^^^^^ expected `i128`, found `u16`
+   |         ------   ^^^^^ expected `i128`, found `u16`
+   |         |
+   |         expected because this is `i128`
    |
 help: you can convert a `u16` to an `i128`
    |
@@ -1344,7 +1588,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:298:18
    |
 LL |         x_i128 > x_u32;
-   |                  ^^^^^ expected `i128`, found `u32`
+   |         ------   ^^^^^ expected `i128`, found `u32`
+   |         |
+   |         expected because this is `i128`
    |
 help: you can convert a `u32` to an `i128`
    |
@@ -1355,7 +1601,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:300:18
    |
 LL |         x_i128 > x_u64;
-   |                  ^^^^^ expected `i128`, found `u64`
+   |         ------   ^^^^^ expected `i128`, found `u64`
+   |         |
+   |         expected because this is `i128`
    |
 help: you can convert a `u64` to an `i128`
    |
@@ -1366,7 +1614,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:302:18
    |
 LL |         x_i128 > x_u128;
-   |                  ^^^^^^ expected `i128`, found `u128`
+   |         ------   ^^^^^^ expected `i128`, found `u128`
+   |         |
+   |         expected because this is `i128`
    |
 help: you can convert a `u128` to an `i128` and panic if the converted value doesn't fit
    |
@@ -1377,7 +1627,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:304:18
    |
 LL |         x_i128 > x_usize;
-   |                  ^^^^^^^ expected `i128`, found `usize`
+   |         ------   ^^^^^^^ expected `i128`, found `usize`
+   |         |
+   |         expected because this is `i128`
    |
 help: you can convert a `usize` to an `i128` and panic if the converted value doesn't fit
    |
@@ -1388,7 +1640,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:307:19
    |
 LL |         x_isize > x_u8;
-   |                   ^^^^ expected `isize`, found `u8`
+   |         -------   ^^^^ expected `isize`, found `u8`
+   |         |
+   |         expected because this is `isize`
    |
 help: you can convert a `u8` to an `isize`
    |
@@ -1399,7 +1653,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:309:19
    |
 LL |         x_isize > x_u16;
-   |                   ^^^^^ expected `isize`, found `u16`
+   |         -------   ^^^^^ expected `isize`, found `u16`
+   |         |
+   |         expected because this is `isize`
    |
 help: you can convert a `u16` to an `isize` and panic if the converted value doesn't fit
    |
@@ -1410,7 +1666,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:311:19
    |
 LL |         x_isize > x_u32;
-   |                   ^^^^^ expected `isize`, found `u32`
+   |         -------   ^^^^^ expected `isize`, found `u32`
+   |         |
+   |         expected because this is `isize`
    |
 help: you can convert a `u32` to an `isize` and panic if the converted value doesn't fit
    |
@@ -1421,7 +1679,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:313:19
    |
 LL |         x_isize > x_u64;
-   |                   ^^^^^ expected `isize`, found `u64`
+   |         -------   ^^^^^ expected `isize`, found `u64`
+   |         |
+   |         expected because this is `isize`
    |
 help: you can convert a `u64` to an `isize` and panic if the converted value doesn't fit
    |
@@ -1432,7 +1692,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:315:19
    |
 LL |         x_isize > x_u128;
-   |                   ^^^^^^ expected `isize`, found `u128`
+   |         -------   ^^^^^^ expected `isize`, found `u128`
+   |         |
+   |         expected because this is `isize`
    |
 help: you can convert a `u128` to an `isize` and panic if the converted value doesn't fit
    |
@@ -1443,7 +1705,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:317:19
    |
 LL |         x_isize > x_usize;
-   |                   ^^^^^^^ expected `isize`, found `usize`
+   |         -------   ^^^^^^^ expected `isize`, found `usize`
+   |         |
+   |         expected because this is `isize`
    |
 help: you can convert a `usize` to an `isize` and panic if the converted value doesn't fit
    |
index e4843206de1dd48c2025a796c22552b2f612a79a..c244e479d24c6b00493db40c33639faf29f2a137 100644 (file)
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:10:15
    |
 LL |     x_usize > -1_isize;
-   |               ^^^^^^^^ expected `usize`, found `isize`
+   |     -------   ^^^^^^^^ expected `usize`, found `isize`
+   |     |
+   |     expected because this is `usize`
    |
    = note: `-1_isize` cannot fit into type `usize`
 
@@ -10,7 +12,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:12:14
    |
 LL |     x_u128 > -1_isize;
-   |              ^^^^^^^^ expected `u128`, found `isize`
+   |     ------   ^^^^^^^^ expected `u128`, found `isize`
+   |     |
+   |     expected because this is `u128`
    |
    = note: `-1_isize` cannot fit into type `u128`
 
@@ -18,7 +22,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:14:13
    |
 LL |     x_u64 > -1_isize;
-   |             ^^^^^^^^ expected `u64`, found `isize`
+   |     -----   ^^^^^^^^ expected `u64`, found `isize`
+   |     |
+   |     expected because this is `u64`
    |
    = note: `-1_isize` cannot fit into type `u64`
 
@@ -26,7 +32,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:16:13
    |
 LL |     x_u32 > -1_isize;
-   |             ^^^^^^^^ expected `u32`, found `isize`
+   |     -----   ^^^^^^^^ expected `u32`, found `isize`
+   |     |
+   |     expected because this is `u32`
    |
    = note: `-1_isize` cannot fit into type `u32`
 
@@ -34,7 +42,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:18:13
    |
 LL |     x_u16 > -1_isize;
-   |             ^^^^^^^^ expected `u16`, found `isize`
+   |     -----   ^^^^^^^^ expected `u16`, found `isize`
+   |     |
+   |     expected because this is `u16`
    |
    = note: `-1_isize` cannot fit into type `u16`
 
@@ -42,7 +52,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:20:12
    |
 LL |     x_u8 > -1_isize;
-   |            ^^^^^^^^ expected `u8`, found `isize`
+   |     ----   ^^^^^^^^ expected `u8`, found `isize`
+   |     |
+   |     expected because this is `u8`
    |
 help: you can convert `x_u8` from `u8` to `isize`, matching the type of `-1_isize`
    |
@@ -53,7 +65,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:23:15
    |
 LL |     x_usize > -1_i128;
-   |               ^^^^^^^ expected `usize`, found `i128`
+   |     -------   ^^^^^^^ expected `usize`, found `i128`
+   |     |
+   |     expected because this is `usize`
    |
    = note: `-1_i128` cannot fit into type `usize`
 
@@ -61,7 +75,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:25:14
    |
 LL |     x_u128 > -1_i128;
-   |              ^^^^^^^ expected `u128`, found `i128`
+   |     ------   ^^^^^^^ expected `u128`, found `i128`
+   |     |
+   |     expected because this is `u128`
    |
    = note: `-1_i128` cannot fit into type `u128`
 
@@ -69,7 +85,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:27:13
    |
 LL |     x_u64 > -1_i128;
-   |             ^^^^^^^ expected `u64`, found `i128`
+   |     -----   ^^^^^^^ expected `u64`, found `i128`
+   |     |
+   |     expected because this is `u64`
    |
 help: you can convert `x_u64` from `u64` to `i128`, matching the type of `-1_i128`
    |
@@ -80,7 +98,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:29:13
    |
 LL |     x_u32 > -1_i128;
-   |             ^^^^^^^ expected `u32`, found `i128`
+   |     -----   ^^^^^^^ expected `u32`, found `i128`
+   |     |
+   |     expected because this is `u32`
    |
 help: you can convert `x_u32` from `u32` to `i128`, matching the type of `-1_i128`
    |
@@ -91,7 +111,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:31:13
    |
 LL |     x_u16 > -1_i128;
-   |             ^^^^^^^ expected `u16`, found `i128`
+   |     -----   ^^^^^^^ expected `u16`, found `i128`
+   |     |
+   |     expected because this is `u16`
    |
 help: you can convert `x_u16` from `u16` to `i128`, matching the type of `-1_i128`
    |
@@ -102,7 +124,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:33:12
    |
 LL |     x_u8 > -1_i128;
-   |            ^^^^^^^ expected `u8`, found `i128`
+   |     ----   ^^^^^^^ expected `u8`, found `i128`
+   |     |
+   |     expected because this is `u8`
    |
 help: you can convert `x_u8` from `u8` to `i128`, matching the type of `-1_i128`
    |
@@ -113,7 +137,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:36:15
    |
 LL |     x_usize > -1_i64;
-   |               ^^^^^^ expected `usize`, found `i64`
+   |     -------   ^^^^^^ expected `usize`, found `i64`
+   |     |
+   |     expected because this is `usize`
    |
    = note: `-1_i64` cannot fit into type `usize`
 
@@ -121,7 +147,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:38:14
    |
 LL |     x_u128 > -1_i64;
-   |              ^^^^^^ expected `u128`, found `i64`
+   |     ------   ^^^^^^ expected `u128`, found `i64`
+   |     |
+   |     expected because this is `u128`
    |
    = note: `-1_i64` cannot fit into type `u128`
 
@@ -129,7 +157,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:40:13
    |
 LL |     x_u64 > -1_i64;
-   |             ^^^^^^ expected `u64`, found `i64`
+   |     -----   ^^^^^^ expected `u64`, found `i64`
+   |     |
+   |     expected because this is `u64`
    |
    = note: `-1_i64` cannot fit into type `u64`
 
@@ -137,7 +167,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:42:13
    |
 LL |     x_u32 > -1_i64;
-   |             ^^^^^^ expected `u32`, found `i64`
+   |     -----   ^^^^^^ expected `u32`, found `i64`
+   |     |
+   |     expected because this is `u32`
    |
 help: you can convert `x_u32` from `u32` to `i64`, matching the type of `-1_i64`
    |
@@ -148,7 +180,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:44:13
    |
 LL |     x_u16 > -1_i64;
-   |             ^^^^^^ expected `u16`, found `i64`
+   |     -----   ^^^^^^ expected `u16`, found `i64`
+   |     |
+   |     expected because this is `u16`
    |
 help: you can convert `x_u16` from `u16` to `i64`, matching the type of `-1_i64`
    |
@@ -159,7 +193,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:46:12
    |
 LL |     x_u8 > -1_i64;
-   |            ^^^^^^ expected `u8`, found `i64`
+   |     ----   ^^^^^^ expected `u8`, found `i64`
+   |     |
+   |     expected because this is `u8`
    |
 help: you can convert `x_u8` from `u8` to `i64`, matching the type of `-1_i64`
    |
@@ -170,7 +206,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:49:15
    |
 LL |     x_usize > -1_i32;
-   |               ^^^^^^ expected `usize`, found `i32`
+   |     -------   ^^^^^^ expected `usize`, found `i32`
+   |     |
+   |     expected because this is `usize`
    |
    = note: `-1_i32` cannot fit into type `usize`
 
@@ -178,7 +216,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:51:14
    |
 LL |     x_u128 > -1_i32;
-   |              ^^^^^^ expected `u128`, found `i32`
+   |     ------   ^^^^^^ expected `u128`, found `i32`
+   |     |
+   |     expected because this is `u128`
    |
    = note: `-1_i32` cannot fit into type `u128`
 
@@ -186,7 +226,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:53:13
    |
 LL |     x_u64 > -1_i32;
-   |             ^^^^^^ expected `u64`, found `i32`
+   |     -----   ^^^^^^ expected `u64`, found `i32`
+   |     |
+   |     expected because this is `u64`
    |
    = note: `-1_i32` cannot fit into type `u64`
 
@@ -194,7 +236,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:55:13
    |
 LL |     x_u32 > -1_i32;
-   |             ^^^^^^ expected `u32`, found `i32`
+   |     -----   ^^^^^^ expected `u32`, found `i32`
+   |     |
+   |     expected because this is `u32`
    |
    = note: `-1_i32` cannot fit into type `u32`
 
@@ -202,7 +246,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:57:13
    |
 LL |     x_u16 > -1_i32;
-   |             ^^^^^^ expected `u16`, found `i32`
+   |     -----   ^^^^^^ expected `u16`, found `i32`
+   |     |
+   |     expected because this is `u16`
    |
 help: you can convert `x_u16` from `u16` to `i32`, matching the type of `-1_i32`
    |
@@ -213,7 +259,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:59:12
    |
 LL |     x_u8 > -1_i32;
-   |            ^^^^^^ expected `u8`, found `i32`
+   |     ----   ^^^^^^ expected `u8`, found `i32`
+   |     |
+   |     expected because this is `u8`
    |
 help: you can convert `x_u8` from `u8` to `i32`, matching the type of `-1_i32`
    |
@@ -224,7 +272,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:62:15
    |
 LL |     x_usize > -1_i16;
-   |               ^^^^^^ expected `usize`, found `i16`
+   |     -------   ^^^^^^ expected `usize`, found `i16`
+   |     |
+   |     expected because this is `usize`
    |
    = note: `-1_i16` cannot fit into type `usize`
 
@@ -232,7 +282,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:64:14
    |
 LL |     x_u128 > -1_i16;
-   |              ^^^^^^ expected `u128`, found `i16`
+   |     ------   ^^^^^^ expected `u128`, found `i16`
+   |     |
+   |     expected because this is `u128`
    |
    = note: `-1_i16` cannot fit into type `u128`
 
@@ -240,7 +292,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:66:13
    |
 LL |     x_u64 > -1_i16;
-   |             ^^^^^^ expected `u64`, found `i16`
+   |     -----   ^^^^^^ expected `u64`, found `i16`
+   |     |
+   |     expected because this is `u64`
    |
    = note: `-1_i16` cannot fit into type `u64`
 
@@ -248,7 +302,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:68:13
    |
 LL |     x_u32 > -1_i16;
-   |             ^^^^^^ expected `u32`, found `i16`
+   |     -----   ^^^^^^ expected `u32`, found `i16`
+   |     |
+   |     expected because this is `u32`
    |
    = note: `-1_i16` cannot fit into type `u32`
 
@@ -256,7 +312,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:70:13
    |
 LL |     x_u16 > -1_i16;
-   |             ^^^^^^ expected `u16`, found `i16`
+   |     -----   ^^^^^^ expected `u16`, found `i16`
+   |     |
+   |     expected because this is `u16`
    |
    = note: `-1_i16` cannot fit into type `u16`
 
@@ -264,7 +322,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:72:12
    |
 LL |     x_u8 > -1_i16;
-   |            ^^^^^^ expected `u8`, found `i16`
+   |     ----   ^^^^^^ expected `u8`, found `i16`
+   |     |
+   |     expected because this is `u8`
    |
 help: you can convert `x_u8` from `u8` to `i16`, matching the type of `-1_i16`
    |
@@ -275,7 +335,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:75:15
    |
 LL |     x_usize > -1_i8;
-   |               ^^^^^ expected `usize`, found `i8`
+   |     -------   ^^^^^ expected `usize`, found `i8`
+   |     |
+   |     expected because this is `usize`
    |
    = note: `-1_i8` cannot fit into type `usize`
 
@@ -283,7 +345,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:77:14
    |
 LL |     x_u128 > -1_i8;
-   |              ^^^^^ expected `u128`, found `i8`
+   |     ------   ^^^^^ expected `u128`, found `i8`
+   |     |
+   |     expected because this is `u128`
    |
    = note: `-1_i8` cannot fit into type `u128`
 
@@ -291,7 +355,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:79:13
    |
 LL |     x_u64 > -1_i8;
-   |             ^^^^^ expected `u64`, found `i8`
+   |     -----   ^^^^^ expected `u64`, found `i8`
+   |     |
+   |     expected because this is `u64`
    |
    = note: `-1_i8` cannot fit into type `u64`
 
@@ -299,7 +365,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:81:13
    |
 LL |     x_u32 > -1_i8;
-   |             ^^^^^ expected `u32`, found `i8`
+   |     -----   ^^^^^ expected `u32`, found `i8`
+   |     |
+   |     expected because this is `u32`
    |
    = note: `-1_i8` cannot fit into type `u32`
 
@@ -307,7 +375,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:83:13
    |
 LL |     x_u16 > -1_i8;
-   |             ^^^^^ expected `u16`, found `i8`
+   |     -----   ^^^^^ expected `u16`, found `i8`
+   |     |
+   |     expected because this is `u16`
    |
    = note: `-1_i8` cannot fit into type `u16`
 
@@ -315,7 +385,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:85:12
    |
 LL |     x_u8 > -1_i8;
-   |            ^^^^^ expected `u8`, found `i8`
+   |     ----   ^^^^^ expected `u8`, found `i8`
+   |     |
+   |     expected because this is `u8`
    |
    = note: `-1_i8` cannot fit into type `u8`
 
diff --git a/src/test/ui/numeric/uppercase-base-prefix-invalid-no-fix.rs b/src/test/ui/numeric/uppercase-base-prefix-invalid-no-fix.rs
new file mode 100644 (file)
index 0000000..f00cde4
--- /dev/null
@@ -0,0 +1,34 @@
+// Checks that integers with seeming uppercase base prefixes do not get bogus capitalization
+// suggestions.
+
+fn main() {
+    _ = 123X1a3;
+    //~^ ERROR invalid suffix `X1a3` for number literal
+    //~| NOTE invalid suffix `X1a3`
+    //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+    _ = 456O123;
+    //~^ ERROR invalid suffix `O123` for number literal
+    //~| NOTE invalid suffix `O123`
+    //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+    _ = 789B101;
+    //~^ ERROR invalid suffix `B101` for number literal
+    //~| NOTE invalid suffix `B101`
+    //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+    _ = 0XYZ;
+    //~^ ERROR invalid suffix `XYZ` for number literal
+    //~| NOTE invalid suffix `XYZ`
+    //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+    _ = 0OPQ;
+    //~^ ERROR invalid suffix `OPQ` for number literal
+    //~| NOTE invalid suffix `OPQ`
+    //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+    _ = 0BCD;
+    //~^ ERROR invalid suffix `BCD` for number literal
+    //~| NOTE invalid suffix `BCD`
+    //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+}
diff --git a/src/test/ui/numeric/uppercase-base-prefix-invalid-no-fix.stderr b/src/test/ui/numeric/uppercase-base-prefix-invalid-no-fix.stderr
new file mode 100644 (file)
index 0000000..380c16c
--- /dev/null
@@ -0,0 +1,50 @@
+error: invalid suffix `X1a3` for number literal
+  --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:5:9
+   |
+LL |     _ = 123X1a3;
+   |         ^^^^^^^ invalid suffix `X1a3`
+   |
+   = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+error: invalid suffix `O123` for number literal
+  --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:10:9
+   |
+LL |     _ = 456O123;
+   |         ^^^^^^^ invalid suffix `O123`
+   |
+   = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+error: invalid suffix `B101` for number literal
+  --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:15:9
+   |
+LL |     _ = 789B101;
+   |         ^^^^^^^ invalid suffix `B101`
+   |
+   = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+error: invalid suffix `XYZ` for number literal
+  --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:20:9
+   |
+LL |     _ = 0XYZ;
+   |         ^^^^ invalid suffix `XYZ`
+   |
+   = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+error: invalid suffix `OPQ` for number literal
+  --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:25:9
+   |
+LL |     _ = 0OPQ;
+   |         ^^^^ invalid suffix `OPQ`
+   |
+   = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+error: invalid suffix `BCD` for number literal
+  --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:30:9
+   |
+LL |     _ = 0BCD;
+   |         ^^^^ invalid suffix `BCD`
+   |
+   = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/on-unimplemented/sum.rs b/src/test/ui/on-unimplemented/sum.rs
new file mode 100644 (file)
index 0000000..4f1c521
--- /dev/null
@@ -0,0 +1,9 @@
+// <https://github.com/rust-lang/rust/issues/105184>
+
+fn main() {
+    vec![(), ()].iter().sum::<i32>();
+    //~^ ERROR
+
+    vec![(), ()].iter().product::<i32>();
+    //~^ ERROR
+}
diff --git a/src/test/ui/on-unimplemented/sum.stderr b/src/test/ui/on-unimplemented/sum.stderr
new file mode 100644 (file)
index 0000000..2a316db
--- /dev/null
@@ -0,0 +1,43 @@
+error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `&()`
+  --> $DIR/sum.rs:4:25
+   |
+LL |     vec![(), ()].iter().sum::<i32>();
+   |                         ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=&()>`
+   |
+   = help: the trait `Sum<&()>` is not implemented for `i32`
+   = help: the following other types implement trait `Sum<A>`:
+             <i32 as Sum<&'a i32>>
+             <i32 as Sum>
+note: the method call chain might not have had the expected associated types
+  --> $DIR/sum.rs:4:18
+   |
+LL |     vec![(), ()].iter().sum::<i32>();
+   |     ------------ ^^^^^^ `Iterator::Item` is `&()` here
+   |     |
+   |     this expression has type `Vec<()>`
+note: required by a bound in `std::iter::Iterator::sum`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error[E0277]: a value of type `i32` cannot be made by multiplying all elements of type `&()` from an iterator
+  --> $DIR/sum.rs:7:25
+   |
+LL |     vec![(), ()].iter().product::<i32>();
+   |                         ^^^^^^^ value of type `i32` cannot be made by multiplying all elements from a `std::iter::Iterator<Item=&()>`
+   |
+   = help: the trait `Product<&()>` is not implemented for `i32`
+   = help: the following other types implement trait `Product<A>`:
+             <i32 as Product<&'a i32>>
+             <i32 as Product>
+note: the method call chain might not have had the expected associated types
+  --> $DIR/sum.rs:7:18
+   |
+LL |     vec![(), ()].iter().product::<i32>();
+   |     ------------ ^^^^^^ `Iterator::Item` is `&()` here
+   |     |
+   |     this expression has type `Vec<()>`
+note: required by a bound in `std::iter::Iterator::product`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
index 920720a4f53e2558afea17f400dfa896c3ee91cc..10d42b7e3c0b8de4892a98ee411bb38e709c8198 100644 (file)
@@ -35,11 +35,8 @@ note: an implementation of `BitOr<_>` might be missing for `E`
    |
 LL | enum E { A, B }
    | ^^^^^^ must implement `BitOr<_>`
-note: the following trait must be implemented
+note: the trait `BitOr` must be implemented
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL | pub trait BitOr<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 5 previous errors
 
index 794535aeb11052adbc69329dfb59cb4727791172..2e16007825935a159bf5d213f332dd096b54d483 100644 (file)
@@ -6,9 +6,6 @@ LL | impl FnMut<isize> for S {
    |
 note: required by a bound in `FnMut`
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait FnMut<Args: Tuple>: FnOnce<Args> {
-   |                       ^^^^^ required by this bound in `FnMut`
 
 error[E0059]: type parameter to bare `FnOnce` trait must be a tuple
   --> $DIR/overloaded-calls-nontuple.rs:18:6
@@ -18,9 +15,6 @@ LL | impl FnOnce<isize> for S {
    |
 note: required by a bound in `FnOnce`
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait FnOnce<Args: Tuple> {
-   |                        ^^^^^ required by this bound in `FnOnce`
 
 error[E0277]: functions with the "rust-call" ABI must take a single non-self tuple argument
   --> $DIR/overloaded-calls-nontuple.rs:12:5
index c77992b2c3406f3b0dbd7037c7cc6025ea201028..7d17ea59647ec043f7eb0b5f071f80442ec4ef5d 100644 (file)
@@ -34,7 +34,9 @@ error[E0308]: mismatched types
   --> $DIR/bare-struct-body.rs:11:14
    |
 LL |     x.val == 42;
-   |              ^^ expected `()`, found integer
+   |     -----    ^^ expected `()`, found integer
+   |     |
+   |     expected because this is `()`
 
 error: aborting due to 3 previous errors
 
index 694b0b6eb028f7498b7b1e60d65388bb8d9a9487..ae243816d7c2d55af0aebf01fa34cc452b2a9b1a 100644 (file)
@@ -123,37 +123,49 @@ error[E0308]: mismatched types
   --> $DIR/chained-comparison-suggestion.rs:4:14
    |
 LL |     1 < 2 <= 3;
-   |              ^ expected `bool`, found integer
+   |     -----    ^ expected `bool`, found integer
+   |     |
+   |     expected because this is `bool`
 
 error[E0308]: mismatched types
   --> $DIR/chained-comparison-suggestion.rs:13:14
    |
 LL |     1 <= 2 < 3;
-   |              ^ expected `bool`, found integer
+   |     ------   ^ expected `bool`, found integer
+   |     |
+   |     expected because this is `bool`
 
 error[E0308]: mismatched types
   --> $DIR/chained-comparison-suggestion.rs:18:15
    |
 LL |     1 <= 2 <= 3;
-   |               ^ expected `bool`, found integer
+   |     ------    ^ expected `bool`, found integer
+   |     |
+   |     expected because this is `bool`
 
 error[E0308]: mismatched types
   --> $DIR/chained-comparison-suggestion.rs:23:14
    |
 LL |     1 > 2 >= 3;
-   |              ^ expected `bool`, found integer
+   |     -----    ^ expected `bool`, found integer
+   |     |
+   |     expected because this is `bool`
 
 error[E0308]: mismatched types
   --> $DIR/chained-comparison-suggestion.rs:36:15
    |
 LL |     1 >= 2 >= 3;
-   |               ^ expected `bool`, found integer
+   |     ------    ^ expected `bool`, found integer
+   |     |
+   |     expected because this is `bool`
 
 error[E0308]: mismatched types
   --> $DIR/chained-comparison-suggestion.rs:49:15
    |
 LL |     1 == 2 == 3;
-   |               ^ expected `bool`, found integer
+   |     ------    ^ expected `bool`, found integer
+   |     |
+   |     expected because this is `bool`
 
 error: aborting due to 17 previous errors
 
diff --git a/src/test/ui/parser/increment-autofix-2.fixed b/src/test/ui/parser/increment-autofix-2.fixed
new file mode 100644 (file)
index 0000000..580ebaf
--- /dev/null
@@ -0,0 +1,63 @@
+// run-rustfix
+
+struct Foo {
+    bar: Bar,
+}
+
+struct Bar {
+    qux: i32,
+}
+
+pub fn post_regular() {
+    let mut i = 0;
+    i += 1; //~ ERROR Rust has no postfix increment operator
+    println!("{}", i);
+}
+
+pub fn post_while() {
+    let mut i = 0;
+    while { let tmp = i; i += 1; tmp } < 5 {
+        //~^ ERROR Rust has no postfix increment operator
+        println!("{}", i);
+    }
+}
+
+pub fn post_regular_tmp() {
+    let mut tmp = 0;
+    tmp += 1; //~ ERROR Rust has no postfix increment operator
+    println!("{}", tmp);
+}
+
+pub fn post_while_tmp() {
+    let mut tmp = 0;
+    while { let tmp_ = tmp; tmp += 1; tmp_ } < 5 {
+        //~^ ERROR Rust has no postfix increment operator
+        println!("{}", tmp);
+    }
+}
+
+pub fn post_field() {
+    let mut foo = Foo { bar: Bar { qux: 0 } };
+    foo.bar.qux += 1;
+    //~^ ERROR Rust has no postfix increment operator
+    println!("{}", foo.bar.qux);
+}
+
+pub fn post_field_tmp() {
+    struct S {
+        tmp: i32
+    }
+    let mut s = S { tmp: 0 };
+    s.tmp += 1;
+    //~^ ERROR Rust has no postfix increment operator
+    println!("{}", s.tmp);
+}
+
+pub fn pre_field() {
+    let mut foo = Foo { bar: Bar { qux: 0 } };
+    foo.bar.qux += 1;
+    //~^ ERROR Rust has no prefix increment operator
+    println!("{}", foo.bar.qux);
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/increment-autofix-2.rs b/src/test/ui/parser/increment-autofix-2.rs
new file mode 100644 (file)
index 0000000..ebe5fa6
--- /dev/null
@@ -0,0 +1,63 @@
+// run-rustfix
+
+struct Foo {
+    bar: Bar,
+}
+
+struct Bar {
+    qux: i32,
+}
+
+pub fn post_regular() {
+    let mut i = 0;
+    i++; //~ ERROR Rust has no postfix increment operator
+    println!("{}", i);
+}
+
+pub fn post_while() {
+    let mut i = 0;
+    while i++ < 5 {
+        //~^ ERROR Rust has no postfix increment operator
+        println!("{}", i);
+    }
+}
+
+pub fn post_regular_tmp() {
+    let mut tmp = 0;
+    tmp++; //~ ERROR Rust has no postfix increment operator
+    println!("{}", tmp);
+}
+
+pub fn post_while_tmp() {
+    let mut tmp = 0;
+    while tmp++ < 5 {
+        //~^ ERROR Rust has no postfix increment operator
+        println!("{}", tmp);
+    }
+}
+
+pub fn post_field() {
+    let mut foo = Foo { bar: Bar { qux: 0 } };
+    foo.bar.qux++;
+    //~^ ERROR Rust has no postfix increment operator
+    println!("{}", foo.bar.qux);
+}
+
+pub fn post_field_tmp() {
+    struct S {
+        tmp: i32
+    }
+    let mut s = S { tmp: 0 };
+    s.tmp++;
+    //~^ ERROR Rust has no postfix increment operator
+    println!("{}", s.tmp);
+}
+
+pub fn pre_field() {
+    let mut foo = Foo { bar: Bar { qux: 0 } };
+    ++foo.bar.qux;
+    //~^ ERROR Rust has no prefix increment operator
+    println!("{}", foo.bar.qux);
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/increment-autofix-2.stderr b/src/test/ui/parser/increment-autofix-2.stderr
new file mode 100644 (file)
index 0000000..11e9854
--- /dev/null
@@ -0,0 +1,84 @@
+error: Rust has no postfix increment operator
+  --> $DIR/increment-autofix-2.rs:13:6
+   |
+LL |     i++;
+   |      ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     i += 1;
+   |       ~~~~
+
+error: Rust has no postfix increment operator
+  --> $DIR/increment-autofix-2.rs:19:12
+   |
+LL |     while i++ < 5 {
+   |     -----  ^^ not a valid postfix operator
+   |     |
+   |     while parsing the condition of this `while` expression
+   |
+help: use `+= 1` instead
+   |
+LL |     while { let tmp = i; i += 1; tmp } < 5 {
+   |           +++++++++++  ~~~~~~~~~~~~~~~
+
+error: Rust has no postfix increment operator
+  --> $DIR/increment-autofix-2.rs:27:8
+   |
+LL |     tmp++;
+   |        ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     tmp += 1;
+   |         ~~~~
+
+error: Rust has no postfix increment operator
+  --> $DIR/increment-autofix-2.rs:33:14
+   |
+LL |     while tmp++ < 5 {
+   |     -----    ^^ not a valid postfix operator
+   |     |
+   |     while parsing the condition of this `while` expression
+   |
+help: use `+= 1` instead
+   |
+LL |     while { let tmp_ = tmp; tmp += 1; tmp_ } < 5 {
+   |           ++++++++++++    ~~~~~~~~~~~~~~~~~~
+
+error: Rust has no postfix increment operator
+  --> $DIR/increment-autofix-2.rs:41:16
+   |
+LL |     foo.bar.qux++;
+   |                ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     foo.bar.qux += 1;
+   |                 ~~~~
+
+error: Rust has no postfix increment operator
+  --> $DIR/increment-autofix-2.rs:51:10
+   |
+LL |     s.tmp++;
+   |          ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     s.tmp += 1;
+   |           ~~~~
+
+error: Rust has no prefix increment operator
+  --> $DIR/increment-autofix-2.rs:58:5
+   |
+LL |     ++foo.bar.qux;
+   |     ^^ not a valid prefix operator
+   |
+help: use `+= 1` instead
+   |
+LL -     ++foo.bar.qux;
+LL +     foo.bar.qux += 1;
+   |
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/parser/increment-notfixed.rs b/src/test/ui/parser/increment-notfixed.rs
deleted file mode 100644 (file)
index 15f159e..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-struct Foo {
-    bar: Bar,
-}
-
-struct Bar {
-    qux: i32,
-}
-
-pub fn post_regular() {
-    let mut i = 0;
-    i++; //~ ERROR Rust has no postfix increment operator
-    println!("{}", i);
-}
-
-pub fn post_while() {
-    let mut i = 0;
-    while i++ < 5 {
-        //~^ ERROR Rust has no postfix increment operator
-        println!("{}", i);
-    }
-}
-
-pub fn post_regular_tmp() {
-    let mut tmp = 0;
-    tmp++; //~ ERROR Rust has no postfix increment operator
-    println!("{}", tmp);
-}
-
-pub fn post_while_tmp() {
-    let mut tmp = 0;
-    while tmp++ < 5 {
-        //~^ ERROR Rust has no postfix increment operator
-        println!("{}", tmp);
-    }
-}
-
-pub fn post_field() {
-    let foo = Foo { bar: Bar { qux: 0 } };
-    foo.bar.qux++;
-    //~^ ERROR Rust has no postfix increment operator
-    println!("{}", foo.bar.qux);
-}
-
-pub fn post_field_tmp() {
-    struct S {
-        tmp: i32
-    }
-    let s = S { tmp: 0 };
-    s.tmp++;
-    //~^ ERROR Rust has no postfix increment operator
-    println!("{}", s.tmp);
-}
-
-pub fn pre_field() {
-    let foo = Foo { bar: Bar { qux: 0 } };
-    ++foo.bar.qux;
-    //~^ ERROR Rust has no prefix increment operator
-    println!("{}", foo.bar.qux);
-}
-
-fn main() {}
diff --git a/src/test/ui/parser/increment-notfixed.stderr b/src/test/ui/parser/increment-notfixed.stderr
deleted file mode 100644 (file)
index ae55ae0..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-error: Rust has no postfix increment operator
-  --> $DIR/increment-notfixed.rs:11:6
-   |
-LL |     i++;
-   |      ^^ not a valid postfix operator
-   |
-help: use `+= 1` instead
-   |
-LL |     { let tmp = i; i += 1; tmp };
-   |     +++++++++++  ~~~~~~~~~~~~~~~
-LL |     i += 1;
-   |       ~~~~
-
-error: Rust has no postfix increment operator
-  --> $DIR/increment-notfixed.rs:17:12
-   |
-LL |     while i++ < 5 {
-   |     -----  ^^ not a valid postfix operator
-   |     |
-   |     while parsing the condition of this `while` expression
-   |
-help: use `+= 1` instead
-   |
-LL |     while { let tmp = i; i += 1; tmp } < 5 {
-   |           +++++++++++  ~~~~~~~~~~~~~~~
-LL |     while i += 1 < 5 {
-   |             ~~~~
-
-error: Rust has no postfix increment operator
-  --> $DIR/increment-notfixed.rs:25:8
-   |
-LL |     tmp++;
-   |        ^^ not a valid postfix operator
-   |
-help: use `+= 1` instead
-   |
-LL |     { let tmp_ = tmp; tmp += 1; tmp_ };
-   |     ++++++++++++    ~~~~~~~~~~~~~~~~~~
-LL |     tmp += 1;
-   |         ~~~~
-
-error: Rust has no postfix increment operator
-  --> $DIR/increment-notfixed.rs:31:14
-   |
-LL |     while tmp++ < 5 {
-   |     -----    ^^ not a valid postfix operator
-   |     |
-   |     while parsing the condition of this `while` expression
-   |
-help: use `+= 1` instead
-   |
-LL |     while { let tmp_ = tmp; tmp += 1; tmp_ } < 5 {
-   |           ++++++++++++    ~~~~~~~~~~~~~~~~~~
-LL |     while tmp += 1 < 5 {
-   |               ~~~~
-
-error: Rust has no postfix increment operator
-  --> $DIR/increment-notfixed.rs:39:16
-   |
-LL |     foo.bar.qux++;
-   |                ^^ not a valid postfix operator
-   |
-help: use `+= 1` instead
-   |
-LL |     { let tmp = foo.bar.qux; foo.bar.qux += 1; tmp };
-   |     +++++++++++            ~~~~~~~~~~~~~~~~~~~~~~~~~
-LL |     foo.bar.qux += 1;
-   |                 ~~~~
-
-error: Rust has no postfix increment operator
-  --> $DIR/increment-notfixed.rs:49:10
-   |
-LL |     s.tmp++;
-   |          ^^ not a valid postfix operator
-   |
-help: use `+= 1` instead
-   |
-LL |     { let tmp = s.tmp; s.tmp += 1; tmp };
-   |     +++++++++++      ~~~~~~~~~~~~~~~~~~~
-LL |     s.tmp += 1;
-   |           ~~~~
-
-error: Rust has no prefix increment operator
-  --> $DIR/increment-notfixed.rs:56:5
-   |
-LL |     ++foo.bar.qux;
-   |     ^^ not a valid prefix operator
-   |
-help: use `+= 1` instead
-   |
-LL -     ++foo.bar.qux;
-LL +     foo.bar.qux += 1;
-   |
-
-error: aborting due to 7 previous errors
-
diff --git a/src/test/ui/parser/issue-104867-inc-dec-2.rs b/src/test/ui/parser/issue-104867-inc-dec-2.rs
new file mode 100644 (file)
index 0000000..a006421
--- /dev/null
@@ -0,0 +1,52 @@
+fn test1() {
+    let mut i = 0;
+    let _ = i + ++i; //~ ERROR Rust has no prefix increment operator
+}
+
+fn test2() {
+    let mut i = 0;
+    let _ = ++i + i; //~ ERROR Rust has no prefix increment operator
+}
+
+fn test3() {
+    let mut i = 0;
+    let _ = ++i + ++i; //~ ERROR Rust has no prefix increment operator
+}
+
+fn test4() {
+    let mut i = 0;
+    let _ = i + i++; //~ ERROR Rust has no postfix increment operator
+    // won't suggest since we can not handle the precedences
+}
+
+fn test5() {
+    let mut i = 0;
+    let _ = i++ + i; //~ ERROR Rust has no postfix increment operator
+}
+
+fn test6() {
+    let mut i = 0;
+    let _ = i++ + i++; //~ ERROR Rust has no postfix increment operator
+}
+
+fn test7() {
+    let mut i = 0;
+    let _ = ++i + i++; //~ ERROR Rust has no prefix increment operator
+}
+
+fn test8() {
+    let mut i = 0;
+    let _ = i++ + ++i; //~ ERROR Rust has no postfix increment operator
+}
+
+fn test9() {
+    let mut i = 0;
+    let _ = (1 + 2 + i)++; //~ ERROR Rust has no postfix increment operator
+}
+
+fn test10() {
+    let mut i = 0;
+    let _ = (i++ + 1) + 2; //~ ERROR Rust has no postfix increment operator
+}
+
+fn main() { }
diff --git a/src/test/ui/parser/issue-104867-inc-dec-2.stderr b/src/test/ui/parser/issue-104867-inc-dec-2.stderr
new file mode 100644 (file)
index 0000000..4e2d054
--- /dev/null
@@ -0,0 +1,107 @@
+error: Rust has no prefix increment operator
+  --> $DIR/issue-104867-inc-dec-2.rs:3:17
+   |
+LL |     let _ = i + ++i;
+   |                 ^^ not a valid prefix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     let _ = i + { i += 1; i };
+   |                 ~   +++++++++
+
+error: Rust has no prefix increment operator
+  --> $DIR/issue-104867-inc-dec-2.rs:8:13
+   |
+LL |     let _ = ++i + i;
+   |             ^^ not a valid prefix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     let _ = { i += 1; i } + i;
+   |             ~   +++++++++
+
+error: Rust has no prefix increment operator
+  --> $DIR/issue-104867-inc-dec-2.rs:13:13
+   |
+LL |     let _ = ++i + ++i;
+   |             ^^ not a valid prefix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     let _ = { i += 1; i } + ++i;
+   |             ~   +++++++++
+
+error: Rust has no postfix increment operator
+  --> $DIR/issue-104867-inc-dec-2.rs:18:18
+   |
+LL |     let _ = i + i++;
+   |                  ^^ not a valid postfix operator
+
+error: Rust has no postfix increment operator
+  --> $DIR/issue-104867-inc-dec-2.rs:24:14
+   |
+LL |     let _ = i++ + i;
+   |              ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     let _ = { let tmp = i; i += 1; tmp } + i;
+   |             +++++++++++  ~~~~~~~~~~~~~~~
+
+error: Rust has no postfix increment operator
+  --> $DIR/issue-104867-inc-dec-2.rs:29:14
+   |
+LL |     let _ = i++ + i++;
+   |              ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     let _ = { let tmp = i; i += 1; tmp } + i++;
+   |             +++++++++++  ~~~~~~~~~~~~~~~
+
+error: Rust has no prefix increment operator
+  --> $DIR/issue-104867-inc-dec-2.rs:34:13
+   |
+LL |     let _ = ++i + i++;
+   |             ^^ not a valid prefix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     let _ = { i += 1; i } + i++;
+   |             ~   +++++++++
+
+error: Rust has no postfix increment operator
+  --> $DIR/issue-104867-inc-dec-2.rs:39:14
+   |
+LL |     let _ = i++ + ++i;
+   |              ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     let _ = { let tmp = i; i += 1; tmp } + ++i;
+   |             +++++++++++  ~~~~~~~~~~~~~~~
+
+error: Rust has no postfix increment operator
+  --> $DIR/issue-104867-inc-dec-2.rs:44:24
+   |
+LL |     let _ = (1 + 2 + i)++;
+   |                        ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     let _ = { let tmp = (1 + 2 + i); (1 + 2 + i) += 1; tmp };
+   |             +++++++++++            ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: Rust has no postfix increment operator
+  --> $DIR/issue-104867-inc-dec-2.rs:49:15
+   |
+LL |     let _ = (i++ + 1) + 2;
+   |               ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     let _ = ({ let tmp = i; i += 1; tmp } + 1) + 2;
+   |              +++++++++++  ~~~~~~~~~~~~~~~
+
+error: aborting due to 10 previous errors
+
diff --git a/src/test/ui/parser/issue-104867-inc-dec.rs b/src/test/ui/parser/issue-104867-inc-dec.rs
new file mode 100644 (file)
index 0000000..760c67b
--- /dev/null
@@ -0,0 +1,45 @@
+struct S {
+    x: i32,
+}
+
+fn test1() {
+    let mut i = 0;
+    i++; //~ ERROR Rust has no postfix increment operator
+}
+
+fn test2() {
+    let s = S { x: 0 };
+    s.x++; //~ ERROR Rust has no postfix increment operator
+}
+
+fn test3() {
+    let mut i = 0;
+    if i++ == 1 {} //~ ERROR Rust has no postfix increment operator
+}
+
+fn test4() {
+    let mut i = 0;
+    ++i; //~ ERROR Rust has no prefix increment operator
+}
+
+fn test5() {
+    let mut i = 0;
+    if ++i == 1 { } //~ ERROR Rust has no prefix increment operator
+}
+
+fn test6() {
+    let mut i = 0;
+    loop { break; }
+    i++; //~ ERROR Rust has no postfix increment operator
+    loop { break; }
+    ++i;
+}
+
+fn test7() {
+    let mut i = 0;
+    loop { break; }
+    ++i; //~ ERROR Rust has no prefix increment operator
+}
+
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-104867-inc-dec.stderr b/src/test/ui/parser/issue-104867-inc-dec.stderr
new file mode 100644 (file)
index 0000000..78bfd3e
--- /dev/null
@@ -0,0 +1,81 @@
+error: Rust has no postfix increment operator
+  --> $DIR/issue-104867-inc-dec.rs:7:6
+   |
+LL |     i++;
+   |      ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     i += 1;
+   |       ~~~~
+
+error: Rust has no postfix increment operator
+  --> $DIR/issue-104867-inc-dec.rs:12:8
+   |
+LL |     s.x++;
+   |        ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     s.x += 1;
+   |         ~~~~
+
+error: Rust has no postfix increment operator
+  --> $DIR/issue-104867-inc-dec.rs:17:9
+   |
+LL |     if i++ == 1 {}
+   |         ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     if { let tmp = i; i += 1; tmp } == 1 {}
+   |        +++++++++++  ~~~~~~~~~~~~~~~
+
+error: Rust has no prefix increment operator
+  --> $DIR/issue-104867-inc-dec.rs:22:5
+   |
+LL |     ++i;
+   |     ^^ not a valid prefix operator
+   |
+help: use `+= 1` instead
+   |
+LL -     ++i;
+LL +     i += 1;
+   |
+
+error: Rust has no prefix increment operator
+  --> $DIR/issue-104867-inc-dec.rs:27:8
+   |
+LL |     if ++i == 1 { }
+   |        ^^ not a valid prefix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     if { i += 1; i } == 1 { }
+   |        ~   +++++++++
+
+error: Rust has no postfix increment operator
+  --> $DIR/issue-104867-inc-dec.rs:33:6
+   |
+LL |     i++;
+   |      ^^ not a valid postfix operator
+   |
+help: use `+= 1` instead
+   |
+LL |     i += 1;
+   |       ~~~~
+
+error: Rust has no prefix increment operator
+  --> $DIR/issue-104867-inc-dec.rs:41:5
+   |
+LL |     ++i;
+   |     ^^ not a valid prefix operator
+   |
+help: use `+= 1` instead
+   |
+LL -     ++i;
+LL +     i += 1;
+   |
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/parser/issue-105366.fixed b/src/test/ui/parser/issue-105366.fixed
new file mode 100644 (file)
index 0000000..ad26643
--- /dev/null
@@ -0,0 +1,12 @@
+// run-rustfix
+
+struct Foo;
+
+impl From<i32> for Foo {
+    //~^ ERROR you might have meant to write `impl` instead of `fn`
+    fn from(_a: i32) -> Self {
+        Foo
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-105366.rs b/src/test/ui/parser/issue-105366.rs
new file mode 100644 (file)
index 0000000..311b6a6
--- /dev/null
@@ -0,0 +1,12 @@
+// run-rustfix
+
+struct Foo;
+
+fn From<i32> for Foo {
+    //~^ ERROR you might have meant to write `impl` instead of `fn`
+    fn from(_a: i32) -> Self {
+        Foo
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-105366.stderr b/src/test/ui/parser/issue-105366.stderr
new file mode 100644 (file)
index 0000000..0a7408e
--- /dev/null
@@ -0,0 +1,13 @@
+error: you might have meant to write `impl` instead of `fn`
+  --> $DIR/issue-105366.rs:5:1
+   |
+LL | fn From<i32> for Foo {
+   | ^^
+   |
+help: replace `fn` with `impl` here
+   |
+LL | impl From<i32> for Foo {
+   | ~~~~
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-39616.rs b/src/test/ui/parser/issue-39616.rs
new file mode 100644 (file)
index 0000000..46b5aa3
--- /dev/null
@@ -0,0 +1,3 @@
+fn foo(a: [0; 1]) {} //~ ERROR expected type, found `0`
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-39616.stderr b/src/test/ui/parser/issue-39616.stderr
new file mode 100644 (file)
index 0000000..393d1f2
--- /dev/null
@@ -0,0 +1,8 @@
+error: expected type, found `0`
+  --> $DIR/issue-39616.rs:1:12
+   |
+LL | fn foo(a: [0; 1]) {}
+   |            ^ expected type
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-49257.rs b/src/test/ui/parser/issue-49257.rs
new file mode 100644 (file)
index 0000000..a7fa19d
--- /dev/null
@@ -0,0 +1,14 @@
+// Test for #49257:
+// emits good diagnostics for `..` pattern fragments not in the last position.
+
+#![allow(unused)]
+
+struct Point { x: u8, y: u8 }
+
+fn main() {
+    let p = Point { x: 0, y: 0 };
+    let Point { .., y, } = p; //~ ERROR expected `}`, found `,`
+    let Point { .., y } = p; //~ ERROR expected `}`, found `,`
+    let Point { .., } = p; //~ ERROR expected `}`, found `,`
+    let Point { .. } = p;
+}
diff --git a/src/test/ui/parser/issue-49257.stderr b/src/test/ui/parser/issue-49257.stderr
new file mode 100644 (file)
index 0000000..846467f
--- /dev/null
@@ -0,0 +1,42 @@
+error: expected `}`, found `,`
+  --> $DIR/issue-49257.rs:10:19
+   |
+LL |     let Point { .., y, } = p;
+   |                 --^
+   |                 | |
+   |                 | expected `}`
+   |                 `..` must be at the end and cannot have a trailing comma
+   |
+help: move the `..` to the end of the field list
+   |
+LL -     let Point { .., y, } = p;
+LL +     let Point { y, .. } = p;
+   |
+
+error: expected `}`, found `,`
+  --> $DIR/issue-49257.rs:11:19
+   |
+LL |     let Point { .., y } = p;
+   |                 --^
+   |                 | |
+   |                 | expected `}`
+   |                 `..` must be at the end and cannot have a trailing comma
+   |
+help: move the `..` to the end of the field list
+   |
+LL -     let Point { .., y } = p;
+LL +     let Point { y , .. } = p;
+   |
+
+error: expected `}`, found `,`
+  --> $DIR/issue-49257.rs:12:19
+   |
+LL |     let Point { .., } = p;
+   |                 --^
+   |                 | |
+   |                 | expected `}`
+   |                 | help: remove this comma
+   |                 `..` must be at the end and cannot have a trailing comma
+
+error: aborting due to 3 previous errors
+
index ae89926914ebaa7d6c4592d6df24afdf2ea2e64f..07a203bf416eada152c3ca9da8e11d59d0c7ccd3 100644 (file)
@@ -42,11 +42,9 @@ LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq!
 LL |
 LL | fn main() {}
    | ^^ unexpected token
+  --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-   |
-LL |     ($left:expr, $right:expr $(,)?) => {
-   |      ---------- while parsing argument for this `expr` macro fragment
+   = note: while parsing argument for this `expr` macro fragment
 
 error: aborting due to 4 previous errors
 
index 546ad84eeee7bf25abbb3c1caa44db0dc7f3b224..79643660e8b0078c73e70de919e0fd285dc0f415 100644 (file)
@@ -91,44 +91,36 @@ error[E0405]: cannot find trait `r#fn` in this scope
    |
 LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
    |          ^^ help: a trait with a similar name exists (notice the capitalization): `Fn`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   | -------------------------------------- similarly named trait `Fn` defined here
+   = note: similarly named trait `Fn` defined here
 
 error[E0405]: cannot find trait `r#fn` in this scope
   --> $DIR/kw-in-trait-bounds.rs:17:4
    |
 LL | G: fn(),
    |    ^^ help: a trait with a similar name exists (notice the capitalization): `Fn`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   | -------------------------------------- similarly named trait `Fn` defined here
+   = note: similarly named trait `Fn` defined here
 
 error[E0405]: cannot find trait `r#fn` in this scope
   --> $DIR/kw-in-trait-bounds.rs:3:27
    |
 LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
    |                           ^^ help: a trait with a similar name exists (notice the capitalization): `Fn`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   | -------------------------------------- similarly named trait `Fn` defined here
+   = note: similarly named trait `Fn` defined here
 
 error[E0405]: cannot find trait `r#fn` in this scope
   --> $DIR/kw-in-trait-bounds.rs:3:41
    |
 LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
    |                                         ^^ help: a trait with a similar name exists (notice the capitalization): `Fn`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   | -------------------------------------- similarly named trait `Fn` defined here
+   = note: similarly named trait `Fn` defined here
 
 error[E0405]: cannot find trait `r#struct` in this scope
   --> $DIR/kw-in-trait-bounds.rs:24:10
diff --git a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.fixed b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.fixed
new file mode 100644 (file)
index 0000000..5f04fc8
--- /dev/null
@@ -0,0 +1,12 @@
+// run-rustfix
+#![allow(unused_variables)]
+fn main() {
+    struct U;
+
+    // A tuple is a "non-reference pattern".
+    // A `mut` binding pattern resets the binding mode to by-value.
+
+    let mut p = (U, U);
+    let (a, ref mut b) = &mut p;
+    //~^ ERROR cannot move out of a mutable reference
+}
diff --git a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.rs b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.rs
new file mode 100644 (file)
index 0000000..5dc1ae2
--- /dev/null
@@ -0,0 +1,12 @@
+// run-rustfix
+#![allow(unused_variables)]
+fn main() {
+    struct U;
+
+    // A tuple is a "non-reference pattern".
+    // A `mut` binding pattern resets the binding mode to by-value.
+
+    let mut p = (U, U);
+    let (a, mut b) = &mut p;
+    //~^ ERROR cannot move out of a mutable reference
+}
diff --git a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.stderr b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.stderr
new file mode 100644 (file)
index 0000000..d3ab533
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0507]: cannot move out of a mutable reference
+  --> $DIR/move-ref-patterns-default-binding-modes-fixable.rs:10:22
+   |
+LL |     let (a, mut b) = &mut p;
+   |             -----    ^^^^^^
+   |             |
+   |             data moved here
+   |             move occurs because `b` has type `U`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     let (a, ref mut b) = &mut p;
+   |             +++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
index 1dd66aad57a33f71afe27f1c0362f54c064db53b..6c913c245130d7307b7c8361731568bbc76385b1 100644 (file)
@@ -7,8 +7,4 @@ fn main() {
     let p = (U, U);
     let (a, mut b) = &p;
     //~^ ERROR cannot move out of a shared reference
-
-    let mut p = (U, U);
-    let (a, mut b) = &mut p;
-    //~^ ERROR cannot move out of a mutable reference
 }
index 6952c743a3069e5d6dd1f8072abcb8d47e24f6bb..65030b62250012729961a9f6938d6d012a4b1dd0 100644 (file)
@@ -6,16 +6,12 @@ LL |     let (a, mut b) = &p;
    |             |
    |             data moved here
    |             move occurs because `b` has type `U`, which does not implement the `Copy` trait
-
-error[E0507]: cannot move out of a mutable reference
-  --> $DIR/move-ref-patterns-default-binding-modes.rs:12:22
    |
-LL |     let (a, mut b) = &mut p;
-   |             -----    ^^^^^^
-   |             |
-   |             data moved here
-   |             move occurs because `b` has type `U`, which does not implement the `Copy` trait
+help: consider borrowing the pattern binding
+   |
+LL |     let (a, ref mut b) = &p;
+   |             +++
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0507`.
index 3342b8e4002b909ce770b6aceeef2b8aaec128a9..da369d33397fc0c5df6f2b6739a727b920d9e86c 100644 (file)
@@ -9,8 +9,8 @@ LL |         (..) => {}
    |
 help: consider giving `x` an explicit type
    |
-LL |     let x: _;
-   |          +++
+LL |     let x: /* Type */;
+   |          ++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/pat-tuple-bad-type.rs:10:9
index e6a4e5f19b716ecd44949a0fe713ab756944fc41..beba7def96f5236034d546819979f3e0f4b7eb17 100644 (file)
@@ -193,8 +193,8 @@ LL |     let x @ ..;
    |
 help: consider giving this pattern a type
    |
-LL |     let x @ ..: _;
-   |               +++
+LL |     let x @ ..: /* Type */;
+   |               ++++++++++++
 
 error: aborting due to 23 previous errors
 
index f3dca9bcb07d1f42b6ca0e3b628cefea64441f43..2a016048f2f7a03c38464de94af8c4ba0d0021a0 100644 (file)
@@ -6,12 +6,9 @@ LL |     match Some(1) {
    |
 note: `Option<i32>` defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
    |
-LL | pub enum Option<T> {
-   | ------------------
-...
-LL |     None,
-   |     ^^^^ not covered
+   = note: not covered
    = note: the matched value is of type `Option<i32>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
index b450a9aeddf8d71f5cfd19de3a4ab80e7e3306c3..17e1a2304a13c0c8011481553170e1886fc11e5e 100644 (file)
@@ -66,12 +66,9 @@ LL |     match None {
    |
 note: `Option<HiddenEnum>` defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
    |
-LL | pub enum Option<T> {
-   | ------------------
-...
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^ not covered
+   = note: not covered
    = note: the matched value is of type `Option<HiddenEnum>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
index c9781d52e6dcf529a79639257c79e9a238be0e5b..12113957d6340dbc0862060d0b2072ed0ba124d4 100644 (file)
@@ -107,9 +107,6 @@ LL |     match Some(A) {
    |
 note: `Option<Enum>` defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL | pub enum Option<T> {
-   | ^^^^^^^^^^^^^^^^^^
    = note: the matched value is of type `Option<Enum>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
    |
index eb8c63919b6445fbd4576ffec0af6968e62a3a7f..59d7bcd4b5e799d443b90374b7b18d6b2eef5d10 100644 (file)
@@ -6,12 +6,6 @@ LL |         box NodeKind::Element(ed) => match ed.kind {
    |
 note: `Box<ElementKind>` defined here
   --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
-   |
-LL | / pub struct Box<
-LL | |     T: ?Sized,
-LL | |     #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
-LL | | >(Unique<T>, A);
-   | |_^
    = note: the matched value is of type `Box<ElementKind>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
index b0d7fe5eb6892174c9c92821a39d7abdf9cdbc31..e4dd35a59958ef37f2dc2ed58508168472bec0af 100644 (file)
@@ -19,15 +19,11 @@ LL |     match Some(Some(North)) {
    |
 note: `Option<Option<Direction>>` defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
    |
-LL | pub enum Option<T> {
-   | ------------------
-...
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^
-   |     |
-   |     not covered
-   |     not covered
+   = note: not covered
+   |
+   = note: not covered
    = note: the matched value is of type `Option<Option<Direction>>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
index 4607cfaae1719db36dfec2abc9bc7270ab8fb073..86f75d15cfde7736c2294be1373bd6c9b605993b 100644 (file)
@@ -6,12 +6,9 @@ LL |     match private::DATA {
    |
 note: `Option<Private>` defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
    |
-LL | pub enum Option<T> {
-   | ------------------
-...
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^ not covered
+   = note: not covered
    = note: the matched value is of type `Option<Private>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
index 4234600d0d02f75144dd41ef900ea1681d522aa6..e2260f50bfef2b462fa795ace1352d6a714f7916 100644 (file)
@@ -36,12 +36,9 @@ LL |     match Some(10) {
    |
 note: `Option<i32>` defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
    |
-LL | pub enum Option<T> {
-   | ------------------
-...
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^ not covered
+   = note: not covered
    = note: the matched value is of type `Option<i32>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
index 49895f3db4dff417b3967215b97a8ef308c8c33c..08b90b365e326db0e796f1b2de0e2efba56651ab 100644 (file)
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/pptypedef.rs:4:37
    |
 LL |     let_in(3u32, |i| { assert!(i == 3i32); });
-   |                                     ^^^^ expected `u32`, found `i32`
+   |                                -    ^^^^ expected `u32`, found `i32`
+   |                                |
+   |                                expected because this is `u32`
    |
 help: change the type of the numeric literal from `i32` to `u32`
    |
@@ -13,7 +15,9 @@ error[E0308]: mismatched types
   --> $DIR/pptypedef.rs:8:37
    |
 LL |     let_in(3i32, |i| { assert!(i == 3u32); });
-   |                                     ^^^^ expected `i32`, found `u32`
+   |                                -    ^^^^ expected `i32`, found `u32`
+   |                                |
+   |                                expected because this is `i32`
    |
 help: change the type of the numeric literal from `u32` to `i32`
    |
diff --git a/src/test/ui/print_type_sizes/async.rs b/src/test/ui/print_type_sizes/async.rs
new file mode 100644 (file)
index 0000000..1598b06
--- /dev/null
@@ -0,0 +1,11 @@
+// compile-flags: -Z print-type-sizes --crate-type lib
+// edition:2021
+// build-pass
+// ignore-pass
+
+async fn wait() {}
+
+pub async fn test(arg: [u8; 8192]) {
+    wait().await;
+    drop(arg);
+}
diff --git a/src/test/ui/print_type_sizes/async.stdout b/src/test/ui/print_type_sizes/async.stdout
new file mode 100644 (file)
index 0000000..6e47bb4
--- /dev/null
@@ -0,0 +1,34 @@
+print-type-size type: `[async fn body@$DIR/async.rs:8:36: 11:2]`: 16386 bytes, alignment: 1 bytes
+print-type-size     discriminant: 1 bytes
+print-type-size     variant `Suspend0`: 16385 bytes
+print-type-size         field `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size         field `.arg`: 8192 bytes
+print-type-size         field `.__awaitee`: 1 bytes
+print-type-size     variant `Unresumed`: 8192 bytes
+print-type-size         field `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size     variant `Returned`: 8192 bytes
+print-type-size         field `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size     variant `Panicked`: 8192 bytes
+print-type-size         field `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::ManuallyDrop<[u8; 8192]>`: 8192 bytes, alignment: 1 bytes
+print-type-size     field `.value`: 8192 bytes
+print-type-size type: `std::mem::MaybeUninit<[u8; 8192]>`: 8192 bytes, alignment: 1 bytes
+print-type-size     variant `MaybeUninit`: 8192 bytes
+print-type-size         field `.uninit`: 0 bytes
+print-type-size         field `.value`: 8192 bytes
+print-type-size type: `[async fn body@$DIR/async.rs:6:17: 6:19]`: 1 bytes, alignment: 1 bytes
+print-type-size     discriminant: 1 bytes
+print-type-size     variant `Unresumed`: 0 bytes
+print-type-size     variant `Returned`: 0 bytes
+print-type-size     variant `Panicked`: 0 bytes
+print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/async.rs:6:17: 6:19]>`: 1 bytes, alignment: 1 bytes
+print-type-size     field `.value`: 1 bytes
+print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/async.rs:6:17: 6:19]>`: 1 bytes, alignment: 1 bytes
+print-type-size     variant `MaybeUninit`: 1 bytes
+print-type-size         field `.uninit`: 0 bytes
+print-type-size         field `.value`: 1 bytes
+print-type-size type: `std::task::Poll<()>`: 1 bytes, alignment: 1 bytes
+print-type-size     discriminant: 1 bytes
+print-type-size     variant `Ready`: 0 bytes
+print-type-size         field `.0`: 0 bytes
+print-type-size     variant `Pending`: 0 bytes
diff --git a/src/test/ui/print_type_sizes/generator.rs b/src/test/ui/print_type_sizes/generator.rs
new file mode 100644 (file)
index 0000000..d1cd362
--- /dev/null
@@ -0,0 +1,18 @@
+// compile-flags: -Z print-type-sizes --crate-type=lib
+// build-pass
+// ignore-pass
+
+#![feature(generators, generator_trait)]
+
+use std::ops::Generator;
+
+fn generator<const C: usize>(array: [u8; C]) -> impl Generator<Yield = (), Return = ()> {
+    move |()| {
+        yield ();
+        let _ = array;
+    }
+}
+
+pub fn foo() {
+    let _ = generator([0; 8192]);
+}
diff --git a/src/test/ui/print_type_sizes/generator.stdout b/src/test/ui/print_type_sizes/generator.stdout
new file mode 100644 (file)
index 0000000..28d4a6e
--- /dev/null
@@ -0,0 +1,10 @@
+print-type-size type: `[generator@$DIR/generator.rs:10:5: 10:14]`: 8193 bytes, alignment: 1 bytes
+print-type-size     discriminant: 1 bytes
+print-type-size     variant `Unresumed`: 8192 bytes
+print-type-size         field `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size     variant `Returned`: 8192 bytes
+print-type-size         field `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size     variant `Panicked`: 8192 bytes
+print-type-size         field `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size     variant `Suspend0`: 8192 bytes
+print-type-size         field `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
diff --git a/src/test/ui/print_type_sizes/generator_discr_placement.rs b/src/test/ui/print_type_sizes/generator_discr_placement.rs
new file mode 100644 (file)
index 0000000..1a85fe9
--- /dev/null
@@ -0,0 +1,23 @@
+// compile-flags: -Z print-type-sizes --crate-type lib
+// build-pass
+// ignore-pass
+
+// Tests a generator that has its discriminant as the *final* field.
+
+// Avoid emitting panic handlers, like the rest of these tests...
+#![feature(generators)]
+
+pub fn foo() {
+    let a = || {
+        {
+            let w: i32 = 4;
+            yield;
+            drop(w);
+        }
+        {
+            let z: i32 = 7;
+            yield;
+            drop(z);
+        }
+    };
+}
diff --git a/src/test/ui/print_type_sizes/generator_discr_placement.stdout b/src/test/ui/print_type_sizes/generator_discr_placement.stdout
new file mode 100644 (file)
index 0000000..7f8f4cc
--- /dev/null
@@ -0,0 +1,11 @@
+print-type-size type: `[generator@$DIR/generator_discr_placement.rs:11:13: 11:15]`: 8 bytes, alignment: 4 bytes
+print-type-size     discriminant: 1 bytes
+print-type-size     variant `Suspend0`: 7 bytes
+print-type-size         padding: 3 bytes
+print-type-size         field `.w`: 4 bytes, alignment: 4 bytes
+print-type-size     variant `Suspend1`: 7 bytes
+print-type-size         padding: 3 bytes
+print-type-size         field `.z`: 4 bytes, alignment: 4 bytes
+print-type-size     variant `Unresumed`: 0 bytes
+print-type-size     variant `Returned`: 0 bytes
+print-type-size     variant `Panicked`: 0 bytes
index 3ef7b60db2caee840885f4631d0b169f90fc3757..05097087d5a811e1c07a8e36bb50b755aa0941e6 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 // ignore-pass
 // ^-- needed because `--pass check` does not emit the output needed.
@@ -8,24 +8,6 @@
 // monomorphized, in the MIR of the original function in which they
 // occur, to have their size reported.
 
-#![feature(start)]
-
-// In an ad-hoc attempt to avoid the injection of unwinding code
-// (which clutters the output of `-Z print-type-sizes` with types from
-// `unwind::libunwind`):
-//
-//   * I am not using Default to build values because that seems to
-//     cause the injection of unwinding code. (Instead I just make `fn new`
-//     methods.)
-//
-//   * Pair derive Copy to ensure that we don't inject
-//     unwinding code into generic uses of Pair when T itself is also
-//     Copy.
-//
-//     (I suspect this reflect some naivety within the rust compiler
-//      itself; it should be checking for drop glue, i.e., a destructor
-//      somewhere in the monomorphized types. It should not matter whether
-//      the type is Copy.)
 #[derive(Copy, Clone)]
 pub struct Pair<T> {
     _car: T,
@@ -61,11 +43,9 @@ pub fn f1<T:Copy>(x: T) {
         Pair::new(FiftyBytes::new(), FiftyBytes::new());
 }
 
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
+pub fn start() {
     let _b: Pair<u8> = Pair::new(0, 0);
     let _s: Pair<SevenBytes> = Pair::new(SevenBytes::new(), SevenBytes::new());
     let ref _z: ZeroSized = ZeroSized;
     f1::<SevenBytes>(SevenBytes::new());
-    0
 }
index f1ad27ec131371988f2e0810fc4c709646dfb28b..9159038924719f288091a30166a4a362b2a7fc07 100644 (file)
@@ -1,11 +1,9 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 
 // This file illustrates that when multiple structural types occur in
 // a function, every one of them is included in the output.
 
-#![feature(start)]
-
 pub struct SevenBytes([u8;  7]);
 pub struct FiftyBytes([u8; 50]);
 
@@ -13,11 +11,3 @@ pub enum Enum {
     Small(SevenBytes),
     Large(FiftyBytes),
 }
-
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
-    let _e: Enum;
-    let _f: FiftyBytes;
-    let _s: SevenBytes;
-    0
-}
index 0716cee21c6626a71670081e752d2abdddc11775..5e620f248b65d35b1dd4243686249b7cb44aac46 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 // ignore-pass
 // ^-- needed because `--pass check` does not emit the output needed.
@@ -14,7 +14,6 @@
 // aligned (while on most it is 8-byte aligned) and so the resulting
 // padding and overall computed sizes can be quite different.
 
-#![feature(start)]
 #![feature(rustc_attrs)]
 #![allow(dead_code)]
 
@@ -56,7 +55,7 @@ pub struct NestedNonZero {
 
 impl Default for NestedNonZero {
     fn default() -> Self {
-        NestedNonZero { pre: 0, val: NonZeroU32::new(1).unwrap(), post: 0 }
+        NestedNonZero { pre: 0, val: unsafe { NonZeroU32::new_unchecked(1) }, post: 0 }
     }
 }
 
@@ -76,8 +75,7 @@ pub union Union2<A: Copy, B: Copy> {
     b: B,
 }
 
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
+pub fn test() {
     let _x: MyOption<NonZeroU32> = Default::default();
     let _y: EmbeddedDiscr = Default::default();
     let _z: MyOption<IndirectNonZero> = Default::default();
@@ -96,6 +94,4 @@ fn start(_: isize, _: *const *const u8) -> isize {
     // ...even when theoretically possible.
     let _j: MyOption<Union1<NonZeroU32>> = Default::default();
     let _k: MyOption<Union2<NonZeroU32, NonZeroU32>> = Default::default();
-
-    0
 }
index e45e4794a3526a754357c88511c647a8d5637677..2ec5d9e64bfbfbad3de1496e7cdf2773002d6194 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 // ignore-pass
 // ^-- needed because `--pass check` does not emit the output needed.
@@ -8,16 +8,12 @@
 // (even if multiple functions), it is only printed once in the
 // print-type-sizes output.
 
-#![feature(start)]
-
 pub struct SevenBytes([u8; 7]);
 
 pub fn f1() {
     let _s: SevenBytes = SevenBytes([0; 7]);
 }
 
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
+pub fn test() {
     let _s: SevenBytes = SevenBytes([0; 7]);
-    0
 }
index 269cc3cc2825fccc97c3991c15f7c61f43ba6705..5ddfe4bf4dbb0a9bfaed5ac3a2a0a95547de2da9 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 // ignore-pass
 // ^-- needed because `--pass check` does not emit the output needed.
 // padding and overall computed sizes can be quite different.
 
 #![allow(dead_code)]
-#![feature(start)]
 
 #[derive(Default)]
 #[repr(packed)]
-struct Packed1 {
+pub struct Packed1 {
     a: u8,
     b: u8,
     g: i32,
@@ -28,7 +27,7 @@ struct Packed1 {
 
 #[derive(Default)]
 #[repr(packed(2))]
-struct Packed2 {
+pub struct Packed2 {
     a: u8,
     b: u8,
     g: i32,
@@ -40,7 +39,7 @@ struct Packed2 {
 #[derive(Default)]
 #[repr(packed(2))]
 #[repr(C)]
-struct Packed2C {
+pub struct Packed2C {
     a: u8,
     b: u8,
     g: i32,
@@ -50,7 +49,7 @@ struct Packed2C {
 }
 
 #[derive(Default)]
-struct Padded {
+pub struct Padded {
     a: u8,
     b: u8,
     g: i32,
@@ -58,12 +57,3 @@ struct Padded {
     h: i16,
     d: u8,
 }
-
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
-    let _c: Packed1 = Default::default();
-    let _d: Packed2 = Default::default();
-    let _e: Packed2C = Default::default();
-    let _f: Padded = Default::default();
-    0
-}
index d1acad16d7e1d3a60a13b290408b751f2f1ae406..f41c677dc6c08ff7bd0a0b61c489b677fbd89b2c 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 
 // This file illustrates how padding is handled: alignment
@@ -9,7 +9,6 @@
 // aligned (while on most it is 8-byte aligned) and so the resulting
 // padding and overall computed sizes can be quite different.
 
-#![feature(start)]
 #![allow(dead_code)]
 
 struct S {
@@ -27,8 +26,3 @@ enum E2 {
     A(i8, i32),
     B(S),
 }
-
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
-    0
-}
index 07544935b2f828480eafeceff869d76898ff001b..0bd11ebc958433a3369b7addf8a8d2213be792d2 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 // ignore-pass
 // ^-- needed because `--pass check` does not emit the output needed.
@@ -11,7 +11,7 @@
 // It avoids using u64/i64 because on some targets that is only 4-byte
 // aligned (while on most it is 8-byte aligned) and so the resulting
 // padding and overall computed sizes can be quite different.
-#![feature(start)]
+
 #![allow(dead_code)]
 
 #[repr(align(16))]
@@ -24,15 +24,9 @@ enum E {
 }
 
 #[derive(Default)]
-struct S {
+pub struct S {
     a: i32,
     b: i32,
     c: A,
     d: i8,
 }
-
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
-    let _s: S = Default::default();
-    0
-}
index b8067c112eef13c974e2d8f12afeba90feb80c40..6b103776a30d3c6c700a85cf3a242f4661edc8ee 100644 (file)
@@ -1,10 +1,9 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 
 // This test makes sure that the tag is not grown for `repr(C)` or `repr(u8)`
 // variants (see https://github.com/rust-lang/rust/issues/50098 for the original bug).
 
-#![feature(start)]
 #![allow(dead_code)]
 
 #[repr(C, u8)]
@@ -18,8 +17,3 @@ enum Repru8 {
     A(u16),
     B,
 }
-
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
-    0
-}
index 06a62db4ebb0f37014d835f0e71fc2f2fe85ad25..86fab7b500af08030a7acca69d30b776a5724a3a 100644 (file)
@@ -1,14 +1,12 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 // ignore-pass
 // ^-- needed because `--pass check` does not emit the output needed.
 //     FIXME: consider using an attribute instead of side-effects.
 
 #![feature(never_type)]
-#![feature(start)]
 
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
+pub fn test() {
     let _x: Option<!> = None;
     let _y: Result<u32, !> = Ok(42);
     let _z: Result<!, !> = loop {};
index 6c8553cc23ded83bffdef6a0a643b9bd099970df..5a3020520265db95a15f4857f10cfa2f0655e1ba 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 
 // This file illustrates two things:
@@ -9,8 +9,6 @@
 // 2. For an enum, the print-type-sizes output will also include the
 //    size of each variant.
 
-#![feature(start)]
-
 pub struct SevenBytes([u8;  7]);
 pub struct FiftyBytes([u8; 50]);
 
@@ -18,9 +16,3 @@ pub enum Enum {
     Small(SevenBytes),
     Large(FiftyBytes),
 }
-
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
-    let _e: Enum;
-    0
-}
index e02a33109e56af728bd6776cf7b576290a0e27df..09415824d5df00835f9cda3dabbd4f5b9c4bc467 100644 (file)
@@ -1,12 +1,10 @@
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
 // build-pass
 // ignore-pass
 
 // At one point, zero-sized fields such as those in this file were causing
 // incorrect output from `-Z print-type-sizes`.
 
-#![feature(start)]
-
 struct S1 {
     x: u32,
     y: u32,
@@ -28,8 +26,7 @@ struct S5<TagW, TagZ> {
     tagz: TagZ,
 }
 
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
+pub fn test() {
     let _s1: S1 = S1 { x: 0, y: 0, tag: () };
 
     let _s5: S5<(), Empty> = S5 {
@@ -43,5 +40,4 @@ fn start(_: isize, _: *const *const u8) -> isize {
         z: 4,
         tagz: Empty {},
     };
-    0
 }
index ad9a5e15c4e6e4376ff1d1e9dc014a34f4c4ebf9..c686a21772e0ed4e7ebfb3026779ff712d183222 100644 (file)
@@ -19,9 +19,9 @@ pub trait PubTr: PrivTr {}
         Pub.method();
         //~^ ERROR type `for<'a> fn(&'a Self) {<Self as PrivTr>::method}` is private
         <Pub as PrivTr>::CONST;
-        //~^ ERROR associated constant `<Pub as PrivTr>::CONST` is private
+        //~^ ERROR associated constant `PrivTr::CONST` is private
         let _: <Pub as PrivTr>::AssocTy;
-        //~^ ERROR associated type `<Pub as PrivTr>::AssocTy` is private
+        //~^ ERROR associated type `PrivTr::AssocTy` is private
         pub type InSignatureTy = <Pub as PrivTr>::AssocTy;
         //~^ ERROR trait `PrivTr` is private
         pub trait InSignatureTr: PrivTr {}
index c4be1a9d9a2027ddc6f9eae41386b5793ea302cb..eb905bf7ef85890d7783430b9db3e206c5eda39f 100644 (file)
@@ -31,7 +31,7 @@ LL |     priv_trait::mac!();
    |
    = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: associated constant `<Pub as PrivTr>::CONST` is private
+error: associated constant `PrivTr::CONST` is private
   --> $DIR/associated-item-privacy-trait.rs:21:9
    |
 LL |         <Pub as PrivTr>::CONST;
@@ -42,7 +42,7 @@ LL |     priv_trait::mac!();
    |
    = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: associated type `<Pub as PrivTr>::AssocTy` is private
+error: associated type `PrivTr::AssocTy` is private
   --> $DIR/associated-item-privacy-trait.rs:23:16
    |
 LL |         let _: <Pub as PrivTr>::AssocTy;
index 0337aedd0088165222b794c3327254c51b8947e7..cdbdcf60b2c540f78ffe6643c9b4745a38957ff1 100644 (file)
@@ -1,7 +1,7 @@
 // aux-build:private-inferred-type.rs
 
 // error-pattern:type `fn() {ext::priv_fn}` is private
-// error-pattern:static `PRIV_STATIC` is private
+// error-pattern:static `ext::PRIV_STATIC` is private
 // error-pattern:type `ext::PrivEnum` is private
 // error-pattern:type `fn() {<u8 as ext::PrivTrait>::method}` is private
 // error-pattern:type `fn(u8) -> ext::PrivTupleStruct {ext::PrivTupleStruct}` is private
index 00b61512de6b4d3176a3a509dc348b45505335e5..42faeb4bf341dea982b44442d2cbec0061059d1a 100644 (file)
@@ -6,7 +6,7 @@ LL |     ext::m!();
    |
    = note: this error originates in the macro `ext::m` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: static `PRIV_STATIC` is private
+error: static `ext::PRIV_STATIC` is private
   --> $DIR/private-inferred-type-3.rs:16:5
    |
 LL |     ext::m!();
index bcb54df0ecac75388f3b36ab2cda47f6d197d019..f96939bb6efcee107a0ebd29246c9fcbdb0cd2e4 100644 (file)
@@ -8,21 +8,25 @@ error: macro expansion ignores token `,` and any following
   --> $DIR/attr-invalid-exprs.rs:15:13
    |
 LL |     let _ = #[duplicate] "Hello, world!";
-   |             ^^^^^^^^^^^^- help: you might be missing a semicolon here: `;`
-   |             |
-   |             caused by the macro expansion here
+   |             ^^^^^^^^^^^^ caused by the macro expansion here
    |
    = note: the usage of `duplicate!` is likely invalid in expression context
+help: you might be missing a semicolon here
+   |
+LL |     let _ = #[duplicate]; "Hello, world!";
+   |                         +
 
 error: macro expansion ignores token `,` and any following
   --> $DIR/attr-invalid-exprs.rs:24:9
    |
 LL |         #[duplicate]
-   |         ^^^^^^^^^^^^- help: you might be missing a semicolon here: `;`
-   |         |
-   |         caused by the macro expansion here
+   |         ^^^^^^^^^^^^ caused by the macro expansion here
    |
    = note: the usage of `duplicate!` is likely invalid in expression context
+help: you might be missing a semicolon here
+   |
+LL |         #[duplicate];
+   |                     +
 
 error: aborting due to 3 previous errors
 
index 5531b32362125b4a4ed227dab4a785b9b3cb08d3..9e40e4d9ba63e92d243403451274948859aa7ea0 100644 (file)
@@ -53,19 +53,19 @@ pub fn foo11(input: TokenStream) -> TokenStream { input }
 pub fn foo12(input: TokenStream) -> TokenStream { input }
 
 #[proc_macro_derive(d13, attributes("a"))]
-//~^ ERROR: not a meta item
+//~^ ERROR: attribute must be a meta item, not a literal
 pub fn foo13(input: TokenStream) -> TokenStream { input }
 
 #[proc_macro_derive(d14, attributes(a = ""))]
-//~^ ERROR: must only be one word
+//~^ ERROR: attribute must only be a single word
 pub fn foo14(input: TokenStream) -> TokenStream { input }
 
 #[proc_macro_derive(d15, attributes(m::a))]
-//~^ ERROR: must only be one word
+//~^ ERROR: attribute must only be a single word
 pub fn foo15(input: TokenStream) -> TokenStream { input }
 
 #[proc_macro_derive(d16, attributes(a(b)))]
-//~^ ERROR: must only be one word
+//~^ ERROR: attribute must only be a single word
 pub fn foo16(input: TokenStream) -> TokenStream { input }
 
 #[proc_macro_derive(d17, attributes(self))]
index 021e7cad09b695c7e1bc72cece3b99d61431cbe9..3269aaf7f917eff367e0ac424f85b0aa802e04ec 100644 (file)
@@ -70,25 +70,25 @@ error: attribute must be of form: `attributes(foo, bar)`
 LL | #[proc_macro_derive(d12, attributes)]
    |                          ^^^^^^^^^^
 
-error: not a meta item
+error: attribute must be a meta item, not a literal
   --> $DIR/attribute.rs:55:37
    |
 LL | #[proc_macro_derive(d13, attributes("a"))]
    |                                     ^^^
 
-error: must only be one word
+error: attribute must only be a single word
   --> $DIR/attribute.rs:59:37
    |
 LL | #[proc_macro_derive(d14, attributes(a = ""))]
    |                                     ^^^^^^
 
-error: must only be one word
+error: attribute must only be a single word
   --> $DIR/attribute.rs:63:37
    |
 LL | #[proc_macro_derive(d15, attributes(m::a))]
    |                                     ^^^^
 
-error: must only be one word
+error: attribute must only be a single word
   --> $DIR/attribute.rs:67:37
    |
 LL | #[proc_macro_derive(d16, attributes(a(b)))]
index c6c4695fd9c43ee3093272a895cd3ff6f70b74af..0004f2fe17f01ebfb65aaabbd86b376482eee382 100644 (file)
@@ -26,21 +26,25 @@ error: macro expansion ignores token `hello` and any following
   --> $DIR/expand-expr.rs:115:47
    |
 LL | expand_expr_is!("string", echo_tts!("string"; hello));
-   |                           --------------------^^^^^-- help: you might be missing a semicolon here: `;`
-   |                           |
-   |                           caused by the macro expansion here
+   |                           --------------------^^^^^- caused by the macro expansion here
    |
    = note: the usage of `echo_tts!` is likely invalid in expression context
+help: you might be missing a semicolon here
+   |
+LL | expand_expr_is!("string", echo_tts!("string"; hello););
+   |                                                     +
 
 error: macro expansion ignores token `;` and any following
   --> $DIR/expand-expr.rs:116:44
    |
 LL | expand_expr_is!("string", echo_pm!("string"; hello));
-   |                           -----------------^-------- help: you might be missing a semicolon here: `;`
-   |                           |
-   |                           caused by the macro expansion here
+   |                           -----------------^------- caused by the macro expansion here
    |
    = note: the usage of `echo_pm!` is likely invalid in expression context
+help: you might be missing a semicolon here
+   |
+LL | expand_expr_is!("string", echo_pm!("string"; hello););
+   |                                                    +
 
 error: recursion limit reached while expanding `recursive_expand!`
   --> $DIR/expand-expr.rs:124:16
index ac49e04e3c0a9ed21ddafd652569e9b9c48454be..14e5df21ef651a2e5d3c24e520770a77720b4105 100644 (file)
@@ -7,9 +7,6 @@ LL | #[derive(PartialOrd, AddImpl)]
    = help: the trait `PartialEq` is not implemented for `PriorityQueue<T>`
 note: required by a bound in `PartialOrd`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
-   |                                           ^^^^^^^^^^^^^^ required by this bound in `PartialOrd`
    = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: the trait bound `PriorityQueue<T>: Eq` is not satisfied
@@ -20,9 +17,6 @@ LL | #[derive(PartialOrd, AddImpl)]
    |
 note: required by a bound in `Ord`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub trait Ord: Eq + PartialOrd<Self> {
-   |                ^^ required by this bound in `Ord`
    = note: this error originates in the derive macro `AddImpl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: can't compare `T` with `T`
@@ -38,9 +32,6 @@ LL | #[derive(PartialOrd, AddImpl)]
    |          ^^^^^^^^^^
 note: required by a bound in `Ord`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub trait Ord: Eq + PartialOrd<Self> {
-   |                     ^^^^^^^^^^^^^^^^ required by this bound in `Ord`
    = note: this error originates in the derive macro `AddImpl` which comes from the expansion of the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 3 previous errors
index 65ce24e55229684d72a7d7c01e20b1c9c41afbae..a3b27fd7bcc1bd5997b83c9fb567a6a0b9973ca6 100644 (file)
@@ -144,11 +144,9 @@ LL |     parent_source_spans!($($tokens)*);
 ...
 LL |     one!("hello", "world");
    |     ---------------------- in this macro invocation
+  --> $SRC_DIR/core/src/result.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     -- similarly named tuple variant `Ok` defined here
+   = note: similarly named tuple variant `Ok` defined here
    |
    = note: this error originates in the macro `parent_source_spans` which comes from the expansion of the macro `one` (in Nightly builds, run with -Z macro-backtrace for more info)
 
@@ -160,11 +158,9 @@ LL |     parent_source_spans!($($tokens)*);
 ...
 LL |     two!("yay", "rust");
    |     ------------------- in this macro invocation
+  --> $SRC_DIR/core/src/result.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     -- similarly named tuple variant `Ok` defined here
+   = note: similarly named tuple variant `Ok` defined here
    |
    = note: this error originates in the macro `parent_source_spans` which comes from the expansion of the macro `two` (in Nightly builds, run with -Z macro-backtrace for more info)
 
@@ -176,11 +172,9 @@ LL |     parent_source_spans!($($tokens)*);
 ...
 LL |     three!("hip", "hop");
    |     -------------------- in this macro invocation
+  --> $SRC_DIR/core/src/result.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     -- similarly named tuple variant `Ok` defined here
+   = note: similarly named tuple variant `Ok` defined here
    |
    = note: this error originates in the macro `parent_source_spans` which comes from the expansion of the macro `three` (in Nightly builds, run with -Z macro-backtrace for more info)
 
index a534b9d5377adbecec406d3010981e73a020bf65..3c3f24d0ff22e319e72c930a6b0462aa69423db9 100644 (file)
@@ -72,22 +72,18 @@ error: cannot find derive macro `Dlone` in this scope
    |
 LL | #[derive(Dlone)]
    |          ^^^^^ help: a derive macro with a similar name exists: `Clone`
+  --> $SRC_DIR/core/src/clone.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL | pub macro Clone($item:item) {
-   | --------------- similarly named derive macro `Clone` defined here
+   = note: similarly named derive macro `Clone` defined here
 
 error: cannot find derive macro `Dlone` in this scope
   --> $DIR/resolve-error.rs:35:10
    |
 LL | #[derive(Dlone)]
    |          ^^^^^ help: a derive macro with a similar name exists: `Clone`
+  --> $SRC_DIR/core/src/clone.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL | pub macro Clone($item:item) {
-   | --------------- similarly named derive macro `Clone` defined here
+   = note: similarly named derive macro `Clone` defined here
 
 error: cannot find attribute `FooWithLongNan` in this scope
   --> $DIR/resolve-error.rs:32:3
index 59b3e44c74a52270e2e87b2d9f205072e2fd4b59..79f2001da005510f915eb3f696d550df0364f3c8 100644 (file)
@@ -14,9 +14,6 @@ LL | | }
    = note: unsafe function cannot be called generically without an unsafe block
 note: required by a bound in `ProcMacro::custom_derive`
   --> $SRC_DIR/proc_macro/src/bridge/client.rs:LL:COL
-   |
-LL |         expand: impl Fn(crate::TokenStream) -> crate::TokenStream + Copy,
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `ProcMacro::custom_derive`
 
 error: aborting due to previous error
 
index 914ad54ed0370513b3b5c1460d96277fa17948b2..3f04ba866b7d6952addcbf0faf54f006c94b903c 100644 (file)
@@ -2,6 +2,7 @@
 // ignore-pretty
 // aux-build:span-api-tests.rs
 // aux-build:span-test-macros.rs
+// compile-flags: -Ztranslate-remapped-path-to-local-path=yes
 
 #[macro_use]
 extern crate span_test_macros;
index 4cbf8869d0c59b4723857e55a21c45fd4adbbb96..070dc844563c9aabca3407b3442117c824d224a3 100644 (file)
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
 LL |     take_range(std::ops::Range { start: 0, end: 1 });
    |     ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |     |          |
-   |     |          expected reference, found struct `std::ops::Range`
+   |     |          expected reference, found struct `Range`
    |     |          help: consider borrowing here: `&std::ops::Range { start: 0, end: 1 }`
    |     arguments to this function are incorrect
    |
@@ -22,7 +22,7 @@ error[E0308]: mismatched types
 LL |     take_range(::std::ops::Range { start: 0, end: 1 });
    |     ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |     |          |
-   |     |          expected reference, found struct `std::ops::Range`
+   |     |          expected reference, found struct `Range`
    |     |          help: consider borrowing here: `&::std::ops::Range { start: 0, end: 1 }`
    |     arguments to this function are incorrect
    |
index 38df6e14496a626ef873498e4ae32f756c25cd3c..9eec169404cdf2e72373789c1fc88fdb1f222d6e 100644 (file)
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
 LL |     take_range(0..1);
    |     ---------- ^^^^
    |     |          |
-   |     |          expected reference, found struct `std::ops::Range`
+   |     |          expected reference, found struct `Range`
    |     |          help: consider borrowing here: `&(0..1)`
    |     arguments to this function are incorrect
    |
index 6badd998f9617ab4af6e8306e4f8199218f60d4d..d08d9b1345d4ad516edfeedd474037174d985e6c 100644 (file)
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
 LL |     demo(tell(1)..tell(10));
    |     ---- ^^^^^^^^^^^^^^^^^
    |     |    |
-   |     |    expected reference, found struct `std::ops::Range`
+   |     |    expected `&Range<usize>`, found struct `Range`
    |     |    help: consider borrowing here: `&(tell(1)..tell(10))`
    |     arguments to this function are incorrect
    |
@@ -22,7 +22,7 @@ error[E0308]: mismatched types
 LL |     demo(1..10);
    |     ---- ^^^^^
    |     |    |
-   |     |    expected reference, found struct `std::ops::Range`
+   |     |    expected `&Range<usize>`, found struct `Range`
    |     |    help: consider borrowing here: `&(1..10)`
    |     arguments to this function are incorrect
    |
index aaea91ce0cbae15aac806d8e64ab459fbd531233..3956390368f7f132ab5b975d168a06516ba8ae4f 100644 (file)
@@ -32,9 +32,6 @@ LL |     let range = *arr..;
    = help: the trait `Sized` is not implemented for `[{integer}]`
 note: required by a bound in `RangeFrom`
   --> $SRC_DIR/core/src/ops/range.rs:LL:COL
-   |
-LL | pub struct RangeFrom<Idx> {
-   |                      ^^^ required by this bound in `RangeFrom`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/reachable/auxiliary/issue-11225-1.rs b/src/test/ui/reachable/auxiliary/issue-11225-1.rs
new file mode 100644 (file)
index 0000000..2c6f899
--- /dev/null
@@ -0,0 +1,18 @@
+mod inner {
+    pub trait Trait {
+        fn f(&self) { f(); }
+        fn f_ufcs(&self) { f_ufcs(); }
+    }
+
+    impl Trait for isize {}
+
+    fn f() {}
+    fn f_ufcs() {}
+}
+
+pub fn foo<T: inner::Trait>(t: T) {
+    t.f();
+}
+pub fn foo_ufcs<T: inner::Trait>(t: T) {
+    T::f_ufcs(&t);
+}
diff --git a/src/test/ui/reachable/auxiliary/issue-11225-2.rs b/src/test/ui/reachable/auxiliary/issue-11225-2.rs
new file mode 100644 (file)
index 0000000..4381f0a
--- /dev/null
@@ -0,0 +1,28 @@
+use inner::Trait;
+
+mod inner {
+    pub struct Foo;
+    pub trait Trait {
+        fn f(&self);
+        fn f_ufcs(&self);
+    }
+
+    impl Trait for Foo {
+        fn f(&self) { }
+        fn f_ufcs(&self) { }
+    }
+}
+
+pub trait Outer {
+    fn foo<T: Trait>(&self, t: T) { t.f(); }
+    fn foo_ufcs<T: Trait>(&self, t: T) { T::f(&t); }
+}
+
+impl Outer for isize {}
+
+pub fn foo<T: Outer>(t: T) {
+    t.foo(inner::Foo);
+}
+pub fn foo_ufcs<T: Outer>(t: T) {
+    T::foo_ufcs(&t, inner::Foo)
+}
diff --git a/src/test/ui/reachable/auxiliary/issue-11225-3.rs b/src/test/ui/reachable/auxiliary/issue-11225-3.rs
new file mode 100644 (file)
index 0000000..266e42a
--- /dev/null
@@ -0,0 +1,28 @@
+trait PrivateTrait {
+    fn private_trait_method(&self);
+    fn private_trait_method_ufcs(&self);
+}
+
+struct PrivateStruct;
+
+impl PrivateStruct {
+    fn private_inherent_method(&self) { }
+    fn private_inherent_method_ufcs(&self) { }
+}
+
+impl PrivateTrait for PrivateStruct {
+    fn private_trait_method(&self) { }
+    fn private_trait_method_ufcs(&self) { }
+}
+
+#[inline]
+pub fn public_inlinable_function() {
+    PrivateStruct.private_trait_method();
+    PrivateStruct.private_inherent_method();
+}
+
+#[inline]
+pub fn public_inlinable_function_ufcs() {
+    PrivateStruct::private_trait_method(&PrivateStruct);
+    PrivateStruct::private_inherent_method(&PrivateStruct);
+}
diff --git a/src/test/ui/reachable/issue-11225-1.rs b/src/test/ui/reachable/issue-11225-1.rs
new file mode 100644 (file)
index 0000000..d1f2ea5
--- /dev/null
@@ -0,0 +1,11 @@
+// run-pass
+// aux-build:issue-11225-1.rs
+
+// pretty-expanded FIXME #23616
+
+extern crate issue_11225_1 as foo;
+
+pub fn main() {
+    foo::foo(1);
+    foo::foo_ufcs(1);
+}
diff --git a/src/test/ui/reachable/issue-11225-2.rs b/src/test/ui/reachable/issue-11225-2.rs
new file mode 100644 (file)
index 0000000..d41c754
--- /dev/null
@@ -0,0 +1,11 @@
+// run-pass
+// aux-build:issue-11225-2.rs
+
+// pretty-expanded FIXME #23616
+
+extern crate issue_11225_2 as foo;
+
+pub fn main() {
+    foo::foo(1);
+    foo::foo_ufcs(1);
+}
diff --git a/src/test/ui/reachable/issue-11225-3.rs b/src/test/ui/reachable/issue-11225-3.rs
new file mode 100644 (file)
index 0000000..e69496b
--- /dev/null
@@ -0,0 +1,11 @@
+// run-pass
+// aux-build:issue-11225-3.rs
+
+// pretty-expanded FIXME #23616
+
+extern crate issue_11225_3;
+
+pub fn main() {
+    issue_11225_3::public_inlinable_function();
+    issue_11225_3::public_inlinable_function_ufcs();
+}
index 1da29be43db864d627d9b905147687e68b935058..002dfe115b03f2f343f624377170c706334ea1db 100644 (file)
@@ -8,3 +8,4 @@ LL | fn f(x: S<u32>) {}
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0320`.
index 4d00a7083137782aba899be905d2dd4e9d34033e..dde8ad1b6b327615fe66c1c2c75a644275dd3477 100644 (file)
@@ -12,7 +12,7 @@ LL |     func(&mut iter.map(|x| x + 1))
 error[E0275]: overflow evaluating the requirement `Map<&mut Map<&mut Map<&mut Map<..., ...>, ...>, ...>, ...>: Iterator`
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_83150`)
-   = note: required for `&mut Map<&mut Map<&mut Map<..., ...>, ...>, ...>` to implement `Iterator`
+   = note: required for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<..., ...>, ...>, ...>, ...>, ...>, ...>, ...>` to implement `Iterator`
    = note: the full type name has been written to '$TEST_BUILD_DIR/recursion/issue-83150/issue-83150.long-type-hash.txt'
 
 error: aborting due to previous error; 1 warning emitted
index f2307899d3c47e0a074dcf4e7ab111d75b4e68b1..86ad6aa847c9fe5adfeb0947cd19d921ffe62b3d 100644 (file)
@@ -8,12 +8,9 @@ LL |     let Ok(x) = res;
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
 note: `Result<u32, &R<'_>>` defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
+  ::: $SRC_DIR/core/src/result.rs:LL:COL
    |
-LL | pub enum Result<T, E> {
-   | ---------------------
-...
-LL |     Err(#[stable(feature = "rust1", since = "1.0.0")] E),
-   |     ^^^ not covered
+   = note: not covered
    = note: the matched value is of type `Result<u32, &R<'_>>`
 help: you might want to use `if let` to ignore the variant that isn't matched
    |
index e0a1164211a2cad83dacf482db3542e60eb791e7..fd71248d9cb458fc53300679e1d72ea404b778e1 100644 (file)
@@ -1,3 +1,4 @@
+// normalize-stderr-test: "long-type-\d+" -> "long-type-hash"
 use std::cell::Cell;
 
 #[rustfmt::skip]
index 31b855c36bead701fb95d1399bda114653a697b5..157850693ab506ad96fd63ebed1062efe6ac83c5 100644 (file)
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-102374.rs:16:5
+  --> $DIR/issue-102374.rs:17:5
    |
 LL | ) -> i32 {
    |      --- expected `i32` because of return type
@@ -7,7 +7,8 @@ LL |     f
    |     ^ expected `i32`, found fn pointer
    |
    = note:    expected type `i32`
-           found fn pointer `for<'z1, 'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k, 'l, 'm, 'n, 'o, 'p, 'q, 'r, 's, 't, 'u, 'v, 'w, 'x, 'y, 'z, 'z0> fn(Cell<(&'z1 i32, &'a i32, &'b i32, &'c i32, &'d i32, &'e i32, &'f i32, &'g i32, &'h i32, &'i i32, &'j i32, &'k i32, &'l i32, &'m i32, &'n i32, &'o i32, &'p i32, &'q i32, &'r i32, &'s i32, &'t i32, &'u i32, &'v i32, &'w i32, &'x i32, &'y i32, &'z i32, &'z0 i32)>)`
+           found fn pointer `for<'z1, 'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k, 'l, 'm, 'n, 'o, 'p, 'q, 'r, 's, 't, 'u, 'v, 'w, 'x, 'y, 'z, 'z0> fn(Cell<...>)`
+           the full type name has been written to '$TEST_BUILD_DIR/regions/issue-102374/issue-102374.long-type-hash.txt'
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/resolve/issue-104700-inner_scope.rs b/src/test/ui/resolve/issue-104700-inner_scope.rs
new file mode 100644 (file)
index 0000000..e8f28c1
--- /dev/null
@@ -0,0 +1,11 @@
+fn main() {
+    let foo = 1;
+    {
+        let bar = 2;
+        let test_func = |x| x > 3;
+    }
+    if bar == 2 { //~ ERROR cannot find value
+        println!("yes");
+    }
+    test_func(1); //~ ERROR cannot find function
+}
diff --git a/src/test/ui/resolve/issue-104700-inner_scope.stderr b/src/test/ui/resolve/issue-104700-inner_scope.stderr
new file mode 100644 (file)
index 0000000..051b234
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0425]: cannot find value `bar` in this scope
+  --> $DIR/issue-104700-inner_scope.rs:7:8
+   |
+LL |     if bar == 2 {
+   |        ^^^
+   |
+help: the binding `bar` is available in a different scope in the same function
+  --> $DIR/issue-104700-inner_scope.rs:4:13
+   |
+LL |         let bar = 2;
+   |             ^^^
+
+error[E0425]: cannot find function `test_func` in this scope
+  --> $DIR/issue-104700-inner_scope.rs:10:5
+   |
+LL |     test_func(1);
+   |     ^^^^^^^^^ not found in this scope
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
index 939392733f0e9659de281625967ee497f98f9eb1..558e6b7b118d8221125e8cdd953d2ac1b9834bdd 100644 (file)
@@ -6,6 +6,10 @@ LL | fn foo(_x: K) {}
    |
    = help: the trait `Sized` is not implemented for `(dyn I + 'static)`
    = help: unsized fn params are gated as an unstable feature
+help: you can use `impl Trait` as the argument type
+   |
+LL | fn foo(_x: impl K) {}
+   |            ++++
 help: function arguments must have a statically known size, borrowed types always have a known size
    |
 LL | fn foo(_x: &K) {}
index f839dd927db999b883504950badb49cf32a914e8..42b43f825d10c28711b7f3f450da977f855124fe 100644 (file)
@@ -21,8 +21,8 @@ LL |         let mut N;
    |
 help: consider giving `N` an explicit type
    |
-LL |         let mut N: _;
-   |                  +++
+LL |         let mut N: /* Type */;
+   |                  ++++++++++++
 
 error: aborting due to 3 previous errors
 
index 9a2d61ea4054b52f83eb6075e074d3aea85fd09c..cf478210132ede5fbc5eeaffb7f8168dd08c27ef 100644 (file)
@@ -18,11 +18,9 @@ error[E0412]: cannot find type `Opiton` in this scope
    |
 LL | type B = Opiton<u8>; // Misspelled type name from the prelude.
    |          ^^^^^^ help: an enum with a similar name exists: `Option`
+  --> $SRC_DIR/core/src/option.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL | pub enum Option<T> {
-   | ------------------ similarly named enum `Option` defined here
+   = note: similarly named enum `Option` defined here
 
 error[E0412]: cannot find type `Baz` in this scope
   --> $DIR/levenshtein.rs:16:14
index 6d5d5bad9fe1a342f67b5b581035203fccda800d..964302e924c8ae7cdd987f2590bd4adfb52949e1 100644 (file)
@@ -28,9 +28,6 @@ LL |     std::mem::size_of(u16);
    |
 note: function defined here
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL | pub const fn size_of<T>() -> usize {
-   |              ^^^^^^^
 help: remove the extra argument
    |
 LL |     std::mem::size_of();
index 9577952119adb2c480bc9b2caf5731574304da51..a19750cc73aa559b5d33ae614d3cf920134b95c0 100644 (file)
@@ -9,9 +9,6 @@ LL | fn can_parse_zero_as_f32() -> Result<f32, ParseFloatError> {
    = note: required for `Result<f32, ParseFloatError>` to implement `Termination`
 note: required by a bound in `assert_test_result`
   --> $SRC_DIR/test/src/lib.rs:LL:COL
-   |
-LL | pub fn assert_test_result<T: Termination>(result: T) -> Result<(), String> {
-   |                              ^^^^^^^^^^^ required by this bound in `assert_test_result`
    = note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
index 9cc20a7bf3144ffa05e86a1452db184d4a4fbc9e..07991af6ef97c60bd5314f186fdcee1175de73c6 100644 (file)
@@ -6,6 +6,11 @@ LL |     for (n, mut m) in &tups {
    |             |
    |             data moved here
    |             move occurs because `m` has type `Foo`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     for (n, ref mut m) in &tups {
+   |             +++
 
 error: aborting due to previous error
 
index 06699b947be40f2bb66426cfde35e04c8de7d81e..e97fdcce1c18f0913a55090db7eb2d05ffd80ec2 100644 (file)
@@ -8,11 +8,6 @@ LL |     let _ = dbg!(a);
 LL |     let _ = dbg!(a);
    |                  ^ value used here after move
    |
-help: borrow this binding in the pattern to avoid moving the value
-  --> $SRC_DIR/std/src/macros.rs:LL:COL
-   |
-LL |             ref tmp => {
-   |             +++
 
 error: aborting due to previous error
 
index 91c001151803a35d8fe341619c90db05b4e71002..3028f8dbdbf771e947270f6fbfa874a561dcaf7f 100644 (file)
@@ -1516,7 +1516,7 @@ error[E0308]: mismatched types
   --> $DIR/disallowed-positions.rs:157:8
    |
 LL |     if true..(let 0 = 0) {}
-   |        ^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+   |        ^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<bool>`
@@ -1545,7 +1545,7 @@ error[E0308]: mismatched types
 LL |     if let Range { start: _, end: _ } = true..true && false {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
    |            |
-   |            expected `bool`, found struct `std::ops::Range`
+   |            expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<_>`
@@ -1554,7 +1554,7 @@ error[E0308]: mismatched types
   --> $DIR/disallowed-positions.rs:171:8
    |
 LL |     if let Range { start: _, end: _ } = true..true && false {}
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<bool>`
@@ -1565,7 +1565,7 @@ error[E0308]: mismatched types
 LL |     if let Range { start: _, end: _ } = true..true || false {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
    |            |
-   |            expected `bool`, found struct `std::ops::Range`
+   |            expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<_>`
@@ -1574,7 +1574,7 @@ error[E0308]: mismatched types
   --> $DIR/disallowed-positions.rs:175:8
    |
 LL |     if let Range { start: _, end: _ } = true..true || false {}
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<bool>`
@@ -1585,7 +1585,7 @@ error[E0308]: mismatched types
 LL |     if let Range { start: F, end } = F..|| true {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `fn() -> bool`
    |            |
-   |            expected fn pointer, found struct `std::ops::Range`
+   |            expected fn pointer, found struct `Range`
    |
    = note: expected fn pointer `fn() -> bool`
                   found struct `std::ops::Range<_>`
@@ -1607,7 +1607,7 @@ error[E0308]: mismatched types
   --> $DIR/disallowed-positions.rs:182:8
    |
 LL |     if let Range { start: F, end } = F..|| true {}
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<bool>`
@@ -1618,7 +1618,7 @@ error[E0308]: mismatched types
 LL |     if let Range { start: true, end } = t..&&false {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `&&bool`
    |            |
-   |            expected `bool`, found struct `std::ops::Range`
+   |            expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<_>`
@@ -1639,7 +1639,7 @@ error[E0308]: mismatched types
   --> $DIR/disallowed-positions.rs:190:8
    |
 LL |     if let Range { start: true, end } = t..&&false {}
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<bool>`
@@ -1710,7 +1710,7 @@ error[E0308]: mismatched types
   --> $DIR/disallowed-positions.rs:249:11
    |
 LL |     while true..(let 0 = 0) {}
-   |           ^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+   |           ^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<bool>`
@@ -1739,7 +1739,7 @@ error[E0308]: mismatched types
 LL |     while let Range { start: _, end: _ } = true..true && false {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
    |               |
-   |               expected `bool`, found struct `std::ops::Range`
+   |               expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<_>`
@@ -1748,7 +1748,7 @@ error[E0308]: mismatched types
   --> $DIR/disallowed-positions.rs:263:11
    |
 LL |     while let Range { start: _, end: _ } = true..true && false {}
-   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<bool>`
@@ -1759,7 +1759,7 @@ error[E0308]: mismatched types
 LL |     while let Range { start: _, end: _ } = true..true || false {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
    |               |
-   |               expected `bool`, found struct `std::ops::Range`
+   |               expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<_>`
@@ -1768,7 +1768,7 @@ error[E0308]: mismatched types
   --> $DIR/disallowed-positions.rs:267:11
    |
 LL |     while let Range { start: _, end: _ } = true..true || false {}
-   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<bool>`
@@ -1779,7 +1779,7 @@ error[E0308]: mismatched types
 LL |     while let Range { start: F, end } = F..|| true {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `fn() -> bool`
    |               |
-   |               expected fn pointer, found struct `std::ops::Range`
+   |               expected fn pointer, found struct `Range`
    |
    = note: expected fn pointer `fn() -> bool`
                   found struct `std::ops::Range<_>`
@@ -1801,7 +1801,7 @@ error[E0308]: mismatched types
   --> $DIR/disallowed-positions.rs:274:11
    |
 LL |     while let Range { start: F, end } = F..|| true {}
-   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<bool>`
@@ -1812,7 +1812,7 @@ error[E0308]: mismatched types
 LL |     while let Range { start: true, end } = t..&&false {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `&&bool`
    |               |
-   |               expected `bool`, found struct `std::ops::Range`
+   |               expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<_>`
@@ -1833,7 +1833,7 @@ error[E0308]: mismatched types
   --> $DIR/disallowed-positions.rs:282:11
    |
 LL |     while let Range { start: true, end } = t..&&false {}
-   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<bool>`
@@ -1883,7 +1883,7 @@ error[E0308]: mismatched types
 LL |     (let Range { start: _, end: _ } = true..true || false);
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
    |          |
-   |          expected `bool`, found struct `std::ops::Range`
+   |          expected `bool`, found struct `Range`
    |
    = note: expected type `bool`
             found struct `std::ops::Range<_>`
index c64930db9bee2ee1b695337ff1f12ed29c797e2e..f9d0d1f7875fb891b4016ed2078de369beeecca8 100644 (file)
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `NonConstImpl: ~const ConstDefaultFn` is not satisfied
-  --> $DIR/const-default-method-bodies.rs:24:5
+  --> $DIR/const-default-method-bodies.rs:24:18
    |
 LL |     NonConstImpl.a();
-   |     ^^^^^^^^^^^^ - required by a bound introduced by this call
-   |     |
-   |     the trait `~const ConstDefaultFn` is not implemented for `NonConstImpl`
+   |                  ^ the trait `~const ConstDefaultFn` is not implemented for `NonConstImpl`
    |
 note: the trait `ConstDefaultFn` is implemented for `NonConstImpl`, but that implementation is not `const`
   --> $DIR/const-default-method-bodies.rs:24:5
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-impl-trait.rs b/src/test/ui/rfc-2632-const-trait-impl/const-impl-trait.rs
new file mode 100644 (file)
index 0000000..0622f96
--- /dev/null
@@ -0,0 +1,55 @@
+// check-pass
+#![allow(incomplete_features)]
+#![feature(
+    associated_type_bounds,
+    const_trait_impl,
+    const_cmp,
+    return_position_impl_trait_in_trait,
+)]
+
+use std::marker::Destruct;
+
+const fn cmp(a: &impl ~const PartialEq) -> bool {
+    a == a
+}
+
+const fn wrap(x: impl ~const PartialEq + ~const Destruct)
+    -> impl ~const PartialEq + ~const Destruct
+{
+    x
+}
+
+#[const_trait]
+trait Foo {
+    fn huh() -> impl ~const PartialEq + ~const Destruct + Copy;
+}
+
+impl const Foo for () {
+    fn huh() -> impl ~const PartialEq + ~const Destruct + Copy {
+        123
+    }
+}
+
+const _: () = {
+    assert!(cmp(&0xDEADBEEFu32));
+    assert!(cmp(&()));
+    assert!(wrap(123) == wrap(123));
+    assert!(wrap(123) != wrap(456));
+    let x = <() as Foo>::huh();
+    assert!(x == x);
+};
+
+#[const_trait]
+trait T {}
+struct S;
+impl const T for S {}
+
+const fn rpit() -> impl ~const T { S }
+
+const fn apit(_: impl ~const T + ~const Destruct) {}
+
+const fn rpit_assoc_bound() -> impl IntoIterator<Item: ~const T> { Some(S) }
+
+const fn apit_assoc_bound(_: impl IntoIterator<Item: ~const T> + ~const Destruct) {}
+
+fn main() {}
index 925ae53e3249961c776b16e6d3e0de54ecb03ffc..633b7cc255a52a817a20a02d03afbdf079247331 100644 (file)
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `cross_crate::NonConst: ~const cross_crate::MyTrait` is not satisfied
-  --> $DIR/cross-crate.rs:17:5
+  --> $DIR/cross-crate.rs:17:14
    |
 LL |     NonConst.func();
-   |     ^^^^^^^^ ---- required by a bound introduced by this call
-   |     |
-   |     the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
+   |              ^^^^ the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
    |
 note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst`, but that implementation is not `const`
   --> $DIR/cross-crate.rs:17:5
index 11db0c2b8f290bff0447a0cc2a7cb3a6b2ac6e7d..9e97d3f11376014a3f08bd9eb596d664e70c0e4a 100644 (file)
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `cross_crate::NonConst: cross_crate::MyTrait` is not satisfied
-  --> $DIR/cross-crate.rs:17:5
+  --> $DIR/cross-crate.rs:17:14
    |
 LL |     NonConst.func();
-   |     ^^^^^^^^ ---- required by a bound introduced by this call
-   |     |
-   |     the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
+   |              ^^^^ the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
    |
 note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst`, but that implementation is not `const`
   --> $DIR/cross-crate.rs:17:5
index c2c16921c2eb233fb9ef3ea76cc96e0f25dddd26..21ecddaffbb6517c64933d1c5114bed8bd42eb38 100644 (file)
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `(): ~const Tr` is not satisfied
-  --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:9
+  --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:12
    |
 LL |         ().a()
-   |         ^^ - required by a bound introduced by this call
-   |         |
-   |         the trait `~const Tr` is not implemented for `()`
+   |            ^ the trait `~const Tr` is not implemented for `()`
    |
 note: the trait `Tr` is implemented for `()`, but that implementation is not `const`
   --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:9
index b52eb2c0332fd460e93f5f2b5d1586e4036a6c9f..13fc719f28c5c2ad681a357c78c1df7170f691d7 100644 (file)
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `T: ~const Foo` is not satisfied
-  --> $DIR/super-traits-fail-2.rs:15:5
+  --> $DIR/super-traits-fail-2.rs:15:7
    |
 LL |     x.a();
-   |     ^ - required by a bound introduced by this call
-   |     |
-   |     the trait `~const Foo` is not implemented for `T`
+   |       ^ the trait `~const Foo` is not implemented for `T`
    |
 note: the trait `Foo` is implemented for `T`, but that implementation is not `const`
   --> $DIR/super-traits-fail-2.rs:15:5
index b52eb2c0332fd460e93f5f2b5d1586e4036a6c9f..13fc719f28c5c2ad681a357c78c1df7170f691d7 100644 (file)
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `T: ~const Foo` is not satisfied
-  --> $DIR/super-traits-fail-2.rs:15:5
+  --> $DIR/super-traits-fail-2.rs:15:7
    |
 LL |     x.a();
-   |     ^ - required by a bound introduced by this call
-   |     |
-   |     the trait `~const Foo` is not implemented for `T`
+   |       ^ the trait `~const Foo` is not implemented for `T`
    |
 note: the trait `Foo` is implemented for `T`, but that implementation is not `const`
   --> $DIR/super-traits-fail-2.rs:15:5
index 5bd52151f42acdc097cd97516a038ad44ff31c2f..95f7aaba0fc389fe5d8c895e6a319947bb554829 100644 (file)
@@ -1,23 +1,6 @@
 #![feature(const_trait_impl)]
 #![feature(associated_type_bounds)]
 
-#[const_trait]
-trait T {}
-struct S;
-impl T for S {}
-
-fn rpit() -> impl ~const T { S }
-//~^ ERROR `~const` is not allowed
-
-fn apit(_: impl ~const T) {}
-//~^ ERROR `~const` is not allowed
-
-fn rpit_assoc_bound() -> impl IntoIterator<Item: ~const T> { Some(S) }
-//~^ ERROR `~const` is not allowed
-
-fn apit_assoc_bound(_: impl IntoIterator<Item: ~const T>) {}
-//~^ ERROR `~const` is not allowed
-
 struct TildeQuestion<T: ~const ?Sized>(std::marker::PhantomData<T>);
 //~^ ERROR `~const` and `?` are mutually exclusive
 
index 84867cb4a5342cfb7cd10fa0b37dfd568484da7b..d20f146df3f1a102fa36cbe168734f1cec616f91 100644 (file)
@@ -1,40 +1,8 @@
-error: `~const` is not allowed here
-  --> $DIR/tilde-const-invalid-places.rs:9:19
-   |
-LL | fn rpit() -> impl ~const T { S }
-   |                   ^^^^^^^^
-   |
-   = note: `impl Trait`s cannot have `~const` trait bounds
-
-error: `~const` is not allowed here
-  --> $DIR/tilde-const-invalid-places.rs:12:17
-   |
-LL | fn apit(_: impl ~const T) {}
-   |                 ^^^^^^^^
-   |
-   = note: `impl Trait`s cannot have `~const` trait bounds
-
-error: `~const` is not allowed here
-  --> $DIR/tilde-const-invalid-places.rs:15:50
-   |
-LL | fn rpit_assoc_bound() -> impl IntoIterator<Item: ~const T> { Some(S) }
-   |                                                  ^^^^^^^^
-   |
-   = note: `impl Trait`s cannot have `~const` trait bounds
-
-error: `~const` is not allowed here
-  --> $DIR/tilde-const-invalid-places.rs:18:48
-   |
-LL | fn apit_assoc_bound(_: impl IntoIterator<Item: ~const T>) {}
-   |                                                ^^^^^^^^
-   |
-   = note: `impl Trait`s cannot have `~const` trait bounds
-
 error: `~const` and `?` are mutually exclusive
-  --> $DIR/tilde-const-invalid-places.rs:21:25
+  --> $DIR/tilde-const-invalid-places.rs:4:25
    |
 LL | struct TildeQuestion<T: ~const ?Sized>(std::marker::PhantomData<T>);
    |                         ^^^^^^^^^^^^^
 
-error: aborting due to 5 previous errors
+error: aborting due to previous error
 
index eea94643e0a0aeb427d4472e6226097c3d6d60b3..5d4d692b2cffb7e5c39ccc0754002018c7ca9ed1 100644 (file)
@@ -26,11 +26,8 @@ note: an implementation of `Add<_>` might be missing for `World`
    |
 LL | enum World {
    | ^^^^^^^^^^ must implement `Add<_>`
-note: the following trait must be implemented
+note: the trait `Add` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait Add<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0369]: cannot add `String` to `&str`
   --> $DIR/issue-39018.rs:11:22
index bbb4a93623b144b8d182c675c292b2f3a4e25511..8014f3796250a1c5c217a24c6e0977c089abbf88 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -Z simulate-remapped-rust-src-base=/rustc/xyz -Z translate-remapped-path-to-local-path=no -Z ui-testing=no
+// compile-flags: -Z ui-testing=no
 
 struct MyError;
 impl std::error::Error for MyError {}
index 04e2b46c31738f60a3719ca04722b6205bb89d48..6c7ea007ee03e4cb6fa00d649597517d10c3c8ad 100644 (file)
@@ -7,6 +7,7 @@ error[E0277]: `MyError` doesn't implement `std::fmt::Display`
   = help: the trait `std::fmt::Display` is not implemented for `MyError`
   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
 note: required by a bound in `std::error::Error`
+ --> $SRC_DIR/core/src/error.rs:LL:COL
 
 error[E0277]: `MyError` doesn't implement `Debug`
  --> $DIR/issue-71363.rs:4:6
@@ -17,6 +18,7 @@ error[E0277]: `MyError` doesn't implement `Debug`
   = help: the trait `Debug` is not implemented for `MyError`
   = note: add `#[derive(Debug)]` to `MyError` or manually `impl Debug for MyError`
 note: required by a bound in `std::error::Error`
+ --> $SRC_DIR/core/src/error.rs:LL:COL
 help: consider annotating `MyError` with `#[derive(Debug)]`
   |
 3 | #[derive(Debug)]
index 7d240589a3f133647b2b85ccfe61f504d6f47bf7..f6efbe40bc23457047427cfc5a90cb9af723d3f6 100644 (file)
@@ -9,8 +9,8 @@ LL |     x.0;
    |
 help: consider giving `x` an explicit type
    |
-LL |     let mut x: _ = Default::default();
-   |              +++
+LL |     let mut x: /* Type */ = Default::default();
+   |              ++++++++++++
 
 error[E0282]: type annotations needed
   --> $DIR/method-and-field-eager-resolution.rs:11:9
@@ -23,8 +23,8 @@ LL |     x[0];
    |
 help: consider giving `x` an explicit type
    |
-LL |     let mut x: _ = Default::default();
-   |              +++
+LL |     let mut x: /* Type */ = Default::default();
+   |              ++++++++++++
 
 error: aborting due to 2 previous errors
 
index b76a3ab307ae458bc091ec8a5b0f22099e82a962..48a2e763af615a23e15104e5ffcf57f0c127cf30 100644 (file)
@@ -6,9 +6,6 @@ LL |     let _: Result<(), String> = Ok();
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^
 help: provide the argument
    |
 LL |     let _: Result<(), String> = Ok(());
index 33ca7a2c210d680ec7d7f664fae9aca585c0b029..37788612f4371dd6ce95af228211a59799424d6a 100644 (file)
@@ -27,7 +27,7 @@ LL | default impl<T> Foo for T {
    | ^^^^^^^^^^^^^^^^---^^^^^-
    | |
    | unsatisfied trait bound introduced here
-note: the following trait must be implemented
+note: the trait `Foo` must be implemented
   --> $DIR/specialization-trait-not-implemented.rs:7:1
    |
 LL | trait Foo {
index e64f2acbd351d1bc2d160c860e06074a19332679..2f02a24960e01af20612e1bd026baf58e6df45f9 100644 (file)
@@ -6,9 +6,6 @@ LL |     let _ = std::thread::thread_info::current_thread();
    |
 note: the module `thread_info` is defined here
   --> $SRC_DIR/std/src/thread/mod.rs:LL:COL
-   |
-LL | use crate::sys_common::thread_info;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 9db9fcf40f82c0d34bddd0eb2d2322eff055090f..8c5d0b9609627f04d183d7223c52d5bb7006d4b0 100644 (file)
@@ -2,37 +2,49 @@ error[E0507]: cannot move out of a shared reference
   --> $DIR/std-uncopyable-atomics.rs:9:13
    |
 LL |     let x = *&x;
-   |             ^^^
-   |             |
-   |             move occurs because value has type `std::sync::atomic::AtomicBool`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&*&x`
+   |             ^^^ move occurs because value has type `std::sync::atomic::AtomicBool`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let x = *&x;
+LL +     let x = &x;
+   |
 
 error[E0507]: cannot move out of a shared reference
   --> $DIR/std-uncopyable-atomics.rs:11:13
    |
 LL |     let x = *&x;
-   |             ^^^
-   |             |
-   |             move occurs because value has type `std::sync::atomic::AtomicIsize`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&*&x`
+   |             ^^^ move occurs because value has type `std::sync::atomic::AtomicIsize`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let x = *&x;
+LL +     let x = &x;
+   |
 
 error[E0507]: cannot move out of a shared reference
   --> $DIR/std-uncopyable-atomics.rs:13:13
    |
 LL |     let x = *&x;
-   |             ^^^
-   |             |
-   |             move occurs because value has type `std::sync::atomic::AtomicUsize`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&*&x`
+   |             ^^^ move occurs because value has type `std::sync::atomic::AtomicUsize`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let x = *&x;
+LL +     let x = &x;
+   |
 
 error[E0507]: cannot move out of a shared reference
   --> $DIR/std-uncopyable-atomics.rs:15:13
    |
 LL |     let x = *&x;
-   |             ^^^
-   |             |
-   |             move occurs because value has type `std::sync::atomic::AtomicPtr<usize>`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&*&x`
+   |             ^^^ move occurs because value has type `std::sync::atomic::AtomicPtr<usize>`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let x = *&x;
+LL +     let x = &x;
+   |
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/stdlib-unit-tests/issue-21058.rs b/src/test/ui/stdlib-unit-tests/issue-21058.rs
new file mode 100644 (file)
index 0000000..6facf0b
--- /dev/null
@@ -0,0 +1,64 @@
+// run-pass
+#![allow(dead_code)]
+
+use std::fmt::Debug;
+
+struct NT(str);
+struct DST { a: u32, b: str }
+
+macro_rules! check {
+    (val: $ty_of:expr, $expected:expr) => {
+        assert_eq!(type_name_of_val($ty_of), $expected);
+    };
+    ($ty:ty, $expected:expr) => {
+        assert_eq!(std::any::type_name::<$ty>(), $expected);
+    };
+}
+
+fn main() {
+    // type_name should support unsized types
+    check!([u8], "[u8]");
+    check!(str, "str");
+    check!(dyn Send, "dyn core::marker::Send");
+    check!(NT, "issue_21058::NT");
+    check!(DST, "issue_21058::DST");
+    check!(&i32, "&i32");
+    check!(&'static i32, "&i32");
+    check!((i32, u32), "(i32, u32)");
+    check!(val: foo(), "issue_21058::Foo");
+    check!(val: Foo::new, "issue_21058::Foo::new");
+    check!(val:
+        <Foo as Debug>::fmt,
+        "<issue_21058::Foo as core::fmt::Debug>::fmt"
+    );
+    check!(val: || {}, "issue_21058::main::{{closure}}");
+    bar::<i32>();
+}
+
+trait Trait {
+    type Assoc;
+}
+
+impl Trait for i32 {
+    type Assoc = String;
+}
+
+fn bar<T: Trait>() {
+    check!(T::Assoc, "alloc::string::String");
+    check!(T, "i32");
+}
+
+fn type_name_of_val<T>(_: T) -> &'static str {
+    std::any::type_name::<T>()
+}
+
+#[derive(Debug)]
+struct Foo;
+
+impl Foo {
+    fn new() -> Self { Foo }
+}
+
+fn foo() -> impl Debug {
+    Foo
+}
index 019305def2932ec3ce768e2895b19d86cf07cccb..cb1a6fcacfc9b5d24d8d6caae1a5f53e63304074 100644 (file)
@@ -24,9 +24,6 @@ LL |     let _ = s.get(4);
    = help: the trait `SliceIndex<[T]>` is implemented for `usize`
 note: required by a bound in `core::str::<impl str>::get`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
-   |
-LL |     pub const fn get<I: ~const SliceIndex<str>>(&self, i: I) -> Option<&I::Output> {
-   |                         ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `core::str::<impl str>::get`
 
 error[E0277]: the type `str` cannot be indexed by `{integer}`
   --> $DIR/str-idx.rs:5:29
@@ -42,9 +39,6 @@ LL |     let _ = s.get_unchecked(4);
    = help: the trait `SliceIndex<[T]>` is implemented for `usize`
 note: required by a bound in `core::str::<impl str>::get_unchecked`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
-   |
-LL |     pub const unsafe fn get_unchecked<I: ~const SliceIndex<str>>(&self, i: I) -> &I::Output {
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `core::str::<impl str>::get_unchecked`
 
 error[E0277]: the type `str` cannot be indexed by `char`
   --> $DIR/str-idx.rs:6:19
index b165c482590a253babc0ea50d99126542b863e65..ca4b86ba3065b79af5c536f86b0f061e3743cd8e 100644 (file)
@@ -48,9 +48,6 @@ LL |     s.get_mut(1);
    = help: the trait `SliceIndex<[T]>` is implemented for `usize`
 note: required by a bound in `core::str::<impl str>::get_mut`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
-   |
-LL |     pub const fn get_mut<I: ~const SliceIndex<str>>(&mut self, i: I) -> Option<&mut I::Output> {
-   |                             ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `core::str::<impl str>::get_mut`
 
 error[E0277]: the type `str` cannot be indexed by `{integer}`
   --> $DIR/str-mut-idx.rs:11:25
@@ -66,9 +63,6 @@ LL |     s.get_unchecked_mut(1);
    = help: the trait `SliceIndex<[T]>` is implemented for `usize`
 note: required by a bound in `core::str::<impl str>::get_unchecked_mut`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
-   |
-LL |     pub const unsafe fn get_unchecked_mut<I: ~const SliceIndex<str>>(
-   |                                              ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `core::str::<impl str>::get_unchecked_mut`
 
 error[E0277]: the type `str` cannot be indexed by `char`
   --> $DIR/str-mut-idx.rs:13:7
index f4fd655e698b08171f3d6375d673c6d098f9ab5d..9b751d1b66c54d79547acb96e05a76068f2079e1 100644 (file)
@@ -18,7 +18,7 @@ error[E0308]: mismatched types
   --> $DIR/struct-record-suggestion.rs:23:20
    |
 LL |     let q = B { b: 1..Default::default() };
-   |                    ^^^^^^^^^^^^^^^^^^^^^ expected `u32`, found struct `std::ops::Range`
+   |                    ^^^^^^^^^^^^^^^^^^^^^ expected `u32`, found struct `Range`
    |
    = note: expected type `u32`
             found struct `std::ops::Range<{integer}>`
diff --git a/src/test/ui/structs/unresolved-struct-with-fru.rs b/src/test/ui/structs/unresolved-struct-with-fru.rs
new file mode 100644 (file)
index 0000000..c9fdca4
--- /dev/null
@@ -0,0 +1,12 @@
+struct S {
+    a: u32,
+}
+
+fn main() {
+    let s1 = S { a: 1 };
+
+    let _ = || {
+        let s2 = Oops { a: 2, ..s1 };
+        //~^ ERROR cannot find struct, variant or union type `Oops` in this scope
+    };
+}
diff --git a/src/test/ui/structs/unresolved-struct-with-fru.stderr b/src/test/ui/structs/unresolved-struct-with-fru.stderr
new file mode 100644 (file)
index 0000000..a5796a2
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0422]: cannot find struct, variant or union type `Oops` in this scope
+  --> $DIR/unresolved-struct-with-fru.rs:9:18
+   |
+LL |         let s2 = Oops { a: 2, ..s1 };
+   |                  ^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0422`.
index 0a91c442d2c6f0e45dd21bc6d8212c9dc8b7265e..44a39efdf25425015543ec99292f7e9c78ad7ed3 100644 (file)
@@ -13,9 +13,6 @@ LL |     let _: Option<(i32, bool)> = Some(1, 2);
                found type `{integer}`
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^
 help: remove the extra argument
    |
 LL |     let _: Option<(i32, bool)> = Some(/* (i32, bool) */);
@@ -52,9 +49,6 @@ LL |     let _: Option<(i8,)> = Some();
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^
 help: provide the argument
    |
 LL |     let _: Option<(i8,)> = Some(/* (i8,) */);
@@ -72,9 +66,6 @@ LL |     let _: Option<(i32,)> = Some(5_usize);
                found type `usize`
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^
 
 error[E0308]: mismatched types
   --> $DIR/args-instead-of-tuple-errors.rs:17:34
@@ -88,9 +79,6 @@ LL |     let _: Option<(i32,)> = Some((5_usize));
                found type `usize`
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^
 
 error: aborting due to 5 previous errors
 
index 20f9e5259a4e2c050427970dec7b033a07d699ba..c8499010d6896365bccf42f5689638ca088156e0 100644 (file)
@@ -6,9 +6,6 @@ LL |     let _: Result<(i32, i8), ()> = Ok(1, 2);
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^
 help: wrap these arguments in parentheses to construct a tuple
    |
 LL |     let _: Result<(i32, i8), ()> = Ok((1, 2));
@@ -22,9 +19,6 @@ LL |     let _: Option<(i32, i8, &'static str)> = Some(1, 2, "hi");
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^
 help: wrap these arguments in parentheses to construct a tuple
    |
 LL |     let _: Option<(i32, i8, &'static str)> = Some((1, 2, "hi"));
@@ -38,9 +32,6 @@ LL |     let _: Option<()> = Some();
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^
 help: provide the argument
    |
 LL |     let _: Option<()> = Some(());
@@ -58,9 +49,6 @@ LL |     let _: Option<(i32,)> = Some(3);
                found type `{integer}`
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^
 help: use a trailing comma to create a tuple with one element
    |
 LL |     let _: Option<(i32,)> = Some((3,));
@@ -78,9 +66,6 @@ LL |     let _: Option<(i32,)> = Some((3));
                found type `{integer}`
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^
 help: use a trailing comma to create a tuple with one element
    |
 LL |     let _: Option<(i32,)> = Some((3,));
index e15e45d86b992c64fe39afe87742e96a62a18b9e..e2129b4502abea13774d1917bbf23c3eedbb8bee 100644 (file)
@@ -10,11 +10,8 @@ LL |     let _x: Option<Struct> = foo.map(|s| bar(&s));
 LL |     let _y = foo;
    |              ^^^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `foo`
+note: `Option::<T>::map` takes ownership of the receiver `self`, which moves `foo`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     pub const fn map<U, F>(self, f: F) -> Option<U>
-   |                            ^^^^
 
 error: aborting due to previous error
 
index 54122cb7360b438912caf6e4aafc7bcdf7f050b9..b871c9b45a56c7c675c5d8ec6476c41298585bc0 100644 (file)
@@ -15,11 +15,9 @@ error: cannot find attribute `tests` in this scope
    |
 LL | #[tests]
    |   ^^^^^ help: an attribute macro with a similar name exists: `test`
+  --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-   |
-LL |     pub macro test($item:item) {
-   |     -------------- similarly named attribute macro `test` defined here
+   = note: similarly named attribute macro `test` defined here
 
 error: cannot find attribute `deprcated` in this scope
   --> $DIR/attribute-typos.rs:1:3
index 0cc8994fe1f2d7589f564287f46c730d45824769..cbdb94877bdb7fbf897d0020c928bc6d718646a8 100644 (file)
@@ -16,11 +16,8 @@ LL |     for i in &a {
 LL |         for j in a {
    |                  ^ `a` moved due to this implicit call to `.into_iter()`, in previous iteration of loop
    |
-note: this function takes ownership of the receiver `self`, which moves `a`
+note: `into_iter` takes ownership of the receiver `self`, which moves `a`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 help: consider iterating over a slice of the `Vec<i32>`'s content to avoid moving into the `for` loop
    |
 LL |         for j in &a {
index d53715937f7d841ed3be7007bfe747c91700d84f..cd27947f02fad5cc111ec107e250eaf82c8fb4ce 100644 (file)
@@ -78,9 +78,6 @@ LL |     const SIZE: usize = core::mem::size_of::<Self>();
    |
 note: required by a bound in `std::mem::size_of`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL | pub const fn size_of<T>() -> usize {
-   |                      ^ required by this bound in `std::mem::size_of`
 help: consider further restricting `Self`
    |
 LL | trait Foo<T>: Sized {
@@ -94,9 +91,6 @@ LL |     const SIZE: usize = core::mem::size_of::<Self>();
    |
 note: required by a bound in `std::mem::size_of`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL | pub const fn size_of<T>() -> usize {
-   |                      ^ required by this bound in `std::mem::size_of`
 help: consider further restricting `Self`
    |
 LL | trait Bar: std::fmt::Display + Sized {
@@ -110,9 +104,6 @@ LL |     const SIZE: usize = core::mem::size_of::<Self>();
    |
 note: required by a bound in `std::mem::size_of`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL | pub const fn size_of<T>() -> usize {
-   |                      ^ required by this bound in `std::mem::size_of`
 help: consider further restricting `Self`
    |
 LL | trait Baz: Sized where Self: std::fmt::Display {
@@ -126,9 +117,6 @@ LL |     const SIZE: usize = core::mem::size_of::<Self>();
    |
 note: required by a bound in `std::mem::size_of`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL | pub const fn size_of<T>() -> usize {
-   |                      ^ required by this bound in `std::mem::size_of`
 help: consider further restricting `Self`
    |
 LL | trait Qux<T>: Sized where Self: std::fmt::Display {
@@ -142,9 +130,6 @@ LL |     const SIZE: usize = core::mem::size_of::<Self>();
    |
 note: required by a bound in `std::mem::size_of`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL | pub const fn size_of<T>() -> usize {
-   |                      ^ required by this bound in `std::mem::size_of`
 help: consider further restricting `Self`
    |
 LL | trait Bat<T>: std::fmt::Display + Sized {
diff --git a/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.fixed b/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.fixed
new file mode 100644 (file)
index 0000000..4f9e93a
--- /dev/null
@@ -0,0 +1,16 @@
+// run-rustfix
+fn wat<T: Clone>(t: &T) -> T {
+    t.clone() //~ ERROR E0308
+}
+
+#[derive(Clone)]
+struct Foo;
+
+fn wut(t: &Foo) -> Foo {
+    t.clone() //~ ERROR E0308
+}
+
+fn main() {
+    wat(&42);
+    wut(&Foo);
+}
diff --git a/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.rs b/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.rs
new file mode 100644 (file)
index 0000000..89b077d
--- /dev/null
@@ -0,0 +1,15 @@
+// run-rustfix
+fn wat<T>(t: &T) -> T {
+    t.clone() //~ ERROR E0308
+}
+
+struct Foo;
+
+fn wut(t: &Foo) -> Foo {
+    t.clone() //~ ERROR E0308
+}
+
+fn main() {
+    wat(&42);
+    wut(&Foo);
+}
diff --git a/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr b/src/test/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr
new file mode 100644 (file)
index 0000000..26ab515
--- /dev/null
@@ -0,0 +1,43 @@
+error[E0308]: mismatched types
+  --> $DIR/clone-on-unconstrained-borrowed-type-param.rs:3:5
+   |
+LL | fn wat<T>(t: &T) -> T {
+   |        -            - expected `T` because of return type
+   |        |
+   |        this type parameter
+LL |     t.clone()
+   |     ^^^^^^^^^ expected type parameter `T`, found `&T`
+   |
+   = note: expected type parameter `T`
+                   found reference `&T`
+note: `T` does not implement `Clone`, so `&T` was cloned instead
+  --> $DIR/clone-on-unconstrained-borrowed-type-param.rs:3:5
+   |
+LL |     t.clone()
+   |     ^
+help: consider restricting type parameter `T`
+   |
+LL | fn wat<T: Clone>(t: &T) -> T {
+   |         +++++++
+
+error[E0308]: mismatched types
+  --> $DIR/clone-on-unconstrained-borrowed-type-param.rs:9:5
+   |
+LL | fn wut(t: &Foo) -> Foo {
+   |                    --- expected `Foo` because of return type
+LL |     t.clone()
+   |     ^^^^^^^^^ expected struct `Foo`, found `&Foo`
+   |
+note: `Foo` does not implement `Clone`, so `&Foo` was cloned instead
+  --> $DIR/clone-on-unconstrained-borrowed-type-param.rs:9:5
+   |
+LL |     t.clone()
+   |     ^
+help: consider annotating `Foo` with `#[derive(Clone)]`
+   |
+LL | #[derive(Clone)]
+   |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
index 0645f0cdde7c0b31e5b70ed146fc5d03d10a02d9..0a18b770405c1d2629d319478030493fcd6b3f3a 100644 (file)
@@ -11,9 +11,6 @@ LL | impl<T: Clone, U> PartialEq<U> for Struct<T>
    |                   ^^^^^^^^^^^^     ^^^^^^^^^
 note: required by a bound in `Eq`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub trait Eq: PartialEq<Self> {
-   |               ^^^^^^^^^^^^^^^ required by this bound in `Eq`
    = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider restricting type parameter `T`
    |
index 7cc372f2422aebdd730376b951fe295834869466..14e8a2675dd18dca6b2dc57fc4c4a973d1d2ebee 100644 (file)
@@ -20,11 +20,8 @@ LL |     let y = x.test();
            `Enum: Clone`
            `Enum: Default`
            `CloneEnum: Default`
-note: the following trait must be implemented
+note: the trait `Default` must be implemented
   --> $SRC_DIR/core/src/default.rs:LL:COL
-   |
-LL | pub trait Default: Sized {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
 help: consider annotating `Enum` with `#[derive(Clone)]`
    |
 LL | #[derive(Clone)]
@@ -69,16 +66,12 @@ LL | struct Foo<X, Y> (X, Y);
 ...
 LL |     let y = x.test();
    |               ^^^^ method cannot be called on `Foo<Vec<Enum>, Instant>` due to unsatisfied trait bounds
+  --> $SRC_DIR/std/src/time.rs:LL:COL
    |
-  ::: $SRC_DIR/std/src/time.rs:LL:COL
-   |
-LL | pub struct Instant(time::Instant);
-   | ------------------ doesn't satisfy `Instant: Default`
-   |
-  ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+   = note: doesn't satisfy `Instant: Default`
+  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
    |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
-   | ------------------------------------------------------------------------------------------------ doesn't satisfy `Vec<Enum>: Clone`
+   = note: doesn't satisfy `Vec<Enum>: Clone`
    |
    = note: the following trait bounds were not satisfied:
            `Vec<Enum>: Clone`
index 7bdc8e00f447dc2ec308fd02fa5f922cb51161a2..0cd6267b3b313ebfa8f50125af998bdef20a1d8f 100644 (file)
@@ -3,11 +3,9 @@ error[E0573]: expected type, found module `result`
    |
 LL | impl result {
    |      ^^^^^^ help: an enum with a similar name exists: `Result`
+  --> $SRC_DIR/core/src/result.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   | --------------------- similarly named enum `Result` defined here
+   = note: similarly named enum `Result` defined here
 
 error[E0573]: expected type, found variant `Err`
   --> $DIR/do-not-attempt-to-add-suggestions-with-no-changes.rs:3:25
index bf0c1dc27ce43e9a0fbea89f23ffceab736a3f77..e19d497f21d29f9386a85308ee6c3e027ed5d960 100644 (file)
@@ -38,31 +38,25 @@ pub fn main() {
 
     let &(X(_t), X(_u)) = &(x.clone(), x.clone());
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&`
-    //~| SUGGESTION (X(_t), X(_u))
+    //~| HELP consider removing the borrow
     if let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&`
-    //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+    //~| HELP consider removing the borrow
     while let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&`
-    //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+    //~| HELP consider removing the borrow
     match &(e.clone(), e.clone()) {
         //~^ ERROR cannot move
         &(Either::One(_t), Either::Two(_u)) => (),
-        //~^ HELP consider removing the `&`
-        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        //~^ HELP consider removing the borrow
         &(Either::Two(_t), Either::One(_u)) => (),
-        //~^ HELP consider removing the `&`
-        //~| SUGGESTION (Either::Two(_t), Either::One(_u))
+        //~^ HELP consider removing the borrow
         _ => (),
     }
     match &(e.clone(), e.clone()) {
         //~^ ERROR cannot move
         &(Either::One(_t), Either::Two(_u))
-        //~^ HELP consider removing the `&`
-        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        //~^ HELP consider removing the borrow
         | &(Either::Two(_t), Either::One(_u)) => (),
         // FIXME: would really like a suggestion here too
         _ => (),
@@ -70,51 +64,42 @@ pub fn main() {
     match &(e.clone(), e.clone()) {
         //~^ ERROR cannot move
         &(Either::One(_t), Either::Two(_u)) => (),
-        //~^ HELP consider removing the `&`
-        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        //~^ HELP consider removing the borrow
         &(Either::Two(ref _t), Either::One(ref _u)) => (),
         _ => (),
     }
     match &(e.clone(), e.clone()) {
         //~^ ERROR cannot move
         &(Either::One(_t), Either::Two(_u)) => (),
-        //~^ HELP consider removing the `&`
-        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        //~^ HELP consider removing the borrow
         (Either::Two(_t), Either::One(_u)) => (),
         _ => (),
     }
     fn f5(&(X(_t), X(_u)): &(X, X)) { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&`
-    //~| SUGGESTION (X(_t), X(_u))
+    //~| HELP consider removing the borrow
 
     let &mut (X(_t), X(_u)) = &mut (xm.clone(), xm.clone());
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&mut`
-    //~| SUGGESTION (X(_t), X(_u))
+    //~| HELP consider removing the mutable borrow
     if let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&mut`
-    //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+    //~| HELP consider removing the mutable borrow
     while let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&mut`
-    //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+    //~| HELP consider removing the mutable borrow
     match &mut (em.clone(), em.clone()) {
         //~^ ERROR cannot move
         &mut (Either::One(_t), Either::Two(_u)) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        //~^ HELP consider removing the mutable borrow
         &mut (Either::Two(_t), Either::One(_u)) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION (Either::Two(_t), Either::One(_u))
+        //~^ HELP consider removing the mutable borrow
         _ => (),
     }
     match &mut (em.clone(), em.clone()) {
         //~^ ERROR cannot move
         &mut (Either::One(_t), Either::Two(_u))
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        //~^ HELP consider removing the mutable borrow
         | &mut (Either::Two(_t), Either::One(_u)) => (),
         // FIXME: would really like a suggestion here too
         _ => (),
@@ -122,29 +107,25 @@ fn f5(&(X(_t), X(_u)): &(X, X)) { }
     match &mut (em.clone(), em.clone()) {
         //~^ ERROR cannot move
         &mut (Either::One(_t), Either::Two(_u)) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        //~^ HELP consider removing the mutable borrow
         &mut (Either::Two(ref _t), Either::One(ref _u)) => (),
         _ => (),
     }
     match &mut (em.clone(), em.clone()) {
         //~^ ERROR cannot move
         &mut (Either::One(_t), Either::Two(_u)) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        //~^ HELP consider removing the mutable borrow
         &mut (Either::Two(ref mut _t), Either::One(ref mut _u)) => (),
         _ => (),
     }
     match &mut (em.clone(), em.clone()) {
         //~^ ERROR cannot move
         &mut (Either::One(_t), Either::Two(_u)) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        //~^ HELP consider removing the mutable borrow
         (Either::Two(_t), Either::One(_u)) => (),
         _ => (),
     }
     fn f6(&mut (X(_t), X(_u)): &mut (X, X)) { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&mut`
-    //~| SUGGESTION (X(_t), X(_u))
+    //~| HELP consider removing the mutable borrow
 }
index 40ad671f9663029c6d0790cd0d4ea87433403378..b96b3713f2a7ab74d37d5763832a0d2198a04462 100644 (file)
@@ -2,40 +2,52 @@ error[E0507]: cannot move out of a shared reference
   --> $DIR/duplicate-suggestions.rs:39:27
    |
 LL |     let &(X(_t), X(_u)) = &(x.clone(), x.clone());
-   |         ---------------   ^^^^^^^^^^^^^^^^^^^^^^^
-   |         |   |      |
-   |         |   |      ...and here
-   |         |   data moved here
-   |         help: consider removing the `&`: `(X(_t), X(_u))`
+   |             --     --     ^^^^^^^^^^^^^^^^^^^^^^^
+   |             |      |
+   |             |      ...and here
+   |             data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the borrow
+   |
+LL -     let &(X(_t), X(_u)) = &(x.clone(), x.clone());
+LL +     let (X(_t), X(_u)) = &(x.clone(), x.clone());
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/duplicate-suggestions.rs:43:50
+  --> $DIR/duplicate-suggestions.rs:42:50
    |
 LL |     if let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
-   |            -----------------------------------   ^^^^^^^^^^^^^^^^^^^^^^^
-   |            |             |                |
-   |            |             |                ...and here
-   |            |             data moved here
-   |            help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+   |                          --               --     ^^^^^^^^^^^^^^^^^^^^^^^
+   |                          |                |
+   |                          |                ...and here
+   |                          data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the borrow
+   |
+LL -     if let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+LL +     if let (Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/duplicate-suggestions.rs:47:53
+  --> $DIR/duplicate-suggestions.rs:45:53
    |
 LL |     while let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
-   |               -----------------------------------   ^^^^^^^^^^^^^^^^^^^^^^^
-   |               |             |                |
-   |               |             |                ...and here
-   |               |             data moved here
-   |               help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+   |                             --               --     ^^^^^^^^^^^^^^^^^^^^^^^
+   |                             |                |
+   |                             |                ...and here
+   |                             data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the borrow
+   |
+LL -     while let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+LL +     while let (Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/duplicate-suggestions.rs:51:11
+  --> $DIR/duplicate-suggestions.rs:48:11
    |
 LL |     match &(e.clone(), e.clone()) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^
@@ -44,22 +56,24 @@ LL |         &(Either::One(_t), Either::Two(_u)) => (),
    |                       --               -- ...and here
    |                       |
    |                       data moved here
-...
+LL |
 LL |         &(Either::Two(_t), Either::One(_u)) => (),
    |                       -- ...and here   -- ...and here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
-help: consider removing the `&`
+help: consider removing the borrow
    |
-LL |         (Either::One(_t), Either::Two(_u)) => (),
-   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-help: consider removing the `&`
+LL -         &(Either::One(_t), Either::Two(_u)) => (),
+LL +         (Either::One(_t), Either::Two(_u)) => (),
+   |
+help: consider removing the borrow
+   |
+LL -         &(Either::Two(_t), Either::One(_u)) => (),
+LL +         (Either::Two(_t), Either::One(_u)) => (),
    |
-LL |         (Either::Two(_t), Either::One(_u)) => (),
-   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/duplicate-suggestions.rs:61:11
+  --> $DIR/duplicate-suggestions.rs:56:11
    |
 LL |     match &(e.clone(), e.clone()) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^
@@ -70,82 +84,98 @@ LL |         &(Either::One(_t), Either::Two(_u))
    |                       data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
-help: consider removing the `&`
+help: consider removing the borrow
    |
-LL ~         (Either::One(_t), Either::Two(_u))
-LL +
-LL +
-LL ~         | &(Either::Two(_t), Either::One(_u)) => (),
+LL -         &(Either::One(_t), Either::Two(_u))
+LL +         (Either::One(_t), Either::Two(_u))
    |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/duplicate-suggestions.rs:70:11
+  --> $DIR/duplicate-suggestions.rs:64:11
    |
 LL |     match &(e.clone(), e.clone()) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^
 LL |
 LL |         &(Either::One(_t), Either::Two(_u)) => (),
-   |         -----------------------------------
-   |         |             |                |
-   |         |             |                ...and here
-   |         |             data moved here
-   |         help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+   |                       --               -- ...and here
+   |                       |
+   |                       data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the borrow
+   |
+LL -         &(Either::One(_t), Either::Two(_u)) => (),
+LL +         (Either::One(_t), Either::Two(_u)) => (),
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/duplicate-suggestions.rs:78:11
+  --> $DIR/duplicate-suggestions.rs:71:11
    |
 LL |     match &(e.clone(), e.clone()) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^
 LL |
 LL |         &(Either::One(_t), Either::Two(_u)) => (),
-   |         -----------------------------------
-   |         |             |                |
-   |         |             |                ...and here
-   |         |             data moved here
-   |         help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+   |                       --               -- ...and here
+   |                       |
+   |                       data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the borrow
+   |
+LL -         &(Either::One(_t), Either::Two(_u)) => (),
+LL +         (Either::One(_t), Either::Two(_u)) => (),
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/duplicate-suggestions.rs:91:31
+  --> $DIR/duplicate-suggestions.rs:82:31
    |
 LL |     let &mut (X(_t), X(_u)) = &mut (xm.clone(), xm.clone());
-   |         -------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |       |      |
-   |         |       |      ...and here
-   |         |       data moved here
-   |         help: consider removing the `&mut`: `(X(_t), X(_u))`
+   |                 --     --     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                 |      |
+   |                 |      ...and here
+   |                 data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+   |
+LL -     let &mut (X(_t), X(_u)) = &mut (xm.clone(), xm.clone());
+LL +     let (X(_t), X(_u)) = &mut (xm.clone(), xm.clone());
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/duplicate-suggestions.rs:95:54
+  --> $DIR/duplicate-suggestions.rs:85:54
    |
 LL |     if let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
-   |            ---------------------------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |            |                 |                |
-   |            |                 |                ...and here
-   |            |                 data moved here
-   |            help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+   |                              --               --     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                              |                |
+   |                              |                ...and here
+   |                              data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+   |
+LL -     if let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+LL +     if let (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/duplicate-suggestions.rs:99:57
+  --> $DIR/duplicate-suggestions.rs:88:57
    |
 LL |     while let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
-   |               ---------------------------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |               |                 |                |
-   |               |                 |                ...and here
-   |               |                 data moved here
-   |               help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+   |                                 --               --     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                 |                |
+   |                                 |                ...and here
+   |                                 data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+   |
+LL -     while let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+LL +     while let (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/duplicate-suggestions.rs:103:11
+  --> $DIR/duplicate-suggestions.rs:91:11
    |
 LL |     match &mut (em.clone(), em.clone()) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -154,22 +184,24 @@ LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
    |                           --               -- ...and here
    |                           |
    |                           data moved here
-...
+LL |
 LL |         &mut (Either::Two(_t), Either::One(_u)) => (),
    |                           -- ...and here   -- ...and here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
-help: consider removing the `&mut`
+help: consider removing the mutable borrow
+   |
+LL -         &mut (Either::One(_t), Either::Two(_u)) => (),
+LL +         (Either::One(_t), Either::Two(_u)) => (),
    |
-LL |         (Either::One(_t), Either::Two(_u)) => (),
-   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-help: consider removing the `&mut`
+help: consider removing the mutable borrow
+   |
+LL -         &mut (Either::Two(_t), Either::One(_u)) => (),
+LL +         (Either::Two(_t), Either::One(_u)) => (),
    |
-LL |         (Either::Two(_t), Either::One(_u)) => (),
-   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/duplicate-suggestions.rs:113:11
+  --> $DIR/duplicate-suggestions.rs:99:11
    |
 LL |     match &mut (em.clone(), em.clone()) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -180,82 +212,97 @@ LL |         &mut (Either::One(_t), Either::Two(_u))
    |                           data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
-help: consider removing the `&mut`
+help: consider removing the mutable borrow
    |
-LL ~         (Either::One(_t), Either::Two(_u))
-LL +
-LL +
-LL ~         | &mut (Either::Two(_t), Either::One(_u)) => (),
+LL -         &mut (Either::One(_t), Either::Two(_u))
+LL +         (Either::One(_t), Either::Two(_u))
    |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/duplicate-suggestions.rs:122:11
+  --> $DIR/duplicate-suggestions.rs:107:11
    |
 LL |     match &mut (em.clone(), em.clone()) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 LL |
 LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
-   |         ---------------------------------------
-   |         |                 |                |
-   |         |                 |                ...and here
-   |         |                 data moved here
-   |         help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+   |                           --               -- ...and here
+   |                           |
+   |                           data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+   |
+LL -         &mut (Either::One(_t), Either::Two(_u)) => (),
+LL +         (Either::One(_t), Either::Two(_u)) => (),
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/duplicate-suggestions.rs:130:11
+  --> $DIR/duplicate-suggestions.rs:114:11
    |
 LL |     match &mut (em.clone(), em.clone()) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 LL |
 LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
-   |         ---------------------------------------
-   |         |                 |                |
-   |         |                 |                ...and here
-   |         |                 data moved here
-   |         help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+   |                           --               -- ...and here
+   |                           |
+   |                           data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+   |
+LL -         &mut (Either::One(_t), Either::Two(_u)) => (),
+LL +         (Either::One(_t), Either::Two(_u)) => (),
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/duplicate-suggestions.rs:138:11
+  --> $DIR/duplicate-suggestions.rs:121:11
    |
 LL |     match &mut (em.clone(), em.clone()) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 LL |
 LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
-   |         ---------------------------------------
-   |         |                 |                |
-   |         |                 |                ...and here
-   |         |                 data moved here
-   |         help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+   |                           --               -- ...and here
+   |                           |
+   |                           data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+   |
+LL -         &mut (Either::One(_t), Either::Two(_u)) => (),
+LL +         (Either::One(_t), Either::Two(_u)) => (),
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/duplicate-suggestions.rs:86:11
+  --> $DIR/duplicate-suggestions.rs:78:11
    |
 LL |     fn f5(&(X(_t), X(_u)): &(X, X)) { }
    |           ^^^^--^^^^^--^^
-   |           |   |      |
-   |           |   |      ...and here
-   |           |   data moved here
-   |           help: consider removing the `&`: `(X(_t), X(_u))`
+   |               |      |
+   |               |      ...and here
+   |               data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the borrow
+   |
+LL -     fn f5(&(X(_t), X(_u)): &(X, X)) { }
+LL +     fn f5((X(_t), X(_u)): &(X, X)) { }
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/duplicate-suggestions.rs:146:11
+  --> $DIR/duplicate-suggestions.rs:128:11
    |
 LL |     fn f6(&mut (X(_t), X(_u)): &mut (X, X)) { }
    |           ^^^^^^^^--^^^^^--^^
-   |           |       |      |
-   |           |       |      ...and here
-   |           |       data moved here
-   |           help: consider removing the `&mut`: `(X(_t), X(_u))`
+   |                   |      |
+   |                   |      ...and here
+   |                   data moved here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+   |
+LL -     fn f6(&mut (X(_t), X(_u)): &mut (X, X)) { }
+LL +     fn f6((X(_t), X(_u)): &mut (X, X)) { }
+   |
 
 error: aborting due to 17 previous errors
 
index f1e043c30f213e99e4fddaede6937b5ec9644a17..44eac3691a3beb89ab81bb4b7f882dc35bd55dd5 100644 (file)
@@ -28,26 +28,21 @@ fn move_into_fn() {
         let X(_t) = x;
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &x
         if let Either::One(_t) = e { }
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &e
         while let Either::One(_t) = e { }
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &e
         match e {
             //~^ ERROR cannot move
             //~| HELP consider borrowing here
-            //~| SUGGESTION &e
             Either::One(_t)
             | Either::Two(_t) => (),
         }
         match e {
             //~^ ERROR cannot move
             //~| HELP consider borrowing here
-            //~| SUGGESTION &e
             Either::One(_t) => (),
             Either::Two(ref _t) => (),
             // FIXME: should suggest removing `ref` too
@@ -56,26 +51,21 @@ fn move_into_fn() {
         let X(mut _t) = x;
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &x
         if let Either::One(mut _t) = em { }
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &em
         while let Either::One(mut _t) = em { }
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &em
         match em {
             //~^ ERROR cannot move
             //~| HELP consider borrowing here
-            //~| SUGGESTION &em
             Either::One(mut _t)
             | Either::Two(mut _t) => (),
         }
         match em {
             //~^ ERROR cannot move
             //~| HELP consider borrowing here
-            //~| SUGGESTION &em
             Either::One(mut _t) => (),
             Either::Two(ref _t) => (),
             // FIXME: should suggest removing `ref` too
@@ -95,26 +85,21 @@ fn move_into_fnmut() {
         let X(_t) = x;
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &x
         if let Either::One(_t) = e { }
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &e
         while let Either::One(_t) = e { }
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &e
         match e {
             //~^ ERROR cannot move
             //~| HELP consider borrowing here
-            //~| SUGGESTION &e
             Either::One(_t)
             | Either::Two(_t) => (),
         }
         match e {
             //~^ ERROR cannot move
             //~| HELP consider borrowing here
-            //~| SUGGESTION &e
             Either::One(_t) => (),
             Either::Two(ref _t) => (),
             // FIXME: should suggest removing `ref` too
@@ -123,26 +108,21 @@ fn move_into_fnmut() {
         let X(mut _t) = x;
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &x
         if let Either::One(mut _t) = em { }
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &em
         while let Either::One(mut _t) = em { }
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &em
         match em {
             //~^ ERROR cannot move
             //~| HELP consider borrowing here
-            //~| SUGGESTION &em
             Either::One(mut _t)
             | Either::Two(mut _t) => (),
         }
         match em {
             //~^ ERROR cannot move
             //~| HELP consider borrowing here
-            //~| SUGGESTION &em
             Either::One(mut _t) => (),
             Either::Two(ref _t) => (),
             // FIXME: should suggest removing `ref` too
@@ -150,7 +130,6 @@ fn move_into_fnmut() {
         match em {
             //~^ ERROR cannot move
             //~| HELP consider borrowing here
-            //~| SUGGESTION &em
             Either::One(mut _t) => (),
             Either::Two(ref mut _t) => (),
             // FIXME: should suggest removing `ref` too
index e06ee4290abd801d35092d3f3f03f3c1ec3921a7..edda2cbc735a25dc541d5ff80cbf0642bb634224 100644 (file)
@@ -7,13 +7,18 @@ LL |     let x = X(Y);
 LL |     consume_fn(|| {
    |                -- captured by this `Fn` closure
 LL |         let X(_t) = x;
-   |               --    ^ help: consider borrowing here: `&x`
+   |               --    ^
    |               |
    |               data moved here
    |               move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         let X(_t) = &x;
+   |                     +
 
 error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure
-  --> $DIR/move-into-closure.rs:32:34
+  --> $DIR/move-into-closure.rs:31:34
    |
 LL |     let e = Either::One(X(Y));
    |         - captured outer variable
@@ -22,13 +27,18 @@ LL |     consume_fn(|| {
    |                -- captured by this `Fn` closure
 ...
 LL |         if let Either::One(_t) = e { }
-   |                            --    ^ help: consider borrowing here: `&e`
+   |                            --    ^
    |                            |
    |                            data moved here
    |                            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         if let Either::One(_t) = &e { }
+   |                                  +
 
 error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure
-  --> $DIR/move-into-closure.rs:36:37
+  --> $DIR/move-into-closure.rs:34:37
    |
 LL |     let e = Either::One(X(Y));
    |         - captured outer variable
@@ -37,13 +47,18 @@ LL |     consume_fn(|| {
    |                -- captured by this `Fn` closure
 ...
 LL |         while let Either::One(_t) = e { }
-   |                               --    ^ help: consider borrowing here: `&e`
+   |                               --    ^
    |                               |
    |                               data moved here
    |                               move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         while let Either::One(_t) = &e { }
+   |                                     +
 
 error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure
-  --> $DIR/move-into-closure.rs:40:15
+  --> $DIR/move-into-closure.rs:37:15
    |
 LL |     let e = Either::One(X(Y));
    |         - captured outer variable
@@ -52,16 +67,21 @@ LL |     consume_fn(|| {
    |                -- captured by this `Fn` closure
 ...
 LL |         match e {
-   |               ^ help: consider borrowing here: `&e`
+   |               ^
 ...
 LL |             Either::One(_t)
    |                         --
    |                         |
    |                         data moved here
    |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         match &e {
+   |               +
 
 error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure
-  --> $DIR/move-into-closure.rs:47:15
+  --> $DIR/move-into-closure.rs:43:15
    |
 LL |     let e = Either::One(X(Y));
    |         - captured outer variable
@@ -70,16 +90,21 @@ LL |     consume_fn(|| {
    |                -- captured by this `Fn` closure
 ...
 LL |         match e {
-   |               ^ help: consider borrowing here: `&e`
+   |               ^
 ...
 LL |             Either::One(_t) => (),
    |                         --
    |                         |
    |                         data moved here
    |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         match &e {
+   |               +
 
 error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `Fn` closure
-  --> $DIR/move-into-closure.rs:56:25
+  --> $DIR/move-into-closure.rs:51:25
    |
 LL |     let x = X(Y);
    |         - captured outer variable
@@ -88,13 +113,18 @@ LL |     consume_fn(|| {
    |                -- captured by this `Fn` closure
 ...
 LL |         let X(mut _t) = x;
-   |               ------    ^ help: consider borrowing here: `&x`
+   |               ------    ^
    |               |
    |               data moved here
    |               move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         let X(mut _t) = &x;
+   |                         +
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure
-  --> $DIR/move-into-closure.rs:60:38
+  --> $DIR/move-into-closure.rs:54:38
    |
 LL |     let mut em = Either::One(X(Y));
    |         ------ captured outer variable
@@ -103,13 +133,18 @@ LL |     consume_fn(|| {
    |                -- captured by this `Fn` closure
 ...
 LL |         if let Either::One(mut _t) = em { }
-   |                            ------    ^^ help: consider borrowing here: `&em`
+   |                            ------    ^^
    |                            |
    |                            data moved here
    |                            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         if let Either::One(mut _t) = &em { }
+   |                                      +
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure
-  --> $DIR/move-into-closure.rs:64:41
+  --> $DIR/move-into-closure.rs:57:41
    |
 LL |     let mut em = Either::One(X(Y));
    |         ------ captured outer variable
@@ -118,13 +153,18 @@ LL |     consume_fn(|| {
    |                -- captured by this `Fn` closure
 ...
 LL |         while let Either::One(mut _t) = em { }
-   |                               ------    ^^ help: consider borrowing here: `&em`
+   |                               ------    ^^
    |                               |
    |                               data moved here
    |                               move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         while let Either::One(mut _t) = &em { }
+   |                                         +
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure
-  --> $DIR/move-into-closure.rs:68:15
+  --> $DIR/move-into-closure.rs:60:15
    |
 LL |     let mut em = Either::One(X(Y));
    |         ------ captured outer variable
@@ -133,16 +173,21 @@ LL |     consume_fn(|| {
    |                -- captured by this `Fn` closure
 ...
 LL |         match em {
-   |               ^^ help: consider borrowing here: `&em`
+   |               ^^
 ...
 LL |             Either::One(mut _t)
    |                         ------
    |                         |
    |                         data moved here
    |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         match &em {
+   |               +
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure
-  --> $DIR/move-into-closure.rs:75:15
+  --> $DIR/move-into-closure.rs:66:15
    |
 LL |     let mut em = Either::One(X(Y));
    |         ------ captured outer variable
@@ -151,16 +196,21 @@ LL |     consume_fn(|| {
    |                -- captured by this `Fn` closure
 ...
 LL |         match em {
-   |               ^^ help: consider borrowing here: `&em`
+   |               ^^
 ...
 LL |             Either::One(mut _t) => (),
    |                         ------
    |                         |
    |                         data moved here
    |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         match &em {
+   |               +
 
 error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `FnMut` closure
-  --> $DIR/move-into-closure.rs:95:21
+  --> $DIR/move-into-closure.rs:85:21
    |
 LL |     let x = X(Y);
    |         - captured outer variable
@@ -168,13 +218,18 @@ LL |     let x = X(Y);
 LL |     consume_fnmut(|| {
    |                   -- captured by this `FnMut` closure
 LL |         let X(_t) = x;
-   |               --    ^ help: consider borrowing here: `&x`
+   |               --    ^
    |               |
    |               data moved here
    |               move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         let X(_t) = &x;
+   |                     +
 
 error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure
-  --> $DIR/move-into-closure.rs:99:34
+  --> $DIR/move-into-closure.rs:88:34
    |
 LL |     let e = Either::One(X(Y));
    |         - captured outer variable
@@ -183,13 +238,18 @@ LL |     consume_fnmut(|| {
    |                   -- captured by this `FnMut` closure
 ...
 LL |         if let Either::One(_t) = e { }
-   |                            --    ^ help: consider borrowing here: `&e`
+   |                            --    ^
    |                            |
    |                            data moved here
    |                            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         if let Either::One(_t) = &e { }
+   |                                  +
 
 error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure
-  --> $DIR/move-into-closure.rs:103:37
+  --> $DIR/move-into-closure.rs:91:37
    |
 LL |     let e = Either::One(X(Y));
    |         - captured outer variable
@@ -198,13 +258,18 @@ LL |     consume_fnmut(|| {
    |                   -- captured by this `FnMut` closure
 ...
 LL |         while let Either::One(_t) = e { }
-   |                               --    ^ help: consider borrowing here: `&e`
+   |                               --    ^
    |                               |
    |                               data moved here
    |                               move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         while let Either::One(_t) = &e { }
+   |                                     +
 
 error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure
-  --> $DIR/move-into-closure.rs:107:15
+  --> $DIR/move-into-closure.rs:94:15
    |
 LL |     let e = Either::One(X(Y));
    |         - captured outer variable
@@ -213,16 +278,21 @@ LL |     consume_fnmut(|| {
    |                   -- captured by this `FnMut` closure
 ...
 LL |         match e {
-   |               ^ help: consider borrowing here: `&e`
+   |               ^
 ...
 LL |             Either::One(_t)
    |                         --
    |                         |
    |                         data moved here
    |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         match &e {
+   |               +
 
 error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure
-  --> $DIR/move-into-closure.rs:114:15
+  --> $DIR/move-into-closure.rs:100:15
    |
 LL |     let e = Either::One(X(Y));
    |         - captured outer variable
@@ -231,16 +301,21 @@ LL |     consume_fnmut(|| {
    |                   -- captured by this `FnMut` closure
 ...
 LL |         match e {
-   |               ^ help: consider borrowing here: `&e`
+   |               ^
 ...
 LL |             Either::One(_t) => (),
    |                         --
    |                         |
    |                         data moved here
    |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         match &e {
+   |               +
 
 error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `FnMut` closure
-  --> $DIR/move-into-closure.rs:123:25
+  --> $DIR/move-into-closure.rs:108:25
    |
 LL |     let x = X(Y);
    |         - captured outer variable
@@ -249,13 +324,18 @@ LL |     consume_fnmut(|| {
    |                   -- captured by this `FnMut` closure
 ...
 LL |         let X(mut _t) = x;
-   |               ------    ^ help: consider borrowing here: `&x`
+   |               ------    ^
    |               |
    |               data moved here
    |               move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         let X(mut _t) = &x;
+   |                         +
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
-  --> $DIR/move-into-closure.rs:127:38
+  --> $DIR/move-into-closure.rs:111:38
    |
 LL |     let mut em = Either::One(X(Y));
    |         ------ captured outer variable
@@ -264,13 +344,18 @@ LL |     consume_fnmut(|| {
    |                   -- captured by this `FnMut` closure
 ...
 LL |         if let Either::One(mut _t) = em { }
-   |                            ------    ^^ help: consider borrowing here: `&em`
+   |                            ------    ^^
    |                            |
    |                            data moved here
    |                            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         if let Either::One(mut _t) = &em { }
+   |                                      +
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
-  --> $DIR/move-into-closure.rs:131:41
+  --> $DIR/move-into-closure.rs:114:41
    |
 LL |     let mut em = Either::One(X(Y));
    |         ------ captured outer variable
@@ -279,13 +364,18 @@ LL |     consume_fnmut(|| {
    |                   -- captured by this `FnMut` closure
 ...
 LL |         while let Either::One(mut _t) = em { }
-   |                               ------    ^^ help: consider borrowing here: `&em`
+   |                               ------    ^^
    |                               |
    |                               data moved here
    |                               move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         while let Either::One(mut _t) = &em { }
+   |                                         +
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
-  --> $DIR/move-into-closure.rs:135:15
+  --> $DIR/move-into-closure.rs:117:15
    |
 LL |     let mut em = Either::One(X(Y));
    |         ------ captured outer variable
@@ -294,16 +384,21 @@ LL |     consume_fnmut(|| {
    |                   -- captured by this `FnMut` closure
 ...
 LL |         match em {
-   |               ^^ help: consider borrowing here: `&em`
+   |               ^^
 ...
 LL |             Either::One(mut _t)
    |                         ------
    |                         |
    |                         data moved here
    |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         match &em {
+   |               +
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
-  --> $DIR/move-into-closure.rs:142:15
+  --> $DIR/move-into-closure.rs:123:15
    |
 LL |     let mut em = Either::One(X(Y));
    |         ------ captured outer variable
@@ -312,16 +407,21 @@ LL |     consume_fnmut(|| {
    |                   -- captured by this `FnMut` closure
 ...
 LL |         match em {
-   |               ^^ help: consider borrowing here: `&em`
+   |               ^^
 ...
 LL |             Either::One(mut _t) => (),
    |                         ------
    |                         |
    |                         data moved here
    |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         match &em {
+   |               +
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
-  --> $DIR/move-into-closure.rs:150:15
+  --> $DIR/move-into-closure.rs:130:15
    |
 LL |     let mut em = Either::One(X(Y));
    |         ------ captured outer variable
@@ -330,13 +430,18 @@ LL |     consume_fnmut(|| {
    |                   -- captured by this `FnMut` closure
 ...
 LL |         match em {
-   |               ^^ help: consider borrowing here: `&em`
+   |               ^^
 ...
 LL |             Either::One(mut _t) => (),
    |                         ------
    |                         |
    |                         data moved here
    |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |         match &em {
+   |               +
 
 error: aborting due to 21 previous errors
 
index c53ac3d2cd684fcecf5de1061354ee5254a94ec5..1e40e60a1ce12c4785d17e5b7c61ee5dc3fa5b52 100644 (file)
@@ -37,27 +37,22 @@ pub fn main() {
 
     let X(_t) = *s;
     //~^ ERROR cannot move
-    //~| HELP consider borrowing here
-    //~| SUGGESTION s
+    //~| HELP consider removing the dereference here
     if let Either::One(_t) = *r { }
     //~^ ERROR cannot move
-    //~| HELP consider borrowing here
-    //~| SUGGESTION r
+    //~| HELP consider removing the dereference here
     while let Either::One(_t) = *r { }
     //~^ ERROR cannot move
-    //~| HELP consider borrowing here
-    //~| SUGGESTION r
+    //~| HELP consider removing the dereference here
     match *r {
         //~^ ERROR cannot move
-        //~| HELP consider borrowing here
-        //~| SUGGESTION r
+        //~| HELP consider removing the dereference here
         Either::One(_t)
         | Either::Two(_t) => (),
     }
     match *r {
         //~^ ERROR cannot move
-        //~| HELP consider borrowing here
-        //~| SUGGESTION r
+        //~| HELP consider removing the dereference here
         Either::One(_t) => (),
         Either::Two(ref _t) => (),
         // FIXME: should suggest removing `ref` too
@@ -65,35 +60,29 @@ pub fn main() {
 
     let X(_t) = *sm;
     //~^ ERROR cannot move
-    //~| HELP consider borrowing here
-    //~| SUGGESTION sm
+    //~| HELP consider removing the dereference here
     if let Either::One(_t) = *rm { }
     //~^ ERROR cannot move
-    //~| HELP consider borrowing here
-    //~| SUGGESTION rm
+    //~| HELP consider removing the dereference here
     while let Either::One(_t) = *rm { }
     //~^ ERROR cannot move
-    //~| HELP consider borrowing here
-    //~| SUGGESTION rm
+    //~| HELP consider removing the dereference here
     match *rm {
         //~^ ERROR cannot move
-        //~| HELP consider borrowing here
-        //~| SUGGESTION rm
+        //~| HELP consider removing the dereference here
         Either::One(_t)
         | Either::Two(_t) => (),
     }
     match *rm {
         //~^ ERROR cannot move
-        //~| HELP consider borrowing here
-        //~| SUGGESTION rm
+        //~| HELP consider removing the dereference here
         Either::One(_t) => (),
         Either::Two(ref _t) => (),
         // FIXME: should suggest removing `ref` too
     }
     match *rm {
         //~^ ERROR cannot move
-        //~| HELP consider borrowing here
-        //~| SUGGESTION rm
+        //~| HELP consider removing the dereference here
         Either::One(_t) => (),
         Either::Two(ref mut _t) => (),
         // FIXME: should suggest removing `ref` too
@@ -102,26 +91,21 @@ pub fn main() {
     let X(_t) = vs[0];
     //~^ ERROR cannot move
     //~| HELP consider borrowing here
-    //~| SUGGESTION &vs[0]
     if let Either::One(_t) = vr[0] { }
     //~^ ERROR cannot move
     //~| HELP consider borrowing here
-    //~| SUGGESTION &vr[0]
     while let Either::One(_t) = vr[0] { }
     //~^ ERROR cannot move
     //~| HELP consider borrowing here
-    //~| SUGGESTION &vr[0]
     match vr[0] {
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &vr[0]
         Either::One(_t)
         | Either::Two(_t) => (),
     }
     match vr[0] {
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &vr[0]
         Either::One(_t) => (),
         Either::Two(ref _t) => (),
         // FIXME: should suggest removing `ref` too
@@ -130,26 +114,21 @@ pub fn main() {
     let X(_t) = vsm[0];
     //~^ ERROR cannot move
     //~| HELP consider borrowing here
-    //~| SUGGESTION &vsm[0]
     if let Either::One(_t) = vrm[0] { }
     //~^ ERROR cannot move
     //~| HELP consider borrowing here
-    //~| SUGGESTION &vrm[0]
     while let Either::One(_t) = vrm[0] { }
     //~^ ERROR cannot move
     //~| HELP consider borrowing here
-    //~| SUGGESTION &vrm[0]
     match vrm[0] {
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &vrm[0]
         Either::One(_t)
         | Either::Two(_t) => (),
     }
     match vrm[0] {
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &vrm[0]
         Either::One(_t) => (),
         Either::Two(ref _t) => (),
         // FIXME: should suggest removing `ref` too
@@ -157,7 +136,6 @@ pub fn main() {
     match vrm[0] {
         //~^ ERROR cannot move
         //~| HELP consider borrowing here
-        //~| SUGGESTION &vrm[0]
         Either::One(_t) => (),
         Either::Two(ref mut _t) => (),
         // FIXME: should suggest removing `ref` too
@@ -167,89 +145,73 @@ pub fn main() {
 
     let &X(_t) = s;
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&`
-    //~| SUGGESTION X(_t)
+    //~| HELP consider removing
     if let &Either::One(_t) = r { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&`
-    //~| SUGGESTION Either::One(_t)
+    //~| HELP consider removing
     while let &Either::One(_t) = r { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&`
-    //~| SUGGESTION Either::One(_t)
+    //~| HELP consider removing
     match r {
         //~^ ERROR cannot move
         &Either::One(_t)
-        //~^ HELP consider removing the `&`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         | &Either::Two(_t) => (),
         // FIXME: would really like a suggestion here too
     }
     match r {
         //~^ ERROR cannot move
         &Either::One(_t) => (),
-        //~^ HELP consider removing the `&`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         &Either::Two(ref _t) => (),
     }
     match r {
         //~^ ERROR cannot move
         &Either::One(_t) => (),
-        //~^ HELP consider removing the `&`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         Either::Two(_t) => (),
     }
     fn f1(&X(_t): &X) { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&`
-    //~| SUGGESTION X(_t)
+    //~| HELP consider removing
 
     let &mut X(_t) = sm;
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&mut`
-    //~| SUGGESTION X(_t)
+    //~| HELP consider removing
     if let &mut Either::One(_t) = rm { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&mut`
-    //~| SUGGESTION Either::One(_t)
+    //~| HELP consider removing
     while let &mut Either::One(_t) = rm { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&mut`
-    //~| SUGGESTION Either::One(_t)
+    //~| HELP consider removing
     match rm {
         //~^ ERROR cannot move
         &mut Either::One(_t) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         &mut Either::Two(_t) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION Either::Two(_t)
+        //~^ HELP consider removing
     }
     match rm {
         //~^ ERROR cannot move
         &mut Either::One(_t) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         &mut Either::Two(ref _t) => (),
     }
     match rm {
         //~^ ERROR cannot move
         &mut Either::One(_t) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         &mut Either::Two(ref mut _t) => (),
     }
     match rm {
         //~^ ERROR cannot move
         &mut Either::One(_t) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         Either::Two(_t) => (),
     }
     fn f2(&mut X(_t): &mut X) { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&mut`
-    //~| SUGGESTION X(_t)
+    //~| HELP consider removing
 
     // move from tuple of &Either/&X
 
@@ -257,108 +219,118 @@ fn f2(&mut X(_t): &mut X) { }
 
     let (&X(_t),) = (&x.clone(),);
     //~^ ERROR cannot move
+    //~| HELP consider borrowing the pattern binding
     if let (&Either::One(_t),) = (&e.clone(),) { }
     //~^ ERROR cannot move
+    //~| HELP consider borrowing the pattern binding
     while let (&Either::One(_t),) = (&e.clone(),) { }
     //~^ ERROR cannot move
+    //~| HELP consider borrowing the pattern binding
     match (&e.clone(),) {
         //~^ ERROR cannot move
         (&Either::One(_t),)
+        //~^ HELP consider borrowing the pattern binding
         | (&Either::Two(_t),) => (),
     }
     fn f3((&X(_t),): (&X,)) { }
     //~^ ERROR cannot move
+    //~| HELP consider borrowing the pattern binding
 
     let (&mut X(_t),) = (&mut xm.clone(),);
     //~^ ERROR cannot move
+    //~| HELP consider borrowing the pattern binding
     if let (&mut Either::One(_t),) = (&mut em.clone(),) { }
     //~^ ERROR cannot move
+    //~| HELP consider borrowing the pattern binding
     while let (&mut Either::One(_t),) = (&mut em.clone(),) { }
     //~^ ERROR cannot move
+    //~| HELP consider borrowing the pattern binding
     match (&mut em.clone(),) {
         //~^ ERROR cannot move
         (&mut Either::One(_t),) => (),
+        //~^ HELP consider borrowing the pattern binding
         (&mut Either::Two(_t),) => (),
+        //~^ HELP consider borrowing the pattern binding
     }
     fn f4((&mut X(_t),): (&mut X,)) { }
     //~^ ERROR cannot move
+    //~| HELP consider borrowing the pattern binding
 
     // move from &Either/&X value
 
     let &X(_t) = &x;
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&`
-    //~| SUGGESTION X(_t)
+    //~| HELP consider removing
     if let &Either::One(_t) = &e { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&`
-    //~| SUGGESTION Either::One(_t)
+    //~| HELP consider removing
     while let &Either::One(_t) = &e { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&`
-    //~| SUGGESTION Either::One(_t)
+    //~| HELP consider removing
     match &e {
         //~^ ERROR cannot move
         &Either::One(_t)
-        //~^ HELP consider removing the `&`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         | &Either::Two(_t) => (),
         // FIXME: would really like a suggestion here too
     }
     match &e {
         //~^ ERROR cannot move
         &Either::One(_t) => (),
-        //~^ HELP consider removing the `&`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         &Either::Two(ref _t) => (),
     }
     match &e {
         //~^ ERROR cannot move
         &Either::One(_t) => (),
-        //~^ HELP consider removing the `&`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         Either::Two(_t) => (),
     }
 
     let &mut X(_t) = &mut xm;
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&mut`
-    //~| SUGGESTION X(_t)
+    //~| HELP consider removing
     if let &mut Either::One(_t) = &mut em { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&mut`
-    //~| SUGGESTION Either::One(_t)
+    //~| HELP consider removing
     while let &mut Either::One(_t) = &mut em { }
     //~^ ERROR cannot move
-    //~| HELP consider removing the `&mut`
-    //~| SUGGESTION Either::One(_t)
+    //~| HELP consider removing
     match &mut em {
         //~^ ERROR cannot move
         &mut Either::One(_t)
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         | &mut Either::Two(_t) => (),
         // FIXME: would really like a suggestion here too
     }
     match &mut em {
         //~^ ERROR cannot move
         &mut Either::One(_t) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         &mut Either::Two(ref _t) => (),
     }
     match &mut em {
         //~^ ERROR cannot move
         &mut Either::One(_t) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         &mut Either::Two(ref mut _t) => (),
     }
     match &mut em {
         //~^ ERROR cannot move
         &mut Either::One(_t) => (),
-        //~^ HELP consider removing the `&mut`
-        //~| SUGGESTION Either::One(_t)
+        //~^ HELP consider removing
         Either::Two(_t) => (),
     }
 }
+
+struct Testing {
+    a: Option<String>
+}
+
+fn testing(a: &Testing) {
+    let Some(_s) = a.a else {
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing the pattern binding
+        return;
+    };
+}
index e5443290f9e7a603f60dec3ac74f75d5a3233c47..5263265242318f13d4a9cfe85abda0446f15424b 100644 (file)
@@ -2,262 +2,398 @@ error[E0507]: cannot move out of `s` which is behind a shared reference
   --> $DIR/simple.rs:38:17
    |
 LL |     let X(_t) = *s;
-   |           --    ^^ help: consider borrowing here: `&*s`
+   |           --    ^^
    |           |
    |           data moved here
    |           move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let X(_t) = *s;
+LL +     let X(_t) = s;
+   |
 
 error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
-  --> $DIR/simple.rs:42:30
+  --> $DIR/simple.rs:41:30
    |
 LL |     if let Either::One(_t) = *r { }
-   |                        --    ^^ help: consider borrowing here: `&*r`
+   |                        --    ^^
    |                        |
    |                        data moved here
    |                        move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     if let Either::One(_t) = *r { }
+LL +     if let Either::One(_t) = r { }
+   |
 
 error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
-  --> $DIR/simple.rs:46:33
+  --> $DIR/simple.rs:44:33
    |
 LL |     while let Either::One(_t) = *r { }
-   |                           --    ^^ help: consider borrowing here: `&*r`
+   |                           --    ^^
    |                           |
    |                           data moved here
    |                           move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     while let Either::One(_t) = *r { }
+LL +     while let Either::One(_t) = r { }
+   |
 
 error[E0507]: cannot move out of `r` as enum variant `Two` which is behind a shared reference
-  --> $DIR/simple.rs:50:11
+  --> $DIR/simple.rs:47:11
    |
 LL |     match *r {
-   |           ^^ help: consider borrowing here: `&*r`
+   |           ^^
 ...
 LL |         Either::One(_t)
    |                     --
    |                     |
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     match *r {
+LL +     match r {
+   |
 
 error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
-  --> $DIR/simple.rs:57:11
+  --> $DIR/simple.rs:53:11
    |
 LL |     match *r {
-   |           ^^ help: consider borrowing here: `&*r`
+   |           ^^
 ...
 LL |         Either::One(_t) => (),
    |                     --
    |                     |
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     match *r {
+LL +     match r {
+   |
 
 error[E0507]: cannot move out of `sm` which is behind a mutable reference
-  --> $DIR/simple.rs:66:17
+  --> $DIR/simple.rs:61:17
    |
 LL |     let X(_t) = *sm;
-   |           --    ^^^ help: consider borrowing here: `&*sm`
+   |           --    ^^^
    |           |
    |           data moved here
    |           move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     let X(_t) = *sm;
+LL +     let X(_t) = sm;
+   |
 
 error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
-  --> $DIR/simple.rs:70:30
+  --> $DIR/simple.rs:64:30
    |
 LL |     if let Either::One(_t) = *rm { }
-   |                        --    ^^^ help: consider borrowing here: `&*rm`
+   |                        --    ^^^
    |                        |
    |                        data moved here
    |                        move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     if let Either::One(_t) = *rm { }
+LL +     if let Either::One(_t) = rm { }
+   |
 
 error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
-  --> $DIR/simple.rs:74:33
+  --> $DIR/simple.rs:67:33
    |
 LL |     while let Either::One(_t) = *rm { }
-   |                           --    ^^^ help: consider borrowing here: `&*rm`
+   |                           --    ^^^
    |                           |
    |                           data moved here
    |                           move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     while let Either::One(_t) = *rm { }
+LL +     while let Either::One(_t) = rm { }
+   |
 
 error[E0507]: cannot move out of `rm` as enum variant `Two` which is behind a mutable reference
-  --> $DIR/simple.rs:78:11
+  --> $DIR/simple.rs:70:11
    |
 LL |     match *rm {
-   |           ^^^ help: consider borrowing here: `&*rm`
+   |           ^^^
 ...
 LL |         Either::One(_t)
    |                     --
    |                     |
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     match *rm {
+LL +     match rm {
+   |
 
 error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
-  --> $DIR/simple.rs:85:11
+  --> $DIR/simple.rs:76:11
    |
 LL |     match *rm {
-   |           ^^^ help: consider borrowing here: `&*rm`
+   |           ^^^
 ...
 LL |         Either::One(_t) => (),
    |                     --
    |                     |
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     match *rm {
+LL +     match rm {
+   |
 
 error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
-  --> $DIR/simple.rs:93:11
+  --> $DIR/simple.rs:83:11
    |
 LL |     match *rm {
-   |           ^^^ help: consider borrowing here: `&*rm`
+   |           ^^^
 ...
 LL |         Either::One(_t) => (),
    |                     --
    |                     |
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the dereference here
+   |
+LL -     match *rm {
+LL +     match rm {
+   |
 
 error[E0507]: cannot move out of index of `Vec<X>`
-  --> $DIR/simple.rs:102:17
+  --> $DIR/simple.rs:91:17
    |
 LL |     let X(_t) = vs[0];
-   |           --    ^^^^^ help: consider borrowing here: `&vs[0]`
+   |           --    ^^^^^
    |           |
    |           data moved here
    |           move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     let X(_t) = &vs[0];
+   |                 +
 
 error[E0507]: cannot move out of index of `Vec<Either>`
-  --> $DIR/simple.rs:106:30
+  --> $DIR/simple.rs:94:30
    |
 LL |     if let Either::One(_t) = vr[0] { }
-   |                        --    ^^^^^ help: consider borrowing here: `&vr[0]`
+   |                        --    ^^^^^
    |                        |
    |                        data moved here
    |                        move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     if let Either::One(_t) = &vr[0] { }
+   |                              +
 
 error[E0507]: cannot move out of index of `Vec<Either>`
-  --> $DIR/simple.rs:110:33
+  --> $DIR/simple.rs:97:33
    |
 LL |     while let Either::One(_t) = vr[0] { }
-   |                           --    ^^^^^ help: consider borrowing here: `&vr[0]`
+   |                           --    ^^^^^
    |                           |
    |                           data moved here
    |                           move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     while let Either::One(_t) = &vr[0] { }
+   |                                 +
 
 error[E0507]: cannot move out of index of `Vec<Either>`
-  --> $DIR/simple.rs:114:11
+  --> $DIR/simple.rs:100:11
    |
 LL |     match vr[0] {
-   |           ^^^^^ help: consider borrowing here: `&vr[0]`
+   |           ^^^^^
 ...
 LL |         Either::One(_t)
    |                     --
    |                     |
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     match &vr[0] {
+   |           +
 
 error[E0507]: cannot move out of index of `Vec<Either>`
-  --> $DIR/simple.rs:121:11
+  --> $DIR/simple.rs:106:11
    |
 LL |     match vr[0] {
-   |           ^^^^^ help: consider borrowing here: `&vr[0]`
+   |           ^^^^^
 ...
 LL |         Either::One(_t) => (),
    |                     --
    |                     |
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     match &vr[0] {
+   |           +
 
 error[E0507]: cannot move out of index of `Vec<X>`
-  --> $DIR/simple.rs:130:17
+  --> $DIR/simple.rs:114:17
    |
 LL |     let X(_t) = vsm[0];
-   |           --    ^^^^^^ help: consider borrowing here: `&vsm[0]`
+   |           --    ^^^^^^
    |           |
    |           data moved here
    |           move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     let X(_t) = &vsm[0];
+   |                 +
 
 error[E0507]: cannot move out of index of `Vec<Either>`
-  --> $DIR/simple.rs:134:30
+  --> $DIR/simple.rs:117:30
    |
 LL |     if let Either::One(_t) = vrm[0] { }
-   |                        --    ^^^^^^ help: consider borrowing here: `&vrm[0]`
+   |                        --    ^^^^^^
    |                        |
    |                        data moved here
    |                        move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     if let Either::One(_t) = &vrm[0] { }
+   |                              +
 
 error[E0507]: cannot move out of index of `Vec<Either>`
-  --> $DIR/simple.rs:138:33
+  --> $DIR/simple.rs:120:33
    |
 LL |     while let Either::One(_t) = vrm[0] { }
-   |                           --    ^^^^^^ help: consider borrowing here: `&vrm[0]`
+   |                           --    ^^^^^^
    |                           |
    |                           data moved here
    |                           move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     while let Either::One(_t) = &vrm[0] { }
+   |                                 +
 
 error[E0507]: cannot move out of index of `Vec<Either>`
-  --> $DIR/simple.rs:142:11
+  --> $DIR/simple.rs:123:11
    |
 LL |     match vrm[0] {
-   |           ^^^^^^ help: consider borrowing here: `&vrm[0]`
+   |           ^^^^^^
 ...
 LL |         Either::One(_t)
    |                     --
    |                     |
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     match &vrm[0] {
+   |           +
 
 error[E0507]: cannot move out of index of `Vec<Either>`
-  --> $DIR/simple.rs:149:11
+  --> $DIR/simple.rs:129:11
    |
 LL |     match vrm[0] {
-   |           ^^^^^^ help: consider borrowing here: `&vrm[0]`
+   |           ^^^^^^
 ...
 LL |         Either::One(_t) => (),
    |                     --
    |                     |
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     match &vrm[0] {
+   |           +
 
 error[E0507]: cannot move out of index of `Vec<Either>`
-  --> $DIR/simple.rs:157:11
+  --> $DIR/simple.rs:136:11
    |
 LL |     match vrm[0] {
-   |           ^^^^^^ help: consider borrowing here: `&vrm[0]`
+   |           ^^^^^^
 ...
 LL |         Either::One(_t) => (),
    |                     --
    |                     |
    |                     data moved here
    |                     move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     match &vrm[0] {
+   |           +
 
 error[E0507]: cannot move out of `s` which is behind a shared reference
-  --> $DIR/simple.rs:168:18
+  --> $DIR/simple.rs:146:18
    |
 LL |     let &X(_t) = s;
-   |         ------   ^
-   |         |  |
-   |         |  data moved here
-   |         |  move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `X(_t)`
+   |            --    ^
+   |            |
+   |            data moved here
+   |            move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     let &X(_t) = s;
+LL +     let X(_t) = s;
+   |
 
 error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
-  --> $DIR/simple.rs:172:31
+  --> $DIR/simple.rs:149:31
    |
 LL |     if let &Either::One(_t) = r { }
-   |            ----------------   ^
-   |            |            |
-   |            |            data moved here
-   |            |            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |            help: consider removing the `&`: `Either::One(_t)`
+   |                         --    ^
+   |                         |
+   |                         data moved here
+   |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     if let &Either::One(_t) = r { }
+LL +     if let Either::One(_t) = r { }
+   |
 
 error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
-  --> $DIR/simple.rs:176:34
+  --> $DIR/simple.rs:152:34
    |
 LL |     while let &Either::One(_t) = r { }
-   |               ----------------   ^
-   |               |            |
-   |               |            data moved here
-   |               |            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |               help: consider removing the `&`: `Either::One(_t)`
+   |                            --    ^
+   |                            |
+   |                            data moved here
+   |                            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     while let &Either::One(_t) = r { }
+LL +     while let Either::One(_t) = r { }
+   |
 
 error[E0507]: cannot move out of `r` as enum variant `Two` which is behind a shared reference
-  --> $DIR/simple.rs:180:11
+  --> $DIR/simple.rs:155:11
    |
 LL |     match r {
    |           ^
@@ -268,160 +404,215 @@ LL |         &Either::One(_t)
    |                      data moved here
    |                      move occurs because `_t` has type `X`, which does not implement the `Copy` trait
    |
-help: consider removing the `&`
+help: consider removing the borrow
    |
-LL ~         Either::One(_t)
-LL +
-LL +
-LL ~         | &Either::Two(_t) => (),
+LL -         &Either::One(_t)
+LL +         Either::One(_t)
    |
 
 error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
-  --> $DIR/simple.rs:188:11
+  --> $DIR/simple.rs:162:11
    |
 LL |     match r {
    |           ^
 LL |
 LL |         &Either::One(_t) => (),
-   |         ----------------
-   |         |            |
-   |         |            data moved here
-   |         |            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `Either::One(_t)`
+   |                      --
+   |                      |
+   |                      data moved here
+   |                      move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -         &Either::One(_t) => (),
+LL +         Either::One(_t) => (),
+   |
 
 error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
-  --> $DIR/simple.rs:195:11
+  --> $DIR/simple.rs:168:11
    |
 LL |     match r {
    |           ^
 LL |
 LL |         &Either::One(_t) => (),
-   |         ----------------
-   |         |            |
-   |         |            data moved here
-   |         |            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `Either::One(_t)`
+   |                      --
+   |                      |
+   |                      data moved here
+   |                      move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -         &Either::One(_t) => (),
+LL +         Either::One(_t) => (),
+   |
 
 error[E0507]: cannot move out of `sm` which is behind a mutable reference
-  --> $DIR/simple.rs:207:22
+  --> $DIR/simple.rs:178:22
    |
 LL |     let &mut X(_t) = sm;
-   |         ----------   ^^
-   |         |      |
-   |         |      data moved here
-   |         |      move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
-   |         help: consider removing the `&mut`: `X(_t)`
+   |                --    ^^
+   |                |
+   |                data moved here
+   |                move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -     let &mut X(_t) = sm;
+LL +     let X(_t) = sm;
+   |
 
 error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
-  --> $DIR/simple.rs:211:35
+  --> $DIR/simple.rs:181:35
    |
 LL |     if let &mut Either::One(_t) = rm { }
-   |            --------------------   ^^
-   |            |                |
-   |            |                data moved here
-   |            |                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |            help: consider removing the `&mut`: `Either::One(_t)`
+   |                             --    ^^
+   |                             |
+   |                             data moved here
+   |                             move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -     if let &mut Either::One(_t) = rm { }
+LL +     if let Either::One(_t) = rm { }
+   |
 
 error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
-  --> $DIR/simple.rs:215:38
+  --> $DIR/simple.rs:184:38
    |
 LL |     while let &mut Either::One(_t) = rm { }
-   |               --------------------   ^^
-   |               |                |
-   |               |                data moved here
-   |               |                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |               help: consider removing the `&mut`: `Either::One(_t)`
+   |                                --    ^^
+   |                                |
+   |                                data moved here
+   |                                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -     while let &mut Either::One(_t) = rm { }
+LL +     while let Either::One(_t) = rm { }
+   |
 
 error[E0507]: cannot move out of `rm` as enum variant `Two` which is behind a mutable reference
-  --> $DIR/simple.rs:219:11
+  --> $DIR/simple.rs:187:11
    |
 LL |     match rm {
    |           ^^
 LL |
 LL |         &mut Either::One(_t) => (),
    |                          -- data moved here
-...
+LL |
 LL |         &mut Either::Two(_t) => (),
    |                          -- ...and here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
-help: consider removing the `&mut`
+help: consider removing the mutable borrow
    |
-LL |         Either::One(_t) => (),
-   |         ~~~~~~~~~~~~~~~
-help: consider removing the `&mut`
+LL -         &mut Either::One(_t) => (),
+LL +         Either::One(_t) => (),
+   |
+help: consider removing the mutable borrow
+   |
+LL -         &mut Either::Two(_t) => (),
+LL +         Either::Two(_t) => (),
    |
-LL |         Either::Two(_t) => (),
-   |         ~~~~~~~~~~~~~~~
 
 error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
-  --> $DIR/simple.rs:228:11
+  --> $DIR/simple.rs:194:11
    |
 LL |     match rm {
    |           ^^
 LL |
 LL |         &mut Either::One(_t) => (),
-   |         --------------------
-   |         |                |
-   |         |                data moved here
-   |         |                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |         help: consider removing the `&mut`: `Either::One(_t)`
+   |                          --
+   |                          |
+   |                          data moved here
+   |                          move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -         &mut Either::One(_t) => (),
+LL +         Either::One(_t) => (),
+   |
 
 error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
-  --> $DIR/simple.rs:235:11
+  --> $DIR/simple.rs:200:11
    |
 LL |     match rm {
    |           ^^
 LL |
 LL |         &mut Either::One(_t) => (),
-   |         --------------------
-   |         |                |
-   |         |                data moved here
-   |         |                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |         help: consider removing the `&mut`: `Either::One(_t)`
+   |                          --
+   |                          |
+   |                          data moved here
+   |                          move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -         &mut Either::One(_t) => (),
+LL +         Either::One(_t) => (),
+   |
 
 error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
-  --> $DIR/simple.rs:242:11
+  --> $DIR/simple.rs:206:11
    |
 LL |     match rm {
    |           ^^
 LL |
 LL |         &mut Either::One(_t) => (),
-   |         --------------------
-   |         |                |
-   |         |                data moved here
-   |         |                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |         help: consider removing the `&mut`: `Either::One(_t)`
+   |                          --
+   |                          |
+   |                          data moved here
+   |                          move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -         &mut Either::One(_t) => (),
+LL +         Either::One(_t) => (),
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:258:21
+  --> $DIR/simple.rs:220:21
    |
 LL |     let (&X(_t),) = (&x.clone(),);
    |             --      ^^^^^^^^^^^^^
    |             |
    |             data moved here
    |             move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     let (&X(ref _t),) = (&x.clone(),);
+   |             +++
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:260:34
+  --> $DIR/simple.rs:223:34
    |
 LL |     if let (&Either::One(_t),) = (&e.clone(),) { }
    |                          --      ^^^^^^^^^^^^^
    |                          |
    |                          data moved here
    |                          move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     if let (&Either::One(ref _t),) = (&e.clone(),) { }
+   |                          +++
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:262:37
+  --> $DIR/simple.rs:226:37
    |
 LL |     while let (&Either::One(_t),) = (&e.clone(),) { }
    |                             --      ^^^^^^^^^^^^^
    |                             |
    |                             data moved here
    |                             move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     while let (&Either::One(ref _t),) = (&e.clone(),) { }
+   |                             +++
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:264:11
+  --> $DIR/simple.rs:229:11
    |
 LL |     match (&e.clone(),) {
    |           ^^^^^^^^^^^^^
@@ -431,79 +622,123 @@ LL |         (&Either::One(_t),)
    |                       |
    |                       data moved here
    |                       move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         (&Either::One(ref _t),)
+   |                       +++
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:272:25
+  --> $DIR/simple.rs:239:25
    |
 LL |     let (&mut X(_t),) = (&mut xm.clone(),);
    |                 --      ^^^^^^^^^^^^^^^^^^
    |                 |
    |                 data moved here
    |                 move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     let (&mut X(ref _t),) = (&mut xm.clone(),);
+   |                 +++
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:274:38
+  --> $DIR/simple.rs:242:38
    |
 LL |     if let (&mut Either::One(_t),) = (&mut em.clone(),) { }
    |                              --      ^^^^^^^^^^^^^^^^^^
    |                              |
    |                              data moved here
    |                              move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     if let (&mut Either::One(ref _t),) = (&mut em.clone(),) { }
+   |                              +++
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:276:41
+  --> $DIR/simple.rs:245:41
    |
 LL |     while let (&mut Either::One(_t),) = (&mut em.clone(),) { }
    |                                 --      ^^^^^^^^^^^^^^^^^^
    |                                 |
    |                                 data moved here
    |                                 move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     while let (&mut Either::One(ref _t),) = (&mut em.clone(),) { }
+   |                                 +++
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:278:11
+  --> $DIR/simple.rs:248:11
    |
 LL |     match (&mut em.clone(),) {
    |           ^^^^^^^^^^^^^^^^^^
 LL |
 LL |         (&mut Either::One(_t),) => (),
    |                           -- data moved here
+LL |
 LL |         (&mut Either::Two(_t),) => (),
    |                           -- ...and here
    |
    = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider borrowing the pattern binding
+   |
+LL |         (&mut Either::One(ref _t),) => (),
+   |                           +++
+help: consider borrowing the pattern binding
+   |
+LL |         (&mut Either::Two(ref _t),) => (),
+   |                           +++
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:288:18
+  --> $DIR/simple.rs:261:18
    |
 LL |     let &X(_t) = &x;
-   |         ------   ^^
-   |         |  |
-   |         |  data moved here
-   |         |  move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `X(_t)`
+   |            --    ^^
+   |            |
+   |            data moved here
+   |            move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     let &X(_t) = &x;
+LL +     let X(_t) = &x;
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:292:31
+  --> $DIR/simple.rs:264:31
    |
 LL |     if let &Either::One(_t) = &e { }
-   |            ----------------   ^^
-   |            |            |
-   |            |            data moved here
-   |            |            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |            help: consider removing the `&`: `Either::One(_t)`
+   |                         --    ^^
+   |                         |
+   |                         data moved here
+   |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     if let &Either::One(_t) = &e { }
+LL +     if let Either::One(_t) = &e { }
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:296:34
+  --> $DIR/simple.rs:267:34
    |
 LL |     while let &Either::One(_t) = &e { }
-   |               ----------------   ^^
-   |               |            |
-   |               |            data moved here
-   |               |            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |               help: consider removing the `&`: `Either::One(_t)`
+   |                            --    ^^
+   |                            |
+   |                            data moved here
+   |                            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     while let &Either::One(_t) = &e { }
+LL +     while let Either::One(_t) = &e { }
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:300:11
+  --> $DIR/simple.rs:270:11
    |
 LL |     match &e {
    |           ^^
@@ -514,72 +749,95 @@ LL |         &Either::One(_t)
    |                      data moved here
    |                      move occurs because `_t` has type `X`, which does not implement the `Copy` trait
    |
-help: consider removing the `&`
+help: consider removing the borrow
    |
-LL ~         Either::One(_t)
-LL +
-LL +
-LL ~         | &Either::Two(_t) => (),
+LL -         &Either::One(_t)
+LL +         Either::One(_t)
    |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:308:11
+  --> $DIR/simple.rs:277:11
    |
 LL |     match &e {
    |           ^^
 LL |
 LL |         &Either::One(_t) => (),
-   |         ----------------
-   |         |            |
-   |         |            data moved here
-   |         |            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `Either::One(_t)`
+   |                      --
+   |                      |
+   |                      data moved here
+   |                      move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -         &Either::One(_t) => (),
+LL +         Either::One(_t) => (),
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:315:11
+  --> $DIR/simple.rs:283:11
    |
 LL |     match &e {
    |           ^^
 LL |
 LL |         &Either::One(_t) => (),
-   |         ----------------
-   |         |            |
-   |         |            data moved here
-   |         |            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |         help: consider removing the `&`: `Either::One(_t)`
+   |                      --
+   |                      |
+   |                      data moved here
+   |                      move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -         &Either::One(_t) => (),
+LL +         Either::One(_t) => (),
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:323:22
+  --> $DIR/simple.rs:290:22
    |
 LL |     let &mut X(_t) = &mut xm;
-   |         ----------   ^^^^^^^
-   |         |      |
-   |         |      data moved here
-   |         |      move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
-   |         help: consider removing the `&mut`: `X(_t)`
+   |                --    ^^^^^^^
+   |                |
+   |                data moved here
+   |                move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -     let &mut X(_t) = &mut xm;
+LL +     let X(_t) = &mut xm;
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:327:35
+  --> $DIR/simple.rs:293:35
    |
 LL |     if let &mut Either::One(_t) = &mut em { }
-   |            --------------------   ^^^^^^^
-   |            |                |
-   |            |                data moved here
-   |            |                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |            help: consider removing the `&mut`: `Either::One(_t)`
+   |                             --    ^^^^^^^
+   |                             |
+   |                             data moved here
+   |                             move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -     if let &mut Either::One(_t) = &mut em { }
+LL +     if let Either::One(_t) = &mut em { }
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:331:38
+  --> $DIR/simple.rs:296:38
    |
 LL |     while let &mut Either::One(_t) = &mut em { }
-   |               --------------------   ^^^^^^^
-   |               |                |
-   |               |                data moved here
-   |               |                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |               help: consider removing the `&mut`: `Either::One(_t)`
+   |                                --    ^^^^^^^
+   |                                |
+   |                                data moved here
+   |                                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -     while let &mut Either::One(_t) = &mut em { }
+LL +     while let Either::One(_t) = &mut em { }
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:335:11
+  --> $DIR/simple.rs:299:11
    |
 LL |     match &mut em {
    |           ^^^^^^^
@@ -590,91 +848,138 @@ LL |         &mut Either::One(_t)
    |                          data moved here
    |                          move occurs because `_t` has type `X`, which does not implement the `Copy` trait
    |
-help: consider removing the `&mut`
+help: consider removing the mutable borrow
    |
-LL ~         Either::One(_t)
-LL +
-LL +
-LL ~         | &mut Either::Two(_t) => (),
+LL -         &mut Either::One(_t)
+LL +         Either::One(_t)
    |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:343:11
+  --> $DIR/simple.rs:306:11
    |
 LL |     match &mut em {
    |           ^^^^^^^
 LL |
 LL |         &mut Either::One(_t) => (),
-   |         --------------------
-   |         |                |
-   |         |                data moved here
-   |         |                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |         help: consider removing the `&mut`: `Either::One(_t)`
+   |                          --
+   |                          |
+   |                          data moved here
+   |                          move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -         &mut Either::One(_t) => (),
+LL +         Either::One(_t) => (),
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:350:11
+  --> $DIR/simple.rs:312:11
    |
 LL |     match &mut em {
    |           ^^^^^^^
 LL |
 LL |         &mut Either::One(_t) => (),
-   |         --------------------
-   |         |                |
-   |         |                data moved here
-   |         |                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |         help: consider removing the `&mut`: `Either::One(_t)`
+   |                          --
+   |                          |
+   |                          data moved here
+   |                          move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -         &mut Either::One(_t) => (),
+LL +         Either::One(_t) => (),
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:357:11
+  --> $DIR/simple.rs:318:11
    |
 LL |     match &mut em {
    |           ^^^^^^^
 LL |
 LL |         &mut Either::One(_t) => (),
-   |         --------------------
-   |         |                |
-   |         |                data moved here
-   |         |                move occurs because `_t` has type `X`, which does not implement the `Copy` trait
-   |         help: consider removing the `&mut`: `Either::One(_t)`
+   |                          --
+   |                          |
+   |                          data moved here
+   |                          move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -         &mut Either::One(_t) => (),
+LL +         Either::One(_t) => (),
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:202:11
+  --> $DIR/simple.rs:174:11
    |
 LL |     fn f1(&X(_t): &X) { }
    |           ^^^--^
-   |           |  |
-   |           |  data moved here
-   |           |  move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
-   |           help: consider removing the `&`: `X(_t)`
+   |              |
+   |              data moved here
+   |              move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     fn f1(&X(_t): &X) { }
+LL +     fn f1(X(_t): &X) { }
+   |
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:249:11
+  --> $DIR/simple.rs:212:11
    |
 LL |     fn f2(&mut X(_t): &mut X) { }
    |           ^^^^^^^--^
-   |           |      |
-   |           |      data moved here
-   |           |      move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
-   |           help: consider removing the `&mut`: `X(_t)`
+   |                  |
+   |                  data moved here
+   |                  move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider removing the mutable borrow
+   |
+LL -     fn f2(&mut X(_t): &mut X) { }
+LL +     fn f2(X(_t): &mut X) { }
+   |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/simple.rs:269:11
+  --> $DIR/simple.rs:235:11
    |
 LL |     fn f3((&X(_t),): (&X,)) { }
    |           ^^^^--^^^
    |               |
    |               data moved here
    |               move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     fn f3((&X(ref _t),): (&X,)) { }
+   |               +++
 
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/simple.rs:283:11
+  --> $DIR/simple.rs:255:11
    |
 LL |     fn f4((&mut X(_t),): (&mut X,)) { }
    |           ^^^^^^^^--^^^
    |                   |
    |                   data moved here
    |                   move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     fn f4((&mut X(ref _t),): (&mut X,)) { }
+   |                   +++
+
+error[E0507]: cannot move out of `a.a` as enum variant `Some` which is behind a shared reference
+  --> $DIR/simple.rs:331:20
+   |
+LL |     let Some(_s) = a.a else {
+   |              --    ^^^
+   |              |
+   |              data moved here
+   |              move occurs because `_s` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |     let Some(ref _s) = a.a else {
+   |              +++
 
-error: aborting due to 60 previous errors
+error: aborting due to 61 previous errors
 
 For more information about this error, try `rustc --explain E0507`.
index 4e21d36014c9045afc27508826558583a308670e..bc6342004f4db638b4cdb89015a2127ce0cb7bab 100644 (file)
@@ -2,7 +2,10 @@ error[E0308]: mismatched types
   --> $DIR/dont-suggest-try_into-in-macros.rs:2:5
    |
 LL |     assert_eq!(10u64, 10usize);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u64`, found `usize`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     expected `u64`, found `usize`
+   |     expected because this is `u64`
    |
    = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
index 34ff59a9bb0508185e9f889c124c8bb9c0afd458..b1e04dab8f623853794cc53cc468b1fdaf3a876d 100644 (file)
@@ -41,9 +41,6 @@ LL |     Pin::new(x)
            found type parameter `F`
 note: associated function defined here
   --> $SRC_DIR/core/src/pin.rs:LL:COL
-   |
-LL |     pub const fn new(pointer: P) -> Pin<P> {
-   |                  ^^^
 
 error[E0277]: `dyn Future<Output = i32> + Send` cannot be unpinned
   --> $DIR/expected-boxed-future-isnt-pinned.rs:19:14
@@ -56,9 +53,6 @@ LL |     Pin::new(x)
    = note: consider using `Box::pin`
 note: required by a bound in `Pin::<P>::new`
   --> $SRC_DIR/core/src/pin.rs:LL:COL
-   |
-LL | impl<P: Deref<Target: Unpin>> Pin<P> {
-   |                       ^^^^^ required by this bound in `Pin::<P>::new`
 
 error[E0277]: `dyn Future<Output = i32> + Send` cannot be unpinned
   --> $DIR/expected-boxed-future-isnt-pinned.rs:24:14
@@ -71,9 +65,6 @@ LL |     Pin::new(Box::new(x))
    = note: consider using `Box::pin`
 note: required by a bound in `Pin::<P>::new`
   --> $SRC_DIR/core/src/pin.rs:LL:COL
-   |
-LL | impl<P: Deref<Target: Unpin>> Pin<P> {
-   |                       ^^^^^ required by this bound in `Pin::<P>::new`
 
 error[E0308]: mismatched types
   --> $DIR/expected-boxed-future-isnt-pinned.rs:28:5
@@ -90,9 +81,6 @@ LL | |     }
            found `async` block `[async block@$DIR/expected-boxed-future-isnt-pinned.rs:28:5: 30:6]`
 note: function defined here
   --> $SRC_DIR/core/src/future/mod.rs:LL:COL
-   |
-LL | pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut {
-   |              ^^^^^^^^^^^^^^^
 help: you need to pin and box this expression
    |
 LL ~     Box::pin(async {
index 88be9e30a764125261b822c14a6e7c761d4d26a2..c5b81e6b87174d209ce65331def3447c7f8df707 100644 (file)
@@ -7,11 +7,8 @@ LL |         for _ in self.v {
    |                  `self.v` moved due to this implicit call to `.into_iter()`
    |                  move occurs because `self.v` has type `Vec<u32>`, which does not implement the `Copy` trait
    |
-note: this function takes ownership of the receiver `self`, which moves `self.v`
+note: `into_iter` takes ownership of the receiver `self`, which moves `self.v`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 help: consider iterating over a slice of the `Vec<u32>`'s content to avoid moving into the `for` loop
    |
 LL |         for _ in &self.v {
@@ -40,11 +37,8 @@ LL |     for loader in *LOADERS {
    |                   value moved due to this implicit call to `.into_iter()`
    |                   move occurs because value has type `Vec<&u8>`, which does not implement the `Copy` trait
    |
-note: this function takes ownership of the receiver `self`, which moves value
+note: `into_iter` takes ownership of the receiver `self`, which moves value
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-   |
-LL |     fn into_iter(self) -> Self::IntoIter;
-   |                  ^^^^
 help: consider iterating over a slice of the `Vec<&u8>`'s content to avoid moving into the `for` loop
    |
 LL |     for loader in &*LOADERS {
index 42ca3a78d8f9f70ef5c222f7a7f18c30461711f9..7791b308d5d0e597a4263c6afb85570b07f1158a 100644 (file)
@@ -3,11 +3,9 @@ error: the `min` method cannot be invoked on a trait object
    |
 LL |      t.min().unwrap()
    |        ^^^
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-   |
-LL |         Self: Sized,
-   |               ----- this has a `Sized` requirement
+   = note: this has a `Sized` requirement
    |
    = note: you need `&mut dyn Iterator<Item = &u64>` instead of `&dyn Iterator<Item = &u64>`
 
index bac8de7987256058de5b5f0312b41cdffd326ee6..f159b51a26969fec807e8cd5cb7c8dfde6fe85c9 100644 (file)
@@ -3,11 +3,9 @@ error[E0599]: no method named `finish` found for struct `DefaultHasher` in the c
    |
 LL |     h.finish()
    |       ^^^^^^ method not found in `DefaultHasher`
+  --> $SRC_DIR/core/src/hash/mod.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/hash/mod.rs:LL:COL
-   |
-LL |     fn finish(&self) -> u64;
-   |        ------ the method is available for `DefaultHasher` here
+   = note: the method is available for `DefaultHasher` here
    |
    = help: items from traits can only be used if the trait is in scope
 help: the following trait is implemented but not in scope; perhaps add a `use` for it:
index 4b302dd6509192f79b5367406b2594e248ac4f2a..79812a2985ef9444f0d46f15a698e19916fbeed3 100644 (file)
@@ -11,12 +11,6 @@ LL |     simd_gt::<()>(x);
    |     ^^^^^^^------ help: remove these generics
    |     |
    |     expected 0 generic arguments
-   |
-note: associated function defined here, with 0 generic parameters
-  --> $SRC_DIR/core/src/../../portable-simd/crates/core_simd/src/ord.rs:LL:COL
-   |
-LL |     fn simd_gt(self, other: Self) -> Self::Mask;
-   |        ^^^^^^^
 
 error[E0425]: cannot find function `simd_gt` in this scope
   --> $DIR/issue-104287.rs:6:5
diff --git a/src/test/ui/suggestions/issue-104327.rs b/src/test/ui/suggestions/issue-104327.rs
new file mode 100644 (file)
index 0000000..dd621ae
--- /dev/null
@@ -0,0 +1,12 @@
+trait Bar {}
+
+trait Foo {
+    fn f() {}
+}
+
+impl Foo for dyn Bar {}
+
+fn main() {
+    Foo::f();
+    //~^ ERROR cannot call associated function on trait without specifying the corresponding `impl` type
+}
diff --git a/src/test/ui/suggestions/issue-104327.stderr b/src/test/ui/suggestions/issue-104327.stderr
new file mode 100644 (file)
index 0000000..acec3a5
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
+  --> $DIR/issue-104327.rs:10:5
+   |
+LL |     fn f() {}
+   |     --------- `Foo::f` defined here
+...
+LL |     Foo::f();
+   |     ^^^^^^ cannot call associated function of trait
+   |
+help: use the fully-qualified path to the only available implementation
+   |
+LL |     <(dyn Bar + 'static) as Foo>::f();
+   |     +++++++++++++++++++++++    +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0790`.
diff --git a/src/test/ui/suggestions/issue-104328.rs b/src/test/ui/suggestions/issue-104328.rs
new file mode 100644 (file)
index 0000000..c3707ba
--- /dev/null
@@ -0,0 +1,12 @@
+#![feature(object_safe_for_dispatch)]
+
+trait Foo {
+    fn f() {}
+}
+
+impl Foo for dyn Sized {}
+
+fn main() {
+    Foo::f();
+    //~^ ERROR cannot call associated function on trait without specifying the corresponding `impl` type
+}
diff --git a/src/test/ui/suggestions/issue-104328.stderr b/src/test/ui/suggestions/issue-104328.stderr
new file mode 100644 (file)
index 0000000..b31b847
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
+  --> $DIR/issue-104328.rs:10:5
+   |
+LL |     fn f() {}
+   |     --------- `Foo::f` defined here
+...
+LL |     Foo::f();
+   |     ^^^^^^ cannot call associated function of trait
+   |
+help: use the fully-qualified path to the only available implementation
+   |
+LL |     <(dyn Sized + 'static) as Foo>::f();
+   |     +++++++++++++++++++++++++    +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0790`.
diff --git a/src/test/ui/suggestions/issue-105226.rs b/src/test/ui/suggestions/issue-105226.rs
new file mode 100644 (file)
index 0000000..f123dbf
--- /dev/null
@@ -0,0 +1,22 @@
+use std::fmt;
+
+struct S {
+}
+
+impl S {
+    fn hello<P>(&self, val: &P) where P: fmt::Display; {
+        //~^ ERROR non-item in item list
+        //~| ERROR associated function in `impl` without body
+        println!("val: {}", val);
+    }
+}
+
+impl S {
+    fn hello_empty<P>(&self, val: &P) where P: fmt::Display;
+    //~^ ERROR associated function in `impl` without body
+}
+
+fn main() {
+    let s = S{};
+    s.hello(&32);
+}
diff --git a/src/test/ui/suggestions/issue-105226.stderr b/src/test/ui/suggestions/issue-105226.stderr
new file mode 100644 (file)
index 0000000..f16a809
--- /dev/null
@@ -0,0 +1,31 @@
+error: non-item in item list
+  --> $DIR/issue-105226.rs:7:56
+   |
+LL | impl S {
+   |        - item list starts here
+LL |     fn hello<P>(&self, val: &P) where P: fmt::Display; {
+   |                                                      - ^ non-item starts here
+   |                                                      |
+   |                                                      help: consider removing this semicolon
+...
+LL | }
+   | - item list ends here
+
+error: associated function in `impl` without body
+  --> $DIR/issue-105226.rs:7:5
+   |
+LL |     fn hello<P>(&self, val: &P) where P: fmt::Display; {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |                                                      |
+   |                                                      help: provide a definition for the function: `{ <body> }`
+
+error: associated function in `impl` without body
+  --> $DIR/issue-105226.rs:15:5
+   |
+LL |     fn hello_empty<P>(&self, val: &P) where P: fmt::Display;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |                                                            |
+   |                                                            help: provide a definition for the function: `{ <body> }`
+
+error: aborting due to 3 previous errors
+
index 62f0943d4c9d99f1466df7eab512747d0eaed232..b6e271de8076c700487ebea36b4c6c0c04c160f1 100644 (file)
@@ -10,9 +10,6 @@ LL |     println!("{:?}", line.find(pattern));
    = note: required for `String` to implement `Pattern<'_>`
 note: required by a bound in `core::str::<impl str>::find`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
-   |
-LL |     pub fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> {
-   |                        ^^^^^^^^^^^ required by this bound in `core::str::<impl str>::find`
 help: consider borrowing here
    |
 LL |     println!("{:?}", line.find(&pattern));
index 684db23e1355f3ff31f596d73198298221964bd2..a5e6f5b5ffcb0a40fa7a4041ea1baff58bdd7042 100644 (file)
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `&[i8]: From<&[u8]>` is not satisfied
-  --> $DIR/issue-71394-no-from-impl.rs:3:20
+  --> $DIR/issue-71394-no-from-impl.rs:3:25
    |
 LL |     let _: &[i8] = data.into();
-   |                    ^^^^ ---- required by a bound introduced by this call
-   |                    |
-   |                    the trait `From<&[u8]>` is not implemented for `&[i8]`
+   |                         ^^^^ the trait `From<&[u8]>` is not implemented for `&[i8]`
    |
    = help: the following other types implement trait `From<T>`:
              <[T; LANES] as From<Simd<T, LANES>>>
index 8b2a388162806e86866c4da9657ffafad3b83024..93d8da226c817f35f99cd09ca8e9329881d4a47d 100644 (file)
@@ -62,11 +62,6 @@ error[E0107]: this associated function takes 0 generic arguments but 1 generic a
 LL |     let _ = 42.into::<Option<_>>();
    |                ^^^^ expected 0 generic arguments
    |
-note: associated function defined here, with 0 generic parameters
-  --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
-   |
-LL |     fn into(self) -> T;
-   |        ^^^^
 help: consider moving this generic argument to the `Into` trait, which takes up to 1 argument
    |
 LL |     let _ = Into::<Option<_>>::into(42);
index d121932c842e35324a8a8f1060e4713f8dd8ab0c..6910b77d9bc3fa1874c69f464fba0e1b1444ef3b 100644 (file)
@@ -9,9 +9,6 @@ LL |     let fp = BufWriter::new(fp);
    = note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write`
 note: required by a bound in `BufWriter::<W>::new`
   --> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL
-   |
-LL | impl<W: Write> BufWriter<W> {
-   |         ^^^^^ required by this bound in `BufWriter::<W>::new`
 
 error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied
   --> $DIR/mut-borrow-needed-by-trait.rs:17:14
@@ -22,20 +19,15 @@ LL |     let fp = BufWriter::new(fp);
    = note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write`
 note: required by a bound in `BufWriter`
   --> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL
-   |
-LL | pub struct BufWriter<W: Write> {
-   |                         ^^^^^ required by this bound in `BufWriter`
 
-error[E0599]: the method `write_fmt` exists for struct `BufWriter<&dyn std::io::Write>`, but its trait bounds were not satisfied
+error[E0599]: the method `write_fmt` exists for struct `BufWriter<&dyn Write>`, but its trait bounds were not satisfied
   --> $DIR/mut-borrow-needed-by-trait.rs:21:5
    |
 LL |     writeln!(fp, "hello world").unwrap();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `BufWriter<&dyn std::io::Write>` due to unsatisfied trait bounds
-   |
-  ::: $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `BufWriter<&dyn Write>` due to unsatisfied trait bounds
+  --> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL
    |
-LL | pub struct BufWriter<W: Write> {
-   | ------------------------------ doesn't satisfy `BufWriter<&dyn std::io::Write>: std::io::Write`
+   = note: doesn't satisfy `BufWriter<&dyn std::io::Write>: std::io::Write`
    |
    = note: the following trait bounds were not satisfied:
            `&dyn std::io::Write: std::io::Write`
index debb8cabaea027b557bccdb05753adc85d2678cf..97d05d9dcffaf840cef3f3640cac2fe823c63a83 100644 (file)
@@ -9,6 +9,11 @@ LL |         (None, &c) => &c.unwrap(),
    |                 |
    |                 data moved here
    |                 move occurs because `c` has type `Option<String>`, which does not implement the `Copy` trait
+   |
+help: consider borrowing the pattern binding
+   |
+LL |         (None, &ref c) => &c.unwrap(),
+   |                 +++
 
 error: aborting due to previous error
 
index a6f1ebc975fd5bc450fcfadc41d43a568cb420c5..3e0271d02572b98354603945119ef6803b174d64 100644 (file)
@@ -7,11 +7,8 @@ LL |                 if selection.1.unwrap().contains(selection.0) {
    |                    help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
    |                    move occurs because `selection.1` has type `Option<String>`, which does not implement the `Copy` trait
    |
-note: this function takes ownership of the receiver `self`, which moves `selection.1`
+note: `Option::<T>::unwrap` takes ownership of the receiver `self`, which moves `selection.1`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     pub const fn unwrap(self) -> T {
-   |                         ^^^^
 
 error[E0507]: cannot move out of `selection.1` which is behind a shared reference
   --> $DIR/option-content-move.rs:27:20
@@ -22,11 +19,8 @@ LL |                 if selection.1.unwrap().contains(selection.0) {
    |                    help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
    |                    move occurs because `selection.1` has type `Result<String, String>`, which does not implement the `Copy` trait
    |
-note: this function takes ownership of the receiver `self`, which moves `selection.1`
+note: `Result::<T, E>::unwrap` takes ownership of the receiver `self`, which moves `selection.1`
   --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     pub fn unwrap(self) -> T
-   |                   ^^^^
 
 error: aborting due to 2 previous errors
 
index 57a934b83420cc0da80c5d74b191c946cafb1d0c..4050c7be82a0af369c459b9cc5f36217cc153746 100644 (file)
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/option-to-bool.rs:4:16
    |
 LL |     if true && x {}
-   |                ^ expected `bool`, found enum `Option`
+   |        ----    ^ expected `bool`, found enum `Option`
+   |        |
+   |        expected because this is `bool`
    |
    = note: expected type `bool`
               found enum `Option<i32>`
index e7d9c5ecbe48208a720fac6deb23cfff4778b96a..5434472ceecc7605e3b324553e86d07a6acb0517 100644 (file)
@@ -11,11 +11,8 @@ note: an implementation of `Add<_>` might be missing for `Wrapper<T>`
    |
 LL | struct Wrapper<T>(T);
    | ^^^^^^^^^^^^^^^^^ must implement `Add<_>`
-note: the following trait must be implemented
+note: the trait `Add` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait Add<Rhs = Self> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
    |
 LL | fn qux<T>(a: Wrapper<T>, b: T) -> T where Wrapper<T>: Add<T, Output = T> {
index 55a0eee18179a17b4a1afab55efbe4eafd1a389a..da4db46aad3d67d36178d0fd831f56afc1f12cec 100644 (file)
@@ -10,9 +10,6 @@ LL |     let _s = y.unwrap_or(|| x.split('.').nth(1).unwrap());
                 found closure `[closure@$DIR/sugg-else-for-closure.rs:6:26: 6:28]`
 note: associated function defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     pub const fn unwrap_or(self, default: T) -> T
-   |                  ^^^^^^^^^
 help: try calling `unwrap_or_else` instead
    |
 LL |     let _s = y.unwrap_or_else(|| x.split('.').nth(1).unwrap());
index 889b11a741084c09f25260b17841ca65dde369e8..d194afeaf931d96f3032011e3338cd633a4645a1 100644 (file)
@@ -8,9 +8,6 @@ LL |         let mut stream_reader = BufReader::new(&stream);
    |
 note: required by a bound in `BufReader::<R>::new`
   --> $SRC_DIR/std/src/io/buffered/bufreader.rs:LL:COL
-   |
-LL | impl<R: Read> BufReader<R> {
-   |         ^^^^ required by this bound in `BufReader::<R>::new`
 help: consider removing the leading `&`-reference
    |
 LL -         let mut stream_reader = BufReader::new(&stream);
@@ -30,11 +27,9 @@ error[E0599]: the method `read_until` exists for struct `BufReader<&T>`, but its
    |
 LL |         stream_reader.read_until(b'\n', &mut buffer).expect("Reading into buffer failed");
    |                       ^^^^^^^^^^ method cannot be called on `BufReader<&T>` due to unsatisfied trait bounds
+  --> $SRC_DIR/std/src/io/buffered/bufreader.rs:LL:COL
    |
-  ::: $SRC_DIR/std/src/io/buffered/bufreader.rs:LL:COL
-   |
-LL | pub struct BufReader<R> {
-   | ----------------------- doesn't satisfy `BufReader<&T>: BufRead`
+   = note: doesn't satisfy `BufReader<&T>: BufRead`
    |
    = note: the following trait bounds were not satisfied:
            `&T: std::io::Read`
index 3d1f2492360bf29ba658b5e469f2a526f9636bc4..018083f9e03af40468b781c6ec63b4b8bdb04b8b 100644 (file)
@@ -52,11 +52,9 @@ error[E0599]: no method named `try_into` found for type `i32` in the current sco
    |
 LL |     let _i: i16 = 0_i32.try_into().unwrap();
    |                         ^^^^^^^^ method not found in `i32`
+  --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/convert/mod.rs:LL:COL
-   |
-LL |     fn try_into(self) -> Result<T, Self::Error>;
-   |        -------- the method is available for `i32` here
+   = note: the method is available for `i32` here
    |
    = help: items from traits can only be used if the trait is in scope
    = note: 'std::convert::TryInto' is included in the prelude starting in Edition 2021
index 951ff23d635635084a59d45fcd6145b7db8f19c0..fcff02e09dbb1ade66e0f1b28dfdeebc46ab4e3a 100644 (file)
@@ -24,11 +24,6 @@ error[E0107]: this struct takes at least 1 generic argument but 0 generic argume
 LL |     let _: Vec<A:B> = A::B;
    |            ^^^ expected at least 1 generic argument
    |
-note: struct defined here, with at least 1 generic parameter: `T`
-  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
-   |            ^^^ -
 help: add missing generic argument
    |
 LL |     let _: Vec<T, A:B> = A::B;
index 773f1392ae7655827c2e619bf95beefdcefb48a8..34eaa8322c8701e70f451c34a510a4567055d18d 100644 (file)
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/unnecessary_dot_for_floating_point_literal.rs:2:18
    |
 LL |     let _: f64 = 0..10;
-   |            ---   ^^^^^ expected `f64`, found struct `std::ops::Range`
+   |            ---   ^^^^^ expected `f64`, found struct `Range`
    |            |
    |            expected due to this
    |
@@ -47,7 +47,7 @@ error[E0308]: mismatched types
   --> $DIR/unnecessary_dot_for_floating_point_literal.rs:5:18
    |
 LL |     let _: f64 = std::ops::Range { start: 0, end: 1 };
-   |            ---   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `f64`, found struct `std::ops::Range`
+   |            ---   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `f64`, found struct `Range`
    |            |
    |            expected due to this
    |
index 76a068e864a3c6380ac1822aa379441f38ca6baf..0d3f794aa0f7af882d9da1f487bd37c13c6e14a5 100644 (file)
@@ -12,11 +12,9 @@ error[E0393]: the type parameter `Rhs` must be explicitly specified
    |
 LL | struct Foo<T>(dyn SendEqAlias<T>);
    |                   ^^^^^^^^^^^^^^ missing reference to `Rhs`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub trait PartialEq<Rhs: ?Sized = Self> {
-   | --------------------------------------- type parameter `Rhs` must be specified for this
+   = note: type parameter `Rhs` must be specified for this
    |
    = note: because of the default `Self` reference, type parameters must be specified on object types
 
@@ -25,11 +23,9 @@ error[E0393]: the type parameter `Rhs` must be explicitly specified
    |
 LL | struct Bar<T>(dyn SendEqAlias<T>, T);
    |                   ^^^^^^^^^^^^^^ missing reference to `Rhs`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub trait PartialEq<Rhs: ?Sized = Self> {
-   | --------------------------------------- type parameter `Rhs` must be specified for this
+   = note: type parameter `Rhs` must be specified for this
    |
    = note: because of the default `Self` reference, type parameters must be specified on object types
 
index 325bc6d2808595c9eaf2b34ee8a633fe2fccfe27..048a150df8c521c497d143190b8ed6c4b561e4c4 100644 (file)
@@ -7,8 +7,7 @@ LL |     let _: &dyn EqAlias = &123;
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
    |
-LL | pub trait Eq: PartialEq<Self> {
-   |               ^^^^^^^^^^^^^^^ the trait cannot be made into an object because it uses `Self` as a type parameter
+   = note: the trait cannot be made into an object because it uses `Self` as a type parameter
 
 error[E0191]: the value of the associated type `Item` (from trait `Iterator`) must be specified
   --> $DIR/object-fail.rs:9:17
index d7d6241ef708cda1a68a922940d7a3963417a6ba..65340b2a2092ff5cdf345a4c08703603d70c0ee1 100644 (file)
@@ -10,7 +10,7 @@ pub trait Foo: Iterator<Item = <Self as Foo>::Key> {
 
 impl Foo for IntoIter<i32> {
     type Key = u32;
-    //~^ ERROR expected `std::vec::IntoIter<i32>` to be an iterator that yields `u32`, but it yields `i32`
+    //~^ ERROR expected `IntoIter<i32>` to be an iterator that yields `u32`, but it yields `i32`
 }
 
 fn main() {}
index 3e2d9d9038aa7c1e6b8655cd3fdf668cc42f6190..7fa1d2c2eed67c8fd85f48d77f1aa019a3d36fb7 100644 (file)
@@ -1,4 +1,4 @@
-error[E0271]: expected `std::vec::IntoIter<i32>` to be an iterator that yields `u32`, but it yields `i32`
+error[E0271]: expected `IntoIter<i32>` to be an iterator that yields `u32`, but it yields `i32`
   --> $DIR/assoc-type-in-superbad.rs:12:16
    |
 LL |     type Key = u32;
index 9ca446a0a891d82ecb0436977b226f971a18b68d..5be334986418292c4f98d9c4020bd7c09c17e0ca 100644 (file)
@@ -9,11 +9,9 @@ error[E0404]: expected trait, found struct `String`
    |
 LL | struct Foo<T> where T: Bar, <T as Bar>::Baz: String {
    |                                              ^^^^^^ not a trait
+  --> $SRC_DIR/alloc/src/string.rs:LL:COL
    |
-  ::: $SRC_DIR/alloc/src/string.rs:LL:COL
-   |
-LL | pub trait ToString {
-   | ------------------ similarly named trait `ToString` defined here
+   = note: similarly named trait `ToString` defined here
    |
 help: constrain the associated type to `String`
    |
@@ -29,11 +27,9 @@ error[E0404]: expected trait, found struct `String`
    |
 LL | struct Qux<'a, T> where T: Bar, <&'a T as Bar>::Baz: String {
    |                                                      ^^^^^^ not a trait
+  --> $SRC_DIR/alloc/src/string.rs:LL:COL
    |
-  ::: $SRC_DIR/alloc/src/string.rs:LL:COL
-   |
-LL | pub trait ToString {
-   | ------------------ similarly named trait `ToString` defined here
+   = note: similarly named trait `ToString` defined here
    |
 help: constrain the associated type to `String`
    |
@@ -49,11 +45,9 @@ error[E0404]: expected trait, found struct `String`
    |
 LL | fn foo<T: Bar>(_: T) where <T as Bar>::Baz: String {
    |                                             ^^^^^^ not a trait
+  --> $SRC_DIR/alloc/src/string.rs:LL:COL
    |
-  ::: $SRC_DIR/alloc/src/string.rs:LL:COL
-   |
-LL | pub trait ToString {
-   | ------------------ similarly named trait `ToString` defined here
+   = note: similarly named trait `ToString` defined here
    |
 help: constrain the associated type to `String`
    |
@@ -69,11 +63,9 @@ error[E0404]: expected trait, found struct `String`
    |
 LL | fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: String {
    |                                                         ^^^^^^ not a trait
+  --> $SRC_DIR/alloc/src/string.rs:LL:COL
    |
-  ::: $SRC_DIR/alloc/src/string.rs:LL:COL
-   |
-LL | pub trait ToString {
-   | ------------------ similarly named trait `ToString` defined here
+   = note: similarly named trait `ToString` defined here
    |
 help: constrain the associated type to `String`
    |
@@ -89,11 +81,9 @@ error[E0404]: expected trait, found struct `String`
    |
 LL | fn issue_95327() where <u8 as Unresolved>::Assoc: String {}
    |                                                   ^^^^^^ help: a trait with a similar name exists: `ToString`
+  --> $SRC_DIR/alloc/src/string.rs:LL:COL
    |
-  ::: $SRC_DIR/alloc/src/string.rs:LL:COL
-   |
-LL | pub trait ToString {
-   | ------------------ similarly named trait `ToString` defined here
+   = note: similarly named trait `ToString` defined here
 
 error: aborting due to 6 previous errors
 
index 6f9113fff516193e80bdca725a5e33454a25cf74..fb9900bc57bbcddb536a3bc6e3acabb59f83793a 100644 (file)
@@ -18,9 +18,6 @@ LL |     let x: Vec<dyn Trait + Sized> = Vec::new();
    = help: the trait `Sized` is not implemented for `dyn Trait`
 note: required by a bound in `Vec`
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
-   |                ^ required by this bound in `Vec`
 
 error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time
   --> $DIR/bad-sized.rs:4:37
@@ -31,9 +28,6 @@ LL |     let x: Vec<dyn Trait + Sized> = Vec::new();
    = help: the trait `Sized` is not implemented for `dyn Trait`
 note: required by a bound in `Vec::<T>::new`
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL | impl<T> Vec<T> {
-   |      ^ required by this bound in `Vec::<T>::new`
 
 error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time
   --> $DIR/bad-sized.rs:4:37
@@ -44,9 +38,6 @@ LL |     let x: Vec<dyn Trait + Sized> = Vec::new();
    = help: the trait `Sized` is not implemented for `dyn Trait`
 note: required by a bound in `Vec`
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
-   |                ^ required by this bound in `Vec`
 
 error: aborting due to 4 previous errors
 
index 8da0b6d6b85056198c76584c63492e85841f1dee..36b08a7d3093141c3ee61e6ff410794cc2092341 100644 (file)
@@ -20,6 +20,10 @@ LL | fn foo(_x: Foo + Send) {
    |
    = help: the trait `Sized` is not implemented for `(dyn Foo + Send + 'static)`
    = help: unsized fn params are gated as an unstable feature
+help: you can use `impl Trait` as the argument type
+   |
+LL | fn foo(_x: impl Foo + Send) {
+   |            ++++
 help: function arguments must have a statically known size, borrowed types always have a known size
    |
 LL | fn foo(_x: &Foo + Send) {
index 56e8fcff0fce507f3bd96dcc969373f7b95e74f2..8db5fa615c08d30a107a5251399fa58d825f2752 100644 (file)
@@ -1,15 +1,15 @@
 #![feature(rustc_attrs)]
 
 #[rustc_must_implement_one_of(a, a)]
-//~^ Functions names are duplicated
+//~^ functions names are duplicated
 trait Trait {
     fn a() {}
 }
 
 #[rustc_must_implement_one_of(b, a, a, c, b, c)]
-//~^ Functions names are duplicated
-//~| Functions names are duplicated
-//~| Functions names are duplicated
+//~^ functions names are duplicated
+//~| functions names are duplicated
+//~| functions names are duplicated
 trait Trait1 {
     fn a() {}
     fn b() {}
index 777beba618277f50d9aa4f1314956f7de4b41838..cd1476a6eb81b4e039bafe293c1cba61d7647cb0 100644 (file)
@@ -1,34 +1,34 @@
-error: Functions names are duplicated
+error: functions names are duplicated
   --> $DIR/rustc_must_implement_one_of_duplicates.rs:3:31
    |
 LL | #[rustc_must_implement_one_of(a, a)]
    |                               ^  ^
    |
-   = note: All `#[rustc_must_implement_one_of]` arguments must be unique
+   = note: all `#[rustc_must_implement_one_of]` arguments must be unique
 
-error: Functions names are duplicated
+error: functions names are duplicated
   --> $DIR/rustc_must_implement_one_of_duplicates.rs:9:34
    |
 LL | #[rustc_must_implement_one_of(b, a, a, c, b, c)]
    |                                  ^  ^
    |
-   = note: All `#[rustc_must_implement_one_of]` arguments must be unique
+   = note: all `#[rustc_must_implement_one_of]` arguments must be unique
 
-error: Functions names are duplicated
+error: functions names are duplicated
   --> $DIR/rustc_must_implement_one_of_duplicates.rs:9:31
    |
 LL | #[rustc_must_implement_one_of(b, a, a, c, b, c)]
    |                               ^           ^
    |
-   = note: All `#[rustc_must_implement_one_of]` arguments must be unique
+   = note: all `#[rustc_must_implement_one_of]` arguments must be unique
 
-error: Functions names are duplicated
+error: functions names are duplicated
   --> $DIR/rustc_must_implement_one_of_duplicates.rs:9:40
    |
 LL | #[rustc_must_implement_one_of(b, a, a, c, b, c)]
    |                                        ^     ^
    |
-   = note: All `#[rustc_must_implement_one_of]` arguments must be unique
+   = note: all `#[rustc_must_implement_one_of]` arguments must be unique
 
 error: aborting due to 4 previous errors
 
index 1f896da94db57c279aefcae77bcef77009587a66..b1b91966c8d8883ab6cfc2aaa95a652f79648136 100644 (file)
@@ -1,12 +1,12 @@
 #![feature(rustc_attrs)]
 
 #[rustc_must_implement_one_of(a, b)]
-//~^ Function not found in this trait
-//~| Function not found in this trait
+//~^ function not found in this trait
+//~| function not found in this trait
 trait Tr0 {}
 
 #[rustc_must_implement_one_of(a, b)]
-//~^ Function not found in this trait
+//~^ function not found in this trait
 trait Tr1 {
     fn a() {}
 }
@@ -23,16 +23,16 @@ trait Tr3 {}
 
 #[rustc_must_implement_one_of(A, B)]
 trait Tr4 {
-    const A: u8 = 1; //~ Not a function
+    const A: u8 = 1; //~ not a function
 
-    type B; //~ Not a function
+    type B; //~ not a function
 }
 
 #[rustc_must_implement_one_of(a, b)]
 trait Tr5 {
-    fn a(); //~ This function doesn't have a default implementation
+    fn a(); //~ function doesn't have a default implementation
 
-    fn b(); //~ This function doesn't have a default implementation
+    fn b(); //~ function doesn't have a default implementation
 }
 
 #[rustc_must_implement_one_of(abc, xyz)]
index 869184f0d1a69fc3f28f5ccd186116077158f634..38e692521ca23508dd310e2935de0a393bb061a3 100644 (file)
@@ -22,19 +22,19 @@ LL |
 LL | struct Struct {}
    | ---------------- not a trait
 
-error: Function not found in this trait
+error: function not found in this trait
   --> $DIR/rustc_must_implement_one_of_misuse.rs:3:31
    |
 LL | #[rustc_must_implement_one_of(a, b)]
    |                               ^
 
-error: Function not found in this trait
+error: function not found in this trait
   --> $DIR/rustc_must_implement_one_of_misuse.rs:3:34
    |
 LL | #[rustc_must_implement_one_of(a, b)]
    |                                  ^
 
-error: Function not found in this trait
+error: function not found in this trait
   --> $DIR/rustc_must_implement_one_of_misuse.rs:8:34
    |
 LL | #[rustc_must_implement_one_of(a, b)]
@@ -46,7 +46,7 @@ error: the `#[rustc_must_implement_one_of]` attribute must be used with at least
 LL | #[rustc_must_implement_one_of(a)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: Not a function
+error: not a function
   --> $DIR/rustc_must_implement_one_of_misuse.rs:26:5
    |
 LL |     const A: u8 = 1;
@@ -57,9 +57,9 @@ note: required by this annotation
    |
 LL | #[rustc_must_implement_one_of(A, B)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: All `#[rustc_must_implement_one_of]` arguments must be associated function names
+   = note: all `#[rustc_must_implement_one_of]` arguments must be associated function names
 
-error: Not a function
+error: not a function
   --> $DIR/rustc_must_implement_one_of_misuse.rs:28:5
    |
 LL |     type B;
@@ -70,9 +70,9 @@ note: required by this annotation
    |
 LL | #[rustc_must_implement_one_of(A, B)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: All `#[rustc_must_implement_one_of]` arguments must be associated function names
+   = note: all `#[rustc_must_implement_one_of]` arguments must be associated function names
 
-error: This function doesn't have a default implementation
+error: function doesn't have a default implementation
   --> $DIR/rustc_must_implement_one_of_misuse.rs:33:5
    |
 LL |     fn a();
@@ -84,7 +84,7 @@ note: required by this annotation
 LL | #[rustc_must_implement_one_of(a, b)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: This function doesn't have a default implementation
+error: function doesn't have a default implementation
   --> $DIR/rustc_must_implement_one_of_misuse.rs:35:5
    |
 LL |     fn b();
diff --git a/src/test/ui/traits/issue-38404.rs b/src/test/ui/traits/issue-38404.rs
new file mode 100644 (file)
index 0000000..1a92acc
--- /dev/null
@@ -0,0 +1,6 @@
+trait A<T>: std::ops::Add<Self> + Sized {}
+trait B<T>: A<T> {}
+trait C<T>: A<dyn B<T, Output=usize>> {}
+//~^ ERROR the trait `B` cannot be made into an object
+
+fn main() {}
diff --git a/src/test/ui/traits/issue-38404.stderr b/src/test/ui/traits/issue-38404.stderr
new file mode 100644 (file)
index 0000000..d7721d7
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0038]: the trait `B` cannot be made into an object
+  --> $DIR/issue-38404.rs:3:15
+   |
+LL | trait C<T>: A<dyn B<T, Output=usize>> {}
+   |               ^^^^^^^^^^^^^^^^^^^^^^ `B` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/issue-38404.rs:1:13
+   |
+LL | trait A<T>: std::ops::Add<Self> + Sized {}
+   |             ^^^^^^^^^^^^^^^^^^^ ...because it uses `Self` as a type parameter
+LL | trait B<T>: A<T> {}
+   |       - this trait cannot be made into an object...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/traits/issue-50480.rs b/src/test/ui/traits/issue-50480.rs
new file mode 100644 (file)
index 0000000..10597ca
--- /dev/null
@@ -0,0 +1,17 @@
+#[derive(Clone, Copy)]
+//~^ ERROR the trait `Copy` may not be implemented for this type
+struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+//~^ ERROR cannot find type `NotDefined` in this scope
+//~| ERROR cannot find type `NotDefined` in this scope
+//~| ERROR cannot find type `N` in this scope
+//~| ERROR cannot find type `N` in this scope
+//~| ERROR `i32` is not an iterator
+
+#[derive(Clone, Copy)]
+//~^ ERROR the trait `Copy` may not be implemented for this type
+struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+//~^ ERROR cannot find type `NotDefined` in this scope
+//~| ERROR cannot find type `N` in this scope
+//~| ERROR `i32` is not an iterator
+
+fn main() {}
diff --git a/src/test/ui/traits/issue-50480.stderr b/src/test/ui/traits/issue-50480.stderr
new file mode 100644 (file)
index 0000000..0bb1f9a
--- /dev/null
@@ -0,0 +1,101 @@
+error[E0412]: cannot find type `N` in this scope
+  --> $DIR/issue-50480.rs:3:12
+   |
+LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |           -^ not found in this scope
+   |           |
+   |           help: you might be missing a type parameter: `<N>`
+
+error[E0412]: cannot find type `NotDefined` in this scope
+  --> $DIR/issue-50480.rs:3:15
+   |
+LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |               ^^^^^^^^^^ not found in this scope
+
+error[E0412]: cannot find type `N` in this scope
+  --> $DIR/issue-50480.rs:3:12
+   |
+LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |           -^ not found in this scope
+   |           |
+   |           help: you might be missing a type parameter: `<N>`
+
+error[E0412]: cannot find type `NotDefined` in this scope
+  --> $DIR/issue-50480.rs:3:15
+   |
+LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |           -   ^^^^^^^^^^ not found in this scope
+   |           |
+   |           help: you might be missing a type parameter: `<NotDefined>`
+
+error[E0412]: cannot find type `N` in this scope
+  --> $DIR/issue-50480.rs:12:18
+   |
+LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |            -     ^
+   |            |
+   |            similarly named type parameter `T` defined here
+   |
+help: a type parameter with a similar name exists
+   |
+LL | struct Bar<T>(T, T, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |                  ~
+help: you might be missing a type parameter
+   |
+LL | struct Bar<T, N>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |             +++
+
+error[E0412]: cannot find type `NotDefined` in this scope
+  --> $DIR/issue-50480.rs:12:21
+   |
+LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |                     ^^^^^^^^^^ not found in this scope
+
+error[E0277]: `i32` is not an iterator
+  --> $DIR/issue-50480.rs:3:27
+   |
+LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator
+   |
+   = help: the trait `Iterator` is not implemented for `i32`
+   = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+
+error[E0204]: the trait `Copy` may not be implemented for this type
+  --> $DIR/issue-50480.rs:1:17
+   |
+LL | #[derive(Clone, Copy)]
+   |                 ^^^^
+LL |
+LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |                                                    --------  ------ this field does not implement `Copy`
+   |                                                    |
+   |                                                    this field does not implement `Copy`
+   |
+   = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: `i32` is not an iterator
+  --> $DIR/issue-50480.rs:12:33
+   |
+LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator
+   |
+   = help: the trait `Iterator` is not implemented for `i32`
+   = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+
+error[E0204]: the trait `Copy` may not be implemented for this type
+  --> $DIR/issue-50480.rs:10:17
+   |
+LL | #[derive(Clone, Copy)]
+   |                 ^^^^
+LL |
+LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |                                                          --------  ------ this field does not implement `Copy`
+   |                                                          |
+   |                                                          this field does not implement `Copy`
+   |
+   = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 10 previous errors
+
+Some errors have detailed explanations: E0204, E0277, E0412.
+For more information about an error, try `rustc --explain E0204`.
index b6a04585583c933079d52ac7c76cffeefe53938e..0b57a8212bdc63495ca6cb6ee4b0a08d0056b067 100644 (file)
@@ -12,9 +12,6 @@ LL |     opts.get(opt.as_ref());
              where T: ?Sized;
 note: required by a bound in `HashMap::<K, V, S>::get`
   --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
-   |
-LL |         K: Borrow<Q>,
-   |            ^^^^^^^^^ required by this bound in `HashMap::<K, V, S>::get`
 help: consider specifying the generic argument
    |
 LL |     opts.get::<Q>(opt.as_ref());
@@ -46,7 +43,15 @@ LL |     let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect(
    |                                            |
    |                                            required by a bound introduced by this call
    |
-   = note: cannot satisfy `u32: From<_>`
+   = note: multiple `impl`s satisfying `u32: From<_>` found in the following crates: `core`, `std`:
+           - impl From<Ipv4Addr> for u32;
+           - impl From<NonZeroU32> for u32;
+           - impl From<bool> for u32;
+           - impl From<char> for u32;
+           - impl From<u16> for u32;
+           - impl From<u8> for u32;
+           - impl<T> From<!> for T;
+           - impl<T> From<T> for T;
 help: try using a fully qualified path to specify the expected types
    |
 LL |     let ips: Vec<_> = (0..100_000).map(|_| u32::from(<u32 as Into<T>>::into(0u32))).collect();
index fa280135beb2d98a99f1605dc79ea8c33b57b7fa..9e80497ca6e92a1cf95c3f58df7ca752a728e388 100644 (file)
@@ -4,7 +4,14 @@ error[E0283]: type annotations needed: cannot satisfy `T: FnMut<(&'a (),)>`
 LL |     T: FnMut(&'a ()),
    |        ^^^^^^^^^^^^^
    |
-   = note: cannot satisfy `T: FnMut<(&'a (),)>`
+note: multiple `impl`s or `where` clauses satisfying `T: FnMut<(&'a (),)>` found
+  --> $DIR/issue-85735.rs:7:8
+   |
+LL |     T: FnMut(&'a ()),
+   |        ^^^^^^^^^^^^^
+LL |
+LL |     T: FnMut(&'b ()),
+   |        ^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index a74d2524996a10d4d9f85c9ed166f1733264c3fe..1f18c5daf66e3dd2c0944da6fe3f8becd61e2552 100644 (file)
@@ -17,7 +17,7 @@ error[E0275]: overflow evaluating the requirement `(): Sized`
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "512"]` attribute to your crate (`issue_91949_hangs_on_recursion`)
    = note: required for `std::iter::Empty<()>` to implement `Iterator`
    = note: 171 redundant requirements hidden
-   = note: required for `IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<..., ...>>, ...>>` to implement `Iterator`
+   = note: required for `IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<..., ...>>, ...>>, ...>>` to implement `Iterator`
    = note: the full type name has been written to '$TEST_BUILD_DIR/traits/issue-91949-hangs-on-recursion/issue-91949-hangs-on-recursion.long-type-hash.txt'
 
 error: aborting due to previous error; 1 warning emitted
index 146d38d076a3ccb1e7696c60c940fdf82cab8773..9062a0fab630a3103d5e8ac839e5b1a54dd90b40 100644 (file)
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `String: From<impl ToString>` is not satisfied
-  --> $DIR/issue-97576.rs:8:18
+  --> $DIR/issue-97576.rs:8:22
    |
 LL |             bar: bar.into(),
-   |                  ^^^ ---- required by a bound introduced by this call
-   |                  |
-   |                  the trait `From<impl ToString>` is not implemented for `String`
+   |                      ^^^^ the trait `From<impl ToString>` is not implemented for `String`
    |
    = note: required for `impl ToString` to implement `Into<String>`
 
index 920f66121e09897094a55787cdcd975c1105cde1..23e182738f700236e158bd4f90b4c6b009d3f1aa 100644 (file)
@@ -7,9 +7,6 @@ LL |     iso(left, right)
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`mutual_recursion_issue_75860`)
 note: required by a bound in `Option`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL | pub enum Option<T> {
-   |                 ^ required by this bound in `Option`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/object/issue-44454-1.rs b/src/test/ui/traits/object/issue-44454-1.rs
new file mode 100644 (file)
index 0000000..bbaf318
--- /dev/null
@@ -0,0 +1,22 @@
+// Taken from https://github.com/rust-lang/rust/issues/44454#issue-256435333
+
+trait Animal<X>: 'static {}
+
+fn foo<Y, X>()
+where
+    Y: Animal<X> + ?Sized,
+{
+    // `Y` implements `Animal<X>` so `Y` is 'static.
+    baz::<Y>()
+}
+
+fn bar<'a>(_arg: &'a i32) {
+    foo::<dyn Animal<&'a i32>, &'a i32>() //~ ERROR: lifetime may not live long enough
+}
+
+fn baz<T: 'static + ?Sized>() {}
+
+fn main() {
+    let a = 5;
+    bar(&a);
+}
diff --git a/src/test/ui/traits/object/issue-44454-1.stderr b/src/test/ui/traits/object/issue-44454-1.stderr
new file mode 100644 (file)
index 0000000..859487f
--- /dev/null
@@ -0,0 +1,10 @@
+error: lifetime may not live long enough
+  --> $DIR/issue-44454-1.rs:14:5
+   |
+LL | fn bar<'a>(_arg: &'a i32) {
+   |        -- lifetime `'a` defined here
+LL |     foo::<dyn Animal<&'a i32>, &'a i32>()
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/traits/object/issue-44454-2.rs b/src/test/ui/traits/object/issue-44454-2.rs
new file mode 100644 (file)
index 0000000..f5178bc
--- /dev/null
@@ -0,0 +1,22 @@
+// Taken from https://github.com/rust-lang/rust/issues/44454#issuecomment-1175925928
+
+trait Trait<ARG: 'static>: 'static {
+    type Assoc: AsRef<str>;
+}
+
+fn hr<T: ?Sized, ARG>(x: T::Assoc) -> Box<dyn AsRef<str> + 'static>
+where
+    T: Trait<ARG>
+{
+    Box::new(x)
+}
+
+fn extend_lt<'a>(x: &'a str) -> Box<dyn AsRef<str> + 'static> {
+    type DynTrait = dyn for<'a> Trait<&'a str, Assoc = &'a str>;
+    hr::<DynTrait, _>(x) //~ ERROR: borrowed data escapes outside of function
+}
+
+fn main() {
+    let extended = extend_lt(&String::from("hello"));
+    println!("{}", extended.as_ref().as_ref());
+}
diff --git a/src/test/ui/traits/object/issue-44454-2.stderr b/src/test/ui/traits/object/issue-44454-2.stderr
new file mode 100644 (file)
index 0000000..7f57476
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0521]: borrowed data escapes outside of function
+  --> $DIR/issue-44454-2.rs:16:5
+   |
+LL | fn extend_lt<'a>(x: &'a str) -> Box<dyn AsRef<str> + 'static> {
+   |              --  - `x` is a reference that is only valid in the function body
+   |              |
+   |              lifetime `'a` defined here
+LL |     type DynTrait = dyn for<'a> Trait<&'a str, Assoc = &'a str>;
+LL |     hr::<DynTrait, _>(x)
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     `x` escapes the function body here
+   |     argument requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0521`.
diff --git a/src/test/ui/traits/object/issue-44454-3.rs b/src/test/ui/traits/object/issue-44454-3.rs
new file mode 100644 (file)
index 0000000..bff7270
--- /dev/null
@@ -0,0 +1,33 @@
+// Taken from https://github.com/rust-lang/rust/issues/44454#issuecomment-1332781290
+
+use std::any::Any;
+
+trait Animal<X>: 'static {}
+
+trait Projector {
+    type Foo;
+}
+
+impl<X> Projector for dyn Animal<X> {
+    type Foo = X;
+}
+
+fn make_static<'a, T>(t: &'a T) -> &'static T {
+    let x: <dyn Animal<&'a T> as Projector>::Foo = t;
+    let any = generic::<dyn Animal<&'a T>, &'a T>(x);
+    //~^ ERROR: lifetime may not live long enough
+    any.downcast_ref::<&'static T>().unwrap()
+}
+
+fn generic<T: Projector + Animal<U> + ?Sized, U>(x: <T as Projector>::Foo) -> Box<dyn Any> {
+    make_static_any(x)
+}
+
+fn make_static_any<U: 'static>(u: U) -> Box<dyn Any> {
+    Box::new(u)
+}
+
+fn main() {
+    let a = make_static(&"salut".to_string());
+    println!("{}", *a);
+}
diff --git a/src/test/ui/traits/object/issue-44454-3.stderr b/src/test/ui/traits/object/issue-44454-3.stderr
new file mode 100644 (file)
index 0000000..294684d
--- /dev/null
@@ -0,0 +1,11 @@
+error: lifetime may not live long enough
+  --> $DIR/issue-44454-3.rs:17:15
+   |
+LL | fn make_static<'a, T>(t: &'a T) -> &'static T {
+   |                -- lifetime `'a` defined here
+LL |     let x: <dyn Animal<&'a T> as Projector>::Foo = t;
+LL |     let any = generic::<dyn Animal<&'a T>, &'a T>(x);
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
index 5f74d0c3b9260e5686593d89852bb77abed05823..575ace2374ee64ec15c33701d40fffab44285bce 100644 (file)
@@ -9,8 +9,8 @@ LL |     let _f: base::Foo = base::HasNew::new();
    |
 help: use the fully-qualified path to the only available implementation
    |
-LL |     let _f: base::Foo = base::<Foo as HasNew>::new();
-   |                               +++++++       +
+LL |     let _f: base::Foo = <Foo as base::HasNew>::new();
+   |                         +++++++             +
 
 error: aborting due to previous error
 
index eb2b88059d485e0059be5f736f5e26b96911421f..49e20c6a76ad94d871ecb9165979c3bc27eaa852 100644 (file)
@@ -9,9 +9,6 @@ LL |     let _errors = TcpListener::bind(&bad);
    = note: required for `&NoToSocketAddrs` to implement `ToSocketAddrs`
 note: required by a bound in `TcpListener::bind`
   --> $SRC_DIR/std/src/net/tcp.rs:LL:COL
-   |
-LL |     pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
-   |                    ^^^^^^^^^^^^^ required by this bound in `TcpListener::bind`
 help: consider dereferencing here
    |
 LL |     let _errors = TcpListener::bind(&*bad);
index 76663ace7edbdb013a12605ea52115dc548fea9d..1363fb8c47af8862e642a613e6e9b124cc4bdea5 100644 (file)
@@ -11,9 +11,6 @@ LL |         .filter(|c| "aeiou".contains(c))
    = note: required for `&char` to implement `Pattern<'_>`
 note: required by a bound in `core::str::<impl str>::contains`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
-   |
-LL |     pub fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
-   |                            ^^^^^^^^^^^ required by this bound in `core::str::<impl str>::contains`
 help: consider dereferencing here
    |
 LL |         .filter(|c| "aeiou".contains(*c))
diff --git a/src/test/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.fixed b/src/test/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.fixed
new file mode 100644 (file)
index 0000000..ea3d1bf
--- /dev/null
@@ -0,0 +1,14 @@
+// run-rustfix
+
+struct TargetStruct;
+
+impl From<usize> for TargetStruct {
+    fn from(_unchecked: usize) -> Self {
+        TargetStruct
+    }
+}
+
+fn main() {
+    let a = &3;
+    let _b: TargetStruct = (*a).into(); //~ ERROR the trait bound `TargetStruct: From<&{integer}>` is not satisfied
+}
diff --git a/src/test/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.rs b/src/test/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.rs
new file mode 100644 (file)
index 0000000..9eda680
--- /dev/null
@@ -0,0 +1,14 @@
+// run-rustfix
+
+struct TargetStruct;
+
+impl From<usize> for TargetStruct {
+    fn from(_unchecked: usize) -> Self {
+        TargetStruct
+    }
+}
+
+fn main() {
+    let a = &3;
+    let _b: TargetStruct = a.into(); //~ ERROR the trait bound `TargetStruct: From<&{integer}>` is not satisfied
+}
diff --git a/src/test/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.stderr b/src/test/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.stderr
new file mode 100644 (file)
index 0000000..ede31a2
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `TargetStruct: From<&{integer}>` is not satisfied
+  --> $DIR/suggest-dereferencing-receiver-argument.rs:13:30
+   |
+LL |     let _b: TargetStruct = a.into();
+   |                              ^^^^ the trait `From<&{integer}>` is not implemented for `TargetStruct`
+   |
+   = note: required for `&{integer}` to implement `Into<TargetStruct>`
+help: consider dereferencing here
+   |
+LL |     let _b: TargetStruct = (*a).into();
+   |                            ++ +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
index 747e2477b9cf14193c2c806ec2d87c09136e8f32..44e63b78cce85b7c5945f4d7a0518938a39331bf 100644 (file)
@@ -9,9 +9,6 @@ LL |     mem::size_of::<U>();
    |
 note: required by a bound in `std::mem::size_of`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL | pub const fn size_of<T>() -> usize {
-   |                      ^ required by this bound in `std::mem::size_of`
 help: consider removing the `?Sized` bound to make the type parameter `Sized`
    |
 LL - fn check<T: Iterator, U: ?Sized>() {
@@ -34,9 +31,6 @@ LL | struct Misc<T:?Sized>(T);
    |        ^^^^
 note: required by a bound in `std::mem::size_of`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL | pub const fn size_of<T>() -> usize {
-   |                      ^ required by this bound in `std::mem::size_of`
 help: consider removing the `?Sized` bound to make the type parameter `Sized`
    |
 LL - fn check<T: Iterator, U: ?Sized>() {
@@ -80,9 +74,6 @@ LL |     mem::size_of::<[T]>();
    = help: the trait `Sized` is not implemented for `[T]`
 note: required by a bound in `std::mem::size_of`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL | pub const fn size_of<T>() -> usize {
-   |                      ^ required by this bound in `std::mem::size_of`
 
 error[E0277]: the size for values of type `[&U]` cannot be known at compilation time
   --> $DIR/suggest-where-clause.rs:31:20
@@ -93,9 +84,6 @@ LL |     mem::size_of::<[&U]>();
    = help: the trait `Sized` is not implemented for `[&U]`
 note: required by a bound in `std::mem::size_of`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL | pub const fn size_of<T>() -> usize {
-   |                      ^ required by this bound in `std::mem::size_of`
 
 error: aborting due to 7 previous errors
 
index 3f83d6583b09cc6e723bfdedd1807cff6ebf50a5..1b3d202590db46d47dc31107c135a3dd169e51a5 100644 (file)
@@ -8,12 +8,6 @@ LL | /             ASSUME_LIFETIMES,
 LL | |             ASSUME_VALIDITY,
 LL | |             ASSUME_VISIBILITY,
    | |_____________________________- help: remove these generic arguments
-   |
-note: trait defined here, with at most 3 generic parameters: `Src`, `Context`, `ASSUME`
-  --> $SRC_DIR/core/src/mem/transmutability.rs:LL:COL
-   |
-LL | pub unsafe trait BikeshedIntrinsicFrom<Src, Context, const ASSUME: Assume = { Assume::NOTHING }>
-   |                  ^^^^^^^^^^^^^^^^^^^^^ ---  -------  ------------------------------------------
 
 error: aborting due to previous error
 
index f3a547fa238273c4cdd26ec2a6f21bba0c75b673..fe3712ef83917f1fb60cd082ca601f550bd7c86d 100644 (file)
@@ -13,9 +13,6 @@ LL |         groups.push(new_group, vec![process]);
              found struct `Vec<String>`
 note: associated function defined here
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL |     pub fn push(&mut self, value: T) {
-   |            ^^^^
 help: remove the extra argument
    |
 LL |         groups.push(/* (Vec<String>, Vec<Process>) */);
index ec07f1e70cff6a135376c7f51c3529237dfdd66c..452413fc51679bd93f90cba315007b01f3b72367 100644 (file)
@@ -6,9 +6,6 @@ LL |         self.acc.push_back(self.current_provides, self.current_requires);
    |
 note: associated function defined here
   --> $SRC_DIR/alloc/src/collections/vec_deque/mod.rs:LL:COL
-   |
-LL |     pub fn push_back(&mut self, value: T) {
-   |            ^^^^^^^^^
 help: wrap these arguments in parentheses to construct a tuple
    |
 LL |         self.acc.push_back((self.current_provides, self.current_requires));
index 48b7946ea820e8b6d328520786965cef37fecbdf..9cc15f14a991d5516050b277133921024cfbd0cd 100644 (file)
@@ -6,8 +6,8 @@ LL |         |x| x.len()
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |         |x: _| x.len()
-   |           +++
+LL |         |x: /* Type */| x.len()
+   |           ++++++++++++
 
 error[E0282]: type annotations needed
   --> $DIR/closures_in_branches.rs:21:10
@@ -17,8 +17,8 @@ LL |         |x| x.len()
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |         |x: _| x.len()
-   |           +++
+LL |         |x: /* Type */| x.len()
+   |           ++++++++++++
 
 error: aborting due to 2 previous errors
 
index 24b3a045856a6accd5656b25a2531e4afae89465..4aa5966ff25d4cedac7d9db5a84b39087a0ef0f9 100644 (file)
@@ -8,7 +8,7 @@ trait Foo {
 
 impl Foo for () {
     type Bar = std::vec::IntoIter<u32>;
-    //~^ ERROR expected `std::vec::IntoIter<u32>` to be an iterator that yields `X`, but it yields `u32`
+    //~^ ERROR expected `IntoIter<u32>` to be an iterator that yields `X`, but it yields `u32`
 }
 
 fn incoherent() {
index fb40895c49f15d13e28a81527f3ef4ac2e159014..8d11b48888947d91bce4b7039892a34a8cc72b15 100644 (file)
@@ -1,4 +1,4 @@
-error[E0271]: expected `std::vec::IntoIter<u32>` to be an iterator that yields `X`, but it yields `u32`
+error[E0271]: expected `IntoIter<u32>` to be an iterator that yields `X`, but it yields `u32`
   --> $DIR/issue-57961.rs:10:16
    |
 LL | type X = impl Sized;
diff --git a/src/test/ui/type-alias/issue-37515.rs b/src/test/ui/type-alias/issue-37515.rs
new file mode 100644 (file)
index 0000000..b3a870d
--- /dev/null
@@ -0,0 +1,8 @@
+// check-pass
+
+#![warn(unused)]
+
+type Z = dyn for<'x> Send;
+//~^ WARN type alias `Z` is never used
+
+fn main() {}
diff --git a/src/test/ui/type-alias/issue-37515.stderr b/src/test/ui/type-alias/issue-37515.stderr
new file mode 100644 (file)
index 0000000..f1e83ca
--- /dev/null
@@ -0,0 +1,15 @@
+warning: type alias `Z` is never used
+  --> $DIR/issue-37515.rs:5:6
+   |
+LL | type Z = dyn for<'x> Send;
+   |      ^
+   |
+note: the lint level is defined here
+  --> $DIR/issue-37515.rs:3:9
+   |
+LL | #![warn(unused)]
+   |         ^^^^^^
+   = note: `#[warn(dead_code)]` implied by `#[warn(unused)]`
+
+warning: 1 warning emitted
+
index 6819d14bb010690472625fcd338fcb03861a8698..fd43e1114c8912769e8b06fbad8aae279f66cd88 100644 (file)
@@ -25,11 +25,6 @@ error[E0107]: missing generics for struct `Vec`
 LL |         input_cells: Vec::new()
    |                      ^^^ expected at least 1 generic argument
    |
-note: struct defined here, with at least 1 generic parameter: `T`
-  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
-   |            ^^^ -
 help: add missing generic argument
    |
 LL |         input_cells: Vec<T>::new()
index 4af4c22f75166153ab35739f1c1c2fd8ac3869df..87bba3166be6a3cde426e54f1b4f57c8023bd791 100644 (file)
@@ -10,7 +10,7 @@ note: required by a bound in `foo`
    |
 LL | fn foo<T: Into<String>>(x: i32) {}
    |           ^^^^^^^^^^^^ required by this bound in `foo`
-help: consider specifying the type argument in the function call
+help: consider specifying the generic argument
    |
 LL |     foo::<T>(42);
    |        +++++
index de578ca93ed59b827d3ab48bb0086eb619d77c03..ba8d15d0b7317f1a557c11dac272e5b886b10951 100644 (file)
@@ -15,9 +15,6 @@ LL |     let x: Vec::with_capacity(10, 20);
    |
 note: associated function defined here
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-   |
-LL |     pub fn with_capacity(capacity: usize) -> Self {
-   |            ^^^^^^^^^^^^^
 help: remove the extra argument
    |
 LL |     let x: Vec::with_capacity(10);
index a8139063db1d8aea857cdd2354cd1ac65d4250ab..edc5aeffdcd65fda4697a7fcc12895bd9ca88f54 100644 (file)
@@ -33,11 +33,8 @@ note: an implementation of `std::ops::Neg` might be missing for `Z`
    |
 LL | struct Z;
    | ^^^^^^^^ must implement `std::ops::Neg`
-note: the following trait must be implemented
+note: the trait `std::ops::Neg` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL | pub trait Neg {
-   | ^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/type-ascription-precedence.rs:45:5
@@ -55,7 +52,7 @@ error[E0308]: mismatched types
   --> $DIR/type-ascription-precedence.rs:53:5
    |
 LL |     (S .. S): S;
-   |     ^^^^^^^^ expected struct `S`, found struct `std::ops::Range`
+   |     ^^^^^^^^ expected struct `S`, found struct `Range`
    |
    = note: expected struct `S`
               found struct `std::ops::Range<S>`
index 8ab08e25e30920213a4c8e03cc669b11adcce23b..9f4558adab150708696dc1aba163bd6cdbacca3d 100644 (file)
@@ -68,7 +68,9 @@ error[E0308]: mismatched types
   --> $DIR/assignment-in-if.rs:44:18
    |
 LL |     if x == x && x = x && x == x {
-   |                  ^ expected `bool`, found `usize`
+   |        ------    ^ expected `bool`, found `usize`
+   |        |
+   |        expected because this is `bool`
 
 error[E0308]: mismatched types
   --> $DIR/assignment-in-if.rs:44:22
@@ -91,7 +93,9 @@ error[E0308]: mismatched types
   --> $DIR/assignment-in-if.rs:51:28
    |
 LL |     if x == x && x == x && x = x {
-   |                            ^ expected `bool`, found `usize`
+   |        ----------------    ^ expected `bool`, found `usize`
+   |        |
+   |        expected because this is `bool`
 
 error[E0308]: mismatched types
   --> $DIR/assignment-in-if.rs:51:8
index 75feb5698eb630ea2e868cfb5cf4ea6d0e0b1eb5..d15fd23418bb0be17020759ab5df157b6891b0b3 100644 (file)
@@ -4,7 +4,13 @@ error[E0283]: type annotations needed: cannot satisfy `&'a T: Foo`
 LL |     where &'a T : Foo,
    |                   ^^^
    |
-   = note: cannot satisfy `&'a T: Foo`
+note: multiple `impl`s or `where` clauses satisfying `&'a T: Foo` found
+  --> $DIR/issue-40294.rs:6:19
+   |
+LL |     where &'a T : Foo,
+   |                   ^^^
+LL |           &'b T : Foo
+   |                   ^^^
 
 error: aborting due to previous error
 
index 9ae97f390d3e4bcb04fb13431c64092f8fc4051e..e5e29aabf374b03d7609c70f75b12fd2dd40322c 100644 (file)
@@ -12,8 +12,8 @@ LL |     let x = |_| {};
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |     let x = |_: _| {};
-   |               +++
+LL |     let x = |_: /* Type */| {};
+   |               ++++++++++++
 
 error[E0282]: type annotations needed
   --> $DIR/unknown_type_for_closure.rs:10:14
index 4e73e10a3014382815b80cb672e1b359c1a694e5..7529f25bd8e4b318e12f6b05a521323c4a21dfd0 100644 (file)
@@ -6,7 +6,9 @@ LL | trait BrokenAdd: Copy + Add<Output=Self> {
 LL |     fn broken_add<T>(&self, rhs: T) -> Self {
    |                   - found type parameter
 LL |         *self + rhs
-   |                 ^^^ expected type parameter `Self`, found type parameter `T`
+   |         -----   ^^^ expected type parameter `Self`, found type parameter `T`
+   |         |
+   |         expected because this is `Self`
    |
    = note: expected type parameter `Self`
               found type parameter `T`
index c1ae10efac4b4e874169caf6729eb77e2e8af666..1aed1dbe4babd21662ce83308a7bcdc0f1e66983 100644 (file)
@@ -30,8 +30,8 @@ LL |     let _ = |a, b: _| -> _ { 0 };
    |
 help: consider giving this closure parameter an explicit type
    |
-LL |     let _ = |a: _, b: _| -> _ { 0 };
-   |               +++
+LL |     let _ = |a: /* Type */, b: _| -> _ { 0 };
+   |               ++++++++++++
 
 error: aborting due to 5 previous errors
 
index ff487466902236425d4be9180f9fb20f71ac6bd2..5b00d387aba5dd0e115f117006f0186f7fd3f962 100644 (file)
@@ -1,9 +1,6 @@
 error: reached the type-length limit while instantiating `std::mem::drop::<Option<((((..., ..., ...), ..., ...), ..., ...), ..., ...)>>`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
    |
-LL | pub fn drop<T>(_x: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^
-   |
    = help: consider adding a `#![type_length_limit="10"]` attribute to your crate
    = note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit/type_length_limit.long-type.txt'
 
index faac680ea19318f02e674ec0e5ddb67ad34cf9eb..ff36e18d28301ef3b1934208e8ed2175a8ecbe9f 100644 (file)
@@ -12,6 +12,10 @@ note: `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
    |
 LL |     nc.clone()
    |     ^^
+help: consider annotating `NotClone` with `#[derive(Clone)]`
+   |
+LL | #[derive(Clone)]
+   |
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/typeck/issue-104582.rs b/src/test/ui/typeck/issue-104582.rs
new file mode 100644 (file)
index 0000000..104669d
--- /dev/null
@@ -0,0 +1,5 @@
+fn main(){
+    let my_var: String(String?);
+    //~^ ERROR: invalid `?` in type
+    //~| ERROR: parenthesized type parameters may only be used with a `Fn` trait
+}
diff --git a/src/test/ui/typeck/issue-104582.stderr b/src/test/ui/typeck/issue-104582.stderr
new file mode 100644 (file)
index 0000000..61b6b23
--- /dev/null
@@ -0,0 +1,25 @@
+error: invalid `?` in type
+  --> $DIR/issue-104582.rs:2:30
+   |
+LL |     let my_var: String(String?);
+   |                              ^ `?` is only allowed on expressions, not types
+   |
+help: if you meant to express that the type might not contain a value, use the `Option` wrapper type
+   |
+LL |     let my_var: String(Option<String>);
+   |                        +++++++      ~
+
+error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
+  --> $DIR/issue-104582.rs:2:17
+   |
+LL |     let my_var: String(String?);
+   |                 ^^^^^^^^^^^^^^^ only `Fn` traits may use parentheses
+   |
+help: use angle brackets instead
+   |
+LL |     let my_var: String<String?>;
+   |                       ~       ~
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0214`.
index 657bda5f62b3f2605ec329981c7f442a10ea130f..876ac2c67ef3f34cf19718cff61a7a2bb65dc5a7 100644 (file)
@@ -5,7 +5,7 @@ LL |     fn nodes<'a, I: Iterator<Item=&'a N>>(&self) -> I
    |                  - this type parameter              - expected `I` because of return type
 ...
 LL |         self.iter()
-   |         ^^^^^^^^^^^ expected type parameter `I`, found struct `std::slice::Iter`
+   |         ^^^^^^^^^^^ expected type parameter `I`, found struct `Iter`
    |
    = note: expected type parameter `I`
                       found struct `std::slice::Iter<'_, N>`
diff --git a/src/test/ui/typeck/issue-33575.rs b/src/test/ui/typeck/issue-33575.rs
new file mode 100644 (file)
index 0000000..de544af
--- /dev/null
@@ -0,0 +1,4 @@
+fn main() {
+    let baz = ().foo(); //~ ERROR no method named `foo` found
+    <i32 as std::str::FromStr>::from_str(&baz); // No complaints about `str` being unsized
+}
diff --git a/src/test/ui/typeck/issue-33575.stderr b/src/test/ui/typeck/issue-33575.stderr
new file mode 100644 (file)
index 0000000..bbd8042
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0599]: no method named `foo` found for unit type `()` in the current scope
+  --> $DIR/issue-33575.rs:2:18
+   |
+LL |     let baz = ().foo();
+   |                  ^^^ method not found in `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
index 91381e8ef4acf6ebff0d94551cacae652a7a5f6b..f488463ae3ce9faedbd67b008ae8cac5468b11bd 100644 (file)
@@ -10,9 +10,6 @@ LL | fn main() { test(Ok(())); }
            found unit type `()`
 note: tuple variant defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^
 help: try wrapping the expression in `Some`
    |
 LL | fn main() { test(Ok(Some(()))); }
index 3861e0507f6ddeb6b8d313d76db226b38f6b601b..f5adcabe3e91e0c89ab5a471e4eb5d41ec601832 100644 (file)
@@ -6,11 +6,6 @@ LL |     pub fn run() -> Result<_> {
    |                     |
    |                     expected 2 generic arguments
    |
-note: enum defined here, with 2 generic parameters: `T`, `E`
-  --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   |          ^^^^^^ -  -
 help: add missing generic argument
    |
 LL |     pub fn run() -> Result<_, E> {
@@ -24,11 +19,6 @@ LL |     pub fn interact(&mut self) -> Result<_> {
    |                                   |
    |                                   expected 2 generic arguments
    |
-note: enum defined here, with 2 generic parameters: `T`, `E`
-  --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL | pub enum Result<T, E> {
-   |          ^^^^^^ -  -
 help: add missing generic argument
    |
 LL |     pub fn interact(&mut self) -> Result<_, E> {
index 1e45c2d35dfdc13cbd0d769b66e350232a713adb..ce4f73b820a18c1d26a6dde668cd1fc7b21d1c02 100644 (file)
@@ -3,11 +3,9 @@ error[E0412]: cannot find type `F` in this scope
    |
 LL | impl F {
    |      ^ help: a trait with a similar name exists: `Fn`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   | -------------------------------------- similarly named trait `Fn` defined here
+   = note: similarly named trait `Fn` defined here
 
 error[E0412]: cannot find type `TestResult` in this scope
   --> $DIR/issue-83693.rs:9:22
index 04dc0e36520b4e7e9b5033f746c8270b3abeedce..00d23389720b9d636cd2272e0686d5361dd2bdbe 100644 (file)
@@ -16,9 +16,6 @@ LL |     <F as FnOnce(&mut u8)>::call_once(f, 1)
                found type `{integer}`
 note: associated function defined here
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL |     extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
-   |                           ^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/typeck/issue-92481.rs b/src/test/ui/typeck/issue-92481.rs
new file mode 100644 (file)
index 0000000..0a6b184
--- /dev/null
@@ -0,0 +1,14 @@
+//check-fail
+
+#![crate_type="lib"]
+
+fn r({) {
+    Ok {             //~ ERROR mismatched types [E0308]
+        d..||_=m
+    }
+}
+//~^^^^^ ERROR expected parameter name, found `{`
+//~| ERROR expected one of `,`, `:`, or `}`, found `..`
+//~^^^^^ ERROR cannot find value `d` in this scope [E0425]
+//~| ERROR cannot find value `m` in this scope [E0425]
+//~| ERROR variant `Result<_, _>::Ok` has no field named `d` [E0559]
diff --git a/src/test/ui/typeck/issue-92481.stderr b/src/test/ui/typeck/issue-92481.stderr
new file mode 100644 (file)
index 0000000..cd778a6
--- /dev/null
@@ -0,0 +1,60 @@
+error: expected parameter name, found `{`
+  --> $DIR/issue-92481.rs:5:6
+   |
+LL | fn r({) {
+   |      ^ expected parameter name
+
+error: expected one of `,`, `:`, or `}`, found `..`
+  --> $DIR/issue-92481.rs:5:6
+   |
+LL | fn r({) {
+   |      ^ unclosed delimiter
+LL |     Ok {
+LL |         d..||_=m
+   |          -^
+   |          |
+   |          help: `}` may belong here
+
+error[E0425]: cannot find value `d` in this scope
+  --> $DIR/issue-92481.rs:7:9
+   |
+LL |         d..||_=m
+   |         ^ not found in this scope
+
+error[E0425]: cannot find value `m` in this scope
+  --> $DIR/issue-92481.rs:7:16
+   |
+LL |         d..||_=m
+   |                ^ not found in this scope
+
+error[E0559]: variant `Result<_, _>::Ok` has no field named `d`
+  --> $DIR/issue-92481.rs:7:9
+   |
+LL |         d..||_=m
+   |         ^ field does not exist
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+   |
+   = note: `Result<_, _>::Ok` defined here
+   |
+help: `Result<_, _>::Ok` is a tuple variant, use the appropriate syntax
+   |
+LL |     Result<_, _>::Ok(/* fields */)
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/issue-92481.rs:6:5
+   |
+LL |   fn r({) {
+   |           - help: a return type might be missing here: `-> _`
+LL | /     Ok {
+LL | |         d..||_=m
+LL | |     }
+   | |_____^ expected `()`, found enum `Result`
+   |
+   = note: expected unit type `()`
+                   found enum `Result<_, _>`
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0308, E0425, E0559.
+For more information about an error, try `rustc --explain E0308`.
index ea94bcbc2903058476c441be1bab37ab14807f52..fbced928a8a9b78bc2fc46811a741243fba31d50 100644 (file)
@@ -6,9 +6,6 @@ LL |     let _ = Some(3, 2);
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^^^
 help: remove the extra argument
    |
 LL |     let _ = Some(3);
@@ -24,9 +21,6 @@ LL |     let _ = Ok(3, 6, 2);
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^
 help: remove the extra arguments
    |
 LL |     let _ = Ok(3);
@@ -40,9 +34,6 @@ LL |     let _ = Ok();
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-LL |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
-   |     ^^
 help: provide the argument
    |
 LL |     let _ = Ok(/* value */);
index bf74dd7dec0040ede852fdd6ab1bc4f8db2e2f2d..331540d1e4204217151cc6851df288af765987b1 100644 (file)
@@ -5,12 +5,6 @@ LL | fn foo1<T:Copy<U>, U>(x: T) {}
    |           ^^^^--- help: remove these generics
    |           |
    |           expected 0 generic arguments
-   |
-note: trait defined here, with 0 generic parameters
-  --> $SRC_DIR/core/src/marker.rs:LL:COL
-   |
-LL | pub trait Copy: Clone {
-   |           ^^^^
 
 error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
   --> $DIR/typeck-builtin-bound-type-parameters.rs:4:14
@@ -19,12 +13,6 @@ LL | trait Trait: Copy<dyn Send> {}
    |              ^^^^---------- help: remove these generics
    |              |
    |              expected 0 generic arguments
-   |
-note: trait defined here, with 0 generic parameters
-  --> $SRC_DIR/core/src/marker.rs:LL:COL
-   |
-LL | pub trait Copy: Clone {
-   |           ^^^^
 
 error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
   --> $DIR/typeck-builtin-bound-type-parameters.rs:7:21
@@ -33,12 +21,6 @@ LL | struct MyStruct1<T: Copy<T>>;
    |                     ^^^^--- help: remove these generics
    |                     |
    |                     expected 0 generic arguments
-   |
-note: trait defined here, with 0 generic parameters
-  --> $SRC_DIR/core/src/marker.rs:LL:COL
-   |
-LL | pub trait Copy: Clone {
-   |           ^^^^
 
 error[E0107]: this trait takes 0 lifetime arguments but 1 lifetime argument was supplied
   --> $DIR/typeck-builtin-bound-type-parameters.rs:10:25
@@ -47,12 +29,6 @@ LL | struct MyStruct2<'a, T: Copy<'a>>;
    |                         ^^^^---- help: remove these generics
    |                         |
    |                         expected 0 lifetime arguments
-   |
-note: trait defined here, with 0 lifetime parameters
-  --> $SRC_DIR/core/src/marker.rs:LL:COL
-   |
-LL | pub trait Copy: Clone {
-   |           ^^^^
 
 error[E0107]: this trait takes 0 lifetime arguments but 1 lifetime argument was supplied
   --> $DIR/typeck-builtin-bound-type-parameters.rs:13:15
@@ -61,12 +37,6 @@ LL | fn foo2<'a, T:Copy<'a, U>, U>(x: T) {}
    |               ^^^^ -- help: remove this lifetime argument
    |               |
    |               expected 0 lifetime arguments
-   |
-note: trait defined here, with 0 lifetime parameters
-  --> $SRC_DIR/core/src/marker.rs:LL:COL
-   |
-LL | pub trait Copy: Clone {
-   |           ^^^^
 
 error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
   --> $DIR/typeck-builtin-bound-type-parameters.rs:13:15
@@ -75,12 +45,6 @@ LL | fn foo2<'a, T:Copy<'a, U>, U>(x: T) {}
    |               ^^^^     - help: remove this generic argument
    |               |
    |               expected 0 generic arguments
-   |
-note: trait defined here, with 0 generic parameters
-  --> $SRC_DIR/core/src/marker.rs:LL:COL
-   |
-LL | pub trait Copy: Clone {
-   |           ^^^^
 
 error: aborting due to 6 previous errors
 
index ed56e1cf957f5c719c0b3ea01f37448ae2b2a354..a2fe627868aeb36faef45712e678d61e0e83064f 100644 (file)
@@ -23,9 +23,6 @@ LL |     <i32 as Add<i32>>::add(1u32, 2);
    |
 note: associated function defined here
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL |     fn add(self, rhs: Rhs) -> Self::Output;
-   |        ^^^
 help: change the type of the numeric literal from `u32` to `i32`
    |
 LL |     <i32 as Add<i32>>::add(1i32, 2);
@@ -41,9 +38,6 @@ LL |     <i32 as Add<i32>>::add(1, 2u32);
    |
 note: associated function defined here
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-   |
-LL |     fn add(self, rhs: Rhs) -> Self::Output;
-   |        ^^^
 help: change the type of the numeric literal from `u32` to `i32`
    |
 LL |     <i32 as Add<i32>>::add(1, 2i32);
index 1c18eb0fc4905bbf8c1a41c8acd8cb546cf48bab..cfbe1c6f2cbbc91ba63662d821c2e98aa9a36776 100644 (file)
@@ -6,9 +6,6 @@ LL | fn a<F: Fn<usize>>(f: F) {}
    |
 note: required by a bound in `Fn`
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
-   |                    ^^^^^ required by this bound in `Fn`
 
 error: aborting due to previous error
 
index e5ca0edd7a91c62826aa111d4be9dada4161bb37..99ec5178340030d15ca4cac950f747182a9e36cc 100644 (file)
@@ -1,8 +1,8 @@
-error[E0599]: no method named `call` found for closure `[closure@$DIR/unboxed-closures-static-call-wrong-trait.rs:6:26: 6:29]` in the current scope
+error[E0599]: no method named `call` found for closure `[closure@unboxed-closures-static-call-wrong-trait.rs:6:26]` in the current scope
   --> $DIR/unboxed-closures-static-call-wrong-trait.rs:7:10
    |
 LL |     mut_.call((0, ));
-   |          ^^^^ method not found in `[closure@$DIR/unboxed-closures-static-call-wrong-trait.rs:6:26: 6:29]`
+   |          ^^^^ method not found in `[closure@unboxed-closures-static-call-wrong-trait.rs:6:26]`
 
 error: aborting due to previous error
 
index c7882963407f707b03e986b06fb2ca70f430ebb1..d33a61ca8485cbf36db95e3b18ee082188679d02 100644 (file)
@@ -6,12 +6,9 @@ LL |     let _ = match x {
    |
 note: `Result<u32, &Void>` defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
+  ::: $SRC_DIR/core/src/result.rs:LL:COL
    |
-LL | pub enum Result<T, E> {
-   | ---------------------
-...
-LL |     Err(#[stable(feature = "rust1", since = "1.0.0")] E),
-   |     ^^^ not covered
+   = note: not covered
    = note: the matched value is of type `Result<u32, &Void>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
@@ -88,12 +85,9 @@ LL |     let _ = match x {
    |
 note: `Result<u32, Void>` defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
+  ::: $SRC_DIR/core/src/result.rs:LL:COL
    |
-LL | pub enum Result<T, E> {
-   | ---------------------
-...
-LL |     Err(#[stable(feature = "rust1", since = "1.0.0")] E),
-   |     ^^^ not covered
+   = note: not covered
    = note: the matched value is of type `Result<u32, Void>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
@@ -111,12 +105,9 @@ LL |     let Ok(x) = x;
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
 note: `Result<u32, Void>` defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
+  ::: $SRC_DIR/core/src/result.rs:LL:COL
    |
-LL | pub enum Result<T, E> {
-   | ---------------------
-...
-LL |     Err(#[stable(feature = "rust1", since = "1.0.0")] E),
-   |     ^^^ not covered
+   = note: not covered
    = note: the matched value is of type `Result<u32, Void>`
 help: you might want to use `if let` to ignore the variant that isn't matched
    |
index ca02de4c61bb8d660b4b942736cea88ae12c0f1c..7f931b49a58f5553434b9c525595358e659d9ca3 100644 (file)
@@ -14,10 +14,12 @@ error[E0507]: cannot move out of dereference of `ManuallyDrop<((MockVec<u8>, Moc
   --> $DIR/union-borrow-move-parent-sibling.rs:62:13
    |
 LL |     let a = u.x.0;
-   |             ^^^^^
-   |             |
-   |             move occurs because value has type `(MockVec<u8>, MockVec<u8>)`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&u.x.0`
+   |             ^^^^^ move occurs because value has type `(MockVec<u8>, MockVec<u8>)`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     let a = &u.x.0;
+   |             +
 
 error[E0382]: use of moved value: `u`
   --> $DIR/union-borrow-move-parent-sibling.rs:64:13
@@ -46,10 +48,12 @@ error[E0507]: cannot move out of dereference of `ManuallyDrop<((MockVec<u8>, Moc
   --> $DIR/union-borrow-move-parent-sibling.rs:76:13
    |
 LL |     let a = (u.x.0).0;
-   |             ^^^^^^^^^
-   |             |
-   |             move occurs because value has type `MockVec<u8>`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&(u.x.0).0`
+   |             ^^^^^^^^^ move occurs because value has type `MockVec<u8>`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     let a = &(u.x.0).0;
+   |             +
 
 error[E0382]: use of moved value: `u`
   --> $DIR/union-borrow-move-parent-sibling.rs:78:13
index ca02de4c61bb8d660b4b942736cea88ae12c0f1c..7f931b49a58f5553434b9c525595358e659d9ca3 100644 (file)
@@ -14,10 +14,12 @@ error[E0507]: cannot move out of dereference of `ManuallyDrop<((MockVec<u8>, Moc
   --> $DIR/union-borrow-move-parent-sibling.rs:62:13
    |
 LL |     let a = u.x.0;
-   |             ^^^^^
-   |             |
-   |             move occurs because value has type `(MockVec<u8>, MockVec<u8>)`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&u.x.0`
+   |             ^^^^^ move occurs because value has type `(MockVec<u8>, MockVec<u8>)`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     let a = &u.x.0;
+   |             +
 
 error[E0382]: use of moved value: `u`
   --> $DIR/union-borrow-move-parent-sibling.rs:64:13
@@ -46,10 +48,12 @@ error[E0507]: cannot move out of dereference of `ManuallyDrop<((MockVec<u8>, Moc
   --> $DIR/union-borrow-move-parent-sibling.rs:76:13
    |
 LL |     let a = (u.x.0).0;
-   |             ^^^^^^^^^
-   |             |
-   |             move occurs because value has type `MockVec<u8>`, which does not implement the `Copy` trait
-   |             help: consider borrowing here: `&(u.x.0).0`
+   |             ^^^^^^^^^ move occurs because value has type `MockVec<u8>`, which does not implement the `Copy` trait
+   |
+help: consider borrowing here
+   |
+LL |     let a = &(u.x.0).0;
+   |             +
 
 error[E0382]: use of moved value: `u`
   --> $DIR/union-borrow-move-parent-sibling.rs:78:13
index 148fb5046705bf6265734a1586f09556bd73a58f..65ff72fe474b18b683e5bdd6f85ac0fdd68b90fb 100644 (file)
@@ -6,9 +6,6 @@ LL | #[derive(Clone)]
    |
 note: required by a bound in `AssertParamIsCopy`
   --> $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL | pub struct AssertParamIsCopy<T: Copy + ?Sized> {
-   |                                 ^^^^ required by this bound in `AssertParamIsCopy`
    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `U1` with `#[derive(Copy)]`
    |
index 148fb5046705bf6265734a1586f09556bd73a58f..65ff72fe474b18b683e5bdd6f85ac0fdd68b90fb 100644 (file)
@@ -6,9 +6,6 @@ LL | #[derive(Clone)]
    |
 note: required by a bound in `AssertParamIsCopy`
   --> $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL | pub struct AssertParamIsCopy<T: Copy + ?Sized> {
-   |                                 ^^^^ required by this bound in `AssertParamIsCopy`
    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `U1` with `#[derive(Copy)]`
    |
index 99505f31639686770f8ecfb51ebb5daea54bd266..9e55390b54dbe2751229c317b2a487a47385402b 100644 (file)
@@ -9,9 +9,6 @@ LL |     a: PartialEqNotEq,
    |
 note: required by a bound in `AssertParamIsEq`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub struct AssertParamIsEq<T: Eq + ?Sized> {
-   |                               ^^ required by this bound in `AssertParamIsEq`
    = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `PartialEqNotEq` with `#[derive(Eq)]`
    |
index 99505f31639686770f8ecfb51ebb5daea54bd266..9e55390b54dbe2751229c317b2a487a47385402b 100644 (file)
@@ -9,9 +9,6 @@ LL |     a: PartialEqNotEq,
    |
 note: required by a bound in `AssertParamIsEq`
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
-   |
-LL | pub struct AssertParamIsEq<T: Eq + ?Sized> {
-   |                               ^^ required by this bound in `AssertParamIsEq`
    = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `PartialEqNotEq` with `#[derive(Eq)]`
    |
index 98a9bd07ed21d0ca5d3bfee529a37cd3c42d9635..db42ed9baf1ed4e3fe6d1655866f02847c37b4d1 100644 (file)
@@ -9,14 +9,10 @@ LL |   trait Foo {
 ...
 LL |       let _z = y.clone();
    |                  ^^^^^ method cannot be called on `Box<dyn Foo>` due to unsatisfied trait bounds
-   |
+  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
   ::: $SRC_DIR/alloc/src/boxed.rs:LL:COL
    |
-LL | / pub struct Box<
-LL | |     T: ?Sized,
-LL | |     #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
-LL | | >(Unique<T>, A);
-   | |_- doesn't satisfy `Box<dyn Foo>: Clone`
+   = note: doesn't satisfy `Box<dyn Foo>: Clone`
    |
    = note: the following trait bounds were not satisfied:
            `dyn Foo: Sized`
index 7af9c684b72e3b7e3e809085e1b3f53e015a4b5e..de6611324cac137c006a4ff24f9ad56470c9c13b 100644 (file)
@@ -6,14 +6,10 @@ LL |   struct R {
 ...
 LL |       let _j = i.clone();
    |                  ^^^^^ method cannot be called on `Box<R>` due to unsatisfied trait bounds
-   |
+  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
   ::: $SRC_DIR/alloc/src/boxed.rs:LL:COL
    |
-LL | / pub struct Box<
-LL | |     T: ?Sized,
-LL | |     #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
-LL | | >(Unique<T>, A);
-   | |_- doesn't satisfy `Box<R>: Clone`
+   = note: doesn't satisfy `Box<R>: Clone`
    |
    = note: the following trait bounds were not satisfied:
            `R: Clone`
index d52a92b8888e8dde0ec433d54af6072b6b5be0cd..2a3ca14433f62ffeaec52fb189a016064eda8d35 100644 (file)
@@ -11,9 +11,6 @@ LL |     x.clone();
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL |     fn not(self) -> Self::Output;
-   |            ^^^^
 help: consider cloning the value if the performance cost is acceptable
    |
 LL |     !x.clone();
@@ -57,9 +54,6 @@ LL |     !*m;
    |
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
-   |
-LL |     fn not(self) -> Self::Output;
-   |            ^^^^
 
 error[E0507]: cannot move out of `*n` which is behind a shared reference
   --> $DIR/unop-move-semantics.rs:26:6
index d8bffd4f9cf3e51f94559b79fcd34feec564898d..9e3c345dd80011636573cd4f6601187545fdf9b1 100644 (file)
@@ -59,7 +59,7 @@ LL |         y.foo();
 LL |         println!("{}", &y);
    |                        ^^ value borrowed here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `y`
+note: `Foo::foo` takes ownership of the receiver `self`, which moves `y`
   --> $DIR/borrow-after-move.rs:5:12
    |
 LL |     fn foo(self) -> String;
index 71534818141caeb3fc06791687887b757dd799ca..49b906bbe02b725c0f9d1e806a470949c55d591a 100644 (file)
@@ -55,7 +55,7 @@ LL |         y.foo();
 LL |         y.foo();
    |         ^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `y`
+note: `Foo::foo` takes ownership of the receiver `self`, which moves `y`
   --> $DIR/double-move.rs:5:12
    |
 LL |     fn foo(self) -> String;
index 50060e53a49d64fe15b62716e0de51e8545baa98..d7b95f55769fdc600f7b37ff9ec22b43e9844215 100644 (file)
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `dyn Foo: CastTo<[i32]>` is not satisfied
-  --> $DIR/issue-71659.rs:30:13
+  --> $DIR/issue-71659.rs:30:15
    |
 LL |     let x = x.cast::<[i32]>();
-   |             ^ ---- required by a bound introduced by this call
-   |             |
-   |             the trait `CastTo<[i32]>` is not implemented for `dyn Foo`
+   |               ^^^^ the trait `CastTo<[i32]>` is not implemented for `dyn Foo`
    |
 note: required by a bound in `Cast::cast`
   --> $DIR/issue-71659.rs:19:15
index 7fdc4ab251fe8ad5b2f93102c959ecb7c1f5346a..1bdf49801f975ba72192dfb6d72324d316c04324 100644 (file)
@@ -8,7 +8,7 @@ LL |         self.bar();
 LL |         return self.x;
    |                ^^^^^^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `self`
+note: `S::bar` takes ownership of the receiver `self`, which moves `self`
   --> $DIR/use-after-move-self-based-on-type.rs:15:16
    |
 LL |     pub fn bar(self) {}
index 073deee63b98c763a35049c2a377af3925f3a5eb..59cc22eadb0153c8bd3903278f649ccdc13ab133 100644 (file)
@@ -8,7 +8,7 @@ LL |         self.bar();
 LL |         return *self.x;
    |                ^^^^^^^ value used here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `self`
+note: `S::bar` takes ownership of the receiver `self`, which moves `self`
   --> $DIR/use-after-move-self.rs:13:16
    |
 LL |     pub fn bar(self) {}
index 4384e345e85c72cbb24ed3e3e68e1f4e8c237fb7..2b85fa9bed480df4bf954d69decde3dfeeb292cf 100644 (file)
@@ -8,7 +8,7 @@ LL |     let end = Mine{other_val:1, ..start.make_string_bar()};
 LL |     println!("{}", start.test);
    |                    ^^^^^^^^^^ value borrowed here after move
    |
-note: this function takes ownership of the receiver `self`, which moves `start`
+note: `Mine::make_string_bar` takes ownership of the receiver `self`, which moves `start`
   --> $DIR/walk-struct-literal-with.rs:7:28
    |
 LL |     fn make_string_bar(mut self) -> Mine{
diff --git a/src/test/ui/wf/hir-wf-canonicalized.rs b/src/test/ui/wf/hir-wf-canonicalized.rs
new file mode 100644 (file)
index 0000000..bdb8440
--- /dev/null
@@ -0,0 +1,18 @@
+// incremental
+
+trait Foo {
+    type V;
+}
+
+trait Callback<T: Foo>: Fn(&Bar<'_, T>, &T::V) {}
+
+struct Bar<'a, T> {
+    callback: Box<dyn Callback<dyn Callback<Bar<'a, T>>>>,
+    //~^ ERROR the trait bound `Bar<'a, T>: Foo` is not satisfied
+    //~| ERROR the trait bound `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static): Foo` is not satisfied
+    //~| ERROR the size for values of type `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static)` cannot be known at compilation time
+}
+
+impl<T: Foo> Bar<'_, Bar<'_, T>> {}
+
+fn main() {}
diff --git a/src/test/ui/wf/hir-wf-canonicalized.stderr b/src/test/ui/wf/hir-wf-canonicalized.stderr
new file mode 100644 (file)
index 0000000..9fd0f9c
--- /dev/null
@@ -0,0 +1,32 @@
+error[E0277]: the trait bound `Bar<'a, T>: Foo` is not satisfied
+  --> $DIR/hir-wf-canonicalized.rs:10:15
+   |
+LL |     callback: Box<dyn Callback<dyn Callback<Bar<'a, T>>>>,
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `Bar<'a, T>`
+
+error[E0277]: the trait bound `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static): Foo` is not satisfied
+  --> $DIR/hir-wf-canonicalized.rs:10:15
+   |
+LL |     callback: Box<dyn Callback<dyn Callback<Bar<'a, T>>>>,
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static)`
+
+error[E0277]: the size for values of type `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static)` cannot be known at compilation time
+  --> $DIR/hir-wf-canonicalized.rs:10:15
+   |
+LL |     callback: Box<dyn Callback<dyn Callback<Bar<'a, T>>>>,
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static)`
+note: required by a bound in `Bar`
+  --> $DIR/hir-wf-canonicalized.rs:9:16
+   |
+LL | struct Bar<'a, T> {
+   |                ^ required by this bound in `Bar`
+help: consider relaxing the implicit `Sized` restriction
+   |
+LL | struct Bar<'a, T: ?Sized> {
+   |                 ++++++++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
index b04588c5716150a43ed078d7d2ffc4a968e550b4..7bc19dd2e2162de72de9a84446393042e1c8d63c 100644 (file)
@@ -9,9 +9,6 @@ LL |     type IntoIter = std::iter::Flatten<std::slice::Iter<'a, T>>;
    = note: required for `&T` to implement `IntoIterator`
 note: required by a bound in `Flatten`
   --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL
-   |
-LL | pub struct Flatten<I: Iterator<Item: IntoIterator>> {
-   |                                      ^^^^^^^^^^^^ required by this bound in `Flatten`
 
 error[E0277]: `&T` is not an iterator
   --> $DIR/hir-wf-check-erase-regions.rs:10:27
@@ -24,9 +21,6 @@ LL |     fn into_iter(self) -> Self::IntoIter {
    = note: required for `&T` to implement `IntoIterator`
 note: required by a bound in `Flatten`
   --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL
-   |
-LL | pub struct Flatten<I: Iterator<Item: IntoIterator>> {
-   |                                      ^^^^^^^^^^^^ required by this bound in `Flatten`
 
 error: aborting due to 2 previous errors
 
index 371321793adf89f5c54c4cd13534f84376ed96a1..1ca368729fe6fb6b5f57a791801d950df12fa83d 100644 (file)
@@ -7,9 +7,6 @@ LL | impl Foo for Option<[u8]> {}
    = help: the trait `Sized` is not implemented for `[u8]`
 note: required by a bound in `Option`
   --> $SRC_DIR/core/src/option.rs:LL:COL
-   |
-LL | pub enum Option<T> {
-   |                 ^ required by this bound in `Option`
 
 error: aborting due to previous error
 
index 9f8896f01ee06f90e776c07c1ccbfdfa8a496216..8338f61b22a756941d048eaa59d04c33263e8b99 100644 (file)
@@ -38,7 +38,9 @@ error[E0308]: mismatched types
   --> $DIR/wrong-mul-method-signature.rs:63:45
    |
 LL |     let x: Vec2 = Vec2 { x: 1.0, y: 2.0 } * 2.0; // trait had reversed order
-   |                                             ^^^ expected struct `Vec2`, found floating-point number
+   |                   -----------------------   ^^^ expected struct `Vec2`, found floating-point number
+   |                   |
+   |                   expected because this is `Vec2`
 
 error[E0308]: mismatched types
   --> $DIR/wrong-mul-method-signature.rs:63:19
index f6e737b1e3386adb89333bf06a01f68a91ac5306..cc0a320879c17207bbfb96b5d778e28a2c62030d 160000 (submodule)
@@ -1 +1 @@
-Subproject commit f6e737b1e3386adb89333bf06a01f68a91ac5306
+Subproject commit cc0a320879c17207bbfb96b5d778e28a2c62030d
index 6448b2d4068deb480aa9484fb082288e7c8b81ca..1bc457a947936b4e35fa9c9cbe8a4f945d1721e5 100644 (file)
@@ -82,13 +82,6 @@ jobs:
       with:
         github_token: "${{ secrets.github_token }}"
 
-    - name: Install dependencies (Linux-i686)
-      run: |
-        sudo dpkg --add-architecture i386
-        sudo apt-get update
-        sudo apt-get install gcc-multilib libssl-dev:i386 libgit2-dev:i386
-      if: matrix.host == 'i686-unknown-linux-gnu'
-
     - name: Checkout
       uses: actions/checkout@v3.0.2
 
index 23912bb3ed6b16aea9a4ce27ad1cd5a1a2f50661..903ee938d9d2d2f73e535c3b05eff4be2b628b49 100644 (file)
@@ -6,11 +6,181 @@ document.
 
 ## Unreleased / Beta / In Rust Nightly
 
-[b52fb523...master](https://github.com/rust-lang/rust-clippy/compare/b52fb523...master)
+[4f142aa1...master](https://github.com/rust-lang/rust-clippy/compare/4f142aa1...master)
+
+## Rust 1.66
+
+Current stable, released 2022-12-15
+
+[b52fb523...4f142aa1](https://github.com/rust-lang/rust-clippy/compare/b52fb523...4f142aa1)
+
+### New Lints
+
+* [`manual_clamp`]
+  [#9484](https://github.com/rust-lang/rust-clippy/pull/9484)
+* [`missing_trait_methods`]
+  [#9670](https://github.com/rust-lang/rust-clippy/pull/9670)
+* [`unused_format_specs`]
+  [#9637](https://github.com/rust-lang/rust-clippy/pull/9637)
+* [`iter_kv_map`]
+  [#9409](https://github.com/rust-lang/rust-clippy/pull/9409)
+* [`manual_filter`]
+  [#9451](https://github.com/rust-lang/rust-clippy/pull/9451)
+* [`box_default`]
+  [#9511](https://github.com/rust-lang/rust-clippy/pull/9511)
+* [`implicit_saturating_add`]
+  [#9549](https://github.com/rust-lang/rust-clippy/pull/9549)
+* [`as_ptr_cast_mut`]
+  [#9572](https://github.com/rust-lang/rust-clippy/pull/9572)
+* [`disallowed_macros`]
+  [#9495](https://github.com/rust-lang/rust-clippy/pull/9495)
+* [`partial_pub_fields`]
+  [#9658](https://github.com/rust-lang/rust-clippy/pull/9658)
+* [`uninlined_format_args`]
+  [#9233](https://github.com/rust-lang/rust-clippy/pull/9233)
+* [`cast_nan_to_int`]
+  [#9617](https://github.com/rust-lang/rust-clippy/pull/9617)
+
+### Moves and Deprecations
+
+* `positional_named_format_parameters` was uplifted to rustc under the new name
+  `named_arguments_used_positionally`
+  [#8518](https://github.com/rust-lang/rust-clippy/pull/8518)
+* Moved [`implicit_saturating_sub`] to `style` (Now warn-by-default)
+  [#9584](https://github.com/rust-lang/rust-clippy/pull/9584)
+* Moved `derive_partial_eq_without_eq` to `nursery` (now allow-by-default)
+  [#9536](https://github.com/rust-lang/rust-clippy/pull/9536)
+
+### Enhancements
+
+* [`nonstandard_macro_braces`]: Now includes `matches!()` in the default lint config
+  [#9471](https://github.com/rust-lang/rust-clippy/pull/9471)
+* [`suboptimal_flops`]: Now supports multiplication and subtraction operations
+  [#9581](https://github.com/rust-lang/rust-clippy/pull/9581)
+* [`arithmetic_side_effects`]: Now detects cases with literals behind references
+  [#9587](https://github.com/rust-lang/rust-clippy/pull/9587)
+* [`upper_case_acronyms`]: Now also checks enum names
+  [#9580](https://github.com/rust-lang/rust-clippy/pull/9580)
+* [`needless_borrowed_reference`]: Now lints nested patterns
+  [#9573](https://github.com/rust-lang/rust-clippy/pull/9573)
+* [`unnecessary_cast`]: Now works for non-trivial non-literal expressions
+  [#9576](https://github.com/rust-lang/rust-clippy/pull/9576)
+* [`arithmetic_side_effects`]: Now detects operations with custom types
+  [#9559](https://github.com/rust-lang/rust-clippy/pull/9559)
+* [`disallowed_methods`], [`disallowed_types`]: Not correctly lints types, functions and macros
+  with the same path
+  [#9495](https://github.com/rust-lang/rust-clippy/pull/9495)
+* [`self_named_module_files`], [`mod_module_files`]: Now take remapped path prefixes into account
+  [#9475](https://github.com/rust-lang/rust-clippy/pull/9475)
+* [`bool_to_int_with_if`]: Now detects the inverse if case
+  [#9476](https://github.com/rust-lang/rust-clippy/pull/9476)
+
+### False Positive Fixes
+
+* [`arithmetic_side_effects`]: Now allows operations that can't overflow
+  [#9474](https://github.com/rust-lang/rust-clippy/pull/9474)
+* [`unnecessary_lazy_evaluations`]: No longer lints in external macros
+  [#9486](https://github.com/rust-lang/rust-clippy/pull/9486)
+* [`needless_borrow`], [`explicit_auto_deref`]: No longer lint on unions that require the reference
+  [#9490](https://github.com/rust-lang/rust-clippy/pull/9490)
+* [`almost_complete_letter_range`]: No longer lints in external macros
+  [#9467](https://github.com/rust-lang/rust-clippy/pull/9467)
+* [`drop_copy`]: No longer lints on idiomatic cases in match arms 
+  [#9491](https://github.com/rust-lang/rust-clippy/pull/9491)
+* [`question_mark`]: No longer lints in const context
+  [#9487](https://github.com/rust-lang/rust-clippy/pull/9487)
+* [`collapsible_if`]: Suggestion now work in macros
+  [#9410](https://github.com/rust-lang/rust-clippy/pull/9410)
+* [`std_instead_of_core`]: No longer triggers on unstable modules
+  [#9545](https://github.com/rust-lang/rust-clippy/pull/9545)
+* [`unused_peekable`]: No longer lints, if the peak is done in a closure or function
+  [#9465](https://github.com/rust-lang/rust-clippy/pull/9465)
+* [`useless_attribute`]: No longer lints on `#[allow]` attributes for [`unsafe_removed_from_name`]
+  [#9593](https://github.com/rust-lang/rust-clippy/pull/9593)
+* [`unnecessary_lazy_evaluations`]: No longer suggest switching to early evaluation when type has
+  custom `Drop` implementation
+  [#9551](https://github.com/rust-lang/rust-clippy/pull/9551)
+* [`unnecessary_cast`]: No longer lints on negative hexadecimal literals when cast as floats
+  [#9609](https://github.com/rust-lang/rust-clippy/pull/9609)
+* [`use_self`]: No longer lints in proc macros
+  [#9454](https://github.com/rust-lang/rust-clippy/pull/9454)
+* [`never_loop`]: Now takes `let ... else` statements into consideration.
+  [#9496](https://github.com/rust-lang/rust-clippy/pull/9496)
+* [`default_numeric_fallback`]: Now ignores constants
+  [#9636](https://github.com/rust-lang/rust-clippy/pull/9636)
+* [`uninit_vec`]: No longer lints `Vec::set_len(0)`
+  [#9519](https://github.com/rust-lang/rust-clippy/pull/9519)
+* [`arithmetic_side_effects`]: Now ignores references to integer types
+  [#9507](https://github.com/rust-lang/rust-clippy/pull/9507)
+* [`large_stack_arrays`]: No longer lints inside static items
+  [#9466](https://github.com/rust-lang/rust-clippy/pull/9466)
+* [`ref_option_ref`]: No longer lints if the inner reference is mutable
+  [#9684](https://github.com/rust-lang/rust-clippy/pull/9684)
+* [`ptr_arg`]: No longer lints if the argument is used as an incomplete trait object
+  [#9645](https://github.com/rust-lang/rust-clippy/pull/9645)
+* [`should_implement_trait`]: Now also works for `default` methods
+  [#9546](https://github.com/rust-lang/rust-clippy/pull/9546)
+
+### Suggestion Fixes/Improvements
+
+* [`derivable_impls`]: The suggestion is now machine applicable
+  [#9429](https://github.com/rust-lang/rust-clippy/pull/9429)
+* [`match_single_binding`]: The suggestion now handles scrutinies with side effects better
+  [#9601](https://github.com/rust-lang/rust-clippy/pull/9601)
+* [`zero_prefixed_literal`]: Only suggests using octal numbers, if this is possible
+  [#9652](https://github.com/rust-lang/rust-clippy/pull/9652)
+* [`rc_buffer`]: The suggestion is no longer machine applicable to avoid semantic changes
+  [#9633](https://github.com/rust-lang/rust-clippy/pull/9633)
+* [`print_literal`], [`write_literal`], [`uninlined_format_args`]: The suggestion now ignores
+  comments after the macro call.
+  [#9586](https://github.com/rust-lang/rust-clippy/pull/9586)
+* [`expect_fun_call`]:Improved the suggestion for `format!` calls with captured variables
+  [#9586](https://github.com/rust-lang/rust-clippy/pull/9586)
+* [`nonstandard_macro_braces`]: The suggestion is now machine applicable and will no longer
+  replace brackets inside the macro argument.
+  [#9499](https://github.com/rust-lang/rust-clippy/pull/9499)
+* [`from_over_into`]: The suggestion is now a machine applicable and contains explanations
+  [#9649](https://github.com/rust-lang/rust-clippy/pull/9649)
+* [`needless_return`]: The automatic suggestion now removes all required semicolons
+  [#9497](https://github.com/rust-lang/rust-clippy/pull/9497)
+* [`to_string_in_format_args`]: The suggestion now keeps parenthesis around values
+  [#9590](https://github.com/rust-lang/rust-clippy/pull/9590)
+* [`manual_assert`]: The suggestion now preserves comments
+  [#9479](https://github.com/rust-lang/rust-clippy/pull/9479)
+* [`redundant_allocation`]: The suggestion applicability is now marked `MaybeIncorrect` to
+  avoid semantic changes
+  [#9634](https://github.com/rust-lang/rust-clippy/pull/9634)
+* [`assertions_on_result_states`]: The suggestion has been corrected, for cases where the
+  `assert!` is not in a statement.
+  [#9453](https://github.com/rust-lang/rust-clippy/pull/9453)
+* [`nonminimal_bool`]: The suggestion no longer expands macros
+  [#9457](https://github.com/rust-lang/rust-clippy/pull/9457)
+* [`collapsible_match`]: Now specifies field names, when a struct is destructed
+  [#9685](https://github.com/rust-lang/rust-clippy/pull/9685)
+* [`unnecessary_cast`]: The suggestion now adds parenthesis for negative numbers
+  [#9577](https://github.com/rust-lang/rust-clippy/pull/9577)
+* [`redundant_closure`]: The suggestion now works for `impl FnMut` arguments
+  [#9556](https://github.com/rust-lang/rust-clippy/pull/9556)
+
+### ICE Fixes
+
+* [`unnecessary_to_owned`]: Avoid ICEs in favor of false negatives if information is missing
+  [#9505](https://github.com/rust-lang/rust-clippy/pull/9505)
+* [`manual_range_contains`]: No longer ICEs on values behind references
+  [#9627](https://github.com/rust-lang/rust-clippy/pull/9627)
+* [`needless_pass_by_value`]: No longer ICEs on unsized `dyn Fn` arguments
+  [#9531](https://github.com/rust-lang/rust-clippy/pull/9531)
+* `*_interior_mutable_const` lints: no longer ICE on const unions containing `!Freeze` types
+  [#9539](https://github.com/rust-lang/rust-clippy/pull/9539)
+
+### Others
+
+* Released `rustc_tools_util` for version information on `Crates.io`. (Further adjustments will
+  not be published as part of this changelog)
 
 ## Rust 1.65
 
-Current stable, released 2022-11-03
+Released 2022-11-03
 
 [3c7e7dbc...b52fb523](https://github.com/rust-lang/rust-clippy/compare/3c7e7dbc...b52fb523)
 
@@ -3875,6 +4045,7 @@ Released 2018-09-13
 [`alloc_instead_of_core`]: https://rust-lang.github.io/rust-clippy/master/index.html#alloc_instead_of_core
 [`allow_attributes_without_reason`]: https://rust-lang.github.io/rust-clippy/master/index.html#allow_attributes_without_reason
 [`almost_complete_letter_range`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_letter_range
+[`almost_complete_range`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_range
 [`almost_swapped`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_swapped
 [`approx_constant`]: https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant
 [`arithmetic_side_effects`]: https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects
@@ -4353,6 +4524,8 @@ Released 2018-09-13
 [`self_named_constructors`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_named_constructors
 [`self_named_module_files`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_named_module_files
 [`semicolon_if_nothing_returned`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
+[`semicolon_inside_block`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_inside_block
+[`semicolon_outside_block`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_outside_block
 [`separated_literal_suffix`]: https://rust-lang.github.io/rust-clippy/master/index.html#separated_literal_suffix
 [`serde_api_misuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#serde_api_misuse
 [`shadow_reuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#shadow_reuse
index fe425a2fb991fdb1377b985eb83d007156ad58dc..f8cb4b7219c47467e6e41412b57f17733c02a46b 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name = "clippy"
-version = "0.1.67"
+version = "0.1.68"
 description = "A bunch of helpful lints to avoid common pitfalls in Rust"
 repository = "https://github.com/rust-lang/rust-clippy"
 readme = "README.md"
@@ -23,7 +23,7 @@ path = "src/driver.rs"
 [dependencies]
 clippy_lints = { path = "clippy_lints" }
 semver = "1.0"
-rustc_tools_util = "0.2.1"
+rustc_tools_util = "0.3.0"
 tempfile = { version = "3.2", optional = true }
 termize = "0.1"
 
@@ -55,7 +55,7 @@ tokio = { version = "1", features = ["io-util"] }
 rustc-semver = "1.1"
 
 [build-dependencies]
-rustc_tools_util = "0.2.1"
+rustc_tools_util = "0.3.0"
 
 [features]
 deny-warnings = ["clippy_lints/deny-warnings"]
index 6248d588a890b9dc13038eaa051ca56cd46d18b6..23867df8efe1dc0ce542f3e299df8326fe1ad56d 100644 (file)
@@ -1,6 +1,6 @@
 # Clippy
 
-[![Clippy Test](https://github.com/rust-lang/rust-clippy/workflows/Clippy%20Test/badge.svg?branch=auto&event=push)](https://github.com/rust-lang/rust-clippy/actions?query=workflow%3A%22Clippy+Test%22+event%3Apush+branch%3Aauto)
+[![Clippy Test](https://github.com/rust-lang/rust-clippy/workflows/Clippy%20Test%20(bors)/badge.svg?branch=auto&event=push)](https://github.com/rust-lang/rust-clippy/actions?query=workflow%3A%22Clippy+Test+(bors)%22+event%3Apush+branch%3Aauto)
 [![License: MIT OR Apache-2.0](https://img.shields.io/crates/l/clippy.svg)](https://github.com/rust-lang/rust-clippy#license)
 
 A collection of lints to catch common mistakes and improve your
index b5484bec3c8b8dca5dc0a00930d846e60533d4a7..b79d09b0dd2d2776e98a4ae73de9c2884e722677 100644 (file)
@@ -3,17 +3,5 @@ fn main() {
     println!("cargo:rustc-env=PROFILE={}", std::env::var("PROFILE").unwrap());
     // Don't rebuild even if nothing changed
     println!("cargo:rerun-if-changed=build.rs");
-    // forward git repo hashes we build at
-    println!(
-        "cargo:rustc-env=GIT_HASH={}",
-        rustc_tools_util::get_commit_hash().unwrap_or_default()
-    );
-    println!(
-        "cargo:rustc-env=COMMIT_DATE={}",
-        rustc_tools_util::get_commit_date().unwrap_or_default()
-    );
-    println!(
-        "cargo:rustc-env=RUSTC_RELEASE_CHANNEL={}",
-        rustc_tools_util::get_channel()
-    );
+    rustc_tools_util::setup_version_info!();
 }
index aedff24c12c6078b7aec3236f261837008df36e3..a9f69b1ba6300907b1ec7c4770a53ab98f9eceba 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name = "clippy_lints"
-version = "0.1.67"
+version = "0.1.68"
 description = "A bunch of helpful lints to avoid common pitfalls in Rust"
 repository = "https://github.com/rust-lang/rust-clippy"
 readme = "README.md"
diff --git a/src/tools/clippy/clippy_lints/src/almost_complete_letter_range.rs b/src/tools/clippy/clippy_lints/src/almost_complete_letter_range.rs
deleted file mode 100644 (file)
index 52beaf5..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::msrvs::{self, Msrv};
-use clippy_utils::source::{trim_span, walk_span_to_context};
-use rustc_ast::ast::{Expr, ExprKind, LitKind, Pat, PatKind, RangeEnd, RangeLimits};
-use rustc_errors::Applicability;
-use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
-use rustc_middle::lint::in_external_macro;
-use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_span::Span;
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for ranges which almost include the entire range of letters from 'a' to 'z', but
-    /// don't because they're a half open range.
-    ///
-    /// ### Why is this bad?
-    /// This (`'a'..'z'`) is almost certainly a typo meant to include all letters.
-    ///
-    /// ### Example
-    /// ```rust
-    /// let _ = 'a'..'z';
-    /// ```
-    /// Use instead:
-    /// ```rust
-    /// let _ = 'a'..='z';
-    /// ```
-    #[clippy::version = "1.63.0"]
-    pub ALMOST_COMPLETE_LETTER_RANGE,
-    suspicious,
-    "almost complete letter range"
-}
-impl_lint_pass!(AlmostCompleteLetterRange => [ALMOST_COMPLETE_LETTER_RANGE]);
-
-pub struct AlmostCompleteLetterRange {
-    msrv: Msrv,
-}
-impl AlmostCompleteLetterRange {
-    pub fn new(msrv: Msrv) -> Self {
-        Self { msrv }
-    }
-}
-impl EarlyLintPass for AlmostCompleteLetterRange {
-    fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &Expr) {
-        if let ExprKind::Range(Some(start), Some(end), RangeLimits::HalfOpen) = &e.kind {
-            let ctxt = e.span.ctxt();
-            let sugg = if let Some(start) = walk_span_to_context(start.span, ctxt)
-                && let Some(end) = walk_span_to_context(end.span, ctxt)
-                && self.msrv.meets(msrvs::RANGE_INCLUSIVE)
-            {
-                Some((trim_span(cx.sess().source_map(), start.between(end)), "..="))
-            } else {
-                None
-            };
-            check_range(cx, e.span, start, end, sugg);
-        }
-    }
-
-    fn check_pat(&mut self, cx: &EarlyContext<'_>, p: &Pat) {
-        if let PatKind::Range(Some(start), Some(end), kind) = &p.kind
-            && matches!(kind.node, RangeEnd::Excluded)
-        {
-            let sugg = if self.msrv.meets(msrvs::RANGE_INCLUSIVE) {
-                "..="
-            } else {
-                "..."
-            };
-            check_range(cx, p.span, start, end, Some((kind.span, sugg)));
-        }
-    }
-
-    extract_msrv_attr!(EarlyContext);
-}
-
-fn check_range(cx: &EarlyContext<'_>, span: Span, start: &Expr, end: &Expr, sugg: Option<(Span, &str)>) {
-    if let ExprKind::Lit(start_token_lit) = start.peel_parens().kind
-        && let ExprKind::Lit(end_token_lit) = end.peel_parens().kind
-        && matches!(
-            (
-                LitKind::from_token_lit(start_token_lit),
-                LitKind::from_token_lit(end_token_lit),
-            ),
-            (
-                Ok(LitKind::Byte(b'a') | LitKind::Char('a')),
-                Ok(LitKind::Byte(b'z') | LitKind::Char('z'))
-            )
-            | (
-                Ok(LitKind::Byte(b'A') | LitKind::Char('A')),
-                Ok(LitKind::Byte(b'Z') | LitKind::Char('Z')),
-            )
-        )
-        && !in_external_macro(cx.sess(), span)
-    {
-        span_lint_and_then(
-            cx,
-            ALMOST_COMPLETE_LETTER_RANGE,
-            span,
-            "almost complete ascii letter range",
-            |diag| {
-                if let Some((span, sugg)) = sugg {
-                    diag.span_suggestion(
-                        span,
-                        "use an inclusive range",
-                        sugg,
-                        Applicability::MaybeIncorrect,
-                    );
-                }
-            }
-        );
-    }
-}
diff --git a/src/tools/clippy/clippy_lints/src/almost_complete_range.rs b/src/tools/clippy/clippy_lints/src/almost_complete_range.rs
new file mode 100644 (file)
index 0000000..42e14b5
--- /dev/null
@@ -0,0 +1,114 @@
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::msrvs::{self, Msrv};
+use clippy_utils::source::{trim_span, walk_span_to_context};
+use rustc_ast::ast::{Expr, ExprKind, LitKind, Pat, PatKind, RangeEnd, RangeLimits};
+use rustc_errors::Applicability;
+use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
+use rustc_middle::lint::in_external_macro;
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::Span;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for ranges which almost include the entire range of letters from 'a' to 'z'
+    /// or digits from '0' to '9', but don't because they're a half open range.
+    ///
+    /// ### Why is this bad?
+    /// This (`'a'..'z'`) is almost certainly a typo meant to include all letters.
+    ///
+    /// ### Example
+    /// ```rust
+    /// let _ = 'a'..'z';
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// let _ = 'a'..='z';
+    /// ```
+    #[clippy::version = "1.63.0"]
+    pub ALMOST_COMPLETE_RANGE,
+    suspicious,
+    "almost complete range"
+}
+impl_lint_pass!(AlmostCompleteRange => [ALMOST_COMPLETE_RANGE]);
+
+pub struct AlmostCompleteRange {
+    msrv: Msrv,
+}
+impl AlmostCompleteRange {
+    pub fn new(msrv: Msrv) -> Self {
+        Self { msrv }
+    }
+}
+impl EarlyLintPass for AlmostCompleteRange {
+    fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &Expr) {
+        if let ExprKind::Range(Some(start), Some(end), RangeLimits::HalfOpen) = &e.kind {
+            let ctxt = e.span.ctxt();
+            let sugg = if let Some(start) = walk_span_to_context(start.span, ctxt)
+                && let Some(end) = walk_span_to_context(end.span, ctxt)
+                && self.msrv.meets(msrvs::RANGE_INCLUSIVE)
+            {
+                Some((trim_span(cx.sess().source_map(), start.between(end)), "..="))
+            } else {
+                None
+            };
+            check_range(cx, e.span, start, end, sugg);
+        }
+    }
+
+    fn check_pat(&mut self, cx: &EarlyContext<'_>, p: &Pat) {
+        if let PatKind::Range(Some(start), Some(end), kind) = &p.kind
+            && matches!(kind.node, RangeEnd::Excluded)
+        {
+            let sugg = if self.msrv.meets(msrvs::RANGE_INCLUSIVE) {
+                "..="
+            } else {
+                "..."
+            };
+            check_range(cx, p.span, start, end, Some((kind.span, sugg)));
+        }
+    }
+
+    extract_msrv_attr!(EarlyContext);
+}
+
+fn check_range(cx: &EarlyContext<'_>, span: Span, start: &Expr, end: &Expr, sugg: Option<(Span, &str)>) {
+    if let ExprKind::Lit(start_token_lit) = start.peel_parens().kind
+        && let ExprKind::Lit(end_token_lit) = end.peel_parens().kind
+        && matches!(
+            (
+                LitKind::from_token_lit(start_token_lit),
+                LitKind::from_token_lit(end_token_lit),
+            ),
+            (
+                Ok(LitKind::Byte(b'a') | LitKind::Char('a')),
+                Ok(LitKind::Byte(b'z') | LitKind::Char('z'))
+            )
+            | (
+                Ok(LitKind::Byte(b'A') | LitKind::Char('A')),
+                Ok(LitKind::Byte(b'Z') | LitKind::Char('Z')),
+            )
+            | (
+                Ok(LitKind::Byte(b'0') | LitKind::Char('0')),
+                Ok(LitKind::Byte(b'9') | LitKind::Char('9')),
+            )
+        )
+        && !in_external_macro(cx.sess(), span)
+    {
+        span_lint_and_then(
+            cx,
+            ALMOST_COMPLETE_RANGE,
+            span,
+            "almost complete ascii range",
+            |diag| {
+                if let Some((span, sugg)) = sugg {
+                    diag.span_suggestion(
+                        span,
+                        "use an inclusive range",
+                        sugg,
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+            }
+        );
+    }
+}
index 36daceabe0bea61a034aeac4dd894cbcff834eb0..91900542af8330e52d72655efb34be044bbfbbf5 100644 (file)
@@ -30,7 +30,7 @@
     /// ```rust
     /// let x: Box<String> = Box::default();
     /// ```
-    #[clippy::version = "1.65.0"]
+    #[clippy::version = "1.66.0"]
     pub BOX_DEFAULT,
     perf,
     "Using Box::new(T::default()) instead of Box::default()"
index c6d505c4a181fc2e3b52c2be3b1d713f7123eec2..161e3a698e9ea6133ba0d6a86e2ad70983d7dbf8 100644 (file)
     /// ```rust,ignore
     /// let _: = 0_u64;
     /// ```
-    #[clippy::version = "1.64.0"]
+    #[clippy::version = "1.66.0"]
     pub CAST_NAN_TO_INT,
     suspicious,
     "casting a known floating-point NaN into an integer"
index e4d76f07d6b482b13fa7d5fbaf9cb8b6ce9923fd..3cd7d1d7e722833645876976a615e1d5a7de123f 100644 (file)
@@ -35,7 +35,7 @@
     crate::utils::internal_lints::produce_ice::PRODUCE_ICE_INFO,
     #[cfg(feature = "internal")]
     crate::utils::internal_lints::unnecessary_def_path::UNNECESSARY_DEF_PATH_INFO,
-    crate::almost_complete_letter_range::ALMOST_COMPLETE_LETTER_RANGE_INFO,
+    crate::almost_complete_range::ALMOST_COMPLETE_RANGE_INFO,
     crate::approx_const::APPROX_CONSTANT_INFO,
     crate::as_conversions::AS_CONVERSIONS_INFO,
     crate::asm_syntax::INLINE_ASM_X86_ATT_SYNTAX_INFO,
     crate::returns::NEEDLESS_RETURN_INFO,
     crate::same_name_method::SAME_NAME_METHOD_INFO,
     crate::self_named_constructors::SELF_NAMED_CONSTRUCTORS_INFO,
+    crate::semicolon_block::SEMICOLON_INSIDE_BLOCK_INFO,
+    crate::semicolon_block::SEMICOLON_OUTSIDE_BLOCK_INFO,
     crate::semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED_INFO,
     crate::serde_api::SERDE_API_MISUSE_INFO,
     crate::shadow::SHADOW_REUSE_INFO,
index 38329659e02b76108ed46d071dd49f38c2a04650..7b43d8ccc67d1fec92a5be0389860e9c8c6658a5 100644 (file)
@@ -1244,7 +1244,7 @@ fn is_mixed_projection_predicate<'tcx>(
         let mut projection_ty = projection_predicate.projection_ty;
         loop {
             match projection_ty.self_ty().kind() {
-                ty::Projection(inner_projection_ty) => {
+                ty::Alias(ty::Projection, inner_projection_ty) => {
                     projection_ty = *inner_projection_ty;
                 }
                 ty::Param(param_ty) => {
@@ -1330,7 +1330,7 @@ fn replace_types<'tcx>(
                     && let Some(term_ty) = projection_predicate.term.ty()
                     && let ty::Param(term_param_ty) = term_ty.kind()
                 {
-                    let item_def_id = projection_predicate.projection_ty.item_def_id;
+                    let item_def_id = projection_predicate.projection_ty.def_id;
                     let assoc_item = cx.tcx.associated_item(item_def_id);
                     let projection = cx.tcx
                         .mk_projection(assoc_item.def_id, cx.tcx.mk_substs_trait(new_ty, []));
@@ -1390,10 +1390,15 @@ fn ty_auto_deref_stability<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, precedenc
                 continue;
             },
             ty::Param(_) => TyPosition::new_deref_stable_for_result(precedence, ty),
-            ty::Projection(_) if ty.has_non_region_param() => TyPosition::new_deref_stable_for_result(precedence, ty),
-            ty::Infer(_) | ty::Error(_) | ty::Bound(..) | ty::Opaque(..) | ty::Placeholder(_) | ty::Dynamic(..) => {
-                Position::ReborrowStable(precedence).into()
+            ty::Alias(ty::Projection, _) if ty.has_non_region_param() => {
+                TyPosition::new_deref_stable_for_result(precedence, ty)
             },
+            ty::Infer(_)
+            | ty::Error(_)
+            | ty::Bound(..)
+            | ty::Alias(ty::Opaque, ..)
+            | ty::Placeholder(_)
+            | ty::Dynamic(..) => Position::ReborrowStable(precedence).into(),
             ty::Adt(..) if ty.has_placeholders() || ty.has_opaque_types() => {
                 Position::ReborrowStable(precedence).into()
             },
@@ -1417,7 +1422,7 @@ fn ty_auto_deref_stability<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, precedenc
             | ty::Closure(..)
             | ty::Never
             | ty::Tuple(_)
-            | ty::Projection(_) => {
+            | ty::Alias(ty::Projection, _) => {
                 Position::DerefStable(precedence, ty.is_sized(cx.tcx, cx.param_env.without_caller_bounds())).into()
             },
         };
index 9e596ca8157eb93b58fc827d6c4d3eda261a116c..cf3483d4c00b17134724bbc51eafcf6abb904aaa 100644 (file)
@@ -15,7 +15,7 @@
 use rustc_middle::traits::Reveal;
 use rustc_middle::ty::{
     self, Binder, BoundConstness, Clause, GenericParamDefKind, ImplPolarity, ParamEnv, PredicateKind, TraitPredicate,
-    TraitRef, Ty, TyCtxt,
+    Ty, TyCtxt,
 };
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Span;
@@ -513,10 +513,7 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) ->
         tcx.mk_predicates(ty_predicates.iter().map(|&(p, _)| p).chain(
             params.iter().filter(|&&(_, needs_eq)| needs_eq).map(|&(param, _)| {
                 tcx.mk_predicate(Binder::dummy(PredicateKind::Clause(Clause::Trait(TraitPredicate {
-                    trait_ref: TraitRef::new(
-                        eq_trait_id,
-                        tcx.mk_substs(std::iter::once(tcx.mk_param_from_def(param))),
-                    ),
+                    trait_ref: tcx.mk_trait_ref(eq_trait_id, [tcx.mk_param_from_def(param)]),
                     constness: BoundConstness::NotConst,
                     polarity: ImplPolarity::Positive,
                 }))))
index 68122b4cef577fede678085f08f58baa9181cbe1..1971cab64ef38a8f01890c1cd8394f7bd238af96 100644 (file)
@@ -47,7 +47,7 @@
     ///     value: usize,
     /// }
     /// ```
-    #[clippy::version = "1.65.0"]
+    #[clippy::version = "1.66.0"]
     pub DISALLOWED_MACROS,
     style,
     "use of a disallowed macro"
index 111b624f52994d747fc327b41830a4cbbba11ff8..69f7c152fc4af84ad6eb70ce628129babe33502f 100644 (file)
@@ -2,7 +2,8 @@
 use clippy_utils::is_diag_trait_item;
 use clippy_utils::macros::FormatParamKind::{Implicit, Named, NamedInline, Numbered, Starred};
 use clippy_utils::macros::{
-    is_format_macro, is_panic, root_macro_call, Count, FormatArg, FormatArgsExpn, FormatParam, FormatParamUsage,
+    is_assert_macro, is_format_macro, is_panic, root_macro_call, Count, FormatArg, FormatArgsExpn, FormatParam,
+    FormatParamUsage,
 };
 use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet_opt;
     ///
     /// If a format string contains a numbered argument that cannot be inlined
     /// nothing will be suggested, e.g. `println!("{0}={1}", var, 1+2)`.
-    #[clippy::version = "1.65.0"]
+    #[clippy::version = "1.66.0"]
     pub UNINLINED_FORMAT_ARGS,
     style,
     "using non-inlined variables in `format!` calls"
@@ -290,8 +291,9 @@ fn check_uninlined_args(
     if args.format_string.span.from_expansion() {
         return;
     }
-    if call_site.edition() < Edition2021 && is_panic(cx, def_id) {
-        // panic! before 2021 edition considers a single string argument as non-format
+    if call_site.edition() < Edition2021 && (is_panic(cx, def_id) || is_assert_macro(cx, def_id)) {
+        // panic!, assert!, and debug_assert! before 2021 edition considers a single string argument as
+        // non-format
         return;
     }
 
index 0634b2798fefee63669f0a2325e9e89b8332ca7a..a92f7548ff254d16a2f51b255675650d139e8734 100644 (file)
@@ -10,7 +10,7 @@
     TyKind,
 };
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::hir::nested_filter::OnlyBodies;
+use rustc_middle::{hir::nested_filter::OnlyBodies, ty};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::symbol::{kw, sym};
 use rustc_span::{Span, Symbol};
@@ -78,6 +78,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
             && let Some(GenericArgs { args: [GenericArg::Type(target_ty)], .. }) = into_trait_seg.args
             && let Some(middle_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id)
             && cx.tcx.is_diagnostic_item(sym::Into, middle_trait_ref.def_id)
+            && !matches!(middle_trait_ref.substs.type_at(1).kind(), ty::Alias(ty::Opaque, _))
         {
             span_lint_and_then(
                 cx,
index 61934a9142633003f805f421ea4f9855451e76f3..989f83cf80d5972301fc06eef9604796f674a7b8 100644 (file)
@@ -4,7 +4,7 @@
 use rustc_hir::{Body, FnDecl, HirId};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::{Clause, EarlyBinder, Opaque, PredicateKind};
+use rustc_middle::ty::{self, AliasTy, Clause, EarlyBinder, PredicateKind};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::{sym, Span};
 use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt;
@@ -62,11 +62,11 @@ fn check_fn(
             return;
         }
         let ret_ty = return_ty(cx, hir_id);
-        if let Opaque(id, subst) = *ret_ty.kind() {
-            let preds = cx.tcx.explicit_item_bounds(id);
+        if let ty::Alias(ty::Opaque, AliasTy { def_id, substs, .. }) = *ret_ty.kind() {
+            let preds = cx.tcx.explicit_item_bounds(def_id);
             let mut is_future = false;
             for &(p, _span) in preds {
-                let p = EarlyBinder(p).subst(cx.tcx, subst);
+                let p = EarlyBinder(p).subst(cx.tcx, substs);
                 if let Some(trait_pred) = p.to_opt_poly_trait_pred() {
                     if Some(trait_pred.skip_binder().trait_ref.def_id) == cx.tcx.lang_items().future_trait() {
                         is_future = true;
index bf1351829c6a5e2e61755dc873df6494e5009ab5..6e19343931ecb846bc9d9ece97efd37c9f27683b 100644 (file)
@@ -31,7 +31,7 @@
     ///
     /// u = u.saturating_add(1);
     /// ```
-    #[clippy::version = "1.65.0"]
+    #[clippy::version = "1.66.0"]
     pub IMPLICIT_SATURATING_ADD,
     style,
     "Perform saturating addition instead of implicitly checking max bound of data type"
index 4cd7dff4cfd762c95352f230beb6b8b3f0652458..eebfb753a0c5dfdefcb0e542676fcbf9c8faba6d 100644 (file)
@@ -1,13 +1,13 @@
 //! lint on indexing and slicing operations
 
 use clippy_utils::consts::{constant, Constant};
-use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
 use clippy_utils::higher;
 use rustc_ast::ast::RangeLimits;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
-use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
 
 declare_clippy_lint! {
     /// ### What it does
     "indexing/slicing usage"
 }
 
-declare_lint_pass!(IndexingSlicing => [INDEXING_SLICING, OUT_OF_BOUNDS_INDEXING]);
+impl_lint_pass!(IndexingSlicing => [INDEXING_SLICING, OUT_OF_BOUNDS_INDEXING]);
+
+#[derive(Copy, Clone)]
+pub struct IndexingSlicing {
+    suppress_restriction_lint_in_const: bool,
+}
+
+impl IndexingSlicing {
+    pub fn new(suppress_restriction_lint_in_const: bool) -> Self {
+        Self {
+            suppress_restriction_lint_in_const,
+        }
+    }
+}
 
 impl<'tcx> LateLintPass<'tcx> for IndexingSlicing {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if cx.tcx.hir().is_inside_const_context(expr.hir_id) {
+        if self.suppress_restriction_lint_in_const && cx.tcx.hir().is_inside_const_context(expr.hir_id) {
             return;
         }
 
         if let ExprKind::Index(array, index) = &expr.kind {
+            let note = "the suggestion might not be applicable in constant blocks";
             let ty = cx.typeck_results().expr_ty(array).peel_refs();
             if let Some(range) = higher::Range::hir(index) {
                 // Ranged indexes, i.e., &x[n..m], &x[n..], &x[..n] and &x[..]
@@ -141,7 +155,13 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
                     (None, None) => return, // [..] is ok.
                 };
 
-                span_lint_and_help(cx, INDEXING_SLICING, expr.span, "slicing may panic", None, help_msg);
+                span_lint_and_then(cx, INDEXING_SLICING, expr.span, "slicing may panic", |diag| {
+                    diag.help(help_msg);
+
+                    if cx.tcx.hir().is_inside_const_context(expr.hir_id) {
+                        diag.note(note);
+                    }
+                });
             } else {
                 // Catchall non-range index, i.e., [n] or [n << m]
                 if let ty::Array(..) = ty.kind() {
@@ -156,14 +176,13 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
                     }
                 }
 
-                span_lint_and_help(
-                    cx,
-                    INDEXING_SLICING,
-                    expr.span,
-                    "indexing may panic",
-                    None,
-                    "consider using `.get(n)` or `.get_mut(n)` instead",
-                );
+                span_lint_and_then(cx, INDEXING_SLICING, expr.span, "indexing may panic", |diag| {
+                    diag.help("consider using `.get(n)` or `.get_mut(n)` instead");
+
+                    if cx.tcx.hir().is_inside_const_context(expr.hir_id) {
+                        diag.note(note);
+                    }
+                });
             }
         }
     }
index e0a607f9a95b68391d69d69a76ea2418b5b681bf..6a4861747d267c83663ca3e405a8d61d13564c26 100644 (file)
@@ -33,7 +33,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
         if let Some([arg]) = match_function_call(cx, expr, &paths::STR_FROM_UTF8_UNCHECKED) {
             match &arg.kind {
                 ExprKind::Lit(Spanned { node: lit, .. }) => {
-                    if let LitKind::ByteStr(bytes) = &lit
+                    if let LitKind::ByteStr(bytes, _) = &lit
                         && std::str::from_utf8(bytes).is_err()
                     {
                         lint(cx, expr.span);
index 84dd61a1e4b0d6cb219ca9acdf933667fcab632a..424c0d9e798288257d0347c61c666a12574b5f23 100644 (file)
@@ -60,7 +60,7 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) {
             then {
                 let len = match &lit.node {
                     // include_bytes
-                    LitKind::ByteStr(bstr) => bstr.len(),
+                    LitKind::ByteStr(bstr, _) => bstr.len(),
                     // include_str
                     LitKind::Str(sym, _) => sym.as_str().len(),
                     _ => return,
index 4c133c06a157ac9e0fcc6ce422bc1c2191404536..e88d1764a24896a23d168a5b01c2d908e851e804 100644 (file)
@@ -1,13 +1,13 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{get_item_name, get_parent_as_impl, is_lint_allowed};
+use clippy_utils::{get_item_name, get_parent_as_impl, is_lint_allowed, peel_ref_operators};
 use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::def_id::DefIdSet;
 use rustc_hir::{
     def_id::DefId, AssocItemKind, BinOpKind, Expr, ExprKind, FnRetTy, ImplItem, ImplItemKind, ImplicitSelfKind, Item,
-    ItemKind, Mutability, Node, TraitItemRef, TyKind,
+    ItemKind, Mutability, Node, TraitItemRef, TyKind, UnOp,
 };
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::{self, AssocKind, FnSig, Ty};
@@ -16,6 +16,7 @@
     source_map::{Span, Spanned, Symbol},
     symbol::sym,
 };
+use std::borrow::Cow;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -428,16 +429,23 @@ fn check_len(
 fn check_empty_expr(cx: &LateContext<'_>, span: Span, lit1: &Expr<'_>, lit2: &Expr<'_>, op: &str) {
     if (is_empty_array(lit2) || is_empty_string(lit2)) && has_is_empty(cx, lit1) {
         let mut applicability = Applicability::MachineApplicable;
+
+        let lit1 = peel_ref_operators(cx, lit1);
+        let mut lit_str = snippet_with_applicability(cx, lit1.span, "_", &mut applicability);
+
+        // Wrap the expression in parentheses if it's a deref expression. Otherwise operator precedence will
+        // cause the code to dereference boolean(won't compile).
+        if let ExprKind::Unary(UnOp::Deref, _) = lit1.kind {
+            lit_str = Cow::from(format!("({lit_str})"));
+        }
+
         span_lint_and_sugg(
             cx,
             COMPARISON_TO_EMPTY,
             span,
             "comparison to empty slice",
             &format!("using `{op}is_empty` is clearer and more explicit"),
-            format!(
-                "{op}{}.is_empty()",
-                snippet_with_applicability(cx, lit1.span, "_", &mut applicability)
-            ),
+            format!("{op}{lit_str}.is_empty()"),
             applicability,
         );
     }
@@ -493,7 +501,7 @@ fn has_is_empty_impl(cx: &LateContext<'_>, id: DefId) -> bool {
                 .filter_by_name_unhygienic(is_empty)
                 .any(|item| is_is_empty(cx, item))
         }),
-        ty::Projection(ref proj) => has_is_empty_impl(cx, proj.item_def_id),
+        ty::Alias(ty::Projection, ref proj) => has_is_empty_impl(cx, proj.def_id),
         ty::Adt(id, _) => has_is_empty_impl(cx, id.did()),
         ty::Array(..) | ty::Slice(..) | ty::Str => true,
         _ => false,
index 7b17d8a156d5af6ddb3b9417b7990e65d2a3d5ee..39850d598038f1b3d15fce37e068528a3c9b1c8d 100644 (file)
@@ -66,7 +66,7 @@
 mod renamed_lints;
 
 // begin lints modules, do not remove this comment, it’s used in `update_lints`
-mod almost_complete_letter_range;
+mod almost_complete_range;
 mod approx_const;
 mod as_conversions;
 mod asm_syntax;
 mod returns;
 mod same_name_method;
 mod self_named_constructors;
+mod semicolon_block;
 mod semicolon_if_nothing_returned;
 mod serde_api;
 mod shadow;
@@ -507,9 +508,20 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     }
 
     let arithmetic_side_effects_allowed = conf.arithmetic_side_effects_allowed.clone();
+    let arithmetic_side_effects_allowed_binary = conf.arithmetic_side_effects_allowed_binary.clone();
+    let arithmetic_side_effects_allowed_unary = conf.arithmetic_side_effects_allowed_unary.clone();
     store.register_late_pass(move |_| {
         Box::new(operators::arithmetic_side_effects::ArithmeticSideEffects::new(
-            arithmetic_side_effects_allowed.clone(),
+            arithmetic_side_effects_allowed
+                .iter()
+                .flat_map(|el| [[el.clone(), "*".to_string()], ["*".to_string(), el.clone()]])
+                .chain(arithmetic_side_effects_allowed_binary.clone())
+                .collect(),
+            arithmetic_side_effects_allowed
+                .iter()
+                .chain(arithmetic_side_effects_allowed_unary.iter())
+                .cloned()
+                .collect(),
         ))
     });
     store.register_late_pass(|_| Box::new(utils::dump_hir::DumpHir));
@@ -538,7 +550,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::new(needless_bool::NeedlessBool));
     store.register_late_pass(|_| Box::new(needless_bool::BoolComparison));
     store.register_late_pass(|_| Box::new(needless_for_each::NeedlessForEach));
-    store.register_late_pass(|_| Box::new(misc::MiscLints));
+    store.register_late_pass(|_| Box::<misc::LintPass>::default());
     store.register_late_pass(|_| Box::new(eta_reduction::EtaReduction));
     store.register_late_pass(|_| Box::new(mut_mut::MutMut));
     store.register_late_pass(|_| Box::new(mut_reference::UnnecessaryMutPassed));
@@ -561,6 +573,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     let avoid_breaking_exported_api = conf.avoid_breaking_exported_api;
     let allow_expect_in_tests = conf.allow_expect_in_tests;
     let allow_unwrap_in_tests = conf.allow_unwrap_in_tests;
+    let suppress_restriction_lint_in_const = conf.suppress_restriction_lint_in_const;
     store.register_late_pass(move |_| Box::new(approx_const::ApproxConstant::new(msrv())));
     store.register_late_pass(move |_| {
         Box::new(methods::Methods::new(
@@ -682,7 +695,11 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::new(inherent_impl::MultipleInherentImpl));
     store.register_late_pass(|_| Box::new(neg_cmp_op_on_partial_ord::NoNegCompOpForPartialOrd));
     store.register_late_pass(|_| Box::new(unwrap::Unwrap));
-    store.register_late_pass(|_| Box::new(indexing_slicing::IndexingSlicing));
+    store.register_late_pass(move |_| {
+        Box::new(indexing_slicing::IndexingSlicing::new(
+            suppress_restriction_lint_in_const,
+        ))
+    });
     store.register_late_pass(|_| Box::new(non_copy_const::NonCopyConst));
     store.register_late_pass(|_| Box::new(ptr_offset_with_cast::PtrOffsetWithCast));
     store.register_late_pass(|_| Box::new(redundant_clone::RedundantClone));
@@ -859,7 +876,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::new(rc_clone_in_vec_init::RcCloneInVecInit));
     store.register_early_pass(|| Box::<duplicate_mod::DuplicateMod>::default());
     store.register_early_pass(|| Box::new(unused_rounding::UnusedRounding));
-    store.register_early_pass(move || Box::new(almost_complete_letter_range::AlmostCompleteLetterRange::new(msrv())));
+    store.register_early_pass(move || Box::new(almost_complete_range::AlmostCompleteRange::new(msrv())));
     store.register_late_pass(|_| Box::new(swap_ptr_to_ref::SwapPtrToRef));
     store.register_late_pass(|_| Box::new(mismatching_type_param_order::TypeParamMismatch));
     store.register_late_pass(|_| Box::new(read_zero_byte_vec::ReadZeroByteVec));
@@ -884,6 +901,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::new(from_raw_with_void_ptr::FromRawWithVoidPtr));
     store.register_late_pass(|_| Box::new(suspicious_xor_used_as_pow::ConfusingXorAndPow));
     store.register_late_pass(move |_| Box::new(manual_is_ascii_check::ManualIsAsciiCheck::new(msrv())));
+    store.register_late_pass(|_| Box::new(semicolon_block::SemicolonBlock));
     // add lints here, do not remove this comment, it's used in `new_lint`
 }
 
index b6f4cf7bbb37f149eccda55bbc0ef40b2f08def9..28ee24309cc467e57c6f374f8b0d86a314134d57 100644 (file)
@@ -25,7 +25,6 @@ pub(super) struct IncrementVisitor<'a, 'tcx> {
     cx: &'a LateContext<'tcx>,                  // context reference
     states: HirIdMap<IncrementVisitorVarState>, // incremented variables
     depth: u32,                                 // depth of conditional expressions
-    done: bool,
 }
 
 impl<'a, 'tcx> IncrementVisitor<'a, 'tcx> {
@@ -34,7 +33,6 @@ pub(super) fn new(cx: &'a LateContext<'tcx>) -> Self {
             cx,
             states: HirIdMap::default(),
             depth: 0,
-            done: false,
         }
     }
 
@@ -51,10 +49,6 @@ pub(super) fn into_results(self) -> impl Iterator<Item = HirId> {
 
 impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> {
     fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
-        if self.done {
-            return;
-        }
-
         // If node is a variable
         if let Some(def_id) = path_to_local(expr) {
             if let Some(parent) = get_parent_expr(self.cx, expr) {
@@ -95,7 +89,9 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
             walk_expr(self, expr);
             self.depth -= 1;
         } else if let ExprKind::Continue(_) = expr.kind {
-            self.done = true;
+            // If we see a `continue` block, then we increment depth so that the IncrementVisitor
+            // state will be set to DontWarn if we see the variable being modified anywhere afterwards.
+            self.depth += 1;
         } else {
             walk_expr(self, expr);
         }
index b8ed9b9ec18f718b0cc56160b0966a9e0cf220a5..4277455a3a21c8e096e0c36e588724d065372d99 100644 (file)
@@ -2,7 +2,7 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::macros::{root_macro_call, FormatArgsExpn};
 use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{peel_blocks_with_stmt, span_extract_comment, sugg};
+use clippy_utils::{is_else_clause, peel_blocks_with_stmt, span_extract_comment, sugg};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
@@ -47,6 +47,10 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
             if cx.tcx.item_name(macro_call.def_id) == sym::panic;
             if !cx.tcx.sess.source_map().is_multiline(cond.span);
             if let Some(format_args) = FormatArgsExpn::find_nested(cx, then, macro_call.expn);
+            // Don't change `else if foo { panic!(..) }` to `else { assert!(foo, ..) }` as it just
+            // shuffles the condition around.
+            // Should this have a config value?
+            if !is_else_clause(cx.tcx, expr);
             then {
                 let mut applicability = Applicability::MachineApplicable;
                 let format_args_snip = snippet_with_applicability(cx, format_args.inputs_span(), "..", &mut applicability);
index 5ab049d8d133fd34629227da15fbfef84c255915..d9ef7dffa020dbbd6d24715a35129fa72f88bcf2 100644 (file)
@@ -1,11 +1,12 @@
 use clippy_utils::msrvs::{self, Msrv};
-use clippy_utils::{diagnostics::span_lint_and_sugg, in_constant, macros::root_macro_call, source::snippet};
+use clippy_utils::{diagnostics::span_lint_and_sugg, higher, in_constant, macros::root_macro_call, source::snippet};
+use rustc_ast::ast::RangeLimits;
 use rustc_ast::LitKind::{Byte, Char};
 use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind, PatKind, RangeEnd};
+use rustc_hir::{BorrowKind, Expr, ExprKind, PatKind, RangeEnd};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_span::{def_id::DefId, sym};
+use rustc_span::{def_id::DefId, sym, Span};
 
 declare_clippy_lint! {
     /// ### What it does
     ///     assert!(matches!(b'X', b'A'..=b'Z'));
     ///     assert!(matches!('2', '0'..='9'));
     ///     assert!(matches!('x', 'A'..='Z' | 'a'..='z'));
+    ///
+    ///     ('0'..='9').contains(&'0');
+    ///     ('a'..='z').contains(&'a');
+    ///     ('A'..='Z').contains(&'A');
     /// }
     /// ```
     /// Use instead:
     ///     assert!(b'X'.is_ascii_uppercase());
     ///     assert!('2'.is_ascii_digit());
     ///     assert!('x'.is_ascii_alphabetic());
+    ///
+    ///     '0'.is_ascii_digit();
+    ///     'a'.is_ascii_lowercase();
+    ///     'A'.is_ascii_uppercase();
     /// }
     /// ```
     #[clippy::version = "1.66.0"]
@@ -75,40 +84,21 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
             return;
         }
 
-        let Some(macro_call) = root_macro_call(expr.span) else { return };
-
-        if is_matches_macro(cx, macro_call.def_id) {
+        if let Some(macro_call) = root_macro_call(expr.span)
+            && is_matches_macro(cx, macro_call.def_id) {
             if let ExprKind::Match(recv, [arm, ..], _) = expr.kind {
                 let range = check_pat(&arm.pat.kind);
-
-                if let Some(sugg) = match range {
-                    CharRange::UpperChar => Some("is_ascii_uppercase"),
-                    CharRange::LowerChar => Some("is_ascii_lowercase"),
-                    CharRange::FullChar => Some("is_ascii_alphabetic"),
-                    CharRange::Digit => Some("is_ascii_digit"),
-                    CharRange::Otherwise => None,
-                } {
-                    let default_snip = "..";
-                    // `snippet_with_applicability` may set applicability to `MaybeIncorrect` for
-                    // macro span, so we check applicability manually by comparing `recv` is not default.
-                    let recv = snippet(cx, recv.span, default_snip);
-
-                    let applicability = if recv == default_snip {
-                        Applicability::HasPlaceholders
-                    } else {
-                        Applicability::MachineApplicable
-                    };
-
-                    span_lint_and_sugg(
-                        cx,
-                        MANUAL_IS_ASCII_CHECK,
-                        macro_call.span,
-                        "manual check for common ascii range",
-                        "try",
-                        format!("{recv}.{sugg}()"),
-                        applicability,
-                    );
-                }
+                check_is_ascii(cx, macro_call.span, recv, &range);
+            }
+        } else if let ExprKind::MethodCall(path, receiver, [arg], ..) = expr.kind
+            && path.ident.name == sym!(contains)
+            && let Some(higher::Range { start: Some(start), end: Some(end), limits: RangeLimits::Closed })
+            = higher::Range::hir(receiver) {
+            let range = check_range(start, end);
+            if let ExprKind::AddrOf(BorrowKind::Ref, _, e) = arg.kind {
+                check_is_ascii(cx, expr.span, e, &range);
+            } else {
+                check_is_ascii(cx, expr.span, arg, &range);
             }
         }
     }
@@ -116,6 +106,37 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
     extract_msrv_attr!(LateContext);
 }
 
+fn check_is_ascii(cx: &LateContext<'_>, span: Span, recv: &Expr<'_>, range: &CharRange) {
+    if let Some(sugg) = match range {
+        CharRange::UpperChar => Some("is_ascii_uppercase"),
+        CharRange::LowerChar => Some("is_ascii_lowercase"),
+        CharRange::FullChar => Some("is_ascii_alphabetic"),
+        CharRange::Digit => Some("is_ascii_digit"),
+        CharRange::Otherwise => None,
+    } {
+        let default_snip = "..";
+        // `snippet_with_applicability` may set applicability to `MaybeIncorrect` for
+        // macro span, so we check applicability manually by comparing `recv` is not default.
+        let recv = snippet(cx, recv.span, default_snip);
+
+        let applicability = if recv == default_snip {
+            Applicability::HasPlaceholders
+        } else {
+            Applicability::MachineApplicable
+        };
+
+        span_lint_and_sugg(
+            cx,
+            MANUAL_IS_ASCII_CHECK,
+            span,
+            "manual check for common ascii range",
+            "try",
+            format!("{recv}.{sugg}()"),
+            applicability,
+        );
+    }
+}
+
 fn check_pat(pat_kind: &PatKind<'_>) -> CharRange {
     match pat_kind {
         PatKind::Or(pats) => {
index 874d36ca9f4e378704019c8ae971c046c68d898c..9c6f8b43c078fbc77abd20dd5e7b374c47b6ffad 100644 (file)
@@ -151,7 +151,12 @@ fn emit_manual_let_else(cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, pat:
             } else {
                 format!("{{ {sn_else} }}")
             };
-            let sugg = format!("let {sn_pat} = {sn_expr} else {else_bl};");
+            let sn_bl = if matches!(pat.kind, PatKind::Or(..)) {
+                format!("({sn_pat})")
+            } else {
+                sn_pat.into_owned()
+            };
+            let sugg = format!("let {sn_bl} = {sn_expr} else {else_bl};");
             diag.span_suggestion(span, "consider writing", sugg, app);
         },
     );
index c1e6c82487dc54d79b5e86185541108c149af35e..72cdb9c17361676240c5d767cd34a67db9164dbd 100644 (file)
@@ -70,7 +70,8 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
             && seg.args.is_none()
             && 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) {
+            && cx.tcx.is_diagnostic_item(sym::iterator_collect_fn, collect_def_id)
+        {
             check_into_iter(cx, parent_expr, left_expr, target_expr, &self.msrv);
             check_iter(cx, parent_expr, left_expr, target_expr, &self.msrv);
             check_to_owned(cx, parent_expr, left_expr, target_expr, &self.msrv);
index 168c1e4d2e60d4d3da9e94412c674d8539a299a5..158e6caa4de5485ebcc7b30bd7eb806bc822f84b 100644 (file)
@@ -282,7 +282,7 @@ fn from_pat(cx: &LateContext<'_>, arena: &'a DroplessArena, pat: &'a Pat<'_>) ->
                 // TODO: Handle negative integers. They're currently treated as a wild match.
                 ExprKind::Lit(lit) => match lit.node {
                     LitKind::Str(sym, _) => Self::LitStr(sym),
-                    LitKind::ByteStr(ref bytes) => Self::LitBytes(bytes),
+                    LitKind::ByteStr(ref bytes, _) => Self::LitBytes(bytes),
                     LitKind::Byte(val) => Self::LitInt(val.into()),
                     LitKind::Char(val) => Self::LitInt(val.into()),
                     LitKind::Int(val, _) => Self::LitInt(val),
index 429cdc1918d79d7c03d1d5b24fe1bff04c8e7afb..06ecbce4e70e940bed5d941b41be29198817ef6c 100644 (file)
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_context;
-use clippy_utils::ty::peel_mid_ty_refs;
+use clippy_utils::ty::{implements_trait, peel_mid_ty_refs};
 use clippy_utils::{is_diag_item_method, is_diag_trait_item};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
@@ -19,6 +19,8 @@ pub fn check(cx: &LateContext<'_>, method_name: &str, expr: &hir::Expr<'_>, recv
         let (input_type, ref_count) = peel_mid_ty_refs(input_type);
         if let Some(ty_name) = input_type.ty_adt_def().map(|adt_def| cx.tcx.item_name(adt_def.did()));
         if return_type == input_type;
+        if let Some(clone_trait) = cx.tcx.lang_items().clone_trait();
+        if implements_trait(cx, return_type, clone_trait, &[]);
         then {
             let mut app = Applicability::MachineApplicable;
             let recv_snip = snippet_with_context(cx, recv.span, expr.span.ctxt(), "..", &mut app).0;
index d2913680cbb742a11db2439aa668aff4d0a979c0..561e4336593b047ed5f071e89c18f5ec6c82c69e 100644 (file)
     /// let map: HashMap<u32, u32> = HashMap::new();
     /// let values = map.values().collect::<Vec<_>>();
     /// ```
-    #[clippy::version = "1.65.0"]
+    #[clippy::version = "1.66.0"]
     pub ITER_KV_MAP,
     complexity,
     "iterating on map using `iter` when `keys` or `values` would do"
@@ -3672,7 +3672,10 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
                     no_effect_replace::check(cx, expr, arg1, arg2);
 
                     // Check for repeated `str::replace` calls to perform `collapsible_str_replace` lint
-                    if name == "replace" && let Some(("replace", ..)) = method_call(recv) {
+                    if self.msrv.meets(msrvs::PATTERN_TRAIT_CHAR_ARRAY)
+                        && name == "replace"
+                        && let Some(("replace", ..)) = method_call(recv)
+                    {
                         collapsible_str_replace::check(cx, expr, arg1, arg2);
                     }
                 },
index b088e642e0e9acd258e5e422ce1984d08b06d226..f4d3ef3b742509f40debe7616bb272b7f295f274 100644 (file)
@@ -151,7 +151,7 @@ fn iterates_same_ty<'tcx>(cx: &LateContext<'tcx>, iter_ty: Ty<'tcx>, collect_ty:
         && let Some(into_iter_item_proj) = make_projection(cx.tcx, into_iter_trait, item, [collect_ty])
         && let Ok(into_iter_item_ty) = cx.tcx.try_normalize_erasing_regions(
             cx.param_env,
-            cx.tcx.mk_projection(into_iter_item_proj.item_def_id, into_iter_item_proj.substs)
+            cx.tcx.mk_projection(into_iter_item_proj.def_id, into_iter_item_proj.substs)
         )
     {
         iter_item_ty == into_iter_item_ty
index 7e3bed1e41a9457d9ca485d17ac4c0b92cf52dc7..660b7049cce974df23d916d36959aae105e45139 100644 (file)
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::ty::implements_trait;
-use clippy_utils::{get_trait_def_id, match_def_path, paths};
+use clippy_utils::{get_trait_def_id, is_expr_used_or_unified, match_def_path, paths};
 use rustc_ast::ast::{LitIntType, LitKind};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
@@ -19,6 +19,10 @@ pub(super) fn check<'tcx>(
     // Get receiver type
     let ty = cx.typeck_results().expr_ty(recv).peel_refs();
 
+    if is_expr_used_or_unified(cx.tcx, expr) {
+        return;
+    }
+
     if let Some(seek_trait_id) = get_trait_def_id(cx, &paths::STD_IO_SEEK) &&
         implements_trait(cx, ty, seek_trait_id, &[]) &&
         let ExprKind::Call(func, args1) = arg.kind &&
index 17b0507682ae905b9e7fb438f76eef3022d317b8..9263f0519724bcaa58d30f45ef2c05d6569ec230 100644 (file)
@@ -386,14 +386,12 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
             Node::Expr(parent_expr) => {
                 if let Some((callee_def_id, call_substs, recv, call_args)) = get_callee_substs_and_args(cx, parent_expr)
                 {
-                    if Some(callee_def_id) == cx.tcx.lang_items().into_future_fn() {
-                        return false;
-                    }
-
                     let fn_sig = cx.tcx.fn_sig(callee_def_id).skip_binder();
                     if let Some(arg_index) = recv.into_iter().chain(call_args).position(|arg| arg.hir_id == expr.hir_id)
                         && let Some(param_ty) = fn_sig.inputs().get(arg_index)
                         && let ty::Param(ParamTy { index: param_index , ..}) = param_ty.kind()
+                        // https://github.com/rust-lang/rust-clippy/issues/9504 and https://github.com/rust-lang/rust-clippy/issues/10021
+                        && (*param_index as usize) < call_substs.len()
                     {
                         if fn_sig
                             .inputs()
index 516dee20f8b15f17266ca589927a2631361f7072..9f4beb92b9d2e77bc265e5f13eb3b050989fc77a 100644 (file)
@@ -9,12 +9,14 @@
 };
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::lint::in_external_macro;
-use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::hygiene::DesugaringKind;
 use rustc_span::source_map::{ExpnKind, Span};
 
 use clippy_utils::sugg::Sugg;
-use clippy_utils::{get_parent_expr, in_constant, is_integer_literal, iter_input_pats, last_path_segment, SpanlessEq};
+use clippy_utils::{
+    get_parent_expr, in_constant, is_integer_literal, is_no_std_crate, iter_input_pats, last_path_segment, SpanlessEq,
+};
 
 declare_clippy_lint! {
     /// ### What it does
     "using `0 as *{const, mut} T`"
 }
 
-declare_lint_pass!(MiscLints => [
+pub struct LintPass {
+    std_or_core: &'static str,
+}
+impl Default for LintPass {
+    fn default() -> Self {
+        Self { std_or_core: "std" }
+    }
+}
+impl_lint_pass!(LintPass => [
     TOPLEVEL_REF_ARG,
     USED_UNDERSCORE_BINDING,
     SHORT_CIRCUIT_STATEMENT,
     ZERO_PTR,
 ]);
 
-impl<'tcx> LateLintPass<'tcx> for MiscLints {
+impl<'tcx> LateLintPass<'tcx> for LintPass {
+    fn check_crate(&mut self, cx: &LateContext<'_>) {
+        if is_no_std_crate(cx) {
+            self.std_or_core = "core";
+        }
+    }
+
     fn check_fn(
         &mut self,
         cx: &LateContext<'tcx>,
@@ -231,7 +247,7 @@ fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
 
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         if let ExprKind::Cast(e, ty) = expr.kind {
-            check_cast(cx, expr.span, e, ty);
+            self.check_cast(cx, expr.span, e, ty);
             return;
         }
         if in_attributes_expansion(expr) || expr.span.is_desugaring(DesugaringKind::Await) {
@@ -310,26 +326,28 @@ fn non_macro_local(cx: &LateContext<'_>, res: def::Res) -> bool {
     }
 }
 
-fn check_cast(cx: &LateContext<'_>, span: Span, e: &Expr<'_>, ty: &hir::Ty<'_>) {
-    if_chain! {
-        if let TyKind::Ptr(ref mut_ty) = ty.kind;
-        if is_integer_literal(e, 0);
-        if !in_constant(cx, e.hir_id);
-        then {
-            let (msg, sugg_fn) = match mut_ty.mutbl {
-                Mutability::Mut => ("`0 as *mut _` detected", "std::ptr::null_mut"),
-                Mutability::Not => ("`0 as *const _` detected", "std::ptr::null"),
-            };
+impl LintPass {
+    fn check_cast(&self, cx: &LateContext<'_>, span: Span, e: &Expr<'_>, ty: &hir::Ty<'_>) {
+        if_chain! {
+            if let TyKind::Ptr(ref mut_ty) = ty.kind;
+            if is_integer_literal(e, 0);
+            if !in_constant(cx, e.hir_id);
+            then {
+                let (msg, sugg_fn) = match mut_ty.mutbl {
+                    Mutability::Mut => ("`0 as *mut _` detected", "ptr::null_mut"),
+                    Mutability::Not => ("`0 as *const _` detected", "ptr::null"),
+                };
 
-            let (sugg, appl) = if let TyKind::Infer = mut_ty.ty.kind {
-                (format!("{sugg_fn}()"), Applicability::MachineApplicable)
-            } else if let Some(mut_ty_snip) = snippet_opt(cx, mut_ty.ty.span) {
-                (format!("{sugg_fn}::<{mut_ty_snip}>()"), Applicability::MachineApplicable)
-            } else {
-                // `MaybeIncorrect` as type inference may not work with the suggested code
-                (format!("{sugg_fn}()"), Applicability::MaybeIncorrect)
-            };
-            span_lint_and_sugg(cx, ZERO_PTR, span, msg, "try", sugg, appl);
+                let (sugg, appl) = if let TyKind::Infer = mut_ty.ty.kind {
+                    (format!("{}::{sugg_fn}()", self.std_or_core), Applicability::MachineApplicable)
+                } else if let Some(mut_ty_snip) = snippet_opt(cx, mut_ty.ty.span) {
+                    (format!("{}::{sugg_fn}::<{mut_ty_snip}>()", self.std_or_core), Applicability::MachineApplicable)
+                } else {
+                    // `MaybeIncorrect` as type inference may not work with the suggested code
+                    (format!("{}::{sugg_fn}()", self.std_or_core), Applicability::MaybeIncorrect)
+                };
+                span_lint_and_sugg(cx, ZERO_PTR, span, msg, "try", sugg, appl);
+            }
         }
     }
 }
index 20b82d81a2aeb64e57d11994ceb3755a96e4cde4..4fbc8398e373443d5cc80c80eb2214933bfe786d 100644 (file)
@@ -5,25 +5,26 @@
     peel_hir_expr_refs,
 };
 use rustc_ast as ast;
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::Ty;
 use rustc_session::impl_lint_pass;
 use rustc_span::source_map::{Span, Spanned};
 
-const HARD_CODED_ALLOWED: &[&str] = &[
-    "&str",
-    "f32",
-    "f64",
-    "std::num::Saturating",
-    "std::num::Wrapping",
-    "std::string::String",
+const HARD_CODED_ALLOWED_BINARY: &[[&str; 2]] = &[
+    ["f32", "f32"],
+    ["f64", "f64"],
+    ["std::num::Saturating", "std::num::Saturating"],
+    ["std::num::Wrapping", "std::num::Wrapping"],
+    ["std::string::String", "&str"],
 ];
+const HARD_CODED_ALLOWED_UNARY: &[&str] = &["f32", "f64", "std::num::Saturating", "std::num::Wrapping"];
 
 #[derive(Debug)]
 pub struct ArithmeticSideEffects {
-    allowed: FxHashSet<String>,
+    allowed_binary: FxHashMap<String, FxHashSet<String>>,
+    allowed_unary: FxHashSet<String>,
     // Used to check whether expressions are constants, such as in enum discriminants and consts
     const_span: Option<Span>,
     expr_span: Option<Span>,
@@ -33,19 +34,55 @@ pub struct ArithmeticSideEffects {
 
 impl ArithmeticSideEffects {
     #[must_use]
-    pub fn new(mut allowed: FxHashSet<String>) -> Self {
-        allowed.extend(HARD_CODED_ALLOWED.iter().copied().map(String::from));
+    pub fn new(user_allowed_binary: Vec<[String; 2]>, user_allowed_unary: Vec<String>) -> Self {
+        let mut allowed_binary: FxHashMap<String, FxHashSet<String>> = <_>::default();
+        for [lhs, rhs] in user_allowed_binary.into_iter().chain(
+            HARD_CODED_ALLOWED_BINARY
+                .iter()
+                .copied()
+                .map(|[lhs, rhs]| [lhs.to_string(), rhs.to_string()]),
+        ) {
+            allowed_binary.entry(lhs).or_default().insert(rhs);
+        }
+        let allowed_unary = user_allowed_unary
+            .into_iter()
+            .chain(HARD_CODED_ALLOWED_UNARY.iter().copied().map(String::from))
+            .collect();
         Self {
-            allowed,
+            allowed_binary,
+            allowed_unary,
             const_span: None,
             expr_span: None,
         }
     }
 
-    /// Checks if the given `expr` has any of the inner `allowed` elements.
-    fn is_allowed_ty(&self, ty: Ty<'_>) -> bool {
-        self.allowed
-            .contains(ty.to_string().split('<').next().unwrap_or_default())
+    /// Checks if the lhs and the rhs types of a binary operation like "addition" or
+    /// "multiplication" are present in the inner set of allowed types.
+    fn has_allowed_binary(&self, lhs_ty: Ty<'_>, rhs_ty: Ty<'_>) -> bool {
+        let lhs_ty_string = lhs_ty.to_string();
+        let lhs_ty_string_elem = lhs_ty_string.split('<').next().unwrap_or_default();
+        let rhs_ty_string = rhs_ty.to_string();
+        let rhs_ty_string_elem = rhs_ty_string.split('<').next().unwrap_or_default();
+        if let Some(rhs_from_specific) = self.allowed_binary.get(lhs_ty_string_elem)
+            && {
+                let rhs_has_allowed_ty = rhs_from_specific.contains(rhs_ty_string_elem);
+                rhs_has_allowed_ty || rhs_from_specific.contains("*")
+            }
+        {
+           true
+        } else if let Some(rhs_from_glob) = self.allowed_binary.get("*") {
+            rhs_from_glob.contains(rhs_ty_string_elem)
+        } else {
+            false
+        }
+    }
+
+    /// Checks if the type of an unary operation like "negation" is present in the inner set of
+    /// allowed types.
+    fn has_allowed_unary(&self, ty: Ty<'_>) -> bool {
+        let ty_string = ty.to_string();
+        let ty_string_elem = ty_string.split('<').next().unwrap_or_default();
+        self.allowed_unary.contains(ty_string_elem)
     }
 
     // For example, 8i32 or &i64::MAX.
@@ -97,8 +134,7 @@ fn manage_bin_ops<'tcx>(
         };
         let lhs_ty = cx.typeck_results().expr_ty(lhs);
         let rhs_ty = cx.typeck_results().expr_ty(rhs);
-        let lhs_and_rhs_have_the_same_ty = lhs_ty == rhs_ty;
-        if lhs_and_rhs_have_the_same_ty && self.is_allowed_ty(lhs_ty) && self.is_allowed_ty(rhs_ty) {
+        if self.has_allowed_binary(lhs_ty, rhs_ty) {
             return;
         }
         let has_valid_op = if Self::is_integral(lhs_ty) && Self::is_integral(rhs_ty) {
@@ -137,7 +173,7 @@ fn manage_unary_ops<'tcx>(
             return;
         }
         let ty = cx.typeck_results().expr_ty(expr).peel_refs();
-        if self.is_allowed_ty(ty) {
+        if self.has_allowed_unary(ty) {
             return;
         }
         let actual_un_expr = peel_hir_expr_refs(un_expr).0;
index b48d6c4e2e2af96318e38bdcb81ce5b2f3a548e9..14a12da862efeb68d4f151077dac7859d2ecb9db 100644 (file)
@@ -1,7 +1,7 @@
 use clippy_utils::consts::{constant_full_int, constant_simple, Constant, FullInt};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{clip, unsext};
+use clippy_utils::{clip, peel_hir_expr_refs, unsext};
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Expr, ExprKind, Node};
 use rustc_lint::LateContext;
@@ -20,20 +20,76 @@ pub(crate) fn check<'tcx>(
     if !is_allowed(cx, op, left, right) {
         match op {
             BinOpKind::Add | BinOpKind::BitOr | BinOpKind::BitXor => {
-                check_op(cx, left, 0, expr.span, right.span, needs_parenthesis(cx, expr, right));
-                check_op(cx, right, 0, expr.span, left.span, Parens::Unneeded);
+                check_op(
+                    cx,
+                    left,
+                    0,
+                    expr.span,
+                    peel_hir_expr_refs(right).0.span,
+                    needs_parenthesis(cx, expr, right),
+                );
+                check_op(
+                    cx,
+                    right,
+                    0,
+                    expr.span,
+                    peel_hir_expr_refs(left).0.span,
+                    Parens::Unneeded,
+                );
             },
             BinOpKind::Shl | BinOpKind::Shr | BinOpKind::Sub => {
-                check_op(cx, right, 0, expr.span, left.span, Parens::Unneeded);
+                check_op(
+                    cx,
+                    right,
+                    0,
+                    expr.span,
+                    peel_hir_expr_refs(left).0.span,
+                    Parens::Unneeded,
+                );
             },
             BinOpKind::Mul => {
-                check_op(cx, left, 1, expr.span, right.span, needs_parenthesis(cx, expr, right));
-                check_op(cx, right, 1, expr.span, left.span, Parens::Unneeded);
+                check_op(
+                    cx,
+                    left,
+                    1,
+                    expr.span,
+                    peel_hir_expr_refs(right).0.span,
+                    needs_parenthesis(cx, expr, right),
+                );
+                check_op(
+                    cx,
+                    right,
+                    1,
+                    expr.span,
+                    peel_hir_expr_refs(left).0.span,
+                    Parens::Unneeded,
+                );
             },
-            BinOpKind::Div => check_op(cx, right, 1, expr.span, left.span, Parens::Unneeded),
+            BinOpKind::Div => check_op(
+                cx,
+                right,
+                1,
+                expr.span,
+                peel_hir_expr_refs(left).0.span,
+                Parens::Unneeded,
+            ),
             BinOpKind::BitAnd => {
-                check_op(cx, left, -1, expr.span, right.span, needs_parenthesis(cx, expr, right));
-                check_op(cx, right, -1, expr.span, left.span, Parens::Unneeded);
+                check_op(
+                    cx,
+                    left,
+                    -1,
+                    expr.span,
+                    peel_hir_expr_refs(right).0.span,
+                    needs_parenthesis(cx, expr, right),
+                );
+                check_op(
+                    cx,
+                    right,
+                    -1,
+                    expr.span,
+                    peel_hir_expr_refs(left).0.span,
+                    Parens::Unneeded,
+                );
             },
             BinOpKind::Rem => check_remainder(cx, left, right, expr.span, left.span),
             _ => (),
index b8a20d5ebe9bd689e7d996fea0dff6e86d9dcdd4..eba230da6c39b772bb90e600f07d9f2df3fcc9b5 100644 (file)
@@ -90,9 +90,6 @@
     /// use rust_decimal::Decimal;
     /// let _n = Decimal::MAX + Decimal::MAX;
     /// ```
-    ///
-    /// ### Allowed types
-    /// Custom allowed types can be specified through the "arithmetic-side-effects-allowed" filter.
     #[clippy::version = "1.64.0"]
     pub ARITHMETIC_SIDE_EFFECTS,
     restriction,
index d612d249c2f000ab3c869952f1806ff491ac2450..c2a8db7df038b9355ca6abf1e9833436688ce033 100644 (file)
@@ -84,7 +84,11 @@ fn check_item_post(&mut self, _cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
 
 fn is_not_macro_export<'tcx>(item: &'tcx Item<'tcx>) -> bool {
     if let ItemKind::Use(path, _) = item.kind {
-        if path.res.iter().all(|res| matches!(res, Res::Def(DefKind::Macro(MacroKind::Bang), _))) {
+        if path
+            .res
+            .iter()
+            .all(|res| matches!(res, Res::Def(DefKind::Macro(MacroKind::Bang), _)))
+        {
             return false;
         }
     } else if let ItemKind::Macro(..) = item.kind {
index 3aa2490bc44e018fa32371b1f94e0c69a46e4892..41f991a967bfd9929b025657ef21c8fc0aa573ca 100644 (file)
@@ -66,7 +66,7 @@ fn visit_type(ty: &Ty, cx: &EarlyContext<'_>, reason: &str) {
                         TyKind::Path(..) | TyKind::Slice(..) | TyKind::Array(..) | TyKind::Tup(..) => {
                             if lifetime.ident.name == rustc_span::symbol::kw::StaticLifetime {
                                 let snip = snippet(cx, borrow_type.ty.span, "<type>");
-                                let sugg = format!("&{snip}");
+                                let sugg = format!("&{}{snip}", borrow_type.mutbl.prefix_str());
                                 span_lint_and_then(
                                     cx,
                                     REDUNDANT_STATIC_LIFETIMES,
index 8e214218f23ae1d5f617147d4e9ca2ff42cb37af..72c25592609ba77191f7877134b6c8bff1df90d8 100644 (file)
@@ -2,6 +2,7 @@
 
 #[rustfmt::skip]
 pub static RENAMED_LINTS: &[(&str, &str)] = &[
+    ("clippy::almost_complete_letter_range", "clippy::almost_complete_range"),
     ("clippy::blacklisted_name", "clippy::disallowed_names"),
     ("clippy::block_in_if_condition_expr", "clippy::blocks_in_if_conditions"),
     ("clippy::block_in_if_condition_stmt", "clippy::blocks_in_if_conditions"),
diff --git a/src/tools/clippy/clippy_lints/src/semicolon_block.rs b/src/tools/clippy/clippy_lints/src/semicolon_block.rs
new file mode 100644 (file)
index 0000000..8f1d149
--- /dev/null
@@ -0,0 +1,137 @@
+use clippy_utils::diagnostics::{multispan_sugg_with_applicability, span_lint_and_then};
+use rustc_errors::Applicability;
+use rustc_hir::{Block, Expr, ExprKind, Stmt, StmtKind};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::Span;
+
+declare_clippy_lint! {
+    /// ### What it does
+    ///
+    /// Suggests moving the semicolon after a block to the inside of the block, after its last
+    /// expression.
+    ///
+    /// ### Why is this bad?
+    ///
+    /// For consistency it's best to have the semicolon inside/outside the block. Either way is fine
+    /// and this lint suggests inside the block.
+    /// Take a look at `semicolon_outside_block` for the other alternative.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// # fn f(_: u32) {}
+    /// # let x = 0;
+    /// unsafe { f(x) };
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// # fn f(_: u32) {}
+    /// # let x = 0;
+    /// unsafe { f(x); }
+    /// ```
+    #[clippy::version = "1.66.0"]
+    pub SEMICOLON_INSIDE_BLOCK,
+    restriction,
+    "add a semicolon inside the block"
+}
+declare_clippy_lint! {
+    /// ### What it does
+    ///
+    /// Suggests moving the semicolon from a block's final expression outside of the block.
+    ///
+    /// ### Why is this bad?
+    ///
+    /// For consistency it's best to have the semicolon inside/outside the block. Either way is fine
+    /// and this lint suggests outside the block.
+    /// Take a look at `semicolon_inside_block` for the other alternative.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// # fn f(_: u32) {}
+    /// # let x = 0;
+    /// unsafe { f(x); }
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// # fn f(_: u32) {}
+    /// # let x = 0;
+    /// unsafe { f(x) };
+    /// ```
+    #[clippy::version = "1.66.0"]
+    pub SEMICOLON_OUTSIDE_BLOCK,
+    restriction,
+    "add a semicolon outside the block"
+}
+declare_lint_pass!(SemicolonBlock => [SEMICOLON_INSIDE_BLOCK, SEMICOLON_OUTSIDE_BLOCK]);
+
+impl LateLintPass<'_> for SemicolonBlock {
+    fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &Stmt<'_>) {
+        match stmt.kind {
+            StmtKind::Expr(Expr {
+                kind: ExprKind::Block(block, _),
+                ..
+            }) if !block.span.from_expansion() => {
+                let Block {
+                    expr: None,
+                    stmts: [.., stmt],
+                    ..
+                } = block else { return };
+                let &Stmt {
+                    kind: StmtKind::Semi(expr),
+                    span,
+                    ..
+                } = stmt else { return };
+                semicolon_outside_block(cx, block, expr, span);
+            },
+            StmtKind::Semi(Expr {
+                kind: ExprKind::Block(block @ Block { expr: Some(tail), .. }, _),
+                ..
+            }) if !block.span.from_expansion() => semicolon_inside_block(cx, block, tail, stmt.span),
+            _ => (),
+        }
+    }
+}
+
+fn semicolon_inside_block(cx: &LateContext<'_>, block: &Block<'_>, tail: &Expr<'_>, semi_span: Span) {
+    let insert_span = tail.span.source_callsite().shrink_to_hi();
+    let remove_span = semi_span.with_lo(block.span.hi());
+
+    span_lint_and_then(
+        cx,
+        SEMICOLON_INSIDE_BLOCK,
+        semi_span,
+        "consider moving the `;` inside the block for consistent formatting",
+        |diag| {
+            multispan_sugg_with_applicability(
+                diag,
+                "put the `;` here",
+                Applicability::MachineApplicable,
+                [(remove_span, String::new()), (insert_span, ";".to_owned())],
+            );
+        },
+    );
+}
+
+fn semicolon_outside_block(cx: &LateContext<'_>, block: &Block<'_>, tail_stmt_expr: &Expr<'_>, semi_span: Span) {
+    let insert_span = block.span.with_lo(block.span.hi());
+    // account for macro calls
+    let semi_span = cx.sess().source_map().stmt_span(semi_span, block.span);
+    let remove_span = semi_span.with_lo(tail_stmt_expr.span.source_callsite().hi());
+
+    span_lint_and_then(
+        cx,
+        SEMICOLON_OUTSIDE_BLOCK,
+        block.span,
+        "consider moving the `;` outside the block for consistent formatting",
+        |diag| {
+            multispan_sugg_with_applicability(
+                diag,
+                "put the `;` here",
+                Applicability::MachineApplicable,
+                [(remove_span, String::new()), (insert_span, ";".to_owned())],
+            );
+        },
+    );
+}
index f4705481d4e69b3131ad73ce0439ba6903092dca..bc18cad6d381b0cb165d46e6bd000b7c8305d637 100644 (file)
@@ -1,12 +1,12 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg};
 use clippy_utils::source::{snippet, snippet_with_applicability};
 use clippy_utils::ty::is_type_lang_item;
+use clippy_utils::{get_expr_use_or_unification_node, peel_blocks, SpanlessEq};
 use clippy_utils::{get_parent_expr, is_lint_allowed, match_function_call, method_calls, paths};
-use clippy_utils::{peel_blocks, SpanlessEq};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::def_id::DefId;
-use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, LangItem, QPath};
+use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, LangItem, Node, QPath};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty;
@@ -249,6 +249,7 @@ fn is_add(cx: &LateContext<'_>, src: &Expr<'_>, target: &Expr<'_>) -> bool {
 declare_lint_pass!(StringLitAsBytes => [STRING_LIT_AS_BYTES, STRING_FROM_UTF8_AS_BYTES]);
 
 impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes {
+    #[expect(clippy::too_many_lines)]
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
         use rustc_ast::LitKind;
 
@@ -316,18 +317,27 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
                     && lit_content.as_str().len() <= MAX_LENGTH_BYTE_STRING_LIT
                     && !receiver.span.from_expansion()
                 {
-                    span_lint_and_sugg(
-                        cx,
-                        STRING_LIT_AS_BYTES,
-                        e.span,
-                        "calling `as_bytes()` on a string literal",
-                        "consider using a byte string literal instead",
-                        format!(
-                            "b{}",
-                            snippet_with_applicability(cx, receiver.span, r#""foo""#, &mut applicability)
-                        ),
-                        applicability,
-                    );
+                    if let Some((parent, id)) = get_expr_use_or_unification_node(cx.tcx, e)
+                        && let Node::Expr(parent) = parent
+                        && let ExprKind::Match(scrutinee, ..) = parent.kind
+                        && scrutinee.hir_id == id
+                    {
+                        // Don't lint. Byte strings produce `&[u8; N]` whereas `as_bytes()` produces
+                        // `&[u8]`. This change would prevent matching with different sized slices.
+                    } else {
+                        span_lint_and_sugg(
+                            cx,
+                            STRING_LIT_AS_BYTES,
+                            e.span,
+                            "calling `as_bytes()` on a string literal",
+                            "consider using a byte string literal instead",
+                            format!(
+                                "b{}",
+                                snippet_with_applicability(cx, receiver.span, r#""foo""#, &mut applicability)
+                            ),
+                            applicability,
+                        );
+                    }
                 }
             }
         }
index 0c052d86eda409dc1eb4fa3103f8e6b4ea4fdbae..bd7daf0773caf914b7d3bd4b34b9ba88e4f5cba6 100644 (file)
@@ -299,7 +299,7 @@ macro_rules! kind {
                 };
                 kind!("Float(_, {float_ty})");
             },
-            LitKind::ByteStr(ref vec) => {
+            LitKind::ByteStr(ref vec, _) => {
                 bind!(self, vec);
                 kind!("ByteStr(ref {vec})");
                 chain!(self, "let [{:?}] = **{vec}", vec.value);
index b6dc8cd7ab1197e338e653a2fa3e1d5f20442877..3e7d0028c0fbd97df2a73e40300db80ac39606fe 100644 (file)
@@ -205,10 +205,49 @@ pub(crate) fn get_configuration_metadata() -> Vec<ClippyConfiguration> {
 }
 
 define_Conf! {
-    /// Lint: Arithmetic.
+    /// Lint: ARITHMETIC_SIDE_EFFECTS.
     ///
-    /// Suppress checking of the passed type names.
+    /// Suppress checking of the passed type names in all types of operations.
+    ///
+    /// If a specific operation is desired, consider using `arithmetic_side_effects_allowed_binary` or `arithmetic_side_effects_allowed_unary` instead.
+    ///
+    /// #### Example
+    ///
+    /// ```toml
+    /// arithmetic-side-effects-allowed = ["SomeType", "AnotherType"]
+    /// ```
+    ///
+    /// #### Noteworthy
+    ///
+    /// A type, say `SomeType`, listed in this configuration has the same behavior of `["SomeType" , "*"], ["*", "SomeType"]` in `arithmetic_side_effects_allowed_binary`.
     (arithmetic_side_effects_allowed: rustc_data_structures::fx::FxHashSet<String> = <_>::default()),
+    /// Lint: ARITHMETIC_SIDE_EFFECTS.
+    ///
+    /// Suppress checking of the passed type pair names in binary operations like addition or
+    /// multiplication.
+    ///
+    /// Supports the "*" wildcard to indicate that a certain type won't trigger the lint regardless
+    /// of the involved counterpart. For example, `["SomeType", "*"]` or `["*", "AnotherType"]`.
+    ///
+    /// Pairs are asymmetric, which means that `["SomeType", "AnotherType"]` is not the same as
+    /// `["AnotherType", "SomeType"]`.
+    ///
+    /// #### Example
+    ///
+    /// ```toml
+    /// arithmetic-side-effects-allowed-binary = [["SomeType" , "f32"], ["AnotherType", "*"]]
+    /// ```
+    (arithmetic_side_effects_allowed_binary: Vec<[String; 2]> = <_>::default()),
+    /// Lint: ARITHMETIC_SIDE_EFFECTS.
+    ///
+    /// Suppress checking of the passed type names in unary operations like "negation" (`-`).
+    ///
+    /// #### Example
+    ///
+    /// ```toml
+    /// arithmetic-side-effects-allowed-unary = ["SomeType", "AnotherType"]
+    /// ```
+    (arithmetic_side_effects_allowed_unary: rustc_data_structures::fx::FxHashSet<String> = <_>::default()),
     /// Lint: ENUM_VARIANT_NAMES, LARGE_TYPES_PASSED_BY_VALUE, TRIVIALLY_COPY_PASS_BY_REF, UNNECESSARY_WRAPS, UNUSED_SELF, UPPER_CASE_ACRONYMS, WRONG_SELF_CONVENTION, BOX_COLLECTION, REDUNDANT_ALLOCATION, RC_BUFFER, VEC_BOX, OPTION_OPTION, LINKEDLIST, RC_MUTEX.
     ///
     /// Suppress lints whenever the suggested change would cause breakage for other crates.
@@ -406,6 +445,14 @@ pub(crate) fn get_configuration_metadata() -> Vec<ClippyConfiguration> {
     ///
     /// Whether to allow mixed uninlined format args, e.g. `format!("{} {}", a, foo.bar)`
     (allow_mixed_uninlined_format_args: bool = true),
+    /// Lint: INDEXING_SLICING
+    ///
+    /// Whether to suppress a restriction lint in constant code. In same
+    /// cases the restructured operation might not be unavoidable, as the
+    /// suggested counterparts are unavailable in constant code. This
+    /// configuration will cause restriction lints to trigger even
+    /// if no suggestion can be made.
+    (suppress_restriction_lint_in_const: bool = false),
 }
 
 /// Search for the configuration file.
index 680935f2329e4e5037ffdf2c1f01022c962f3702..9afe02c1e47da00cadc26e240f6e4d34d6fe99ae 100644 (file)
@@ -7,7 +7,7 @@
 use rustc_hir::Item;
 use rustc_hir_analysis::hir_ty_to_ty;
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::{self, fast_reject::SimplifiedTypeGen, FloatTy};
+use rustc_middle::ty::{self, fast_reject::SimplifiedType, FloatTy};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::symbol::Symbol;
 
@@ -73,10 +73,10 @@ pub fn check_path(cx: &LateContext<'_>, path: &[&str]) -> bool {
     let lang_items = cx.tcx.lang_items();
     // This list isn't complete, but good enough for our current list of paths.
     let incoherent_impls = [
-        SimplifiedTypeGen::FloatSimplifiedType(FloatTy::F32),
-        SimplifiedTypeGen::FloatSimplifiedType(FloatTy::F64),
-        SimplifiedTypeGen::SliceSimplifiedType,
-        SimplifiedTypeGen::StrSimplifiedType,
+        SimplifiedType::FloatSimplifiedType(FloatTy::F32),
+        SimplifiedType::FloatSimplifiedType(FloatTy::F64),
+        SimplifiedType::SliceSimplifiedType,
+        SimplifiedType::StrSimplifiedType,
     ]
     .iter()
     .flat_map(|&ty| cx.tcx.incoherent_impls(ty).iter().copied());
index fb9f4740ecc5003922077019e7c3c12e4d634e77..ac6a566b9cd3ae5f208e9c4758a71c79f5867b50 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name = "clippy_utils"
-version = "0.1.67"
+version = "0.1.68"
 edition = "2021"
 publish = false
 
index c6bf98b7b8bbd35fbf2b1c12994d94e2a7de6b59..43f0df145f0ec606a4393b7ea73db736b376195d 100644 (file)
@@ -69,7 +69,9 @@ fn lit_search_pat(lit: &LitKind) -> (Pat, Pat) {
         LitKind::Str(_, StrStyle::Cooked) => (Pat::Str("\""), Pat::Str("\"")),
         LitKind::Str(_, StrStyle::Raw(0)) => (Pat::Str("r"), Pat::Str("\"")),
         LitKind::Str(_, StrStyle::Raw(_)) => (Pat::Str("r#"), Pat::Str("#")),
-        LitKind::ByteStr(_) => (Pat::Str("b\""), Pat::Str("\"")),
+        LitKind::ByteStr(_, StrStyle::Cooked) => (Pat::Str("b\""), Pat::Str("\"")),
+        LitKind::ByteStr(_, StrStyle::Raw(0)) => (Pat::Str("br\""), Pat::Str("\"")),
+        LitKind::ByteStr(_, StrStyle::Raw(_)) => (Pat::Str("br#\""), Pat::Str("#")),
         LitKind::Byte(_) => (Pat::Str("b'"), Pat::Str("'")),
         LitKind::Char(_) => (Pat::Str("'"), Pat::Str("'")),
         LitKind::Int(_, LitIntType::Signed(IntTy::Isize)) => (Pat::Num, Pat::Str("isize")),
index 315aea9aa091bc3b4f8f8f3d3e83fb0cc3c83b2f..7a637d32babecab6656bd5705f5dbf1873449f60 100644 (file)
@@ -210,7 +210,7 @@ pub fn lit_to_mir_constant(lit: &LitKind, ty: Option<Ty<'_>>) -> Constant {
     match *lit {
         LitKind::Str(ref is, _) => Constant::Str(is.to_string()),
         LitKind::Byte(b) => Constant::Int(u128::from(b)),
-        LitKind::ByteStr(ref s) => Constant::Binary(Lrc::clone(s)),
+        LitKind::ByteStr(ref s, _) => Constant::Binary(Lrc::clone(s)),
         LitKind::Char(c) => Constant::Char(c),
         LitKind::Int(n, _) => Constant::Int(n),
         LitKind::Float(ref is, LitFloatType::Suffixed(fty)) => match fty {
index 90192f46cbfa09f416e88c94060d3962f5c9cfef..43e2d1ec826c2343b9d6dea43c11ae3fe3789917 100644 (file)
@@ -97,7 +97,7 @@
 use rustc_middle::ty as rustc_ty;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
 use rustc_middle::ty::binding::BindingMode;
-use rustc_middle::ty::fast_reject::SimplifiedTypeGen::{
+use rustc_middle::ty::fast_reject::SimplifiedType::{
     ArraySimplifiedType, BoolSimplifiedType, CharSimplifiedType, FloatSimplifiedType, IntSimplifiedType,
     PtrSimplifiedType, SliceSimplifiedType, StrSimplifiedType, UintSimplifiedType,
 };
@@ -196,7 +196,7 @@ pub fn in_constant(cx: &LateContext<'_>, id: HirId) -> bool {
     let parent_id = cx.tcx.hir().get_parent_item(id).def_id;
     match cx.tcx.hir().get_by_def_id(parent_id) {
         Node::Item(&Item {
-            kind: ItemKind::Const(..) | ItemKind::Static(..),
+            kind: ItemKind::Const(..) | ItemKind::Static(..) | ItemKind::Enum(..),
             ..
         })
         | Node::TraitItem(&TraitItem {
index d13b34a66cca783ea01a70426ca6316af8684471..77c5f1155423c4a7a4399694988e3b56442bae5a 100644 (file)
@@ -208,6 +208,12 @@ pub fn is_panic(cx: &LateContext<'_>, def_id: DefId) -> bool {
     )
 }
 
+/// Is `def_id` of `assert!` or `debug_assert!`
+pub fn is_assert_macro(cx: &LateContext<'_>, def_id: DefId) -> bool {
+    let Some(name) = cx.tcx.get_diagnostic_name(def_id) else { return false };
+    matches!(name, sym::assert_macro | sym::debug_assert_macro)
+}
+
 pub enum PanicExpn<'a> {
     /// No arguments - `panic!()`
     Empty,
index 12a512f78a699eb30c92ac178b17663db424d090..ba5bc9c3135daa8ca34a9eddf552dafb332af796 100644 (file)
@@ -21,7 +21,7 @@ macro_rules! msrv_aliases {
 msrv_aliases! {
     1,65,0 { LET_ELSE }
     1,62,0 { BOOL_THEN_SOME }
-    1,58,0 { FORMAT_ARGS_CAPTURE }
+    1,58,0 { FORMAT_ARGS_CAPTURE, PATTERN_TRAIT_CHAR_ARRAY }
     1,53,0 { OR_PATTERNS, MANUAL_BITS, BTREE_MAP_RETAIN, BTREE_SET_RETAIN, ARRAY_INTO_ITERATOR }
     1,52,0 { STR_SPLIT_ONCE, REM_EUCLID_CONST }
     1,51,0 { BORROW_AS_PTR, SEEK_FROM_CURRENT, UNSIGNED_ABS }
index 6417f0f3c71348bb6761918cb08c7c373e7b9bc6..9ca50105ae57d0e93c96f7b48d1030bb10011c85 100644 (file)
@@ -20,7 +20,6 @@
 pub const BTREEMAP_INSERT: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "insert"];
 pub const BTREESET_ITER: [&str; 6] = ["alloc", "collections", "btree", "set", "BTreeSet", "iter"];
 pub const CLONE_TRAIT_METHOD: [&str; 4] = ["core", "clone", "Clone", "clone"];
-pub const CORE_ITER_COLLECT: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "collect"];
 pub const CORE_ITER_CLONED: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "cloned"];
 pub const CORE_ITER_COPIED: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "copied"];
 pub const CORE_ITER_FILTER: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "filter"];
index 480e8e55cf39cc8c66b0edf209a7f609c0071ccb..e5d7da682813c16d4883f2985d0963c03eb03a7c 100644 (file)
@@ -82,7 +82,7 @@ fn check_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) -> McfResult {
             ty::Ref(_, _, hir::Mutability::Mut) => {
                 return Err((span, "mutable references in const fn are unstable".into()));
             },
-            ty::Opaque(..) => return Err((span, "`impl Trait` in const fn is unstable".into())),
+            ty::Alias(ty::Opaque, ..) => return Err((span, "`impl Trait` in const fn is unstable".into())),
             ty::FnPtr(..) => {
                 return Err((span, "function pointers in const fn are unstable".into()));
             },
@@ -301,11 +301,7 @@ fn check_terminator<'tcx>(
             check_operand(tcx, value, span, body)
         },
 
-        TerminatorKind::SwitchInt {
-            discr,
-            switch_ty: _,
-            targets: _,
-        } => check_operand(tcx, discr, span, body),
+        TerminatorKind::SwitchInt { discr, targets: _ } => check_operand(tcx, discr, span, body),
 
         TerminatorKind::Abort => Err((span, "abort is not stable in const fn".into())),
         TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => {
index bfb2d472a393cf0525955de8f38dce24e0f270b2..2773da70d7880c2b387b96bfebabe33963051adb 100644 (file)
@@ -16,8 +16,8 @@
 use rustc_lint::LateContext;
 use rustc_middle::mir::interpret::{ConstValue, Scalar};
 use rustc_middle::ty::{
-    self, AdtDef, AssocKind, Binder, BoundRegion, DefIdTree, FnSig, IntTy, List, ParamEnv, Predicate, PredicateKind,
-    ProjectionTy, Region, RegionKind, SubstsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, UintTy,
+    self, AdtDef, AliasTy, AssocKind, Binder, BoundRegion, DefIdTree, FnSig, IntTy, List, ParamEnv, Predicate,
+    PredicateKind, Region, RegionKind, SubstsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, UintTy,
     VariantDef, VariantDiscr,
 };
 use rustc_middle::ty::{GenericArg, GenericArgKind};
@@ -30,7 +30,7 @@
 
 use crate::{match_def_path, path_res, paths};
 
-// Checks if the given type implements copy.
+/// Checks if the given type implements copy.
 pub fn is_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
     ty.is_copy_modulo_regions(cx.tcx, cx.param_env)
 }
@@ -69,50 +69,66 @@ pub fn contains_adt_constructor<'tcx>(ty: Ty<'tcx>, adt: AdtDef<'tcx>) -> bool {
 /// This method also recurses into opaque type predicates, so call it with `impl Trait<U>` and `U`
 /// will also return `true`.
 pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, needle: Ty<'tcx>) -> bool {
-    ty.walk().any(|inner| match inner.unpack() {
-        GenericArgKind::Type(inner_ty) => {
-            if inner_ty == needle {
-                return true;
-            }
+    fn contains_ty_adt_constructor_opaque_inner<'tcx>(
+        cx: &LateContext<'tcx>,
+        ty: Ty<'tcx>,
+        needle: Ty<'tcx>,
+        seen: &mut FxHashSet<DefId>,
+    ) -> bool {
+        ty.walk().any(|inner| match inner.unpack() {
+            GenericArgKind::Type(inner_ty) => {
+                if inner_ty == needle {
+                    return true;
+                }
 
-            if inner_ty.ty_adt_def() == needle.ty_adt_def() {
-                return true;
-            }
+                if inner_ty.ty_adt_def() == needle.ty_adt_def() {
+                    return true;
+                }
 
-            if let ty::Opaque(def_id, _) = *inner_ty.kind() {
-                for &(predicate, _span) in cx.tcx.explicit_item_bounds(def_id) {
-                    match predicate.kind().skip_binder() {
-                        // For `impl Trait<U>`, it will register a predicate of `T: Trait<U>`, so we go through
-                        // and check substituions to find `U`.
-                        ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) => {
-                            if trait_predicate
-                                .trait_ref
-                                .substs
-                                .types()
-                                .skip(1) // Skip the implicit `Self` generic parameter
-                                .any(|ty| contains_ty_adt_constructor_opaque(cx, ty, needle))
-                            {
-                                return true;
-                            }
-                        },
-                        // For `impl Trait<Assoc=U>`, it will register a predicate of `<T as Trait>::Assoc = U`,
-                        // so we check the term for `U`.
-                        ty::PredicateKind::Clause(ty::Clause::Projection(projection_predicate)) => {
-                            if let ty::TermKind::Ty(ty) = projection_predicate.term.unpack() {
-                                if contains_ty_adt_constructor_opaque(cx, ty, needle) {
+                if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *inner_ty.kind() {
+                    if !seen.insert(def_id) {
+                        return false;
+                    }
+
+                    for &(predicate, _span) in cx.tcx.explicit_item_bounds(def_id) {
+                        match predicate.kind().skip_binder() {
+                            // For `impl Trait<U>`, it will register a predicate of `T: Trait<U>`, so we go through
+                            // and check substituions to find `U`.
+                            ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) => {
+                                if trait_predicate
+                                    .trait_ref
+                                    .substs
+                                    .types()
+                                    .skip(1) // Skip the implicit `Self` generic parameter
+                                    .any(|ty| contains_ty_adt_constructor_opaque_inner(cx, ty, needle, seen))
+                                {
                                     return true;
                                 }
-                            };
-                        },
-                        _ => (),
+                            },
+                            // For `impl Trait<Assoc=U>`, it will register a predicate of `<T as Trait>::Assoc = U`,
+                            // so we check the term for `U`.
+                            ty::PredicateKind::Clause(ty::Clause::Projection(projection_predicate)) => {
+                                if let ty::TermKind::Ty(ty) = projection_predicate.term.unpack() {
+                                    if contains_ty_adt_constructor_opaque_inner(cx, ty, needle, seen) {
+                                        return true;
+                                    }
+                                };
+                            },
+                            _ => (),
+                        }
                     }
                 }
-            }
 
-            false
-        },
-        GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false,
-    })
+                false
+            },
+            GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false,
+        })
+    }
+
+    // A hash set to ensure that the same opaque type (`impl Trait` in RPIT or TAIT) is not
+    // visited twice.
+    let mut seen = FxHashSet::default();
+    contains_ty_adt_constructor_opaque_inner(cx, ty, needle, &mut seen)
 }
 
 /// Resolves `<T as Iterator>::Item` for `T`
@@ -250,7 +266,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
             is_must_use_ty(cx, *ty)
         },
         ty::Tuple(substs) => substs.iter().any(|ty| is_must_use_ty(cx, ty)),
-        ty::Opaque(def_id, _) => {
+        ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
             for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) {
                 if let ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) = predicate.kind().skip_binder() {
                     if cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use) {
@@ -631,7 +647,9 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'t
             Some(ExprFnSig::Closure(decl, subs.as_closure().sig()))
         },
         ty::FnDef(id, subs) => Some(ExprFnSig::Sig(cx.tcx.bound_fn_sig(id).subst(cx.tcx, subs), Some(id))),
-        ty::Opaque(id, _) => sig_from_bounds(cx, ty, cx.tcx.item_bounds(id), cx.tcx.opt_parent(id)),
+        ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
+            sig_from_bounds(cx, ty, cx.tcx.item_bounds(def_id), cx.tcx.opt_parent(def_id))
+        },
         ty::FnPtr(sig) => Some(ExprFnSig::Sig(sig, None)),
         ty::Dynamic(bounds, _, _) => {
             let lang_items = cx.tcx.lang_items();
@@ -650,7 +668,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'t
                 _ => None,
             }
         },
-        ty::Projection(proj) => match cx.tcx.try_normalize_erasing_regions(cx.param_env, ty) {
+        ty::Alias(ty::Projection, proj) => match cx.tcx.try_normalize_erasing_regions(cx.param_env, ty) {
             Ok(normalized_ty) if normalized_ty != ty => ty_sig(cx, normalized_ty),
             _ => sig_for_projection(cx, proj).or_else(|| sig_from_bounds(cx, ty, cx.param_env.caller_bounds(), None)),
         },
@@ -685,8 +703,7 @@ fn sig_from_bounds<'tcx>(
                 inputs = Some(i);
             },
             PredicateKind::Clause(ty::Clause::Projection(p))
-                if Some(p.projection_ty.item_def_id) == lang_items.fn_once_output()
-                    && p.projection_ty.self_ty() == ty =>
+                if Some(p.projection_ty.def_id) == lang_items.fn_once_output() && p.projection_ty.self_ty() == ty =>
             {
                 if output.is_some() {
                     // Multiple different fn trait impls. Is this even allowed?
@@ -701,14 +718,14 @@ fn sig_from_bounds<'tcx>(
     inputs.map(|ty| ExprFnSig::Trait(ty, output, predicates_id))
 }
 
-fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: ProjectionTy<'tcx>) -> Option<ExprFnSig<'tcx>> {
+fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option<ExprFnSig<'tcx>> {
     let mut inputs = None;
     let mut output = None;
     let lang_items = cx.tcx.lang_items();
 
     for (pred, _) in cx
         .tcx
-        .bound_explicit_item_bounds(ty.item_def_id)
+        .bound_explicit_item_bounds(ty.def_id)
         .subst_iter_copied(cx.tcx, ty.substs)
     {
         match pred.kind().skip_binder() {
@@ -726,7 +743,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: ProjectionTy<'tcx>) -> O
                 inputs = Some(i);
             },
             PredicateKind::Clause(ty::Clause::Projection(p))
-                if Some(p.projection_ty.item_def_id) == lang_items.fn_once_output() =>
+                if Some(p.projection_ty.def_id) == lang_items.fn_once_output() =>
             {
                 if output.is_some() {
                     // Multiple different fn trait impls. Is this even allowed?
@@ -980,13 +997,13 @@ pub fn make_projection<'tcx>(
     container_id: DefId,
     assoc_ty: Symbol,
     substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
-) -> Option<ProjectionTy<'tcx>> {
+) -> Option<AliasTy<'tcx>> {
     fn helper<'tcx>(
         tcx: TyCtxt<'tcx>,
         container_id: DefId,
         assoc_ty: Symbol,
         substs: SubstsRef<'tcx>,
-    ) -> Option<ProjectionTy<'tcx>> {
+    ) -> Option<AliasTy<'tcx>> {
         let Some(assoc_item) = tcx
             .associated_items(container_id)
             .find_by_name_and_kind(tcx, Ident::with_dummy_span(assoc_ty), AssocKind::Type, container_id)
@@ -1039,10 +1056,7 @@ fn helper<'tcx>(
             }
         }
 
-        Some(ProjectionTy {
-            substs,
-            item_def_id: assoc_item.def_id,
-        })
+        Some(tcx.mk_alias_ty(assoc_item.def_id, substs))
     }
     helper(
         tcx,
@@ -1065,7 +1079,7 @@ pub fn make_normalized_projection<'tcx>(
     assoc_ty: Symbol,
     substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
 ) -> Option<Ty<'tcx>> {
-    fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: ProjectionTy<'tcx>) -> Option<Ty<'tcx>> {
+    fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: AliasTy<'tcx>) -> Option<Ty<'tcx>> {
         #[cfg(debug_assertions)]
         if let Some((i, subst)) = ty
             .substs
@@ -1081,7 +1095,7 @@ fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: ProjectionTy<'
             );
             return None;
         }
-        match tcx.try_normalize_erasing_regions(param_env, tcx.mk_projection(ty.item_def_id, ty.substs)) {
+        match tcx.try_normalize_erasing_regions(param_env, tcx.mk_projection(ty.def_id, ty.substs)) {
             Ok(ty) => Some(ty),
             Err(e) => {
                 debug_assert!(false, "failed to normalize type `{ty}`: {e:#?}");
index 082570f1fe5d87a1924f3503a02ce5fcf6931b4e..c01e1062cb5445c2557a08692ff35eb79212db2d 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name = "declare_clippy_lint"
-version = "0.1.67"
+version = "0.1.68"
 edition = "2021"
 publish = false
 
index 19fee38db46e642eb18f600b1a3b7d8b6e8a814f..8e21cef32abb63ff135e93acb27ef0d644e97de9 100644 (file)
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2022-12-01"
+channel = "nightly-2022-12-17"
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
diff --git a/src/tools/clippy/rustc_tools_util/CHANGELOG.md b/src/tools/clippy/rustc_tools_util/CHANGELOG.md
new file mode 100644 (file)
index 0000000..1b351da
--- /dev/null
@@ -0,0 +1,6 @@
+# Changelog
+
+## Version 0.3.0
+
+* Added `setup_version_info!();` macro for automated scripts.
+* `get_version_info!()` no longer requires the user to import `rustc_tools_util::VersionInfo` and `std::env`
index 89c3d6aaa89e785e15db5dd2de15d7ca69d7239e..877049ae7d0ebd92d8d11d95698f89ded3698a93 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name = "rustc_tools_util"
-version = "0.2.1"
+version = "0.3.0"
 description = "small helper to generate version information for git packages"
 repository = "https://github.com/rust-lang/rust-clippy"
 readme = "README.md"
index e947f9c7e66ed29d7fdc0cf9e4fbc5828994fca5..eefc661f96352e04d182fe016702674df122880f 100644 (file)
@@ -13,43 +13,39 @@ build = "build.rs"
 List rustc_tools_util as regular AND build dependency.
 ````toml
 [dependencies]
-rustc_tools_util = "0.2.1"
+rustc_tools_util = "0.3.0"
 
 [build-dependencies]
-rustc_tools_util = "0.2.1"
+rustc_tools_util = "0.3.0"
 ````
 
 In `build.rs`, generate the data in your `main()`
-````rust
+
+```rust
 fn main() {
-    println!(
-        "cargo:rustc-env=GIT_HASH={}",
-        rustc_tools_util::get_commit_hash().unwrap_or_default()
-    );
-    println!(
-        "cargo:rustc-env=COMMIT_DATE={}",
-        rustc_tools_util::get_commit_date().unwrap_or_default()
-    );
-    println!(
-        "cargo:rustc-env=RUSTC_RELEASE_CHANNEL={}",
-        rustc_tools_util::get_channel().unwrap_or_default()
-    );
+    rustc_tools_util::setup_version_info!();
 }
-
-````
+```
 
 Use the version information in your main.rs
-````rust
-use rustc_tools_util::*;
 
+```rust
 fn show_version() {
     let version_info = rustc_tools_util::get_version_info!();
     println!("{}", version_info);
 }
-````
+```
+
 This gives the following output in clippy:
-`clippy 0.0.212 (a416c5e 2018-12-14)`
+`clippy 0.1.66 (a28f3c8 2022-11-20)`
+
+## Repository
+
+This project is part of the rust-lang/rust-clippy repository. The source code
+can be found under `./rustc_tools_util/`.
 
+The changelog for `rustc_tools_util` is available under:
+[`rustc_tools_util/CHANGELOG.md`](https://github.com/rust-lang/rust-clippy/blob/master/rustc_tools_util/CHANGELOG.md)
 
 ## License
 
index 01d25c53126fdefcb7460562a192deccd457aa7d..4c1d8c3733df61b97582e3780118d9b2446b8de7 100644 (file)
@@ -1,20 +1,20 @@
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
 
-use std::env;
-
+/// This macro creates the version string during compilation from the
+/// current environment
 #[macro_export]
 macro_rules! get_version_info {
     () => {{
-        let major = env!("CARGO_PKG_VERSION_MAJOR").parse::<u8>().unwrap();
-        let minor = env!("CARGO_PKG_VERSION_MINOR").parse::<u8>().unwrap();
-        let patch = env!("CARGO_PKG_VERSION_PATCH").parse::<u16>().unwrap();
-        let crate_name = String::from(env!("CARGO_PKG_NAME"));
+        let major = std::env!("CARGO_PKG_VERSION_MAJOR").parse::<u8>().unwrap();
+        let minor = std::env!("CARGO_PKG_VERSION_MINOR").parse::<u8>().unwrap();
+        let patch = std::env!("CARGO_PKG_VERSION_PATCH").parse::<u16>().unwrap();
+        let crate_name = String::from(std::env!("CARGO_PKG_NAME"));
 
-        let host_compiler = option_env!("RUSTC_RELEASE_CHANNEL").map(str::to_string);
-        let commit_hash = option_env!("GIT_HASH").map(str::to_string);
-        let commit_date = option_env!("COMMIT_DATE").map(str::to_string);
+        let host_compiler = std::option_env!("RUSTC_RELEASE_CHANNEL").map(str::to_string);
+        let commit_hash = std::option_env!("GIT_HASH").map(str::to_string);
+        let commit_date = std::option_env!("COMMIT_DATE").map(str::to_string);
 
-        VersionInfo {
+        $crate::VersionInfo {
             major,
             minor,
             patch,
@@ -26,6 +26,24 @@ macro_rules! get_version_info {
     }};
 }
 
+/// This macro can be used in `build.rs` to automatically set the needed
+/// environment values, namely `GIT_HASH`, `COMMIT_DATE` and
+/// `RUSTC_RELEASE_CHANNEL`
+#[macro_export]
+macro_rules! setup_version_info {
+    () => {{
+        println!(
+            "cargo:rustc-env=GIT_HASH={}",
+            $crate::get_commit_hash().unwrap_or_default()
+        );
+        println!(
+            "cargo:rustc-env=COMMIT_DATE={}",
+            $crate::get_commit_date().unwrap_or_default()
+        );
+        println!("cargo:rustc-env=RUSTC_RELEASE_CHANNEL={}", $crate::get_channel());
+    }};
+}
+
 // some code taken and adapted from RLS and cargo
 pub struct VersionInfo {
     pub major: u8,
@@ -101,7 +119,7 @@ pub fn get_commit_date() -> Option<String> {
 
 #[must_use]
 pub fn get_channel() -> String {
-    match env::var("CFG_RELEASE_CHANNEL") {
+    match std::env::var("CFG_RELEASE_CHANNEL") {
         Ok(channel) => channel,
         Err(_) => {
             // if that failed, try to ask rustc -V, do some parsing and find out
@@ -136,8 +154,8 @@ mod test {
     fn test_struct_local() {
         let vi = get_version_info!();
         assert_eq!(vi.major, 0);
-        assert_eq!(vi.minor, 2);
-        assert_eq!(vi.patch, 1);
+        assert_eq!(vi.minor, 3);
+        assert_eq!(vi.patch, 0);
         assert_eq!(vi.crate_name, "rustc_tools_util");
         // hard to make positive tests for these since they will always change
         assert!(vi.commit_hash.is_none());
@@ -147,7 +165,7 @@ fn test_struct_local() {
     #[test]
     fn test_display_local() {
         let vi = get_version_info!();
-        assert_eq!(vi.to_string(), "rustc_tools_util 0.2.1");
+        assert_eq!(vi.to_string(), "rustc_tools_util 0.3.0");
     }
 
     #[test]
@@ -156,7 +174,7 @@ fn test_debug_local() {
         let s = format!("{vi:?}");
         assert_eq!(
             s,
-            "VersionInfo { crate_name: \"rustc_tools_util\", major: 0, minor: 2, patch: 1 }"
+            "VersionInfo { crate_name: \"rustc_tools_util\", major: 0, minor: 3, patch: 0 }"
         );
     }
 }
index 9ec4df8e651b1bf3f7756656f8548f5c2ec8e9c0..bcc096c570e1b7013524d3b20048903cc3d85780 100644 (file)
@@ -19,7 +19,6 @@
 use rustc_interface::interface;
 use rustc_session::parse::ParseSess;
 use rustc_span::symbol::Symbol;
-use rustc_tools_util::VersionInfo;
 
 use std::borrow::Cow;
 use std::env;
index d418d2daa313e75d69fb6454fc12a8e59f7e37f2..7a78b32620d0bf41301fa50cf781b6a5c658bb45 100644 (file)
@@ -2,7 +2,6 @@
 // warn on lints, that are included in `rust-lang/rust`s bootstrap
 #![warn(rust_2018_idioms, unused_lifetimes)]
 
-use rustc_tools_util::VersionInfo;
 use std::env;
 use std::path::PathBuf;
 use std::process::{self, Command};
index 2a240cc249b0c768f084dab5b6f220ae53a59399..3ca45404e44bb88290ad846bccca89f21b88f6a7 100644 (file)
@@ -7,14 +7,6 @@ LL |     const DEREF_TRAIT: [&str; 4] = ["core", "ops", "deref", "Deref"];
    = help: convert all references to use `sym::Deref`
    = note: `-D clippy::unnecessary-def-path` implied by `-D warnings`
 
-error: hardcoded path to a diagnostic item
-  --> $DIR/unnecessary_def_path_hardcoded_path.rs:12:43
-   |
-LL |     const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"];
-   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: convert all references to use `sym::deref_method`
-
 error: hardcoded path to a language item
   --> $DIR/unnecessary_def_path_hardcoded_path.rs:11:40
    |
@@ -23,5 +15,13 @@ LL |     const DEREF_MUT_TRAIT: [&str; 4] = ["core", "ops", "deref", "DerefMut"]
    |
    = help: convert all references to use `LangItem::DerefMut`
 
+error: hardcoded path to a diagnostic item
+  --> $DIR/unnecessary_def_path_hardcoded_path.rs:12:43
+   |
+LL |     const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"];
+   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: convert all references to use `sym::deref_method`
+
 error: aborting due to 3 previous errors
 
index e8a023ab17643514d08d08c803d51beea762610f..36db9e54a228854ac09f5953faedbc07e6ee90ec 100644 (file)
 
 use core::ops::{Add, Neg};
 
-#[derive(Clone, Copy)]
-struct Point {
-    x: i32,
-    y: i32,
+macro_rules! create {
+    ($name:ident) => {
+        #[allow(clippy::arithmetic_side_effects)]
+        #[derive(Clone, Copy)]
+        struct $name;
+
+        impl Add<$name> for $name {
+            type Output = $name;
+            fn add(self, other: $name) -> Self::Output {
+                todo!()
+            }
+        }
+
+        impl Add<i32> for $name {
+            type Output = $name;
+            fn add(self, other: i32) -> Self::Output {
+                todo!()
+            }
+        }
+
+        impl Add<$name> for i32 {
+            type Output = $name;
+            fn add(self, other: $name) -> Self::Output {
+                todo!()
+            }
+        }
+
+        impl Add<i64> for $name {
+            type Output = $name;
+            fn add(self, other: i64) -> Self::Output {
+                todo!()
+            }
+        }
+
+        impl Add<$name> for i64 {
+            type Output = $name;
+            fn add(self, other: $name) -> Self::Output {
+                todo!()
+            }
+        }
+
+        impl Neg for $name {
+            type Output = $name;
+            fn neg(self) -> Self::Output {
+                todo!()
+            }
+        }
+    };
 }
 
-impl Add for Point {
-    type Output = Self;
+create!(Foo);
+create!(Bar);
+create!(Baz);
+create!(OutOfNames);
 
-    fn add(self, other: Self) -> Self {
-        todo!()
-    }
+fn lhs_and_rhs_are_equal() {
+    // is explicitly on the list
+    let _ = OutOfNames + OutOfNames;
+    // is explicitly on the list
+    let _ = Foo + Foo;
+    // is implicitly on the list
+    let _ = Bar + Bar;
+    // not on the list
+    let _ = Baz + Baz;
 }
 
-impl Neg for Point {
-    type Output = Self;
+fn lhs_is_different() {
+    // is explicitly on the list
+    let _ = 1i32 + OutOfNames;
+    // is explicitly on the list
+    let _ = 1i32 + Foo;
+    // is implicitly on the list
+    let _ = 1i32 + Bar;
+    // not on the list
+    let _ = 1i32 + Baz;
 
-    fn neg(self) -> Self::Output {
-        todo!()
-    }
+    // not on the list
+    let _ = 1i64 + Foo;
+    // is implicitly on the list
+    let _ = 1i64 + Bar;
+    // not on the list
+    let _ = 1i64 + Baz;
 }
 
-fn main() {
-    let _ = Point { x: 1, y: 0 } + Point { x: 2, y: 3 };
+fn rhs_is_different() {
+    // is explicitly on the list
+    let _ = OutOfNames + 1i32;
+    // is explicitly on the list
+    let _ = Foo + 1i32;
+    // is implicitly on the list
+    let _ = Bar + 1i32;
+    // not on the list
+    let _ = Baz + 1i32;
+
+    // not on the list
+    let _ = Foo + 1i64;
+    // is implicitly on the list
+    let _ = Bar + 1i64;
+    // not on the list
+    let _ = Baz + 1i64;
+}
 
-    let point: Point = Point { x: 1, y: 0 };
-    let _ = point + point;
-    let _ = -point;
+fn unary() {
+    // is explicitly on the list
+    let _ = -OutOfNames;
+    // is specifically on the list
+    let _ = -Foo;
+    // not on the list
+    let _ = -Bar;
+    // not on the list
+    let _ = -Baz;
 }
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.stderr b/src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.stderr
new file mode 100644 (file)
index 0000000..ad89534
--- /dev/null
@@ -0,0 +1,58 @@
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects_allowed.rs:68:13
+   |
+LL |     let _ = Baz + Baz;
+   |             ^^^^^^^^^
+   |
+   = note: `-D clippy::arithmetic-side-effects` implied by `-D warnings`
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects_allowed.rs:79:13
+   |
+LL |     let _ = 1i32 + Baz;
+   |             ^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects_allowed.rs:82:13
+   |
+LL |     let _ = 1i64 + Foo;
+   |             ^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects_allowed.rs:86:13
+   |
+LL |     let _ = 1i64 + Baz;
+   |             ^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects_allowed.rs:97:13
+   |
+LL |     let _ = Baz + 1i32;
+   |             ^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects_allowed.rs:100:13
+   |
+LL |     let _ = Foo + 1i64;
+   |             ^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects_allowed.rs:104:13
+   |
+LL |     let _ = Baz + 1i64;
+   |             ^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects_allowed.rs:113:13
+   |
+LL |     let _ = -Bar;
+   |             ^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects_allowed.rs:115:13
+   |
+LL |     let _ = -Baz;
+   |             ^^^^
+
+error: aborting due to 9 previous errors
+
index e736256f29a475564c327ccdab471bec05993d49..89cbea7ecfe4728a7660a497312179bdafea4311 100644 (file)
@@ -1 +1,11 @@
-arithmetic-side-effects-allowed = ["Point"]
+arithmetic-side-effects-allowed = [
+    "OutOfNames"
+]
+arithmetic-side-effects-allowed-binary = [
+    ["Foo", "Foo"],
+    ["Foo", "i32"],
+    ["i32", "Foo"],
+    ["Bar", "*"],
+    ["*", "Bar"],
+]
+arithmetic-side-effects-allowed-unary = ["Foo"]
diff --git a/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/clippy.toml b/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/clippy.toml
new file mode 100644 (file)
index 0000000..1b9384d
--- /dev/null
@@ -0,0 +1 @@
+suppress-restriction-lint-in-const = true
diff --git a/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.rs b/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.rs
new file mode 100644 (file)
index 0000000..5a2df9f
--- /dev/null
@@ -0,0 +1,60 @@
+#![feature(inline_const)]
+#![warn(clippy::indexing_slicing)]
+// We also check the out_of_bounds_indexing lint here, because it lints similar things and
+// we want to avoid false positives.
+#![warn(clippy::out_of_bounds_indexing)]
+#![allow(unconditional_panic, clippy::no_effect, clippy::unnecessary_operation)]
+
+const ARR: [i32; 2] = [1, 2];
+const REF: &i32 = &ARR[idx()]; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true.
+const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts.
+
+const fn idx() -> usize {
+    1
+}
+const fn idx4() -> usize {
+    4
+}
+
+fn main() {
+    let x = [1, 2, 3, 4];
+    let index: usize = 1;
+    x[index];
+    x[4]; // Ok, let rustc's `unconditional_panic` lint handle `usize` indexing on arrays.
+    x[1 << 3]; // Ok, let rustc's `unconditional_panic` lint handle `usize` indexing on arrays.
+
+    x[0]; // Ok, should not produce stderr.
+    x[3]; // Ok, should not produce stderr.
+    x[const { idx() }]; // Ok, should not produce stderr.
+    x[const { idx4() }]; // Ok, let rustc's `unconditional_panic` lint handle `usize` indexing on arrays.
+    const { &ARR[idx()] }; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true.
+    const { &ARR[idx4()] }; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true.
+
+    let y = &x;
+    y[0]; // Ok, referencing shouldn't affect this lint. See the issue 6021
+    y[4]; // Ok, rustc will handle references too.
+
+    let v = vec![0; 5];
+    v[0];
+    v[10];
+    v[1 << 3];
+
+    const N: usize = 15; // Out of bounds
+    const M: usize = 3; // In bounds
+    x[N]; // Ok, let rustc's `unconditional_panic` lint handle `usize` indexing on arrays.
+    x[M]; // Ok, should not produce stderr.
+    v[N];
+    v[M];
+}
+
+/// An opaque integer representation
+pub struct Integer<'a> {
+    /// The underlying data
+    value: &'a [u8],
+}
+impl<'a> Integer<'a> {
+    // Check whether `self` holds a negative number or not
+    pub const fn is_negative(&self) -> bool {
+        self.value[0] & 0b1000_0000 != 0
+    }
+}
diff --git a/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.stderr b/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.stderr
new file mode 100644 (file)
index 0000000..bc178b7
--- /dev/null
@@ -0,0 +1,70 @@
+error[E0080]: evaluation of `main::{constant#3}` failed
+  --> $DIR/test.rs:31:14
+   |
+LL |     const { &ARR[idx4()] }; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true.
+   |              ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4
+
+note: erroneous constant used
+  --> $DIR/test.rs:31:5
+   |
+LL |     const { &ARR[idx4()] }; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true.
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: indexing may panic
+  --> $DIR/test.rs:22:5
+   |
+LL |     x[index];
+   |     ^^^^^^^^
+   |
+   = help: consider using `.get(n)` or `.get_mut(n)` instead
+   = note: `-D clippy::indexing-slicing` implied by `-D warnings`
+
+error: indexing may panic
+  --> $DIR/test.rs:38:5
+   |
+LL |     v[0];
+   |     ^^^^
+   |
+   = help: consider using `.get(n)` or `.get_mut(n)` instead
+
+error: indexing may panic
+  --> $DIR/test.rs:39:5
+   |
+LL |     v[10];
+   |     ^^^^^
+   |
+   = help: consider using `.get(n)` or `.get_mut(n)` instead
+
+error: indexing may panic
+  --> $DIR/test.rs:40:5
+   |
+LL |     v[1 << 3];
+   |     ^^^^^^^^^
+   |
+   = help: consider using `.get(n)` or `.get_mut(n)` instead
+
+error: indexing may panic
+  --> $DIR/test.rs:46:5
+   |
+LL |     v[N];
+   |     ^^^^
+   |
+   = help: consider using `.get(n)` or `.get_mut(n)` instead
+
+error: indexing may panic
+  --> $DIR/test.rs:47:5
+   |
+LL |     v[M];
+   |     ^^^^
+   |
+   = help: consider using `.get(n)` or `.get_mut(n)` instead
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/test.rs:10:24
+   |
+LL | const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts.
+   |                        ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
index 01a5e962c9491ea0d52cd89707f4c1d3c3ec4e74..a22c6a5a0607d9ede572bdfd9ed7997237675717 100644 (file)
@@ -6,6 +6,8 @@ error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown fie
            allow-unwrap-in-tests
            allowed-scripts
            arithmetic-side-effects-allowed
+           arithmetic-side-effects-allowed-binary
+           arithmetic-side-effects-allowed-unary
            array-size-threshold
            avoid-breaking-exported-api
            await-holding-invalid-types
@@ -35,6 +37,7 @@ error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown fie
            pass-by-value-size-limit
            single-char-binding-names-threshold
            standard-macro-braces
+           suppress-restriction-lint-in-const
            third-party
            too-large-for-stack
            too-many-arguments-threshold
diff --git a/src/tools/clippy/tests/ui/almost_complete_letter_range.fixed b/src/tools/clippy/tests/ui/almost_complete_letter_range.fixed
deleted file mode 100644 (file)
index adcbd4d..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-// run-rustfix
-// edition:2018
-// aux-build:macro_rules.rs
-
-#![feature(exclusive_range_pattern)]
-#![feature(stmt_expr_attributes)]
-#![warn(clippy::almost_complete_letter_range)]
-#![allow(ellipsis_inclusive_range_patterns)]
-#![allow(clippy::needless_parens_on_range_literals)]
-
-#[macro_use]
-extern crate macro_rules;
-
-macro_rules! a {
-    () => {
-        'a'
-    };
-}
-
-macro_rules! b {
-    () => {
-        let _ = 'a'..='z';
-    };
-}
-
-fn main() {
-    #[rustfmt::skip]
-    {
-        let _ = ('a') ..='z';
-        let _ = 'A' ..= ('Z');
-    }
-
-    let _ = 'b'..'z';
-    let _ = 'B'..'Z';
-
-    let _ = (b'a')..=(b'z');
-    let _ = b'A'..=b'Z';
-
-    let _ = b'b'..b'z';
-    let _ = b'B'..b'Z';
-
-    let _ = a!()..='z';
-
-    let _ = match 0u8 {
-        b'a'..=b'z' if true => 1,
-        b'A'..=b'Z' if true => 2,
-        b'b'..b'z' => 3,
-        b'B'..b'Z' => 4,
-        _ => 5,
-    };
-
-    let _ = match 'x' {
-        'a'..='z' if true => 1,
-        'A'..='Z' if true => 2,
-        'b'..'z' => 3,
-        'B'..'Z' => 4,
-        _ => 5,
-    };
-
-    almost_complete_letter_range!();
-    b!();
-}
-
-#[clippy::msrv = "1.25"]
-fn _under_msrv() {
-    let _ = match 'a' {
-        'a'...'z' => 1,
-        _ => 2,
-    };
-}
-
-#[clippy::msrv = "1.26"]
-fn _meets_msrv() {
-    let _ = 'a'..='z';
-    let _ = match 'a' {
-        'a'..='z' => 1,
-        _ => 2,
-    };
-}
diff --git a/src/tools/clippy/tests/ui/almost_complete_letter_range.rs b/src/tools/clippy/tests/ui/almost_complete_letter_range.rs
deleted file mode 100644 (file)
index 9979316..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-// run-rustfix
-// edition:2018
-// aux-build:macro_rules.rs
-
-#![feature(exclusive_range_pattern)]
-#![feature(stmt_expr_attributes)]
-#![warn(clippy::almost_complete_letter_range)]
-#![allow(ellipsis_inclusive_range_patterns)]
-#![allow(clippy::needless_parens_on_range_literals)]
-
-#[macro_use]
-extern crate macro_rules;
-
-macro_rules! a {
-    () => {
-        'a'
-    };
-}
-
-macro_rules! b {
-    () => {
-        let _ = 'a'..'z';
-    };
-}
-
-fn main() {
-    #[rustfmt::skip]
-    {
-        let _ = ('a') ..'z';
-        let _ = 'A' .. ('Z');
-    }
-
-    let _ = 'b'..'z';
-    let _ = 'B'..'Z';
-
-    let _ = (b'a')..(b'z');
-    let _ = b'A'..b'Z';
-
-    let _ = b'b'..b'z';
-    let _ = b'B'..b'Z';
-
-    let _ = a!()..'z';
-
-    let _ = match 0u8 {
-        b'a'..b'z' if true => 1,
-        b'A'..b'Z' if true => 2,
-        b'b'..b'z' => 3,
-        b'B'..b'Z' => 4,
-        _ => 5,
-    };
-
-    let _ = match 'x' {
-        'a'..'z' if true => 1,
-        'A'..'Z' if true => 2,
-        'b'..'z' => 3,
-        'B'..'Z' => 4,
-        _ => 5,
-    };
-
-    almost_complete_letter_range!();
-    b!();
-}
-
-#[clippy::msrv = "1.25"]
-fn _under_msrv() {
-    let _ = match 'a' {
-        'a'..'z' => 1,
-        _ => 2,
-    };
-}
-
-#[clippy::msrv = "1.26"]
-fn _meets_msrv() {
-    let _ = 'a'..'z';
-    let _ = match 'a' {
-        'a'..'z' => 1,
-        _ => 2,
-    };
-}
diff --git a/src/tools/clippy/tests/ui/almost_complete_letter_range.stderr b/src/tools/clippy/tests/ui/almost_complete_letter_range.stderr
deleted file mode 100644 (file)
index 9abf6d6..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-error: almost complete ascii letter range
-  --> $DIR/almost_complete_letter_range.rs:29:17
-   |
-LL |         let _ = ('a') ..'z';
-   |                 ^^^^^^--^^^
-   |                       |
-   |                       help: use an inclusive range: `..=`
-   |
-   = note: `-D clippy::almost-complete-letter-range` implied by `-D warnings`
-
-error: almost complete ascii letter range
-  --> $DIR/almost_complete_letter_range.rs:30:17
-   |
-LL |         let _ = 'A' .. ('Z');
-   |                 ^^^^--^^^^^^
-   |                     |
-   |                     help: use an inclusive range: `..=`
-
-error: almost complete ascii letter range
-  --> $DIR/almost_complete_letter_range.rs:36:13
-   |
-LL |     let _ = (b'a')..(b'z');
-   |             ^^^^^^--^^^^^^
-   |                   |
-   |                   help: use an inclusive range: `..=`
-
-error: almost complete ascii letter range
-  --> $DIR/almost_complete_letter_range.rs:37:13
-   |
-LL |     let _ = b'A'..b'Z';
-   |             ^^^^--^^^^
-   |                 |
-   |                 help: use an inclusive range: `..=`
-
-error: almost complete ascii letter range
-  --> $DIR/almost_complete_letter_range.rs:42:13
-   |
-LL |     let _ = a!()..'z';
-   |             ^^^^--^^^
-   |                 |
-   |                 help: use an inclusive range: `..=`
-
-error: almost complete ascii letter range
-  --> $DIR/almost_complete_letter_range.rs:45:9
-   |
-LL |         b'a'..b'z' if true => 1,
-   |         ^^^^--^^^^
-   |             |
-   |             help: use an inclusive range: `..=`
-
-error: almost complete ascii letter range
-  --> $DIR/almost_complete_letter_range.rs:46:9
-   |
-LL |         b'A'..b'Z' if true => 2,
-   |         ^^^^--^^^^
-   |             |
-   |             help: use an inclusive range: `..=`
-
-error: almost complete ascii letter range
-  --> $DIR/almost_complete_letter_range.rs:53:9
-   |
-LL |         'a'..'z' if true => 1,
-   |         ^^^--^^^
-   |            |
-   |            help: use an inclusive range: `..=`
-
-error: almost complete ascii letter range
-  --> $DIR/almost_complete_letter_range.rs:54:9
-   |
-LL |         'A'..'Z' if true => 2,
-   |         ^^^--^^^
-   |            |
-   |            help: use an inclusive range: `..=`
-
-error: almost complete ascii letter range
-  --> $DIR/almost_complete_letter_range.rs:22:17
-   |
-LL |         let _ = 'a'..'z';
-   |                 ^^^--^^^
-   |                    |
-   |                    help: use an inclusive range: `..=`
-...
-LL |     b!();
-   |     ---- in this macro invocation
-   |
-   = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: almost complete ascii letter range
-  --> $DIR/almost_complete_letter_range.rs:67:9
-   |
-LL |         'a'..'z' => 1,
-   |         ^^^--^^^
-   |            |
-   |            help: use an inclusive range: `...`
-
-error: almost complete ascii letter range
-  --> $DIR/almost_complete_letter_range.rs:74:13
-   |
-LL |     let _ = 'a'..'z';
-   |             ^^^--^^^
-   |                |
-   |                help: use an inclusive range: `..=`
-
-error: almost complete ascii letter range
-  --> $DIR/almost_complete_letter_range.rs:76:9
-   |
-LL |         'a'..'z' => 1,
-   |         ^^^--^^^
-   |            |
-   |            help: use an inclusive range: `..=`
-
-error: aborting due to 13 previous errors
-
diff --git a/src/tools/clippy/tests/ui/almost_complete_range.fixed b/src/tools/clippy/tests/ui/almost_complete_range.fixed
new file mode 100644 (file)
index 0000000..6046add
--- /dev/null
@@ -0,0 +1,108 @@
+// run-rustfix
+// edition:2018
+// aux-build:macro_rules.rs
+
+#![feature(exclusive_range_pattern)]
+#![feature(stmt_expr_attributes)]
+#![warn(clippy::almost_complete_range)]
+#![allow(ellipsis_inclusive_range_patterns)]
+#![allow(clippy::needless_parens_on_range_literals)]
+#![allow(clippy::double_parens)]
+
+#[macro_use]
+extern crate macro_rules;
+
+macro_rules! a {
+    () => {
+        'a'
+    };
+}
+macro_rules! A {
+    () => {
+        'A'
+    };
+}
+macro_rules! zero {
+    () => {
+        '0'
+    };
+}
+
+macro_rules! b {
+    () => {
+        let _ = 'a'..='z';
+        let _ = 'A'..='Z';
+        let _ = '0'..='9';
+    };
+}
+
+fn main() {
+    #[rustfmt::skip]
+    {
+        let _ = ('a') ..='z';
+        let _ = 'A' ..= ('Z');
+        let _ = ((('0'))) ..= ('9');
+    }
+
+    let _ = 'b'..'z';
+    let _ = 'B'..'Z';
+    let _ = '1'..'9';
+
+    let _ = (b'a')..=(b'z');
+    let _ = b'A'..=b'Z';
+    let _ = b'0'..=b'9';
+
+    let _ = b'b'..b'z';
+    let _ = b'B'..b'Z';
+    let _ = b'1'..b'9';
+
+    let _ = a!()..='z';
+    let _ = A!()..='Z';
+    let _ = zero!()..='9';
+
+    let _ = match 0u8 {
+        b'a'..=b'z' if true => 1,
+        b'A'..=b'Z' if true => 2,
+        b'0'..=b'9' if true => 3,
+        b'b'..b'z' => 4,
+        b'B'..b'Z' => 5,
+        b'1'..b'9' => 6,
+        _ => 7,
+    };
+
+    let _ = match 'x' {
+        'a'..='z' if true => 1,
+        'A'..='Z' if true => 2,
+        '0'..='9' if true => 3,
+        'b'..'z' => 4,
+        'B'..'Z' => 5,
+        '1'..'9' => 6,
+        _ => 7,
+    };
+
+    almost_complete_range!();
+    b!();
+}
+
+#[clippy::msrv = "1.25"]
+fn _under_msrv() {
+    let _ = match 'a' {
+        'a'...'z' => 1,
+        'A'...'Z' => 2,
+        '0'...'9' => 3,
+        _ => 4,
+    };
+}
+
+#[clippy::msrv = "1.26"]
+fn _meets_msrv() {
+    let _ = 'a'..='z';
+    let _ = 'A'..='Z';
+    let _ = '0'..='9';
+    let _ = match 'a' {
+        'a'..='z' => 1,
+        'A'..='Z' => 1,
+        '0'..='9' => 3,
+        _ => 4,
+    };
+}
diff --git a/src/tools/clippy/tests/ui/almost_complete_range.rs b/src/tools/clippy/tests/ui/almost_complete_range.rs
new file mode 100644 (file)
index 0000000..ae7e07a
--- /dev/null
@@ -0,0 +1,108 @@
+// run-rustfix
+// edition:2018
+// aux-build:macro_rules.rs
+
+#![feature(exclusive_range_pattern)]
+#![feature(stmt_expr_attributes)]
+#![warn(clippy::almost_complete_range)]
+#![allow(ellipsis_inclusive_range_patterns)]
+#![allow(clippy::needless_parens_on_range_literals)]
+#![allow(clippy::double_parens)]
+
+#[macro_use]
+extern crate macro_rules;
+
+macro_rules! a {
+    () => {
+        'a'
+    };
+}
+macro_rules! A {
+    () => {
+        'A'
+    };
+}
+macro_rules! zero {
+    () => {
+        '0'
+    };
+}
+
+macro_rules! b {
+    () => {
+        let _ = 'a'..'z';
+        let _ = 'A'..'Z';
+        let _ = '0'..'9';
+    };
+}
+
+fn main() {
+    #[rustfmt::skip]
+    {
+        let _ = ('a') ..'z';
+        let _ = 'A' .. ('Z');
+        let _ = ((('0'))) .. ('9');
+    }
+
+    let _ = 'b'..'z';
+    let _ = 'B'..'Z';
+    let _ = '1'..'9';
+
+    let _ = (b'a')..(b'z');
+    let _ = b'A'..b'Z';
+    let _ = b'0'..b'9';
+
+    let _ = b'b'..b'z';
+    let _ = b'B'..b'Z';
+    let _ = b'1'..b'9';
+
+    let _ = a!()..'z';
+    let _ = A!()..'Z';
+    let _ = zero!()..'9';
+
+    let _ = match 0u8 {
+        b'a'..b'z' if true => 1,
+        b'A'..b'Z' if true => 2,
+        b'0'..b'9' if true => 3,
+        b'b'..b'z' => 4,
+        b'B'..b'Z' => 5,
+        b'1'..b'9' => 6,
+        _ => 7,
+    };
+
+    let _ = match 'x' {
+        'a'..'z' if true => 1,
+        'A'..'Z' if true => 2,
+        '0'..'9' if true => 3,
+        'b'..'z' => 4,
+        'B'..'Z' => 5,
+        '1'..'9' => 6,
+        _ => 7,
+    };
+
+    almost_complete_range!();
+    b!();
+}
+
+#[clippy::msrv = "1.25"]
+fn _under_msrv() {
+    let _ = match 'a' {
+        'a'..'z' => 1,
+        'A'..'Z' => 2,
+        '0'..'9' => 3,
+        _ => 4,
+    };
+}
+
+#[clippy::msrv = "1.26"]
+fn _meets_msrv() {
+    let _ = 'a'..'z';
+    let _ = 'A'..'Z';
+    let _ = '0'..'9';
+    let _ = match 'a' {
+        'a'..'z' => 1,
+        'A'..'Z' => 1,
+        '0'..'9' => 3,
+        _ => 4,
+    };
+}
diff --git a/src/tools/clippy/tests/ui/almost_complete_range.stderr b/src/tools/clippy/tests/ui/almost_complete_range.stderr
new file mode 100644 (file)
index 0000000..a7a5328
--- /dev/null
@@ -0,0 +1,235 @@
+error: almost complete ascii range
+  --> $DIR/almost_complete_range.rs:42:17
+   |
+LL |         let _ = ('a') ..'z';
+   |                 ^^^^^^--^^^
+   |                       |
+   |                       help: use an inclusive range: `..=`
+   |
+   = note: `-D clippy::almost-complete-range` implied by `-D warnings`
+
+error: almost complete ascii range
+  --> $DIR/almost_complete_range.rs:43:17
+   |
+LL |         let _ = 'A' .. ('Z');
+   |                 ^^^^--^^^^^^
+   |                     |
+   |                     help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+  --> $DIR/almost_complete_range.rs:44:17
+   |
+LL |         let _ = ((('0'))) .. ('9');
+   |                 ^^^^^^^^^^--^^^^^^
+   |                           |
+   |                           help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+  --> $DIR/almost_complete_range.rs:51:13
+   |
+LL |     let _ = (b'a')..(b'z');
+   |             ^^^^^^--^^^^^^
+   |                   |
+   |                   help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+  --> $DIR/almost_complete_range.rs:52:13
+   |
+LL |     let _ = b'A'..b'Z';
+   |             ^^^^--^^^^
+   |                 |
+   |                 help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+  --> $DIR/almost_complete_range.rs:53:13
+   |
+LL |     let _ = b'0'..b'9';
+   |             ^^^^--^^^^
+   |                 |
+   |                 help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+  --> $DIR/almost_complete_range.rs:59:13
+   |
+LL |     let _ = a!()..'z';
+   |             ^^^^--^^^
+   |                 |
+   |                 help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+  --> $DIR/almost_complete_range.rs:60:13
+   |
+LL |     let _ = A!()..'Z';
+   |             ^^^^--^^^
+   |                 |
+   |                 help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+  --> $DIR/almost_complete_range.rs:61:13
+   |
+LL |     let _ = zero!()..'9';
+   |             ^^^^^^^--^^^
+   |                    |
+   |                    help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+  --> $DIR/almost_complete_range.rs:64:9
+   |
+LL |         b'a'..b'z' if true => 1,
+   |         ^^^^--^^^^
+   |             |
+   |             help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+  --> $DIR/almost_complete_range.rs:65:9
+   |
+LL |         b'A'..b'Z' if true => 2,
+   |         ^^^^--^^^^
+   |             |
+   |             help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+  --> $DIR/almost_complete_range.rs:66:9
+   |
+LL |         b'0'..b'9' if true => 3,
+   |         ^^^^--^^^^
+   |             |
+   |             help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+  --> $DIR/almost_complete_range.rs:74:9
+   |
+LL |         'a'..'z' if true => 1,
+   |         ^^^--^^^
+   |            |
+   |            help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+  --> $DIR/almost_complete_range.rs:75:9
+   |
+LL |         'A'..'Z' if true => 2,
+   |         ^^^--^^^
+   |            |
+   |            help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+  --> $DIR/almost_complete_range.rs:76:9
+   |
+LL |         '0'..'9' if true => 3,
+   |         ^^^--^^^
+   |            |
+   |            help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+  --> $DIR/almost_complete_range.rs:33:17
+   |
+LL |         let _ = 'a'..'z';
+   |                 ^^^--^^^
+   |                    |
+   |                    help: use an inclusive range: `..=`
+...
+LL |     b!();
+   |     ---- in this macro invocation
+   |
+   = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: almost complete ascii range
+  --> $DIR/almost_complete_range.rs:34:17
+   |
+LL |         let _ = 'A'..'Z';
+   |                 ^^^--^^^
+   |                    |
+   |                    help: use an inclusive range: `..=`
+...
+LL |     b!();
+   |     ---- in this macro invocation
+   |
+   = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: almost complete ascii range
+  --> $DIR/almost_complete_range.rs:35:17
+   |
+LL |         let _ = '0'..'9';
+   |                 ^^^--^^^
+   |                    |
+   |                    help: use an inclusive range: `..=`
+...
+LL |     b!();
+   |     ---- in this macro invocation
+   |
+   = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: almost complete ascii range
+  --> $DIR/almost_complete_range.rs:90:9
+   |
+LL |         'a'..'z' => 1,
+   |         ^^^--^^^
+   |            |
+   |            help: use an inclusive range: `...`
+
+error: almost complete ascii range
+  --> $DIR/almost_complete_range.rs:91:9
+   |
+LL |         'A'..'Z' => 2,
+   |         ^^^--^^^
+   |            |
+   |            help: use an inclusive range: `...`
+
+error: almost complete ascii range
+  --> $DIR/almost_complete_range.rs:92:9
+   |
+LL |         '0'..'9' => 3,
+   |         ^^^--^^^
+   |            |
+   |            help: use an inclusive range: `...`
+
+error: almost complete ascii range
+  --> $DIR/almost_complete_range.rs:99:13
+   |
+LL |     let _ = 'a'..'z';
+   |             ^^^--^^^
+   |                |
+   |                help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+  --> $DIR/almost_complete_range.rs:100:13
+   |
+LL |     let _ = 'A'..'Z';
+   |             ^^^--^^^
+   |                |
+   |                help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+  --> $DIR/almost_complete_range.rs:101:13
+   |
+LL |     let _ = '0'..'9';
+   |             ^^^--^^^
+   |                |
+   |                help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+  --> $DIR/almost_complete_range.rs:103:9
+   |
+LL |         'a'..'z' => 1,
+   |         ^^^--^^^
+   |            |
+   |            help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+  --> $DIR/almost_complete_range.rs:104:9
+   |
+LL |         'A'..'Z' => 1,
+   |         ^^^--^^^
+   |            |
+   |            help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+  --> $DIR/almost_complete_range.rs:105:9
+   |
+LL |         '0'..'9' => 3,
+   |         ^^^--^^^
+   |            |
+   |            help: use an inclusive range: `..=`
+
+error: aborting due to 27 previous errors
+
index 0259a0824e794cc7ba5a0f957f0130f6b3c49a0e..9fe4b7cf28d8d3fc4ee574fa194d060adc6f3d8f 100644 (file)
@@ -1,28 +1,10 @@
-error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:78:13
-   |
-LL |     let _ = String::new() + "";
-   |             ^^^^^^^^^^^^^^^^^^
-   |
-   = note: `-D clippy::arithmetic-side-effects` implied by `-D warnings`
-
-error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:86:27
-   |
-LL |     let inferred_string = string + "";
-   |                           ^^^^^^^^^^^
-
-error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:90:13
-   |
-LL |     let _ = inferred_string + "";
-   |             ^^^^^^^^^^^^^^^^^^^^
-
 error: arithmetic operation that can potentially result in unexpected side-effects
   --> $DIR/arithmetic_side_effects.rs:165:5
    |
 LL |     _n += 1;
    |     ^^^^^^^
+   |
+   = note: `-D clippy::arithmetic-side-effects` implied by `-D warnings`
 
 error: arithmetic operation that can potentially result in unexpected side-effects
   --> $DIR/arithmetic_side_effects.rs:166:5
@@ -348,5 +330,5 @@ error: arithmetic operation that can potentially result in unexpected side-effec
 LL |     _n = -&_n;
    |          ^^^^
 
-error: aborting due to 58 previous errors
+error: aborting due to 55 previous errors
 
index ef3ca9aea380c0bfba020deffb65b601f56a90b4..1e5f20e8c39baf5ad8c47d5dd77530bfcba75dc6 100644 (file)
@@ -142,8 +142,10 @@ macro_rules! equatable_if_let {
 }
 
 #[macro_export]
-macro_rules! almost_complete_letter_range {
+macro_rules! almost_complete_range {
     () => {
         let _ = 'a'..'z';
+        let _ = 'A'..'Z';
+        let _ = '0'..'9';
     };
 }
index 72a708b40737b3932688127ec9b1905901bacb86..925cbf25368fbd18b3ceb6b537b38070e82266a4 100644 (file)
@@ -45,3 +45,9 @@ mod cast_lossless_in_impl {
         }
     }
 }
+
+#[derive(PartialEq, Debug)]
+#[repr(i64)]
+enum Test {
+    A = u32::MAX as i64 + 1,
+}
index 34bb47181e69deffcf1bfe283ed4557b68d08c4e..c82bd9108d23bfb8ad03bc97911c76d49e00cb67 100644 (file)
@@ -45,3 +45,9 @@ pub const fn convert(x: u32) -> u64 {
         }
     }
 }
+
+#[derive(PartialEq, Debug)]
+#[repr(i64)]
+enum Test {
+    A = u32::MAX as i64 + 1,
+}
index 49fc9a9629e25415a714b6e3616602c77367f239..9792ae9ed6b8b34ddb097b3c17be2cf15a4692f4 100644 (file)
@@ -1,5 +1,6 @@
 // run-rustfix
 
+#![allow(unused)]
 #![warn(clippy::collapsible_str_replace)]
 
 fn get_filter() -> char {
@@ -71,3 +72,13 @@ fn main() {
         .replace('u', iter.next().unwrap())
         .replace('s', iter.next().unwrap());
 }
+
+#[clippy::msrv = "1.57"]
+fn msrv_1_57() {
+    let _ = "".replace('a', "1.57").replace('b', "1.57");
+}
+
+#[clippy::msrv = "1.58"]
+fn msrv_1_58() {
+    let _ = "".replace(['a', 'b'], "1.58");
+}
index e3e25c4146ffa6bdd7a71bcd2067ba9a6ec6b68e..baee185b79ea388e77b8d143de03d68d92c964a9 100644 (file)
@@ -1,5 +1,6 @@
 // run-rustfix
 
+#![allow(unused)]
 #![warn(clippy::collapsible_str_replace)]
 
 fn get_filter() -> char {
@@ -74,3 +75,13 @@ fn main() {
         .replace('u', iter.next().unwrap())
         .replace('s', iter.next().unwrap());
 }
+
+#[clippy::msrv = "1.57"]
+fn msrv_1_57() {
+    let _ = "".replace('a', "1.57").replace('b', "1.57");
+}
+
+#[clippy::msrv = "1.58"]
+fn msrv_1_58() {
+    let _ = "".replace('a', "1.58").replace('b', "1.58");
+}
index 8e3daf3b898a3328e6f5f9de77f42e24f2729b79..223358cf53f3e0e07c8b2db2c37a9d4cb9f619b4 100644 (file)
@@ -1,5 +1,5 @@
 error: used consecutive `str::replace` call
-  --> $DIR/collapsible_str_replace.rs:19:27
+  --> $DIR/collapsible_str_replace.rs:20:27
    |
 LL |     let _ = "hesuo worpd".replace('s', "l").replace('u', "l");
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace(['s', 'u'], "l")`
@@ -7,19 +7,19 @@ LL |     let _ = "hesuo worpd".replace('s', "l").replace('u', "l");
    = note: `-D clippy::collapsible-str-replace` implied by `-D warnings`
 
 error: used consecutive `str::replace` call
-  --> $DIR/collapsible_str_replace.rs:21:27
+  --> $DIR/collapsible_str_replace.rs:22:27
    |
 LL |     let _ = "hesuo worpd".replace('s', l).replace('u', l);
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace(['s', 'u'], l)`
 
 error: used consecutive `str::replace` call
-  --> $DIR/collapsible_str_replace.rs:23:27
+  --> $DIR/collapsible_str_replace.rs:24:27
    |
 LL |     let _ = "hesuo worpd".replace('s', "l").replace('u', "l").replace('p', "l");
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace(['s', 'u', 'p'], "l")`
 
 error: used consecutive `str::replace` call
-  --> $DIR/collapsible_str_replace.rs:26:10
+  --> $DIR/collapsible_str_replace.rs:27:10
    |
 LL |           .replace('s', "l")
    |  __________^
@@ -29,58 +29,64 @@ LL | |         .replace('d', "l");
    | |__________________________^ help: replace with: `replace(['s', 'u', 'p', 'd'], "l")`
 
 error: used consecutive `str::replace` call
-  --> $DIR/collapsible_str_replace.rs:31:27
+  --> $DIR/collapsible_str_replace.rs:32:27
    |
 LL |     let _ = "hesuo world".replace(s, "l").replace('u', "l");
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace([s, 'u'], "l")`
 
 error: used consecutive `str::replace` call
-  --> $DIR/collapsible_str_replace.rs:33:27
+  --> $DIR/collapsible_str_replace.rs:34:27
    |
 LL |     let _ = "hesuo worpd".replace(s, "l").replace('u', "l").replace('p', "l");
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace([s, 'u', 'p'], "l")`
 
 error: used consecutive `str::replace` call
-  --> $DIR/collapsible_str_replace.rs:35:27
+  --> $DIR/collapsible_str_replace.rs:36:27
    |
 LL |     let _ = "hesuo worpd".replace(s, "l").replace(u, "l").replace('p', "l");
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace([s, u, 'p'], "l")`
 
 error: used consecutive `str::replace` call
-  --> $DIR/collapsible_str_replace.rs:37:27
+  --> $DIR/collapsible_str_replace.rs:38:27
    |
 LL |     let _ = "hesuo worpd".replace(s, "l").replace(u, "l").replace(p, "l");
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace([s, u, p], "l")`
 
 error: used consecutive `str::replace` call
-  --> $DIR/collapsible_str_replace.rs:39:27
+  --> $DIR/collapsible_str_replace.rs:40:27
    |
 LL |     let _ = "hesuo worlp".replace('s', "l").replace('u', "l").replace('p', "d");
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace(['s', 'u'], "l")`
 
 error: used consecutive `str::replace` call
-  --> $DIR/collapsible_str_replace.rs:41:45
+  --> $DIR/collapsible_str_replace.rs:42:45
    |
 LL |     let _ = "hesuo worpd".replace('s', "x").replace('u', "l").replace('p', "l");
    |                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace(['u', 'p'], "l")`
 
 error: used consecutive `str::replace` call
-  --> $DIR/collapsible_str_replace.rs:44:47
+  --> $DIR/collapsible_str_replace.rs:45:47
    |
 LL |     let _ = "hesudo worpd".replace("su", "l").replace('d', "l").replace('p', "l");
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace(['d', 'p'], "l")`
 
 error: used consecutive `str::replace` call
-  --> $DIR/collapsible_str_replace.rs:46:28
+  --> $DIR/collapsible_str_replace.rs:47:28
    |
 LL |     let _ = "hesudo worpd".replace(d, "l").replace('p', "l").replace("su", "l");
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace([d, 'p'], "l")`
 
 error: used consecutive `str::replace` call
-  --> $DIR/collapsible_str_replace.rs:48:27
+  --> $DIR/collapsible_str_replace.rs:49:27
    |
 LL |     let _ = "hesuo world".replace(get_filter(), "l").replace('s', "l");
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace([get_filter(), 's'], "l")`
 
-error: aborting due to 13 previous errors
+error: used consecutive `str::replace` call
+  --> $DIR/collapsible_str_replace.rs:86:16
+   |
+LL |     let _ = "".replace('a', "1.58").replace('b', "1.58");
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace(['a', 'b'], "1.58")`
+
+error: aborting due to 14 previous errors
 
index 6eddc01e2c471215af0fa4584f5083e5a1eec796..46565a97f005979b3bc03a5a4555d41a8c2ac0cc 100644 (file)
@@ -189,3 +189,33 @@ pub fn test() {
         }
     }
 }
+
+mod issue_10058 {
+    pub fn test() {
+        // should not lint since we are increasing counter potentially more than once in the loop
+        let values = [0, 1, 0, 1, 1, 1, 0, 1, 0, 1];
+        let mut counter = 0;
+        for value in values {
+            counter += 1;
+
+            if value == 0 {
+                continue;
+            }
+
+            counter += 1;
+        }
+    }
+
+    pub fn test2() {
+        // should not lint since we are increasing counter potentially more than once in the loop
+        let values = [0, 1, 0, 1, 1, 1, 0, 1, 0, 1];
+        let mut counter = 0;
+        for value in values {
+            counter += 1;
+
+            if value != 0 {
+                counter += 1;
+            }
+        }
+    }
+}
index 125c9a69cd3fd1fdd48f8b7a37d7672d84f18a9a..72d635c2ccd65609ada5efc15d5197457ec4b622 100644 (file)
@@ -1,5 +1,6 @@
 // run-rustfix
 
+#![feature(type_alias_impl_trait)]
 #![warn(clippy::from_over_into)]
 #![allow(unused)]
 
@@ -81,4 +82,10 @@ fn msrv_1_41() {
     }
 }
 
+type Opaque = impl Sized;
+struct IntoOpaque;
+impl Into<Opaque> for IntoOpaque {
+    fn into(self) -> Opaque {}
+}
+
 fn main() {}
index 5aa127bfabe4b792a59ab914277c7034d7e06b2b..965f4d5d7859ee47484ccc12da79112bbc743fad 100644 (file)
@@ -1,5 +1,6 @@
 // run-rustfix
 
+#![feature(type_alias_impl_trait)]
 #![warn(clippy::from_over_into)]
 #![allow(unused)]
 
@@ -81,4 +82,10 @@ fn into(self) -> FromOverInto<T> {
     }
 }
 
+type Opaque = impl Sized;
+struct IntoOpaque;
+impl Into<Opaque> for IntoOpaque {
+    fn into(self) -> Opaque {}
+}
+
 fn main() {}
index a1764a5ea12ae8f5deef37156c803d244523c4f0..3c4d011d6fb468e735fb07c7d49a7064bad3fcc7 100644 (file)
@@ -1,5 +1,5 @@
 error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
-  --> $DIR/from_over_into.rs:9:1
+  --> $DIR/from_over_into.rs:10:1
    |
 LL | impl Into<StringWrapper> for String {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -13,7 +13,7 @@ LL ~         StringWrapper(val)
    |
 
 error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
-  --> $DIR/from_over_into.rs:17:1
+  --> $DIR/from_over_into.rs:18:1
    |
 LL | impl Into<SelfType> for String {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -26,7 +26,7 @@ LL ~         SelfType(String::new())
    |
 
 error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
-  --> $DIR/from_over_into.rs:32:1
+  --> $DIR/from_over_into.rs:33:1
    |
 LL | impl Into<SelfKeywords> for X {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -41,7 +41,7 @@ LL ~         let _: X = val;
    |
 
 error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
-  --> $DIR/from_over_into.rs:44:1
+  --> $DIR/from_over_into.rs:45:1
    |
 LL | impl core::convert::Into<bool> for crate::ExplicitPaths {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -59,7 +59,7 @@ LL ~         val.0
    |
 
 error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
-  --> $DIR/from_over_into.rs:77:5
+  --> $DIR/from_over_into.rs:78:5
    |
 LL |     impl<T> Into<FromOverInto<T>> for Vec<T> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
index e7b9a78c5dbc3e3fdf95f0aa971f8c128b672e23..cac69ef42c4136e36e5b8571b0963c62b799b11a 100644 (file)
@@ -65,7 +65,7 @@ fn main() {
     42;
     1;
     42;
-    &x;
+    x;
     x;
 
     let mut a = A(String::new());
@@ -112,6 +112,10 @@ fn main() {
     2 * { a };
     (({ a } + 4));
     1;
+
+    // Issue #9904
+    let x = 0i32;
+    let _: i32 = x;
 }
 
 pub fn decide(a: bool, b: bool) -> u32 {
index 9a435cdbb753f34dca293efde32429b27817e88f..33201aad4f641244e93af221aff06f183ac1d470 100644 (file)
@@ -112,6 +112,10 @@ fn f(_: i32) {
     2 * (0 + { a });
     1 * ({ a } + 4);
     1 * 1;
+
+    // Issue #9904
+    let x = 0i32;
+    let _: i32 = &x + 0;
 }
 
 pub fn decide(a: bool, b: bool) -> u32 {
index 1a104a20b841c1688e9412fffaf261867ef26905..3ba557d18b24433c9c57bd491ffcfb44f929e9db 100644 (file)
@@ -70,7 +70,7 @@ error: this operation has no effect
   --> $DIR/identity_op.rs:68:5
    |
 LL |     &x >> 0;
-   |     ^^^^^^^ help: consider reducing it to: `&x`
+   |     ^^^^^^^ help: consider reducing it to: `x`
 
 error: this operation has no effect
   --> $DIR/identity_op.rs:69:5
@@ -229,10 +229,16 @@ LL |     1 * 1;
    |     ^^^^^ help: consider reducing it to: `1`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:118:5
+  --> $DIR/identity_op.rs:118:18
+   |
+LL |     let _: i32 = &x + 0;
+   |                  ^^^^^^ help: consider reducing it to: `x`
+
+error: this operation has no effect
+  --> $DIR/identity_op.rs:122:5
    |
 LL |     0 + if a { 1 } else { 2 } + if b { 3 } else { 5 }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(if a { 1 } else { 2 })`
 
-error: aborting due to 39 previous errors
+error: aborting due to 40 previous errors
 
index 33770fc2a2cf9cca67a956157de5fc83599d93d2..51b1afbe5ac83ecaffe7bcca428f1ed8b08fa2bc 100644 (file)
@@ -115,4 +115,14 @@ fn main() {
     let pathbuf_ref = &pathbuf_ref;
     let _ = pathbuf_ref.to_owned(); // Don't lint. Returns `&&PathBuf`
     let _ = (**pathbuf_ref).clone();
+
+    struct NoClone;
+    impl ToOwned for NoClone {
+        type Owned = Self;
+        fn to_owned(&self) -> Self {
+            NoClone
+        }
+    }
+    let no_clone = &NoClone;
+    let _ = no_clone.to_owned();
 }
index fc896525bd2709ba82b41b56073bf8418649488e..8a9027433d95be632772e54ef97025e8e8a58df1 100644 (file)
@@ -115,4 +115,14 @@ fn main() {
     let pathbuf_ref = &pathbuf_ref;
     let _ = pathbuf_ref.to_owned(); // Don't lint. Returns `&&PathBuf`
     let _ = pathbuf_ref.to_path_buf();
+
+    struct NoClone;
+    impl ToOwned for NoClone {
+        type Owned = Self;
+        fn to_owned(&self) -> Self {
+            NoClone
+        }
+    }
+    let no_clone = &NoClone;
+    let _ = no_clone.to_owned();
 }
index 4476e0eb9220a636eb6c813ec414e661584c8c79..26abc9edb5e445f16976d94e032d33003388166d 100644 (file)
@@ -6,7 +6,7 @@
 #![allow(unconditional_panic, clippy::no_effect, clippy::unnecessary_operation)]
 
 const ARR: [i32; 2] = [1, 2];
-const REF: &i32 = &ARR[idx()]; // Ok, should not produce stderr.
+const REF: &i32 = &ARR[idx()]; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
 const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts.
 
 const fn idx() -> usize {
@@ -27,8 +27,8 @@ fn main() {
     x[3]; // Ok, should not produce stderr.
     x[const { idx() }]; // Ok, should not produce stderr.
     x[const { idx4() }]; // Ok, let rustc's `unconditional_panic` lint handle `usize` indexing on arrays.
-    const { &ARR[idx()] }; // Ok, should not produce stderr.
-    const { &ARR[idx4()] }; // Ok, let rustc handle const contexts.
+    const { &ARR[idx()] }; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
+    const { &ARR[idx4()] }; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
 
     let y = &x;
     y[0]; // Ok, referencing shouldn't affect this lint. See the issue 6021
index d8b6e3f1262b735345660276aa3456cb759aad52..8fd77913a3fd97626ed617357380b578ab13ef1c 100644 (file)
@@ -1,13 +1,32 @@
+error: indexing may panic
+  --> $DIR/indexing_slicing_index.rs:9:20
+   |
+LL | const REF: &i32 = &ARR[idx()]; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
+   |                    ^^^^^^^^^^
+   |
+   = help: consider using `.get(n)` or `.get_mut(n)` instead
+   = note: the suggestion might not be applicable in constant blocks
+   = note: `-D clippy::indexing-slicing` implied by `-D warnings`
+
+error: indexing may panic
+  --> $DIR/indexing_slicing_index.rs:10:24
+   |
+LL | const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts.
+   |                        ^^^^^^^^^^^
+   |
+   = help: consider using `.get(n)` or `.get_mut(n)` instead
+   = note: the suggestion might not be applicable in constant blocks
+
 error[E0080]: evaluation of `main::{constant#3}` failed
   --> $DIR/indexing_slicing_index.rs:31:14
    |
-LL |     const { &ARR[idx4()] }; // Ok, let rustc handle const contexts.
+LL |     const { &ARR[idx4()] }; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
    |              ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4
 
 note: erroneous constant used
   --> $DIR/indexing_slicing_index.rs:31:5
    |
-LL |     const { &ARR[idx4()] }; // Ok, let rustc handle const contexts.
+LL |     const { &ARR[idx4()] }; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error: indexing may panic
@@ -17,7 +36,24 @@ LL |     x[index];
    |     ^^^^^^^^
    |
    = help: consider using `.get(n)` or `.get_mut(n)` instead
-   = note: `-D clippy::indexing-slicing` implied by `-D warnings`
+
+error: indexing may panic
+  --> $DIR/indexing_slicing_index.rs:30:14
+   |
+LL |     const { &ARR[idx()] }; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
+   |              ^^^^^^^^^^
+   |
+   = help: consider using `.get(n)` or `.get_mut(n)` instead
+   = note: the suggestion might not be applicable in constant blocks
+
+error: indexing may panic
+  --> $DIR/indexing_slicing_index.rs:31:14
+   |
+LL |     const { &ARR[idx4()] }; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
+   |              ^^^^^^^^^^^
+   |
+   = help: consider using `.get(n)` or `.get_mut(n)` instead
+   = note: the suggestion might not be applicable in constant blocks
 
 error: indexing may panic
   --> $DIR/indexing_slicing_index.rs:38:5
@@ -65,6 +101,6 @@ error[E0080]: evaluation of constant value failed
 LL | const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts.
    |                        ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4
 
-error: aborting due to 8 previous errors
+error: aborting due to 12 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
index 1f3b8ac99b19146f766e6758d0cd799d37dc92c0..c1c0b5ae40f6170b4b9d4daa0dd5424f661b8fa7 100644 (file)
@@ -3,6 +3,9 @@
 #![warn(clippy::len_zero)]
 #![allow(dead_code, unused, clippy::len_without_is_empty)]
 
+extern crate core;
+use core::ops::Deref;
+
 pub struct One;
 struct Wither;
 
@@ -56,6 +59,26 @@ impl WithIsEmpty for Wither {
     }
 }
 
+struct DerefToDerefToString;
+
+impl Deref for DerefToDerefToString {
+    type Target = DerefToString;
+
+    fn deref(&self) -> &Self::Target {
+        &DerefToString {}
+    }
+}
+
+struct DerefToString;
+
+impl Deref for DerefToString {
+    type Target = str;
+
+    fn deref(&self) -> &Self::Target {
+        "Hello, world!"
+    }
+}
+
 fn main() {
     let x = [1, 2];
     if x.is_empty() {
@@ -64,6 +87,23 @@ fn main() {
 
     if "".is_empty() {}
 
+    let s = "Hello, world!";
+    let s1 = &s;
+    let s2 = &s1;
+    let s3 = &s2;
+    let s4 = &s3;
+    let s5 = &s4;
+    let s6 = &s5;
+    println!("{}", s1.is_empty());
+    println!("{}", s2.is_empty());
+    println!("{}", s3.is_empty());
+    println!("{}", s4.is_empty());
+    println!("{}", s5.is_empty());
+    println!("{}", (s6).is_empty());
+
+    let d2s = DerefToDerefToString {};
+    println!("{}", (**d2s).is_empty());
+
     let y = One;
     if y.len() == 0 {
         // No error; `One` does not have `.is_empty()`.
index dc21de0001b6c76eb2f57cdba4e7416319d5b756..cc2eb05b6bfd2ee81c35ea7754118532dd5f7ab9 100644 (file)
@@ -3,6 +3,9 @@
 #![warn(clippy::len_zero)]
 #![allow(dead_code, unused, clippy::len_without_is_empty)]
 
+extern crate core;
+use core::ops::Deref;
+
 pub struct One;
 struct Wither;
 
@@ -56,6 +59,26 @@ fn is_empty(&self) -> bool {
     }
 }
 
+struct DerefToDerefToString;
+
+impl Deref for DerefToDerefToString {
+    type Target = DerefToString;
+
+    fn deref(&self) -> &Self::Target {
+        &DerefToString {}
+    }
+}
+
+struct DerefToString;
+
+impl Deref for DerefToString {
+    type Target = str;
+
+    fn deref(&self) -> &Self::Target {
+        "Hello, world!"
+    }
+}
+
 fn main() {
     let x = [1, 2];
     if x.len() == 0 {
@@ -64,6 +87,23 @@ fn main() {
 
     if "".len() == 0 {}
 
+    let s = "Hello, world!";
+    let s1 = &s;
+    let s2 = &s1;
+    let s3 = &s2;
+    let s4 = &s3;
+    let s5 = &s4;
+    let s6 = &s5;
+    println!("{}", *s1 == "");
+    println!("{}", **s2 == "");
+    println!("{}", ***s3 == "");
+    println!("{}", ****s4 == "");
+    println!("{}", *****s5 == "");
+    println!("{}", ******(s6) == "");
+
+    let d2s = DerefToDerefToString {};
+    println!("{}", &**d2s == "");
+
     let y = One;
     if y.len() == 0 {
         // No error; `One` does not have `.is_empty()`.
index 6c71f1beeac67c27a89916538cbdfcc2af70d896..b6f13780253c2e526533179cc5602c0ff557f68a 100644 (file)
@@ -1,5 +1,5 @@
 error: length comparison to zero
-  --> $DIR/len_zero.rs:61:8
+  --> $DIR/len_zero.rs:84:8
    |
 LL |     if x.len() == 0 {
    |        ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `x.is_empty()`
@@ -7,82 +7,126 @@ LL |     if x.len() == 0 {
    = note: `-D clippy::len-zero` implied by `-D warnings`
 
 error: length comparison to zero
-  --> $DIR/len_zero.rs:65:8
+  --> $DIR/len_zero.rs:88:8
    |
 LL |     if "".len() == 0 {}
    |        ^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `"".is_empty()`
 
+error: comparison to empty slice
+  --> $DIR/len_zero.rs:97:20
+   |
+LL |     println!("{}", *s1 == "");
+   |                    ^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s1.is_empty()`
+   |
+   = note: `-D clippy::comparison-to-empty` implied by `-D warnings`
+
+error: comparison to empty slice
+  --> $DIR/len_zero.rs:98:20
+   |
+LL |     println!("{}", **s2 == "");
+   |                    ^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s2.is_empty()`
+
+error: comparison to empty slice
+  --> $DIR/len_zero.rs:99:20
+   |
+LL |     println!("{}", ***s3 == "");
+   |                    ^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s3.is_empty()`
+
+error: comparison to empty slice
+  --> $DIR/len_zero.rs:100:20
+   |
+LL |     println!("{}", ****s4 == "");
+   |                    ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s4.is_empty()`
+
+error: comparison to empty slice
+  --> $DIR/len_zero.rs:101:20
+   |
+LL |     println!("{}", *****s5 == "");
+   |                    ^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s5.is_empty()`
+
+error: comparison to empty slice
+  --> $DIR/len_zero.rs:102:20
+   |
+LL |     println!("{}", ******(s6) == "");
+   |                    ^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `(s6).is_empty()`
+
+error: comparison to empty slice
+  --> $DIR/len_zero.rs:105:20
+   |
+LL |     println!("{}", &**d2s == "");
+   |                    ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `(**d2s).is_empty()`
+
 error: length comparison to zero
-  --> $DIR/len_zero.rs:80:8
+  --> $DIR/len_zero.rs:120:8
    |
 LL |     if has_is_empty.len() == 0 {
    |        ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()`
 
 error: length comparison to zero
-  --> $DIR/len_zero.rs:83:8
+  --> $DIR/len_zero.rs:123:8
    |
 LL |     if has_is_empty.len() != 0 {
    |        ^^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()`
 
 error: length comparison to zero
-  --> $DIR/len_zero.rs:86:8
+  --> $DIR/len_zero.rs:126:8
    |
 LL |     if has_is_empty.len() > 0 {
    |        ^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()`
 
 error: length comparison to one
-  --> $DIR/len_zero.rs:89:8
+  --> $DIR/len_zero.rs:129:8
    |
 LL |     if has_is_empty.len() < 1 {
    |        ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()`
 
 error: length comparison to one
-  --> $DIR/len_zero.rs:92:8
+  --> $DIR/len_zero.rs:132:8
    |
 LL |     if has_is_empty.len() >= 1 {
    |        ^^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()`
 
 error: length comparison to zero
-  --> $DIR/len_zero.rs:103:8
+  --> $DIR/len_zero.rs:143:8
    |
 LL |     if 0 == has_is_empty.len() {
    |        ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()`
 
 error: length comparison to zero
-  --> $DIR/len_zero.rs:106:8
+  --> $DIR/len_zero.rs:146:8
    |
 LL |     if 0 != has_is_empty.len() {
    |        ^^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()`
 
 error: length comparison to zero
-  --> $DIR/len_zero.rs:109:8
+  --> $DIR/len_zero.rs:149:8
    |
 LL |     if 0 < has_is_empty.len() {
    |        ^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()`
 
 error: length comparison to one
-  --> $DIR/len_zero.rs:112:8
+  --> $DIR/len_zero.rs:152:8
    |
 LL |     if 1 <= has_is_empty.len() {
    |        ^^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()`
 
 error: length comparison to one
-  --> $DIR/len_zero.rs:115:8
+  --> $DIR/len_zero.rs:155:8
    |
 LL |     if 1 > has_is_empty.len() {
    |        ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()`
 
 error: length comparison to zero
-  --> $DIR/len_zero.rs:129:8
+  --> $DIR/len_zero.rs:169:8
    |
 LL |     if with_is_empty.len() == 0 {
    |        ^^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `with_is_empty.is_empty()`
 
 error: length comparison to zero
-  --> $DIR/len_zero.rs:142:8
+  --> $DIR/len_zero.rs:182:8
    |
 LL |     if b.len() != 0 {}
    |        ^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!b.is_empty()`
 
-error: aborting due to 14 previous errors
+error: aborting due to 21 previous errors
 
index c9a819ba535449a1b8d90b2324204f74b318a585..638320dd6eec439a76ea745736dd2b7fcfd1672f 100644 (file)
@@ -62,6 +62,11 @@ fn main() {
         panic!("panic5");
     }
     assert!(!a.is_empty(), "with expansion {}", one!());
+    if a.is_empty() {
+        let _ = 0;
+    } else if a.len() == 1 {
+        panic!("panic6");
+    }
 }
 
 fn issue7730(a: u8) {
index 2f62de51cadcd948a98c0b75668aa2f13c6b4a92..8c7e919bf62a10d52bc6a343454b438f89c8857b 100644 (file)
@@ -50,6 +50,11 @@ fn main() {
     assert!(!(b.is_empty() || a.is_empty()), "panic4");
     assert!(!(a.is_empty() || !b.is_empty()), "panic5");
     assert!(!a.is_empty(), "with expansion {}", one!());
+    if a.is_empty() {
+        let _ = 0;
+    } else if a.len() == 1 {
+        panic!("panic6");
+    }
 }
 
 fn issue7730(a: u8) {
index 237638ee1344c60274bb31c1accbcf7f7456cee3..3555ac29243a1cb0d819a368d8bb22bf02aea2de 100644 (file)
@@ -65,7 +65,7 @@ LL | |     }
    | |_____^ help: try instead: `assert!(!a.is_empty(), "with expansion {}", one!());`
 
 error: only a `panic!` in `if`-then statement
-  --> $DIR/manual_assert.rs:73:5
+  --> $DIR/manual_assert.rs:78:5
    |
 LL | /     if a > 2 {
 LL | |         // comment
index 6a4cc2468d4193815b6b43299db873b95d8fb33d..f037c5b8405c721cc6755b1874cf5d47f229206b 100644 (file)
@@ -66,6 +66,11 @@ fn main() {
     if a.is_empty() {
         panic!("with expansion {}", one!())
     }
+    if a.is_empty() {
+        let _ = 0;
+    } else if a.len() == 1 {
+        panic!("panic6");
+    }
 }
 
 fn issue7730(a: u8) {
index 231ba83b1426130a3b6482d8e9cb938aacfced4d..5b2b44c2fdb2bbaa6c960d482f36e051616267fe 100644 (file)
@@ -15,6 +15,19 @@ fn main() {
     assert!('x'.is_ascii_alphabetic());
 
     assert!(matches!('x', 'A'..='Z' | 'a'..='z' | '_'));
+
+    b'0'.is_ascii_digit();
+    b'a'.is_ascii_lowercase();
+    b'A'.is_ascii_uppercase();
+
+    '0'.is_ascii_digit();
+    'a'.is_ascii_lowercase();
+    'A'.is_ascii_uppercase();
+
+    let cool_letter = &'g';
+    cool_letter.is_ascii_digit();
+    cool_letter.is_ascii_lowercase();
+    cool_letter.is_ascii_uppercase();
 }
 
 #[clippy::msrv = "1.23"]
index 39ee6151c56f08ff53b77377e9eb916b437d00a6..c9433f33a1b6f3891e47a391ad150a784c2bc0db 100644 (file)
@@ -15,6 +15,19 @@ fn main() {
     assert!(matches!('x', 'A'..='Z' | 'a'..='z'));
 
     assert!(matches!('x', 'A'..='Z' | 'a'..='z' | '_'));
+
+    (b'0'..=b'9').contains(&b'0');
+    (b'a'..=b'z').contains(&b'a');
+    (b'A'..=b'Z').contains(&b'A');
+
+    ('0'..='9').contains(&'0');
+    ('a'..='z').contains(&'a');
+    ('A'..='Z').contains(&'A');
+
+    let cool_letter = &'g';
+    ('0'..='9').contains(cool_letter);
+    ('a'..='z').contains(cool_letter);
+    ('A'..='Z').contains(cool_letter);
 }
 
 #[clippy::msrv = "1.23"]
index 397cbe05c822ad7fba97b5f46d02fd569e2882fe..ee60188506d6fc08182a897d47a9d3c7ca290aa4 100644 (file)
@@ -43,28 +43,82 @@ LL |     assert!(matches!('x', 'A'..='Z' | 'a'..='z'));
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_alphabetic()`
 
 error: manual check for common ascii range
-  --> $DIR/manual_is_ascii_check.rs:29:13
+  --> $DIR/manual_is_ascii_check.rs:19:5
+   |
+LL |     (b'0'..=b'9').contains(&b'0');
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'0'.is_ascii_digit()`
+
+error: manual check for common ascii range
+  --> $DIR/manual_is_ascii_check.rs:20:5
+   |
+LL |     (b'a'..=b'z').contains(&b'a');
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'a'.is_ascii_lowercase()`
+
+error: manual check for common ascii range
+  --> $DIR/manual_is_ascii_check.rs:21:5
+   |
+LL |     (b'A'..=b'Z').contains(&b'A');
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'A'.is_ascii_uppercase()`
+
+error: manual check for common ascii range
+  --> $DIR/manual_is_ascii_check.rs:23:5
+   |
+LL |     ('0'..='9').contains(&'0');
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'0'.is_ascii_digit()`
+
+error: manual check for common ascii range
+  --> $DIR/manual_is_ascii_check.rs:24:5
+   |
+LL |     ('a'..='z').contains(&'a');
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'a'.is_ascii_lowercase()`
+
+error: manual check for common ascii range
+  --> $DIR/manual_is_ascii_check.rs:25:5
+   |
+LL |     ('A'..='Z').contains(&'A');
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'A'.is_ascii_uppercase()`
+
+error: manual check for common ascii range
+  --> $DIR/manual_is_ascii_check.rs:28:5
+   |
+LL |     ('0'..='9').contains(cool_letter);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cool_letter.is_ascii_digit()`
+
+error: manual check for common ascii range
+  --> $DIR/manual_is_ascii_check.rs:29:5
+   |
+LL |     ('a'..='z').contains(cool_letter);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cool_letter.is_ascii_lowercase()`
+
+error: manual check for common ascii range
+  --> $DIR/manual_is_ascii_check.rs:30:5
+   |
+LL |     ('A'..='Z').contains(cool_letter);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cool_letter.is_ascii_uppercase()`
+
+error: manual check for common ascii range
+  --> $DIR/manual_is_ascii_check.rs:42:13
    |
 LL |     assert!(matches!(b'1', b'0'..=b'9'));
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'1'.is_ascii_digit()`
 
 error: manual check for common ascii range
-  --> $DIR/manual_is_ascii_check.rs:30:13
+  --> $DIR/manual_is_ascii_check.rs:43:13
    |
 LL |     assert!(matches!('X', 'A'..='Z'));
    |             ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'X'.is_ascii_uppercase()`
 
 error: manual check for common ascii range
-  --> $DIR/manual_is_ascii_check.rs:31:13
+  --> $DIR/manual_is_ascii_check.rs:44:13
    |
 LL |     assert!(matches!('x', 'A'..='Z' | 'a'..='z'));
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_alphabetic()`
 
 error: manual check for common ascii range
-  --> $DIR/manual_is_ascii_check.rs:41:23
+  --> $DIR/manual_is_ascii_check.rs:54:23
    |
 LL |     const FOO: bool = matches!('x', '0'..='9');
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_digit()`
 
-error: aborting due to 11 previous errors
+error: aborting due to 20 previous errors
 
index 93c86ca24fea3a079c80c8ae7bb32204b29f6be3..28caed9d79df244f074eab27b108794139ca3ac2 100644 (file)
@@ -64,6 +64,13 @@ fn fire() {
         Ok(v) => v,
         Err(()) => return,
     };
+
+    let f = Variant::Bar(1);
+
+    let _value = match f {
+        Variant::Bar(_) | Variant::Baz(_) => (),
+        _ => return,
+    };
 }
 
 fn not_fire() {
index 38be5ac54547368b7fe98d336a1da5acc2e85db7..cd5e9a9ac39c0770fcd41351097e381cfe0f6ec4 100644 (file)
@@ -25,7 +25,7 @@ LL | /         let v = match h() {
 LL | |             (Some(_), Some(_)) | (None, None) => continue,
 LL | |             (Some(v), None) | (None, Some(v)) => v,
 LL | |         };
-   | |__________^ help: consider writing: `let (Some(v), None) | (None, Some(v)) = h() else { continue };`
+   | |__________^ help: consider writing: `let ((Some(v), None) | (None, Some(v))) = h() else { continue };`
 
 error: this could be rewritten as `let...else`
   --> $DIR/manual_let_else_match.rs:49:9
@@ -34,7 +34,7 @@ LL | /         let v = match build_enum() {
 LL | |             _ => continue,
 LL | |             Variant::Bar(v) | Variant::Baz(v) => v,
 LL | |         };
-   | |__________^ help: consider writing: `let Variant::Bar(v) | Variant::Baz(v) = build_enum() else { continue };`
+   | |__________^ help: consider writing: `let (Variant::Bar(v) | Variant::Baz(v)) = build_enum() else { continue };`
 
 error: this could be rewritten as `let...else`
   --> $DIR/manual_let_else_match.rs:57:5
@@ -54,5 +54,14 @@ LL | |         Err(()) => return,
 LL | |     };
    | |______^ help: consider writing: `let Ok(v) = f().map_err(|_| ()) else { return };`
 
-error: aborting due to 6 previous errors
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else_match.rs:70:5
+   |
+LL | /     let _value = match f {
+LL | |         Variant::Bar(_) | Variant::Baz(_) => (),
+LL | |         _ => return,
+LL | |     };
+   | |______^ help: consider writing: `let (Variant::Bar(_) | Variant::Baz(_)) = f else { return };`
+
+error: aborting due to 7 previous errors
 
index 1bd75c806bc94378acadd7f86e5bc533de7548e1..f11330a8916d4adf2ba241ef4495ef772d8fcdf0 100644 (file)
@@ -2,7 +2,7 @@
 // edition:2018
 
 #![warn(clippy::needless_parens_on_range_literals)]
-#![allow(clippy::almost_complete_letter_range)]
+#![allow(clippy::almost_complete_range)]
 
 fn main() {
     let _ = 'a'..='z';
index 7abb8a1adc1bcc4f0178599adc3391c748f73f5b..671c0009e23b7d5b60d8f70f3b6abd5a94dc79cf 100644 (file)
@@ -2,7 +2,7 @@
 // edition:2018
 
 #![warn(clippy::needless_parens_on_range_literals)]
-#![allow(clippy::almost_complete_letter_range)]
+#![allow(clippy::almost_complete_range)]
 
 fn main() {
     let _ = ('a')..=('z');
index f69982d63a898d17ba3b9f6ff417c42ea8442bd8..beec42f08bb05666df617799cc1b4068abfcdb75 100644 (file)
@@ -1,3 +1,4 @@
+#![feature(type_alias_impl_trait)]
 #![warn(clippy::new_ret_no_self)]
 #![allow(dead_code)]
 
@@ -400,3 +401,25 @@ fn new<'b: 'a>(s: &'b str) -> impl Into<RetImplTraitSelfAdt<'b>> {
         }
     }
 }
+
+mod issue10041 {
+    struct Bomb;
+
+    impl Bomb {
+        // Hidden <Rhs = Self> default generic paramter.
+        pub fn new() -> impl PartialOrd {
+            0i32
+        }
+    }
+
+    // TAIT with self-referencing bounds
+    type X = impl std::ops::Add<Output = X>;
+
+    struct Bomb2;
+
+    impl Bomb2 {
+        pub fn new() -> X {
+            0i32
+        }
+    }
+}
index bc13be47927b1c3fa37a75795a316f5c521319ac..2eaebfb5cac50041df6bc18f6c2a78bb79017691 100644 (file)
@@ -1,5 +1,5 @@
 error: methods called `new` usually return `Self`
-  --> $DIR/new_ret_no_self.rs:49:5
+  --> $DIR/new_ret_no_self.rs:50:5
    |
 LL | /     pub fn new(_: String) -> impl R<Item = u32> {
 LL | |         S3
@@ -9,7 +9,7 @@ LL | |     }
    = note: `-D clippy::new-ret-no-self` implied by `-D warnings`
 
 error: methods called `new` usually return `Self`
-  --> $DIR/new_ret_no_self.rs:81:5
+  --> $DIR/new_ret_no_self.rs:82:5
    |
 LL | /     pub fn new() -> u32 {
 LL | |         unimplemented!();
@@ -17,7 +17,7 @@ LL | |     }
    | |_____^
 
 error: methods called `new` usually return `Self`
-  --> $DIR/new_ret_no_self.rs:90:5
+  --> $DIR/new_ret_no_self.rs:91:5
    |
 LL | /     pub fn new(_: String) -> u32 {
 LL | |         unimplemented!();
@@ -25,7 +25,7 @@ LL | |     }
    | |_____^
 
 error: methods called `new` usually return `Self`
-  --> $DIR/new_ret_no_self.rs:126:5
+  --> $DIR/new_ret_no_self.rs:127:5
    |
 LL | /     pub fn new() -> (u32, u32) {
 LL | |         unimplemented!();
@@ -33,7 +33,7 @@ LL | |     }
    | |_____^
 
 error: methods called `new` usually return `Self`
-  --> $DIR/new_ret_no_self.rs:153:5
+  --> $DIR/new_ret_no_self.rs:154:5
    |
 LL | /     pub fn new() -> *mut V {
 LL | |         unimplemented!();
@@ -41,7 +41,7 @@ LL | |     }
    | |_____^
 
 error: methods called `new` usually return `Self`
-  --> $DIR/new_ret_no_self.rs:171:5
+  --> $DIR/new_ret_no_self.rs:172:5
    |
 LL | /     pub fn new() -> Option<u32> {
 LL | |         unimplemented!();
@@ -49,19 +49,19 @@ LL | |     }
    | |_____^
 
 error: methods called `new` usually return `Self`
-  --> $DIR/new_ret_no_self.rs:224:9
+  --> $DIR/new_ret_no_self.rs:225:9
    |
 LL |         fn new() -> String;
    |         ^^^^^^^^^^^^^^^^^^^
 
 error: methods called `new` usually return `Self`
-  --> $DIR/new_ret_no_self.rs:236:9
+  --> $DIR/new_ret_no_self.rs:237:9
    |
 LL |         fn new(_: String) -> String;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: methods called `new` usually return `Self`
-  --> $DIR/new_ret_no_self.rs:271:9
+  --> $DIR/new_ret_no_self.rs:272:9
    |
 LL | /         fn new() -> (u32, u32) {
 LL | |             unimplemented!();
@@ -69,7 +69,7 @@ LL | |         }
    | |_________^
 
 error: methods called `new` usually return `Self`
-  --> $DIR/new_ret_no_self.rs:298:9
+  --> $DIR/new_ret_no_self.rs:299:9
    |
 LL | /         fn new() -> *mut V {
 LL | |             unimplemented!();
@@ -77,7 +77,7 @@ LL | |         }
    | |_________^
 
 error: methods called `new` usually return `Self`
-  --> $DIR/new_ret_no_self.rs:368:9
+  --> $DIR/new_ret_no_self.rs:369:9
    |
 LL | /         fn new(t: T) -> impl Into<i32> {
 LL | |             1
@@ -85,12 +85,28 @@ LL | |         }
    | |_________^
 
 error: methods called `new` usually return `Self`
-  --> $DIR/new_ret_no_self.rs:389:9
+  --> $DIR/new_ret_no_self.rs:390:9
    |
 LL | /         fn new(t: T) -> impl Trait2<(), i32> {
 LL | |             unimplemented!()
 LL | |         }
    | |_________^
 
-error: aborting due to 12 previous errors
+error: methods called `new` usually return `Self`
+  --> $DIR/new_ret_no_self.rs:410:9
+   |
+LL | /         pub fn new() -> impl PartialOrd {
+LL | |             0i32
+LL | |         }
+   | |_________^
+
+error: methods called `new` usually return `Self`
+  --> $DIR/new_ret_no_self.rs:421:9
+   |
+LL | /         pub fn new() -> X {
+LL | |             0i32
+LL | |         }
+   | |_________^
+
+error: aborting due to 14 previous errors
 
index 4c5846fe837eaa8a68ed10ad585271923f0f6588..bca777a890c3b249c2f0ae7bbf61c099a2d0705e 100644 (file)
@@ -39,8 +39,14 @@ static STATIC_VAR_TUPLE: &(u8, u8) = &(1, 2); // ERROR Consider removing 'static
 
 static STATIC_VAR_ARRAY: &[u8; 1] = b"T"; // ERROR Consider removing 'static.
 
+static mut STATIC_MUT_SLICE: &mut [u32] = &mut [0];
+
 fn main() {
     let false_positive: &'static str = "test";
+
+    unsafe {
+        STATIC_MUT_SLICE[0] = 0;
+    }
 }
 
 trait Bar {
index 64a66be1a83c753ff8a786167759fd4f04ea52ef..afe7644816d2e4f0420d04d1547c3080f45d984b 100644 (file)
 
 static STATIC_VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static.
 
+static mut STATIC_MUT_SLICE: &'static mut [u32] = &mut [0];
+
 fn main() {
     let false_positive: &'static str = "test";
+
+    unsafe {
+        STATIC_MUT_SLICE[0] = 0;
+    }
 }
 
 trait Bar {
index 0938ebf783ff16888852e0be386dc22c86f1c254..b2cbd2d9d01b0350e7f31710c9fdec05f2cfc6ce 100644 (file)
@@ -97,10 +97,16 @@ LL | static STATIC_VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removin
    |                          -^^^^^^^-------- help: consider removing `'static`: `&[u8; 1]`
 
 error: statics have by default a `'static` lifetime
-  --> $DIR/redundant_static_lifetimes.rs:65:16
+  --> $DIR/redundant_static_lifetimes.rs:42:31
+   |
+LL | static mut STATIC_MUT_SLICE: &'static mut [u32] = &mut [0];
+   |                              -^^^^^^^---------- help: consider removing `'static`: `&mut [u32]`
+
+error: statics have by default a `'static` lifetime
+  --> $DIR/redundant_static_lifetimes.rs:71:16
    |
 LL |     static V: &'static u8 = &17;
    |               -^^^^^^^--- help: consider removing `'static`: `&u8`
 
-error: aborting due to 17 previous errors
+error: aborting due to 18 previous errors
 
index 689928f0479468fb8c0305b11d1299e01fd4f4ca..2f76b57529607a14ed3165dea40c3ddf0dd9975d 100644 (file)
@@ -4,6 +4,7 @@
 
 // run-rustfix
 
+#![allow(clippy::almost_complete_range)]
 #![allow(clippy::disallowed_names)]
 #![allow(clippy::blocks_in_if_conditions)]
 #![allow(clippy::box_collection)]
@@ -37,6 +38,7 @@
 #![allow(temporary_cstring_as_ptr)]
 #![allow(unknown_lints)]
 #![allow(unused_labels)]
+#![warn(clippy::almost_complete_range)]
 #![warn(clippy::disallowed_names)]
 #![warn(clippy::blocks_in_if_conditions)]
 #![warn(clippy::blocks_in_if_conditions)]
index b74aa650ffd475946adc1f595d0e2d21b4d0fa15..699c0ff464e9fb247989fd0b559c8a35576b63f4 100644 (file)
@@ -4,6 +4,7 @@
 
 // run-rustfix
 
+#![allow(clippy::almost_complete_range)]
 #![allow(clippy::disallowed_names)]
 #![allow(clippy::blocks_in_if_conditions)]
 #![allow(clippy::box_collection)]
@@ -37,6 +38,7 @@
 #![allow(temporary_cstring_as_ptr)]
 #![allow(unknown_lints)]
 #![allow(unused_labels)]
+#![warn(clippy::almost_complete_letter_range)]
 #![warn(clippy::blacklisted_name)]
 #![warn(clippy::block_in_if_condition_expr)]
 #![warn(clippy::block_in_if_condition_stmt)]
index 622a32c5908aeaa3689041a42a6fa6e6f8920be7..9af58dc75a68f41daff7f88a050856295b19ec29 100644 (file)
+error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range`
+  --> $DIR/rename.rs:41:9
+   |
+LL | #![warn(clippy::almost_complete_letter_range)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range`
+   |
+   = note: `-D renamed-and-removed-lints` implied by `-D warnings`
+
 error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
-  --> $DIR/rename.rs:40:9
+  --> $DIR/rename.rs:42:9
    |
 LL | #![warn(clippy::blacklisted_name)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names`
-   |
-   = note: `-D renamed-and-removed-lints` implied by `-D warnings`
 
 error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions`
-  --> $DIR/rename.rs:41:9
+  --> $DIR/rename.rs:43:9
    |
 LL | #![warn(clippy::block_in_if_condition_expr)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
 
 error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions`
-  --> $DIR/rename.rs:42:9
+  --> $DIR/rename.rs:44:9
    |
 LL | #![warn(clippy::block_in_if_condition_stmt)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
 
 error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
-  --> $DIR/rename.rs:43:9
+  --> $DIR/rename.rs:45:9
    |
 LL | #![warn(clippy::box_vec)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
 
 error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
-  --> $DIR/rename.rs:44:9
+  --> $DIR/rename.rs:46:9
    |
 LL | #![warn(clippy::const_static_lifetime)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
 
 error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity`
-  --> $DIR/rename.rs:45:9
+  --> $DIR/rename.rs:47:9
    |
 LL | #![warn(clippy::cyclomatic_complexity)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
 
 error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods`
-  --> $DIR/rename.rs:46:9
+  --> $DIR/rename.rs:48:9
    |
 LL | #![warn(clippy::disallowed_method)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods`
 
 error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types`
-  --> $DIR/rename.rs:47:9
+  --> $DIR/rename.rs:49:9
    |
 LL | #![warn(clippy::disallowed_type)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types`
 
 error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression`
-  --> $DIR/rename.rs:48:9
+  --> $DIR/rename.rs:50:9
    |
 LL | #![warn(clippy::eval_order_dependence)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
 
 error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
-  --> $DIR/rename.rs:49:9
+  --> $DIR/rename.rs:51:9
    |
 LL | #![warn(clippy::identity_conversion)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
 
 error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
-  --> $DIR/rename.rs:50:9
+  --> $DIR/rename.rs:52:9
    |
 LL | #![warn(clippy::if_let_some_result)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
 
 error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
-  --> $DIR/rename.rs:51:9
+  --> $DIR/rename.rs:53:9
    |
 LL | #![warn(clippy::logic_bug)]
    |         ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr`
 
 error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
-  --> $DIR/rename.rs:52:9
+  --> $DIR/rename.rs:54:9
    |
 LL | #![warn(clippy::new_without_default_derive)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
 
 error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
-  --> $DIR/rename.rs:53:9
+  --> $DIR/rename.rs:55:9
    |
 LL | #![warn(clippy::option_and_then_some)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
 
 error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
-  --> $DIR/rename.rs:54:9
+  --> $DIR/rename.rs:56:9
    |
 LL | #![warn(clippy::option_expect_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
 
 error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:55:9
+  --> $DIR/rename.rs:57:9
    |
 LL | #![warn(clippy::option_map_unwrap_or)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:56:9
+  --> $DIR/rename.rs:58:9
    |
 LL | #![warn(clippy::option_map_unwrap_or_else)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
-  --> $DIR/rename.rs:57:9
+  --> $DIR/rename.rs:59:9
    |
 LL | #![warn(clippy::option_unwrap_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
 
 error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow`
-  --> $DIR/rename.rs:58:9
+  --> $DIR/rename.rs:60:9
    |
 LL | #![warn(clippy::ref_in_deref)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
 
 error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
-  --> $DIR/rename.rs:59:9
+  --> $DIR/rename.rs:61:9
    |
 LL | #![warn(clippy::result_expect_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
 
 error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:60:9
+  --> $DIR/rename.rs:62:9
    |
 LL | #![warn(clippy::result_map_unwrap_or_else)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
-  --> $DIR/rename.rs:61:9
+  --> $DIR/rename.rs:63:9
    |
 LL | #![warn(clippy::result_unwrap_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
 
 error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
-  --> $DIR/rename.rs:62:9
+  --> $DIR/rename.rs:64:9
    |
 LL | #![warn(clippy::single_char_push_str)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
 
 error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
-  --> $DIR/rename.rs:63:9
+  --> $DIR/rename.rs:65:9
    |
 LL | #![warn(clippy::stutter)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
 
 error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl`
-  --> $DIR/rename.rs:64:9
+  --> $DIR/rename.rs:66:9
    |
 LL | #![warn(clippy::to_string_in_display)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl`
 
 error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
-  --> $DIR/rename.rs:65:9
+  --> $DIR/rename.rs:67:9
    |
 LL | #![warn(clippy::zero_width_space)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
 
 error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
-  --> $DIR/rename.rs:66:9
+  --> $DIR/rename.rs:68:9
    |
 LL | #![warn(clippy::drop_bounds)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
 
 error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:67:9
+  --> $DIR/rename.rs:69:9
    |
 LL | #![warn(clippy::for_loop_over_option)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:68:9
+  --> $DIR/rename.rs:70:9
    |
 LL | #![warn(clippy::for_loop_over_result)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:69:9
+  --> $DIR/rename.rs:71:9
    |
 LL | #![warn(clippy::for_loops_over_fallibles)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
-  --> $DIR/rename.rs:70:9
+  --> $DIR/rename.rs:72:9
    |
 LL | #![warn(clippy::into_iter_on_array)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
 
 error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
-  --> $DIR/rename.rs:71:9
+  --> $DIR/rename.rs:73:9
    |
 LL | #![warn(clippy::invalid_atomic_ordering)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
 
 error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
-  --> $DIR/rename.rs:72:9
+  --> $DIR/rename.rs:74:9
    |
 LL | #![warn(clippy::invalid_ref)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
 
 error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
-  --> $DIR/rename.rs:73:9
+  --> $DIR/rename.rs:75:9
    |
 LL | #![warn(clippy::let_underscore_drop)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop`
 
 error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
-  --> $DIR/rename.rs:74:9
+  --> $DIR/rename.rs:76:9
    |
 LL | #![warn(clippy::mem_discriminant_non_enum)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
 
 error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
-  --> $DIR/rename.rs:75:9
+  --> $DIR/rename.rs:77:9
    |
 LL | #![warn(clippy::panic_params)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
 
 error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally`
-  --> $DIR/rename.rs:76:9
+  --> $DIR/rename.rs:78:9
    |
 LL | #![warn(clippy::positional_named_format_parameters)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
 
 error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
-  --> $DIR/rename.rs:77:9
+  --> $DIR/rename.rs:79:9
    |
 LL | #![warn(clippy::temporary_cstring_as_ptr)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
 
 error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
-  --> $DIR/rename.rs:78:9
+  --> $DIR/rename.rs:80:9
    |
 LL | #![warn(clippy::unknown_clippy_lints)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
 
 error: lint `clippy::unused_label` has been renamed to `unused_labels`
-  --> $DIR/rename.rs:79:9
+  --> $DIR/rename.rs:81:9
    |
 LL | #![warn(clippy::unused_label)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
 
-error: aborting due to 40 previous errors
+error: aborting due to 41 previous errors
 
index 9d0d1124c460ed45b1b5894bd3878b18d15def72..713cff604a1d7d6028c367f5efcf2e4c2de552fb 100644 (file)
@@ -70,6 +70,12 @@ fn seek_to_end<T: Seek>(t: &mut T) {
     t.seek(SeekFrom::End(0));
 }
 
+// This should NOT trigger clippy warning because
+// expr is used here
+fn seek_to_start_in_let<T: Seek>(t: &mut T) {
+    let a = t.seek(SeekFrom::Start(0)).unwrap();
+}
+
 fn main() {
     let mut f = OpenOptions::new()
         .write(true)
index c5bc57cc3a74ce617a96b4dd401a58cca895647b..467003a1a66f684141d3e8be6bc500d3acb99d66 100644 (file)
@@ -70,6 +70,12 @@ fn seek_to_end<T: Seek>(t: &mut T) {
     t.seek(SeekFrom::End(0));
 }
 
+// This should NOT trigger clippy warning because
+// expr is used here
+fn seek_to_start_in_let<T: Seek>(t: &mut T) {
+    let a = t.seek(SeekFrom::Start(0)).unwrap();
+}
+
 fn main() {
     let mut f = OpenOptions::new()
         .write(true)
index 6cce025359fe2918bce42ea6bdbef601d8c74948..342ec00fe7295ad8ec3afd061f1af4dbbc48110c 100644 (file)
@@ -13,7 +13,7 @@ LL |     t.seek(SeekFrom::Start(0));
    |       ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `rewind()`
 
 error: used `seek` to go to the start of the stream
-  --> $DIR/seek_to_start_instead_of_rewind.rs:128:7
+  --> $DIR/seek_to_start_instead_of_rewind.rs:134:7
    |
 LL |     f.seek(SeekFrom::Start(0));
    |       ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `rewind()`
diff --git a/src/tools/clippy/tests/ui/semicolon_inside_block.fixed b/src/tools/clippy/tests/ui/semicolon_inside_block.fixed
new file mode 100644 (file)
index 0000000..42e97e1
--- /dev/null
@@ -0,0 +1,85 @@
+// run-rustfix
+#![allow(
+    unused,
+    clippy::unused_unit,
+    clippy::unnecessary_operation,
+    clippy::no_effect,
+    clippy::single_element_loop
+)]
+#![warn(clippy::semicolon_inside_block)]
+
+macro_rules! m {
+    (()) => {
+        ()
+    };
+    (0) => {{
+        0
+    };};
+    (1) => {{
+        1;
+    }};
+    (2) => {{
+        2;
+    }};
+}
+
+fn unit_fn_block() {
+    ()
+}
+
+#[rustfmt::skip]
+fn main() {
+    { unit_fn_block() }
+    unsafe { unit_fn_block() }
+
+    {
+        unit_fn_block()
+    }
+
+    { unit_fn_block(); }
+    unsafe { unit_fn_block(); }
+
+    { unit_fn_block(); }
+    unsafe { unit_fn_block(); }
+
+    { unit_fn_block(); };
+    unsafe { unit_fn_block(); };
+
+    {
+        unit_fn_block();
+        unit_fn_block();
+    }
+    {
+        unit_fn_block();
+        unit_fn_block();
+    }
+    {
+        unit_fn_block();
+        unit_fn_block();
+    };
+
+    { m!(()); }
+    { m!(()); }
+    { m!(()); };
+    m!(0);
+    m!(1);
+    m!(2);
+
+    for _ in [()] {
+        unit_fn_block();
+    }
+    for _ in [()] {
+        unit_fn_block()
+    }
+
+    let _d = || {
+        unit_fn_block();
+    };
+    let _d = || {
+        unit_fn_block()
+    };
+
+    { unit_fn_block(); };
+
+    unit_fn_block()
+}
diff --git a/src/tools/clippy/tests/ui/semicolon_inside_block.rs b/src/tools/clippy/tests/ui/semicolon_inside_block.rs
new file mode 100644 (file)
index 0000000..f40848f
--- /dev/null
@@ -0,0 +1,85 @@
+// run-rustfix
+#![allow(
+    unused,
+    clippy::unused_unit,
+    clippy::unnecessary_operation,
+    clippy::no_effect,
+    clippy::single_element_loop
+)]
+#![warn(clippy::semicolon_inside_block)]
+
+macro_rules! m {
+    (()) => {
+        ()
+    };
+    (0) => {{
+        0
+    };};
+    (1) => {{
+        1;
+    }};
+    (2) => {{
+        2;
+    }};
+}
+
+fn unit_fn_block() {
+    ()
+}
+
+#[rustfmt::skip]
+fn main() {
+    { unit_fn_block() }
+    unsafe { unit_fn_block() }
+
+    {
+        unit_fn_block()
+    }
+
+    { unit_fn_block() };
+    unsafe { unit_fn_block() };
+
+    { unit_fn_block(); }
+    unsafe { unit_fn_block(); }
+
+    { unit_fn_block(); };
+    unsafe { unit_fn_block(); };
+
+    {
+        unit_fn_block();
+        unit_fn_block()
+    };
+    {
+        unit_fn_block();
+        unit_fn_block();
+    }
+    {
+        unit_fn_block();
+        unit_fn_block();
+    };
+
+    { m!(()) };
+    { m!(()); }
+    { m!(()); };
+    m!(0);
+    m!(1);
+    m!(2);
+
+    for _ in [()] {
+        unit_fn_block();
+    }
+    for _ in [()] {
+        unit_fn_block()
+    }
+
+    let _d = || {
+        unit_fn_block();
+    };
+    let _d = || {
+        unit_fn_block()
+    };
+
+    { unit_fn_block(); };
+
+    unit_fn_block()
+}
diff --git a/src/tools/clippy/tests/ui/semicolon_inside_block.stderr b/src/tools/clippy/tests/ui/semicolon_inside_block.stderr
new file mode 100644 (file)
index 0000000..48d3690
--- /dev/null
@@ -0,0 +1,54 @@
+error: consider moving the `;` inside the block for consistent formatting
+  --> $DIR/semicolon_inside_block.rs:39:5
+   |
+LL |     { unit_fn_block() };
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::semicolon-inside-block` implied by `-D warnings`
+help: put the `;` here
+   |
+LL -     { unit_fn_block() };
+LL +     { unit_fn_block(); }
+   |
+
+error: consider moving the `;` inside the block for consistent formatting
+  --> $DIR/semicolon_inside_block.rs:40:5
+   |
+LL |     unsafe { unit_fn_block() };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: put the `;` here
+   |
+LL -     unsafe { unit_fn_block() };
+LL +     unsafe { unit_fn_block(); }
+   |
+
+error: consider moving the `;` inside the block for consistent formatting
+  --> $DIR/semicolon_inside_block.rs:48:5
+   |
+LL | /     {
+LL | |         unit_fn_block();
+LL | |         unit_fn_block()
+LL | |     };
+   | |______^
+   |
+help: put the `;` here
+   |
+LL ~         unit_fn_block();
+LL ~     }
+   |
+
+error: consider moving the `;` inside the block for consistent formatting
+  --> $DIR/semicolon_inside_block.rs:61:5
+   |
+LL |     { m!(()) };
+   |     ^^^^^^^^^^^
+   |
+help: put the `;` here
+   |
+LL -     { m!(()) };
+LL +     { m!(()); }
+   |
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/semicolon_outside_block.fixed b/src/tools/clippy/tests/ui/semicolon_outside_block.fixed
new file mode 100644 (file)
index 0000000..091eaa7
--- /dev/null
@@ -0,0 +1,85 @@
+// run-rustfix
+#![allow(
+    unused,
+    clippy::unused_unit,
+    clippy::unnecessary_operation,
+    clippy::no_effect,
+    clippy::single_element_loop
+)]
+#![warn(clippy::semicolon_outside_block)]
+
+macro_rules! m {
+    (()) => {
+        ()
+    };
+    (0) => {{
+        0
+    };};
+    (1) => {{
+        1;
+    }};
+    (2) => {{
+        2;
+    }};
+}
+
+fn unit_fn_block() {
+    ()
+}
+
+#[rustfmt::skip]
+fn main() {
+    { unit_fn_block() }
+    unsafe { unit_fn_block() }
+
+    {
+        unit_fn_block()
+    }
+
+    { unit_fn_block() };
+    unsafe { unit_fn_block() };
+
+    { unit_fn_block() };
+    unsafe { unit_fn_block() };
+
+    { unit_fn_block(); };
+    unsafe { unit_fn_block(); };
+
+    {
+        unit_fn_block();
+        unit_fn_block()
+    };
+    {
+        unit_fn_block();
+        unit_fn_block()
+    };
+    {
+        unit_fn_block();
+        unit_fn_block();
+    };
+
+    { m!(()) };
+    { m!(()) };
+    { m!(()); };
+    m!(0);
+    m!(1);
+    m!(2);
+
+    for _ in [()] {
+        unit_fn_block();
+    }
+    for _ in [()] {
+        unit_fn_block()
+    }
+
+    let _d = || {
+        unit_fn_block();
+    };
+    let _d = || {
+        unit_fn_block()
+    };
+
+    { unit_fn_block(); };
+
+    unit_fn_block()
+}
diff --git a/src/tools/clippy/tests/ui/semicolon_outside_block.rs b/src/tools/clippy/tests/ui/semicolon_outside_block.rs
new file mode 100644 (file)
index 0000000..7ce4643
--- /dev/null
@@ -0,0 +1,85 @@
+// run-rustfix
+#![allow(
+    unused,
+    clippy::unused_unit,
+    clippy::unnecessary_operation,
+    clippy::no_effect,
+    clippy::single_element_loop
+)]
+#![warn(clippy::semicolon_outside_block)]
+
+macro_rules! m {
+    (()) => {
+        ()
+    };
+    (0) => {{
+        0
+    };};
+    (1) => {{
+        1;
+    }};
+    (2) => {{
+        2;
+    }};
+}
+
+fn unit_fn_block() {
+    ()
+}
+
+#[rustfmt::skip]
+fn main() {
+    { unit_fn_block() }
+    unsafe { unit_fn_block() }
+
+    {
+        unit_fn_block()
+    }
+
+    { unit_fn_block() };
+    unsafe { unit_fn_block() };
+
+    { unit_fn_block(); }
+    unsafe { unit_fn_block(); }
+
+    { unit_fn_block(); };
+    unsafe { unit_fn_block(); };
+
+    {
+        unit_fn_block();
+        unit_fn_block()
+    };
+    {
+        unit_fn_block();
+        unit_fn_block();
+    }
+    {
+        unit_fn_block();
+        unit_fn_block();
+    };
+
+    { m!(()) };
+    { m!(()); }
+    { m!(()); };
+    m!(0);
+    m!(1);
+    m!(2);
+
+    for _ in [()] {
+        unit_fn_block();
+    }
+    for _ in [()] {
+        unit_fn_block()
+    }
+
+    let _d = || {
+        unit_fn_block();
+    };
+    let _d = || {
+        unit_fn_block()
+    };
+
+    { unit_fn_block(); };
+
+    unit_fn_block()
+}
diff --git a/src/tools/clippy/tests/ui/semicolon_outside_block.stderr b/src/tools/clippy/tests/ui/semicolon_outside_block.stderr
new file mode 100644 (file)
index 0000000..dcc102e
--- /dev/null
@@ -0,0 +1,54 @@
+error: consider moving the `;` outside the block for consistent formatting
+  --> $DIR/semicolon_outside_block.rs:42:5
+   |
+LL |     { unit_fn_block(); }
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::semicolon-outside-block` implied by `-D warnings`
+help: put the `;` here
+   |
+LL -     { unit_fn_block(); }
+LL +     { unit_fn_block() };
+   |
+
+error: consider moving the `;` outside the block for consistent formatting
+  --> $DIR/semicolon_outside_block.rs:43:5
+   |
+LL |     unsafe { unit_fn_block(); }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: put the `;` here
+   |
+LL -     unsafe { unit_fn_block(); }
+LL +     unsafe { unit_fn_block() };
+   |
+
+error: consider moving the `;` outside the block for consistent formatting
+  --> $DIR/semicolon_outside_block.rs:52:5
+   |
+LL | /     {
+LL | |         unit_fn_block();
+LL | |         unit_fn_block();
+LL | |     }
+   | |_____^
+   |
+help: put the `;` here
+   |
+LL ~         unit_fn_block()
+LL ~     };
+   |
+
+error: consider moving the `;` outside the block for consistent formatting
+  --> $DIR/semicolon_outside_block.rs:62:5
+   |
+LL |     { m!(()); }
+   |     ^^^^^^^^^^^
+   |
+help: put the `;` here
+   |
+LL -     { m!(()); }
+LL +     { m!(()) };
+   |
+
+error: aborting due to 4 previous errors
+
index df2256e4f97de98afe0285e587ac9924c000fb3a..506187fc125736f778df20459bfd641c4350901a 100644 (file)
@@ -25,6 +25,12 @@ fn str_lit_as_bytes() {
     let includestr = include_bytes!("string_lit_as_bytes.rs");
 
     let _ = b"string with newline\t\n";
+
+    let _ = match "x".as_bytes() {
+        b"xx" => 0,
+        [b'x', ..] => 1,
+        _ => 2,
+    };
 }
 
 fn main() {}
index c6bf8f732ed9f615d1ea2d660d6ed7602513270b..2c339f1ddb819334b446e0007f6c5e6146965f29 100644 (file)
@@ -25,6 +25,12 @@ fn str_lit_as_bytes() {
     let includestr = include_str!("string_lit_as_bytes.rs").as_bytes();
 
     let _ = "string with newline\t\n".as_bytes();
+
+    let _ = match "x".as_bytes() {
+        b"xx" => 0,
+        [b'x', ..] => 1,
+        _ => 2,
+    };
 }
 
 fn main() {}
index 96cc0877960ec00c627a896f5eb54cafc633f2c1..52b5343c351e6e42365e484869c1b4dd4160c996 100644 (file)
@@ -26,4 +26,7 @@ fn main() {
             panic!("p4 {var}");
         }
     }
+
+    assert!(var == 1, "p5 {}", var);
+    debug_assert!(var == 1, "p6 {}", var);
 }
index faf8ca4d3a797aa2e989571786cd8c317a2e6652..ee72065e28abf3bfb0c118de65166efd65a7f6a4 100644 (file)
@@ -26,4 +26,7 @@ fn main() {
             panic!("p4 {var}");
         }
     }
+
+    assert!(var == 1, "p5 {var}");
+    debug_assert!(var == 1, "p6 {var}");
 }
index 0f09c45f41324b94da38117a4d885deabe904c0f..fc7b125080e766296e83e69e253dd481640b4e11 100644 (file)
@@ -47,5 +47,29 @@ LL -         panic!("p3 {var}", var = var);
 LL +         panic!("p3 {var}");
    |
 
-error: aborting due to 4 previous errors
+error: variables can be used directly in the `format!` string
+  --> $DIR/uninlined_format_args_panic.rs:30:5
+   |
+LL |     assert!(var == 1, "p5 {}", var);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: change this to
+   |
+LL -     assert!(var == 1, "p5 {}", var);
+LL +     assert!(var == 1, "p5 {var}");
+   |
+
+error: variables can be used directly in the `format!` string
+  --> $DIR/uninlined_format_args_panic.rs:31:5
+   |
+LL |     debug_assert!(var == 1, "p6 {}", var);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: change this to
+   |
+LL -     debug_assert!(var == 1, "p6 {}", var);
+LL +     debug_assert!(var == 1, "p6 {var}");
+   |
+
+error: aborting due to 6 previous errors
 
index 6421c5bbed2f5a05a6b5523d8560f36a374ca6c3..b4a0a0f496e400d7bdb3c4d8f9444c12cb6549f9 100644 (file)
@@ -26,4 +26,7 @@ fn main() {
             panic!("p4 {var}");
         }
     }
+
+    assert!(var == 1, "p5 {}", var);
+    debug_assert!(var == 1, "p6 {}", var);
 }
index ddeda795f81793e8d70d7109a16c958a4821f7f0..345f6d604c4f005028cfda81242cbc275ba6923b 100644 (file)
@@ -454,3 +454,23 @@ mod issue_9771b {
         Key(v.to_vec())
     }
 }
+
+// This is a watered down version of the code in: https://github.com/oxigraph/rio
+// The ICE is triggered by the call to `to_owned` on this line:
+// https://github.com/oxigraph/rio/blob/66635b9ff8e5423e58932353fa40d6e64e4820f7/testsuite/src/parser_evaluator.rs#L116
+mod issue_10021 {
+    #![allow(unused)]
+
+    pub struct Iri<T>(T);
+
+    impl<T: AsRef<str>> Iri<T> {
+        pub fn parse(iri: T) -> Result<Self, ()> {
+            unimplemented!()
+        }
+    }
+
+    pub fn parse_w3c_rdf_test_file(url: &str) -> Result<(), ()> {
+        let base_iri = Iri::parse(url.to_owned())?;
+        Ok(())
+    }
+}
index 95d2576733cd75ea8e42bf0ea127fb8983f7e451..7eb53df39e5b7dace2e82dd95030c53282b01919 100644 (file)
@@ -454,3 +454,23 @@ pub fn from(c: &[u8]) -> Key<Vec<u8>> {
         Key(v.to_vec())
     }
 }
+
+// This is a watered down version of the code in: https://github.com/oxigraph/rio
+// The ICE is triggered by the call to `to_owned` on this line:
+// https://github.com/oxigraph/rio/blob/66635b9ff8e5423e58932353fa40d6e64e4820f7/testsuite/src/parser_evaluator.rs#L116
+mod issue_10021 {
+    #![allow(unused)]
+
+    pub struct Iri<T>(T);
+
+    impl<T: AsRef<str>> Iri<T> {
+        pub fn parse(iri: T) -> Result<Self, ()> {
+            unimplemented!()
+        }
+    }
+
+    pub fn parse_w3c_rdf_test_file(url: &str) -> Result<(), ()> {
+        let base_iri = Iri::parse(url.to_owned())?;
+        Ok(())
+    }
+}
diff --git a/src/tools/clippy/tests/ui/zero_ptr_no_std.fixed b/src/tools/clippy/tests/ui/zero_ptr_no_std.fixed
new file mode 100644 (file)
index 0000000..8906c77
--- /dev/null
@@ -0,0 +1,21 @@
+// run-rustfix
+
+#![feature(lang_items, start, libc)]
+#![no_std]
+#![deny(clippy::zero_ptr)]
+
+#[start]
+fn main(_argc: isize, _argv: *const *const u8) -> isize {
+    let _ = core::ptr::null::<usize>();
+    let _ = core::ptr::null_mut::<f64>();
+    let _: *const u8 = core::ptr::null();
+    0
+}
+
+#[panic_handler]
+fn panic(_info: &core::panic::PanicInfo) -> ! {
+    loop {}
+}
+
+#[lang = "eh_personality"]
+extern "C" fn eh_personality() {}
diff --git a/src/tools/clippy/tests/ui/zero_ptr_no_std.rs b/src/tools/clippy/tests/ui/zero_ptr_no_std.rs
new file mode 100644 (file)
index 0000000..379c1b1
--- /dev/null
@@ -0,0 +1,21 @@
+// run-rustfix
+
+#![feature(lang_items, start, libc)]
+#![no_std]
+#![deny(clippy::zero_ptr)]
+
+#[start]
+fn main(_argc: isize, _argv: *const *const u8) -> isize {
+    let _ = 0 as *const usize;
+    let _ = 0 as *mut f64;
+    let _: *const u8 = 0 as *const _;
+    0
+}
+
+#[panic_handler]
+fn panic(_info: &core::panic::PanicInfo) -> ! {
+    loop {}
+}
+
+#[lang = "eh_personality"]
+extern "C" fn eh_personality() {}
diff --git a/src/tools/clippy/tests/ui/zero_ptr_no_std.stderr b/src/tools/clippy/tests/ui/zero_ptr_no_std.stderr
new file mode 100644 (file)
index 0000000..d92bb4a
--- /dev/null
@@ -0,0 +1,26 @@
+error: `0 as *const _` detected
+  --> $DIR/zero_ptr_no_std.rs:9:13
+   |
+LL |     let _ = 0 as *const usize;
+   |             ^^^^^^^^^^^^^^^^^ help: try: `core::ptr::null::<usize>()`
+   |
+note: the lint level is defined here
+  --> $DIR/zero_ptr_no_std.rs:5:9
+   |
+LL | #![deny(clippy::zero_ptr)]
+   |         ^^^^^^^^^^^^^^^^
+
+error: `0 as *mut _` detected
+  --> $DIR/zero_ptr_no_std.rs:10:13
+   |
+LL |     let _ = 0 as *mut f64;
+   |             ^^^^^^^^^^^^^ help: try: `core::ptr::null_mut::<f64>()`
+
+error: `0 as *const _` detected
+  --> $DIR/zero_ptr_no_std.rs:11:24
+   |
+LL |     let _: *const u8 = 0 as *const _;
+   |                        ^^^^^^^^^^^^^ help: try: `core::ptr::null()`
+
+error: aborting due to 3 previous errors
+
index 7a85386a3df4b8fc9934fe30010e5f87820fe12d..c721e9969c9aa67497c32ab03d2510e6e6ecaf11 100644 (file)
@@ -2,7 +2,6 @@
 #![warn(rust_2018_idioms, unused_lifetimes)]
 #![allow(clippy::single_match_else)]
 
-use rustc_tools_util::VersionInfo;
 use std::fs;
 
 #[test]
index acb476ee69628efc987a0785bae0ddb36ea85b46..6f50ef932e11260ffbc86b75820f2b4aea76f3fd 100644 (file)
@@ -1,7 +1,7 @@
 [relabel]
 allow-unauthenticated = [
     "A-*", "C-*", "E-*", "I-*", "L-*", "P-*", "S-*", "T-*",
-    "good-first-issue"
+    "good-first-issue", "beta-nominated"
 ]
 
 # Allows shortcuts like `@rustbot ready`
index 64d97e9144230fcf8cb665f35677f021c3f77a66..c5767a795382e41a7af9413e8e30adc609b2c3ee 100644 (file)
@@ -906,6 +906,7 @@ pub fn make_test_description<R: Read>(
     let has_asm_support = config.has_asm_support();
     let has_asan = util::ASAN_SUPPORTED_TARGETS.contains(&&*config.target);
     let has_cfi = util::CFI_SUPPORTED_TARGETS.contains(&&*config.target);
+    let has_kcfi = util::KCFI_SUPPORTED_TARGETS.contains(&&*config.target);
     let has_lsan = util::LSAN_SUPPORTED_TARGETS.contains(&&*config.target);
     let has_msan = util::MSAN_SUPPORTED_TARGETS.contains(&&*config.target);
     let has_tsan = util::TSAN_SUPPORTED_TARGETS.contains(&&*config.target);
@@ -957,6 +958,7 @@ pub fn make_test_description<R: Read>(
             && config.parse_name_directive(ln, "needs-sanitizer-support");
         ignore |= !has_asan && config.parse_name_directive(ln, "needs-sanitizer-address");
         ignore |= !has_cfi && config.parse_name_directive(ln, "needs-sanitizer-cfi");
+        ignore |= !has_kcfi && config.parse_name_directive(ln, "needs-sanitizer-kcfi");
         ignore |= !has_lsan && config.parse_name_directive(ln, "needs-sanitizer-leak");
         ignore |= !has_msan && config.parse_name_directive(ln, "needs-sanitizer-memory");
         ignore |= !has_tsan && config.parse_name_directive(ln, "needs-sanitizer-thread");
index e07b71a7c47802b07e5be842899be0f3706cb896..72a43108dc480666e595112eb63a92bdf6d144c4 100644 (file)
@@ -1924,7 +1924,15 @@ fn make_compile_args(
                     rustc.args(&["--json", "future-incompat"]);
                 }
                 rustc.arg("-Ccodegen-units=1");
+                // Hide line numbers to reduce churn
                 rustc.arg("-Zui-testing");
+                // Hide libstd sources from ui tests to make sure we generate the stderr
+                // output that users will see.
+                // Without this, we may be producing good diagnostics in-tree but users
+                // will not see half the information.
+                rustc.arg("-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX");
+                rustc.arg("-Ztranslate-remapped-path-to-local-path=no");
+
                 rustc.arg("-Zdeduplicate-diagnostics=no");
                 // FIXME: use this for other modes too, for perf?
                 rustc.arg("-Cstrip=debuginfo");
@@ -3542,6 +3550,8 @@ fn normalize_output(&self, output: &str, custom_rules: &[(String, String)]) -> S
             option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR").map(PathBuf::from),
             // Virtual `/rustc/$sha` coming from download-rustc:
             std::env::var_os("FAKE_DOWNLOAD_RUSTC_PREFIX").map(PathBuf::from),
+            // Tests using -Zsimulate-remapped-rust-src-base should use this fake path
+            Some("/rustc/FAKE_PREFIX".into()),
         ];
         for base_dir in source_bases {
             if let Some(base_dir) = base_dir {
index ec36f1e4fb72efd5beada293b800ad2aa4733404..ccba313ee357bf10c387f58cc99a8f5c6e5ceca2 100644 (file)
@@ -42,6 +42,8 @@
     "x86_64-unknown-netbsd",
 ];
 
+pub const KCFI_SUPPORTED_TARGETS: &[&str] = &["aarch64-linux-none", "x86_64-linux-none"];
+
 pub const LSAN_SUPPORTED_TARGETS: &[&str] = &[
     // FIXME: currently broken, see #88132
     // "aarch64-apple-darwin",
index 10e6e252e94b70428b58a4a7511522307c305266..f896a337f42caeff8afbbcc98399d6f7c5df0f02 100644 (file)
@@ -11,7 +11,6 @@
 
 use crate::*;
 pub mod stacked_borrows;
-use stacked_borrows::diagnostics::RetagCause;
 
 pub type CallId = NonZeroU64;
 
@@ -265,11 +264,19 @@ pub fn new_allocation(
 
 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
 pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
-    fn retag(&mut self, kind: RetagKind, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
+    fn retag_ptr_value(&mut self, kind: RetagKind, val: &ImmTy<'tcx, Provenance>) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
         let this = self.eval_context_mut();
         let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method;
         match method {
-            BorrowTrackerMethod::StackedBorrows => this.sb_retag(kind, place),
+            BorrowTrackerMethod::StackedBorrows => this.sb_retag_ptr_value(kind, val),
+        }
+    }
+
+    fn retag_place_contents(&mut self, kind: RetagKind, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
+        let this = self.eval_context_mut();
+        let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method;
+        match method {
+            BorrowTrackerMethod::StackedBorrows => this.sb_retag_place_contents(kind, place),
         }
     }
 
index 9a7b38b13a3ade0d98fd88f702e9f14dfffde491..24b3489e0d1d67e61503017feb699a39bfc0b7f7 100644 (file)
@@ -459,10 +459,10 @@ pub fn check_tracked_tag_popped(&self, item: &Item, global: &GlobalStateInner) {
             Operation::Dealloc(_) => format!(" due to deallocation"),
             Operation::Access(AccessOp { kind, tag, .. }) =>
                 format!(" due to {kind:?} access for {tag:?}"),
-            Operation::Retag(RetagOp { orig_tag, permission, .. }) => {
+            Operation::Retag(RetagOp { orig_tag, permission, new_tag, .. }) => {
                 let permission = permission
                     .expect("start_grant should set the current permission before popping a tag");
-                format!(" due to {permission:?} retag from {orig_tag:?}")
+                format!(" due to {permission:?} retag from {orig_tag:?} (that retag created {new_tag:?})")
             }
         };
 
index bcac873251f587509c766cd4197cb929feb950f2..ffbc00864022f4c642d6d9ec6c41f75628d874e4 100644 (file)
@@ -1,9 +1,13 @@
 //! Implements "Stacked Borrows".  See <https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md>
 //! for further information.
 
+pub mod diagnostics;
+mod item;
+mod stack;
+
 use log::trace;
 use std::cmp;
-use std::fmt::{self, Write};
+use std::fmt::Write;
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_middle::mir::{Mutability, RetagKind};
 
 use crate::borrow_tracker::{
     stacked_borrows::diagnostics::{AllocHistory, DiagnosticCx, DiagnosticCxBuilder, TagHistory},
-    AccessKind, GlobalStateInner, ProtectorKind, RetagCause, RetagFields,
+    AccessKind, GlobalStateInner, ProtectorKind, RetagFields,
 };
 use crate::*;
 
-mod item;
+use diagnostics::RetagCause;
 pub use item::{Item, Permission};
-mod stack;
 pub use stack::Stack;
-pub mod diagnostics;
 
 pub type AllocState = Stacks;
 
@@ -40,30 +42,104 @@ pub struct Stacks {
     modified_since_last_gc: bool,
 }
 
-/// Indicates which kind of reference is being created.
-/// Used by high-level `reborrow` to compute which permissions to grant to the
-/// new pointer.
-#[derive(Copy, Clone, Hash, PartialEq, Eq)]
-enum RefKind {
-    /// `Box`.
-    Box,
-    /// `&mut`.
-    Unique { two_phase: bool },
-    /// `&` with or without interior mutability.
-    Shared,
-    /// `*mut`/`*const` (raw pointers).
-    Raw { mutable: bool },
+/// Indicates which permissions to grant to the retagged pointer.
+#[derive(Clone, Debug)]
+enum NewPermission {
+    Uniform {
+        perm: Permission,
+        access: Option<AccessKind>,
+        protector: Option<ProtectorKind>,
+    },
+    FreezeSensitive {
+        freeze_perm: Permission,
+        freeze_access: Option<AccessKind>,
+        freeze_protector: Option<ProtectorKind>,
+        nonfreeze_perm: Permission,
+        nonfreeze_access: Option<AccessKind>,
+        // nonfreeze_protector must always be None
+    },
 }
 
-impl fmt::Display for RefKind {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+impl NewPermission {
+    /// A key function: determine the permissions to grant at a retag for the given kind of
+    /// reference/pointer.
+    fn from_ref_ty<'tcx>(
+        ty: ty::Ty<'tcx>,
+        kind: RetagKind,
+        cx: &crate::MiriInterpCx<'_, 'tcx>,
+    ) -> Self {
+        let protector = (kind == RetagKind::FnEntry).then_some(ProtectorKind::StrongProtector);
+        match ty.kind() {
+            ty::Ref(_, pointee, Mutability::Mut) => {
+                if kind == RetagKind::TwoPhase {
+                    // We mostly just give up on 2phase-borrows, and treat these exactly like raw pointers.
+                    assert!(protector.is_none()); // RetagKind can't be both FnEntry and TwoPhase.
+                    NewPermission::Uniform {
+                        perm: Permission::SharedReadWrite,
+                        access: None,
+                        protector: None,
+                    }
+                } else if pointee.is_unpin(*cx.tcx, cx.param_env()) {
+                    // A regular full mutable reference.
+                    NewPermission::Uniform {
+                        perm: Permission::Unique,
+                        access: Some(AccessKind::Write),
+                        protector,
+                    }
+                } else {
+                    NewPermission::Uniform {
+                        perm: Permission::SharedReadWrite,
+                        // FIXME: We emit `dereferenceable` for `!Unpin` mutable references, so we
+                        // should do fake accesses here. But then we run into
+                        // <https://github.com/rust-lang/unsafe-code-guidelines/issues/381>, so for now
+                        // we don't do that.
+                        access: None,
+                        protector,
+                    }
+                }
+            }
+            ty::RawPtr(ty::TypeAndMut { mutbl: Mutability::Mut, .. }) => {
+                assert!(protector.is_none()); // RetagKind can't be both FnEntry and Raw.
+                // Mutable raw pointer. No access, not protected.
+                NewPermission::Uniform {
+                    perm: Permission::SharedReadWrite,
+                    access: None,
+                    protector: None,
+                }
+            }
+            ty::Ref(_, _pointee, Mutability::Not) => {
+                NewPermission::FreezeSensitive {
+                    freeze_perm: Permission::SharedReadOnly,
+                    freeze_access: Some(AccessKind::Read),
+                    freeze_protector: protector,
+                    nonfreeze_perm: Permission::SharedReadWrite,
+                    // Inside UnsafeCell, this does *not* count as an access, as there
+                    // might actually be mutable references further up the stack that
+                    // we have to keep alive.
+                    nonfreeze_access: None,
+                    // We do not protect inside UnsafeCell.
+                    // This fixes https://github.com/rust-lang/rust/issues/55005.
+                }
+            }
+            ty::RawPtr(ty::TypeAndMut { mutbl: Mutability::Not, .. }) => {
+                assert!(protector.is_none()); // RetagKind can't be both FnEntry and Raw.
+                // `*const T`, when freshly created, are read-only in the frozen part.
+                NewPermission::FreezeSensitive {
+                    freeze_perm: Permission::SharedReadOnly,
+                    freeze_access: Some(AccessKind::Read),
+                    freeze_protector: None,
+                    nonfreeze_perm: Permission::SharedReadWrite,
+                    nonfreeze_access: None,
+                }
+            }
+            _ => unreachable!(),
+        }
+    }
+
+    fn protector(&self) -> Option<ProtectorKind> {
         match self {
-            RefKind::Box => write!(f, "Box"),
-            RefKind::Unique { two_phase: false } => write!(f, "unique reference"),
-            RefKind::Unique { two_phase: true } => write!(f, "unique reference (two-phase)"),
-            RefKind::Shared => write!(f, "shared reference"),
-            RefKind::Raw { mutable: true } => write!(f, "raw (mutable) pointer"),
-            RefKind::Raw { mutable: false } => write!(f, "raw (constant) pointer"),
+            NewPermission::Uniform { protector, .. } => *protector,
+            NewPermission::FreezeSensitive { freeze_protector, .. } => *freeze_protector,
         }
     }
 }
@@ -518,10 +594,9 @@ fn sb_reborrow(
         &mut self,
         place: &MPlaceTy<'tcx, Provenance>,
         size: Size,
-        kind: RefKind,
-        retag_cause: RetagCause, // What caused this retag, for diagnostics only
+        new_perm: NewPermission,
         new_tag: BorTag,
-        protect: Option<ProtectorKind>,
+        retag_cause: RetagCause, // What caused this retag, for diagnostics only
     ) -> InterpResult<'tcx, Option<AllocId>> {
         let this = self.eval_context_mut();
 
@@ -532,20 +607,16 @@ fn sb_reborrow(
             let global = this.machine.borrow_tracker.as_ref().unwrap().borrow();
             let ty = place.layout.ty;
             if global.tracked_pointer_tags.contains(&new_tag) {
-                let mut kind_str = format!("{kind}");
-                match kind {
-                    RefKind::Unique { two_phase: false }
-                        if !ty.is_unpin(*this.tcx, this.param_env()) =>
-                    {
-                        write!(kind_str, " (!Unpin pointee type {ty})").unwrap()
-                    },
-                    RefKind::Shared
-                        if !ty.is_freeze(*this.tcx, this.param_env()) =>
-                    {
-                        write!(kind_str, " (!Freeze pointee type {ty})").unwrap()
-                    },
-                    _ => write!(kind_str, " (pointee type {ty})").unwrap(),
-                };
+                let mut kind_str = String::new();
+                match new_perm {
+                    NewPermission::Uniform { perm, .. } =>
+                        write!(kind_str, "{perm:?} permission").unwrap(),
+                    NewPermission::FreezeSensitive { freeze_perm, .. } if ty.is_freeze(*this.tcx, this.param_env()) =>
+                        write!(kind_str, "{freeze_perm:?} permission").unwrap(),
+                    NewPermission::FreezeSensitive { freeze_perm, nonfreeze_perm, .. }  =>
+                        write!(kind_str, "{freeze_perm:?}/{nonfreeze_perm:?} permission for frozen/non-frozen parts").unwrap(),
+                }
+                write!(kind_str, " (pointee type {ty})").unwrap();
                 this.emit_diagnostic(NonHaltingDiagnostic::CreatedPointerTag(
                     new_tag.inner(),
                     Some(kind_str),
@@ -579,7 +650,7 @@ fn sb_reborrow(
                     );
                     let mut dcx = dcx.build(&mut stacked_borrows.history, base_offset);
                     dcx.log_creation();
-                    if protect.is_some() {
+                    if new_perm.protector().is_some() {
                         dcx.log_protector();
                     }
                 },
@@ -592,8 +663,7 @@ fn sb_reborrow(
 
         if size == Size::ZERO {
             trace!(
-                "reborrow of size 0: {} reference {:?} derived from {:?} (pointee {})",
-                kind,
+                "reborrow of size 0: reference {:?} derived from {:?} (pointee {})",
                 new_tag,
                 place.ptr,
                 place.layout.ty,
@@ -630,8 +700,7 @@ fn sb_reborrow(
         }
 
         trace!(
-            "reborrow: {} reference {:?} derived from {:?} (pointee {}): {:?}, size {}",
-            kind,
+            "reborrow: reference {:?} derived from {:?} (pointee {}): {:?}, size {}",
             new_tag,
             orig_tag,
             place.layout.ty,
@@ -639,7 +708,7 @@ fn sb_reborrow(
             size.bytes()
         );
 
-        if let Some(protect) = protect {
+        if let Some(protect) = new_perm.protector() {
             // See comment in `Stack::item_invalidated` for why we store the tag twice.
             this.frame_mut().extra.borrow_tracker.as_mut().unwrap().protected_tags.push(new_tag);
             this.machine
@@ -651,30 +720,45 @@ fn sb_reborrow(
                 .insert(new_tag, protect);
         }
 
-        // Update the stacks.
-        // Make sure that raw pointers and mutable shared references are reborrowed "weak":
-        // There could be existing unique pointers reborrowed from them that should remain valid!
-        let (perm, access) = match kind {
-            RefKind::Unique { two_phase } => {
-                // Permission is Unique only if the type is `Unpin` and this is not twophase
-                if !two_phase && place.layout.ty.is_unpin(*this.tcx, this.param_env()) {
-                    (Permission::Unique, Some(AccessKind::Write))
-                } else {
-                    // FIXME: We emit `dereferenceable` for `!Unpin` mutable references, so we
-                    // should do fake accesses here. But then we run into
-                    // <https://github.com/rust-lang/unsafe-code-guidelines/issues/381>, so for now
-                    // we don't do that.
-                    (Permission::SharedReadWrite, None)
+        // Update the stacks, according to the new permission information we are given.
+        match new_perm {
+            NewPermission::Uniform { perm, access, protector } => {
+                assert!(perm != Permission::SharedReadOnly);
+                // Here we can avoid `borrow()` calls because we have mutable references.
+                // Note that this asserts that the allocation is mutable -- but since we are creating a
+                // mutable pointer, that seems reasonable.
+                let (alloc_extra, machine) = this.get_alloc_extra_mut(alloc_id)?;
+                let stacked_borrows = alloc_extra.borrow_tracker_sb_mut().get_mut();
+                let item = Item::new(new_tag, perm, protector.is_some());
+                let range = alloc_range(base_offset, size);
+                let global = machine.borrow_tracker.as_ref().unwrap().borrow();
+                let dcx = DiagnosticCxBuilder::retag(
+                    machine,
+                    retag_cause,
+                    new_tag,
+                    orig_tag,
+                    alloc_range(base_offset, size),
+                );
+                stacked_borrows.for_each(range, dcx, |stack, dcx, exposed_tags| {
+                    stack.grant(orig_tag, item, access, &global, dcx, exposed_tags)
+                })?;
+                drop(global);
+                if let Some(access) = access {
+                    assert_eq!(access, AccessKind::Write);
+                    // Make sure the data race model also knows about this.
+                    if let Some(data_race) = alloc_extra.data_race.as_mut() {
+                        data_race.write(alloc_id, range, machine)?;
+                    }
                 }
             }
-            RefKind::Box => (Permission::Unique, Some(AccessKind::Write)),
-            RefKind::Raw { mutable: true } => {
-                // Creating a raw ptr does not count as an access
-                (Permission::SharedReadWrite, None)
-            }
-            RefKind::Shared | RefKind::Raw { mutable: false } => {
-                // Shared references and *const are a whole different kind of game, the
-                // permission is not uniform across the entire range!
+            NewPermission::FreezeSensitive {
+                freeze_perm,
+                freeze_access,
+                freeze_protector,
+                nonfreeze_perm,
+                nonfreeze_access,
+            } => {
+                // The permission is not uniform across the entire range!
                 // We need a frozen-sensitive reborrow.
                 // We have to use shared references to alloc/memory_extra here since
                 // `visit_freeze_sensitive` needs to access the global state.
@@ -684,22 +768,12 @@ fn sb_reborrow(
                     // Adjust range.
                     range.start += base_offset;
                     // We are only ever `SharedReadOnly` inside the frozen bits.
-                    let (perm, access) = if frozen {
-                        (Permission::SharedReadOnly, Some(AccessKind::Read))
-                    } else {
-                        // Inside UnsafeCell, this does *not* count as an access, as there
-                        // might actually be mutable references further up the stack that
-                        // we have to keep alive.
-                        (Permission::SharedReadWrite, None)
-                    };
-                    let protected = if frozen {
-                        protect.is_some()
+                    let (perm, access, protector) = if frozen {
+                        (freeze_perm, freeze_access, freeze_protector)
                     } else {
-                        // We do not protect inside UnsafeCell.
-                        // This fixes https://github.com/rust-lang/rust/issues/55005.
-                        false
+                        (nonfreeze_perm, nonfreeze_access, None)
                     };
-                    let item = Item::new(new_tag, perm, protected);
+                    let item = Item::new(new_tag, perm, protector.is_some());
                     let global = this.machine.borrow_tracker.as_ref().unwrap().borrow();
                     let dcx = DiagnosticCxBuilder::retag(
                         &this.machine,
@@ -721,34 +795,6 @@ fn sb_reborrow(
                     }
                     Ok(())
                 })?;
-                return Ok(Some(alloc_id));
-            }
-        };
-
-        // Here we can avoid `borrow()` calls because we have mutable references.
-        // Note that this asserts that the allocation is mutable -- but since we are creating a
-        // mutable pointer, that seems reasonable.
-        let (alloc_extra, machine) = this.get_alloc_extra_mut(alloc_id)?;
-        let stacked_borrows = alloc_extra.borrow_tracker_sb_mut().get_mut();
-        let item = Item::new(new_tag, perm, protect.is_some());
-        let range = alloc_range(base_offset, size);
-        let global = machine.borrow_tracker.as_ref().unwrap().borrow();
-        let dcx = DiagnosticCxBuilder::retag(
-            machine,
-            retag_cause,
-            new_tag,
-            orig_tag,
-            alloc_range(base_offset, size),
-        );
-        stacked_borrows.for_each(range, dcx, |stack, dcx, exposed_tags| {
-            stack.grant(orig_tag, item, access, &global, dcx, exposed_tags)
-        })?;
-        drop(global);
-        if let Some(access) = access {
-            assert_eq!(access, AccessKind::Write);
-            // Make sure the data race model also knows about this.
-            if let Some(data_race) = alloc_extra.data_race.as_mut() {
-                data_race.write(alloc_id, range, machine)?;
             }
         }
 
@@ -760,9 +806,8 @@ fn sb_reborrow(
     fn sb_retag_reference(
         &mut self,
         val: &ImmTy<'tcx, Provenance>,
-        kind: RefKind,
-        retag_cause: RetagCause, // What caused this retag, for diagnostics only
-        protect: Option<ProtectorKind>,
+        new_perm: NewPermission,
+        cause: RetagCause, // What caused this retag, for diagnostics only
     ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
         let this = self.eval_context_mut();
         // We want a place for where the ptr *points to*, so we get one.
@@ -780,7 +825,7 @@ fn sb_retag_reference(
         let new_tag = this.machine.borrow_tracker.as_mut().unwrap().get_mut().new_ptr();
 
         // Reborrow.
-        let alloc_id = this.sb_reborrow(&place, size, kind, retag_cause, new_tag, protect)?;
+        let alloc_id = this.sb_reborrow(&place, size, new_perm, new_tag, cause)?;
 
         // Adjust pointer.
         let new_place = place.map_provenance(|p| {
@@ -807,7 +852,22 @@ fn sb_retag_reference(
 
 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
 pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
-    fn sb_retag(
+    fn sb_retag_ptr_value(
+        &mut self,
+        kind: RetagKind,
+        val: &ImmTy<'tcx, Provenance>,
+    ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
+        let this = self.eval_context_mut();
+        let new_perm = NewPermission::from_ref_ty(val.layout.ty, kind, this);
+        let retag_cause = match kind {
+            RetagKind::TwoPhase { .. } => RetagCause::TwoPhase,
+            RetagKind::FnEntry => unreachable!(),
+            RetagKind::Raw | RetagKind::Default => RetagCause::Normal,
+        };
+        this.sb_retag_reference(&val, new_perm, retag_cause)
+    }
+
+    fn sb_retag_place_contents(
         &mut self,
         kind: RetagKind,
         place: &PlaceTy<'tcx, Provenance>,
@@ -815,9 +875,9 @@ fn sb_retag(
         let this = self.eval_context_mut();
         let retag_fields = this.machine.borrow_tracker.as_mut().unwrap().get_mut().retag_fields;
         let retag_cause = match kind {
-            RetagKind::TwoPhase { .. } => RetagCause::TwoPhase,
+            RetagKind::Raw | RetagKind::TwoPhase { .. } => unreachable!(), // these can only happen in `retag_ptr_value`
             RetagKind::FnEntry => RetagCause::FnEntry,
-            RetagKind::Raw | RetagKind::Default => RetagCause::Normal,
+            RetagKind::Default => RetagCause::Normal,
         };
         let mut visitor = RetagVisitor { ecx: this, kind, retag_cause, retag_fields };
         return visitor.visit_value(place);
@@ -831,15 +891,14 @@ struct RetagVisitor<'ecx, 'mir, 'tcx> {
         }
         impl<'ecx, 'mir, 'tcx> RetagVisitor<'ecx, 'mir, 'tcx> {
             #[inline(always)] // yes this helps in our benchmarks
-            fn retag_place(
+            fn retag_ptr_inplace(
                 &mut self,
                 place: &PlaceTy<'tcx, Provenance>,
-                ref_kind: RefKind,
+                new_perm: NewPermission,
                 retag_cause: RetagCause,
-                protector: Option<ProtectorKind>,
             ) -> InterpResult<'tcx> {
                 let val = self.ecx.read_immediate(&self.ecx.place_to_op(place)?)?;
-                let val = self.ecx.sb_retag_reference(&val, ref_kind, retag_cause, protector)?;
+                let val = self.ecx.sb_retag_reference(&val, new_perm, retag_cause)?;
                 self.ecx.write_immediate(*val, place)?;
                 Ok(())
             }
@@ -856,13 +915,13 @@ fn ecx(&mut self) -> &mut MiriInterpCx<'mir, 'tcx> {
 
             fn visit_box(&mut self, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
                 // Boxes get a weak protectors, since they may be deallocated.
-                self.retag_place(
-                    place,
-                    RefKind::Box,
-                    self.retag_cause,
-                    /*protector*/
-                    (self.kind == RetagKind::FnEntry).then_some(ProtectorKind::WeakProtector),
-                )
+                let new_perm = NewPermission::Uniform {
+                    perm: Permission::Unique,
+                    access: Some(AccessKind::Write),
+                    protector: (self.kind == RetagKind::FnEntry)
+                        .then_some(ProtectorKind::WeakProtector),
+                };
+                self.retag_ptr_inplace(place, new_perm, self.retag_cause)
             }
 
             fn visit_value(&mut self, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
@@ -876,36 +935,16 @@ fn visit_value(&mut self, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tc
 
                 // Check the type of this value to see what to do with it (retag, or recurse).
                 match place.layout.ty.kind() {
-                    ty::Ref(_, _, mutbl) => {
-                        let ref_kind = match mutbl {
-                            Mutability::Mut =>
-                                RefKind::Unique { two_phase: self.kind == RetagKind::TwoPhase },
-                            Mutability::Not => RefKind::Shared,
-                        };
-                        self.retag_place(
-                            place,
-                            ref_kind,
-                            self.retag_cause,
-                            /*protector*/
-                            (self.kind == RetagKind::FnEntry)
-                                .then_some(ProtectorKind::StrongProtector),
-                        )?;
+                    ty::Ref(..) => {
+                        let new_perm =
+                            NewPermission::from_ref_ty(place.layout.ty, self.kind, self.ecx);
+                        self.retag_ptr_inplace(place, new_perm, self.retag_cause)?;
                     }
-                    ty::RawPtr(tym) => {
-                        // We definitely do *not* want to recurse into raw pointers -- wide raw
-                        // pointers have fields, and for dyn Trait pointees those can have reference
-                        // type!
-                        if self.kind == RetagKind::Raw {
-                            // Raw pointers need to be enabled.
-                            self.retag_place(
-                                place,
-                                RefKind::Raw { mutable: tym.mutbl == Mutability::Mut },
-                                self.retag_cause,
-                                /*protector*/ None,
-                            )?;
-                        }
+                    ty::RawPtr(..) => {
+                        // We do *not* want to recurse into raw pointers -- wide raw pointers have
+                        // fields, and for dyn Trait pointees those can have reference type!
                     }
-                    _ if place.layout.ty.ty_adt_def().is_some_and(|adt| adt.is_box()) => {
+                    ty::Adt(adt, _) if adt.is_box() => {
                         // Recurse for boxes, they require some tricky handling and will end up in `visit_box` above.
                         // (Yes this means we technically also recursively retag the allocator itself
                         // even if field retagging is not enabled. *shrug*)
@@ -953,12 +992,12 @@ fn sb_retag_return_place(&mut self) -> InterpResult<'tcx> {
         let ptr_layout = this.layout_of(this.tcx.mk_mut_ptr(return_place.layout.ty))?;
         let val = ImmTy::from_immediate(return_place.to_ref(this), ptr_layout);
         // Reborrow it. With protection! That is part of the point.
-        let val = this.sb_retag_reference(
-            &val,
-            RefKind::Unique { two_phase: false },
-            RetagCause::FnReturn,
-            /*protector*/ Some(ProtectorKind::StrongProtector),
-        )?;
+        let new_perm = NewPermission::Uniform {
+            perm: Permission::Unique,
+            access: Some(AccessKind::Write),
+            protector: Some(ProtectorKind::StrongProtector),
+        };
+        let val = this.sb_retag_reference(&val, new_perm, RetagCause::FnReturn)?;
         // And use reborrowed pointer for return place.
         let return_place = this.ref_to_mplace(&val)?;
         this.frame_mut().return_place = return_place.into();
index 074fa032dcc427537ef840c750aeee4830e657f3..c22ac50e4557e5fe107d942d46ab384abb495479 100644 (file)
@@ -63,9 +63,9 @@ impl MachineStopType for TerminationInfo {}
 
 /// Miri specific diagnostics
 pub enum NonHaltingDiagnostic {
-    /// (new_tag, new_kind, (alloc_id, base_offset, orig_tag))
+    /// (new_tag, new_perm, (alloc_id, base_offset, orig_tag))
     ///
-    /// new_kind is `None` for base tags.
+    /// new_perm is `None` for base tags.
     CreatedPointerTag(NonZeroU64, Option<String>, Option<(AllocId, AllocRange, ProvenanceExtra)>),
     /// This `Item` was popped from the borrow stack. The string explains the reason.
     PoppedPointerTag(Item, String),
@@ -364,7 +364,9 @@ fn report_msg<'tcx>(
         if is_local && idx > 0 {
             err.span_note(frame_info.span, &frame_info.to_string());
         } else {
-            err.note(&frame_info.to_string());
+            let sm = sess.source_map();
+            let span = sm.span_to_embeddable_string(frame_info.span);
+            err.note(format!("{frame_info} at {span}"));
         }
     }
 
@@ -393,10 +395,10 @@ pub fn emit_diagnostic(&self, e: NonHaltingDiagnostic) {
 
         let msg = match &e {
             CreatedPointerTag(tag, None, _) => format!("created base tag {tag:?}"),
-            CreatedPointerTag(tag, Some(kind), None) => format!("created {tag:?} for {kind}"),
-            CreatedPointerTag(tag, Some(kind), Some((alloc_id, range, orig_tag))) =>
+            CreatedPointerTag(tag, Some(perm), None) => format!("created {tag:?} with {perm} derived from unknown tag"),
+            CreatedPointerTag(tag, Some(perm), Some((alloc_id, range, orig_tag))) =>
                 format!(
-                    "created tag {tag:?} for {kind} at {alloc_id:?}{range:?} derived from {orig_tag:?}"
+                    "created tag {tag:?} with {perm} at {alloc_id:?}{range:?} derived from {orig_tag:?}"
                 ),
             PoppedPointerTag(item, cause) => format!("popped tracked tag for item {item:?}{cause}"),
             CreatedCallId(id) => format!("function call with id {id}"),
index c110229c985db78600cd18626a2b1899852047df..ab629e4711b10c0e2ca8e5fec502336575f2ab9a 100644 (file)
@@ -22,8 +22,9 @@
 };
 use rustc_span::def_id::{CrateNum, DefId};
 use rustc_span::Symbol;
-use rustc_target::abi::Size;
+use rustc_target::abi::{Size, Align};
 use rustc_target::spec::abi::Abi;
+use rustc_const_eval::const_eval::CheckAlignment;
 
 use crate::{
     concurrency::{data_race, weak_memory},
@@ -752,8 +753,12 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
     const PANIC_ON_ALLOC_FAIL: bool = false;
 
     #[inline(always)]
-    fn enforce_alignment(ecx: &MiriInterpCx<'mir, 'tcx>) -> bool {
-        ecx.machine.check_alignment != AlignmentCheck::None
+    fn enforce_alignment(ecx: &MiriInterpCx<'mir, 'tcx>) -> CheckAlignment {
+        if ecx.machine.check_alignment == AlignmentCheck::None {
+            CheckAlignment::No
+        } else {
+            CheckAlignment::Error
+        }
     }
 
     #[inline(always)]
@@ -761,6 +766,15 @@ fn use_addr_for_alignment_check(ecx: &MiriInterpCx<'mir, 'tcx>) -> bool {
         ecx.machine.check_alignment == AlignmentCheck::Int
     }
 
+    fn alignment_check_failed(
+        _ecx: &InterpCx<'mir, 'tcx, Self>,
+        has: Align,
+        required: Align,
+        _check: CheckAlignment,
+    ) -> InterpResult<'tcx, ()> {
+        throw_ub!(AlignmentCheckFailed { has, required })
+    }
+
     #[inline(always)]
     fn enforce_validity(ecx: &MiriInterpCx<'mir, 'tcx>) -> bool {
         ecx.machine.validate
@@ -967,8 +981,9 @@ fn expose_ptr(
         ptr: Pointer<Self::Provenance>,
     ) -> InterpResult<'tcx> {
         match ptr.provenance {
-            Provenance::Concrete { alloc_id, tag } =>
-                intptrcast::GlobalStateInner::expose_ptr(ecx, alloc_id, tag),
+            Provenance::Concrete { alloc_id, tag } => {
+                intptrcast::GlobalStateInner::expose_ptr(ecx, alloc_id, tag)
+            }
             Provenance::Wildcard => {
                 // No need to do anything for wildcard pointers as
                 // their provenances have already been previously exposed.
@@ -1055,13 +1070,26 @@ fn before_memory_deallocation(
     }
 
     #[inline(always)]
-    fn retag(
+    fn retag_ptr_value(
+        ecx: &mut InterpCx<'mir, 'tcx, Self>,
+        kind: mir::RetagKind,
+        val: &ImmTy<'tcx, Provenance>,
+    ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
+        if ecx.machine.borrow_tracker.is_some() {
+            ecx.retag_ptr_value(kind, val)
+        } else {
+            Ok(val.clone())
+        }
+    }
+
+    #[inline(always)]
+    fn retag_place_contents(
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
         kind: mir::RetagKind,
         place: &PlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx> {
         if ecx.machine.borrow_tracker.is_some() {
-            ecx.retag(kind, place)?;
+            ecx.retag_place_contents(kind, place)?;
         }
         Ok(())
     }
index ec9ce76685b5572e6c43d3e4dad1fb10c552c751..2d3275f6b19011eda917967475e5cf9d3c77cc1c 100644 (file)
@@ -10,7 +10,7 @@ LL | | }
    | |_^ the program aborted execution
    |
    = note: inside `panic_abort` at $DIR/abort-terminator.rs:LL:CC
-note: inside `main` at $DIR/abort-terminator.rs:LL:CC
+note: inside `main`
   --> $DIR/abort-terminator.rs:LL:CC
    |
 LL |     panic_abort();
index 28439b54b2908270a7ffbf3f8c022d9b49aab4a6..095eeeb79de7b2d4e58ec72f945f85fbee7d4cd5 100644 (file)
@@ -8,7 +8,7 @@ LL |     unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) }
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `std::alloc::dealloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
-note: inside `main` at $DIR/deallocate-bad-alignment.rs:LL:CC
+note: inside `main`
   --> $DIR/deallocate-bad-alignment.rs:LL:CC
    |
 LL |         dealloc(x, Layout::from_size_align_unchecked(1, 2));
index a6ceab1f56f513d742e5a5055a25a7000de269e3..5fe93c841b22c80c963456a3f77fe230a29ee89b 100644 (file)
@@ -8,7 +8,7 @@ LL |     unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) }
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `std::alloc::dealloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
-note: inside `main` at $DIR/deallocate-bad-size.rs:LL:CC
+note: inside `main`
   --> $DIR/deallocate-bad-size.rs:LL:CC
    |
 LL |         dealloc(x, Layout::from_size_align_unchecked(2, 1));
index b6c5b6f97ee7b9fa9a7bb8f08bc8c492270b9b75..fa7a74ee13cfe64cb12d27181463715ef1c92767 100644 (file)
@@ -8,7 +8,7 @@ LL |     unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) }
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `std::alloc::dealloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
-note: inside `main` at $DIR/deallocate-twice.rs:LL:CC
+note: inside `main`
   --> $DIR/deallocate-twice.rs:LL:CC
    |
 LL |         dealloc(x, Layout::from_size_align_unchecked(1, 1));
index 4ee85add6c228242c656d0bd1f2a361107fe771b..62ffb8142a3fb36c971153894af5f7734c4cbd8f 100644 (file)
@@ -9,7 +9,7 @@ LL |         FREE();
    = note: BACKTRACE:
    = note: inside `std::sys::PLATFORM::alloc::<impl std::alloc::GlobalAlloc for std::alloc::System>::dealloc` at RUSTLIB/std/src/sys/PLATFORM/alloc.rs:LL:CC
    = note: inside `<std::alloc::System as std::alloc::Allocator>::deallocate` at RUSTLIB/std/src/alloc.rs:LL:CC
-note: inside `main` at $DIR/global_system_mixup.rs:LL:CC
+note: inside `main`
   --> $DIR/global_system_mixup.rs:LL:CC
    |
 LL |         System.deallocate(ptr, l);
index c11b5a851048f631c03532712c5a753dff1ac0a1..24cabb395649c21766fd4234f7a89826ff9a846e 100644 (file)
@@ -8,7 +8,7 @@ LL |     unsafe { __rust_realloc(ptr, layout.size(), layout.align(), new_size) }
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `std::alloc::realloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
-note: inside `main` at $DIR/reallocate-bad-size.rs:LL:CC
+note: inside `main`
   --> $DIR/reallocate-bad-size.rs:LL:CC
    |
 LL |         let _y = realloc(x, Layout::from_size_align_unchecked(2, 1), 1);
index c7db5a729048c234e899a153ef03dfc2d74d6fc8..b1460bfb763eed3d219accd982bdfbef528c11b8 100644 (file)
@@ -8,7 +8,7 @@ LL |     unsafe { __rust_realloc(ptr, layout.size(), layout.align(), new_size) }
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `std::alloc::realloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
-note: inside `main` at $DIR/reallocate-dangling.rs:LL:CC
+note: inside `main`
   --> $DIR/reallocate-dangling.rs:LL:CC
    |
 LL |         let _z = realloc(x, Layout::from_size_align_unchecked(1, 1), 1);
index 44991542b135074d8fc1087f290fe7e74da10b6a..b1636050a78ca70972762891a49342f57d66049c 100644 (file)
@@ -12,7 +12,7 @@ LL |     unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) }
    = note: inside `alloc::alloc::box_free::<i32, std::alloc::Global>` at RUSTLIB/alloc/src/alloc.rs:LL:CC
    = note: inside `std::ptr::drop_in_place::<std::boxed::Box<i32>> - shim(Some(std::boxed::Box<i32>))` at RUSTLIB/core/src/ptr/mod.rs:LL:CC
    = note: inside `std::mem::drop::<std::boxed::Box<i32>>` at RUSTLIB/core/src/mem/mod.rs:LL:CC
-note: inside `main` at $DIR/stack_free.rs:LL:CC
+note: inside `main`
   --> $DIR/stack_free.rs:LL:CC
    |
 LL |     drop(bad_box);
index 83701639976877fae534904ea29c8d878643d99f..f57b52c4bda7a14943ba15cc87f305851f85c4d6 100644 (file)
@@ -21,7 +21,7 @@ LL |     let res = helper(val, ptr);
    |                      ^^^
    = note: BACKTRACE:
    = note: inside `helper` at $DIR/box-cell-alias.rs:LL:CC
-note: inside `main` at $DIR/box-cell-alias.rs:LL:CC
+note: inside `main`
   --> $DIR/box-cell-alias.rs:LL:CC
    |
 LL |     let res = helper(val, ptr);
index 20f34cf104d63f1b6f1f83c641ce34cf79b82600..7b297b260d87ab2ce141265147188e8a195132ce 100644 (file)
@@ -10,7 +10,7 @@ LL |         let rc = unsafe { c::WaitForSingleObject(self.handle.as_raw_handle(
    = note: inside `std::sys::PLATFORM::thread::Thread::join` at RUSTLIB/std/src/sys/PLATFORM/thread.rs:LL:CC
    = note: inside `std::thread::JoinInner::<'_, ()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC
    = note: inside `std::thread::JoinHandle::<()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC
-note: inside `main` at $DIR/windows_join_detached.rs:LL:CC
+note: inside `main`
   --> $DIR/windows_join_detached.rs:LL:CC
    |
 LL |     thread.join().unwrap();
index 5a80d1ac5a9b1a11245cd946448be605d02b9cc4..1e7dfaa7499041851561a4da9b354f1b33b6dd95 100644 (file)
@@ -6,7 +6,7 @@ LL |         let res = syscall!(epoll_create1(libc::EPOLL_CLOEXEC));
    |
    = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
    = note: BACKTRACE:
-note: inside `main` at $DIR/tokio_mvp.rs:LL:CC
+note: inside `main`
   --> $DIR/tokio_mvp.rs:LL:CC
    |
 LL | #[tokio::main]
index 72e5f20f924a42bfef5a3c184bff4590b6af6c2d..2ba8116cadc247ca710e303e2a2b2fd529c2cfd7 100644 (file)
@@ -8,7 +8,7 @@ LL |     unsafe { &mut *(LEAK as *mut i32) };
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `evil` at $DIR/storage_dead_dangling.rs:LL:CC
-note: inside `main` at $DIR/storage_dead_dangling.rs:LL:CC
+note: inside `main`
   --> $DIR/storage_dead_dangling.rs:LL:CC
    |
 LL |     evil();
index 5de27108ab633bcfa3e4e90a873bc1f4114e4a8a..0075f877b29dc9b12fb6afceaaaaad85a6e91938 100644 (file)
@@ -8,7 +8,7 @@ LL | }
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `race` at $DIR/stack_pop_race.rs:LL:CC
-note: inside `main` at $DIR/stack_pop_race.rs:LL:CC
+note: inside `main`
   --> $DIR/stack_pop_race.rs:LL:CC
    |
 LL |     race(0);
index 7d9302e3e3adc27c171cfb5d09c24800ea7f2fb5..484f703f9c1b52dba2f20f664a4a73eb45174e99 100644 (file)
@@ -11,7 +11,7 @@ LL | | }
    | |_^ the program aborted execution
    |
    = note: inside `nounwind` at $DIR/exported_symbol_bad_unwind2.rs:LL:CC
-note: inside `main` at $DIR/exported_symbol_bad_unwind2.rs:LL:CC
+note: inside `main`
   --> $DIR/exported_symbol_bad_unwind2.rs:LL:CC
    |
 LL |     unsafe { nounwind() }
index 7d9302e3e3adc27c171cfb5d09c24800ea7f2fb5..484f703f9c1b52dba2f20f664a4a73eb45174e99 100644 (file)
@@ -11,7 +11,7 @@ LL | | }
    | |_^ the program aborted execution
    |
    = note: inside `nounwind` at $DIR/exported_symbol_bad_unwind2.rs:LL:CC
-note: inside `main` at $DIR/exported_symbol_bad_unwind2.rs:LL:CC
+note: inside `main`
   --> $DIR/exported_symbol_bad_unwind2.rs:LL:CC
    |
 LL |     unsafe { nounwind() }
index 4f73671a7894796a7fc577e0f6171cf0f21173bb..80c5794736a9f9b1bcc309e3262cd4482bf8902d 100644 (file)
@@ -8,13 +8,13 @@ LL |         *num += 1;
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside closure at $DIR/generator-pinned-moved.rs:LL:CC
-note: inside `<GeneratorIteratorAdapter<[static generator@$DIR/generator-pinned-moved.rs:LL:CC]> as std::iter::Iterator>::next` at $DIR/generator-pinned-moved.rs:LL:CC
+note: inside `<GeneratorIteratorAdapter<[static generator@$DIR/generator-pinned-moved.rs:LL:CC]> as std::iter::Iterator>::next`
   --> $DIR/generator-pinned-moved.rs:LL:CC
    |
 LL |         match me.resume(()) {
    |               ^^^^^^^^^^^^^
    = note: inside `<std::boxed::Box<GeneratorIteratorAdapter<[static generator@$DIR/generator-pinned-moved.rs:LL:CC]>> as std::iter::Iterator>::next` at RUSTLIB/alloc/src/boxed.rs:LL:CC
-note: inside `main` at $DIR/generator-pinned-moved.rs:LL:CC
+note: inside `main`
   --> $DIR/generator-pinned-moved.rs:LL:CC
    |
 LL |     generator_iterator_2.next(); // and use moved value
index 36bb9643b48d4aa8517f24f56894b77b8e2cfe8b..5c73c76a1613d3119ca8eae60cf92dcc880d6d1b 100644 (file)
@@ -8,7 +8,7 @@ LL |         unsafe { intrinsics::simd_cast(self) }
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `std::simd::Simd::<f32, 2>::to_int_unchecked::<i32>` at RUSTLIB/core/src/../../portable-simd/crates/core_simd/src/vector.rs:LL:CC
-note: inside `main` at $DIR/simd-float-to-int.rs:LL:CC
+note: inside `main`
   --> $DIR/simd-float-to-int.rs:LL:CC
    |
 LL |         let _x: i32x2 = f32x2::from_array([f32::MAX, f32::MIN]).to_int_unchecked();
index 29a4ef65705ab13d58d5a44b67ea3df531b6c165..7512d57f6720e3836a21d8044882923fe665169f 100644 (file)
@@ -8,7 +8,7 @@ LL |         unsafe { intrinsics::simd_gather(or, ptrs, enable.to_int()) }
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `std::simd::Simd::<i8, 4>::gather_select_unchecked` at RUSTLIB/core/src/../../portable-simd/crates/core_simd/src/vector.rs:LL:CC
-note: inside `main` at $DIR/simd-gather.rs:LL:CC
+note: inside `main`
   --> $DIR/simd-gather.rs:LL:CC
    |
 LL |         let _result = Simd::gather_select_unchecked(&vec, Mask::splat(true), idxs, Simd::splat(0));
index fde85a63503b6bf085915d5b8f46eb55b711740b..a9ad60a0e5be2218a57b1a29b5b5cf5afbfccd1f 100644 (file)
@@ -8,7 +8,7 @@ LL |             intrinsics::simd_scatter(self, ptrs, enable.to_int())
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `std::simd::Simd::<i8, 4>::scatter_select_unchecked` at RUSTLIB/core/src/../../portable-simd/crates/core_simd/src/vector.rs:LL:CC
-note: inside `main` at $DIR/simd-scatter.rs:LL:CC
+note: inside `main`
   --> $DIR/simd-scatter.rs:LL:CC
    |
 LL | /         Simd::from_array([-27, 82, -41, 124]).scatter_select_unchecked(
index e6644a72849ff6c63172be08e03102e8bd2861da..f1cb50ab9be788b384ed98693b0812f7baa2142c 100644 (file)
@@ -8,7 +8,7 @@ LL |         let obj = std::mem::transmute::<FatPointer, *mut FunnyPointer>(obj)
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `FunnyPointer::from_data_ptr` at $DIR/issue-miri-1112.rs:LL:CC
-note: inside `main` at $DIR/issue-miri-1112.rs:LL:CC
+note: inside `main`
   --> $DIR/issue-miri-1112.rs:LL:CC
    |
 LL |         let _raw: &FunnyPointer = FunnyPointer::from_data_ptr(&hello, &meta as *const _);
index 4c3a3d075f02843f802af644759acde725e624ab..413172b25464a683451b6652cced69565b029d4c 100644 (file)
@@ -8,7 +8,7 @@ LL |         match v.0 {}
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `m::f` at $DIR/never_transmute_void.rs:LL:CC
-note: inside `main` at $DIR/never_transmute_void.rs:LL:CC
+note: inside `main`
   --> $DIR/never_transmute_void.rs:LL:CC
    |
 LL |     m::f(v);
index 23c33f5e7f3ff0409dd91ed84f820ff7446161be..5d7f01f4786561ffe5700a2927c47672d56f867a 100644 (file)
@@ -13,7 +13,7 @@ LL |     std::panic::catch_unwind(|| unwind()).unwrap_err();
    = note: inside `std::panicking::r#try::do_call::<[closure@$DIR/bad_unwind.rs:LL:CC], ()>` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside `std::panicking::r#try::<(), [closure@$DIR/bad_unwind.rs:LL:CC]>` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside `std::panic::catch_unwind::<[closure@$DIR/bad_unwind.rs:LL:CC], ()>` at RUSTLIB/std/src/panic.rs:LL:CC
-note: inside `main` at $DIR/bad_unwind.rs:LL:CC
+note: inside `main`
   --> $DIR/bad_unwind.rs:LL:CC
    |
 LL |     std::panic::catch_unwind(|| unwind()).unwrap_err();
index f1d2b4de97cc2f0847f702146fbf5c89dfc118e9..6bf13f21601503766daadfb984df0585078d9511 100644 (file)
@@ -75,13 +75,13 @@ LL |     ABORT();
    = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::rt::begin_panic<&str>::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
-note: inside `<Foo as std::ops::Drop>::drop` at RUSTLIB/std/src/panic.rs:LL:CC
+note: inside `<Foo as std::ops::Drop>::drop`
   --> $DIR/double_panic.rs:LL:CC
    |
 LL |         panic!("second");
    | ^
    = note: inside `std::ptr::drop_in_place::<Foo> - shim(Some(Foo))` at RUSTLIB/core/src/ptr/mod.rs:LL:CC
-note: inside `main` at $DIR/double_panic.rs:LL:CC
+note: inside `main`
   --> $DIR/double_panic.rs:LL:CC
    |
 LL | }
index 568b286e1d3bf5733984e3273f00801d74b8282a..39ad0d268b94ea9b9e58f515a1b3e467abf32efe 100644 (file)
@@ -6,7 +6,7 @@ LL |     core::intrinsics::abort();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ the program aborted execution
    |
    = note: inside `panic_handler` at $DIR/no_std.rs:LL:CC
-note: inside `start` at RUSTLIB/core/src/panic.rs:LL:CC
+note: inside `start`
   --> $DIR/no_std.rs:LL:CC
    |
 LL |     panic!("blarg I am dead")
index 75471994546431d4c01d837c3b544838d79aa0d4..d25dd7be63596e3761edc033cef1df496d65cfac 100644 (file)
@@ -12,7 +12,7 @@ LL |                 ABORT();
    = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::rt::begin_panic<&str>::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
-note: inside `main` at RUSTLIB/std/src/panic.rs:LL:CC
+note: inside `main`
   --> $DIR/panic_abort1.rs:LL:CC
    |
 LL |     std::panic!("panicking from libstd");
index 2fdf889d798a2b3d668ccb8596621565f84b2202..f56d509a697b4661f22c9e9bf092adf87a05bdcc 100644 (file)
@@ -13,7 +13,7 @@ LL |                 ABORT();
    = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
    = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
-note: inside `main` at RUSTLIB/std/src/panic.rs:LL:CC
+note: inside `main`
   --> $DIR/panic_abort2.rs:LL:CC
    |
 LL |     std::panic!("{}-panicking from libstd", 42);
index 8704b0d940b7a5ce7eb12039e36992b96f2bd32d..43792f769930b6a7964dce2220018619d03cfccc 100644 (file)
@@ -13,7 +13,7 @@ LL |                 ABORT();
    = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
    = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
-note: inside `main` at RUSTLIB/core/src/panic.rs:LL:CC
+note: inside `main`
   --> $DIR/panic_abort3.rs:LL:CC
    |
 LL |     core::panic!("panicking from libcore");
index 1d75d72c0317cf777ecd2e44ca9d39acf179737e..89e181bfb276c984a5deb2bb9eee286fbe09d8d5 100644 (file)
@@ -13,7 +13,7 @@ LL |                 ABORT();
    = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
    = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
-note: inside `main` at RUSTLIB/core/src/panic.rs:LL:CC
+note: inside `main`
   --> $DIR/panic_abort4.rs:LL:CC
    |
 LL |     core::panic!("{}-panicking from libcore", 42);
index f7c5f6046e198f14b733c5b1883a7209a73b78ad..042d8cd4afe79a99d13573491d3925a3b85c5f46 100644 (file)
@@ -8,7 +8,7 @@ LL |         let _val = *left_ptr;
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `deref` at $DIR/provenance_transmute.rs:LL:CC
-note: inside `main` at $DIR/provenance_transmute.rs:LL:CC
+note: inside `main`
   --> $DIR/provenance_transmute.rs:LL:CC
    |
 LL |         deref(ptr1, ptr2.with_addr(ptr1.addr()));
index 269b1383aad68312bd2848831ce7cc25fd2bfb5b..2385439c8a5f7f85ae007287cfeb6e08313cf33b 100644 (file)
@@ -17,7 +17,7 @@ LL |         let fd = cvt_r(|| unsafe { open64(path.as_ptr(), flags, opts.mode a
    = note: inside `std::fs::OpenOptions::_open` at RUSTLIB/std/src/fs.rs:LL:CC
    = note: inside `std::fs::OpenOptions::open::<&std::path::Path>` at RUSTLIB/std/src/fs.rs:LL:CC
    = note: inside `std::fs::File::open::<&str>` at RUSTLIB/std/src/fs.rs:LL:CC
-note: inside `main` at $DIR/isolated_file.rs:LL:CC
+note: inside `main`
   --> $DIR/isolated_file.rs:LL:CC
    |
 LL |     let _file = std::fs::File::open("file.txt").unwrap();
index 414ac1cb1b70260184db2afb46636b990bc40e2c..35ff1926b065740d35e30966228e67c0af9d4e78 100644 (file)
@@ -8,7 +8,7 @@ LL |     let _fd = unsafe { libc::mkstemp(s) };
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `test_mkstemp_immutable_arg` at $DIR/mkstemp_immutable_arg.rs:LL:CC
-note: inside `main` at $DIR/mkstemp_immutable_arg.rs:LL:CC
+note: inside `main`
   --> $DIR/mkstemp_immutable_arg.rs:LL:CC
    |
 LL |     test_mkstemp_immutable_arg();
index 38d033b494554e243201f06d8c8956e8f566bad0..5a8e7352c768618f53b3cc47ef3b9b95481fc494 100644 (file)
@@ -8,7 +8,7 @@ LL | ...safe { libc::open(name_ptr, libc::O_CREAT) };
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `test_file_open_missing_needed_mode` at $DIR/unix_open_missing_required_mode.rs:LL:CC
-note: inside `main` at $DIR/unix_open_missing_required_mode.rs:LL:CC
+note: inside `main`
   --> $DIR/unix_open_missing_required_mode.rs:LL:CC
    |
 LL |     test_file_open_missing_needed_mode();
index 8a24b085a99f6f56e3f3280918db0b8295ec40d2..325565fa1e786aa327cd337838c91979fa9aa080 100644 (file)
@@ -8,7 +8,7 @@ LL |             std::hint::unreachable_unchecked();
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `test_cpp20_rwc_syncs` at $DIR/cpp20_rwc_syncs.rs:LL:CC
-note: inside `main` at $DIR/cpp20_rwc_syncs.rs:LL:CC
+note: inside `main`
   --> $DIR/cpp20_rwc_syncs.rs:LL:CC
    |
 LL |         test_cpp20_rwc_syncs();
index 268d253ad5b06c65b49b5d9ac60914c231ff0608..4514abb4ab2e47900200bc4dde0ababfa159fe4a 100644 (file)
@@ -18,7 +18,7 @@ LL | pub fn safe(_x: &mut i32, _y: &mut i32) {}
    |             ^^
    = note: BACKTRACE:
    = note: inside `safe` at $DIR/aliasing_mut1.rs:LL:CC
-note: inside `main` at $DIR/aliasing_mut1.rs:LL:CC
+note: inside `main`
   --> $DIR/aliasing_mut1.rs:LL:CC
    |
 LL |     safe_raw(xraw, xraw);
index 77a542f45a2566a5f61af86f328921e92d07c668..9ca9743cbd929be46fb3418a504316321bb3cc9c 100644 (file)
@@ -18,7 +18,7 @@ LL | pub fn safe(_x: &i32, _y: &mut i32) {}
    |             ^^
    = note: BACKTRACE:
    = note: inside `safe` at $DIR/aliasing_mut2.rs:LL:CC
-note: inside `main` at $DIR/aliasing_mut2.rs:LL:CC
+note: inside `main`
   --> $DIR/aliasing_mut2.rs:LL:CC
    |
 LL |     safe_raw(xshr, xraw);
index eb6b01fc6b12bfa02690ee435ce24717923aecd6..b504097a3c91f2541339f527e04e3edf93c545af 100644 (file)
@@ -21,7 +21,7 @@ LL |     safe_raw(xraw, xshr);
    |     ^^^^^^^^^^^^^^^^^^^^
    = note: BACKTRACE:
    = note: inside `safe` at $DIR/aliasing_mut3.rs:LL:CC
-note: inside `main` at $DIR/aliasing_mut3.rs:LL:CC
+note: inside `main`
   --> $DIR/aliasing_mut3.rs:LL:CC
    |
 LL |     safe_raw(xraw, xshr);
index e592b154a7326326da9226cf42c2876ba35f4699..6fe0d70902930fe864390ec1e7c0f9914d77dc21 100644 (file)
@@ -18,7 +18,7 @@ LL | pub fn safe(_x: &i32, _y: &mut Cell<i32>) {}
    |             ^^
    = note: BACKTRACE:
    = note: inside `safe` at $DIR/aliasing_mut4.rs:LL:CC
-note: inside `main` at $DIR/aliasing_mut4.rs:LL:CC
+note: inside `main`
   --> $DIR/aliasing_mut4.rs:LL:CC
    |
 LL |     safe_raw(xshr, xraw as *mut _);
index d82b8342f1231e9828a31bf1cd757859a1c3b04c..f114130f6fafdabece908fc8999b7a357ffc0d0e 100644 (file)
@@ -21,12 +21,12 @@ LL |     *our = 5;
    |     ^^^^^^^^
    = note: BACKTRACE:
    = note: inside `unknown_code_2` at $DIR/box_exclusive_violation1.rs:LL:CC
-note: inside `demo_box_advanced_unique` at $DIR/box_exclusive_violation1.rs:LL:CC
+note: inside `demo_box_advanced_unique`
   --> $DIR/box_exclusive_violation1.rs:LL:CC
    |
 LL |     unknown_code_2();
    |     ^^^^^^^^^^^^^^^^
-note: inside `main` at $DIR/box_exclusive_violation1.rs:LL:CC
+note: inside `main`
   --> $DIR/box_exclusive_violation1.rs:LL:CC
    |
 LL |     demo_box_advanced_unique(Box::new(0));
index 3c84cbcfd5182a0b543111003d38052a8e498bb4..139fcd0ca4583d67502bb5e41081831f0b902093 100644 (file)
@@ -18,7 +18,7 @@ LL | unsafe fn test(mut x: Box<i32>, y: *const i32) -> i32 {
    |                ^^^^^
    = note: BACKTRACE:
    = note: inside `test` at $DIR/box_noalias_violation.rs:LL:CC
-note: inside `main` at $DIR/box_noalias_violation.rs:LL:CC
+note: inside `main`
   --> $DIR/box_noalias_violation.rs:LL:CC
    |
 LL |         test(Box::from_raw(ptr), ptr);
index bb3eaec1e85c0da033b0f68073849a304ae21b71..516964b9a4e6f11a95cc3195d2af7da83ab5ef86 100644 (file)
@@ -12,18 +12,18 @@ LL |     unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) }
    = note: inside `alloc::alloc::box_free::<i32, std::alloc::Global>` at RUSTLIB/alloc/src/alloc.rs:LL:CC
    = note: inside `std::ptr::drop_in_place::<std::boxed::Box<i32>> - shim(Some(std::boxed::Box<i32>))` at RUSTLIB/core/src/ptr/mod.rs:LL:CC
    = note: inside `std::mem::drop::<std::boxed::Box<i32>>` at RUSTLIB/core/src/mem/mod.rs:LL:CC
-note: inside closure at $DIR/deallocate_against_protector1.rs:LL:CC
+note: inside closure
   --> $DIR/deallocate_against_protector1.rs:LL:CC
    |
 LL |         drop(unsafe { Box::from_raw(raw) });
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: inside `<[closure@$DIR/deallocate_against_protector1.rs:LL:CC] as std::ops::FnOnce<(&mut i32,)>>::call_once - shim` at RUSTLIB/core/src/ops/function.rs:LL:CC
-note: inside `inner` at $DIR/deallocate_against_protector1.rs:LL:CC
+note: inside `inner`
   --> $DIR/deallocate_against_protector1.rs:LL:CC
    |
 LL |     f(x)
    |     ^^^^
-note: inside `main` at $DIR/deallocate_against_protector1.rs:LL:CC
+note: inside `main`
   --> $DIR/deallocate_against_protector1.rs:LL:CC
    |
 LL | /     inner(Box::leak(Box::new(0)), |x| {
index 25bab1aa564a65a0145bb1506cda9ded5c95e453..47cfa0de7258c1fe0263442c8387a6d7b3d7a7d9 100644 (file)
@@ -12,18 +12,18 @@ LL |     unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) }
    = note: inside `alloc::alloc::box_free::<NotUnpin, std::alloc::Global>` at RUSTLIB/alloc/src/alloc.rs:LL:CC
    = note: inside `std::ptr::drop_in_place::<std::boxed::Box<NotUnpin>> - shim(Some(std::boxed::Box<NotUnpin>))` at RUSTLIB/core/src/ptr/mod.rs:LL:CC
    = note: inside `std::mem::drop::<std::boxed::Box<NotUnpin>>` at RUSTLIB/core/src/mem/mod.rs:LL:CC
-note: inside closure at $DIR/deallocate_against_protector2.rs:LL:CC
+note: inside closure
   --> $DIR/deallocate_against_protector2.rs:LL:CC
    |
 LL |         drop(unsafe { Box::from_raw(raw) });
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: inside `<[closure@$DIR/deallocate_against_protector2.rs:LL:CC] as std::ops::FnOnce<(&mut NotUnpin,)>>::call_once - shim` at RUSTLIB/core/src/ops/function.rs:LL:CC
-note: inside `inner` at $DIR/deallocate_against_protector2.rs:LL:CC
+note: inside `inner`
   --> $DIR/deallocate_against_protector2.rs:LL:CC
    |
 LL |     f(x)
    |     ^^^^
-note: inside `main` at $DIR/deallocate_against_protector2.rs:LL:CC
+note: inside `main`
   --> $DIR/deallocate_against_protector2.rs:LL:CC
    |
 LL | /     inner(Box::leak(Box::new(NotUnpin(0, PhantomPinned))), |x| {
index 3b7802901a54eb723ddf23ae38b9b557d1772a2c..f2f13d0d5594ea1215bf7f43a95560e05325a390 100644 (file)
@@ -18,7 +18,7 @@ LL |         ptr1.write(0);
    |         ^^^^^^^^^^^^^
    = note: BACKTRACE:
    = note: inside `std::alloc::dealloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
-note: inside `main` at $DIR/illegal_deALLOC.rs:LL:CC
+note: inside `main`
   --> $DIR/illegal_deALLOC.rs:LL:CC
    |
 LL |         dealloc(ptr2, Layout::from_size_align_unchecked(1, 1));
index 1a627b8a883009f07818308cbe6f48f916bb21ac..49d9050f3094771d1f44672fec01770dc6b0c89c 100644 (file)
@@ -18,7 +18,7 @@ LL | fn foo(a: &mut u32, y: *mut u32) -> u32 {
    |        ^
    = note: BACKTRACE:
    = note: inside `foo` at $DIR/illegal_write6.rs:LL:CC
-note: inside `main` at $DIR/illegal_write6.rs:LL:CC
+note: inside `main`
   --> $DIR/illegal_write6.rs:LL:CC
    |
 LL |     foo(x, p);
index 1ef36b7ac10fc4c5005ded98d127b7968315d580..a53c633c3813076df0bc1a336970017d5430fc5a 100644 (file)
@@ -18,7 +18,7 @@ LL | fn inner(x: *mut i32, _y: &mut i32) {
    |                       ^^
    = note: BACKTRACE:
    = note: inside `inner` at $DIR/invalidate_against_protector1.rs:LL:CC
-note: inside `main` at $DIR/invalidate_against_protector1.rs:LL:CC
+note: inside `main`
   --> $DIR/invalidate_against_protector1.rs:LL:CC
    |
 LL |     inner(xraw, xref);
index 941b936e5d7249443852d9692444911c5cd8c898..6ee78d1aac682fd9c79e4286525f627dcf37e269 100644 (file)
@@ -18,7 +18,7 @@ LL | fn inner(x: *mut i32, _y: &i32) {
    |                       ^^
    = note: BACKTRACE:
    = note: inside `inner` at $DIR/invalidate_against_protector2.rs:LL:CC
-note: inside `main` at $DIR/invalidate_against_protector2.rs:LL:CC
+note: inside `main`
   --> $DIR/invalidate_against_protector2.rs:LL:CC
    |
 LL |     inner(xraw, xref);
index 176a859ee8af7692d4b1673d1ce96b03eff79019..2b38dea9dbb719221b89285fd97ba785fd53fa6a 100644 (file)
@@ -18,7 +18,7 @@ LL | fn inner(x: *mut i32, _y: &i32) {
    |                       ^^
    = note: BACKTRACE:
    = note: inside `inner` at $DIR/invalidate_against_protector3.rs:LL:CC
-note: inside `main` at $DIR/invalidate_against_protector3.rs:LL:CC
+note: inside `main`
   --> $DIR/invalidate_against_protector3.rs:LL:CC
    |
 LL |         inner(ptr, &*ptr);
index 16c8810a8e6d90f80cc4ba1361c6eaf3c385890c..c69a3af293c13b1e6b59556a00cf6b64088cb780 100644 (file)
@@ -9,7 +9,7 @@ LL |         Box(unsafe { Unique::new_unchecked(raw) }, alloc)
    = note: BACKTRACE:
    = note: inside `std::boxed::Box::<u32>::from_raw_in` at RUSTLIB/alloc/src/boxed.rs:LL:CC
    = note: inside `std::boxed::Box::<u32>::from_raw` at RUSTLIB/alloc/src/boxed.rs:LL:CC
-note: inside `main` at $DIR/issue-miri-1050-1.rs:LL:CC
+note: inside `main`
   --> $DIR/issue-miri-1050-1.rs:LL:CC
    |
 LL |         drop(Box::from_raw(ptr as *mut u32));
index d57e7662e504aea7fd7959077d72b17e6353f991..23d7fdcd03bc5a3333d409cf0242696b66557ae5 100644 (file)
@@ -9,7 +9,7 @@ LL |         Box(unsafe { Unique::new_unchecked(raw) }, alloc)
    = note: BACKTRACE:
    = note: inside `std::boxed::Box::<i32>::from_raw_in` at RUSTLIB/alloc/src/boxed.rs:LL:CC
    = note: inside `std::boxed::Box::<i32>::from_raw` at RUSTLIB/alloc/src/boxed.rs:LL:CC
-note: inside `main` at $DIR/issue-miri-1050-2.rs:LL:CC
+note: inside `main`
   --> $DIR/issue-miri-1050-2.rs:LL:CC
    |
 LL |         drop(Box::from_raw(ptr.as_ptr()));
index 1c7f8e12d3d78977b4e6c751f7ee822a7137908f..2f3900c40d7261fd8f342e6ecc94d2eacc6e3f07 100644 (file)
@@ -21,12 +21,12 @@ LL |     *our = 5;
    |     ^^^^^^^^
    = note: BACKTRACE:
    = note: inside `unknown_code_2` at $DIR/mut_exclusive_violation1.rs:LL:CC
-note: inside `demo_mut_advanced_unique` at $DIR/mut_exclusive_violation1.rs:LL:CC
+note: inside `demo_mut_advanced_unique`
   --> $DIR/mut_exclusive_violation1.rs:LL:CC
    |
 LL |     unknown_code_2();
    |     ^^^^^^^^^^^^^^^^
-note: inside `main` at $DIR/mut_exclusive_violation1.rs:LL:CC
+note: inside `main`
   --> $DIR/mut_exclusive_violation1.rs:LL:CC
    |
 LL |     demo_mut_advanced_unique(&mut 0);
index 70186dd3a53f3305d9b8622fadf83448f1aae9ad..90677dfaf555e4c8226919cb89f3d08cca536384 100644 (file)
@@ -19,17 +19,17 @@ LL | fn dealloc_while_running(_n: Newtype<'_>, dealloc: impl FnOnce()) {
    = note: BACKTRACE:
    = note: inside `std::boxed::Box::<i32>::from_raw_in` at RUSTLIB/alloc/src/boxed.rs:LL:CC
    = note: inside `std::boxed::Box::<i32>::from_raw` at RUSTLIB/alloc/src/boxed.rs:LL:CC
-note: inside closure at $DIR/newtype_pair_retagging.rs:LL:CC
+note: inside closure
   --> $DIR/newtype_pair_retagging.rs:LL:CC
    |
 LL |             || drop(Box::from_raw(ptr)),
    |                     ^^^^^^^^^^^^^^^^^^
-note: inside `dealloc_while_running::<[closure@$DIR/newtype_pair_retagging.rs:LL:CC]>` at $DIR/newtype_pair_retagging.rs:LL:CC
+note: inside `dealloc_while_running::<[closure@$DIR/newtype_pair_retagging.rs:LL:CC]>`
   --> $DIR/newtype_pair_retagging.rs:LL:CC
    |
 LL |     dealloc();
    |     ^^^^^^^^^
-note: inside `main` at $DIR/newtype_pair_retagging.rs:LL:CC
+note: inside `main`
   --> $DIR/newtype_pair_retagging.rs:LL:CC
    |
 LL | /         dealloc_while_running(
index 69fa27c9c096fef7f6e6c1a3e6a6dfe9287165d5..f189d0483d12d9e459ed3862d1259375ff1cc5f6 100644 (file)
@@ -19,17 +19,17 @@ LL | fn dealloc_while_running(_n: Newtype<'_>, dealloc: impl FnOnce()) {
    = note: BACKTRACE:
    = note: inside `std::boxed::Box::<i32>::from_raw_in` at RUSTLIB/alloc/src/boxed.rs:LL:CC
    = note: inside `std::boxed::Box::<i32>::from_raw` at RUSTLIB/alloc/src/boxed.rs:LL:CC
-note: inside closure at $DIR/newtype_retagging.rs:LL:CC
+note: inside closure
   --> $DIR/newtype_retagging.rs:LL:CC
    |
 LL |             || drop(Box::from_raw(ptr)),
    |                     ^^^^^^^^^^^^^^^^^^
-note: inside `dealloc_while_running::<[closure@$DIR/newtype_retagging.rs:LL:CC]>` at $DIR/newtype_retagging.rs:LL:CC
+note: inside `dealloc_while_running::<[closure@$DIR/newtype_retagging.rs:LL:CC]>`
   --> $DIR/newtype_retagging.rs:LL:CC
    |
 LL |     dealloc();
    |     ^^^^^^^^^
-note: inside `main` at $DIR/newtype_retagging.rs:LL:CC
+note: inside `main`
   --> $DIR/newtype_retagging.rs:LL:CC
    |
 LL | /         dealloc_while_running(
index 6415af1e18bbff221179930289e7bc9837cb8c49..7d58d1aebbecd6154df1cbb535942b3b4356f735 100644 (file)
@@ -21,7 +21,7 @@ LL |     *val = 2; // this invalidates any raw ptrs `fun1` might have created.
    |     ^^^^^^^^
    = note: BACKTRACE:
    = note: inside `fun2` at $DIR/pointer_smuggling.rs:LL:CC
-note: inside `main` at $DIR/pointer_smuggling.rs:LL:CC
+note: inside `main`
   --> $DIR/pointer_smuggling.rs:LL:CC
    |
 LL |     fun2(); // if they now use a raw ptr they break our reference
index f25d689524d1b3c86a565ea215a7ec5034a5e03a..5dc936f0707443f5805196e164c647ff5c17a238 100644 (file)
@@ -8,7 +8,7 @@ LL |         *p = 5;
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `thread_2` at $DIR/retag_data_race_read.rs:LL:CC
-note: inside closure at $DIR/retag_data_race_read.rs:LL:CC
+note: inside closure
   --> $DIR/retag_data_race_read.rs:LL:CC
    |
 LL |     let t2 = std::thread::spawn(move || thread_2(p));
index f97e6bb11e9d674a7535cfef0329d4c8397f61aa..03c2450356416586a3d153f6261e01dec8f2c9e2 100644 (file)
@@ -8,7 +8,7 @@ LL |         *p = 5;
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `thread_2` at $DIR/retag_data_race_write.rs:LL:CC
-note: inside closure at $DIR/retag_data_race_write.rs:LL:CC
+note: inside closure
   --> $DIR/retag_data_race_write.rs:LL:CC
    |
 LL |     let t2 = std::thread::spawn(move || thread_2(p));
index 9deb0c41742f35ea5de0566ecc74e97186e3d58b..1b28f780c1c544a63f0ca9d9850f4539d77f4c09 100644 (file)
@@ -21,7 +21,7 @@ LL |     let _val = unsafe { *xraw }; // invalidate xref
    |                         ^^^^^
    = note: BACKTRACE:
    = note: inside `foo` at $DIR/return_invalid_mut.rs:LL:CC
-note: inside `main` at $DIR/return_invalid_mut.rs:LL:CC
+note: inside `main`
   --> $DIR/return_invalid_mut.rs:LL:CC
    |
 LL |     foo(&mut (1, 2));
index c0ff35ebcde307aa39834ff5a11314ee51345033..db14dcafa008445530d4629312495cc4629ff18d 100644 (file)
@@ -21,7 +21,7 @@ LL |     let _val = unsafe { *xraw }; // invalidate xref
    |                         ^^^^^
    = note: BACKTRACE:
    = note: inside `foo` at $DIR/return_invalid_mut_option.rs:LL:CC
-note: inside `main` at $DIR/return_invalid_mut_option.rs:LL:CC
+note: inside `main`
   --> $DIR/return_invalid_mut_option.rs:LL:CC
    |
 LL |     match foo(&mut (1, 2)) {
index 9abf43c29f08fb3e44601d09e248eeff7288fe9c..81ed4218aade789d54d5ad5598725c862ec98b04 100644 (file)
@@ -21,7 +21,7 @@ LL |     let _val = unsafe { *xraw }; // invalidate xref
    |                         ^^^^^
    = note: BACKTRACE:
    = note: inside `foo` at $DIR/return_invalid_mut_tuple.rs:LL:CC
-note: inside `main` at $DIR/return_invalid_mut_tuple.rs:LL:CC
+note: inside `main`
   --> $DIR/return_invalid_mut_tuple.rs:LL:CC
    |
 LL |     foo(&mut (1, 2)).0;
index dd651517c2fb083b5dae72826dae09955f39ddfc..9c8cc50b2d7ac7b4c87399b9f1ecd4c99a6b34d0 100644 (file)
@@ -21,7 +21,7 @@ LL |     unsafe { *xraw = (42, 23) }; // unfreeze
    |              ^^^^^^^^^^^^^^^^
    = note: BACKTRACE:
    = note: inside `foo` at $DIR/return_invalid_shr.rs:LL:CC
-note: inside `main` at $DIR/return_invalid_shr.rs:LL:CC
+note: inside `main`
   --> $DIR/return_invalid_shr.rs:LL:CC
    |
 LL |     foo(&mut (1, 2));
index 6066bf89f5d095806cab091431260eebca461801..00ce6f6cd5fe129e6f13fe9c26c32b1fcc2440e3 100644 (file)
@@ -21,7 +21,7 @@ LL |     unsafe { *xraw = (42, 23) }; // unfreeze
    |              ^^^^^^^^^^^^^^^^
    = note: BACKTRACE:
    = note: inside `foo` at $DIR/return_invalid_shr_option.rs:LL:CC
-note: inside `main` at $DIR/return_invalid_shr_option.rs:LL:CC
+note: inside `main`
   --> $DIR/return_invalid_shr_option.rs:LL:CC
    |
 LL |     match foo(&mut (1, 2)) {
index 52d365246a74441852bee7c4f2912844c3933159..bbd17b1284c5e6b9508cf5e55de49edd544771a5 100644 (file)
@@ -21,7 +21,7 @@ LL |     unsafe { *xraw = (42, 23) }; // unfreeze
    |              ^^^^^^^^^^^^^^^^
    = note: BACKTRACE:
    = note: inside `foo` at $DIR/return_invalid_shr_tuple.rs:LL:CC
-note: inside `main` at $DIR/return_invalid_shr_tuple.rs:LL:CC
+note: inside `main`
   --> $DIR/return_invalid_shr_tuple.rs:LL:CC
    |
 LL |     foo(&mut (1, 2)).0;
index 0818d07da48e5e776a7f3cae4bd04343a2e6829e..fe0ac211318aac832bd587bf2a4a69fbc3b1fbcf 100644 (file)
@@ -16,12 +16,12 @@ LL |         *(x as *const i32 as *mut i32) = 7;
    |           ^
    = note: BACKTRACE:
    = note: inside `unknown_code` at $DIR/shr_frozen_violation1.rs:LL:CC
-note: inside `foo` at $DIR/shr_frozen_violation1.rs:LL:CC
+note: inside `foo`
   --> $DIR/shr_frozen_violation1.rs:LL:CC
    |
 LL |     unknown_code(&*x);
    |     ^^^^^^^^^^^^^^^^^
-note: inside `main` at $DIR/shr_frozen_violation1.rs:LL:CC
+note: inside `main`
   --> $DIR/shr_frozen_violation1.rs:LL:CC
    |
 LL |     println!("{}", foo(&mut 0));
index 86f1da1f70a33de4b1d549a906bf0051bce68101..e134ee2845d05ea1871bdb3a23b3d1490cd09846 100644 (file)
@@ -16,7 +16,7 @@ LL |         assert_eq!(*s.get_unchecked(1), 2);
    |                     ^^^^^^^^^^^^^^^^^^
    = note: BACKTRACE:
    = note: inside `core::slice::<impl [i32]>::get_unchecked::<usize>` at RUSTLIB/core/src/slice/mod.rs:LL:CC
-note: inside `main` at $DIR/zst_slice.rs:LL:CC
+note: inside `main`
   --> $DIR/zst_slice.rs:LL:CC
    |
 LL |         assert_eq!(*s.get_unchecked(1), 2);
index a543d59addb145d15057a552d18d79bd7829664e..8da532cfff05b38e458ce1052eb8ac2f13380ad1 100644 (file)
@@ -9,7 +9,7 @@ LL |         let mut order = unsafe { memcmp(left.as_ptr(), right.as_ptr(), len)
    = note: BACKTRACE:
    = note: inside `<u8 as core::slice::cmp::SliceOrd>::compare` at RUSTLIB/core/src/slice/cmp.rs:LL:CC
    = note: inside `core::slice::cmp::<impl std::cmp::Ord for [u8]>::cmp` at RUSTLIB/core/src/slice/cmp.rs:LL:CC
-note: inside `main` at $DIR/uninit_buffer.rs:LL:CC
+note: inside `main`
   --> $DIR/uninit_buffer.rs:LL:CC
    |
 LL |         drop(slice1.cmp(slice2));
index 715d76aa1c2e75a6b4f8002cd9bd852c27798c51..210fc8e109aa4843d90de139b0235150c1540685 100644 (file)
@@ -9,7 +9,7 @@ LL |         let mut order = unsafe { memcmp(left.as_ptr(), right.as_ptr(), len)
    = note: BACKTRACE:
    = note: inside `<u8 as core::slice::cmp::SliceOrd>::compare` at RUSTLIB/core/src/slice/cmp.rs:LL:CC
    = note: inside `core::slice::cmp::<impl std::cmp::Ord for [u8]>::cmp` at RUSTLIB/core/src/slice/cmp.rs:LL:CC
-note: inside `main` at $DIR/uninit_buffer_with_provenance.rs:LL:CC
+note: inside `main`
   --> $DIR/uninit_buffer_with_provenance.rs:LL:CC
    |
 LL |         drop(slice1.cmp(slice2));
index 0001a8dd6eb3376ef463e2777fad597d9dfbe49d..4c2fb40e1102179641d96233433afc38aedb4b8b 100644 (file)
@@ -12,7 +12,7 @@ LL |         let r2 = ((r as usize) + 0) as *mut i32;
    = help: Alternatively, the `-Zmiri-permissive-provenance` flag disables this warning.
    = note: BACKTRACE:
    = note: inside `into_raw` at $DIR/box.rs:LL:CC
-note: inside `main` at $DIR/box.rs:LL:CC
+note: inside `main`
   --> $DIR/box.rs:LL:CC
    |
 LL |     into_raw();
@@ -25,7 +25,7 @@ LL |         let r = ((u.as_ptr() as usize) + 0) as *mut i32;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ integer-to-pointer cast
    |
    = note: inside `into_unique` at $DIR/box.rs:LL:CC
-note: inside `main` at $DIR/box.rs:LL:CC
+note: inside `main`
   --> $DIR/box.rs:LL:CC
    |
 LL |     into_unique();
index 8e7c39e72b68bddf1dd817c524adc4f31bc432db..c1450aedc31406edb76091c475999f6d7b109487 100644 (file)
@@ -46,6 +46,7 @@ macro_rules! t {
 struct Config {
     verbose: bool,
     sequential: bool,
+    batch: bool,
     bind: SocketAddr,
 }
 
@@ -54,6 +55,7 @@ pub fn default() -> Config {
         Config {
             verbose: false,
             sequential: false,
+            batch: false,
             bind: if cfg!(target_os = "android") || cfg!(windows) {
                 ([0, 0, 0, 0], 12345).into()
             } else {
@@ -75,6 +77,7 @@ pub fn parse_args() -> Config {
                 }
                 "--bind" => next_is_bind = true,
                 "--sequential" => config.sequential = true,
+                "--batch" => config.batch = true,
                 "--verbose" | "-v" => config.verbose = true,
                 "--help" | "-h" => {
                     show_help();
@@ -100,6 +103,7 @@ fn show_help() {
 OPTIONS:
     --bind <IP>:<PORT>   Specify IP address and port to listen for requests, e.g. "0.0.0.0:12345"
     --sequential         Run only one test at a time
+    --batch              Send stdout and stderr in batch instead of streaming
     -v, --verbose        Show status messages
     -h, --help           Show this help screen
 "#,
@@ -280,22 +284,30 @@ fn handle_run(socket: TcpStream, work: &Path, tmp: &Path, lock: &Mutex<()>, conf
     // Some tests assume RUST_TEST_TMPDIR exists
     cmd.env("RUST_TEST_TMPDIR", tmp.to_owned());
 
-    // Spawn the child and ferry over stdout/stderr to the socket in a framed
-    // fashion (poor man's style)
-    let mut child =
-        t!(cmd.stdin(Stdio::null()).stdout(Stdio::piped()).stderr(Stdio::piped()).spawn());
-    drop(lock);
-    let mut stdout = child.stdout.take().unwrap();
-    let mut stderr = child.stderr.take().unwrap();
     let socket = Arc::new(Mutex::new(reader.into_inner()));
-    let socket2 = socket.clone();
-    let thread = thread::spawn(move || my_copy(&mut stdout, 0, &*socket2));
-    my_copy(&mut stderr, 1, &*socket);
-    thread.join().unwrap();
 
-    // Finally send over the exit status.
-    let status = t!(child.wait());
+    let status = if config.batch {
+        let child =
+            t!(cmd.stdin(Stdio::null()).stdout(Stdio::piped()).stderr(Stdio::piped()).output());
+        batch_copy(&child.stdout, 0, &*socket);
+        batch_copy(&child.stderr, 1, &*socket);
+        child.status
+    } else {
+        // Spawn the child and ferry over stdout/stderr to the socket in a framed
+        // fashion (poor man's style)
+        let mut child =
+            t!(cmd.stdin(Stdio::null()).stdout(Stdio::piped()).stderr(Stdio::piped()).spawn());
+        drop(lock);
+        let mut stdout = child.stdout.take().unwrap();
+        let mut stderr = child.stderr.take().unwrap();
+        let socket2 = socket.clone();
+        let thread = thread::spawn(move || my_copy(&mut stdout, 0, &*socket2));
+        my_copy(&mut stderr, 1, &*socket);
+        thread.join().unwrap();
+        t!(child.wait())
+    };
 
+    // Finally send over the exit status.
     let (which, code) = get_status_code(&status);
 
     t!(socket.lock().unwrap().write_all(&[
@@ -368,6 +380,17 @@ fn my_copy(src: &mut dyn Read, which: u8, dst: &Mutex<dyn Write>) {
     }
 }
 
+fn batch_copy(buf: &[u8], which: u8, dst: &Mutex<dyn Write>) {
+    let n = buf.len();
+    let mut dst = dst.lock().unwrap();
+    t!(dst.write_all(&[which, (n >> 24) as u8, (n >> 16) as u8, (n >> 8) as u8, (n >> 0) as u8,]));
+    if n > 0 {
+        t!(dst.write_all(buf));
+        // Marking buf finished
+        t!(dst.write_all(&[which, 0, 0, 0, 0,]));
+    }
+}
+
 fn read_u32(r: &mut dyn Read) -> u32 {
     let mut len = [0; 4];
     t!(r.read_exact(&mut len));
index 2ac703b957b86456b1784119dfae6d31324af1c4..c503eeeb9b3b950e387d7b8b0e6a82dcd40a226b 100644 (file)
@@ -260,7 +260,9 @@ impl Rewrite for ast::NestedMetaItem {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
         match self {
             ast::NestedMetaItem::MetaItem(ref meta_item) => meta_item.rewrite(context, shape),
-            ast::NestedMetaItem::Lit(ref l) => rewrite_literal(context, l.token_lit, l.span, shape),
+            ast::NestedMetaItem::Lit(ref l) => {
+                rewrite_literal(context, l.as_token_lit(), l.span, shape)
+            }
         }
     }
 }
@@ -308,18 +310,18 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
                     }),
                 )?
             }
-            ast::MetaItemKind::NameValue(ref literal) => {
+            ast::MetaItemKind::NameValue(ref lit) => {
                 let path = rewrite_path(context, PathContext::Type, &None, &self.path, shape)?;
                 // 3 = ` = `
                 let lit_shape = shape.shrink_left(path.len() + 3)?;
-                // `rewrite_literal` returns `None` when `literal` exceeds max
+                // `rewrite_literal` returns `None` when `lit` exceeds max
                 // width. Since a literal is basically unformattable unless it
                 // is a string literal (and only if `format_strings` is set),
                 // we might be better off ignoring the fact that the attribute
                 // is longer than the max width and continue on formatting.
                 // See #2479 for example.
-                let value = rewrite_literal(context, literal.token_lit, literal.span, lit_shape)
-                    .unwrap_or_else(|| context.snippet(literal.span).to_owned());
+                let value = rewrite_literal(context, lit.as_token_lit(), lit.span, lit_shape)
+                    .unwrap_or_else(|| context.snippet(lit.span).to_owned());
                 format!("{} = {}", path, value)
             }
         })
index ff7a219d9bd8518d43cfacf60bb285127b59212c..75454cbdc5fe6a6f5288adda9f3ebc7399e0ce83 100644 (file)
@@ -57,6 +57,7 @@
     ("cranelift-codegen", "Apache-2.0 WITH LLVM-exception"),
     ("cranelift-codegen-meta", "Apache-2.0 WITH LLVM-exception"),
     ("cranelift-codegen-shared", "Apache-2.0 WITH LLVM-exception"),
+    ("cranelift-egraph", "Apache-2.0 WITH LLVM-exception"),
     ("cranelift-entity", "Apache-2.0 WITH LLVM-exception"),
     ("cranelift-frontend", "Apache-2.0 WITH LLVM-exception"),
     ("cranelift-isle", "Apache-2.0 WITH LLVM-exception"),
@@ -67,6 +68,7 @@
     ("mach", "BSD-2-Clause"),
     ("regalloc2", "Apache-2.0 WITH LLVM-exception"),
     ("target-lexicon", "Apache-2.0 WITH LLVM-exception"),
+    ("wasmtime-jit-icache-coherence", "Apache-2.0 WITH LLVM-exception"),
 ];
 
 const EXCEPTIONS_BOOTSTRAP: &[(&str, &str)] = &[
     "snap",
     "stable_deref_trait",
     "stacker",
+    "static_assertions",
     "syn",
     "synstructure",
     "tempfile",
     "tracing-log",
     "tracing-subscriber",
     "tracing-tree",
+    "twox-hash",
     "type-map",
     "typenum",
     "unic-char-property",
     "cranelift-codegen",
     "cranelift-codegen-meta",
     "cranelift-codegen-shared",
+    "cranelift-egraph",
     "cranelift-entity",
     "cranelift-frontend",
     "cranelift-isle",
     "cranelift-native",
     "cranelift-object",
     "crc32fast",
+    "fallible-iterator",
     "fxhash",
     "getrandom",
     "gimli",
     "region",
     "slice-group-by",
     "smallvec",
+    "stable_deref_trait",
     "target-lexicon",
     "version_check",
     "wasi",
+    "wasmtime-jit-icache-coherence",
     "winapi",
     "winapi-i686-pc-windows-gnu",
     "winapi-x86_64-pc-windows-gnu",
index b0b11cafca5a8a20be5482dca060a6403e61623a..6714c63ee62a143a923f84088101cc99ec1142d1 100644 (file)
@@ -35,15 +35,26 @@ fn main() {
 
     let bad = std::sync::Arc::new(AtomicBool::new(false));
 
+    let drain_handles = |handles: &mut VecDeque<ScopedJoinHandle<'_, ()>>| {
+        // poll all threads for completion before awaiting the oldest one
+        for i in (0..handles.len()).rev() {
+            if handles[i].is_finished() {
+                handles.swap_remove_back(i).unwrap().join().unwrap();
+            }
+        }
+
+        while handles.len() >= concurrency.get() {
+            handles.pop_front().unwrap().join().unwrap();
+        }
+    };
+
     scope(|s| {
         let mut handles: VecDeque<ScopedJoinHandle<'_, ()>> =
             VecDeque::with_capacity(concurrency.get());
 
         macro_rules! check {
             ($p:ident $(, $args:expr)* ) => {
-                while handles.len() >= concurrency.get() {
-                    handles.pop_front().unwrap().join().unwrap();
-                }
+                drain_handles(&mut handles);
 
                 let handle = s.spawn(|| {
                     let mut flag = false;
@@ -97,9 +108,8 @@ macro_rules! check {
         check!(alphabetical, &library_path);
 
         let collected = {
-            while handles.len() >= concurrency.get() {
-                handles.pop_front().unwrap().join().unwrap();
-            }
+            drain_handles(&mut handles);
+
             let mut flag = false;
             let r = features::check(&src_path, &compiler_path, &library_path, &mut flag, verbose);
             if flag {
index e3a094caf919aaa43c2f369d923193e0891fd4fb..f91e38262f64ff8fd1800c99b1cc10ec85856569 100644 (file)
@@ -17,7 +17,7 @@
 //! `// ignore-tidy-CHECK-NAME`.
 
 use crate::walk::{filter_dirs, walk};
-use regex::Regex;
+use regex::{Regex, RegexSet};
 use std::path::Path;
 
 /// Error code markdown is restricted to 80 columns because they can be
@@ -225,6 +225,7 @@ fn skip(path: &Path) -> bool {
         .chain(PROBLEMATIC_CONSTS.iter().map(|v| format!("{:x}", v)))
         .chain(PROBLEMATIC_CONSTS.iter().map(|v| format!("{:X}", v)))
         .collect();
+    let problematic_regex = RegexSet::new(problematic_consts_strings.as_slice()).unwrap();
     walk(path, &mut skip, &mut |entry, contents| {
         let file = entry.path();
         let filename = file.file_name().unwrap().to_string_lossy();
@@ -281,7 +282,27 @@ fn skip(path: &Path) -> bool {
         let mut trailing_new_lines = 0;
         let mut lines = 0;
         let mut last_safety_comment = false;
+        let is_test = file.components().any(|c| c.as_os_str() == "tests");
+        // scanning the whole file for multiple needles at once is more efficient than
+        // executing lines times needles separate searches.
+        let any_problematic_line = problematic_regex.is_match(contents);
         for (i, line) in contents.split('\n').enumerate() {
+            if line.is_empty() {
+                if i == 0 {
+                    leading_new_lines = true;
+                }
+                trailing_new_lines += 1;
+                continue;
+            } else {
+                trailing_new_lines = 0;
+            }
+
+            let trimmed = line.trim();
+
+            if !trimmed.starts_with("//") {
+                lines += 1;
+            }
+
             let mut err = |msg: &str| {
                 tidy_error!(bad, "{}:{}: {}", file.display(), i + 1, msg);
             };
@@ -308,28 +329,29 @@ fn skip(path: &Path) -> bool {
                 suppressible_tidy_err!(err, skip_cr, "CR character");
             }
             if filename != "style.rs" {
-                if line.contains("TODO") {
+                if trimmed.contains("TODO") {
                     err("TODO is deprecated; use FIXME")
                 }
-                if line.contains("//") && line.contains(" XXX") {
+                if trimmed.contains("//") && trimmed.contains(" XXX") {
                     err("XXX is deprecated; use FIXME")
                 }
-                for s in problematic_consts_strings.iter() {
-                    if line.contains(s) {
-                        err("Don't use magic numbers that spell things (consider 0x12345678)");
+                if any_problematic_line {
+                    for s in problematic_consts_strings.iter() {
+                        if trimmed.contains(s) {
+                            err("Don't use magic numbers that spell things (consider 0x12345678)");
+                        }
                     }
                 }
             }
-            let is_test = || file.components().any(|c| c.as_os_str() == "tests");
             // for now we just check libcore
-            if line.contains("unsafe {") && !line.trim().starts_with("//") && !last_safety_comment {
-                if file.components().any(|c| c.as_os_str() == "core") && !is_test() {
+            if trimmed.contains("unsafe {") && !trimmed.starts_with("//") && !last_safety_comment {
+                if file.components().any(|c| c.as_os_str() == "core") && !is_test {
                     suppressible_tidy_err!(err, skip_undocumented_unsafe, "undocumented unsafe");
                 }
             }
-            if line.contains("// SAFETY:") {
+            if trimmed.contains("// SAFETY:") {
                 last_safety_comment = true;
-            } else if line.trim().starts_with("//") || line.trim().is_empty() {
+            } else if trimmed.starts_with("//") || trimmed.is_empty() {
                 // keep previous value
             } else {
                 last_safety_comment = false;
@@ -337,7 +359,8 @@ fn skip(path: &Path) -> bool {
             if (line.starts_with("// Copyright")
                 || line.starts_with("# Copyright")
                 || line.starts_with("Copyright"))
-                && (line.contains("Rust Developers") || line.contains("Rust Project Developers"))
+                && (trimmed.contains("Rust Developers")
+                    || trimmed.contains("Rust Project Developers"))
             {
                 suppressible_tidy_err!(
                     err,
@@ -351,18 +374,6 @@ fn skip(path: &Path) -> bool {
             if filename.ends_with(".cpp") && line.contains("llvm_unreachable") {
                 err(LLVM_UNREACHABLE_INFO);
             }
-            if line.is_empty() {
-                if i == 0 {
-                    leading_new_lines = true;
-                }
-                trailing_new_lines += 1;
-            } else {
-                trailing_new_lines = 0;
-            }
-
-            if !line.trim().starts_with("//") {
-                lines += 1;
-            }
         }
         if leading_new_lines {
             let mut err = |_| {
index ee326e190ffa2aa312e11b5997f134b2ac5ea456..19e2528bb240a3534ccb00d360f3c7879e5e768d 100644 (file)
@@ -10,7 +10,7 @@
 const ENTRY_LIMIT: usize = 1000;
 // FIXME: The following limits should be reduced eventually.
 const ROOT_ENTRY_LIMIT: usize = 939;
-const ISSUES_ENTRY_LIMIT: usize = 2070;
+const ISSUES_ENTRY_LIMIT: usize = 2040;
 
 fn check_entries(path: &Path, bad: &mut bool) {
     for dir in Walk::new(&path.join("test/ui")) {
index 02c364dabf960cbc72b10e2edd0ca52bb2f45dc6..f07ff43efe987fec445e76d8102f6c2bbdcabd4a 100644 (file)
@@ -1,51 +1,43 @@
-//! Run `x.py` from any subdirectory of a rust compiler checkout.
+//! Run bootstrap from any subdirectory of a rust compiler checkout.
 //!
 //! We prefer `exec`, to avoid adding an extra process in the process tree.
 //! However, since `exec` isn't available on Windows, we indirect through
 //! `exec_or_status`, which will call `exec` on unix and `status` on Windows.
 //!
-//! We use `python`, `python3`, or `python2` as the python interpreter to run
-//! `x.py`, in that order of preference.
+//! We use `powershell.exe x.ps1` on Windows, and `sh -c x` on Unix, those are
+//! the ones that call `x.py`. We use `sh -c` on Unix, because it is a standard.
+//! We also don't use `pwsh` on Windows, because it is not installed by default;
 
 use std::{
-    env::{self, consts::EXE_EXTENSION},
-    io,
+    env, io,
+    path::Path,
     process::{self, Command, ExitStatus},
 };
 
-const PYTHON: &str = "python";
-const PYTHON2: &str = "python2";
-const PYTHON3: &str = "python3";
-
-fn python() -> &'static str {
-    let val = match env::var_os("PATH") {
-        Some(val) => val,
-        None => return PYTHON,
-    };
-
-    let mut python2 = false;
-    let mut python3 = false;
-
-    for dir in env::split_paths(&val) {
-        // `python` should always take precedence over python2 / python3 if it exists
-        if dir.join(PYTHON).with_extension(EXE_EXTENSION).exists() {
-            return PYTHON;
-        }
+#[cfg(windows)]
+fn x_command(dir: &Path) -> Command {
+    let mut cmd = Command::new("powershell.exe");
+    cmd.args([
+        "-NoLogo",
+        "-NoProfile",
+        "-NonInteractive",
+        "-ExecutionPolicy",
+        "RemoteSigned",
+        "-Command",
+        "./x.ps1",
+    ])
+    .current_dir(dir);
+    cmd
+}
 
-        python2 |= dir.join(PYTHON2).with_extension(EXE_EXTENSION).exists();
-        python3 |= dir.join(PYTHON3).with_extension(EXE_EXTENSION).exists();
-    }
+#[cfg(unix)]
+fn x_command(dir: &Path) -> Command {
+    Command::new(dir.join("x"))
+}
 
-    // try 3 before 2
-    if python3 {
-        PYTHON3
-    } else if python2 {
-        PYTHON2
-    } else {
-        // Python was not found on path, so exit
-        eprintln!("Unable to find python in your PATH. Please check it is installed.");
-        process::exit(1);
-    }
+#[cfg(not(any(windows, unix)))]
+fn x_command(_dir: &Path) -> Command {
+    compile_error!("Unsupported platform");
 }
 
 #[cfg(unix)]
@@ -72,15 +64,15 @@ fn main() {
         let candidate = dir.join("x.py");
 
         if candidate.exists() {
-            let mut python = Command::new(python());
+            let mut cmd = x_command(dir);
 
-            python.arg(&candidate).args(env::args().skip(1)).current_dir(dir);
+            cmd.args(env::args().skip(1)).current_dir(dir);
 
-            let result = exec_or_status(&mut python);
+            let result = exec_or_status(&mut cmd);
 
             match result {
                 Err(error) => {
-                    eprintln!("Failed to invoke `{}`: {}", candidate.display(), error);
+                    eprintln!("Failed to invoke `{:?}`: {}", cmd, error);
                 }
                 Ok(status) => {
                     process::exit(status.code().unwrap_or(1));
index 65ee0959841f14d2e0a0fc971df20d8e761d6e8d..ee2f4ca913048744aab4763a96594995e832c29a 100644 (file)
@@ -1 +1 @@
-1.67.0
+1.68.0
index 49945e5c533cb3e922d09783fded46c45661895e..46a3bab42a17e21364007d6c5657b206012a99e6 100644 (file)
@@ -467,8 +467,8 @@ compiler-team-contributors = [
     "@compiler-errors",
     "@eholk",
     "@jackh726",
-    "@fee1-dead",
     "@TaKO8Ki",
+    "@Nilstrieb",
 ]
 compiler = [
     "compiler-team",