summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_abi/src/layout.rs10
-rw-r--r--compiler/rustc_abi/src/lib.rs20
-rw-r--r--compiler/rustc_ast/src/ast.rs24
-rw-r--r--compiler/rustc_ast/src/lib.rs1
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs6
-rw-r--r--compiler/rustc_ast/src/node_id.rs8
-rw-r--r--compiler/rustc_ast/src/ptr.rs3
-rw-r--r--compiler/rustc_ast/src/util/parser.rs4
-rw-r--r--compiler/rustc_ast/src/visit.rs6
-rw-r--r--compiler/rustc_ast_lowering/Cargo.toml1
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs62
-rw-r--r--compiler/rustc_ast_lowering/src/format.rs14
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs20
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs24
-rw-r--r--compiler/rustc_ast_passes/Cargo.toml1
-rw-r--r--compiler/rustc_ast_passes/messages.ftl2
-rw-r--r--compiler/rustc_ast_passes/src/errors.rs2
-rw-r--r--compiler/rustc_ast_passes/src/lib.rs2
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/expr.rs20
-rw-r--r--compiler/rustc_attr/Cargo.toml1
-rw-r--r--compiler/rustc_attr/src/lib.rs2
-rw-r--r--compiler/rustc_borrowck/Cargo.toml2
-rw-r--r--compiler/rustc_borrowck/messages.ftl150
-rw-r--r--compiler/rustc_borrowck/src/borrowck_errors.rs1
-rw-r--r--compiler/rustc_borrowck/src/consumers.rs9
-rw-r--r--compiler/rustc_borrowck/src/def_use.rs8
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs363
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs252
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/move_errors.rs53
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs28
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/var_name.rs4
-rw-r--r--compiler/rustc_borrowck/src/facts.rs5
-rw-r--r--compiler/rustc_borrowck/src/invalidation.rs2
-rw-r--r--compiler/rustc_borrowck/src/lib.rs37
-rw-r--r--compiler/rustc_borrowck/src/location.rs8
-rw-r--r--compiler/rustc_borrowck/src/nll.rs10
-rw-r--r--compiler/rustc_borrowck/src/session_diagnostics.rs207
-rw-r--r--compiler/rustc_borrowck/src/type_check/input_output.rs3
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs7
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs52
-rw-r--r--compiler/rustc_borrowck/src/util/collect_writes.rs (renamed from compiler/rustc_const_eval/src/util/collect_writes.rs)0
-rw-r--r--compiler/rustc_borrowck/src/util/mod.rs3
-rw-r--r--compiler/rustc_builtin_macros/Cargo.toml1
-rw-r--r--compiler/rustc_builtin_macros/messages.ftl3
-rw-r--r--compiler/rustc_builtin_macros/src/assert/context.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/format.rs8
-rw-r--r--compiler/rustc_builtin_macros/src/lib.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/offset_of.rs99
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs5
-rw-r--r--compiler/rustc_codegen_cranelift/src/constant.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/lib.rs3
-rw-r--r--compiler/rustc_codegen_llvm/Cargo.toml1
-rw-r--r--compiler/rustc_codegen_llvm/src/common.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs11
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/mod.rs15
-rw-r--r--compiler/rustc_codegen_llvm/src/lib.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs1
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/mod.rs1
-rw-r--r--compiler/rustc_codegen_ssa/Cargo.toml3
-rw-r--r--compiler/rustc_codegen_ssa/messages.ftl2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/archive.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/back/symbol_export.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs5
-rw-r--r--compiler/rustc_codegen_ssa/src/errors.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/lib.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/meth.rs8
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs3
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs77
-rw-r--r--compiler/rustc_const_eval/Cargo.toml1
-rw-r--r--compiler/rustc_const_eval/src/const_eval/eval_queries.rs6
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs12
-rw-r--r--compiler/rustc_const_eval/src/interpret/discriminant.rs17
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs15
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/machine.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs27
-rw-r--r--compiler/rustc_const_eval/src/interpret/step.rs19
-rw-r--r--compiler/rustc_const_eval/src/interpret/terminator.rs3
-rw-r--r--compiler/rustc_const_eval/src/interpret/util.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs4
-rw-r--r--compiler/rustc_const_eval/src/lib.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs4
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/ops.rs7
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs5
-rw-r--r--compiler/rustc_const_eval/src/transform/promote_consts.rs5
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs64
-rw-r--r--compiler/rustc_const_eval/src/util/mod.rs5
-rw-r--r--compiler/rustc_data_structures/Cargo.toml1
-rw-r--r--compiler/rustc_data_structures/src/aligned.rs33
-rw-r--r--compiler/rustc_data_structures/src/fingerprint.rs43
-rw-r--r--compiler/rustc_data_structures/src/fingerprint/tests.rs7
-rw-r--r--compiler/rustc_data_structures/src/hashes.rs132
-rw-r--r--compiler/rustc_data_structures/src/lib.rs5
-rw-r--r--compiler/rustc_data_structures/src/memmap.rs3
-rw-r--r--compiler/rustc_data_structures/src/profiling.rs43
-rw-r--r--compiler/rustc_data_structures/src/profiling/tests.rs19
-rw-r--r--compiler/rustc_data_structures/src/sip128.rs196
-rw-r--r--compiler/rustc_data_structures/src/sso/map.rs7
-rw-r--r--compiler/rustc_data_structures/src/stable_hasher.rs30
-rw-r--r--compiler/rustc_data_structures/src/stable_hasher/tests.rs2
-rw-r--r--compiler/rustc_data_structures/src/svh.rs34
-rw-r--r--compiler/rustc_data_structures/src/tagged_ptr.rs270
-rw-r--r--compiler/rustc_data_structures/src/tagged_ptr/copy.rs312
-rw-r--r--compiler/rustc_data_structures/src/tagged_ptr/copy/tests.rs50
-rw-r--r--compiler/rustc_data_structures/src/tagged_ptr/drop.rs116
-rw-r--r--compiler/rustc_data_structures/src/tagged_ptr/drop/tests.rs71
-rw-r--r--compiler/rustc_driver_impl/Cargo.toml1
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs2
-rw-r--r--compiler/rustc_driver_impl/src/pretty.rs14
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0026.md2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0208.md4
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0311.md2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0457.md2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0576.md2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0609.md2
-rw-r--r--compiler/rustc_error_messages/Cargo.toml1
-rw-r--r--compiler/rustc_error_messages/src/lib.rs3
-rw-r--r--compiler/rustc_errors/Cargo.toml1
-rw-r--r--compiler/rustc_errors/src/emitter.rs3
-rw-r--r--compiler/rustc_errors/src/lib.rs6
-rw-r--r--compiler/rustc_expand/Cargo.toml1
-rw-r--r--compiler/rustc_expand/src/lib.rs2
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs4
-rw-r--r--compiler/rustc_expand/src/proc_macro_server.rs11
-rw-r--r--compiler/rustc_expand/src/tests.rs4
-rw-r--r--compiler/rustc_feature/src/removed.rs2
-rw-r--r--compiler/rustc_fluent_macro/Cargo.toml17
-rw-r--r--compiler/rustc_fluent_macro/src/fluent.rs (renamed from compiler/rustc_macros/src/diagnostics/fluent.rs)2
-rw-r--r--compiler/rustc_fluent_macro/src/lib.rs64
-rw-r--r--compiler/rustc_hir/src/arena.rs1
-rw-r--r--compiler/rustc_hir/src/def.rs5
-rw-r--r--compiler/rustc_hir/src/definitions.rs6
-rw-r--r--compiler/rustc_hir/src/hir.rs52
-rw-r--r--compiler/rustc_hir/src/intravisit.rs4
-rw-r--r--compiler/rustc_hir/src/tests.rs3
-rw-r--r--compiler/rustc_hir_analysis/Cargo.toml3
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs13
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs41
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs9
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs5
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs255
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/variance/mod.rs2
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs17
-rw-r--r--compiler/rustc_hir_typeck/Cargo.toml1
-rw-r--r--compiler/rustc_hir_typeck/messages.ftl15
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs202
-rw-r--r--compiler/rustc_hir_typeck/src/expr_use_visitor.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs32
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs25
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/mod.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/intrinsicck.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs19
-rw-r--r--compiler/rustc_hir_typeck/src/mem_categorization.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs25
-rw-r--r--compiler/rustc_incremental/Cargo.toml1
-rw-r--r--compiler/rustc_incremental/src/lib.rs2
-rw-r--r--compiler/rustc_incremental/src/persist/dirty_clean.rs2
-rw-r--r--compiler/rustc_incremental/src/persist/fs.rs2
-rw-r--r--compiler/rustc_index/src/interval.rs3
-rw-r--r--compiler/rustc_index/src/vec.rs15
-rw-r--r--compiler/rustc_infer/Cargo.toml1
-rw-r--r--compiler/rustc_infer/messages.ftl10
-rw-r--r--compiler/rustc_infer/src/errors/mod.rs14
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs4
-rw-r--r--compiler/rustc_infer/src/infer/combine.rs2
-rw-r--r--compiler/rustc_infer/src/infer/equate.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs8
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs6
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs11
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs4
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs5
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/suggest.rs83
-rw-r--r--compiler/rustc_infer/src/infer/higher_ranked/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs11
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs14
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs7
-rw-r--r--compiler/rustc_infer/src/infer/outlives/components.rs40
-rw-r--r--compiler/rustc_infer/src/infer/outlives/obligations.rs29
-rw-r--r--compiler/rustc_infer/src/infer/outlives/verify.rs9
-rw-r--r--compiler/rustc_infer/src/infer/sub.rs2
-rw-r--r--compiler/rustc_infer/src/lib.rs2
-rw-r--r--compiler/rustc_infer/src/traits/mod.rs8
-rw-r--r--compiler/rustc_infer/src/traits/project.rs2
-rw-r--r--compiler/rustc_interface/Cargo.toml1
-rw-r--r--compiler/rustc_interface/src/lib.rs2
-rw-r--r--compiler/rustc_interface/src/passes.rs11
-rw-r--r--compiler/rustc_interface/src/tests.rs3
-rw-r--r--compiler/rustc_lint/Cargo.toml1
-rw-r--r--compiler/rustc_lint/messages.ftl2
-rw-r--r--compiler/rustc_lint/src/builtin.rs20
-rw-r--r--compiler/rustc_lint/src/errors.rs2
-rw-r--r--compiler/rustc_lint/src/lib.rs2
-rw-r--r--compiler/rustc_lint/src/nonstandard_style.rs8
-rw-r--r--compiler/rustc_lint/src/unused.rs89
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs4
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp3
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp2
-rw-r--r--compiler/rustc_macros/Cargo.toml4
-rw-r--r--compiler/rustc_macros/src/diagnostics/mod.rs2
-rw-r--r--compiler/rustc_macros/src/lib.rs54
-rw-r--r--compiler/rustc_macros/src/query.rs8
-rw-r--r--compiler/rustc_metadata/Cargo.toml1
-rw-r--r--compiler/rustc_metadata/src/lib.rs2
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs41
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs10
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs35
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs5
-rw-r--r--compiler/rustc_metadata/src/rmeta/table.rs4
-rw-r--r--compiler/rustc_middle/Cargo.toml1
-rw-r--r--compiler/rustc_middle/src/arena.rs6
-rw-r--r--compiler/rustc_middle/src/dep_graph/dep_node.rs5
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs2
-rw-r--r--compiler/rustc_middle/src/infer/canonical.rs14
-rw-r--r--compiler/rustc_middle/src/lib.rs9
-rw-r--r--compiler/rustc_middle/src/macros.rs34
-rw-r--r--compiler/rustc_middle/src/metadata.rs3
-rw-r--r--compiler/rustc_middle/src/middle/exported_symbols.rs2
-rw-r--r--compiler/rustc_middle/src/mir/graphviz.rs23
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs32
-rw-r--r--compiler/rustc_middle/src/mir/interpret/pointer.rs2
-rw-r--r--compiler/rustc_middle/src/mir/interpret/queries.rs16
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs72
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs21
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs11
-rw-r--r--compiler/rustc_middle/src/mir/query.rs43
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs17
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs4
-rw-r--r--compiler/rustc_middle/src/mir/type_foldable.rs6
-rw-r--r--compiler/rustc_middle/src/query/keys.rs10
-rw-r--r--compiler/rustc_middle/src/query/mod.rs170
-rw-r--r--compiler/rustc_middle/src/thir.rs11
-rw-r--r--compiler/rustc_middle/src/thir/visit.rs1
-rw-r--r--compiler/rustc_middle/src/ty/abstract_const.rs13
-rw-r--r--compiler/rustc_middle/src/ty/codec.rs11
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs22
-rw-r--r--compiler/rustc_middle/src/ty/consts/int.rs10
-rw-r--r--compiler/rustc_middle/src/ty/consts/kind.rs11
-rw-r--r--compiler/rustc_middle/src/ty/context.rs91
-rw-r--r--compiler/rustc_middle/src/ty/fast_reject.rs2
-rw-r--r--compiler/rustc_middle/src/ty/flags.rs8
-rw-r--r--compiler/rustc_middle/src/ty/fold.rs3
-rw-r--r--compiler/rustc_middle/src/ty/impls_ty.rs28
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs102
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs6
-rw-r--r--compiler/rustc_middle/src/ty/list.rs30
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs160
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs26
-rw-r--r--compiler/rustc_middle/src/ty/query.rs40
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs14
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs24
-rw-r--r--compiler/rustc_middle/src/ty/subst.rs115
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs12
-rw-r--r--compiler/rustc_middle/src/ty/util.rs15
-rw-r--r--compiler/rustc_middle/src/ty/visit.rs10
-rw-r--r--compiler/rustc_middle/src/ty/walk.rs2
-rw-r--r--compiler/rustc_middle/src/util/call_kind.rs (renamed from compiler/rustc_const_eval/src/util/call_kind.rs)4
-rw-r--r--compiler/rustc_middle/src/util/find_self_call.rs (renamed from compiler/rustc_const_eval/src/util/find_self_call.rs)6
-rw-r--r--compiler/rustc_middle/src/util/mod.rs7
-rw-r--r--compiler/rustc_mir_build/Cargo.toml1
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_constant.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_place.rs1
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/expr/category.rs3
-rw-r--r--compiler/rustc_mir_build/src/build/expr/into.rs7
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs12
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs74
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs41
-rw-r--r--compiler/rustc_mir_build/src/errors.rs9
-rw-r--r--compiler/rustc_mir_build/src/lib.rs3
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs8
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/mod.rs25
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs8
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/print.rs17
-rw-r--r--compiler/rustc_mir_dataflow/Cargo.toml1
-rw-r--r--compiler/rustc_mir_dataflow/src/lib.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/move_paths/builder.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/value_analysis.rs2
-rw-r--r--compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs4
-rw-r--r--compiler/rustc_mir_transform/src/add_retag.rs2
-rw-r--r--compiler/rustc_mir_transform/src/check_const_item_mutation.rs7
-rw-r--r--compiler/rustc_mir_transform/src/check_unsafety.rs32
-rw-r--r--compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs1
-rw-r--r--compiler/rustc_mir_transform/src/const_debuginfo.rs4
-rw-r--r--compiler/rustc_mir_transform/src/const_prop.rs2
-rw-r--r--compiler/rustc_mir_transform/src/const_prop_lint.rs2
-rw-r--r--compiler/rustc_mir_transform/src/coverage/debug.rs6
-rw-r--r--compiler/rustc_mir_transform/src/coverage/graph.rs2
-rw-r--r--compiler/rustc_mir_transform/src/coverage/mod.rs7
-rw-r--r--compiler/rustc_mir_transform/src/coverage/query.rs3
-rw-r--r--compiler/rustc_mir_transform/src/dataflow_const_prop.rs2
-rw-r--r--compiler/rustc_mir_transform/src/dead_store_elimination.rs5
-rw-r--r--compiler/rustc_mir_transform/src/deduce_param_attrs.rs5
-rw-r--r--compiler/rustc_mir_transform/src/dest_prop.rs11
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_drops.rs2
-rw-r--r--compiler/rustc_mir_transform/src/ffi_unwind_calls.rs2
-rw-r--r--compiler/rustc_mir_transform/src/function_item_references.rs48
-rw-r--r--compiler/rustc_mir_transform/src/generator.rs4
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs10
-rw-r--r--compiler/rustc_mir_transform/src/inline/cycle.rs3
-rw-r--r--compiler/rustc_mir_transform/src/instcombine.rs21
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs149
-rw-r--r--compiler/rustc_mir_transform/src/remove_place_mention.rs23
-rw-r--r--compiler/rustc_mir_transform/src/separate_const_switch.rs3
-rw-r--r--compiler/rustc_mir_transform/src/shim.rs2
-rw-r--r--compiler/rustc_mir_transform/src/simplify.rs62
-rw-r--r--compiler/rustc_mir_transform/src/simplify_branches.rs21
-rw-r--r--compiler/rustc_mir_transform/src/ssa.rs2
-rw-r--r--compiler/rustc_monomorphize/Cargo.toml1
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs2
-rw-r--r--compiler/rustc_monomorphize/src/lib.rs2
-rw-r--r--compiler/rustc_monomorphize/src/partitioning/default.rs22
-rw-r--r--compiler/rustc_monomorphize/src/partitioning/mod.rs98
-rw-r--r--compiler/rustc_monomorphize/src/polymorphize.rs10
-rw-r--r--compiler/rustc_parse/Cargo.toml1
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs2
-rw-r--r--compiler/rustc_parse/src/lib.rs2
-rw-r--r--compiler/rustc_parse/src/parser/attr.rs6
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs8
-rw-r--r--compiler/rustc_parse/src/parser/item.rs14
-rw-r--r--compiler/rustc_parse/src/parser/nonterminal.rs10
-rw-r--r--compiler/rustc_parse/src/validate_attr.rs2
-rw-r--r--compiler/rustc_passes/Cargo.toml1
-rw-r--r--compiler/rustc_passes/messages.ftl6
-rw-r--r--compiler/rustc_passes/src/check_attr.rs12
-rw-r--r--compiler/rustc_passes/src/dead.rs34
-rw-r--r--compiler/rustc_passes/src/errors.rs4
-rw-r--r--compiler/rustc_passes/src/hir_stats.rs5
-rw-r--r--compiler/rustc_passes/src/lib.rs2
-rw-r--r--compiler/rustc_passes/src/liveness.rs5
-rw-r--r--compiler/rustc_passes/src/naked_functions.rs1
-rw-r--r--compiler/rustc_plugin_impl/Cargo.toml1
-rw-r--r--compiler/rustc_plugin_impl/src/lib.rs2
-rw-r--r--compiler/rustc_privacy/Cargo.toml1
-rw-r--r--compiler/rustc_privacy/src/lib.rs2
-rw-r--r--compiler/rustc_query_impl/src/on_disk_cache.rs13
-rw-r--r--compiler/rustc_query_impl/src/plumbing.rs4
-rw-r--r--compiler/rustc_query_impl/src/profiling_support.rs35
-rw-r--r--compiler/rustc_query_system/Cargo.toml1
-rw-r--r--compiler/rustc_query_system/messages.ftl2
-rw-r--r--compiler/rustc_query_system/src/dep_graph/graph.rs2
-rw-r--r--compiler/rustc_query_system/src/dep_graph/query.rs5
-rw-r--r--compiler/rustc_query_system/src/ich/impls_syntax.rs2
-rw-r--r--compiler/rustc_query_system/src/lib.rs2
-rw-r--r--compiler/rustc_query_system/src/query/config.rs2
-rw-r--r--compiler/rustc_query_system/src/query/mod.rs5
-rw-r--r--compiler/rustc_query_system/src/query/plumbing.rs29
-rw-r--r--compiler/rustc_resolve/Cargo.toml1
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs15
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs30
-rw-r--r--compiler/rustc_resolve/src/effective_visibilities.rs2
-rw-r--r--compiler/rustc_resolve/src/errors.rs2
-rw-r--r--compiler/rustc_resolve/src/imports.rs8
-rw-r--r--compiler/rustc_resolve/src/late.rs4
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs4
-rw-r--r--compiler/rustc_resolve/src/lib.rs2
-rw-r--r--compiler/rustc_resolve/src/rustdoc.rs1
-rw-r--r--compiler/rustc_session/Cargo.toml1
-rw-r--r--compiler/rustc_session/src/lib.rs2
-rw-r--r--compiler/rustc_session/src/options.rs7
-rw-r--r--compiler/rustc_session/src/session.rs2
-rw-r--r--compiler/rustc_smir/src/rustc_smir/mod.rs22
-rw-r--r--compiler/rustc_smir/src/stable_mir/mir/body.rs10
-rw-r--r--compiler/rustc_span/src/def_id.rs39
-rw-r--r--compiler/rustc_span/src/hygiene.rs14
-rw-r--r--compiler/rustc_span/src/lib.rs64
-rw-r--r--compiler/rustc_span/src/source_map.rs14
-rw-r--r--compiler/rustc_span/src/symbol.rs7
-rw-r--r--compiler/rustc_span/src/tests.rs8
-rw-r--r--compiler/rustc_symbol_mangling/Cargo.toml1
-rw-r--r--compiler/rustc_symbol_mangling/src/legacy.rs8
-rw-r--r--compiler/rustc_symbol_mangling/src/lib.rs2
-rw-r--r--compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs16
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs2
-rw-r--r--compiler/rustc_target/src/abi/call/avr.rs2
-rw-r--r--compiler/rustc_target/src/abi/mod.rs15
-rw-r--r--compiler/rustc_target/src/spec/apple_base.rs21
-rw-r--r--compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs1
-rw-r--r--compiler/rustc_target/src/spec/mod.rs7
-rw-r--r--compiler/rustc_target/src/spec/thumb_base.rs2
-rw-r--r--compiler/rustc_target/src/spec/x86_64h_apple_darwin.rs44
-rw-r--r--compiler/rustc_trait_selection/Cargo.toml1
-rw-r--r--compiler/rustc_trait_selection/src/lib.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/mod.rs4
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt.rs17
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs26
-rw-r--r--compiler/rustc_trait_selection/src/solve/project_goals.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs3
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs45
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs3
-rw-r--r--compiler/rustc_trait_selection/src/traits/misc.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/outlives_bounds.rs13
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs14
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs48
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs5
-rw-r--r--compiler/rustc_trait_selection/src/traits/util.rs9
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs33
-rw-r--r--compiler/rustc_traits/src/chalk/lowering.rs28
-rw-r--r--compiler/rustc_traits/src/type_op.rs1
-rw-r--r--compiler/rustc_transmute/src/layout/tree.rs2
-rw-r--r--compiler/rustc_transmute/src/lib.rs9
-rw-r--r--compiler/rustc_ty_utils/Cargo.toml1
-rw-r--r--compiler/rustc_ty_utils/src/consts.rs68
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs60
-rw-r--r--compiler/rustc_ty_utils/src/layout_sanity_check.rs2
-rw-r--r--compiler/rustc_ty_utils/src/lib.rs2
-rw-r--r--compiler/rustc_ty_utils/src/needs_drop.rs2
-rw-r--r--compiler/rustc_ty_utils/src/structural_match.rs2
-rw-r--r--compiler/rustc_type_ir/src/fold.rs37
-rw-r--r--compiler/rustc_type_ir/src/macros.rs141
-rw-r--r--compiler/rustc_type_ir/src/structural_impls.rs58
-rw-r--r--compiler/rustc_type_ir/src/sty.rs10
-rw-r--r--compiler/rustc_type_ir/src/visit.rs28
438 files changed, 4725 insertions, 3536 deletions
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
index c863acde7b0..f3af031ade4 100644
--- a/compiler/rustc_abi/src/layout.rs
+++ b/compiler/rustc_abi/src/layout.rs
@@ -79,7 +79,8 @@ pub trait LayoutCalculator {
{
// `ReprOptions.layout_seed` is a deterministic seed that we can use to
// randomize field ordering with
- let mut rng = Xoshiro128StarStar::seed_from_u64(repr.field_shuffle_seed);
+ let mut rng =
+ Xoshiro128StarStar::seed_from_u64(repr.field_shuffle_seed.as_u64());
// Shuffle the ordering of the fields
optimizing.shuffle(&mut rng);
@@ -461,8 +462,8 @@ pub trait LayoutCalculator {
let all_indices = variants.indices();
let needs_disc =
|index: VariantIdx| index != largest_variant_index && !absent(&variants[index]);
- let niche_variants = all_indices.clone().find(|v| needs_disc(*v)).unwrap().index()
- ..=all_indices.rev().find(|v| needs_disc(*v)).unwrap().index();
+ let niche_variants = all_indices.clone().find(|v| needs_disc(*v)).unwrap()
+ ..=all_indices.rev().find(|v| needs_disc(*v)).unwrap();
let count = niche_variants.size_hint().1.unwrap() as u128;
@@ -560,8 +561,7 @@ pub trait LayoutCalculator {
tag: niche_scalar,
tag_encoding: TagEncoding::Niche {
untagged_variant: largest_variant_index,
- niche_variants: (VariantIdx::new(*niche_variants.start())
- ..=VariantIdx::new(*niche_variants.end())),
+ niche_variants,
niche_start,
},
tag_field: 0,
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index b0c0ee942ea..a5cdaa547d8 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -9,9 +9,10 @@ use std::str::FromStr;
use bitflags::bitflags;
use rustc_data_structures::intern::Interned;
+use rustc_data_structures::stable_hasher::Hash64;
#[cfg(feature = "nightly")]
use rustc_data_structures::stable_hasher::StableOrd;
-use rustc_index::vec::{Idx, IndexSlice, IndexVec};
+use rustc_index::vec::{IndexSlice, IndexVec};
#[cfg(feature = "nightly")]
use rustc_macros::HashStable_Generic;
#[cfg(feature = "nightly")]
@@ -77,12 +78,12 @@ pub struct ReprOptions {
pub flags: ReprFlags,
/// The seed to be used for randomizing a type's layout
///
- /// Note: This could technically be a `[u8; 16]` (a `u128`) which would
+ /// Note: This could technically be a `Hash128` which would
/// be the "most accurate" hash as it'd encompass the item and crate
/// hash without loss, but it does pay the price of being larger.
- /// Everything's a tradeoff, a `u64` seed should be sufficient for our
+ /// Everything's a tradeoff, a 64-bit seed should be sufficient for our
/// purposes (primarily `-Z randomize-layout`)
- pub field_shuffle_seed: u64,
+ pub field_shuffle_seed: Hash64,
}
impl ReprOptions {
@@ -665,15 +666,12 @@ impl Align {
format!("`{}` is too large", align)
}
- let mut bytes = align;
- let mut pow2: u8 = 0;
- while (bytes & 1) == 0 {
- pow2 += 1;
- bytes >>= 1;
- }
- if bytes != 1 {
+ let tz = align.trailing_zeros();
+ if align != (1 << tz) {
return Err(not_power_of_2(align));
}
+
+ let pow2 = tz as u8;
if pow2 > Self::MAX.pow2 {
return Err(too_large(align));
}
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index df1a716755b..1e4d3ba47f4 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -1271,6 +1271,7 @@ impl Expr {
ExprKind::Continue(..) => ExprPrecedence::Continue,
ExprKind::Ret(..) => ExprPrecedence::Ret,
ExprKind::InlineAsm(..) => ExprPrecedence::InlineAsm,
+ ExprKind::OffsetOf(..) => ExprPrecedence::OffsetOf,
ExprKind::MacCall(..) => ExprPrecedence::Mac,
ExprKind::Struct(..) => ExprPrecedence::Struct,
ExprKind::Repeat(..) => ExprPrecedence::Repeat,
@@ -1298,17 +1299,17 @@ impl Expr {
/// To a first-order approximation, is this a pattern?
pub fn is_approximately_pattern(&self) -> bool {
- match &self.peel_parens().kind {
+ matches!(
+ &self.peel_parens().kind,
ExprKind::Array(_)
- | ExprKind::Call(_, _)
- | ExprKind::Tup(_)
- | ExprKind::Lit(_)
- | ExprKind::Range(_, _, _)
- | ExprKind::Underscore
- | ExprKind::Path(_, _)
- | ExprKind::Struct(_) => true,
- _ => false,
- }
+ | ExprKind::Call(_, _)
+ | ExprKind::Tup(_)
+ | ExprKind::Lit(_)
+ | ExprKind::Range(_, _, _)
+ | ExprKind::Underscore
+ | ExprKind::Path(_, _)
+ | ExprKind::Struct(_)
+ )
}
}
@@ -1469,6 +1470,9 @@ pub enum ExprKind {
/// Output of the `asm!()` macro.
InlineAsm(P<InlineAsm>),
+ /// Output of the `offset_of!()` macro.
+ OffsetOf(P<Ty>, P<[Ident]>),
+
/// A macro invocation; pre-expansion.
MacCall(P<MacCall>),
diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs
index 23c32fa96ca..b07ed1d1c74 100644
--- a/compiler/rustc_ast/src/lib.rs
+++ b/compiler/rustc_ast/src/lib.rs
@@ -10,7 +10,6 @@
)]
#![feature(associated_type_bounds)]
#![feature(box_patterns)]
-#![feature(const_default_impls)]
#![feature(const_trait_impl)]
#![feature(if_let_guard)]
#![feature(let_chains)]
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 694d31d8f1f..99f1f4bd968 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -1456,6 +1456,12 @@ pub fn noop_visit_expr<T: MutVisitor>(
}
ExprKind::InlineAsm(asm) => vis.visit_inline_asm(asm),
ExprKind::FormatArgs(fmt) => vis.visit_format_args(fmt),
+ ExprKind::OffsetOf(container, fields) => {
+ vis.visit_ty(container);
+ for field in fields.iter_mut() {
+ vis.visit_ident(field);
+ }
+ }
ExprKind::MacCall(mac) => vis.visit_mac_call(mac),
ExprKind::Struct(se) => {
let StructExpr { qself, path, fields, rest } = se.deref_mut();
diff --git a/compiler/rustc_ast/src/node_id.rs b/compiler/rustc_ast/src/node_id.rs
index daa82996b3d..d16741757d1 100644
--- a/compiler/rustc_ast/src/node_id.rs
+++ b/compiler/rustc_ast/src/node_id.rs
@@ -9,14 +9,14 @@ rustc_index::newtype_index! {
///
/// [`DefId`]: rustc_span::def_id::DefId
#[debug_format = "NodeId({})"]
- pub struct NodeId {}
+ pub struct NodeId {
+ /// The [`NodeId`] used to represent the root of the crate.
+ const CRATE_NODE_ID = 0;
+ }
}
rustc_data_structures::define_id_collections!(NodeMap, NodeSet, NodeMapEntry, NodeId);
-/// The [`NodeId`] used to represent the root of the crate.
-pub const CRATE_NODE_ID: NodeId = NodeId::from_u32(0);
-
/// When parsing and at the beginning of doing expansions, we initially give all AST nodes
/// this dummy AST [`NodeId`]. Then, during a later phase of expansion, we renumber them
/// to have small, positive IDs.
diff --git a/compiler/rustc_ast/src/ptr.rs b/compiler/rustc_ast/src/ptr.rs
index 4b2850336a0..0140fb752bf 100644
--- a/compiler/rustc_ast/src/ptr.rs
+++ b/compiler/rustc_ast/src/ptr.rs
@@ -126,7 +126,8 @@ impl<S: Encoder, T: Encodable<S>> Encodable<S> for P<T> {
}
impl<T> P<[T]> {
- pub const fn new() -> P<[T]> {
+ // FIXME(const-hack) make this const again
+ pub fn new() -> P<[T]> {
P { ptr: Box::default() }
}
diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs
index 3893875e9a4..24b4bd8623f 100644
--- a/compiler/rustc_ast/src/util/parser.rs
+++ b/compiler/rustc_ast/src/util/parser.rs
@@ -269,6 +269,7 @@ pub enum ExprPrecedence {
Index,
Try,
InlineAsm,
+ OffsetOf,
Mac,
FormatArgs,
@@ -335,7 +336,8 @@ impl ExprPrecedence {
| ExprPrecedence::Try
| ExprPrecedence::InlineAsm
| ExprPrecedence::Mac
- | ExprPrecedence::FormatArgs => PREC_POSTFIX,
+ | ExprPrecedence::FormatArgs
+ | ExprPrecedence::OffsetOf => PREC_POSTFIX,
// Never need parens
ExprPrecedence::Array
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index ac9b321b71c..8a6b5d5c905 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -909,6 +909,12 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
ExprKind::Paren(subexpression) => visitor.visit_expr(subexpression),
ExprKind::InlineAsm(asm) => visitor.visit_inline_asm(asm),
ExprKind::FormatArgs(f) => visitor.visit_format_args(f),
+ ExprKind::OffsetOf(container, fields) => {
+ visitor.visit_ty(container);
+ for &field in fields {
+ visitor.visit_ident(field);
+ }
+ }
ExprKind::Yield(optional_expression) => {
walk_list!(visitor, visit_expr, optional_expression);
}
diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml
index eb2e82d7988..6b0da256505 100644
--- a/compiler/rustc_ast_lowering/Cargo.toml
+++ b/compiler/rustc_ast_lowering/Cargo.toml
@@ -12,6 +12,7 @@ rustc_ast_pretty = { path = "../rustc_ast_pretty" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_hir = { path = "../rustc_hir" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_index = { path = "../rustc_index" }
rustc_middle = { path = "../rustc_middle" }
rustc_macros = { path = "../rustc_macros" }
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 1b1c4765bc0..6863100d9ba 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -121,12 +121,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
LitKind::Err
}
};
- hir::ExprKind::Lit(respan(self.lower_span(e.span), lit_kind))
+ let lit = self.arena.alloc(respan(self.lower_span(e.span), lit_kind));
+ hir::ExprKind::Lit(lit)
+ }
+ ExprKind::IncludedBytes(bytes) => {
+ let lit = self.arena.alloc(respan(
+ self.lower_span(e.span),
+ LitKind::ByteStr(bytes.clone(), StrStyle::Cooked),
+ ));
+ hir::ExprKind::Lit(lit)
}
- ExprKind::IncludedBytes(bytes) => hir::ExprKind::Lit(respan(
- self.lower_span(e.span),
- LitKind::ByteStr(bytes.clone(), StrStyle::Cooked),
- )),
ExprKind::Cast(expr, ty) => {
let expr = self.lower_expr(expr);
let ty =
@@ -285,6 +289,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir::ExprKind::InlineAsm(self.lower_inline_asm(e.span, asm))
}
ExprKind::FormatArgs(fmt) => self.lower_format_args(e.span, fmt),
+ ExprKind::OffsetOf(container, fields) => hir::ExprKind::OffsetOf(
+ self.lower_ty(
+ container,
+ &mut ImplTraitContext::Disallowed(ImplTraitPosition::OffsetOf),
+ ),
+ self.arena.alloc_from_iter(fields.iter().map(|&ident| self.lower_ident(ident))),
+ ),
ExprKind::Struct(se) => {
let rest = match &se.rest {
StructRest::Base(e) => Some(self.lower_expr(e)),
@@ -1746,40 +1757,31 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
pub(super) fn expr_usize(&mut self, sp: Span, value: usize) -> hir::Expr<'hir> {
- self.expr(
- sp,
- hir::ExprKind::Lit(hir::Lit {
- span: sp,
- node: ast::LitKind::Int(
- value as u128,
- ast::LitIntType::Unsigned(ast::UintTy::Usize),
- ),
- }),
- )
+ let lit = self.arena.alloc(hir::Lit {
+ span: sp,
+ node: ast::LitKind::Int(value as u128, ast::LitIntType::Unsigned(ast::UintTy::Usize)),
+ });
+ self.expr(sp, hir::ExprKind::Lit(lit))
}
pub(super) fn expr_u32(&mut self, sp: Span, value: u32) -> hir::Expr<'hir> {
- self.expr(
- sp,
- hir::ExprKind::Lit(hir::Lit {
- span: sp,
- node: ast::LitKind::Int(value.into(), ast::LitIntType::Unsigned(ast::UintTy::U32)),
- }),
- )
+ let lit = self.arena.alloc(hir::Lit {
+ span: sp,
+ node: ast::LitKind::Int(value.into(), ast::LitIntType::Unsigned(ast::UintTy::U32)),
+ });
+ self.expr(sp, hir::ExprKind::Lit(lit))
}
pub(super) fn expr_char(&mut self, sp: Span, value: char) -> hir::Expr<'hir> {
- self.expr(sp, hir::ExprKind::Lit(hir::Lit { span: sp, node: ast::LitKind::Char(value) }))
+ let lit = self.arena.alloc(hir::Lit { span: sp, node: ast::LitKind::Char(value) });
+ self.expr(sp, hir::ExprKind::Lit(lit))
}
pub(super) fn expr_str(&mut self, sp: Span, value: Symbol) -> hir::Expr<'hir> {
- self.expr(
- sp,
- hir::ExprKind::Lit(hir::Lit {
- span: sp,
- node: ast::LitKind::Str(value, ast::StrStyle::Cooked),
- }),
- )
+ let lit = self
+ .arena
+ .alloc(hir::Lit { span: sp, node: ast::LitKind::Str(value, ast::StrStyle::Cooked) });
+ self.expr(sp, hir::ExprKind::Lit(lit))
}
pub(super) fn expr_call_mut(
diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs
index c41bdc44093..ccf481cb9b3 100644
--- a/compiler/rustc_ast_lowering/src/format.rs
+++ b/compiler/rustc_ast_lowering/src/format.rs
@@ -220,19 +220,19 @@ fn make_argument<'hir>(
/// Generates:
///
/// ```text
-/// <core::fmt::rt::v1::Count>::Is(…)
+/// <core::fmt::rt::Count>::Is(…)
/// ```
///
/// or
///
/// ```text
-/// <core::fmt::rt::v1::Count>::Param(…)
+/// <core::fmt::rt::Count>::Param(…)
/// ```
///
/// or
///
/// ```text
-/// <core::fmt::rt::v1::Count>::Implied
+/// <core::fmt::rt::Count>::Implied
/// ```
fn make_count<'hir>(
ctx: &mut LoweringContext<'_, 'hir>,
@@ -278,13 +278,13 @@ fn make_count<'hir>(
/// Generates
///
/// ```text
-/// <core::fmt::rt::v1::Argument::new(
+/// <core::fmt::rt::Placeholder::new(
/// …usize, // position
/// '…', // fill
-/// <core::fmt::rt::v1::Alignment>::…, // alignment
+/// <core::fmt::rt::Alignment>::…, // alignment
/// …u32, // flags
-/// <core::fmt::rt::v1::Count::…>, // width
-/// <core::fmt::rt::v1::Count::…>, // precision
+/// <core::fmt::rt::Count::…>, // width
+/// <core::fmt::rt::Count::…>, // precision
/// )
/// ```
fn make_format_spec<'hir>(
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index f89e254a2f5..08e7a4dfe5d 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -89,9 +89,9 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
lctx.with_hir_id_owner(owner, |lctx| f(lctx));
for (def_id, info) in lctx.children {
- self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom);
- debug_assert!(matches!(self.owners[def_id], hir::MaybeOwner::Phantom));
- self.owners[def_id] = info;
+ let owner = self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom);
+ debug_assert!(matches!(owner, hir::MaybeOwner::Phantom));
+ *owner = info;
}
}
@@ -99,8 +99,8 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
&mut self,
def_id: LocalDefId,
) -> hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>> {
- self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom);
- if let hir::MaybeOwner::Phantom = self.owners[def_id] {
+ let owner = self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom);
+ if let hir::MaybeOwner::Phantom = owner {
let node = self.ast_index[def_id];
match node {
AstOwner::NonOwner => {}
@@ -138,12 +138,10 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
// Evaluate with the lifetimes in `params` in-scope.
// This is used to track which lifetimes have already been defined,
// and which need to be replicated when lowering an async fn.
- match parent_hir.node().expect_item().kind {
- hir::ItemKind::Impl(hir::Impl { of_trait, .. }) => {
- lctx.is_in_trait_impl = of_trait.is_some();
- }
- _ => {}
- };
+
+ if let hir::ItemKind::Impl(impl_) = parent_hir.node().expect_item().kind {
+ lctx.is_in_trait_impl = impl_.of_trait.is_some();
+ }
match ctxt {
AssocCtxt::Trait => hir::OwnerNode::TraitItem(lctx.lower_trait_item(item)),
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index f7ae96b7c4a..c969d709608 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -55,13 +55,13 @@ use rustc_data_structures::sync::Lrc;
use rustc_errors::{
DiagnosticArgFromDisplay, DiagnosticMessage, Handler, StashKey, SubdiagnosticMessage,
};
+use rustc_fluent_macro::fluent_messages;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
use rustc_hir::definitions::DefPathData;
use rustc_hir::{ConstArg, GenericArg, ItemLocalId, ParamName, TraitCandidate};
use rustc_index::vec::{Idx, IndexSlice, IndexVec};
-use rustc_macros::fluent_messages;
use rustc_middle::{
span_bug,
ty::{ResolverAstLowering, TyCtxt},
@@ -283,6 +283,7 @@ enum ImplTraitPosition {
FieldTy,
Cast,
ImplSelf,
+ OffsetOf,
}
impl std::fmt::Display for ImplTraitPosition {
@@ -313,6 +314,7 @@ impl std::fmt::Display for ImplTraitPosition {
ImplTraitPosition::FieldTy => "field types",
ImplTraitPosition::Cast => "cast types",
ImplTraitPosition::ImplSelf => "impl headers",
+ ImplTraitPosition::OffsetOf => "`offset_of!` params",
};
write!(f, "{name}")
@@ -332,10 +334,7 @@ enum FnDeclKind {
impl FnDeclKind {
fn param_impl_trait_allowed(&self) -> bool {
- match self {
- FnDeclKind::Fn | FnDeclKind::Inherent | FnDeclKind::Impl | FnDeclKind::Trait => true,
- _ => false,
- }
+ matches!(self, FnDeclKind::Fn | FnDeclKind::Inherent | FnDeclKind::Impl | FnDeclKind::Trait)
}
fn return_impl_trait_allowed(&self, tcx: TyCtxt<'_>) -> bool {
@@ -371,8 +370,8 @@ fn index_crate<'a>(
krate: &'a Crate,
) -> IndexVec<LocalDefId, AstOwner<'a>> {
let mut indexer = Indexer { node_id_to_def_id, index: IndexVec::new() };
- indexer.index.ensure_contains_elem(CRATE_DEF_ID, || AstOwner::NonOwner);
- indexer.index[CRATE_DEF_ID] = AstOwner::Crate(krate);
+ *indexer.index.ensure_contains_elem(CRATE_DEF_ID, || AstOwner::NonOwner) =
+ AstOwner::Crate(krate);
visit::walk_crate(&mut indexer, krate);
return indexer.index;
@@ -389,22 +388,21 @@ fn index_crate<'a>(
fn visit_item(&mut self, item: &'a ast::Item) {
let def_id = self.node_id_to_def_id[&item.id];
- self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner);
- self.index[def_id] = AstOwner::Item(item);
+ *self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner) = AstOwner::Item(item);
visit::walk_item(self, item)
}
fn visit_assoc_item(&mut self, item: &'a ast::AssocItem, ctxt: visit::AssocCtxt) {
let def_id = self.node_id_to_def_id[&item.id];
- self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner);
- self.index[def_id] = AstOwner::AssocItem(item, ctxt);
+ *self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner) =
+ AstOwner::AssocItem(item, ctxt);
visit::walk_assoc_item(self, item, ctxt);
}
fn visit_foreign_item(&mut self, item: &'a ast::ForeignItem) {
let def_id = self.node_id_to_def_id[&item.id];
- self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner);
- self.index[def_id] = AstOwner::ForeignItem(item);
+ *self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner) =
+ AstOwner::ForeignItem(item);
visit::walk_foreign_item(self, item);
}
}
diff --git a/compiler/rustc_ast_passes/Cargo.toml b/compiler/rustc_ast_passes/Cargo.toml
index 8bd212073a6..eb736123520 100644
--- a/compiler/rustc_ast_passes/Cargo.toml
+++ b/compiler/rustc_ast_passes/Cargo.toml
@@ -12,6 +12,7 @@ rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_feature = { path = "../rustc_feature" }
rustc_macros = { path = "../rustc_macros" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_parse = { path = "../rustc_parse" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl
index a349fe6a3c4..ffca37ae9d5 100644
--- a/compiler/rustc_ast_passes/messages.ftl
+++ b/compiler/rustc_ast_passes/messages.ftl
@@ -231,7 +231,7 @@ ast_passes_feature_on_non_nightly = `#![feature]` may not be used on the {$chann
.suggestion = remove the attribute
.stable_since = the feature `{$name}` has been stable since `{$since}` and no longer requires an attribute to enable
-ast_passes_incompatbile_features = `{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed
+ast_passes_incompatible_features = `{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed
.help = remove one of these features
ast_passes_show_span = {$msg}
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index 27bbd237961..1732865f0bb 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -677,7 +677,7 @@ impl AddToDiagnostic for StableFeature {
}
#[derive(Diagnostic)]
-#[diag(ast_passes_incompatbile_features)]
+#[diag(ast_passes_incompatible_features)]
#[help]
pub struct IncompatibleFeatures {
#[primary_span]
diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs
index e2c666604b3..7db413c5bbd 100644
--- a/compiler/rustc_ast_passes/src/lib.rs
+++ b/compiler/rustc_ast_passes/src/lib.rs
@@ -13,7 +13,7 @@
#![deny(rustc::diagnostic_outside_of_impl)]
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
-use rustc_macros::fluent_messages;
+use rustc_fluent_macro::fluent_messages;
pub mod ast_validation;
mod errors;
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
index 776bf54244e..aeb0c762020 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
@@ -549,6 +549,26 @@ impl<'a> State<'a> {
self.end();
self.pclose();
}
+ ast::ExprKind::OffsetOf(container, fields) => {
+ // FIXME: This should have its own syntax, distinct from a macro invocation.
+ self.word("offset_of!");
+ self.popen();
+ self.rbox(0, Inconsistent);
+ self.print_type(container);
+ self.word(",");
+ self.space();
+
+ if let Some((&first, rest)) = fields.split_first() {
+ self.print_ident(first);
+
+ for &field in rest {
+ self.word(".");
+ self.print_ident(field);
+ }
+ }
+
+ self.end();
+ }
ast::ExprKind::MacCall(m) => self.print_mac(m),
ast::ExprKind::Paren(e) => {
self.popen();
diff --git a/compiler/rustc_attr/Cargo.toml b/compiler/rustc_attr/Cargo.toml
index 6349ddf31d1..2c4c3a0c263 100644
--- a/compiler/rustc_attr/Cargo.toml
+++ b/compiler/rustc_attr/Cargo.toml
@@ -9,6 +9,7 @@ edition = "2021"
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
rustc_serialize = { path = "../rustc_serialize" }
rustc_errors = { path = "../rustc_errors" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_span = { path = "../rustc_span" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_feature = { path = "../rustc_feature" }
diff --git a/compiler/rustc_attr/src/lib.rs b/compiler/rustc_attr/src/lib.rs
index 49818c14f27..cfed2acfb3a 100644
--- a/compiler/rustc_attr/src/lib.rs
+++ b/compiler/rustc_attr/src/lib.rs
@@ -12,7 +12,7 @@
extern crate rustc_macros;
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
-use rustc_macros::fluent_messages;
+use rustc_fluent_macro::fluent_messages;
mod builtin;
mod session_diagnostics;
diff --git a/compiler/rustc_borrowck/Cargo.toml b/compiler/rustc_borrowck/Cargo.toml
index 87c113f3e30..56a9deb6aab 100644
--- a/compiler/rustc_borrowck/Cargo.toml
+++ b/compiler/rustc_borrowck/Cargo.toml
@@ -15,12 +15,12 @@ rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_graphviz = { path = "../rustc_graphviz" }
rustc_hir = { path = "../rustc_hir" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_index = { path = "../rustc_index" }
rustc_infer = { path = "../rustc_infer" }
rustc_lexer = { path = "../rustc_lexer" }
rustc_macros = { path = "../rustc_macros" }
rustc_middle = { path = "../rustc_middle" }
-rustc_const_eval = { path = "../rustc_const_eval" }
rustc_mir_dataflow = { path = "../rustc_mir_dataflow" }
rustc_serialize = { path = "../rustc_serialize" }
rustc_session = { path = "../rustc_session" }
diff --git a/compiler/rustc_borrowck/messages.ftl b/compiler/rustc_borrowck/messages.ftl
index a3b6b5e8138..0b8123c9703 100644
--- a/compiler/rustc_borrowck/messages.ftl
+++ b/compiler/rustc_borrowck/messages.ftl
@@ -56,18 +56,6 @@ borrowck_returned_lifetime_short =
borrowck_used_impl_require_static =
the used `impl` has a `'static` requirement
-borrowck_capture_kind_label =
- capture is {$kind_desc} because of use here
-
-borrowck_var_borrow_by_use_place_in_generator =
- borrow occurs due to use of {$place} in closure in generator
-
-borrowck_var_borrow_by_use_place_in_closure =
- borrow occurs due to use of {$place} in closure
-
-borrowck_var_borrow_by_use_place =
- borrow occurs due to use of {$place}
-
borrowck_borrow_due_to_use_generator =
borrow occurs due to use in generator
@@ -101,12 +89,63 @@ borrowck_capture_mut =
borrowck_capture_move =
capture is moved because of use here
+borrowck_var_borrow_by_use_place_in_generator =
+ {$is_single_var ->
+ *[true] borrow occurs
+ [false] borrows occur
+ } due to use of {$place} in generator
+
+borrowck_var_borrow_by_use_place_in_closure =
+ {$is_single_var ->
+ *[true] borrow occurs
+ [false] borrows occur
+ } due to use of {$place} in closure
+
+borrowck_var_borrow_by_use_in_generator =
+ borrow occurs due to use in generator
+
+borrowck_var_borrow_by_use_in_closure =
+ borrow occurs due to use in closure
+
borrowck_var_move_by_use_place_in_generator =
move occurs due to use of {$place} in generator
borrowck_var_move_by_use_place_in_closure =
move occurs due to use of {$place} in closure
+borrowck_var_move_by_use_in_generator =
+ move occurs due to use in generator
+
+borrowck_var_move_by_use_in_closure =
+ move occurs due to use in closure
+
+borrowck_partial_var_move_by_use_in_generator =
+ variable {$is_partial ->
+ [true] partially moved
+ *[false] moved
+ } due to use in generator
+
+borrowck_partial_var_move_by_use_in_closure =
+ variable {$is_partial ->
+ [true] partially moved
+ *[false] moved
+ } due to use in closure
+
+borrowck_var_first_borrow_by_use_place_in_generator =
+ first borrow occurs due to use of {$place} in generator
+
+borrowck_var_first_borrow_by_use_place_in_closure =
+ first borrow occurs due to use of {$place} in closure
+
+borrowck_var_second_borrow_by_use_place_in_generator =
+ second borrow occurs due to use of {$place} in generator
+
+borrowck_var_second_borrow_by_use_place_in_closure =
+ second borrow occurs due to use of {$place} in closure
+
+borrowck_var_mutable_borrow_by_use_place_in_closure =
+ mutable borrow occurs due to use of {$place} in closure
+
borrowck_cannot_move_when_borrowed =
cannot move out of {$place ->
[value] value
@@ -127,3 +166,90 @@ borrowck_opaque_type_non_generic_param =
[true] cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
*[other] this generic parameter must be used with a generic {$kind} parameter
}
+
+borrowck_moved_due_to_call =
+ {$place_name} {$is_partial ->
+ [true] partially moved
+ *[false] moved
+ } due to this {$is_loop_message ->
+ [true] call, in previous iteration of loop
+ *[false] call
+ }
+
+borrowck_moved_due_to_usage_in_operator =
+ {$place_name} {$is_partial ->
+ [true] partially moved
+ *[false] moved
+ } due to usage in {$is_loop_message ->
+ [true] operator, in previous iteration of loop
+ *[false] operator
+ }
+
+borrowck_moved_due_to_implicit_into_iter_call =
+ {$place_name} {$is_partial ->
+ [true] partially moved
+ *[false] moved
+ } due to this implicit call to {$is_loop_message ->
+ [true] `.into_iter()`, in previous iteration of loop
+ *[false] `.into_iter()`
+ }
+
+borrowck_moved_due_to_method_call =
+ {$place_name} {$is_partial ->
+ [true] partially moved
+ *[false] moved
+ } due to this method {$is_loop_message ->
+ [true] call, in previous iteration of loop
+ *[false] call
+ }
+
+borrowck_value_moved_here =
+ value {$is_partial ->
+ [true] partially moved
+ *[false] moved
+ } {$is_move_msg ->
+ [true] into closure here
+ *[false] here
+ }{$is_loop_message ->
+ [true] , in previous iteration of loop
+ *[false] {""}
+ }
+
+borrowck_consider_borrow_type_contents =
+ help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
+
+borrowck_moved_a_fn_once_in_call =
+ this value implements `FnOnce`, which causes it to be moved when called
+
+borrowck_calling_operator_moves_lhs =
+ calling this operator moves the left-hand side
+
+borrowck_func_take_self_moved_place =
+ `{$func}` takes ownership of the receiver `self`, which moves {$place_name}
+
+borrowck_suggest_iterate_over_slice =
+ consider iterating over a slice of the `{$ty}`'s content to avoid moving into the `for` loop
+
+borrowck_suggest_create_freash_reborrow =
+ consider reborrowing the `Pin` instead of moving it
+
+borrowck_value_capture_here =
+ value captured {$is_within ->
+ [true] here by generator
+ *[false] here
+ }
+
+borrowck_move_out_place_here =
+ {$place} is moved here
+
+borrowck_closure_invoked_twice =
+ closure cannot be invoked more than once because it moves the variable `{$place_name}` out of its environment
+
+borrowck_closure_moved_twice =
+ closure cannot be moved more than once as it is not `Copy` due to moving the variable `{$place_name}` out of its environment
+
+borrowck_ty_no_impl_copy =
+ {$is_partial_move ->
+ [true] partial move
+ *[false] move
+ } occurs because {$place} has type `{$ty}`, which does not implement the `Copy` trait
diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs
index 2bbb9618dbf..acca1a1477f 100644
--- a/compiler/rustc_borrowck/src/borrowck_errors.rs
+++ b/compiler/rustc_borrowck/src/borrowck_errors.rs
@@ -469,6 +469,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
}
#[rustc_lint_diagnostics]
+ #[track_caller]
pub(crate) fn struct_span_err_with_code<S: Into<MultiSpan>>(
&self,
sp: S,
diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs
index cb1a6522223..cd200aaa277 100644
--- a/compiler/rustc_borrowck/src/consumers.rs
+++ b/compiler/rustc_borrowck/src/consumers.rs
@@ -6,7 +6,7 @@ use rustc_hir::def_id::LocalDefId;
use rustc_index::vec::IndexSlice;
use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
use rustc_middle::mir::Body;
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty::TyCtxt;
pub use super::{
facts::{AllFacts as PoloniusInput, RustcFacts},
@@ -28,12 +28,9 @@ pub use super::{
/// that shows how to do this at `tests/run-make/obtain-borrowck/`.
///
/// * Polonius is highly unstable, so expect regular changes in its signature or other details.
-pub fn get_body_with_borrowck_facts(
- tcx: TyCtxt<'_>,
- def: ty::WithOptConstParam<LocalDefId>,
-) -> BodyWithBorrowckFacts<'_> {
+pub fn get_body_with_borrowck_facts(tcx: TyCtxt<'_>, def: LocalDefId) -> BodyWithBorrowckFacts<'_> {
let (input_body, promoted) = tcx.mir_promoted(def);
- let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(def.did)).build();
+ let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(def)).build();
let input_body: &Body<'_> = &input_body.borrow();
let promoted: &IndexSlice<_, _> = &promoted.borrow();
*super::do_mir_borrowck(&infcx, input_body, promoted, true).1.unwrap()
diff --git a/compiler/rustc_borrowck/src/def_use.rs b/compiler/rustc_borrowck/src/def_use.rs
index 9e9f0b4b4ad..6259722b694 100644
--- a/compiler/rustc_borrowck/src/def_use.rs
+++ b/compiler/rustc_borrowck/src/def_use.rs
@@ -52,12 +52,16 @@ pub fn categorize(context: PlaceContext) -> Option<DefUse> {
PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow) |
PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow) |
+ // `PlaceMention` and `AscribeUserType` both evaluate the place, which must not
+ // contain dangling references.
+ PlaceContext::NonUse(NonUseContext::PlaceMention) |
+ PlaceContext::NonUse(NonUseContext::AscribeUserTy) |
+
PlaceContext::MutatingUse(MutatingUseContext::AddressOf) |
PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf) |
PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect) |
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) |
PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) |
- PlaceContext::NonUse(NonUseContext::AscribeUserTy) |
PlaceContext::MutatingUse(MutatingUseContext::Retag) =>
Some(DefUse::Use),
@@ -72,8 +76,6 @@ pub fn categorize(context: PlaceContext) -> Option<DefUse> {
PlaceContext::MutatingUse(MutatingUseContext::Drop) =>
Some(DefUse::Drop),
- // This statement exists to help unsafeck. It does not require the place to be live.
- PlaceContext::NonUse(NonUseContext::PlaceMention) => None,
// Debug info is neither def nor use.
PlaceContext::NonUse(NonUseContext::VarDebugInfo) => None,
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 75a3dd0c0f3..2320901a053 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -1,5 +1,6 @@
+use std::iter;
+
use either::Either;
-use rustc_const_eval::util::CallKind;
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::{
@@ -11,6 +12,7 @@ use rustc_hir::intravisit::{walk_block, walk_expr, Visitor};
use rustc_hir::{AsyncGeneratorKind, GeneratorKind, LangItem};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::ObligationCause;
+use rustc_middle::hir::nested_filter::OnlyBodies;
use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::mir::{
self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory,
@@ -18,20 +20,19 @@ use rustc_middle::mir::{
ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm,
};
use rustc_middle::ty::{self, suggest_constraining_type_params, PredicateKind, Ty};
+use rustc_middle::util::CallKind;
use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex};
use rustc_span::def_id::LocalDefId;
use rustc_span::hygiene::DesugaringKind;
-use rustc_span::symbol::{kw, sym};
+use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{BytePos, Span, Symbol};
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::ObligationCtxt;
use crate::borrow_set::TwoPhaseActivation;
use crate::borrowck_errors;
-
use crate::diagnostics::conflict_errors::StorageDeadOrDrop::LocalStorageDead;
-use crate::diagnostics::find_all_local_uses;
-use crate::diagnostics::mutability_errors::mut_borrow_of_mutable_ref;
+use crate::diagnostics::{find_all_local_uses, CapturedMessageOpt};
use crate::{
borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf,
InitializationRequiringAction, MirBorrowckCtxt, PrefixSet, WriteKind,
@@ -183,13 +184,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let move_spans = self.move_spans(moved_place.as_ref(), move_out.source);
let move_span = move_spans.args_or_use();
- let move_msg = if move_spans.for_closure() { " into closure" } else { "" };
+ let is_move_msg = move_spans.for_closure();
- let loop_message = if location == move_out.source || move_site.traversed_back_edge {
- ", in previous iteration of loop"
- } else {
- ""
- };
+ let is_loop_message = location == move_out.source || move_site.traversed_back_edge;
if location == move_out.source {
is_loop_move = true;
@@ -206,17 +203,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
);
}
+ let msg_opt = CapturedMessageOpt {
+ is_partial_move,
+ is_loop_message,
+ is_move_msg,
+ is_loop_move,
+ maybe_reinitialized_locations_is_empty: maybe_reinitialized_locations
+ .is_empty(),
+ };
self.explain_captures(
&mut err,
span,
move_span,
move_spans,
*moved_place,
- partially_str,
- loop_message,
- move_msg,
- is_loop_move,
- maybe_reinitialized_locations.is_empty(),
+ msg_opt,
);
}
seen_spans.insert(move_span);
@@ -282,12 +283,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
if needs_note {
- let span = if let Some(local) = place.as_local() {
- Some(self.body.local_decls[local].source_info.span)
+ if let Some(local) = place.as_local() {
+ let span = self.body.local_decls[local].source_info.span;
+ err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
+ is_partial_move,
+ ty,
+ place: &note_msg,
+ span,
+ });
} else {
- None
+ err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Note {
+ is_partial_move,
+ ty,
+ place: &note_msg,
+ });
};
- self.note_type_does_not_implement_copy(&mut err, &note_msg, ty, span, partial_str);
}
if let UseSpans::FnSelfUse {
@@ -827,11 +837,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
borrow_spans.var_path_only_subdiag(&mut err, crate::InitializationRequiringAction::Borrow);
- move_spans.var_span_label(
- &mut err,
- format!("move occurs due to use{}", move_spans.describe()),
- "moved",
- );
+ move_spans.var_subdiag(None, &mut err, None, |kind, var_span| {
+ use crate::session_diagnostics::CaptureVarCause::*;
+ match kind {
+ Some(_) => MoveUseInGenerator { var_span },
+ None => MoveUseInClosure { var_span },
+ }
+ });
self.explain_why_borrow_contains_point(location, borrow, None)
.add_explanation_to_diagnostic(
@@ -868,13 +880,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
borrow_span,
&self.describe_any_place(borrow.borrowed_place.as_ref()),
);
- borrow_spans.var_subdiag(&mut err, Some(borrow.kind), |kind, var_span| {
+ borrow_spans.var_subdiag(None, &mut err, Some(borrow.kind), |kind, var_span| {
use crate::session_diagnostics::CaptureVarCause::*;
let place = &borrow.borrowed_place;
let desc_place = self.describe_any_place(place.as_ref());
match kind {
- Some(_) => BorrowUsePlaceGenerator { place: desc_place, var_span },
- None => BorrowUsePlaceClosure { place: desc_place, var_span },
+ Some(_) => {
+ BorrowUsePlaceGenerator { place: desc_place, var_span, is_single_var: true }
+ }
+ None => BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: true },
}
});
@@ -946,7 +960,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
&msg_borrow,
None,
);
- self.suggest_binding_for_closure_capture_self(
+ self.suggest_binding_for_closure_capture_self(&mut err, &issued_spans);
+ self.suggest_using_closure_argument_instead_of_capture(
&mut err,
issued_borrow.borrowed_place,
&issued_spans,
@@ -969,6 +984,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
place,
issued_borrow.borrowed_place,
);
+ self.suggest_using_closure_argument_instead_of_capture(
+ &mut err,
+ issued_borrow.borrowed_place,
+ &issued_spans,
+ );
err
}
@@ -988,16 +1008,26 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
immutable_section_description,
"mutably borrow",
);
- borrow_spans.var_span_label(
+ borrow_spans.var_subdiag(
+ None,
&mut err,
- format!(
- "borrow occurs due to use of {}{}",
- desc_place,
- borrow_spans.describe(),
- ),
- "immutable",
+ Some(BorrowKind::Unique),
+ |kind, var_span| {
+ use crate::session_diagnostics::CaptureVarCause::*;
+ match kind {
+ Some(_) => BorrowUsePlaceGenerator {
+ place: desc_place,
+ var_span,
+ is_single_var: true,
+ },
+ None => BorrowUsePlaceClosure {
+ place: desc_place,
+ var_span,
+ is_single_var: true,
+ },
+ }
+ },
);
-
return err;
} else {
first_borrow_desc = "immutable ";
@@ -1070,32 +1100,48 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
};
if issued_spans == borrow_spans {
- borrow_spans.var_span_label(
- &mut err,
- format!("borrows occur due to use of {}{}", desc_place, borrow_spans.describe(),),
- gen_borrow_kind.describe_mutability(),
- );
+ borrow_spans.var_subdiag(None, &mut err, Some(gen_borrow_kind), |kind, var_span| {
+ use crate::session_diagnostics::CaptureVarCause::*;
+ match kind {
+ Some(_) => BorrowUsePlaceGenerator {
+ place: desc_place,
+ var_span,
+ is_single_var: false,
+ },
+ None => {
+ BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: false }
+ }
+ }
+ });
} else {
- let borrow_place = &issued_borrow.borrowed_place;
- let borrow_place_desc = self.describe_any_place(borrow_place.as_ref());
- issued_spans.var_span_label(
+ issued_spans.var_subdiag(
+ Some(&self.infcx.tcx.sess.parse_sess.span_diagnostic),
&mut err,
- format!(
- "first borrow occurs due to use of {}{}",
- borrow_place_desc,
- issued_spans.describe(),
- ),
- issued_borrow.kind.describe_mutability(),
+ Some(issued_borrow.kind),
+ |kind, var_span| {
+ use crate::session_diagnostics::CaptureVarCause::*;
+ let borrow_place = &issued_borrow.borrowed_place;
+ let borrow_place_desc = self.describe_any_place(borrow_place.as_ref());
+ match kind {
+ Some(_) => {
+ FirstBorrowUsePlaceGenerator { place: borrow_place_desc, var_span }
+ }
+ None => FirstBorrowUsePlaceClosure { place: borrow_place_desc, var_span },
+ }
+ },
);
- borrow_spans.var_span_label(
+ borrow_spans.var_subdiag(
+ Some(&self.infcx.tcx.sess.parse_sess.span_diagnostic),
&mut err,
- format!(
- "second borrow occurs due to use of {}{}",
- desc_place,
- borrow_spans.describe(),
- ),
- gen_borrow_kind.describe_mutability(),
+ Some(gen_borrow_kind),
+ |kind, var_span| {
+ use crate::session_diagnostics::CaptureVarCause::*;
+ match kind {
+ Some(_) => SecondBorrowUsePlaceGenerator { place: desc_place, var_span },
+ None => SecondBorrowUsePlaceClosure { place: desc_place, var_span },
+ }
+ },
);
}
@@ -1229,22 +1275,160 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
}
- fn suggest_binding_for_closure_capture_self(
+ /// Suggest using closure argument instead of capture.
+ ///
+ /// For example:
+ /// ```ignore (illustrative)
+ /// struct S;
+ ///
+ /// impl S {
+ /// fn call(&mut self, f: impl Fn(&mut Self)) { /* ... */ }
+ /// fn x(&self) {}
+ /// }
+ ///
+ /// let mut v = S;
+ /// v.call(|this: &mut S| v.x());
+ /// // ^\ ^-- help: try using the closure argument: `this`
+ /// // *-- error: cannot borrow `v` as mutable because it is also borrowed as immutable
+ /// ```
+ fn suggest_using_closure_argument_instead_of_capture(
&self,
err: &mut Diagnostic,
borrowed_place: Place<'tcx>,
issued_spans: &UseSpans<'tcx>,
) {
- let UseSpans::ClosureUse { capture_kind_span, .. } = issued_spans else { return };
- let hir = self.infcx.tcx.hir();
+ let &UseSpans::ClosureUse { capture_kind_span, .. } = issued_spans else { return };
+ let tcx = self.infcx.tcx;
+ let hir = tcx.hir();
- // check whether the borrowed place is capturing `self` by mut reference
+ // Get the type of the local that we are trying to borrow
let local = borrowed_place.local;
- let Some(_) = self
- .body
- .local_decls
- .get(local)
- .map(|l| mut_borrow_of_mutable_ref(l, self.local_names[local])) else { return };
+ let local_ty = self.body.local_decls[local].ty;
+
+ // Get the body the error happens in
+ let Some(body_id) = hir.get(self.mir_hir_id()).body_id() else { return };
+
+ let body_expr = hir.body(body_id).value;
+
+ struct ClosureFinder<'hir> {
+ hir: rustc_middle::hir::map::Map<'hir>,
+ borrow_span: Span,
+ res: Option<(&'hir hir::Expr<'hir>, &'hir hir::Closure<'hir>)>,
+ /// The path expression with the `borrow_span` span
+ error_path: Option<(&'hir hir::Expr<'hir>, &'hir hir::QPath<'hir>)>,
+ }
+ impl<'hir> Visitor<'hir> for ClosureFinder<'hir> {
+ type NestedFilter = OnlyBodies;
+
+ fn nested_visit_map(&mut self) -> Self::Map {
+ self.hir
+ }
+
+ fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) {
+ if let hir::ExprKind::Path(qpath) = &ex.kind
+ && ex.span == self.borrow_span
+ {
+ self.error_path = Some((ex, qpath));
+ }
+
+ if let hir::ExprKind::Closure(closure) = ex.kind
+ && ex.span.contains(self.borrow_span)
+ // To support cases like `|| { v.call(|this| v.get()) }`
+ // FIXME: actually support such cases (need to figure out how to move from the capture place to original local)
+ && self.res.as_ref().map_or(true, |(prev_res, _)| prev_res.span.contains(ex.span))
+ {
+ self.res = Some((ex, closure));
+ }
+
+ hir::intravisit::walk_expr(self, ex);
+ }
+ }
+
+ // Find the closure that most tightly wraps `capture_kind_span`
+ let mut finder =
+ ClosureFinder { hir, borrow_span: capture_kind_span, res: None, error_path: None };
+ finder.visit_expr(body_expr);
+ let Some((closure_expr, closure)) = finder.res else { return };
+
+ let typeck_results = tcx.typeck(self.mir_def_id());
+
+ // Check that the parent of the closure is a method call,
+ // with receiver matching with local's type (modulo refs)
+ let parent = hir.parent_id(closure_expr.hir_id);
+ if let hir::Node::Expr(parent) = hir.get(parent) {
+ if let hir::ExprKind::MethodCall(_, recv, ..) = parent.kind {
+ let recv_ty = typeck_results.expr_ty(recv);
+
+ if recv_ty.peel_refs() != local_ty {
+ return;
+ }
+ }
+ }
+
+ // Get closure's arguments
+ let ty::Closure(_, substs) = typeck_results.expr_ty(closure_expr).kind() else { unreachable!() };
+ let sig = substs.as_closure().sig();
+ let tupled_params =
+ tcx.erase_late_bound_regions(sig.inputs().iter().next().unwrap().map_bound(|&b| b));
+ let ty::Tuple(params) = tupled_params.kind() else { return };
+
+ // Find the first argument with a matching type, get its name
+ let Some((_, this_name)) = params
+ .iter()
+ .zip(hir.body_param_names(closure.body))
+ .find(|(param_ty, name)|{
+ // FIXME: also support deref for stuff like `Rc` arguments
+ param_ty.peel_refs() == local_ty && name != &Ident::empty()
+ })
+ else { return };
+
+ let spans;
+ if let Some((_path_expr, qpath)) = finder.error_path
+ && let hir::QPath::Resolved(_, path) = qpath
+ && let hir::def::Res::Local(local_id) = path.res
+ {
+ // Find all references to the problematic variable in this closure body
+
+ struct VariableUseFinder {
+ local_id: hir::HirId,
+ spans: Vec<Span>,
+ }
+ impl<'hir> Visitor<'hir> for VariableUseFinder {
+ fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) {
+ if let hir::ExprKind::Path(qpath) = &ex.kind
+ && let hir::QPath::Resolved(_, path) = qpath
+ && let hir::def::Res::Local(local_id) = path.res
+ && local_id == self.local_id
+ {
+ self.spans.push(ex.span);
+ }
+
+ hir::intravisit::walk_expr(self, ex);
+ }
+ }
+
+ let mut finder = VariableUseFinder { local_id, spans: Vec::new() };
+ finder.visit_expr(hir.body(closure.body).value);
+
+ spans = finder.spans;
+ } else {
+ spans = vec![capture_kind_span];
+ }
+
+ err.multipart_suggestion(
+ "try using the closure argument",
+ iter::zip(spans, iter::repeat(this_name.to_string())).collect(),
+ Applicability::MaybeIncorrect,
+ );
+ }
+
+ fn suggest_binding_for_closure_capture_self(
+ &self,
+ err: &mut Diagnostic,
+ issued_spans: &UseSpans<'tcx>,
+ ) {
+ let UseSpans::ClosureUse { capture_kind_span, .. } = issued_spans else { return };
+ let hir = self.infcx.tcx.hir();
struct ExpressionFinder<'hir> {
capture_span: Span,
@@ -1731,9 +1915,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
err.span_label(borrow_span, "borrowed value does not live long enough");
err.span_label(drop_span, format!("`{}` dropped here while still borrowed", name));
- let within = if borrow_spans.for_generator() { " by generator" } else { "" };
-
- borrow_spans.args_span_label(&mut err, format!("value captured here{}", within));
+ borrow_spans.args_subdiag(&mut err, |args_span| {
+ crate::session_diagnostics::CaptureArgLabel::Capture {
+ is_within: borrow_spans.for_generator(),
+ args_span,
+ }
+ });
explanation.add_explanation_to_diagnostic(
self.infcx.tcx,
@@ -1947,9 +2134,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
None,
);
- let within = if borrow_spans.for_generator() { " by generator" } else { "" };
-
- borrow_spans.args_span_label(&mut err, format!("value captured here{}", within));
+ borrow_spans.args_subdiag(&mut err, |args_span| {
+ crate::session_diagnostics::CaptureArgLabel::Capture {
+ is_within: borrow_spans.for_generator(),
+ args_span,
+ }
+ });
err
}
@@ -2382,11 +2572,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
section,
"assign",
);
- loan_spans.var_span_label(
- &mut err,
- format!("borrow occurs due to use{}", loan_spans.describe()),
- loan.kind.describe_mutability(),
- );
+
+ loan_spans.var_subdiag(None, &mut err, Some(loan.kind), |kind, var_span| {
+ use crate::session_diagnostics::CaptureVarCause::*;
+ match kind {
+ Some(_) => BorrowUseInGenerator { var_span },
+ None => BorrowUseInClosure { var_span },
+ }
+ });
self.buffer_error(err);
@@ -2396,11 +2589,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let mut err = self.cannot_assign_to_borrowed(span, loan_span, &descr_place);
- loan_spans.var_span_label(
- &mut err,
- format!("borrow occurs due to use{}", loan_spans.describe()),
- loan.kind.describe_mutability(),
- );
+ loan_spans.var_subdiag(None, &mut err, Some(loan.kind), |kind, var_span| {
+ use crate::session_diagnostics::CaptureVarCause::*;
+ match kind {
+ Some(_) => BorrowUseInGenerator { var_span },
+ None => BorrowUseInClosure { var_span },
+ }
+ });
self.explain_why_borrow_contains_point(location, loan, None).add_explanation_to_diagnostic(
self.infcx.tcx,
@@ -2424,7 +2619,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
Some((method_did, method_substs)),
) = (
&self.body[loan.reserve_location.block].terminator,
- rustc_const_eval::util::find_self_call(
+ rustc_middle::util::find_self_call(
tcx,
self.body,
loan.assigned_place.local,
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 110354a20d8..4a85df9f8c0 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -1,7 +1,10 @@
//! Borrow checker diagnostics.
+use crate::session_diagnostics::{
+ CaptureArgLabel, CaptureReasonLabel, CaptureReasonNote, CaptureReasonSuggest, CaptureVarCause,
+ CaptureVarKind, CaptureVarPathUseCause, OnClosureNote,
+};
use itertools::Itertools;
-use rustc_const_eval::util::{call_kind, CallDesugaringKind};
use rustc_errors::{Applicability, Diagnostic};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, Namespace};
@@ -15,6 +18,7 @@ use rustc_middle::mir::{
};
use rustc_middle::ty::print::Print;
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
+use rustc_middle::util::{call_kind, CallDesugaringKind};
use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult};
use rustc_span::def_id::LocalDefId;
use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP};
@@ -45,7 +49,7 @@ pub(crate) use mutability_errors::AccessKind;
pub(crate) use outlives_suggestion::OutlivesSuggestionBuilder;
pub(crate) use region_errors::{ErrorConstraintInfo, RegionErrorKind, RegionErrors};
pub(crate) use region_name::{RegionName, RegionNameSource};
-pub(crate) use rustc_const_eval::util::CallKind;
+pub(crate) use rustc_middle::util::CallKind;
pub(super) struct DescribePlaceOpt {
pub including_downcast: bool,
@@ -117,13 +121,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if let ty::Closure(did, _) = self.body.local_decls[closure].ty.kind() {
let did = did.expect_local();
if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) {
- diag.span_note(
- *span,
- &format!(
- "closure cannot be invoked more than once because it moves the \
- variable `{}` out of its environment",
- ty::place_to_string_for_capture(self.infcx.tcx, hir_place)
- ),
+ diag.eager_subdiagnostic(
+ &self.infcx.tcx.sess.parse_sess.span_diagnostic,
+ OnClosureNote::InvokedTwice {
+ place_name: &ty::place_to_string_for_capture(
+ self.infcx.tcx,
+ hir_place,
+ ),
+ span: *span,
+ },
);
return true;
}
@@ -137,13 +143,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if let ty::Closure(did, _) = self.body.local_decls[target].ty.kind() {
let did = did.expect_local();
if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) {
- diag.span_note(
- *span,
- &format!(
- "closure cannot be moved more than once as it is not `Copy` due to \
- moving the variable `{}` out of its environment",
- ty::place_to_string_for_capture(self.infcx.tcx, hir_place)
- ),
+ diag.eager_subdiagnostic(
+ &self.infcx.tcx.sess.parse_sess.span_diagnostic,
+ OnClosureNote::MovedTwice {
+ place_name: &ty::place_to_string_for_capture(self.infcx.tcx, hir_place),
+ span: *span,
+ },
);
return true;
}
@@ -380,25 +385,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
}
- /// Add a note that a type does not implement `Copy`
- pub(super) fn note_type_does_not_implement_copy(
- &self,
- err: &mut Diagnostic,
- place_desc: &str,
- ty: Ty<'tcx>,
- span: Option<Span>,
- move_prefix: &str,
- ) {
- let message = format!(
- "{move_prefix}move occurs because {place_desc} has type `{ty}`, which does not implement the `Copy` trait",
- );
- if let Some(span) = span {
- err.span_label(span, message);
- } else {
- err.note(&message);
- }
- }
-
pub(super) fn borrowed_content_source(
&self,
deref_base: PlaceRef<'tcx>,
@@ -582,9 +568,13 @@ impl UseSpans<'_> {
}
/// Add a span label to the arguments of the closure, if it exists.
- pub(super) fn args_span_label(self, err: &mut Diagnostic, message: impl Into<String>) {
+ pub(super) fn args_subdiag(
+ self,
+ err: &mut Diagnostic,
+ f: impl FnOnce(Span) -> CaptureArgLabel,
+ ) {
if let UseSpans::ClosureUse { args_span, .. } = self {
- err.span_label(args_span, message);
+ err.subdiagnostic(f(args_span));
}
}
@@ -595,8 +585,8 @@ impl UseSpans<'_> {
err: &mut Diagnostic,
action: crate::InitializationRequiringAction,
) {
- use crate::session_diagnostics::CaptureVarPathUseCause::*;
use crate::InitializationRequiringAction::*;
+ use CaptureVarPathUseCause::*;
if let UseSpans::ClosureUse { generator_kind, path_span, .. } = self {
match generator_kind {
Some(_) => {
@@ -619,34 +609,14 @@ impl UseSpans<'_> {
}
}
- /// Add a span label to the use of the captured variable, if it exists.
- pub(super) fn var_span_label(
- self,
- err: &mut Diagnostic,
- message: impl Into<String>,
- kind_desc: impl Into<String>,
- ) {
- if let UseSpans::ClosureUse { capture_kind_span, path_span, .. } = self {
- if capture_kind_span == path_span {
- err.span_label(capture_kind_span, message);
- } else {
- let capture_kind_label =
- format!("capture is {} because of use here", kind_desc.into());
- let path_label = message;
- err.span_label(capture_kind_span, capture_kind_label);
- err.span_label(path_span, path_label);
- }
- }
- }
-
/// Add a subdiagnostic to the use of the captured variable, if it exists.
pub(super) fn var_subdiag(
self,
+ handler: Option<&rustc_errors::Handler>,
err: &mut Diagnostic,
kind: Option<rustc_middle::mir::BorrowKind>,
- f: impl Fn(Option<GeneratorKind>, Span) -> crate::session_diagnostics::CaptureVarCause,
+ f: impl FnOnce(Option<GeneratorKind>, Span) -> CaptureVarCause,
) {
- use crate::session_diagnostics::CaptureVarKind::*;
if let UseSpans::ClosureUse { generator_kind, capture_kind_span, path_span, .. } = self {
if capture_kind_span != path_span {
err.subdiagnostic(match kind {
@@ -654,17 +624,21 @@ impl UseSpans<'_> {
rustc_middle::mir::BorrowKind::Shared
| rustc_middle::mir::BorrowKind::Shallow
| rustc_middle::mir::BorrowKind::Unique => {
- Immute { kind_span: capture_kind_span }
+ CaptureVarKind::Immut { kind_span: capture_kind_span }
}
rustc_middle::mir::BorrowKind::Mut { .. } => {
- Mut { kind_span: capture_kind_span }
+ CaptureVarKind::Mut { kind_span: capture_kind_span }
}
},
- None => Move { kind_span: capture_kind_span },
+ None => CaptureVarKind::Move { kind_span: capture_kind_span },
});
};
- err.subdiagnostic(f(generator_kind, path_span));
+ let diag = f(generator_kind, path_span);
+ match handler {
+ Some(hd) => err.eager_subdiagnostic(hd, diag),
+ None => err.subdiagnostic(diag),
+ };
}
}
@@ -684,20 +658,6 @@ impl UseSpans<'_> {
}
}
- /// Describe the span associated with a use of a place.
- pub(super) fn describe(&self) -> &str {
- match *self {
- UseSpans::ClosureUse { generator_kind, .. } => {
- if generator_kind.is_some() {
- " in generator"
- } else {
- " in closure"
- }
- }
- _ => "",
- }
- }
-
pub(super) fn or_else<F>(self, if_other: F) -> Self
where
F: FnOnce() -> Self,
@@ -788,6 +748,15 @@ impl<'tcx> BorrowedContentSource<'tcx> {
}
}
+///helper struct for explain_captures()
+struct CapturedMessageOpt {
+ is_partial_move: bool,
+ is_loop_message: bool,
+ is_move_msg: bool,
+ is_loop_move: bool,
+ maybe_reinitialized_locations_is_empty: bool,
+}
+
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
/// Finds the spans associated to a move or copy of move_place at location.
pub(super) fn move_spans(
@@ -874,7 +843,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}) = &self.body[location.block].terminator
{
let Some((method_did, method_substs)) =
- rustc_const_eval::util::find_self_call(
+ rustc_middle::util::find_self_call(
self.infcx.tcx,
&self.body,
target_temp,
@@ -1027,12 +996,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
move_span: Span,
move_spans: UseSpans<'tcx>,
moved_place: Place<'tcx>,
- partially_str: &str,
- loop_message: &str,
- move_msg: &str,
- is_loop_move: bool,
- maybe_reinitialized_locations_is_empty: bool,
+ msg_opt: CapturedMessageOpt,
) {
+ let CapturedMessageOpt {
+ is_partial_move: is_partial,
+ is_loop_message,
+ is_move_msg,
+ is_loop_move,
+ maybe_reinitialized_locations_is_empty,
+ } = msg_opt;
if let UseSpans::FnSelfUse { var_span, fn_call_span, fn_span, kind } = move_spans {
let place_name = self
.describe_place(moved_place.as_ref())
@@ -1042,30 +1014,26 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
CallKind::FnCall { fn_trait_id, .. }
if Some(fn_trait_id) == self.infcx.tcx.lang_items().fn_once_trait() =>
{
- err.span_label(
+ err.subdiagnostic(CaptureReasonLabel::Call {
fn_call_span,
- &format!(
- "{place_name} {partially_str}moved due to this call{loop_message}",
- ),
- );
- err.span_note(
- var_span,
- "this value implements `FnOnce`, which causes it to be moved when called",
- );
+ place_name: &place_name,
+ is_partial,
+ is_loop_message,
+ });
+ err.subdiagnostic(CaptureReasonNote::FnOnceMoveInCall { var_span });
}
CallKind::Operator { self_arg, .. } => {
let self_arg = self_arg.unwrap();
- err.span_label(
+ err.subdiagnostic(CaptureReasonLabel::OperatorUse {
fn_call_span,
- &format!(
- "{place_name} {partially_str}moved due to usage in operator{loop_message}",
- ),
- );
+ place_name: &place_name,
+ is_partial,
+ is_loop_message,
+ });
if self.fn_self_span_reported.insert(fn_span) {
- err.span_note(
- self_arg.span,
- "calling this operator moves the left-hand side",
- );
+ err.subdiagnostic(CaptureReasonNote::LhsMoveByOperator {
+ span: self_arg.span,
+ });
}
}
CallKind::Normal { self_arg, desugaring, method_did, method_substs } => {
@@ -1086,23 +1054,18 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
_ => false,
};
if suggest {
- err.span_suggestion_verbose(
- move_span.shrink_to_lo(),
- &format!(
- "consider iterating over a slice of the `{ty}`'s content to \
- avoid moving into the `for` loop",
- ),
- "&",
- Applicability::MaybeIncorrect,
- );
+ err.subdiagnostic(CaptureReasonSuggest::IterateSlice {
+ ty,
+ span: move_span.shrink_to_lo(),
+ });
}
- err.span_label(
+ err.subdiagnostic(CaptureReasonLabel::ImplicitCall {
fn_call_span,
- &format!(
- "{place_name} {partially_str}moved due to this implicit call to `.into_iter()`{loop_message}",
- ),
- );
+ place_name: &place_name,
+ is_partial,
+ is_loop_message,
+ });
// If the moved place was a `&mut` ref, then we can
// suggest to reborrow it where it was moved, so it
// will still be valid by the time we get to the usage.
@@ -1125,13 +1088,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
}
} else {
- err.span_label(
+ err.subdiagnostic(CaptureReasonLabel::MethodCall {
fn_call_span,
- &format!(
- "{place_name} {partially_str}moved due to this method call{loop_message}",
- ),
- );
-
+ place_name: &place_name,
+ is_partial,
+ is_loop_message,
+ });
let infcx = tcx.infer_ctxt().build();
// Erase and shadow everything that could be passed to the new infcx.
let ty = tcx.erase_regions(moved_place.ty(self.body, tcx).ty);
@@ -1147,12 +1109,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
)
&& infcx.can_eq(self.param_env, ty, self_ty)
{
- err.span_suggestion_verbose(
- fn_call_span.shrink_to_lo(),
- "consider reborrowing the `Pin` instead of moving it",
- "as_mut().".to_string(),
- Applicability::MaybeIncorrect,
- );
+ err.eager_subdiagnostic(
+ &self.infcx.tcx.sess.parse_sess.span_diagnostic,
+ CaptureReasonSuggest::FreshReborrow {
+ span: fn_call_span.shrink_to_lo(),
+ });
}
if let Some(clone_trait) = tcx.lang_items().clone_trait()
&& let trait_ref = tcx.mk_trait_ref(clone_trait, [ty])
@@ -1177,10 +1138,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// 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!("`{func}` takes ownership of the receiver `self`, which moves {place_name}")
- );
+ err.subdiagnostic(CaptureReasonNote::FuncTakeSelf {
+ func,
+ place_name,
+ span: self_arg.span,
+ });
}
let parent_did = tcx.parent(method_did);
let parent_self_ty =
@@ -1194,30 +1156,28 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
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,
- "help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents",
- );
+ err.subdiagnostic(CaptureReasonLabel::BorrowContent { var_span });
}
}
// Other desugarings takes &self, which cannot cause a move
_ => {}
}
} else {
- if move_span != span || !loop_message.is_empty() {
- err.span_label(
+ if move_span != span || is_loop_message {
+ err.subdiagnostic(CaptureReasonLabel::MovedHere {
move_span,
- format!("value {partially_str}moved{move_msg} here{loop_message}"),
- );
+ is_partial,
+ is_move_msg,
+ is_loop_message,
+ });
}
// If the move error occurs due to a loop, don't show
// another message for the same span
- if loop_message.is_empty() {
- move_spans.var_span_label(
- err,
- format!("variable {partially_str}moved due to use{}", move_spans.describe()),
- "moved",
- );
+ if !is_loop_message {
+ move_spans.var_subdiag(None, err, None, |kind, var_span| match kind {
+ Some(_) => CaptureVarCause::PartialMoveUseInGenerator { var_span, is_partial },
+ None => CaptureVarCause::PartialMoveUseInClosure { var_span, is_partial },
+ })
}
}
}
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index 3662bec0c76..67af96a71e3 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -6,6 +6,7 @@ use rustc_mir_dataflow::move_paths::{
};
use rustc_span::{BytePos, Span};
+use crate::diagnostics::CapturedMessageOpt;
use crate::diagnostics::{DescribePlaceOpt, UseSpans};
use crate::prefixes::PrefixSet;
use crate::MirBorrowckCtxt;
@@ -397,10 +398,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}
}
};
+ let msg_opt = CapturedMessageOpt {
+ is_partial_move: false,
+ is_loop_message: false,
+ is_move_msg: false,
+ is_loop_move: false,
+ maybe_reinitialized_locations_is_empty: true,
+ };
if let Some(use_spans) = use_spans {
- self.explain_captures(
- &mut err, span, span, use_spans, move_place, "", "", "", false, true,
- );
+ self.explain_captures(&mut err, span, span, use_spans, move_place, msg_opt);
}
err
}
@@ -416,13 +422,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
None => "value".to_string(),
};
- self.note_type_does_not_implement_copy(
- err,
- &place_desc,
- place_ty,
- Some(span),
- "",
- );
+ err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
+ is_partial_move: false,
+ ty: place_ty,
+ place: &place_desc,
+ span,
+ });
} else {
binds_to.sort();
binds_to.dedup();
@@ -444,9 +449,19 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
Some(desc) => format!("`{desc}`"),
None => "value".to_string(),
};
- self.note_type_does_not_implement_copy(err, &place_desc, place_ty, Some(span), "");
+ err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
+ is_partial_move: false,
+ ty: place_ty,
+ place: &place_desc,
+ span,
+ });
- use_spans.args_span_label(err, format!("{place_desc} is moved here"));
+ use_spans.args_subdiag(err, |args_span| {
+ crate::session_diagnostics::CaptureArgLabel::MoveOutPlace {
+ place: place_desc,
+ args_span,
+ }
+ });
}
}
}
@@ -534,13 +549,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}
if binds_to.len() == 1 {
- self.note_type_does_not_implement_copy(
- err,
- &format!("`{}`", self.local_names[*local].unwrap()),
- bind_to.ty,
- Some(binding_span),
- "",
- );
+ let place_desc = &format!("`{}`", self.local_names[*local].unwrap());
+ err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
+ is_partial_move: false,
+ ty: bind_to.ty,
+ place: &place_desc,
+ span: binding_span,
+ });
}
}
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 9d904009650..e3d81194ac8 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -15,8 +15,8 @@ use rustc_span::{sym, BytePos, Span};
use rustc_target::abi::FieldIdx;
use crate::diagnostics::BorrowedContentSource;
+use crate::util::FindAssignments;
use crate::MirBorrowckCtxt;
-use rustc_const_eval::util::collect_writes::FindAssignments;
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub(crate) enum AccessKind {
@@ -231,14 +231,18 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}
}
if suggest {
- borrow_spans.var_span_label(
- &mut err,
- format!(
- "mutable borrow occurs due to use of {} in closure",
- self.describe_any_place(access_place.as_ref()),
- ),
- "mutable",
- );
+ borrow_spans.var_subdiag(
+ None,
+ &mut err,
+ Some(mir::BorrowKind::Mut { allow_two_phase_borrow: false }),
+ |_kind, var_span| {
+ let place = self.describe_any_place(access_place.as_ref());
+ crate::session_diagnostics::CaptureVarCause::MutableBorrowUsePlaceClosure {
+ place,
+ var_span,
+ }
+ },
+ );
}
borrow_span
}
@@ -1143,7 +1147,7 @@ pub fn mut_borrow_of_mutable_ref(local_decl: &LocalDecl<'_>, local_name: Option<
// suggest removing the `&mut`.
//
// Deliberately fall into this case for all implicit self types,
- // so that we don't fall in to the next case with them.
+ // so that we don't fall into the next case with them.
kind == hir::ImplicitSelfKind::MutRef
}
_ if Some(kw::SelfLower) == local_name => {
@@ -1231,7 +1235,7 @@ fn suggest_ampmut<'tcx>(
}
}
- let (suggestability, highlight_span) = match opt_ty_info {
+ let (suggestibility, highlight_span) = match opt_ty_info {
// if this is a variable binding with an explicit type,
// try to highlight that for the suggestion.
Some(ty_span) => (true, ty_span),
@@ -1252,7 +1256,7 @@ fn suggest_ampmut<'tcx>(
let ty_mut = local_decl.ty.builtin_deref(true).unwrap();
assert_eq!(ty_mut.mutbl, hir::Mutability::Not);
(
- suggestability,
+ suggestibility,
highlight_span,
if local_decl.ty.is_ref() {
format!("&mut {}", ty_mut.ty)
diff --git a/compiler/rustc_borrowck/src/diagnostics/var_name.rs b/compiler/rustc_borrowck/src/diagnostics/var_name.rs
index 376415e3d32..aa7cf3578ea 100644
--- a/compiler/rustc_borrowck/src/diagnostics/var_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/var_name.rs
@@ -3,7 +3,7 @@
use crate::region_infer::RegionInferenceContext;
use crate::Upvar;
-use rustc_index::vec::{Idx, IndexSlice};
+use rustc_index::vec::IndexSlice;
use rustc_middle::mir::{Body, Local};
use rustc_middle::ty::{RegionVid, TyCtxt};
use rustc_span::source_map::Span;
@@ -117,7 +117,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
argument_index: usize,
) -> (Option<Symbol>, Span) {
let implicit_inputs = self.universal_regions().defining_ty.implicit_inputs();
- let argument_local = Local::new(implicit_inputs + argument_index + 1);
+ let argument_local = Local::from_usize(implicit_inputs + argument_index + 1);
debug!("get_argument_name_and_span_for_region: argument_local={argument_local:?}");
let argument_name = local_names[argument_local];
diff --git a/compiler/rustc_borrowck/src/facts.rs b/compiler/rustc_borrowck/src/facts.rs
index 02ffb51fbb7..87fad9a355d 100644
--- a/compiler/rustc_borrowck/src/facts.rs
+++ b/compiler/rustc_borrowck/src/facts.rs
@@ -4,7 +4,6 @@ use crate::location::{LocationIndex, LocationTable};
use crate::BorrowIndex;
use polonius_engine::AllFacts as PoloniusFacts;
use polonius_engine::Atom;
-use rustc_index::vec::Idx;
use rustc_middle::mir::Local;
use rustc_middle::ty::{RegionVid, TyCtxt};
use rustc_mir_dataflow::move_paths::MovePathIndex;
@@ -93,13 +92,13 @@ impl AllFactsExt for AllFacts {
impl Atom for BorrowIndex {
fn index(self) -> usize {
- Idx::index(self)
+ self.as_usize()
}
}
impl Atom for LocationIndex {
fn index(self) -> usize {
- Idx::index(self)
+ self.as_usize()
}
}
diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs
index 498d254da65..06986f848bf 100644
--- a/compiler/rustc_borrowck/src/invalidation.rs
+++ b/compiler/rustc_borrowck/src/invalidation.rs
@@ -79,7 +79,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
}
// Only relevant for mir typeck
StatementKind::AscribeUserType(..)
- // Only relevant for unsafeck
+ // Only relevant for liveness and unsafeck
| StatementKind::PlaceMention(..)
// Doesn't have any language semantics
| StatementKind::Coverage(..)
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index a4b285a34fa..5bf3e7632ac 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -20,6 +20,7 @@ extern crate tracing;
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_data_structures::graph::dominators::Dominators;
use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticMessage, SubdiagnosticMessage};
+use rustc_fluent_macro::fluent_messages;
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_index::bit_set::ChunkedBitSet;
@@ -27,7 +28,6 @@ use rustc_index::vec::{IndexSlice, IndexVec};
use rustc_infer::infer::{
DefiningAnchor, InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, TyCtxtInferExt,
};
-use rustc_macros::fluent_messages;
use rustc_middle::mir::{
traversal, Body, ClearCrossCrate, Local, Location, Mutability, NonDivergingIntrinsic, Operand,
Place, PlaceElem, PlaceRef, VarDebugInfoContents,
@@ -88,6 +88,7 @@ mod session_diagnostics;
mod type_check;
mod universal_regions;
mod used_muts;
+mod util;
/// A public API provided for the Rust compiler consumers.
pub mod consumers;
@@ -118,24 +119,12 @@ impl<'tcx> TyCtxtConsts<'tcx> {
}
pub fn provide(providers: &mut Providers) {
- *providers = Providers {
- mir_borrowck: |tcx, did| {
- if let Some(def) = ty::WithOptConstParam::try_lookup(did, tcx) {
- tcx.mir_borrowck_const_arg(def)
- } else {
- mir_borrowck(tcx, ty::WithOptConstParam::unknown(did))
- }
- },
- mir_borrowck_const_arg: |tcx, (did, param_did)| {
- mir_borrowck(tcx, ty::WithOptConstParam { did, const_param_did: Some(param_did) })
- },
- ..*providers
- };
+ *providers = Providers { mir_borrowck, ..*providers };
}
-fn mir_borrowck(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> &BorrowCheckResult<'_> {
+fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> {
let (input_body, promoted) = tcx.mir_promoted(def);
- debug!("run query mir_borrowck: {}", tcx.def_path_str(def.did.to_def_id()));
+ debug!("run query mir_borrowck: {}", tcx.def_path_str(def.to_def_id()));
if input_body.borrow().should_skip() {
debug!("Skipping borrowck because of injected body");
@@ -149,7 +138,7 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> &Bor
return tcx.arena.alloc(result);
}
- let hir_owner = tcx.hir().local_def_id_to_hir_id(def.did).owner;
+ let hir_owner = tcx.hir().local_def_id_to_hir_id(def).owner;
let infcx =
tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)).build();
@@ -166,19 +155,19 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> &Bor
/// If `return_body_with_facts` is true, then return the body with non-erased
/// region ids on which the borrow checking was performed together with Polonius
/// facts.
-#[instrument(skip(infcx, input_body, input_promoted), fields(id=?input_body.source.with_opt_param().as_local().unwrap()), level = "debug")]
+#[instrument(skip(infcx, input_body, input_promoted), fields(id=?input_body.source.def_id()), level = "debug")]
fn do_mir_borrowck<'tcx>(
infcx: &InferCtxt<'tcx>,
input_body: &Body<'tcx>,
input_promoted: &IndexSlice<Promoted, Body<'tcx>>,
return_body_with_facts: bool,
) -> (BorrowCheckResult<'tcx>, Option<Box<BodyWithBorrowckFacts<'tcx>>>) {
- let def = input_body.source.with_opt_param().as_local().unwrap();
+ let def = input_body.source.def_id().expect_local();
debug!(?def);
let tcx = infcx.tcx;
let infcx = BorrowckInferCtxt::new(infcx);
- let param_env = tcx.param_env(def.did);
+ let param_env = tcx.param_env(def);
let mut local_names = IndexVec::from_elem(None, &input_body.local_decls);
for var_debug_info in &input_body.var_debug_info {
@@ -206,7 +195,7 @@ fn do_mir_borrowck<'tcx>(
errors.set_tainted_by_errors(e);
}
let upvars: Vec<_> = tcx
- .closure_captures(def.did)
+ .closure_captures(def)
.iter()
.map(|&captured_place| {
let capture = captured_place.info.capture_kind;
@@ -248,7 +237,7 @@ fn do_mir_borrowck<'tcx>(
.iterate_to_fixpoint()
.into_results_cursor(&body);
- let locals_are_invalidated_at_exit = tcx.hir().body_owner_kind(def.did).is_fn_or_closure();
+ let locals_are_invalidated_at_exit = tcx.hir().body_owner_kind(def).is_fn_or_closure();
let borrow_set =
Rc::new(BorrowSet::build(tcx, body, locals_are_invalidated_at_exit, &mdpe.move_data));
@@ -528,7 +517,7 @@ impl<'cx, 'tcx> BorrowckInferCtxt<'cx, 'tcx> {
where
F: Fn() -> RegionCtxt,
{
- let next_region = self.infcx.next_nll_region_var(origin.clone());
+ let next_region = self.infcx.next_nll_region_var(origin);
let vid = next_region.as_var();
if cfg!(debug_assertions) && !self.inside_canonicalization_ctxt() {
@@ -676,7 +665,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
}
// Only relevant for mir typeck
StatementKind::AscribeUserType(..)
- // Only relevant for unsafeck
+ // Only relevant for liveness and unsafeck
| StatementKind::PlaceMention(..)
// Doesn't have any language semantics
| StatementKind::Coverage(..)
diff --git a/compiler/rustc_borrowck/src/location.rs b/compiler/rustc_borrowck/src/location.rs
index 288b7d85be2..08fa912f368 100644
--- a/compiler/rustc_borrowck/src/location.rs
+++ b/compiler/rustc_borrowck/src/location.rs
@@ -1,6 +1,6 @@
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
-use rustc_index::vec::{Idx, IndexVec};
+use rustc_index::vec::IndexVec;
use rustc_middle::mir::{BasicBlock, Body, Location};
/// Maps between a MIR Location, which identifies a particular
@@ -50,19 +50,19 @@ impl LocationTable {
}
pub fn all_points(&self) -> impl Iterator<Item = LocationIndex> {
- (0..self.num_points).map(LocationIndex::new)
+ (0..self.num_points).map(LocationIndex::from_usize)
}
pub fn start_index(&self, location: Location) -> LocationIndex {
let Location { block, statement_index } = location;
let start_index = self.statements_before_block[block];
- LocationIndex::new(start_index + statement_index * 2)
+ LocationIndex::from_usize(start_index + statement_index * 2)
}
pub fn mid_index(&self, location: Location) -> LocationIndex {
let Location { block, statement_index } = location;
let start_index = self.statements_before_block[block];
- LocationIndex::new(start_index + statement_index * 2 + 1)
+ LocationIndex::from_usize(start_index + statement_index * 2 + 1)
}
pub fn to_location(&self, index: LocationIndex) -> RichLocation {
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index 59a3ab3189d..78bdf00a69c 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -7,8 +7,8 @@ use rustc_hir::def_id::LocalDefId;
use rustc_index::vec::IndexSlice;
use rustc_middle::mir::{create_dump_file, dump_enabled, dump_mir, PassWhere};
use rustc_middle::mir::{
- BasicBlock, Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location,
- Promoted,
+ Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location, Promoted,
+ START_BLOCK,
};
use rustc_middle::ty::{self, OpaqueHiddenType, TyCtxt};
use rustc_span::symbol::sym;
@@ -61,7 +61,7 @@ pub(crate) fn replace_regions_in_mir<'tcx>(
body: &mut Body<'tcx>,
promoted: &mut IndexSlice<Promoted, Body<'tcx>>,
) -> UniversalRegions<'tcx> {
- let def = body.source.with_opt_param().as_local().unwrap();
+ let def = body.source.def_id().expect_local();
debug!(?def);
@@ -94,8 +94,8 @@ fn populate_polonius_move_facts(
}
}
- let fn_entry_start = location_table
- .start_index(Location { block: BasicBlock::from_u32(0u32), statement_index: 0 });
+ let fn_entry_start =
+ location_table.start_index(Location { block: START_BLOCK, statement_index: 0 });
// initialized_at
for init in move_data.inits.iter() {
diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs
index a3678929099..bb95101845f 100644
--- a/compiler/rustc_borrowck/src/session_diagnostics.rs
+++ b/compiler/rustc_borrowck/src/session_diagnostics.rs
@@ -184,7 +184,7 @@ pub(crate) enum CaptureVarPathUseCause {
#[derive(Subdiagnostic)]
pub(crate) enum CaptureVarKind {
#[label(borrowck_capture_immute)]
- Immute {
+ Immut {
#[primary_span]
kind_span: Span,
},
@@ -204,16 +204,80 @@ pub(crate) enum CaptureVarKind {
pub(crate) enum CaptureVarCause {
#[label(borrowck_var_borrow_by_use_place_in_generator)]
BorrowUsePlaceGenerator {
+ is_single_var: bool,
place: String,
#[primary_span]
var_span: Span,
},
#[label(borrowck_var_borrow_by_use_place_in_closure)]
BorrowUsePlaceClosure {
+ is_single_var: bool,
place: String,
#[primary_span]
var_span: Span,
},
+ #[label(borrowck_var_borrow_by_use_in_generator)]
+ BorrowUseInGenerator {
+ #[primary_span]
+ var_span: Span,
+ },
+ #[label(borrowck_var_borrow_by_use_in_closure)]
+ BorrowUseInClosure {
+ #[primary_span]
+ var_span: Span,
+ },
+ #[label(borrowck_var_move_by_use_in_generator)]
+ MoveUseInGenerator {
+ #[primary_span]
+ var_span: Span,
+ },
+ #[label(borrowck_var_move_by_use_in_closure)]
+ MoveUseInClosure {
+ #[primary_span]
+ var_span: Span,
+ },
+ #[label(borrowck_var_first_borrow_by_use_place_in_generator)]
+ FirstBorrowUsePlaceGenerator {
+ place: String,
+ #[primary_span]
+ var_span: Span,
+ },
+ #[label(borrowck_var_first_borrow_by_use_place_in_closure)]
+ FirstBorrowUsePlaceClosure {
+ place: String,
+ #[primary_span]
+ var_span: Span,
+ },
+ #[label(borrowck_var_second_borrow_by_use_place_in_generator)]
+ SecondBorrowUsePlaceGenerator {
+ place: String,
+ #[primary_span]
+ var_span: Span,
+ },
+ #[label(borrowck_var_second_borrow_by_use_place_in_closure)]
+ SecondBorrowUsePlaceClosure {
+ place: String,
+ #[primary_span]
+ var_span: Span,
+ },
+ #[label(borrowck_var_mutable_borrow_by_use_place_in_closure)]
+ MutableBorrowUsePlaceClosure {
+ place: String,
+ #[primary_span]
+ var_span: Span,
+ },
+ #[label(borrowck_partial_var_move_by_use_in_generator)]
+ PartialMoveUseInGenerator {
+ #[primary_span]
+ var_span: Span,
+ is_partial: bool,
+ },
+ #[label(borrowck_partial_var_move_by_use_in_closure)]
+ PartialMoveUseInClosure {
+ #[primary_span]
+ var_span: Span,
+ is_partial: bool,
+ },
}
#[derive(Diagnostic)]
@@ -239,3 +303,144 @@ pub(crate) struct NonGenericOpaqueTypeParam<'a, 'tcx> {
#[label]
pub param_span: Span,
}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum CaptureReasonLabel<'a> {
+ #[label(borrowck_moved_due_to_call)]
+ Call {
+ #[primary_span]
+ fn_call_span: Span,
+ place_name: &'a str,
+ is_partial: bool,
+ is_loop_message: bool,
+ },
+ #[label(borrowck_moved_due_to_usage_in_operator)]
+ OperatorUse {
+ #[primary_span]
+ fn_call_span: Span,
+ place_name: &'a str,
+ is_partial: bool,
+ is_loop_message: bool,
+ },
+ #[label(borrowck_moved_due_to_implicit_into_iter_call)]
+ ImplicitCall {
+ #[primary_span]
+ fn_call_span: Span,
+ place_name: &'a str,
+ is_partial: bool,
+ is_loop_message: bool,
+ },
+ #[label(borrowck_moved_due_to_method_call)]
+ MethodCall {
+ #[primary_span]
+ fn_call_span: Span,
+ place_name: &'a str,
+ is_partial: bool,
+ is_loop_message: bool,
+ },
+ #[label(borrowck_value_moved_here)]
+ MovedHere {
+ #[primary_span]
+ move_span: Span,
+ is_partial: bool,
+ is_move_msg: bool,
+ is_loop_message: bool,
+ },
+ #[label(borrowck_consider_borrow_type_contents)]
+ BorrowContent {
+ #[primary_span]
+ var_span: Span,
+ },
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum CaptureReasonNote {
+ #[note(borrowck_moved_a_fn_once_in_call)]
+ FnOnceMoveInCall {
+ #[primary_span]
+ var_span: Span,
+ },
+ #[note(borrowck_calling_operator_moves_lhs)]
+ LhsMoveByOperator {
+ #[primary_span]
+ span: Span,
+ },
+ #[note(borrowck_func_take_self_moved_place)]
+ FuncTakeSelf {
+ func: String,
+ place_name: String,
+ #[primary_span]
+ span: Span,
+ },
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum CaptureReasonSuggest<'tcx> {
+ #[suggestion(
+ borrowck_suggest_iterate_over_slice,
+ applicability = "maybe-incorrect",
+ code = "&",
+ style = "verbose"
+ )]
+ IterateSlice {
+ ty: Ty<'tcx>,
+ #[primary_span]
+ span: Span,
+ },
+ #[suggestion(
+ borrowck_suggest_create_freash_reborrow,
+ applicability = "maybe-incorrect",
+ code = "as_mut().",
+ style = "verbose"
+ )]
+ FreshReborrow {
+ #[primary_span]
+ span: Span,
+ },
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum CaptureArgLabel {
+ #[label(borrowck_value_capture_here)]
+ Capture {
+ is_within: bool,
+ #[primary_span]
+ args_span: Span,
+ },
+ #[label(borrowck_move_out_place_here)]
+ MoveOutPlace {
+ place: String,
+ #[primary_span]
+ args_span: Span,
+ },
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum OnClosureNote<'a> {
+ #[note(borrowck_closure_invoked_twice)]
+ InvokedTwice {
+ place_name: &'a str,
+ #[primary_span]
+ span: Span,
+ },
+ #[note(borrowck_closure_moved_twice)]
+ MovedTwice {
+ place_name: &'a str,
+ #[primary_span]
+ span: Span,
+ },
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum TypeNoCopy<'a, 'tcx> {
+ #[label(borrowck_ty_no_impl_copy)]
+ Label {
+ is_partial_move: bool,
+ ty: Ty<'tcx>,
+ place: &'a str,
+ #[primary_span]
+ span: Span,
+ },
+ #[note(borrowck_ty_no_impl_copy)]
+ Note { is_partial_move: bool, ty: Ty<'tcx>, place: &'a str },
+}
diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs
index 17e702eb8c5..9250b8d3eaf 100644
--- a/compiler/rustc_borrowck/src/type_check/input_output.rs
+++ b/compiler/rustc_borrowck/src/type_check/input_output.rs
@@ -7,7 +7,6 @@
//! `RETURN_PLACE` the MIR arguments) are always fully normalized (and
//! contain revealed `impl Trait` values).
-use rustc_index::vec::Idx;
use rustc_infer::infer::LateBoundRegionConversionTime;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, Ty};
@@ -83,7 +82,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
// In MIR, argument N is stored in local N+1.
- let local = Local::new(argument_index + 1);
+ let local = Local::from_usize(argument_index + 1);
let mir_input_ty = body.local_decls[local].ty;
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 375eca1b29d..7cb0cec82c7 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -394,7 +394,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
self.cx.ascribe_user_type(
constant.literal.ty(),
UserType::TypeOf(
- uv.def.did,
+ uv.def,
UserSubsts { substs: uv.substs, user_self_ty: None },
),
locations.span(&self.cx.body),
@@ -1766,7 +1766,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
if let Some(uv) = maybe_uneval {
if uv.promoted.is_none() {
let tcx = self.tcx();
- let def_id = uv.def.def_id_for_type_of();
+ let def_id = uv.def;
if tcx.def_kind(def_id) == DefKind::InlineConst {
let def_id = def_id.expect_local();
let predicates =
@@ -2306,7 +2306,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
Rvalue::AddressOf(..)
| Rvalue::ThreadLocalRef(..)
| Rvalue::Len(..)
- | Rvalue::Discriminant(..) => {}
+ | Rvalue::Discriminant(..)
+ | Rvalue::NullaryOp(NullOp::OffsetOf(..), _) => {}
}
}
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index 70fddb1057c..ef37c01cef8 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -19,7 +19,7 @@ use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::lang_items::LangItem;
use rustc_hir::BodyOwnerKind;
-use rustc_index::vec::{Idx, IndexVec};
+use rustc_index::vec::IndexVec;
use rustc_infer::infer::NllRegionVariableOrigin;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::{self, InlineConstSubsts, InlineConstSubstsParts, RegionVid, Ty, TyCtxt};
@@ -226,7 +226,7 @@ impl<'tcx> UniversalRegions<'tcx> {
/// known between those regions.
pub fn new(
infcx: &BorrowckInferCtxt<'_, 'tcx>,
- mir_def: ty::WithOptConstParam<LocalDefId>,
+ mir_def: LocalDefId,
param_env: ty::ParamEnv<'tcx>,
) -> Self {
UniversalRegionsBuilder { infcx, mir_def, param_env }.build()
@@ -289,7 +289,7 @@ impl<'tcx> UniversalRegions<'tcx> {
/// Returns an iterator over all the RegionVids corresponding to
/// universally quantified free regions.
pub fn universal_regions(&self) -> impl Iterator<Item = RegionVid> {
- (FIRST_GLOBAL_INDEX..self.num_universals).map(RegionVid::new)
+ (FIRST_GLOBAL_INDEX..self.num_universals).map(RegionVid::from_usize)
}
/// Returns `true` if `r` is classified as an local region.
@@ -388,7 +388,7 @@ impl<'tcx> UniversalRegions<'tcx> {
struct UniversalRegionsBuilder<'cx, 'tcx> {
infcx: &'cx BorrowckInferCtxt<'cx, 'tcx>,
- mir_def: ty::WithOptConstParam<LocalDefId>,
+ mir_def: LocalDefId,
param_env: ty::ParamEnv<'tcx>,
}
@@ -417,12 +417,12 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
let mut indices = self.compute_indices(fr_static, defining_ty);
debug!("build: indices={:?}", indices);
- let typeck_root_def_id = self.infcx.tcx.typeck_root_def_id(self.mir_def.did.to_def_id());
+ let typeck_root_def_id = self.infcx.tcx.typeck_root_def_id(self.mir_def.to_def_id());
// If this is a 'root' body (not a closure/generator/inline const), then
// there are no extern regions, so the local regions start at the same
// position as the (empty) sub-list of extern regions
- let first_local_index = if self.mir_def.did.to_def_id() == typeck_root_def_id {
+ let first_local_index = if self.mir_def.to_def_id() == typeck_root_def_id {
first_extern_index
} else {
// If this is a closure, generator, or inline-const, then the late-bound regions from the enclosing
@@ -433,7 +433,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
// }
for_each_late_bound_region_in_recursive_scope(
self.infcx.tcx,
- self.infcx.tcx.local_parent(self.mir_def.did),
+ self.infcx.tcx.local_parent(self.mir_def),
|r| {
debug!(?r);
if !indices.indices.contains_key(&r) {
@@ -462,13 +462,13 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
let inputs_and_output = self.infcx.replace_bound_regions_with_nll_infer_vars(
FR,
- self.mir_def.did,
+ self.mir_def,
bound_inputs_and_output,
&mut indices,
);
// Converse of above, if this is a function/closure then the late-bound regions declared on its
// signature are local.
- for_each_late_bound_region_in_item(self.infcx.tcx, self.mir_def.did, |r| {
+ for_each_late_bound_region_in_item(self.infcx.tcx, self.mir_def, |r| {
debug!(?r);
if !indices.indices.contains_key(&r) {
let region_vid = {
@@ -492,7 +492,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
if self.infcx.tcx.fn_sig(def_id).skip_binder().c_variadic() {
let va_list_did = self.infcx.tcx.require_lang_item(
LangItem::VaList,
- Some(self.infcx.tcx.def_span(self.mir_def.did)),
+ Some(self.infcx.tcx.def_span(self.mir_def)),
);
let reg_vid = self
@@ -544,11 +544,11 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
/// see `DefiningTy` for details.
fn defining_ty(&self) -> DefiningTy<'tcx> {
let tcx = self.infcx.tcx;
- let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.did.to_def_id());
+ let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.to_def_id());
- match tcx.hir().body_owner_kind(self.mir_def.did) {
+ match tcx.hir().body_owner_kind(self.mir_def) {
BodyOwnerKind::Closure | BodyOwnerKind::Fn => {
- let defining_ty = tcx.type_of(self.mir_def.def_id_for_type_of()).subst_identity();
+ let defining_ty = tcx.type_of(self.mir_def).subst_identity();
debug!("defining_ty (pre-replacement): {:?}", defining_ty);
@@ -562,9 +562,9 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
}
ty::FnDef(def_id, substs) => DefiningTy::FnDef(def_id, substs),
_ => span_bug!(
- tcx.def_span(self.mir_def.did),
+ tcx.def_span(self.mir_def),
"expected defining type for `{:?}`: `{:?}`",
- self.mir_def.did,
+ self.mir_def,
defining_ty
),
}
@@ -572,10 +572,10 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
BodyOwnerKind::Const | BodyOwnerKind::Static(..) => {
let identity_substs = InternalSubsts::identity_for_item(tcx, typeck_root_def_id);
- if self.mir_def.did.to_def_id() == typeck_root_def_id {
+ if self.mir_def.to_def_id() == typeck_root_def_id {
let substs =
self.infcx.replace_free_regions_with_nll_infer_vars(FR, identity_substs);
- DefiningTy::Const(self.mir_def.did.to_def_id(), substs)
+ DefiningTy::Const(self.mir_def.to_def_id(), substs)
} else {
// FIXME this line creates a dependency between borrowck and typeck.
//
@@ -587,15 +587,15 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
// below), so that `type_of(inline_const_def_id).substs(substs)` uses the
// proper type with NLL infer vars.
let ty = tcx
- .typeck(self.mir_def.did)
- .node_type(tcx.local_def_id_to_hir_id(self.mir_def.did));
+ .typeck(self.mir_def)
+ .node_type(tcx.local_def_id_to_hir_id(self.mir_def));
let substs = InlineConstSubsts::new(
tcx,
InlineConstSubstsParts { parent_substs: identity_substs, ty },
)
.substs;
let substs = self.infcx.replace_free_regions_with_nll_infer_vars(FR, substs);
- DefiningTy::InlineConst(self.mir_def.did.to_def_id(), substs)
+ DefiningTy::InlineConst(self.mir_def.to_def_id(), substs)
}
}
}
@@ -611,7 +611,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
defining_ty: DefiningTy<'tcx>,
) -> UniversalRegionIndices<'tcx> {
let tcx = self.infcx.tcx;
- let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.did.to_def_id());
+ let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.to_def_id());
let identity_substs = InternalSubsts::identity_for_item(tcx, typeck_root_def_id);
let fr_substs = match defining_ty {
DefiningTy::Closure(_, substs)
@@ -647,7 +647,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
let tcx = self.infcx.tcx;
match defining_ty {
DefiningTy::Closure(def_id, substs) => {
- assert_eq!(self.mir_def.did.to_def_id(), def_id);
+ assert_eq!(self.mir_def.to_def_id(), def_id);
let closure_sig = substs.as_closure().sig();
let inputs_and_output = closure_sig.inputs_and_output();
let bound_vars = tcx.mk_bound_variable_kinds_from_iter(
@@ -682,7 +682,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
}
DefiningTy::Generator(def_id, substs, movability) => {
- assert_eq!(self.mir_def.did.to_def_id(), def_id);
+ assert_eq!(self.mir_def.to_def_id(), def_id);
let resume_ty = substs.as_generator().resume_ty();
let output = substs.as_generator().return_ty();
let generator_ty = tcx.mk_generator(def_id, substs, movability);
@@ -700,14 +700,14 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
DefiningTy::Const(def_id, _) => {
// For a constant body, there are no inputs, and one
// "output" (the type of the constant).
- assert_eq!(self.mir_def.did.to_def_id(), def_id);
- let ty = tcx.type_of(self.mir_def.def_id_for_type_of()).subst_identity();
+ assert_eq!(self.mir_def.to_def_id(), def_id);
+ let ty = tcx.type_of(self.mir_def).subst_identity();
let ty = indices.fold_to_region_vids(tcx, ty);
ty::Binder::dummy(tcx.mk_type_list(&[ty]))
}
DefiningTy::InlineConst(def_id, substs) => {
- assert_eq!(self.mir_def.did.to_def_id(), def_id);
+ assert_eq!(self.mir_def.to_def_id(), def_id);
let ty = substs.as_inline_const().ty();
ty::Binder::dummy(tcx.mk_type_list(&[ty]))
}
diff --git a/compiler/rustc_const_eval/src/util/collect_writes.rs b/compiler/rustc_borrowck/src/util/collect_writes.rs
index 8d92bb35938..8d92bb35938 100644
--- a/compiler/rustc_const_eval/src/util/collect_writes.rs
+++ b/compiler/rustc_borrowck/src/util/collect_writes.rs
diff --git a/compiler/rustc_borrowck/src/util/mod.rs b/compiler/rustc_borrowck/src/util/mod.rs
new file mode 100644
index 00000000000..7377d4de727
--- /dev/null
+++ b/compiler/rustc_borrowck/src/util/mod.rs
@@ -0,0 +1,3 @@
+mod collect_writes;
+
+pub use collect_writes::FindAssignments;
diff --git a/compiler/rustc_builtin_macros/Cargo.toml b/compiler/rustc_builtin_macros/Cargo.toml
index 336e14ef966..5f6441660e3 100644
--- a/compiler/rustc_builtin_macros/Cargo.toml
+++ b/compiler/rustc_builtin_macros/Cargo.toml
@@ -17,6 +17,7 @@ rustc_feature = { path = "../rustc_feature" }
rustc_lexer = { path = "../rustc_lexer" }
rustc_lint_defs = { path = "../rustc_lint_defs" }
rustc_macros = { path = "../rustc_macros" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_parse_format = { path = "../rustc_parse_format" }
rustc_parse = { path = "../rustc_parse" }
rustc_session = { path = "../rustc_session" }
diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl
index 43187c32709..ee2aca6fc93 100644
--- a/compiler/rustc_builtin_macros/messages.ftl
+++ b/compiler/rustc_builtin_macros/messages.ftl
@@ -147,3 +147,6 @@ builtin_macros_format_pos_mismatch = {$n} positional {$n ->
[one] argument
*[more] arguments
} in format string, but {$desc}
+builtin_macros_offset_of_expected_field = expected field
+
+builtin_macros_offset_of_expected_two_args = expected 2 arguments
diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs
index c9e3cd486f8..090e00616fb 100644
--- a/compiler/rustc_builtin_macros/src/assert/context.rs
+++ b/compiler/rustc_builtin_macros/src/assert/context.rs
@@ -301,6 +301,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
| ExprKind::If(_, _, _)
| ExprKind::IncludedBytes(..)
| ExprKind::InlineAsm(_)
+ | ExprKind::OffsetOf(_, _)
| ExprKind::Let(_, _, _)
| ExprKind::Lit(_)
| ExprKind::Loop(_, _, _)
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index f0fc61d7c4f..f17df5b0a83 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -141,13 +141,7 @@ fn parse_args<'a>(ecx: &mut ExtCtxt<'a>, sp: Span, tts: TokenStream) -> PResult<
args: args
.named_args()
.iter()
- .filter_map(|a| {
- if let Some(ident) = a.kind.ident() {
- Some((a, ident))
- } else {
- None
- }
- })
+ .filter_map(|a| a.kind.ident().map(|ident| (a, ident)))
.map(|(arg, n)| n.span.to(arg.expr.span))
.collect(),
});
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index e326c37635a..b6170161d6b 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -24,7 +24,7 @@ use crate::deriving::*;
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
use rustc_expand::base::{MacroExpanderFn, ResolverExpand, SyntaxExtensionKind};
use rustc_expand::proc_macro::BangProcMacro;
-use rustc_macros::fluent_messages;
+use rustc_fluent_macro::fluent_messages;
use rustc_span::symbol::sym;
mod assert;
@@ -44,6 +44,7 @@ mod format;
mod format_foreign;
mod global_allocator;
mod log_syntax;
+mod offset_of;
mod source_util;
mod test;
mod trace_macros;
@@ -91,6 +92,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
line: source_util::expand_line,
log_syntax: log_syntax::expand_log_syntax,
module_path: source_util::expand_mod,
+ offset_of: offset_of::expand_offset_of,
option_env: env::expand_option_env,
core_panic: edition_panic::expand_panic,
std_panic: edition_panic::expand_panic,
diff --git a/compiler/rustc_builtin_macros/src/offset_of.rs b/compiler/rustc_builtin_macros/src/offset_of.rs
new file mode 100644
index 00000000000..0ef3e000e41
--- /dev/null
+++ b/compiler/rustc_builtin_macros/src/offset_of.rs
@@ -0,0 +1,99 @@
+use rustc_ast as ast;
+use rustc_ast::ptr::P;
+use rustc_ast::token;
+use rustc_ast::tokenstream::TokenStream;
+use rustc_errors::PResult;
+use rustc_expand::base::{self, *};
+use rustc_macros::Diagnostic;
+use rustc_parse::parser::Parser;
+use rustc_span::{symbol::Ident, Span};
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_offset_of_expected_field)]
+struct ExpectedField {
+ #[primary_span]
+ span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_offset_of_expected_two_args)]
+struct ExpectedTwoArgs {
+ #[primary_span]
+ span: Span,
+}
+
+fn parse_field<'a>(cx: &ExtCtxt<'a>, p: &mut Parser<'a>) -> PResult<'a, Ident> {
+ let token = p.token.uninterpolate();
+ let field = match token.kind {
+ token::Ident(name, _) => Ident::new(name, token.span),
+ token::Literal(token::Lit { kind: token::Integer, symbol, suffix: None }) => {
+ Ident::new(symbol, token.span)
+ }
+ _ => return Err(cx.create_err(ExpectedField { span: p.token.span })),
+ };
+
+ p.bump();
+
+ Ok(field)
+}
+
+fn parse_args<'a>(
+ cx: &mut ExtCtxt<'a>,
+ sp: Span,
+ tts: TokenStream,
+) -> PResult<'a, (P<ast::Ty>, P<[Ident]>)> {
+ let mut p = cx.new_parser_from_tts(tts);
+
+ let container = p.parse_ty()?;
+
+ p.expect(&token::Comma)?;
+
+ if p.eat(&token::Eof) {
+ return Err(cx.create_err(ExpectedTwoArgs { span: sp }));
+ }
+
+ let mut fields = Vec::new();
+
+ loop {
+ let field = parse_field(cx, &mut p)?;
+ fields.push(field);
+
+ if p.eat(&token::Dot) {
+ continue;
+ }
+
+ p.eat(&token::Comma);
+
+ if !p.eat(&token::Eof) {
+ return Err(cx.create_err(ExpectedTwoArgs { span: sp }));
+ }
+
+ break;
+ }
+
+ Ok((container, fields.into()))
+}
+
+pub fn expand_offset_of<'cx>(
+ cx: &'cx mut ExtCtxt<'_>,
+ sp: Span,
+ tts: TokenStream,
+) -> Box<dyn base::MacResult + 'cx> {
+ match parse_args(cx, sp, tts) {
+ Ok((container, fields)) => {
+ let expr = P(ast::Expr {
+ id: ast::DUMMY_NODE_ID,
+ kind: ast::ExprKind::OffsetOf(container, fields),
+ span: sp,
+ attrs: ast::AttrVec::new(),
+ tokens: None,
+ });
+
+ MacEager::expr(expr)
+ }
+ Err(mut err) => {
+ err.emit();
+ DummyResult::any(sp)
+ }
+ }
+}
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index f5301f9f7f1..f481290583e 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -781,12 +781,15 @@ fn codegen_stmt<'tcx>(
let operand = operand.load_scalar(fx);
lval.write_cvalue(fx, CValue::by_val(operand, box_layout));
}
- Rvalue::NullaryOp(null_op, ty) => {
+ Rvalue::NullaryOp(ref null_op, ty) => {
assert!(lval.layout().ty.is_sized(fx.tcx, ParamEnv::reveal_all()));
let layout = fx.layout_of(fx.monomorphize(ty));
let val = match null_op {
NullOp::SizeOf => layout.size.bytes(),
NullOp::AlignOf => layout.align.abi.bytes(),
+ NullOp::OffsetOf(fields) => {
+ layout.offset_of_subfield(fx, fields.iter().map(|f| f.index())).bytes()
+ }
};
let val = CValue::const_val(fx, fx.layout_of(fx.tcx.types.usize), val.into());
lval.write_cvalue(fx, val);
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index e87f4e25891..aacf37bb5b7 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -91,7 +91,7 @@ pub(crate) fn eval_mir_constant<'tcx>(
),
},
ConstantKind::Unevaluated(mir::UnevaluatedConst { def, .. }, _)
- if fx.tcx.is_static(def.did) =>
+ if fx.tcx.is_static(def) =>
{
span_bug!(constant.span, "MIR constant refers to static");
}
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index be710fefe49..1a20dbcebd4 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -27,6 +27,7 @@ extern crate rustc_attr;
extern crate rustc_codegen_ssa;
extern crate rustc_data_structures;
extern crate rustc_errors;
+extern crate rustc_fluent_macro;
extern crate rustc_hir;
extern crate rustc_macros;
extern crate rustc_metadata;
@@ -76,7 +77,7 @@ use rustc_codegen_ssa::target_features::supported_target_features;
use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, ModuleBufferMethods, ThinBufferMethods, WriteBackendMethods};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{DiagnosticMessage, ErrorGuaranteed, Handler, SubdiagnosticMessage};
-use rustc_macros::fluent_messages;
+use rustc_fluent_macro::fluent_messages;
use rustc_metadata::EncodedMetadata;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_middle::ty::TyCtxt;
diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml
index a7ba2f8b695..bdea565a5a6 100644
--- a/compiler/rustc_codegen_llvm/Cargo.toml
+++ b/compiler/rustc_codegen_llvm/Cargo.toml
@@ -22,6 +22,7 @@ rustc_attr = { path = "../rustc_attr" }
rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_fs_util = { path = "../rustc_fs_util" }
rustc_hir = { path = "../rustc_hir" }
rustc_index = { path = "../rustc_index" }
diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs
index 4f8b5abd901..9127fba388b 100644
--- a/compiler/rustc_codegen_llvm/src/common.rs
+++ b/compiler/rustc_codegen_llvm/src/common.rs
@@ -10,7 +10,7 @@ use crate::value::Value;
use rustc_ast::Mutability;
use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_codegen_ssa::traits::*;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher};
use rustc_hir::def_id::DefId;
use rustc_middle::bug;
use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar};
@@ -261,7 +261,7 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
let hash = self.tcx.with_stable_hashing_context(|mut hcx| {
let mut hasher = StableHasher::new();
alloc.hash_stable(&mut hcx, &mut hasher);
- hasher.finish::<u128>()
+ hasher.finish::<Hash128>()
});
llvm::set_value_name(value, format!("alloc_{hash:032x}").as_bytes());
}
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
index ff2b005d757..aaf5dbd9930 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
@@ -22,9 +22,9 @@ pub fn insert_reference_to_gdb_debug_scripts_section_global(bx: &mut Builder<'_,
bx.const_bitcast(get_or_insert_gdb_debug_scripts_section_global(bx), bx.type_i8p());
// Load just the first byte as that's all that's necessary to force
// LLVM to keep around the reference to the global.
- let volative_load_instruction = bx.volatile_load(bx.type_i8(), gdb_debug_scripts_section);
+ let volatile_load_instruction = bx.volatile_load(bx.type_i8(), gdb_debug_scripts_section);
unsafe {
- llvm::LLVMSetAlignment(volative_load_instruction, 1);
+ llvm::LLVMSetAlignment(volatile_load_instruction, 1);
}
}
}
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 21a0a60b012..25fe3cb265d 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -29,7 +29,6 @@ use rustc_hir::def::CtorKind;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_middle::bug;
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
-use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::{
self, AdtKind, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt, Visibility,
};
@@ -1182,12 +1181,12 @@ fn build_generic_type_param_di_nodes<'ll, 'tcx>(
let names = get_parameter_names(cx, generics);
let template_params: SmallVec<_> = iter::zip(substs, names)
.filter_map(|(kind, name)| {
- if let GenericArgKind::Type(ty) = kind.unpack() {
+ kind.as_type().map(|ty| {
let actual_type =
cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
let actual_type_di_node = type_di_node(cx, actual_type);
let name = name.as_str();
- Some(unsafe {
+ unsafe {
llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
DIB(cx),
None,
@@ -1195,10 +1194,8 @@ fn build_generic_type_param_di_nodes<'ll, 'tcx>(
name.len(),
actual_type_di_node,
)
- })
- } else {
- None
- }
+ }
+ })
})
.collect();
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
index 69443b9b828..38ad42370d3 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
@@ -62,7 +62,7 @@ const SINGLE_VARIANT_VIRTUAL_DISR: u64 = 0;
/// In CPP-like mode, we generate a union with a field for each variant and an
/// explicit tag field. The field of each variant has a struct type
-/// that encodes the discrimiant of the variant and it's data layout.
+/// that encodes the discriminant of the variant and it's data layout.
/// The union also has a nested enumeration type that is only used for encoding
/// variant names in an efficient way. Its enumerator values do _not_ correspond
/// to the enum's discriminant values.
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index d56c414cf65..dfc226db57b 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -21,12 +21,13 @@ use rustc_codegen_ssa::debuginfo::type_names;
use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind};
use rustc_codegen_ssa::traits::*;
use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::stable_hasher::Hash128;
use rustc_data_structures::sync::Lrc;
use rustc_hir::def_id::{DefId, DefIdMap};
use rustc_index::vec::IndexVec;
use rustc_middle::mir;
use rustc_middle::ty::layout::LayoutOf;
-use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
+use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TypeVisitableExt};
use rustc_session::config::{self, DebugInfo};
use rustc_session::Session;
@@ -61,7 +62,7 @@ pub struct CodegenUnitDebugContext<'ll, 'tcx> {
llcontext: &'ll llvm::Context,
llmod: &'ll llvm::Module,
builder: &'ll mut DIBuilder<'ll>,
- created_files: RefCell<FxHashMap<Option<(u128, SourceFileHash)>, &'ll DIFile>>,
+ created_files: RefCell<FxHashMap<Option<(Hash128, SourceFileHash)>, &'ll DIFile>>,
type_map: metadata::TypeMap<'ll, 'tcx>,
namespace_map: RefCell<DefIdMap<&'ll DIScope>>,
@@ -460,12 +461,12 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
let names = get_parameter_names(cx, generics);
iter::zip(substs, names)
.filter_map(|(kind, name)| {
- if let GenericArgKind::Type(ty) = kind.unpack() {
+ kind.as_type().map(|ty| {
let actual_type =
cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
let actual_type_metadata = type_di_node(cx, actual_type);
let name = name.as_str();
- Some(unsafe {
+ unsafe {
Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
DIB(cx),
None,
@@ -473,10 +474,8 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
name.len(),
actual_type_metadata,
))
- })
- } else {
- None
- }
+ }
+ })
})
.collect()
} else {
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index 33d66bcd237..00b2dc1287a 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -34,7 +34,7 @@ use rustc_codegen_ssa::ModuleCodegen;
use rustc_codegen_ssa::{CodegenResults, CompiledModule};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{DiagnosticMessage, ErrorGuaranteed, FatalError, Handler, SubdiagnosticMessage};
-use rustc_macros::fluent_messages;
+use rustc_fluent_macro::fluent_messages;
use rustc_metadata::EncodedMetadata;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_middle::ty::query::Providers;
@@ -69,7 +69,7 @@ mod declare;
mod errors;
mod intrinsic;
-// The following is a work around that replaces `pub mod llvm;` and that fixes issue 53912.
+// The following is a workaround that replaces `pub mod llvm;` and that fixes issue 53912.
#[path = "llvm/mod.rs"]
mod llvm_;
pub mod llvm {
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 09f3fe02165..c95148013eb 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -552,6 +552,7 @@ pub enum ArchiveKind {
K_BSD,
K_DARWIN,
K_COFF,
+ K_AIXBIG,
}
// LLVMRustThinLTOData
diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs
index f820e752371..4f5cc575da6 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs
@@ -137,6 +137,7 @@ impl FromStr for ArchiveKind {
"bsd" => Ok(ArchiveKind::K_BSD),
"darwin" => Ok(ArchiveKind::K_DARWIN),
"coff" => Ok(ArchiveKind::K_COFF),
+ "aix_big" => Ok(ArchiveKind::K_AIXBIG),
_ => Err(()),
}
}
diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml
index c55991e00d3..bd1ac6b7bad 100644
--- a/compiler/rustc_codegen_ssa/Cargo.toml
+++ b/compiler/rustc_codegen_ssa/Cargo.toml
@@ -7,7 +7,7 @@ edition = "2021"
test = false
[dependencies]
-ar_archive_writer = "0.1.1"
+ar_archive_writer = "0.1.3"
bitflags = "1.2.1"
cc = "1.0.69"
itertools = "0.10.1"
@@ -29,6 +29,7 @@ rustc_span = { path = "../rustc_span" }
rustc_middle = { path = "../rustc_middle" }
rustc_type_ir = { path = "../rustc_type_ir" }
rustc_attr = { path = "../rustc_attr" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_symbol_mangling = { path = "../rustc_symbol_mangling" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl
index 243be0e1f70..85a96e3e89c 100644
--- a/compiler/rustc_codegen_ssa/messages.ftl
+++ b/compiler/rustc_codegen_ssa/messages.ftl
@@ -148,7 +148,7 @@ codegen_ssa_processing_dymutil_failed = processing debug info with `dsymutil` fa
codegen_ssa_unable_to_run_dsymutil = unable to run `dsymutil`: {$error}
-codegen_ssa_stripping_debu_info_failed = stripping debug info with `{$util}` failed: {$status}
+codegen_ssa_stripping_debug_info_failed = stripping debug info with `{$util}` failed: {$status}
.note = {$output}
codegen_ssa_unable_to_run = unable to run `{$util}`: {$error}
diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs
index 66ec8f5f57d..1c464b3eca4 100644
--- a/compiler/rustc_codegen_ssa/src/back/archive.rs
+++ b/compiler/rustc_codegen_ssa/src/back/archive.rs
@@ -233,6 +233,7 @@ impl<'a> ArArchiveBuilder<'a> {
"bsd" => ArchiveKind::Bsd,
"darwin" => ArchiveKind::Darwin,
"coff" => ArchiveKind::Coff,
+ "aix_big" => ArchiveKind::AixBig,
kind => {
self.sess.emit_fatal(UnknownArchiveKind { kind });
}
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index dbf30e42ae4..bda0cf764e5 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -333,7 +333,7 @@ fn exported_symbols_provider_local(
match *mono_item {
MonoItem::Fn(Instance { def: InstanceDef::Item(def), substs }) => {
if substs.non_erasable_generics().next().is_some() {
- let symbol = ExportedSymbol::Generic(def.did, substs);
+ let symbol = ExportedSymbol::Generic(def, substs);
symbols.push((
symbol,
SymbolExportInfo {
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index 2dda4cd1694..c80347448cb 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -872,7 +872,7 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
let load_from_incr_comp_dir = |output_path: PathBuf, saved_path: &str| {
let source_file = in_incr_comp_dir(&incr_comp_session_dir, saved_path);
debug!(
- "copying pre-existing module `{}` from {:?} to {}",
+ "copying preexisting module `{}` from {:?} to {}",
module.name,
source_file,
output_path.display()
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 8542bab689d..9bfe426c007 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -156,7 +156,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
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
+ // but using `llvm.compiler.used` caused a nontrivial amount
// of unintentional ecosystem breakage -- particularly on
// Mach-O targets.
//
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index f2469fde3b6..03f33d8d8aa 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -12,7 +12,7 @@
// * `"` is treated as the start of a string.
use rustc_data_structures::fx::FxHashSet;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
use rustc_hir::def_id::DefId;
use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData};
use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Mutability};
@@ -675,8 +675,7 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S
hcx.while_hashing_spans(false, |hcx| {
ct.to_valtree().hash_stable(hcx, &mut hasher)
});
- let hash: u64 = hasher.finish();
- hash
+ hasher.finish::<Hash64>()
});
if cpp_like_debuginfo(tcx) {
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs
index 66e7e314f79..44931766678 100644
--- a/compiler/rustc_codegen_ssa/src/errors.rs
+++ b/compiler/rustc_codegen_ssa/src/errors.rs
@@ -424,7 +424,7 @@ pub struct UnableToRunDsymutil {
}
#[derive(Diagnostic)]
-#[diag(codegen_ssa_stripping_debu_info_failed)]
+#[diag(codegen_ssa_stripping_debug_info_failed)]
#[note]
pub struct StrippingDebugInfoFailed<'a> {
pub util: &'a str,
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index 0ab12314b3c..26d55618b49 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -25,8 +25,8 @@ use rustc_ast as ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync::Lrc;
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
+use rustc_fluent_macro::fluent_messages;
use rustc_hir::def_id::CrateNum;
-use rustc_macros::fluent_messages;
use rustc_middle::dep_graph::WorkProduct;
use rustc_middle::middle::dependency_format::Dependencies;
use rustc_middle::middle::exported_symbols::SymbolExportKind;
diff --git a/compiler/rustc_codegen_ssa/src/meth.rs b/compiler/rustc_codegen_ssa/src/meth.rs
index 2421acab471..81b49afb883 100644
--- a/compiler/rustc_codegen_ssa/src/meth.rs
+++ b/compiler/rustc_codegen_ssa/src/meth.rs
@@ -67,10 +67,10 @@ impl<'a, 'tcx> VirtualIndex {
/// ref of the type.
fn expect_dyn_trait_in_self(ty: Ty<'_>) -> ty::PolyExistentialTraitRef<'_> {
for arg in ty.peel_refs().walk() {
- if let GenericArgKind::Type(ty) = arg.unpack() {
- if let ty::Dynamic(data, _, _) = ty.kind() {
- return data.principal().expect("expected principal trait object");
- }
+ if let GenericArgKind::Type(ty) = arg.unpack()
+ && let ty::Dynamic(data, _, _) = ty.kind()
+ {
+ return data.principal().expect("expected principal trait object");
}
}
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index dd86977817f..a0a8246be15 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -12,7 +12,6 @@ use crate::MemFlags;
use rustc_ast as ast;
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_hir::lang_items::LangItem;
-use rustc_index::vec::Idx;
use rustc_middle::mir::{self, AssertKind, SwitchTargets};
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
@@ -369,7 +368,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
if self.fn_abi.c_variadic {
// The `VaList` "spoofed" argument is just after all the real arguments.
let va_list_arg_idx = self.fn_abi.args.len();
- match self.locals[mir::Local::new(1 + va_list_arg_idx)] {
+ match self.locals[mir::Local::from_usize(1 + va_list_arg_idx)] {
LocalRef::Place(va_list) => {
bx.va_end(va_list.llval);
}
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index d88226f5db0..94de19a9c29 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -12,6 +12,7 @@ use rustc_middle::mir::Operand;
use rustc_middle::ty::cast::{CastTy, IntTy};
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
use rustc_middle::ty::{self, adjustment::PointerCast, Instance, Ty, TyCtxt};
+use rustc_session::config::OptLevel;
use rustc_span::source_map::{Span, DUMMY_SP};
use rustc_target::abi::{self, FIRST_VARIANT};
@@ -231,10 +232,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
(ScalarOrZst::Scalar(in_scalar), ScalarOrZst::Scalar(out_scalar))
if in_scalar.size(self.cx) == out_scalar.size(self.cx) =>
{
+ let operand_bty = bx.backend_type(operand.layout);
let cast_bty = bx.backend_type(cast);
- Some(OperandValue::Immediate(
- self.transmute_immediate(bx, imm, in_scalar, out_scalar, cast_bty),
- ))
+ Some(OperandValue::Immediate(self.transmute_immediate(
+ bx,
+ imm,
+ in_scalar,
+ operand_bty,
+ out_scalar,
+ cast_bty,
+ )))
}
_ => None,
}
@@ -250,11 +257,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
&& in_a.size(self.cx) == out_a.size(self.cx)
&& in_b.size(self.cx) == out_b.size(self.cx)
{
+ let in_a_ibty = bx.scalar_pair_element_backend_type(operand.layout, 0, false);
+ let in_b_ibty = bx.scalar_pair_element_backend_type(operand.layout, 1, false);
let out_a_ibty = bx.scalar_pair_element_backend_type(cast, 0, false);
let out_b_ibty = bx.scalar_pair_element_backend_type(cast, 1, false);
Some(OperandValue::Pair(
- self.transmute_immediate(bx, imm_a, in_a, out_a, out_a_ibty),
- self.transmute_immediate(bx, imm_b, in_b, out_b, out_b_ibty),
+ self.transmute_immediate(bx, imm_a, in_a, in_a_ibty, out_a, out_a_ibty),
+ self.transmute_immediate(bx, imm_b, in_b, in_b_ibty, out_b, out_b_ibty),
))
} else {
None
@@ -273,6 +282,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
bx: &mut Bx,
mut imm: Bx::Value,
from_scalar: abi::Scalar,
+ from_backend_ty: Bx::Type,
to_scalar: abi::Scalar,
to_backend_ty: Bx::Type,
) -> Bx::Value {
@@ -280,6 +290,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
use abi::Primitive::*;
imm = bx.from_immediate(imm);
+
+ // When scalars are passed by value, there's no metadata recording their
+ // valid ranges. For example, `char`s are passed as just `i32`, with no
+ // way for LLVM to know that they're 0x10FFFF at most. Thus we assume
+ // the range of the input value too, not just the output range.
+ self.assume_scalar_range(bx, imm, from_scalar, from_backend_ty);
+
imm = match (from_scalar.primitive(), to_scalar.primitive()) {
(Int(..) | F32 | F64, Int(..) | F32 | F64) => bx.bitcast(imm, to_backend_ty),
(Pointer(..), Pointer(..)) => bx.pointercast(imm, to_backend_ty),
@@ -294,10 +311,55 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
bx.bitcast(int_imm, to_backend_ty)
}
};
+ self.assume_scalar_range(bx, imm, to_scalar, to_backend_ty);
imm = bx.to_immediate_scalar(imm, to_scalar);
imm
}
+ fn assume_scalar_range(
+ &self,
+ bx: &mut Bx,
+ imm: Bx::Value,
+ scalar: abi::Scalar,
+ backend_ty: Bx::Type,
+ ) {
+ if matches!(self.cx.sess().opts.optimize, OptLevel::No | OptLevel::Less)
+ // For now, the critical niches are all over `Int`eger values.
+ // Should floating-point values or pointers ever get more complex
+ // niches, then this code will probably want to handle them too.
+ || !matches!(scalar.primitive(), abi::Primitive::Int(..))
+ || scalar.is_always_valid(self.cx)
+ {
+ return;
+ }
+
+ let abi::WrappingRange { start, end } = scalar.valid_range(self.cx);
+
+ if start <= end {
+ if start > 0 {
+ let low = bx.const_uint_big(backend_ty, start);
+ let cmp = bx.icmp(IntPredicate::IntUGE, imm, low);
+ bx.assume(cmp);
+ }
+
+ let type_max = scalar.size(self.cx).unsigned_int_max();
+ if end < type_max {
+ let high = bx.const_uint_big(backend_ty, end);
+ let cmp = bx.icmp(IntPredicate::IntULE, imm, high);
+ bx.assume(cmp);
+ }
+ } else {
+ let low = bx.const_uint_big(backend_ty, start);
+ let cmp_low = bx.icmp(IntPredicate::IntUGE, imm, low);
+
+ let high = bx.const_uint_big(backend_ty, end);
+ let cmp_high = bx.icmp(IntPredicate::IntULE, imm, high);
+
+ let or = bx.or(cmp_low, cmp_high);
+ bx.assume(or);
+ }
+ }
+
pub fn codegen_rvalue_unsized(
&mut self,
bx: &mut Bx,
@@ -604,13 +666,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}
}
- mir::Rvalue::NullaryOp(null_op, ty) => {
+ mir::Rvalue::NullaryOp(ref null_op, ty) => {
let ty = self.monomorphize(ty);
assert!(bx.cx().type_is_sized(ty));
let layout = bx.cx().layout_of(ty);
let val = match null_op {
mir::NullOp::SizeOf => layout.size.bytes(),
mir::NullOp::AlignOf => layout.align.abi.bytes(),
+ mir::NullOp::OffsetOf(fields) => {
+ layout.offset_of_subfield(bx.cx(), fields.iter().map(|f| f.index())).bytes()
+ }
};
let val = bx.cx().const_usize(val);
let tcx = self.cx.tcx();
diff --git a/compiler/rustc_const_eval/Cargo.toml b/compiler/rustc_const_eval/Cargo.toml
index 98ac36c1ced..74030a43c50 100644
--- a/compiler/rustc_const_eval/Cargo.toml
+++ b/compiler/rustc_const_eval/Cargo.toml
@@ -14,6 +14,7 @@ rustc_attr = { path = "../rustc_attr" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_hir = { path = "../rustc_hir" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_index = { path = "../rustc_index" }
rustc_infer = { path = "../rustc_infer" }
rustc_macros = { path = "../rustc_macros" }
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
index 4bd6fe19931..99f180f475d 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -296,12 +296,12 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
}
let cid = key.value;
- let def = cid.instance.def.with_opt_param();
- let is_static = tcx.is_static(def.did);
+ let def = cid.instance.def.def_id();
+ let is_static = tcx.is_static(def);
let mut ecx = InterpCx::new(
tcx,
- tcx.def_span(def.did),
+ tcx.def_span(def),
key.param_env,
// Statics (and promoteds inside statics) may access other statics, because unlike consts
// they do not have to behave "as if" they were evaluated at runtime.
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index a5dfd1072f0..814b67b46ec 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -375,9 +375,9 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> {
match instance {
ty::InstanceDef::Item(def) => {
- if ecx.tcx.is_ctfe_mir_available(def.did) {
- Ok(ecx.tcx.mir_for_ctfe_opt_const_arg(def))
- } else if ecx.tcx.def_kind(def.did) == DefKind::AssocConst {
+ if ecx.tcx.is_ctfe_mir_available(def) {
+ Ok(ecx.tcx.mir_for_ctfe(def))
+ } else if ecx.tcx.def_kind(def) == DefKind::AssocConst {
let guar = ecx.tcx.sess.delay_span_bug(
rustc_span::DUMMY_SP,
"This is likely a const item that is missing from its impl",
@@ -386,7 +386,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
} else {
// `find_mir_or_eval_fn` checks that this is a const fn before even calling us,
// so this should be unreachable.
- let path = ecx.tcx.def_path_str(def.did);
+ let path = ecx.tcx.def_path_str(def);
bug!("trying to call extern function `{path}` at compile-time");
}
}
@@ -410,9 +410,9 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
// Execution might have wandered off into other crates, so we cannot do a stability-
// sensitive check here. But we can at least rule out functions that are not const
// at all.
- if !ecx.tcx.is_const_fn_raw(def.did) {
+ if !ecx.tcx.is_const_fn_raw(def) {
// allow calling functions inside a trait marked with #[const_trait].
- if !ecx.tcx.is_const_default_method(def.did) {
+ if !ecx.tcx.is_const_default_method(def) {
// We certainly do *not* want to actually call the fn
// though, so be sure we return here.
throw_unsup_format!("calling non-const function `{}`", instance)
diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs
index 557e721249d..015a9beab83 100644
--- a/compiler/rustc_const_eval/src/interpret/discriminant.rs
+++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs
@@ -211,18 +211,19 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let variant_index_relative = u32::try_from(variant_index_relative)
.expect("we checked that this fits into a u32");
// Then computing the absolute variant idx should not overflow any more.
- let variant_index = variants_start
- .checked_add(variant_index_relative)
- .expect("overflow computing absolute variant idx");
- let variants_len = op
+ let variant_index = VariantIdx::from_u32(
+ variants_start
+ .checked_add(variant_index_relative)
+ .expect("overflow computing absolute variant idx"),
+ );
+ let variants = op
.layout
.ty
.ty_adt_def()
.expect("tagged layout for non adt")
- .variants()
- .len();
- assert!(usize::try_from(variant_index).unwrap() < variants_len);
- VariantIdx::from_u32(variant_index)
+ .variants();
+ assert!(variant_index < variants.next_index());
+ variant_index
} else {
untagged_variant
}
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index 3e58a58aef7..6030498e946 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -132,11 +132,10 @@ pub struct Frame<'mir, 'tcx, Prov: Provenance = AllocId, Extra = ()> {
}
/// What we store about a frame in an interpreter backtrace.
-#[derive(Debug)]
+#[derive(Clone, Debug)]
pub struct FrameInfo<'tcx> {
pub instance: ty::Instance<'tcx>,
pub span: Span,
- pub lint_root: Option<hir::HirId>,
}
#[derive(Clone, Copy, Eq, PartialEq, Debug)] // Miri debug-prints these
@@ -462,10 +461,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
instance: ty::InstanceDef<'tcx>,
promoted: Option<mir::Promoted>,
) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> {
- let def = instance.with_opt_param();
trace!("load mir(instance={:?}, promoted={:?})", instance, promoted);
let body = if let Some(promoted) = promoted {
- &self.tcx.promoted_mir_opt_const_arg(def)[promoted]
+ let def = instance.def_id();
+ &self.tcx.promoted_mir(def)[promoted]
} else {
M::load_mir(self, instance)?
};
@@ -503,13 +502,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
/// The `substs` are assumed to already be in our interpreter "universe" (param_env).
pub(super) fn resolve(
&self,
- def: ty::WithOptConstParam<DefId>,
+ def: DefId,
substs: SubstsRef<'tcx>,
) -> InterpResult<'tcx, ty::Instance<'tcx>> {
trace!("resolve: {:?}, {:#?}", def, substs);
trace!("param_env: {:#?}", self.param_env);
trace!("substs: {:#?}", substs);
- match ty::Instance::resolve_opt_const_arg(*self.tcx, self.param_env, def, substs) {
+ match ty::Instance::resolve(*self.tcx, self.param_env, def, substs) {
Ok(Some(instance)) => Ok(instance),
Ok(None) => throw_inval!(TooGeneric),
@@ -947,10 +946,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// 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.lint_root();
let span = frame.current_span();
-
- frames.push(FrameInfo { span, instance: frame.instance, lint_root });
+ frames.push(FrameInfo { span, instance: frame.instance });
}
trace!("generate stacktrace: {:#?}", frames);
frames
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index 26fb041b455..eada75ae391 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -75,7 +75,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
}
sym::type_id => {
ensure_monomorphic_enough(tcx, tp_ty)?;
- ConstValue::from_u64(tcx.type_id_hash(tp_ty))
+ ConstValue::from_u64(tcx.type_id_hash(tp_ty).as_u64())
}
sym::variant_count => match tp_ty.kind() {
// Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough.
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index 0291cca7378..b448e3a24c6 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -104,7 +104,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
type FrameExtra;
/// Extra data stored in every allocation.
- type AllocExtra: Debug + Clone + 'static;
+ type AllocExtra: Debug + Clone + 'tcx;
/// Type for the bytes of the allocation.
type Bytes: AllocBytes + 'static;
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index a3764a7d142..d5b6a581a79 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -215,7 +215,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
self.allocate_raw_ptr(alloc, kind)
}
- /// This can fail only of `alloc` contains provenance.
+ /// This can fail only if `alloc` contains provenance.
pub fn allocate_raw_ptr(
&mut self,
alloc: Allocation,
@@ -807,9 +807,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
DumpAllocs { ecx: self, allocs }
}
- /// Print leaked memory. Allocations reachable from `static_roots` or a `Global` allocation
- /// are not considered leaked. Leaks whose kind `may_leak()` returns true are not reported.
- pub fn leak_report(&self, static_roots: &[AllocId]) -> usize {
+ /// Find leaked allocations. Allocations reachable from `static_roots` or a `Global` allocation
+ /// are not considered leaked, as well as leaks whose kind's `may_leak()` returns true.
+ pub fn find_leaked_allocations(
+ &self,
+ static_roots: &[AllocId],
+ ) -> Vec<(AllocId, MemoryKind<M::MemoryKind>, Allocation<M::Provenance, M::AllocExtra, M::Bytes>)>
+ {
// Collect the set of allocations that are *reachable* from `Global` allocations.
let reachable = {
let mut reachable = FxHashSet::default();
@@ -833,14 +837,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
};
// All allocations that are *not* `reachable` and *not* `may_leak` are considered leaking.
- let leaks: Vec<_> = self.memory.alloc_map.filter_map_collect(|&id, &(kind, _)| {
- if kind.may_leak() || reachable.contains(&id) { None } else { Some(id) }
- });
- let n = leaks.len();
- if n > 0 {
- eprintln!("The following memory was leaked: {:?}", self.dump_allocs(leaks));
- }
- n
+ self.memory.alloc_map.filter_map_collect(|id, (kind, alloc)| {
+ if kind.may_leak() || reachable.contains(id) {
+ None
+ } else {
+ Some((*id, *kind, alloc.clone()))
+ }
+ })
}
}
diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs
index 9a366364e76..319b80d66e1 100644
--- a/compiler/rustc_const_eval/src/interpret/step.rs
+++ b/compiler/rustc_const_eval/src/interpret/step.rs
@@ -113,8 +113,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
Intrinsic(box intrinsic) => self.emulate_nondiverging_intrinsic(intrinsic)?,
- // Statements we do not track.
- PlaceMention(..) | AscribeUserType(..) => {}
+ // Evaluate the place expression, without reading from it.
+ PlaceMention(box place) => {
+ let _ = self.eval_place(*place)?;
+ }
+
+ // This exists purely to guide borrowck lifetime inference, and does not have
+ // an operational effect.
+ AscribeUserType(..) => {}
// Currently, Miri discards Coverage statements. Coverage statements are only injected
// via an optional compile time MIR pass and have no side effects. Since Coverage
@@ -280,20 +286,23 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
self.write_immediate(*val, &dest)?;
}
- NullaryOp(null_op, ty) => {
+ NullaryOp(ref null_op, ty) => {
let ty = self.subst_from_current_frame_and_normalize_erasing_regions(ty)?;
let layout = self.layout_of(ty)?;
- if layout.is_unsized() {
+ if let mir::NullOp::SizeOf | mir::NullOp::AlignOf = null_op && layout.is_unsized() {
// FIXME: This should be a span_bug (#80742)
self.tcx.sess.delay_span_bug(
self.frame().current_span(),
- &format!("Nullary MIR operator called for unsized type {}", ty),
+ &format!("{null_op:?} MIR operator called for unsized type {ty}"),
);
throw_inval!(SizeOfUnsizedType(ty));
}
let val = match null_op {
mir::NullOp::SizeOf => layout.size.bytes(),
mir::NullOp::AlignOf => layout.align.abi.bytes(),
+ mir::NullOp::OffsetOf(fields) => {
+ layout.offset_of_subfield(self, fields.iter().map(|f| f.index())).bytes()
+ }
};
self.write_scalar(Scalar::from_target_usize(val, self), &dest)?;
}
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index a07702f7d9b..df387920010 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -83,8 +83,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
(fn_val, self.fn_abi_of_fn_ptr(fn_sig_binder, extra_args)?, false)
}
ty::FnDef(def_id, substs) => {
- let instance =
- self.resolve(ty::WithOptConstParam::unknown(def_id), substs)?;
+ let instance = self.resolve(def_id, substs)?;
(
FnVal::Instance(instance),
self.fn_abi_of_instance(instance, extra_args)?,
diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs
index bf2b4ee69ab..7cb19744987 100644
--- a/compiler/rustc_const_eval/src/interpret/util.rs
+++ b/compiler/rustc_const_eval/src/interpret/util.rs
@@ -36,7 +36,7 @@ where
ty::Closure(def_id, substs)
| ty::Generator(def_id, substs, ..)
| ty::FnDef(def_id, substs) => {
- let instance = ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id));
+ let instance = ty::InstanceDef::Item(def_id);
let unused_params = self.tcx.unused_generic_params(instance);
for (index, subst) in substs.into_iter().enumerate() {
let index = index
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 93b5273e1b1..e06b634cdc3 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -784,7 +784,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
Abi::Scalar(scalar_layout) => {
if !scalar_layout.is_uninit_valid() {
// There is something to check here.
- let scalar = self.read_scalar(op, "initiailized scalar value")?;
+ let scalar = self.read_scalar(op, "initialized scalar value")?;
self.visit_scalar(scalar, scalar_layout)?;
}
}
@@ -794,7 +794,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
// the other must be init.
if !a_layout.is_uninit_valid() && !b_layout.is_uninit_valid() {
let (a, b) =
- self.read_immediate(op, "initiailized scalar value")?.to_scalar_pair();
+ self.read_immediate(op, "initialized scalar value")?.to_scalar_pair();
self.visit_scalar(a, a_layout)?;
self.visit_scalar(b, b_layout)?;
}
diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs
index 5ab389d04c7..1b66eca97a5 100644
--- a/compiler/rustc_const_eval/src/lib.rs
+++ b/compiler/rustc_const_eval/src/lib.rs
@@ -34,7 +34,7 @@ pub mod transform;
pub mod util;
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
-use rustc_macros::fluent_messages;
+use rustc_fluent_macro::fluent_messages;
use rustc_middle::ty;
use rustc_middle::ty::query::Providers;
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index 9dad9479053..696c4517700 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -558,7 +558,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
Rvalue::Cast(_, _, _) => {}
- Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => {}
+ Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_), _) => {}
Rvalue::ShallowInitBox(_, _) => {}
Rvalue::UnaryOp(_, operand) => {
@@ -874,7 +874,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
debug!("Resolving ({:?}) -> {:?}", callee, instance);
if let Ok(Some(func)) = instance {
if let InstanceDef::Item(def) = func.def {
- callee = def.did;
+ callee = def;
}
}
}
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
index c0f5b3725b3..6c11edb742c 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
@@ -14,6 +14,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
use rustc_middle::ty::{suggest_constraining_type_param, Adt, Closure, FnDef, FnPtr, Param, Ty};
use rustc_middle::ty::{Binder, TraitRef};
+use rustc_middle::util::{call_kind, CallDesugaringKind, CallKind};
use rustc_session::parse::feature_err;
use rustc_span::symbol::sym;
use rustc_span::{BytePos, Pos, Span, Symbol};
@@ -21,7 +22,6 @@ use rustc_trait_selection::traits::SelectionContext;
use super::ConstCx;
use crate::errors;
-use crate::util::{call_kind, CallDesugaringKind, CallKind};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Status {
@@ -610,10 +610,11 @@ pub struct RawPtrComparison;
impl<'tcx> NonConstOp<'tcx> for RawPtrComparison {
fn build_error(
&self,
- _: &ConstCx<'_, 'tcx>,
+ ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- span_bug!(span, "raw ptr comparison should already be caught in the trait system");
+ // FIXME(const_trait_impl): revert to span_bug?
+ ccx.tcx.sess.create_err(errors::RawPtrComparisonErr { span })
}
}
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
index 6758cba2eed..bf688f2b34e 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
@@ -364,9 +364,8 @@ where
assert!(promoted.is_none() || Q::ALLOW_PROMOTED);
// Don't peek inside trait associated constants.
- if promoted.is_none() && cx.tcx.trait_of_item(def.did).is_none() {
- assert_eq!(def.const_param_did, None, "expected associated const: {def:?}");
- let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def.did);
+ if promoted.is_none() && cx.tcx.trait_of_item(def).is_none() {
+ let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def);
if !Q::in_qualifs(&qualifs) {
return false;
diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs
index 7919aed097a..e978e344283 100644
--- a/compiler/rustc_const_eval/src/transform/promote_consts.rs
+++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs
@@ -514,6 +514,7 @@ impl<'tcx> Validator<'_, 'tcx> {
Rvalue::NullaryOp(op, _) => match op {
NullOp::SizeOf => {}
NullOp::AlignOf => {}
+ NullOp::OffsetOf(_) => {}
},
Rvalue::ShallowInitBox(_, _) => return Err(Unpromotable),
@@ -828,7 +829,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
}
fn promote_candidate(mut self, candidate: Candidate, next_promoted_id: usize) -> Body<'tcx> {
- let def = self.source.source.with_opt_param();
+ let def = self.source.source.def_id();
let mut rvalue = {
let promoted = &mut self.promoted;
let promoted_id = Promoted::new(next_promoted_id);
@@ -836,7 +837,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
let mut promoted_operand = |ty, span| {
promoted.span = span;
promoted.local_decls[RETURN_PLACE] = LocalDecl::new(ty, span);
- let substs = tcx.erase_regions(InternalSubsts::identity_for_item(tcx, def.did));
+ let substs = tcx.erase_regions(InternalSubsts::identity_for_item(tcx, def));
let uneval = mir::UnevaluatedConst { def, substs, promoted: Some(promoted_id) };
Operand::Constant(Box::new(Constant {
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index d4bed97380b..b8809d29c77 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -8,9 +8,10 @@ use rustc_middle::mir::interpret::Scalar;
use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor};
use rustc_middle::mir::{
traversal, BasicBlock, BinOp, Body, BorrowKind, CastKind, CopyNonOverlapping, Local, Location,
- MirPass, MirPhase, NonDivergingIntrinsic, Operand, Place, PlaceElem, PlaceRef, ProjectionElem,
- RetagKind, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind, Terminator,
- TerminatorKind, UnOp, UnwindAction, VarDebugInfo, VarDebugInfoContents, START_BLOCK,
+ MirPass, MirPhase, NonDivergingIntrinsic, NullOp, Operand, Place, PlaceElem, PlaceRef,
+ ProjectionElem, RetagKind, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind,
+ Terminator, TerminatorKind, UnOp, UnwindAction, VarDebugInfo, VarDebugInfoContents,
+ START_BLOCK,
};
use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt};
use rustc_mir_dataflow::impls::MaybeStorageLive;
@@ -262,7 +263,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// We sometimes have to use `defining_opaque_types` for subtyping
// to succeed here and figuring out how exactly that should work
// is annoying. It is harmless enough to just not validate anything
- // in that case. We still check this after analysis as all opque
+ // in that case. We still check this after analysis as all opaque
// types have been revealed at this point.
if (src, dest).has_opaque_types() {
return true;
@@ -711,10 +712,54 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
}
}
}
+ Rvalue::NullaryOp(NullOp::OffsetOf(fields), container) => {
+ let fail_out_of_bounds = |this: &Self, location, field, ty| {
+ this.fail(location, format!("Out of bounds field {field:?} for {ty:?}"));
+ };
+
+ let mut current_ty = *container;
+
+ for field in fields.iter() {
+ match current_ty.kind() {
+ ty::Tuple(fields) => {
+ let Some(&f_ty) = fields.get(field.as_usize()) else {
+ fail_out_of_bounds(self, location, field, current_ty);
+ return;
+ };
+
+ current_ty = self.tcx.normalize_erasing_regions(self.param_env, f_ty);
+ }
+ ty::Adt(adt_def, substs) => {
+ if adt_def.is_enum() {
+ self.fail(
+ location,
+ format!("Cannot get field offset from enum {current_ty:?}"),
+ );
+ return;
+ }
+
+ let Some(field) = adt_def.non_enum_variant().fields.get(field) else {
+ fail_out_of_bounds(self, location, field, current_ty);
+ return;
+ };
+
+ let f_ty = field.ty(self.tcx, substs);
+ current_ty = self.tcx.normalize_erasing_regions(self.param_env, f_ty);
+ }
+ _ => {
+ self.fail(
+ location,
+ format!("Cannot get field offset from non-adt type {current_ty:?}"),
+ );
+ return;
+ }
+ }
+ }
+ }
Rvalue::Repeat(_, _)
| Rvalue::ThreadLocalRef(_)
| Rvalue::AddressOf(_, _)
- | Rvalue::NullaryOp(_, _)
+ | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _)
| Rvalue::Discriminant(_) => {}
}
self.super_rvalue(rvalue, location);
@@ -757,14 +802,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
}
}
}
- StatementKind::PlaceMention(..) => {
- if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
- self.fail(
- location,
- "`PlaceMention` should have been removed after drop lowering phase",
- );
- }
- }
StatementKind::AscribeUserType(..) => {
if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
self.fail(
@@ -874,6 +911,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
StatementKind::StorageDead(_)
| StatementKind::Coverage(_)
| StatementKind::ConstEvalCounter
+ | StatementKind::PlaceMention(..)
| StatementKind::Nop => {}
}
diff --git a/compiler/rustc_const_eval/src/util/mod.rs b/compiler/rustc_const_eval/src/util/mod.rs
index c0aabd77cee..7641f560714 100644
--- a/compiler/rustc_const_eval/src/util/mod.rs
+++ b/compiler/rustc_const_eval/src/util/mod.rs
@@ -1,14 +1,9 @@
mod alignment;
-mod call_kind;
mod check_validity_requirement;
-pub mod collect_writes;
mod compare_types;
-mod find_self_call;
mod type_name;
pub use self::alignment::is_disaligned;
-pub use self::call_kind::{call_kind, CallDesugaringKind, CallKind};
pub use self::check_validity_requirement::check_validity_requirement;
pub use self::compare_types::{is_equal_up_to_subtyping, is_subtype};
-pub use self::find_self_call::find_self_call;
pub use self::type_name::type_name;
diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml
index 2102f09c56a..39f4bc63c88 100644
--- a/compiler/rustc_data_structures/Cargo.toml
+++ b/compiler/rustc_data_structures/Cargo.toml
@@ -21,7 +21,6 @@ rustc-hash = "1.1.0"
rustc_index = { path = "../rustc_index", package = "rustc_index" }
rustc_macros = { path = "../rustc_macros" }
rustc_serialize = { path = "../rustc_serialize" }
-serde_json = "1.0.59"
smallvec = { version = "1.8.1", features = [
"const_generics",
"union",
diff --git a/compiler/rustc_data_structures/src/aligned.rs b/compiler/rustc_data_structures/src/aligned.rs
new file mode 100644
index 00000000000..0e5ecfd9bff
--- /dev/null
+++ b/compiler/rustc_data_structures/src/aligned.rs
@@ -0,0 +1,33 @@
+use std::ptr::Alignment;
+
+/// Returns the ABI-required minimum alignment of a type in bytes.
+///
+/// This is equivalent to [`mem::align_of`], but also works for some unsized
+/// types (e.g. slices or rustc's `List`s).
+///
+/// [`mem::align_of`]: std::mem::align_of
+pub const fn align_of<T: ?Sized + Aligned>() -> Alignment {
+ T::ALIGN
+}
+
+/// A type with a statically known alignment.
+///
+/// # Safety
+///
+/// `Self::ALIGN` must be equal to the alignment of `Self`. For sized types it
+/// is [`mem::align_of<Self>()`], for unsized types it depends on the type, for
+/// example `[T]` has alignment of `T`.
+///
+/// [`mem::align_of<Self>()`]: std::mem::align_of
+pub unsafe trait Aligned {
+ /// Alignment of `Self`.
+ const ALIGN: Alignment;
+}
+
+unsafe impl<T> Aligned for T {
+ const ALIGN: Alignment = Alignment::of::<Self>();
+}
+
+unsafe impl<T> Aligned for [T] {
+ const ALIGN: Alignment = Alignment::of::<T>();
+}
diff --git a/compiler/rustc_data_structures/src/fingerprint.rs b/compiler/rustc_data_structures/src/fingerprint.rs
index b6e866f15ef..6fa76981408 100644
--- a/compiler/rustc_data_structures/src/fingerprint.rs
+++ b/compiler/rustc_data_structures/src/fingerprint.rs
@@ -1,4 +1,4 @@
-use crate::stable_hasher;
+use crate::stable_hasher::{Hash64, StableHasher, StableHasherResult};
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use std::hash::{Hash, Hasher};
@@ -9,32 +9,49 @@ mod tests;
#[repr(C)]
pub struct Fingerprint(u64, u64);
-impl Fingerprint {
- pub const ZERO: Fingerprint = Fingerprint(0, 0);
+pub trait FingerprintComponent {
+ fn as_u64(&self) -> u64;
+}
+impl FingerprintComponent for Hash64 {
#[inline]
- pub fn new(_0: u64, _1: u64) -> Fingerprint {
- Fingerprint(_0, _1)
+ fn as_u64(&self) -> u64 {
+ Hash64::as_u64(*self)
+ }
+}
+
+impl FingerprintComponent for u64 {
+ #[inline]
+ fn as_u64(&self) -> u64 {
+ *self
}
+}
+
+impl Fingerprint {
+ pub const ZERO: Fingerprint = Fingerprint(0, 0);
#[inline]
- pub fn from_smaller_hash(hash: u64) -> Fingerprint {
- Fingerprint(hash, hash)
+ pub fn new<A, B>(_0: A, _1: B) -> Fingerprint
+ where
+ A: FingerprintComponent,
+ B: FingerprintComponent,
+ {
+ Fingerprint(_0.as_u64(), _1.as_u64())
}
#[inline]
- pub fn to_smaller_hash(&self) -> u64 {
+ pub fn to_smaller_hash(&self) -> Hash64 {
// Even though both halves of the fingerprint are expected to be good
// quality hash values, let's still combine the two values because the
// Fingerprints in DefPathHash have the StableCrateId portion which is
// the same for all DefPathHashes from the same crate. Combining the
// two halves makes sure we get a good quality hash in such cases too.
- self.0.wrapping_mul(3).wrapping_add(self.1)
+ Hash64::new(self.0.wrapping_mul(3).wrapping_add(self.1))
}
#[inline]
- pub fn as_value(&self) -> (u64, u64) {
- (self.0, self.1)
+ pub fn split(&self) -> (Hash64, Hash64) {
+ (Hash64::new(self.0), Hash64::new(self.1))
}
#[inline]
@@ -131,9 +148,9 @@ impl FingerprintHasher for crate::unhash::Unhasher {
}
}
-impl stable_hasher::StableHasherResult for Fingerprint {
+impl StableHasherResult for Fingerprint {
#[inline]
- fn finish(hasher: stable_hasher::StableHasher) -> Self {
+ fn finish(hasher: StableHasher) -> Self {
let (_0, _1) = hasher.finalize();
Fingerprint(_0, _1)
}
diff --git a/compiler/rustc_data_structures/src/fingerprint/tests.rs b/compiler/rustc_data_structures/src/fingerprint/tests.rs
index 9b0783e33ab..09ec2622a65 100644
--- a/compiler/rustc_data_structures/src/fingerprint/tests.rs
+++ b/compiler/rustc_data_structures/src/fingerprint/tests.rs
@@ -1,11 +1,12 @@
use super::*;
+use crate::stable_hasher::Hash64;
// Check that `combine_commutative` is order independent.
#[test]
fn combine_commutative_is_order_independent() {
- let a = Fingerprint::new(0xf6622fb349898b06, 0x70be9377b2f9c610);
- let b = Fingerprint::new(0xa9562bf5a2a5303c, 0x67d9b6c82034f13d);
- let c = Fingerprint::new(0x0d013a27811dbbc3, 0x9a3f7b3d9142ec43);
+ let a = Fingerprint::new(Hash64::new(0xf6622fb349898b06), Hash64::new(0x70be9377b2f9c610));
+ let b = Fingerprint::new(Hash64::new(0xa9562bf5a2a5303c), Hash64::new(0x67d9b6c82034f13d));
+ let c = Fingerprint::new(Hash64::new(0x0d013a27811dbbc3), Hash64::new(0x9a3f7b3d9142ec43));
let permutations = [(a, b, c), (a, c, b), (b, a, c), (b, c, a), (c, a, b), (c, b, a)];
let f = a.combine_commutative(b).combine_commutative(c);
for p in &permutations {
diff --git a/compiler/rustc_data_structures/src/hashes.rs b/compiler/rustc_data_structures/src/hashes.rs
new file mode 100644
index 00000000000..ad068cdbc98
--- /dev/null
+++ b/compiler/rustc_data_structures/src/hashes.rs
@@ -0,0 +1,132 @@
+//! rustc encodes a lot of hashes. If hashes are stored as `u64` or `u128`, a `derive(Encodable)`
+//! will apply varint encoding to the hashes, which is less efficient than directly encoding the 8
+//! or 16 bytes of the hash.
+//!
+//! The types in this module represent 64-bit or 128-bit hashes produced by a `StableHasher`.
+//! `Hash64` and `Hash128` expose some utilty functions to encourage users to not extract the inner
+//! hash value as an integer type and accidentally apply varint encoding to it.
+//!
+//! In contrast with `Fingerprint`, users of these types cannot and should not attempt to construct
+//! and decompose these types into constitutent pieces. The point of these types is only to
+//! connect the fact that they can only be produced by a `StableHasher` to their
+//! `Encode`/`Decode` impls.
+
+use crate::stable_hasher::{StableHasher, StableHasherResult};
+use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
+use std::fmt;
+use std::ops::BitXorAssign;
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
+pub struct Hash64 {
+ inner: u64,
+}
+
+impl Hash64 {
+ pub const ZERO: Hash64 = Hash64 { inner: 0 };
+
+ #[inline]
+ pub(crate) fn new(n: u64) -> Self {
+ Self { inner: n }
+ }
+
+ #[inline]
+ pub fn as_u64(self) -> u64 {
+ self.inner
+ }
+}
+
+impl BitXorAssign<u64> for Hash64 {
+ #[inline]
+ fn bitxor_assign(&mut self, rhs: u64) {
+ self.inner ^= rhs;
+ }
+}
+
+impl<S: Encoder> Encodable<S> for Hash64 {
+ #[inline]
+ fn encode(&self, s: &mut S) {
+ s.emit_raw_bytes(&self.inner.to_le_bytes());
+ }
+}
+
+impl<D: Decoder> Decodable<D> for Hash64 {
+ #[inline]
+ fn decode(d: &mut D) -> Self {
+ Self { inner: u64::from_le_bytes(d.read_raw_bytes(8).try_into().unwrap()) }
+ }
+}
+
+impl StableHasherResult for Hash64 {
+ #[inline]
+ fn finish(hasher: StableHasher) -> Self {
+ Self { inner: hasher.finalize().0 }
+ }
+}
+
+impl fmt::Debug for Hash64 {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.inner.fmt(f)
+ }
+}
+
+impl fmt::LowerHex for Hash64 {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::LowerHex::fmt(&self.inner, f)
+ }
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
+pub struct Hash128 {
+ inner: u128,
+}
+
+impl Hash128 {
+ #[inline]
+ pub fn truncate(self) -> Hash64 {
+ Hash64 { inner: self.inner as u64 }
+ }
+
+ #[inline]
+ pub fn wrapping_add(self, other: Self) -> Self {
+ Self { inner: self.inner.wrapping_add(other.inner) }
+ }
+
+ #[inline]
+ pub fn as_u128(self) -> u128 {
+ self.inner
+ }
+}
+
+impl<S: Encoder> Encodable<S> for Hash128 {
+ #[inline]
+ fn encode(&self, s: &mut S) {
+ s.emit_raw_bytes(&self.inner.to_le_bytes());
+ }
+}
+
+impl<D: Decoder> Decodable<D> for Hash128 {
+ #[inline]
+ fn decode(d: &mut D) -> Self {
+ Self { inner: u128::from_le_bytes(d.read_raw_bytes(16).try_into().unwrap()) }
+ }
+}
+
+impl StableHasherResult for Hash128 {
+ #[inline]
+ fn finish(hasher: StableHasher) -> Self {
+ let (_0, _1) = hasher.finalize();
+ Self { inner: u128::from(_0) | (u128::from(_1) << 64) }
+ }
+}
+
+impl fmt::Debug for Hash128 {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.inner.fmt(f)
+ }
+}
+
+impl fmt::LowerHex for Hash128 {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::LowerHex::fmt(&self.inner, f)
+ }
+}
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index e373bd18402..426d2c4034b 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -29,10 +29,13 @@
#![feature(get_mut_unchecked)]
#![feature(lint_reasons)]
#![feature(unwrap_infallible)]
+#![feature(strict_provenance)]
+#![feature(ptr_alignment_type)]
#![allow(rustc::default_hash_types)]
#![allow(rustc::potential_query_instability)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
+#![deny(unsafe_op_in_unsafe_fn)]
#[macro_use]
extern crate tracing;
@@ -82,7 +85,9 @@ pub mod transitive_relation;
pub mod vec_linked_list;
pub mod work_queue;
pub use atomic_ref::AtomicRef;
+pub mod aligned;
pub mod frozen;
+mod hashes;
pub mod owned_slice;
pub mod sso;
pub mod steal;
diff --git a/compiler/rustc_data_structures/src/memmap.rs b/compiler/rustc_data_structures/src/memmap.rs
index ef37a606f31..ca908671ae5 100644
--- a/compiler/rustc_data_structures/src/memmap.rs
+++ b/compiler/rustc_data_structures/src/memmap.rs
@@ -13,7 +13,8 @@ pub struct Mmap(Vec<u8>);
impl Mmap {
#[inline]
pub unsafe fn map(file: File) -> io::Result<Self> {
- memmap2::Mmap::map(&file).map(Mmap)
+ // Safety: this is in fact not safe.
+ unsafe { memmap2::Mmap::map(&file).map(Mmap) }
}
}
diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs
index 1ed584eafad..572bd4ac21c 100644
--- a/compiler/rustc_data_structures/src/profiling.rs
+++ b/compiler/rustc_data_structures/src/profiling.rs
@@ -87,6 +87,7 @@ use crate::fx::FxHashMap;
use std::borrow::Borrow;
use std::collections::hash_map::Entry;
use std::error::Error;
+use std::fmt::Display;
use std::fs;
use std::intrinsics::unlikely;
use std::path::Path;
@@ -97,7 +98,6 @@ use std::time::{Duration, Instant};
pub use measureme::EventId;
use measureme::{EventIdBuilder, Profiler, SerializableString, StringId};
use parking_lot::RwLock;
-use serde_json::json;
use smallvec::SmallVec;
bitflags::bitflags! {
@@ -557,7 +557,7 @@ impl SelfProfiler {
let crate_name = crate_name.unwrap_or("unknown-crate");
// HACK(eddyb) we need to pad the PID, strange as it may seem, as its
// length can behave as a source of entropy for heap addresses, when
- // ASLR is disabled and the heap is otherwise determinic.
+ // ASLR is disabled and the heap is otherwise deterministic.
let pid: u32 = process::id();
let filename = format!("{crate_name}-{pid:07}.rustc_profile");
let path = output_directory.join(&filename);
@@ -763,6 +763,31 @@ impl Drop for VerboseTimingGuard<'_> {
}
}
+struct JsonTimePassesEntry<'a> {
+ pass: &'a str,
+ time: f64,
+ start_rss: Option<usize>,
+ end_rss: Option<usize>,
+}
+
+impl Display for JsonTimePassesEntry<'_> {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ let Self { pass: what, time, start_rss, end_rss } = self;
+ write!(f, r#"{{"pass":"{what}","time":{time},"rss_start":"#).unwrap();
+ match start_rss {
+ Some(rss) => write!(f, "{rss}")?,
+ None => write!(f, "null")?,
+ }
+ write!(f, r#","rss_end":"#)?;
+ match end_rss {
+ Some(rss) => write!(f, "{rss}")?,
+ None => write!(f, "null")?,
+ }
+ write!(f, "}}")?;
+ Ok(())
+ }
+}
+
pub fn print_time_passes_entry(
what: &str,
dur: Duration,
@@ -772,13 +797,10 @@ pub fn print_time_passes_entry(
) {
match format {
TimePassesFormat::Json => {
- let json = json!({
- "pass": what,
- "time": dur.as_secs_f64(),
- "rss_start": start_rss,
- "rss_end": end_rss,
- });
- eprintln!("time: {json}");
+ let entry =
+ JsonTimePassesEntry { pass: what, time: dur.as_secs_f64(), start_rss, end_rss };
+
+ eprintln!(r#"time: {entry}"#);
return;
}
TimePassesFormat::Text => (),
@@ -894,3 +916,6 @@ cfg_if! {
}
}
}
+
+#[cfg(test)]
+mod tests;
diff --git a/compiler/rustc_data_structures/src/profiling/tests.rs b/compiler/rustc_data_structures/src/profiling/tests.rs
new file mode 100644
index 00000000000..2b09de085da
--- /dev/null
+++ b/compiler/rustc_data_structures/src/profiling/tests.rs
@@ -0,0 +1,19 @@
+use super::JsonTimePassesEntry;
+
+#[test]
+fn with_rss() {
+ let entry =
+ JsonTimePassesEntry { pass: "typeck", time: 56.1, start_rss: Some(10), end_rss: Some(20) };
+
+ assert_eq!(entry.to_string(), r#"{"pass":"typeck","time":56.1,"rss_start":10,"rss_end":20}"#)
+}
+
+#[test]
+fn no_rss() {
+ let entry = JsonTimePassesEntry { pass: "typeck", time: 56.1, start_rss: None, end_rss: None };
+
+ assert_eq!(
+ entry.to_string(),
+ r#"{"pass":"typeck","time":56.1,"rss_start":null,"rss_end":null}"#
+ )
+}
diff --git a/compiler/rustc_data_structures/src/sip128.rs b/compiler/rustc_data_structures/src/sip128.rs
index d849fe0373f..4a0ed87f77c 100644
--- a/compiler/rustc_data_structures/src/sip128.rs
+++ b/compiler/rustc_data_structures/src/sip128.rs
@@ -96,28 +96,30 @@ macro_rules! compress {
unsafe fn copy_nonoverlapping_small(src: *const u8, dst: *mut u8, count: usize) {
debug_assert!(count <= 8);
- if count == 8 {
- ptr::copy_nonoverlapping(src, dst, 8);
- return;
- }
+ unsafe {
+ if count == 8 {
+ ptr::copy_nonoverlapping(src, dst, 8);
+ return;
+ }
- let mut i = 0;
- if i + 3 < count {
- ptr::copy_nonoverlapping(src.add(i), dst.add(i), 4);
- i += 4;
- }
+ let mut i = 0;
+ if i + 3 < count {
+ ptr::copy_nonoverlapping(src.add(i), dst.add(i), 4);
+ i += 4;
+ }
- if i + 1 < count {
- ptr::copy_nonoverlapping(src.add(i), dst.add(i), 2);
- i += 2
- }
+ if i + 1 < count {
+ ptr::copy_nonoverlapping(src.add(i), dst.add(i), 2);
+ i += 2
+ }
- if i < count {
- *dst.add(i) = *src.add(i);
- i += 1;
- }
+ if i < count {
+ *dst.add(i) = *src.add(i);
+ i += 1;
+ }
- debug_assert_eq!(i, count);
+ debug_assert_eq!(i, count);
+ }
}
// # Implementation
@@ -232,38 +234,40 @@ impl SipHasher128 {
// overflow) if it wasn't already.
#[inline(never)]
unsafe fn short_write_process_buffer<const LEN: usize>(&mut self, bytes: [u8; LEN]) {
- let nbuf = self.nbuf;
- debug_assert!(LEN <= 8);
- debug_assert!(nbuf < BUFFER_SIZE);
- debug_assert!(nbuf + LEN >= BUFFER_SIZE);
- debug_assert!(nbuf + LEN < BUFFER_WITH_SPILL_SIZE);
+ unsafe {
+ let nbuf = self.nbuf;
+ debug_assert!(LEN <= 8);
+ debug_assert!(nbuf < BUFFER_SIZE);
+ debug_assert!(nbuf + LEN >= BUFFER_SIZE);
+ debug_assert!(nbuf + LEN < BUFFER_WITH_SPILL_SIZE);
+
+ // Copy first part of input into end of buffer, possibly into spill
+ // element. The memcpy call is optimized away because the size is known.
+ let dst = (self.buf.as_mut_ptr() as *mut u8).add(nbuf);
+ ptr::copy_nonoverlapping(bytes.as_ptr(), dst, LEN);
+
+ // Process buffer.
+ for i in 0..BUFFER_CAPACITY {
+ let elem = self.buf.get_unchecked(i).assume_init().to_le();
+ self.state.v3 ^= elem;
+ Sip13Rounds::c_rounds(&mut self.state);
+ self.state.v0 ^= elem;
+ }
- // Copy first part of input into end of buffer, possibly into spill
- // element. The memcpy call is optimized away because the size is known.
- let dst = (self.buf.as_mut_ptr() as *mut u8).add(nbuf);
- ptr::copy_nonoverlapping(bytes.as_ptr(), dst, LEN);
-
- // Process buffer.
- for i in 0..BUFFER_CAPACITY {
- let elem = self.buf.get_unchecked(i).assume_init().to_le();
- self.state.v3 ^= elem;
- Sip13Rounds::c_rounds(&mut self.state);
- self.state.v0 ^= elem;
+ // Copy remaining input into start of buffer by copying LEN - 1
+ // elements from spill (at most LEN - 1 bytes could have overflowed
+ // into the spill). The memcpy call is optimized away because the size
+ // is known. And the whole copy is optimized away for LEN == 1.
+ let dst = self.buf.as_mut_ptr() as *mut u8;
+ let src = self.buf.get_unchecked(BUFFER_SPILL_INDEX) as *const _ as *const u8;
+ ptr::copy_nonoverlapping(src, dst, LEN - 1);
+
+ // This function should only be called when the write fills the buffer.
+ // Therefore, when LEN == 1, the new `self.nbuf` must be zero.
+ // LEN is statically known, so the branch is optimized away.
+ self.nbuf = if LEN == 1 { 0 } else { nbuf + LEN - BUFFER_SIZE };
+ self.processed += BUFFER_SIZE;
}
-
- // Copy remaining input into start of buffer by copying LEN - 1
- // elements from spill (at most LEN - 1 bytes could have overflowed
- // into the spill). The memcpy call is optimized away because the size
- // is known. And the whole copy is optimized away for LEN == 1.
- let dst = self.buf.as_mut_ptr() as *mut u8;
- let src = self.buf.get_unchecked(BUFFER_SPILL_INDEX) as *const _ as *const u8;
- ptr::copy_nonoverlapping(src, dst, LEN - 1);
-
- // This function should only be called when the write fills the buffer.
- // Therefore, when LEN == 1, the new `self.nbuf` must be zero.
- // LEN is statically known, so the branch is optimized away.
- self.nbuf = if LEN == 1 { 0 } else { nbuf + LEN - BUFFER_SIZE };
- self.processed += BUFFER_SIZE;
}
// A write function for byte slices.
@@ -301,57 +305,59 @@ impl SipHasher128 {
// containing the byte offset `self.nbuf`.
#[inline(never)]
unsafe fn slice_write_process_buffer(&mut self, msg: &[u8]) {
- let length = msg.len();
- let nbuf = self.nbuf;
- debug_assert!(nbuf < BUFFER_SIZE);
- debug_assert!(nbuf + length >= BUFFER_SIZE);
-
- // Always copy first part of input into current element of buffer.
- // This function should only be called when the write fills the buffer,
- // so we know that there is enough input to fill the current element.
- let valid_in_elem = nbuf % ELEM_SIZE;
- let needed_in_elem = ELEM_SIZE - valid_in_elem;
-
- let src = msg.as_ptr();
- let dst = (self.buf.as_mut_ptr() as *mut u8).add(nbuf);
- copy_nonoverlapping_small(src, dst, needed_in_elem);
-
- // Process buffer.
+ unsafe {
+ let length = msg.len();
+ let nbuf = self.nbuf;
+ debug_assert!(nbuf < BUFFER_SIZE);
+ debug_assert!(nbuf + length >= BUFFER_SIZE);
+
+ // Always copy first part of input into current element of buffer.
+ // This function should only be called when the write fills the buffer,
+ // so we know that there is enough input to fill the current element.
+ let valid_in_elem = nbuf % ELEM_SIZE;
+ let needed_in_elem = ELEM_SIZE - valid_in_elem;
+
+ let src = msg.as_ptr();
+ let dst = (self.buf.as_mut_ptr() as *mut u8).add(nbuf);
+ copy_nonoverlapping_small(src, dst, needed_in_elem);
+
+ // Process buffer.
+
+ // Using `nbuf / ELEM_SIZE + 1` rather than `(nbuf + needed_in_elem) /
+ // ELEM_SIZE` to show the compiler that this loop's upper bound is > 0.
+ // We know that is true, because last step ensured we have a full
+ // element in the buffer.
+ let last = nbuf / ELEM_SIZE + 1;
+
+ for i in 0..last {
+ let elem = self.buf.get_unchecked(i).assume_init().to_le();
+ self.state.v3 ^= elem;
+ Sip13Rounds::c_rounds(&mut self.state);
+ self.state.v0 ^= elem;
+ }
- // Using `nbuf / ELEM_SIZE + 1` rather than `(nbuf + needed_in_elem) /
- // ELEM_SIZE` to show the compiler that this loop's upper bound is > 0.
- // We know that is true, because last step ensured we have a full
- // element in the buffer.
- let last = nbuf / ELEM_SIZE + 1;
+ // Process the remaining element-sized chunks of input.
+ let mut processed = needed_in_elem;
+ let input_left = length - processed;
+ let elems_left = input_left / ELEM_SIZE;
+ let extra_bytes_left = input_left % ELEM_SIZE;
+
+ for _ in 0..elems_left {
+ let elem = (msg.as_ptr().add(processed) as *const u64).read_unaligned().to_le();
+ self.state.v3 ^= elem;
+ Sip13Rounds::c_rounds(&mut self.state);
+ self.state.v0 ^= elem;
+ processed += ELEM_SIZE;
+ }
- for i in 0..last {
- let elem = self.buf.get_unchecked(i).assume_init().to_le();
- self.state.v3 ^= elem;
- Sip13Rounds::c_rounds(&mut self.state);
- self.state.v0 ^= elem;
- }
+ // Copy remaining input into start of buffer.
+ let src = msg.as_ptr().add(processed);
+ let dst = self.buf.as_mut_ptr() as *mut u8;
+ copy_nonoverlapping_small(src, dst, extra_bytes_left);
- // Process the remaining element-sized chunks of input.
- let mut processed = needed_in_elem;
- let input_left = length - processed;
- let elems_left = input_left / ELEM_SIZE;
- let extra_bytes_left = input_left % ELEM_SIZE;
-
- for _ in 0..elems_left {
- let elem = (msg.as_ptr().add(processed) as *const u64).read_unaligned().to_le();
- self.state.v3 ^= elem;
- Sip13Rounds::c_rounds(&mut self.state);
- self.state.v0 ^= elem;
- processed += ELEM_SIZE;
+ self.nbuf = extra_bytes_left;
+ self.processed += nbuf + processed;
}
-
- // Copy remaining input into start of buffer.
- let src = msg.as_ptr().add(processed);
- let dst = self.buf.as_mut_ptr() as *mut u8;
- copy_nonoverlapping_small(src, dst, extra_bytes_left);
-
- self.nbuf = extra_bytes_left;
- self.processed += nbuf + processed;
}
#[inline]
diff --git a/compiler/rustc_data_structures/src/sso/map.rs b/compiler/rustc_data_structures/src/sso/map.rs
index 89b8c852649..99581ed2375 100644
--- a/compiler/rustc_data_structures/src/sso/map.rs
+++ b/compiler/rustc_data_structures/src/sso/map.rs
@@ -256,12 +256,9 @@ impl<K: Eq + Hash, V> SsoHashMap<K, V> {
pub fn remove(&mut self, key: &K) -> Option<V> {
match self {
SsoHashMap::Array(array) => {
- if let Some(index) = array.iter().position(|(k, _v)| k == key) {
- Some(array.swap_remove(index).1)
- } else {
- None
- }
+ array.iter().position(|(k, _v)| k == key).map(|index| array.swap_remove(index).1)
}
+
SsoHashMap::Map(map) => map.remove(key),
}
}
diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs
index 3ed1de1bc3c..b2bd0bfe714 100644
--- a/compiler/rustc_data_structures/src/stable_hasher.rs
+++ b/compiler/rustc_data_structures/src/stable_hasher.rs
@@ -2,6 +2,7 @@ use crate::sip128::SipHasher128;
use rustc_index::bit_set;
use rustc_index::vec;
use smallvec::SmallVec;
+use std::fmt;
use std::hash::{BuildHasher, Hash, Hasher};
use std::marker::PhantomData;
use std::mem;
@@ -9,6 +10,8 @@ use std::mem;
#[cfg(test)]
mod tests;
+pub use crate::hashes::{Hash128, Hash64};
+
/// When hashing something that ends up affecting properties like symbol names,
/// we want these symbol names to be calculated independently of other factors
/// like what architecture you're compiling *from*.
@@ -20,8 +23,8 @@ pub struct StableHasher {
state: SipHasher128,
}
-impl ::std::fmt::Debug for StableHasher {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+impl fmt::Debug for StableHasher {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self.state)
}
}
@@ -42,21 +45,6 @@ impl StableHasher {
}
}
-impl StableHasherResult for u128 {
- #[inline]
- fn finish(hasher: StableHasher) -> Self {
- let (_0, _1) = hasher.finalize();
- u128::from(_0) | (u128::from(_1) << 64)
- }
-}
-
-impl StableHasherResult for u64 {
- #[inline]
- fn finish(hasher: StableHasher) -> Self {
- hasher.finalize().0
- }
-}
-
impl StableHasher {
#[inline]
pub fn finalize(self) -> (u64, u64) {
@@ -107,7 +95,8 @@ impl Hasher for StableHasher {
#[inline]
fn write_u128(&mut self, i: u128) {
- self.state.write(&i.to_le_bytes());
+ self.write_u64(i as u64);
+ self.write_u64((i >> 64) as u64);
}
#[inline]
@@ -286,6 +275,9 @@ impl_stable_traits_for_trivial_type!(i128);
impl_stable_traits_for_trivial_type!(char);
impl_stable_traits_for_trivial_type!(());
+impl_stable_traits_for_trivial_type!(Hash64);
+impl_stable_traits_for_trivial_type!(Hash128);
+
impl<CTX> HashStable<CTX> for ! {
fn hash_stable(&self, _ctx: &mut CTX, _hasher: &mut StableHasher) {
unreachable!()
@@ -668,7 +660,7 @@ fn stable_hash_reduce<HCX, I, C, F>(
.map(|value| {
let mut hasher = StableHasher::new();
hash_function(&mut hasher, hcx, value);
- hasher.finish::<u128>()
+ hasher.finish::<Hash128>()
})
.reduce(|accum, value| accum.wrapping_add(value));
hash.hash_stable(hcx, hasher);
diff --git a/compiler/rustc_data_structures/src/stable_hasher/tests.rs b/compiler/rustc_data_structures/src/stable_hasher/tests.rs
index a98b1bc3626..c8921f6a778 100644
--- a/compiler/rustc_data_structures/src/stable_hasher/tests.rs
+++ b/compiler/rustc_data_structures/src/stable_hasher/tests.rs
@@ -72,7 +72,7 @@ fn test_hash_isize() {
assert_eq!(h.finalize(), expected);
}
-fn hash<T: HashStable<()>>(t: &T) -> u128 {
+fn hash<T: HashStable<()>>(t: &T) -> Hash128 {
let mut h = StableHasher::new();
let ctx = &mut ();
t.hash_stable(ctx, &mut h);
diff --git a/compiler/rustc_data_structures/src/svh.rs b/compiler/rustc_data_structures/src/svh.rs
index 61654b9e8f5..a3d2724fcdb 100644
--- a/compiler/rustc_data_structures/src/svh.rs
+++ b/compiler/rustc_data_structures/src/svh.rs
@@ -5,40 +5,30 @@
//! mismatches where we have two versions of the same crate that were
//! compiled from distinct sources.
-use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
+use crate::fingerprint::Fingerprint;
use std::fmt;
-use std::hash::{Hash, Hasher};
use crate::stable_hasher;
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug, Encodable, Decodable, Hash)]
pub struct Svh {
- hash: u64,
+ hash: Fingerprint,
}
impl Svh {
/// Creates a new `Svh` given the hash. If you actually want to
/// compute the SVH from some HIR, you want the `calculate_svh`
/// function found in `rustc_incremental`.
- pub fn new(hash: u64) -> Svh {
+ pub fn new(hash: Fingerprint) -> Svh {
Svh { hash }
}
pub fn as_u64(&self) -> u64 {
- self.hash
+ self.hash.to_smaller_hash().as_u64()
}
pub fn to_string(&self) -> String {
- format!("{:016x}", self.hash)
- }
-}
-
-impl Hash for Svh {
- fn hash<H>(&self, state: &mut H)
- where
- H: Hasher,
- {
- self.hash.to_le().hash(state);
+ format!("{:016x}", self.hash.to_smaller_hash())
}
}
@@ -48,18 +38,6 @@ impl fmt::Display for Svh {
}
}
-impl<S: Encoder> Encodable<S> for Svh {
- fn encode(&self, s: &mut S) {
- s.emit_u64(self.as_u64().to_le());
- }
-}
-
-impl<D: Decoder> Decodable<D> for Svh {
- fn decode(d: &mut D) -> Svh {
- Svh::new(u64::from_le(d.read_u64()))
- }
-}
-
impl<T> stable_hasher::HashStable<T> for Svh {
#[inline]
fn hash_stable(&self, ctx: &mut T, hasher: &mut stable_hasher::StableHasher) {
diff --git a/compiler/rustc_data_structures/src/tagged_ptr.rs b/compiler/rustc_data_structures/src/tagged_ptr.rs
index 651bc556c98..8568aac67c0 100644
--- a/compiler/rustc_data_structures/src/tagged_ptr.rs
+++ b/compiler/rustc_data_structures/src/tagged_ptr.rs
@@ -3,166 +3,262 @@
//! In order to utilize the pointer packing, you must have two types: a pointer,
//! and a tag.
//!
-//! The pointer must implement the `Pointer` trait, with the primary requirement
-//! being conversion to and from a usize. Note that the pointer must be
-//! dereferenceable, so raw pointers generally cannot implement the `Pointer`
-//! trait. This implies that the pointer must also be nonzero.
+//! The pointer must implement the [`Pointer`] trait, with the primary
+//! requirement being convertible to and from a raw pointer. Note that the
+//! pointer must be dereferenceable, so raw pointers generally cannot implement
+//! the [`Pointer`] trait. This implies that the pointer must also be non-null.
//!
-//! Many common pointer types already implement the `Pointer` trait.
+//! Many common pointer types already implement the [`Pointer`] trait.
//!
-//! The tag must implement the `Tag` trait. We assert that the tag and `Pointer`
-//! are compatible at compile time.
+//! The tag must implement the [`Tag`] trait.
+//!
+//! We assert that the tag and the [`Pointer`] types are compatible at compile
+//! time.
-use std::mem::ManuallyDrop;
use std::ops::Deref;
+use std::ptr::NonNull;
use std::rc::Rc;
use std::sync::Arc;
+use crate::aligned::Aligned;
+
mod copy;
mod drop;
pub use copy::CopyTaggedPtr;
pub use drop::TaggedPtr;
-/// This describes the pointer type encapsulated by TaggedPtr.
+/// This describes the pointer type encapsulated by [`TaggedPtr`] and
+/// [`CopyTaggedPtr`].
///
/// # Safety
///
-/// The usize returned from `into_usize` must be a valid, dereferenceable,
-/// pointer to `<Self as Deref>::Target`. Note that pointers to `Pointee` must
-/// be thin, even though `Pointee` may not be sized.
+/// The pointer returned from [`into_ptr`] must be a [valid], pointer to
+/// [`<Self as Deref>::Target`].
///
-/// Note that the returned pointer from `into_usize` should be castable to `&mut
-/// <Self as Deref>::Target` if `Pointer: DerefMut`.
+/// Note that if `Self` implements [`DerefMut`] the pointer returned from
+/// [`into_ptr`] must be valid for writes (and thus calling [`NonNull::as_mut`]
+/// on it must be safe).
///
-/// The BITS constant must be correct. At least `BITS` bits, least-significant,
-/// must be zero on all returned pointers from `into_usize`.
+/// The [`BITS`] constant must be correct. [`BITS`] least-significant bits,
+/// must be zero on all pointers returned from [`into_ptr`].
///
-/// For example, if the alignment of `Pointee` is 2, then `BITS` should be 1.
+/// For example, if the alignment of [`Self::Target`] is 2, then `BITS` should be 1.
+///
+/// [`BITS`]: Pointer::BITS
+/// [`into_ptr`]: Pointer::into_ptr
+/// [valid]: std::ptr#safety
+/// [`<Self as Deref>::Target`]: Deref::Target
+/// [`Self::Target`]: Deref::Target
+/// [`DerefMut`]: std::ops::DerefMut
pub unsafe trait Pointer: Deref {
+ /// Number of unused (always zero) **least-significant bits** in this
+ /// pointer, usually related to the pointees alignment.
+ ///
+ /// For example if [`BITS`] = `2`, then given `ptr = Self::into_ptr(..)`,
+ /// `ptr.addr() & 0b11 == 0` must be true.
+ ///
/// Most likely the value you want to use here is the following, unless
- /// your Pointee type is unsized (e.g., `ty::List<T>` in rustc) in which
- /// case you'll need to manually figure out what the right type to pass to
- /// align_of is.
+ /// your [`Self::Target`] type is unsized (e.g., `ty::List<T>` in rustc)
+ /// or your pointer is over/under aligned, in which case you'll need to
+ /// manually figure out what the right type to pass to [`bits_for`] is, or
+ /// what the value to set here.
///
- /// ```ignore UNSOLVED (what to do about the Self)
+ /// ```rust
/// # use std::ops::Deref;
- /// std::mem::align_of::<<Self as Deref>::Target>().trailing_zeros() as usize;
+ /// # use rustc_data_structures::tagged_ptr::bits_for;
+ /// # struct T;
+ /// # impl Deref for T { type Target = u8; fn deref(&self) -> &u8 { &0 } }
+ /// # impl T {
+ /// const BITS: u32 = bits_for::<<Self as Deref>::Target>();
+ /// # }
/// ```
- const BITS: usize;
- fn into_usize(self) -> usize;
+ ///
+ /// [`BITS`]: Pointer::BITS
+ /// [`Self::Target`]: Deref::Target
+ const BITS: u32;
- /// # Safety
+ /// Turns this pointer into a raw, non-null pointer.
+ ///
+ /// The inverse of this function is [`from_ptr`].
///
- /// The passed `ptr` must be returned from `into_usize`.
+ /// This function guarantees that the least-significant [`Self::BITS`] bits
+ /// are zero.
///
- /// This acts as `ptr::read` semantically, it should not be called more than
- /// once on non-`Copy` `Pointer`s.
- unsafe fn from_usize(ptr: usize) -> Self;
+ /// [`from_ptr`]: Pointer::from_ptr
+ /// [`Self::BITS`]: Pointer::BITS
+ fn into_ptr(self) -> NonNull<Self::Target>;
- /// This provides a reference to the `Pointer` itself, rather than the
- /// `Deref::Target`. It is used for cases where we want to call methods that
- /// may be implement differently for the Pointer than the Pointee (e.g.,
- /// `Rc::clone` vs cloning the inner value).
+ /// Re-creates the original pointer, from a raw pointer returned by [`into_ptr`].
///
/// # Safety
///
- /// The passed `ptr` must be returned from `into_usize`.
- unsafe fn with_ref<R, F: FnOnce(&Self) -> R>(ptr: usize, f: F) -> R;
+ /// The passed `ptr` must be returned from [`into_ptr`].
+ ///
+ /// This acts as [`ptr::read::<Self>()`] semantically, it should not be called more than
+ /// once on non-[`Copy`] `Pointer`s.
+ ///
+ /// [`into_ptr`]: Pointer::into_ptr
+ /// [`ptr::read::<Self>()`]: std::ptr::read
+ unsafe fn from_ptr(ptr: NonNull<Self::Target>) -> Self;
}
-/// This describes tags that the `TaggedPtr` struct can hold.
+/// This describes tags that the [`TaggedPtr`] struct can hold.
///
/// # Safety
///
-/// The BITS constant must be correct.
+/// The [`BITS`] constant must be correct.
+///
+/// No more than [`BITS`] least-significant bits may be set in the returned usize.
///
-/// No more than `BITS` least significant bits may be set in the returned usize.
+/// [`BITS`]: Tag::BITS
pub unsafe trait Tag: Copy {
- const BITS: usize;
+ /// Number of least-significant bits in the return value of [`into_usize`]
+ /// which may be non-zero. In other words this is the bit width of the
+ /// value.
+ ///
+ /// [`into_usize`]: Tag::into_usize
+ const BITS: u32;
+ /// Turns this tag into an integer.
+ ///
+ /// The inverse of this function is [`from_usize`].
+ ///
+ /// This function guarantees that only the least-significant [`Self::BITS`]
+ /// bits can be non-zero.
+ ///
+ /// [`from_usize`]: Tag::from_usize
+ /// [`Self::BITS`]: Tag::BITS
fn into_usize(self) -> usize;
+ /// Re-creates the tag from the integer returned by [`into_usize`].
+ ///
/// # Safety
///
- /// The passed `tag` must be returned from `into_usize`.
+ /// The passed `tag` must be returned from [`into_usize`].
+ ///
+ /// [`into_usize`]: Tag::into_usize
unsafe fn from_usize(tag: usize) -> Self;
}
-unsafe impl<T> Pointer for Box<T> {
- const BITS: usize = std::mem::align_of::<T>().trailing_zeros() as usize;
+unsafe impl<T: ?Sized + Aligned> Pointer for Box<T> {
+ const BITS: u32 = bits_for::<Self::Target>();
+
#[inline]
- fn into_usize(self) -> usize {
- Box::into_raw(self) as usize
+ fn into_ptr(self) -> NonNull<T> {
+ // Safety: pointers from `Box::into_raw` are valid & non-null
+ unsafe { NonNull::new_unchecked(Box::into_raw(self)) }
}
+
#[inline]
- unsafe fn from_usize(ptr: usize) -> Self {
- Box::from_raw(ptr as *mut T)
- }
- unsafe fn with_ref<R, F: FnOnce(&Self) -> R>(ptr: usize, f: F) -> R {
- let raw = ManuallyDrop::new(Self::from_usize(ptr));
- f(&raw)
+ unsafe fn from_ptr(ptr: NonNull<T>) -> Self {
+ // Safety: `ptr` comes from `into_ptr` which calls `Box::into_raw`
+ unsafe { Box::from_raw(ptr.as_ptr()) }
}
}
-unsafe impl<T> Pointer for Rc<T> {
- const BITS: usize = std::mem::align_of::<T>().trailing_zeros() as usize;
+unsafe impl<T: ?Sized + Aligned> Pointer for Rc<T> {
+ const BITS: u32 = bits_for::<Self::Target>();
+
#[inline]
- fn into_usize(self) -> usize {
- Rc::into_raw(self) as usize
+ fn into_ptr(self) -> NonNull<T> {
+ // Safety: pointers from `Rc::into_raw` are valid & non-null
+ unsafe { NonNull::new_unchecked(Rc::into_raw(self).cast_mut()) }
+ }
+
+ #[inline]
+ unsafe fn from_ptr(ptr: NonNull<T>) -> Self {
+ // Safety: `ptr` comes from `into_ptr` which calls `Rc::into_raw`
+ unsafe { Rc::from_raw(ptr.as_ptr()) }
}
+}
+
+unsafe impl<T: ?Sized + Aligned> Pointer for Arc<T> {
+ const BITS: u32 = bits_for::<Self::Target>();
+
#[inline]
- unsafe fn from_usize(ptr: usize) -> Self {
- Rc::from_raw(ptr as *const T)
+ fn into_ptr(self) -> NonNull<T> {
+ // Safety: pointers from `Arc::into_raw` are valid & non-null
+ unsafe { NonNull::new_unchecked(Arc::into_raw(self).cast_mut()) }
}
- unsafe fn with_ref<R, F: FnOnce(&Self) -> R>(ptr: usize, f: F) -> R {
- let raw = ManuallyDrop::new(Self::from_usize(ptr));
- f(&raw)
+
+ #[inline]
+ unsafe fn from_ptr(ptr: NonNull<T>) -> Self {
+ // Safety: `ptr` comes from `into_ptr` which calls `Arc::into_raw`
+ unsafe { Arc::from_raw(ptr.as_ptr()) }
}
}
-unsafe impl<T> Pointer for Arc<T> {
- const BITS: usize = std::mem::align_of::<T>().trailing_zeros() as usize;
+unsafe impl<'a, T: 'a + ?Sized + Aligned> Pointer for &'a T {
+ const BITS: u32 = bits_for::<Self::Target>();
+
#[inline]
- fn into_usize(self) -> usize {
- Arc::into_raw(self) as usize
+ fn into_ptr(self) -> NonNull<T> {
+ NonNull::from(self)
}
+
#[inline]
- unsafe fn from_usize(ptr: usize) -> Self {
- Arc::from_raw(ptr as *const T)
- }
- unsafe fn with_ref<R, F: FnOnce(&Self) -> R>(ptr: usize, f: F) -> R {
- let raw = ManuallyDrop::new(Self::from_usize(ptr));
- f(&raw)
+ unsafe fn from_ptr(ptr: NonNull<T>) -> Self {
+ // Safety:
+ // `ptr` comes from `into_ptr` which gets the pointer from a reference
+ unsafe { ptr.as_ref() }
}
}
-unsafe impl<'a, T: 'a> Pointer for &'a T {
- const BITS: usize = std::mem::align_of::<T>().trailing_zeros() as usize;
+unsafe impl<'a, T: 'a + ?Sized + Aligned> Pointer for &'a mut T {
+ const BITS: u32 = bits_for::<Self::Target>();
+
#[inline]
- fn into_usize(self) -> usize {
- self as *const T as usize
+ fn into_ptr(self) -> NonNull<T> {
+ NonNull::from(self)
}
+
#[inline]
- unsafe fn from_usize(ptr: usize) -> Self {
- &*(ptr as *const T)
- }
- unsafe fn with_ref<R, F: FnOnce(&Self) -> R>(ptr: usize, f: F) -> R {
- f(&*(&ptr as *const usize as *const Self))
+ unsafe fn from_ptr(mut ptr: NonNull<T>) -> Self {
+ // Safety:
+ // `ptr` comes from `into_ptr` which gets the pointer from a reference
+ unsafe { ptr.as_mut() }
}
}
-unsafe impl<'a, T: 'a> Pointer for &'a mut T {
- const BITS: usize = std::mem::align_of::<T>().trailing_zeros() as usize;
- #[inline]
+/// Returns the number of bits available for use for tags in a pointer to `T`
+/// (this is based on `T`'s alignment).
+pub const fn bits_for<T: ?Sized + Aligned>() -> u32 {
+ crate::aligned::align_of::<T>().as_nonzero().trailing_zeros()
+}
+
+/// A tag type used in [`CopyTaggedPtr`] and [`TaggedPtr`] tests.
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+#[cfg(test)]
+enum Tag2 {
+ B00 = 0b00,
+ B01 = 0b01,
+ B10 = 0b10,
+ B11 = 0b11,
+}
+
+#[cfg(test)]
+unsafe impl Tag for Tag2 {
+ const BITS: u32 = 2;
+
fn into_usize(self) -> usize {
- self as *mut T as usize
+ self as _
}
- #[inline]
- unsafe fn from_usize(ptr: usize) -> Self {
- &mut *(ptr as *mut T)
+
+ unsafe fn from_usize(tag: usize) -> Self {
+ match tag {
+ 0b00 => Tag2::B00,
+ 0b01 => Tag2::B01,
+ 0b10 => Tag2::B10,
+ 0b11 => Tag2::B11,
+ _ => unreachable!(),
+ }
}
- unsafe fn with_ref<R, F: FnOnce(&Self) -> R>(ptr: usize, f: F) -> R {
- f(&*(&ptr as *const usize as *const Self))
+}
+
+#[cfg(test)]
+impl<HCX> crate::stable_hasher::HashStable<HCX> for Tag2 {
+ fn hash_stable(&self, hcx: &mut HCX, hasher: &mut crate::stable_hasher::StableHasher) {
+ (*self as u8).hash_stable(hcx, hasher);
}
}
diff --git a/compiler/rustc_data_structures/src/tagged_ptr/copy.rs b/compiler/rustc_data_structures/src/tagged_ptr/copy.rs
index e1d3e0bd35a..691e92f196a 100644
--- a/compiler/rustc_data_structures/src/tagged_ptr/copy.rs
+++ b/compiler/rustc_data_structures/src/tagged_ptr/copy.rs
@@ -1,78 +1,92 @@
use super::{Pointer, Tag};
use crate::stable_hasher::{HashStable, StableHasher};
use std::fmt;
+use std::hash::{Hash, Hasher};
use std::marker::PhantomData;
+use std::mem::ManuallyDrop;
use std::num::NonZeroUsize;
+use std::ops::{Deref, DerefMut};
+use std::ptr::NonNull;
-/// A `Copy` TaggedPtr.
+/// A [`Copy`] tagged pointer.
///
-/// You should use this instead of the `TaggedPtr` type in all cases where
-/// `P: Copy`.
+/// This is essentially `{ pointer: P, tag: T }` packed in a single pointer.
+///
+/// You should use this instead of the [`TaggedPtr`] type in all cases where
+/// `P` implements [`Copy`].
///
/// If `COMPARE_PACKED` is true, then the pointers will be compared and hashed without
-/// unpacking. Otherwise we don't implement PartialEq/Eq/Hash; if you want that,
-/// wrap the TaggedPtr.
+/// unpacking. Otherwise we don't implement [`PartialEq`], [`Eq`] and [`Hash`];
+/// if you want that, wrap the [`CopyTaggedPtr`].
+///
+/// [`TaggedPtr`]: crate::tagged_ptr::TaggedPtr
pub struct CopyTaggedPtr<P, T, const COMPARE_PACKED: bool>
where
P: Pointer,
T: Tag,
{
- packed: NonZeroUsize,
- data: PhantomData<(P, T)>,
-}
-
-impl<P, T, const COMPARE_PACKED: bool> Copy for CopyTaggedPtr<P, T, COMPARE_PACKED>
-where
- P: Pointer,
- T: Tag,
- P: Copy,
-{
-}
-
-impl<P, T, const COMPARE_PACKED: bool> Clone for CopyTaggedPtr<P, T, COMPARE_PACKED>
-where
- P: Pointer,
- T: Tag,
- P: Copy,
-{
- fn clone(&self) -> Self {
- *self
- }
+ /// This is semantically a pair of `pointer: P` and `tag: T` fields,
+ /// however we pack them in a single pointer, to save space.
+ ///
+ /// We pack the tag into the **most**-significant bits of the pointer to
+ /// ease retrieval of the value. A left shift is a multiplication and
+ /// those are embeddable in instruction encoding, for example:
+ ///
+ /// ```asm
+ /// // (<https://godbolt.org/z/jqcYPWEr3>)
+ /// example::shift_read3:
+ /// mov eax, dword ptr [8*rdi]
+ /// ret
+ ///
+ /// example::mask_read3:
+ /// and rdi, -8
+ /// mov eax, dword ptr [rdi]
+ /// ret
+ /// ```
+ ///
+ /// This is ASM outputted by rustc for reads of values behind tagged
+ /// pointers for different approaches of tagging:
+ /// - `shift_read3` uses `<< 3` (the tag is in the most-significant bits)
+ /// - `mask_read3` uses `& !0b111` (the tag is in the least-significant bits)
+ ///
+ /// The shift approach thus produces less instructions and is likely faster
+ /// (see <https://godbolt.org/z/Y913sMdWb>).
+ ///
+ /// Encoding diagram:
+ /// ```text
+ /// [ packed.addr ]
+ /// [ tag ] [ pointer.addr >> T::BITS ] <-- usize::BITS - T::BITS bits
+ /// ^
+ /// |
+ /// T::BITS bits
+ /// ```
+ ///
+ /// The tag can be retrieved by `packed.addr() >> T::BITS` and the pointer
+ /// can be retrieved by `packed.map_addr(|addr| addr << T::BITS)`.
+ packed: NonNull<P::Target>,
+ tag_ghost: PhantomData<T>,
}
-// We pack the tag into the *upper* bits of the pointer to ease retrieval of the
-// value; a left shift is a multiplication and those are embeddable in
-// instruction encoding.
-impl<P, T, const COMPARE_PACKED: bool> CopyTaggedPtr<P, T, COMPARE_PACKED>
+// Note that even though `CopyTaggedPtr` is only really expected to work with
+// `P: Copy`, can't add `P: Copy` bound, because `CopyTaggedPtr` is used in the
+// `TaggedPtr`'s implementation.
+impl<P, T, const CP: bool> CopyTaggedPtr<P, T, CP>
where
P: Pointer,
T: Tag,
{
- const TAG_BIT_SHIFT: usize = usize::BITS as usize - T::BITS;
- const ASSERTION: () = {
- assert!(T::BITS <= P::BITS);
- // Used for the transmute_copy's below
- assert!(std::mem::size_of::<&P::Target>() == std::mem::size_of::<usize>());
- };
-
+ /// Tags `pointer` with `tag`.
+ ///
+ /// Note that this leaks `pointer`: it won't be dropped when
+ /// `CopyTaggedPtr` is dropped. If you have a pointer with a significant
+ /// drop, use [`TaggedPtr`] instead.
+ ///
+ /// [`TaggedPtr`]: crate::tagged_ptr::TaggedPtr
pub fn new(pointer: P, tag: T) -> Self {
- // Trigger assert!
- let () = Self::ASSERTION;
- let packed_tag = tag.into_usize() << Self::TAG_BIT_SHIFT;
-
- Self {
- // SAFETY: We know that the pointer is non-null, as it must be
- // dereferenceable per `Pointer` safety contract.
- packed: unsafe {
- NonZeroUsize::new_unchecked((P::into_usize(pointer) >> T::BITS) | packed_tag)
- },
- data: PhantomData,
- }
+ Self { packed: Self::pack(P::into_ptr(pointer), tag), tag_ghost: PhantomData }
}
- pub(super) fn pointer_raw(&self) -> usize {
- self.packed.get() << T::BITS
- }
+ /// Retrieves the pointer.
pub fn pointer(self) -> P
where
P: Copy,
@@ -81,66 +95,138 @@ where
//
// Note that this isn't going to double-drop or anything because we have
// P: Copy
- unsafe { P::from_usize(self.pointer_raw()) }
- }
- pub fn pointer_ref(&self) -> &P::Target {
- // SAFETY: pointer_raw returns the original pointer
- unsafe { std::mem::transmute_copy(&self.pointer_raw()) }
- }
- pub fn pointer_mut(&mut self) -> &mut P::Target
- where
- P: std::ops::DerefMut,
- {
- // SAFETY: pointer_raw returns the original pointer
- unsafe { std::mem::transmute_copy(&self.pointer_raw()) }
+ unsafe { P::from_ptr(self.pointer_raw()) }
}
+
+ /// Retrieves the tag.
#[inline]
pub fn tag(&self) -> T {
- unsafe { T::from_usize(self.packed.get() >> Self::TAG_BIT_SHIFT) }
+ // Unpack the tag, according to the `self.packed` encoding scheme
+ let tag = self.packed.addr().get() >> Self::TAG_BIT_SHIFT;
+
+ // Safety:
+ // The shift retrieves the original value from `T::into_usize`,
+ // satisfying `T::from_usize`'s preconditions.
+ unsafe { T::from_usize(tag) }
}
+
+ /// Sets the tag to a new value.
#[inline]
pub fn set_tag(&mut self, tag: T) {
- let mut packed = self.packed.get();
- let new_tag = T::into_usize(tag) << Self::TAG_BIT_SHIFT;
- let tag_mask = (1 << T::BITS) - 1;
- packed &= !(tag_mask << Self::TAG_BIT_SHIFT);
- packed |= new_tag;
- self.packed = unsafe { NonZeroUsize::new_unchecked(packed) };
+ self.packed = Self::pack(self.pointer_raw(), tag);
+ }
+
+ const TAG_BIT_SHIFT: u32 = usize::BITS - T::BITS;
+ const ASSERTION: () = { assert!(T::BITS <= P::BITS) };
+
+ /// Pack pointer `ptr` that comes from [`P::into_ptr`] with a `tag`,
+ /// according to `self.packed` encoding scheme.
+ ///
+ /// [`P::into_ptr`]: Pointer::into_ptr
+ fn pack(ptr: NonNull<P::Target>, tag: T) -> NonNull<P::Target> {
+ // Trigger assert!
+ let () = Self::ASSERTION;
+
+ let packed_tag = tag.into_usize() << Self::TAG_BIT_SHIFT;
+
+ ptr.map_addr(|addr| {
+ // Safety:
+ // - The pointer is `NonNull` => it's address is `NonZeroUsize`
+ // - `P::BITS` least significant bits are always zero (`Pointer` contract)
+ // - `T::BITS <= P::BITS` (from `Self::ASSERTION`)
+ //
+ // Thus `addr >> T::BITS` is guaranteed to be non-zero.
+ //
+ // `{non_zero} | packed_tag` can't make the value zero.
+
+ let packed = (addr.get() >> T::BITS) | packed_tag;
+ unsafe { NonZeroUsize::new_unchecked(packed) }
+ })
+ }
+
+ /// Retrieves the original raw pointer from `self.packed`.
+ pub(super) fn pointer_raw(&self) -> NonNull<P::Target> {
+ self.packed.map_addr(|addr| unsafe { NonZeroUsize::new_unchecked(addr.get() << T::BITS) })
+ }
+
+ /// This provides a reference to the `P` pointer itself, rather than the
+ /// `Deref::Target`. It is used for cases where we want to call methods
+ /// that may be implement differently for the Pointer than the Pointee
+ /// (e.g., `Rc::clone` vs cloning the inner value).
+ pub(super) fn with_pointer_ref<R>(&self, f: impl FnOnce(&P) -> R) -> R {
+ // Safety:
+ // - `self.raw.pointer_raw()` is originally returned from `P::into_ptr`
+ // and as such is valid for `P::from_ptr`.
+ // - This also allows us to not care whatever `f` panics or not.
+ // - Even though we create a copy of the pointer, we store it inside
+ // `ManuallyDrop` and only access it by-ref, so we don't double-drop.
+ //
+ // Semantically this is just `f(&self.pointer)` (where `self.pointer`
+ // is non-packed original pointer).
+ //
+ // Note that even though `CopyTaggedPtr` is only really expected to
+ // work with `P: Copy`, we have to assume `P: ?Copy`, because
+ // `CopyTaggedPtr` is used in the `TaggedPtr`'s implementation.
+ let ptr = unsafe { ManuallyDrop::new(P::from_ptr(self.pointer_raw())) };
+ f(&ptr)
}
}
-impl<P, T, const COMPARE_PACKED: bool> std::ops::Deref for CopyTaggedPtr<P, T, COMPARE_PACKED>
+impl<P, T, const CP: bool> Copy for CopyTaggedPtr<P, T, CP>
+where
+ P: Pointer + Copy,
+ T: Tag,
+{
+}
+
+impl<P, T, const CP: bool> Clone for CopyTaggedPtr<P, T, CP>
+where
+ P: Pointer + Copy,
+ T: Tag,
+{
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
+impl<P, T, const CP: bool> Deref for CopyTaggedPtr<P, T, CP>
where
P: Pointer,
T: Tag,
{
type Target = P::Target;
+
fn deref(&self) -> &Self::Target {
- self.pointer_ref()
+ // Safety:
+ // `pointer_raw` returns the original pointer from `P::into_ptr` which,
+ // by the `Pointer`'s contract, must be valid.
+ unsafe { self.pointer_raw().as_ref() }
}
}
-impl<P, T, const COMPARE_PACKED: bool> std::ops::DerefMut for CopyTaggedPtr<P, T, COMPARE_PACKED>
+impl<P, T, const CP: bool> DerefMut for CopyTaggedPtr<P, T, CP>
where
- P: Pointer + std::ops::DerefMut,
+ P: Pointer + DerefMut,
T: Tag,
{
fn deref_mut(&mut self) -> &mut Self::Target {
- self.pointer_mut()
+ // Safety:
+ // `pointer_raw` returns the original pointer from `P::into_ptr` which,
+ // by the `Pointer`'s contract, must be valid for writes if
+ // `P: DerefMut`.
+ unsafe { self.pointer_raw().as_mut() }
}
}
-impl<P, T, const COMPARE_PACKED: bool> fmt::Debug for CopyTaggedPtr<P, T, COMPARE_PACKED>
+impl<P, T, const CP: bool> fmt::Debug for CopyTaggedPtr<P, T, CP>
where
- P: Pointer,
- P::Target: fmt::Debug,
+ P: Pointer + fmt::Debug,
T: Tag + fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("CopyTaggedPtr")
- .field("pointer", &self.pointer_ref())
- .field("tag", &self.tag())
- .finish()
+ self.with_pointer_ref(|ptr| {
+ f.debug_struct("CopyTaggedPtr").field("pointer", ptr).field("tag", &self.tag()).finish()
+ })
}
}
@@ -161,25 +247,73 @@ where
{
}
-impl<P, T> std::hash::Hash for CopyTaggedPtr<P, T, true>
+impl<P, T> Hash for CopyTaggedPtr<P, T, true>
where
P: Pointer,
T: Tag,
{
- fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+ fn hash<H: Hasher>(&self, state: &mut H) {
self.packed.hash(state);
}
}
-impl<P, T, HCX, const COMPARE_PACKED: bool> HashStable<HCX> for CopyTaggedPtr<P, T, COMPARE_PACKED>
+impl<P, T, HCX, const CP: bool> HashStable<HCX> for CopyTaggedPtr<P, T, CP>
where
P: Pointer + HashStable<HCX>,
T: Tag + HashStable<HCX>,
{
fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
- unsafe {
- Pointer::with_ref(self.pointer_raw(), |p: &P| p.hash_stable(hcx, hasher));
- }
+ self.with_pointer_ref(|ptr| ptr.hash_stable(hcx, hasher));
self.tag().hash_stable(hcx, hasher);
}
}
+
+// Safety:
+// `CopyTaggedPtr<P, T, ..>` is semantically just `{ ptr: P, tag: T }`, as such
+// it's ok to implement `Sync` as long as `P: Sync, T: Sync`
+unsafe impl<P, T, const CP: bool> Sync for CopyTaggedPtr<P, T, CP>
+where
+ P: Sync + Pointer,
+ T: Sync + Tag,
+{
+}
+
+// Safety:
+// `CopyTaggedPtr<P, T, ..>` is semantically just `{ ptr: P, tag: T }`, as such
+// it's ok to implement `Send` as long as `P: Send, T: Send`
+unsafe impl<P, T, const CP: bool> Send for CopyTaggedPtr<P, T, CP>
+where
+ P: Send + Pointer,
+ T: Send + Tag,
+{
+}
+
+/// Test that `new` does not compile if there is not enough alignment for the
+/// tag in the pointer.
+///
+/// ```compile_fail,E0080
+/// use rustc_data_structures::tagged_ptr::{CopyTaggedPtr, Tag};
+///
+/// #[derive(Copy, Clone, Debug, PartialEq, Eq)]
+/// enum Tag2 { B00 = 0b00, B01 = 0b01, B10 = 0b10, B11 = 0b11 };
+///
+/// unsafe impl Tag for Tag2 {
+/// const BITS: u32 = 2;
+///
+/// fn into_usize(self) -> usize { todo!() }
+/// unsafe fn from_usize(tag: usize) -> Self { todo!() }
+/// }
+///
+/// let value = 12u16;
+/// let reference = &value;
+/// let tag = Tag2::B01;
+///
+/// let _ptr = CopyTaggedPtr::<_, _, true>::new(reference, tag);
+/// ```
+// For some reason miri does not get the compile error
+// probably it `check`s instead of `build`ing?
+#[cfg(not(miri))]
+const _: () = ();
+
+#[cfg(test)]
+mod tests;
diff --git a/compiler/rustc_data_structures/src/tagged_ptr/copy/tests.rs b/compiler/rustc_data_structures/src/tagged_ptr/copy/tests.rs
new file mode 100644
index 00000000000..bfcc2e603de
--- /dev/null
+++ b/compiler/rustc_data_structures/src/tagged_ptr/copy/tests.rs
@@ -0,0 +1,50 @@
+use std::ptr;
+
+use crate::stable_hasher::{HashStable, StableHasher};
+use crate::tagged_ptr::{CopyTaggedPtr, Pointer, Tag, Tag2};
+
+#[test]
+fn smoke() {
+ let value = 12u32;
+ let reference = &value;
+ let tag = Tag2::B01;
+
+ let ptr = tag_ptr(reference, tag);
+
+ assert_eq!(ptr.tag(), tag);
+ assert_eq!(*ptr, 12);
+ assert!(ptr::eq(ptr.pointer(), reference));
+
+ let copy = ptr;
+
+ let mut ptr = ptr;
+ ptr.set_tag(Tag2::B00);
+ assert_eq!(ptr.tag(), Tag2::B00);
+
+ assert_eq!(copy.tag(), tag);
+ assert_eq!(*copy, 12);
+ assert!(ptr::eq(copy.pointer(), reference));
+}
+
+#[test]
+fn stable_hash_hashes_as_tuple() {
+ let hash_packed = {
+ let mut hasher = StableHasher::new();
+ tag_ptr(&12, Tag2::B11).hash_stable(&mut (), &mut hasher);
+
+ hasher.finalize()
+ };
+
+ let hash_tupled = {
+ let mut hasher = StableHasher::new();
+ (&12, Tag2::B11).hash_stable(&mut (), &mut hasher);
+ hasher.finalize()
+ };
+
+ assert_eq!(hash_packed, hash_tupled);
+}
+
+/// Helper to create tagged pointers without specifying `COMPARE_PACKED` if it does not matter.
+fn tag_ptr<P: Pointer, T: Tag>(ptr: P, tag: T) -> CopyTaggedPtr<P, T, true> {
+ CopyTaggedPtr::new(ptr, tag)
+}
diff --git a/compiler/rustc_data_structures/src/tagged_ptr/drop.rs b/compiler/rustc_data_structures/src/tagged_ptr/drop.rs
index b0315c93d93..d418c06b7eb 100644
--- a/compiler/rustc_data_structures/src/tagged_ptr/drop.rs
+++ b/compiler/rustc_data_structures/src/tagged_ptr/drop.rs
@@ -1,14 +1,21 @@
-use super::{Pointer, Tag};
-use crate::stable_hasher::{HashStable, StableHasher};
use std::fmt;
+use std::hash::{Hash, Hasher};
+use std::ops::{Deref, DerefMut};
use super::CopyTaggedPtr;
+use super::{Pointer, Tag};
+use crate::stable_hasher::{HashStable, StableHasher};
-/// A TaggedPtr implementing `Drop`.
+/// A tagged pointer that supports pointers that implement [`Drop`].
+///
+/// This is essentially `{ pointer: P, tag: T }` packed in a single pointer.
+///
+/// You should use [`CopyTaggedPtr`] instead of the this type in all cases
+/// where `P` implements [`Copy`].
///
/// If `COMPARE_PACKED` is true, then the pointers will be compared and hashed without
-/// unpacking. Otherwise we don't implement PartialEq/Eq/Hash; if you want that,
-/// wrap the TaggedPtr.
+/// unpacking. Otherwise we don't implement [`PartialEq`], [`Eq`] and [`Hash`];
+/// if you want that, wrap the [`TaggedPtr`].
pub struct TaggedPtr<P, T, const COMPARE_PACKED: bool>
where
P: Pointer,
@@ -17,58 +24,61 @@ where
raw: CopyTaggedPtr<P, T, COMPARE_PACKED>,
}
-impl<P, T, const COMPARE_PACKED: bool> Clone for TaggedPtr<P, T, COMPARE_PACKED>
-where
- P: Pointer + Clone,
- T: Tag,
-{
- fn clone(&self) -> Self {
- unsafe { Self::new(P::with_ref(self.raw.pointer_raw(), |p| p.clone()), self.raw.tag()) }
- }
-}
-
-// We pack the tag into the *upper* bits of the pointer to ease retrieval of the
-// value; a right shift is a multiplication and those are embeddable in
-// instruction encoding.
-impl<P, T, const COMPARE_PACKED: bool> TaggedPtr<P, T, COMPARE_PACKED>
+impl<P, T, const CP: bool> TaggedPtr<P, T, CP>
where
P: Pointer,
T: Tag,
{
+ /// Tags `pointer` with `tag`.
pub fn new(pointer: P, tag: T) -> Self {
TaggedPtr { raw: CopyTaggedPtr::new(pointer, tag) }
}
- pub fn pointer_ref(&self) -> &P::Target {
- self.raw.pointer_ref()
- }
+ /// Retrieves the tag.
pub fn tag(&self) -> T {
self.raw.tag()
}
+
+ /// Sets the tag to a new value.
+ pub fn set_tag(&mut self, tag: T) {
+ self.raw.set_tag(tag)
+ }
}
-impl<P, T, const COMPARE_PACKED: bool> std::ops::Deref for TaggedPtr<P, T, COMPARE_PACKED>
+impl<P, T, const CP: bool> Clone for TaggedPtr<P, T, CP>
+where
+ P: Pointer + Clone,
+ T: Tag,
+{
+ fn clone(&self) -> Self {
+ let ptr = self.raw.with_pointer_ref(P::clone);
+
+ Self::new(ptr, self.tag())
+ }
+}
+
+impl<P, T, const CP: bool> Deref for TaggedPtr<P, T, CP>
where
P: Pointer,
T: Tag,
{
type Target = P::Target;
fn deref(&self) -> &Self::Target {
- self.raw.pointer_ref()
+ self.raw.deref()
}
}
-impl<P, T, const COMPARE_PACKED: bool> std::ops::DerefMut for TaggedPtr<P, T, COMPARE_PACKED>
+impl<P, T, const CP: bool> DerefMut for TaggedPtr<P, T, CP>
where
- P: Pointer + std::ops::DerefMut,
+ P: Pointer + DerefMut,
T: Tag,
{
fn deref_mut(&mut self) -> &mut Self::Target {
- self.raw.pointer_mut()
+ self.raw.deref_mut()
}
}
-impl<P, T, const COMPARE_PACKED: bool> Drop for TaggedPtr<P, T, COMPARE_PACKED>
+impl<P, T, const CP: bool> Drop for TaggedPtr<P, T, CP>
where
P: Pointer,
T: Tag,
@@ -76,22 +86,20 @@ where
fn drop(&mut self) {
// No need to drop the tag, as it's Copy
unsafe {
- drop(P::from_usize(self.raw.pointer_raw()));
+ drop(P::from_ptr(self.raw.pointer_raw()));
}
}
}
-impl<P, T, const COMPARE_PACKED: bool> fmt::Debug for TaggedPtr<P, T, COMPARE_PACKED>
+impl<P, T, const CP: bool> fmt::Debug for TaggedPtr<P, T, CP>
where
- P: Pointer,
- P::Target: fmt::Debug,
+ P: Pointer + fmt::Debug,
T: Tag + fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("TaggedPtr")
- .field("pointer", &self.pointer_ref())
- .field("tag", &self.tag())
- .finish()
+ self.raw.with_pointer_ref(|ptr| {
+ f.debug_struct("TaggedPtr").field("pointer", ptr).field("tag", &self.tag()).finish()
+ })
}
}
@@ -112,17 +120,17 @@ where
{
}
-impl<P, T> std::hash::Hash for TaggedPtr<P, T, true>
+impl<P, T> Hash for TaggedPtr<P, T, true>
where
P: Pointer,
T: Tag,
{
- fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+ fn hash<H: Hasher>(&self, state: &mut H) {
self.raw.hash(state);
}
}
-impl<P, T, HCX, const COMPARE_PACKED: bool> HashStable<HCX> for TaggedPtr<P, T, COMPARE_PACKED>
+impl<P, T, HCX, const CP: bool> HashStable<HCX> for TaggedPtr<P, T, CP>
where
P: Pointer + HashStable<HCX>,
T: Tag + HashStable<HCX>,
@@ -131,3 +139,33 @@ where
self.raw.hash_stable(hcx, hasher);
}
}
+
+/// Test that `new` does not compile if there is not enough alignment for the
+/// tag in the pointer.
+///
+/// ```compile_fail,E0080
+/// use rustc_data_structures::tagged_ptr::{TaggedPtr, Tag};
+///
+/// #[derive(Copy, Clone, Debug, PartialEq, Eq)]
+/// enum Tag2 { B00 = 0b00, B01 = 0b01, B10 = 0b10, B11 = 0b11 };
+///
+/// unsafe impl Tag for Tag2 {
+/// const BITS: u32 = 2;
+///
+/// fn into_usize(self) -> usize { todo!() }
+/// unsafe fn from_usize(tag: usize) -> Self { todo!() }
+/// }
+///
+/// let value = 12u16;
+/// let reference = &value;
+/// let tag = Tag2::B01;
+///
+/// let _ptr = TaggedPtr::<_, _, true>::new(reference, tag);
+/// ```
+// For some reason miri does not get the compile error
+// probably it `check`s instead of `build`ing?
+#[cfg(not(miri))]
+const _: () = ();
+
+#[cfg(test)]
+mod tests;
diff --git a/compiler/rustc_data_structures/src/tagged_ptr/drop/tests.rs b/compiler/rustc_data_structures/src/tagged_ptr/drop/tests.rs
new file mode 100644
index 00000000000..2c17d678d3a
--- /dev/null
+++ b/compiler/rustc_data_structures/src/tagged_ptr/drop/tests.rs
@@ -0,0 +1,71 @@
+use std::{ptr, sync::Arc};
+
+use crate::tagged_ptr::{Pointer, Tag, Tag2, TaggedPtr};
+
+#[test]
+fn smoke() {
+ let value = 12u32;
+ let reference = &value;
+ let tag = Tag2::B01;
+
+ let ptr = tag_ptr(reference, tag);
+
+ assert_eq!(ptr.tag(), tag);
+ assert_eq!(*ptr, 12);
+
+ let clone = ptr.clone();
+ assert_eq!(clone.tag(), tag);
+ assert_eq!(*clone, 12);
+
+ let mut ptr = ptr;
+ ptr.set_tag(Tag2::B00);
+ assert_eq!(ptr.tag(), Tag2::B00);
+
+ assert_eq!(clone.tag(), tag);
+ assert_eq!(*clone, 12);
+ assert!(ptr::eq(&*ptr, &*clone))
+}
+
+#[test]
+fn boxed() {
+ let value = 12u32;
+ let boxed = Box::new(value);
+ let tag = Tag2::B01;
+
+ let ptr = tag_ptr(boxed, tag);
+
+ assert_eq!(ptr.tag(), tag);
+ assert_eq!(*ptr, 12);
+
+ let clone = ptr.clone();
+ assert_eq!(clone.tag(), tag);
+ assert_eq!(*clone, 12);
+
+ let mut ptr = ptr;
+ ptr.set_tag(Tag2::B00);
+ assert_eq!(ptr.tag(), Tag2::B00);
+
+ assert_eq!(clone.tag(), tag);
+ assert_eq!(*clone, 12);
+ assert!(!ptr::eq(&*ptr, &*clone))
+}
+
+#[test]
+fn arclones() {
+ let value = 12u32;
+ let arc = Arc::new(value);
+ let tag = Tag2::B01;
+
+ let ptr = tag_ptr(arc, tag);
+
+ assert_eq!(ptr.tag(), tag);
+ assert_eq!(*ptr, 12);
+
+ let clone = ptr.clone();
+ assert!(ptr::eq(&*ptr, &*clone))
+}
+
+/// Helper to create tagged pointers without specifying `COMPARE_PACKED` if it does not matter.
+fn tag_ptr<P: Pointer, T: Tag>(ptr: P, tag: T) -> TaggedPtr<P, T, true> {
+ TaggedPtr::new(ptr, tag)
+}
diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml
index 73a1f79a020..cc4c5a0cacd 100644
--- a/compiler/rustc_driver_impl/Cargo.toml
+++ b/compiler/rustc_driver_impl/Cargo.toml
@@ -18,6 +18,7 @@ rustc_const_eval = { path = "../rustc_const_eval" }
rustc_error_messages = { path = "../rustc_error_messages" }
rustc_expand = { path = "../rustc_expand" }
rustc_hir_typeck = { path = "../rustc_hir_typeck" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_incremental = { path = "../rustc_incremental" }
rustc_infer = { path = "../rustc_infer" }
rustc_mir_build = { path = "../rustc_mir_build" }
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index b9f0e756e65..1a80b4fc314 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -28,10 +28,10 @@ use rustc_errors::{
DiagnosticMessage, ErrorGuaranteed, PResult, SubdiagnosticMessage, TerminalUrl,
};
use rustc_feature::find_gated_cfg;
+use rustc_fluent_macro::fluent_messages;
use rustc_interface::util::{self, collect_crate_types, get_codegen_backend};
use rustc_interface::{interface, Queries};
use rustc_lint::LintStore;
-use rustc_macros::fluent_messages;
use rustc_metadata::locator;
use rustc_session::config::{nightly_options, CG_OPTIONS, Z_OPTIONS};
use rustc_session::config::{ErrorOutputType, Input, OutputType, PrintRequest, TrimmedDefPaths};
diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs
index 446c6832cb7..ee64b18d3f6 100644
--- a/compiler/rustc_driver_impl/src/pretty.rs
+++ b/compiler/rustc_driver_impl/src/pretty.rs
@@ -488,12 +488,7 @@ fn print_with_analysis(tcx: TyCtxt<'_>, ppm: PpMode) -> Result<(), ErrorGuarante
abort_on_err(rustc_hir_analysis::check_crate(tcx), tcx.sess);
debug!("pretty printing THIR tree");
for did in tcx.hir().body_owners() {
- let _ = writeln!(
- out,
- "{:?}:\n{}\n",
- did,
- tcx.thir_tree(ty::WithOptConstParam::unknown(did))
- );
+ let _ = writeln!(out, "{:?}:\n{}\n", did, tcx.thir_tree(did));
}
out
}
@@ -503,12 +498,7 @@ fn print_with_analysis(tcx: TyCtxt<'_>, ppm: PpMode) -> Result<(), ErrorGuarante
abort_on_err(rustc_hir_analysis::check_crate(tcx), tcx.sess);
debug!("pretty printing THIR flat");
for did in tcx.hir().body_owners() {
- let _ = writeln!(
- out,
- "{:?}:\n{}\n",
- did,
- tcx.thir_flat(ty::WithOptConstParam::unknown(did))
- );
+ let _ = writeln!(out, "{:?}:\n{}\n", did, tcx.thir_flat(did));
}
out
}
diff --git a/compiler/rustc_error_codes/src/error_codes/E0026.md b/compiler/rustc_error_codes/src/error_codes/E0026.md
index 72c575aabb6..f485112cca2 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0026.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0026.md
@@ -1,4 +1,4 @@
-A struct pattern attempted to extract a non-existent field from a struct.
+A struct pattern attempted to extract a nonexistent field from a struct.
Erroneous code example:
diff --git a/compiler/rustc_error_codes/src/error_codes/E0208.md b/compiler/rustc_error_codes/src/error_codes/E0208.md
index 1ae01106f20..c6db9b5d61b 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0208.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0208.md
@@ -32,7 +32,7 @@ error: [-, o]
This error is deliberately triggered with the `#[rustc_variance]` attribute
(`#![feature(rustc_attrs)]` must be enabled) and helps to show you the variance
of the type's generic parameters. You can read more about variance and
-subtyping in [this section of the Rustnomicon]. For a more in depth look at
+subtyping in [this section of the Rustonomicon]. For a more in depth look at
variance (including a more complete list of common variances) see
[this section of the Reference]. For information on how variance is implemented
in the compiler, see [this section of `rustc-dev-guide`].
@@ -41,6 +41,6 @@ This error can be easily fixed by removing the `#[rustc_variance]` attribute,
the compiler's suggestion to comment it out can be applied automatically with
`rustfix`.
-[this section of the Rustnomicon]: https://doc.rust-lang.org/nomicon/subtyping.html
+[this section of the Rustonomicon]: https://doc.rust-lang.org/nomicon/subtyping.html
[this section of the Reference]: https://doc.rust-lang.org/reference/subtyping.html#variance
[this section of `rustc-dev-guide`]: https://rustc-dev-guide.rust-lang.org/variance.html
diff --git a/compiler/rustc_error_codes/src/error_codes/E0311.md b/compiler/rustc_error_codes/src/error_codes/E0311.md
index 08159d3f469..c1104a88a76 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0311.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0311.md
@@ -29,7 +29,7 @@ If `no_restriction()` were to use `&T` instead of `&()` as an argument, the
compiler would have added an implied bound, causing this to compile.
This error can be resolved by explicitly naming the elided lifetime for `x` and
-then explicily requiring that the generic parameter `T` outlives that lifetime:
+then explicitly requiring that the generic parameter `T` outlives that lifetime:
```
fn no_restriction<'a, T: 'a>(x: &'a ()) -> &'a () {
diff --git a/compiler/rustc_error_codes/src/error_codes/E0457.md b/compiler/rustc_error_codes/src/error_codes/E0457.md
index 53d384d36c4..2c33d1e6a24 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0457.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0457.md
@@ -1,6 +1,6 @@
Plugin `..` only found in rlib format, but must be available in dylib format.
-Erroronous code example:
+Erroneous code example:
`rlib-plugin.rs`
```ignore (needs-linkage-with-other-tests)
diff --git a/compiler/rustc_error_codes/src/error_codes/E0576.md b/compiler/rustc_error_codes/src/error_codes/E0576.md
index 8eead4e7e3b..300a57a1985 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0576.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0576.md
@@ -10,7 +10,7 @@ trait Hello {
}
```
-In this example, we tried to use the non-existent associated type `You` of the
+In this example, we tried to use the nonexistent associated type `You` of the
`Hello` trait. To fix this error, use an existing associated type:
```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0609.md b/compiler/rustc_error_codes/src/error_codes/E0609.md
index a9db34f474e..0f5ac94e6d5 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0609.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0609.md
@@ -1,4 +1,4 @@
-Attempted to access a non-existent field in a struct.
+Attempted to access a nonexistent field in a struct.
Erroneous code example:
diff --git a/compiler/rustc_error_messages/Cargo.toml b/compiler/rustc_error_messages/Cargo.toml
index 27783d60be4..481c94266f2 100644
--- a/compiler/rustc_error_messages/Cargo.toml
+++ b/compiler/rustc_error_messages/Cargo.toml
@@ -11,6 +11,7 @@ fluent-syntax = "0.11"
intl-memoizer = "0.5.1"
rustc_baked_icu_data = { path = "../rustc_baked_icu_data" }
rustc_data_structures = { path = "../rustc_data_structures" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_serialize = { path = "../rustc_serialize" }
rustc_span = { path = "../rustc_span" }
rustc_macros = { path = "../rustc_macros" }
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs
index 6f319b96f2f..88d94c93bf5 100644
--- a/compiler/rustc_error_messages/src/lib.rs
+++ b/compiler/rustc_error_messages/src/lib.rs
@@ -12,7 +12,8 @@ use fluent_bundle::FluentResource;
use fluent_syntax::parser::ParserError;
use icu_provider_adapters::fallback::{LocaleFallbackProvider, LocaleFallbacker};
use rustc_data_structures::sync::Lrc;
-use rustc_macros::{fluent_messages, Decodable, Encodable};
+use rustc_fluent_macro::fluent_messages;
+use rustc_macros::{Decodable, Encodable};
use rustc_span::Span;
use std::borrow::Cow;
use std::error::Error;
diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml
index e1ead08ea66..46ace8eb2dd 100644
--- a/compiler/rustc_errors/Cargo.toml
+++ b/compiler/rustc_errors/Cargo.toml
@@ -10,6 +10,7 @@ tracing = "0.1"
rustc_ast = { path = "../rustc_ast" }
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
rustc_error_messages = { path = "../rustc_error_messages" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_serialize = { path = "../rustc_serialize" }
rustc_span = { path = "../rustc_span" }
rustc_macros = { path = "../rustc_macros" }
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index fe44799efdb..2498ae2b7bc 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -1336,6 +1336,7 @@ impl EmitterWriter {
// see?
for (text, style) in msg.iter() {
let text = self.translate_message(text, args).map_err(Report::new).unwrap();
+ let text = &normalize_whitespace(&text);
let lines = text.split('\n').collect::<Vec<_>>();
if lines.len() > 1 {
for (i, line) in lines.iter().enumerate() {
@@ -1980,7 +1981,7 @@ impl EmitterWriter {
}
if let DisplaySuggestion::Add = show_code_change && is_item_attribute {
// The suggestion adds an entire line of code, ending on a newline, so we'll also
- // print the *following* line, to provide context of what we're advicing people to
+ // print the *following* line, to provide context of what we're advising people to
// do. Otherwise you would only see contextless code that can be confused for
// already existing code, despite the colors and UI elements.
// We special case `#[derive(_)]\n` and other attribute suggestions, because those
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index d20b168904d..b65a636d770 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -31,15 +31,15 @@ use Level::*;
use emitter::{is_case_difference, Emitter, EmitterWriter};
use registry::Registry;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
-use rustc_data_structures::stable_hasher::StableHasher;
+use rustc_data_structures::stable_hasher::{Hash128, StableHasher};
use rustc_data_structures::sync::{self, Lock, Lrc};
use rustc_data_structures::AtomicRef;
pub use rustc_error_messages::{
fallback_fluent_bundle, fluent_bundle, DelayDm, DiagnosticMessage, FluentBundle,
LanguageIdentifier, LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagnosticMessage,
};
+use rustc_fluent_macro::fluent_messages;
pub use rustc_lint_defs::{pluralize, Applicability};
-use rustc_macros::fluent_messages;
use rustc_span::source_map::SourceMap;
pub use rustc_span::ErrorGuaranteed;
use rustc_span::{Loc, Span};
@@ -427,7 +427,7 @@ struct HandlerInner {
/// This set contains a hash of every diagnostic that has been emitted by
/// this handler. These hashes is used to avoid emitting the same error
/// twice.
- emitted_diagnostics: FxHashSet<u128>,
+ emitted_diagnostics: FxHashSet<Hash128>,
/// Stashed diagnostics emitted in one stage of the compiler that may be
/// stolen by other stages (e.g. to improve them and add more information).
diff --git a/compiler/rustc_expand/Cargo.toml b/compiler/rustc_expand/Cargo.toml
index c971714e05b..2dae0e3f53c 100644
--- a/compiler/rustc_expand/Cargo.toml
+++ b/compiler/rustc_expand/Cargo.toml
@@ -16,6 +16,7 @@ rustc_attr = { path = "../rustc_attr" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_feature = { path = "../rustc_feature" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_lexer = { path = "../rustc_lexer" }
rustc_lint_defs = { path = "../rustc_lint_defs" }
rustc_macros = { path = "../rustc_macros" }
diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs
index ced7531c3fe..83a5043b0aa 100644
--- a/compiler/rustc_expand/src/lib.rs
+++ b/compiler/rustc_expand/src/lib.rs
@@ -21,7 +21,7 @@ extern crate tracing;
extern crate proc_macro as pm;
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
-use rustc_macros::fluent_messages;
+use rustc_fluent_macro::fluent_messages;
mod placeholders;
mod proc_macro_server;
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index 5679cdcbbd0..3aeb2edb54c 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -341,7 +341,7 @@ pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>(
Success(named_matches) => {
debug!("Parsed arm successfully");
// The matcher was `Success(..)`ful.
- // Merge the gated spans from parsing the matcher with the pre-existing ones.
+ // Merge the gated spans from parsing the matcher with the preexisting ones.
sess.gated_spans.merge(gated_spans_snapshot);
return Ok((i, named_matches));
@@ -873,7 +873,7 @@ impl<'tt> FirstSets<'tt> {
}
}
-// Most `mbe::TokenTree`s are pre-existing in the matcher, but some are defined
+// Most `mbe::TokenTree`s are preexisting in the matcher, but some are defined
// implicitly, such as opening/closing delimiters and sequence repetition ops.
// This type encapsulates both kinds. It implements `Clone` while avoiding the
// need for `mbe::TokenTree` to implement `Clone`.
diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs
index 341ae18541b..1e7d07bc22d 100644
--- a/compiler/rustc_expand/src/proc_macro_server.rs
+++ b/compiler/rustc_expand/src/proc_macro_server.rs
@@ -18,7 +18,7 @@ use rustc_span::def_id::CrateNum;
use rustc_span::symbol::{self, sym, Symbol};
use rustc_span::{BytePos, FileName, Pos, SourceFile, Span};
use smallvec::{smallvec, SmallVec};
-use std::ops::Bound;
+use std::ops::{Bound, Range};
trait FromInternal<T> {
fn from_internal(x: T) -> Self;
@@ -634,6 +634,15 @@ impl server::Span for Rustc<'_, '_> {
span.source_callsite()
}
+ fn byte_range(&mut self, span: Self::Span) -> Range<usize> {
+ let source_map = self.sess().source_map();
+
+ let relative_start_pos = source_map.lookup_byte_offset(span.lo()).pos;
+ let relative_end_pos = source_map.lookup_byte_offset(span.hi()).pos;
+
+ Range { start: relative_start_pos.0 as usize, end: relative_end_pos.0 as usize }
+ }
+
fn start(&mut self, span: Self::Span) -> LineColumn {
let loc = self.sess().source_map().lookup_char_pos(span.lo());
LineColumn { line: loc.line, column: loc.col.to_usize() }
diff --git a/compiler/rustc_expand/src/tests.rs b/compiler/rustc_expand/src/tests.rs
index 480d95b77e9..8a5e09475ff 100644
--- a/compiler/rustc_expand/src/tests.rs
+++ b/compiler/rustc_expand/src/tests.rs
@@ -513,7 +513,7 @@ error: foo
}
#[test]
-fn non_overlaping() {
+fn non_overlapping() {
test_harness(
r#"
fn foo() {
@@ -552,7 +552,7 @@ error: foo
}
#[test]
-fn overlaping_start_and_end() {
+fn overlapping_start_and_end() {
test_harness(
r#"
fn foo() {
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index 568c289e2f7..c978d6472c8 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -141,7 +141,7 @@ declare_features! (
/// Allows using `#[on_unimplemented(..)]` on traits.
/// (Moved to `rustc_attrs`.)
(removed, on_unimplemented, "1.40.0", None, None, None),
- /// A way to temporarily opt out of opt in copy. This will *never* be accepted.
+ /// A way to temporarily opt out of opt-in copy. This will *never* be accepted.
(removed, opt_out_copy, "1.0.0", None, None, None),
/// Allows features specific to OIBIT (now called auto traits).
/// Renamed to `auto_traits`.
diff --git a/compiler/rustc_fluent_macro/Cargo.toml b/compiler/rustc_fluent_macro/Cargo.toml
new file mode 100644
index 00000000000..a45559af713
--- /dev/null
+++ b/compiler/rustc_fluent_macro/Cargo.toml
@@ -0,0 +1,17 @@
+[package]
+name = "rustc_fluent_macro"
+version = "0.1.0"
+edition = "2021"
+
+[lib]
+proc-macro = true
+
+[dependencies]
+annotate-snippets = "0.9"
+fluent-bundle = "0.15.2"
+fluent-syntax = "0.11"
+synstructure = "0.13.0"
+syn = { version = "2", features = ["full"] }
+proc-macro2 = "1"
+quote = "1"
+unic-langid = { version = "0.9.0", features = ["macros"] }
diff --git a/compiler/rustc_macros/src/diagnostics/fluent.rs b/compiler/rustc_fluent_macro/src/fluent.rs
index 607d51f5608..9dffc9a7645 100644
--- a/compiler/rustc_macros/src/diagnostics/fluent.rs
+++ b/compiler/rustc_fluent_macro/src/fluent.rs
@@ -68,7 +68,7 @@ fn failed(crate_name: &Ident) -> proc_macro::TokenStream {
.into()
}
-/// See [rustc_macros::fluent_messages].
+/// See [rustc_fluent_macro::fluent_messages].
pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let crate_name = std::env::var("CARGO_PKG_NAME")
// If `CARGO_PKG_NAME` is missing, then we're probably running in a test, so use
diff --git a/compiler/rustc_fluent_macro/src/lib.rs b/compiler/rustc_fluent_macro/src/lib.rs
new file mode 100644
index 00000000000..a01643cd67d
--- /dev/null
+++ b/compiler/rustc_fluent_macro/src/lib.rs
@@ -0,0 +1,64 @@
+#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
+#![feature(proc_macro_diagnostic)]
+#![feature(proc_macro_span)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
+#![allow(rustc::default_hash_types)]
+
+use proc_macro::TokenStream;
+
+mod fluent;
+
+/// Implements the `fluent_messages` macro, which performs compile-time validation of the
+/// compiler's Fluent resources (i.e. that the resources parse and don't multiply define the same
+/// messages) and generates constants that make using those messages in diagnostics more ergonomic.
+///
+/// For example, given the following invocation of the macro..
+///
+/// ```ignore (rust)
+/// fluent_messages! { "./typeck.ftl" }
+/// ```
+/// ..where `typeck.ftl` has the following contents..
+///
+/// ```fluent
+/// typeck_field_multiply_specified_in_initializer =
+/// field `{$ident}` specified more than once
+/// .label = used more than once
+/// .label_previous_use = first use of `{$ident}`
+/// ```
+/// ...then the macro parse the Fluent resource, emitting a diagnostic if it fails to do so, and
+/// will generate the following code:
+///
+/// ```ignore (rust)
+/// pub static DEFAULT_LOCALE_RESOURCE: &'static [&'static str] = include_str!("./typeck.ftl");
+///
+/// mod fluent_generated {
+/// mod typeck {
+/// pub const field_multiply_specified_in_initializer: DiagnosticMessage =
+/// DiagnosticMessage::fluent("typeck_field_multiply_specified_in_initializer");
+/// pub const field_multiply_specified_in_initializer_label_previous_use: DiagnosticMessage =
+/// DiagnosticMessage::fluent_attr(
+/// "typeck_field_multiply_specified_in_initializer",
+/// "previous_use_label"
+/// );
+/// }
+/// }
+/// ```
+/// When emitting a diagnostic, the generated constants can be used as follows:
+///
+/// ```ignore (rust)
+/// let mut err = sess.struct_span_err(
+/// span,
+/// fluent::typeck::field_multiply_specified_in_initializer
+/// );
+/// err.span_default_label(span);
+/// err.span_label(
+/// previous_use_span,
+/// fluent::typeck::field_multiply_specified_in_initializer_label_previous_use
+/// );
+/// err.emit();
+/// ```
+#[proc_macro]
+pub fn fluent_messages(input: TokenStream) -> TokenStream {
+ fluent::fluent_messages(input)
+}
diff --git a/compiler/rustc_hir/src/arena.rs b/compiler/rustc_hir/src/arena.rs
index c89e7eb75f8..3e5b3c498ee 100644
--- a/compiler/rustc_hir/src/arena.rs
+++ b/compiler/rustc_hir/src/arena.rs
@@ -51,6 +51,7 @@ macro_rules! arena_types {
[] type_binding: rustc_hir::TypeBinding<'tcx>,
[] variant: rustc_hir::Variant<'tcx>,
[] where_predicate: rustc_hir::WherePredicate<'tcx>,
+ [] lit: rustc_hir::Lit,
]);
)
}
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
index 8c58129c800..30bf8c2ad10 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -234,10 +234,7 @@ impl DefKind {
#[inline]
pub fn is_fn_like(self) -> bool {
- match self {
- DefKind::Fn | DefKind::AssocFn | DefKind::Closure | DefKind::Generator => true,
- _ => false,
- }
+ matches!(self, DefKind::Fn | DefKind::AssocFn | DefKind::Closure | DefKind::Generator)
}
/// Whether `query get_codegen_attrs` should be used with this definition.
diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs
index 8ceb176491b..5a5a1e44f12 100644
--- a/compiler/rustc_hir/src/definitions.rs
+++ b/compiler/rustc_hir/src/definitions.rs
@@ -9,7 +9,7 @@ use crate::def_id::{CrateNum, DefIndex, LocalDefId, StableCrateId, CRATE_DEF_IND
use crate::def_path_hash_map::DefPathHashMap;
use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::stable_hasher::StableHasher;
+use rustc_data_structures::stable_hasher::{Hash64, StableHasher};
use rustc_index::vec::IndexVec;
use rustc_span::symbol::{kw, sym, Symbol};
@@ -130,7 +130,7 @@ impl DefKey {
disambiguator.hash(&mut hasher);
- let local_hash: u64 = hasher.finish();
+ let local_hash = hasher.finish();
// Construct the new DefPathHash, making sure that the `crate_id`
// portion of the hash is properly copied from the parent. This way the
@@ -325,7 +325,7 @@ impl Definitions {
},
};
- let parent_hash = DefPathHash::new(stable_crate_id, 0);
+ let parent_hash = DefPathHash::new(stable_crate_id, Hash64::ZERO);
let def_path_hash = key.compute_stable_hash(parent_hash);
// Create the root definition.
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 35a72f868fb..52ed9660256 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1715,6 +1715,7 @@ impl Expr<'_> {
ExprKind::Continue(..) => ExprPrecedence::Continue,
ExprKind::Ret(..) => ExprPrecedence::Ret,
ExprKind::InlineAsm(..) => ExprPrecedence::InlineAsm,
+ ExprKind::OffsetOf(..) => ExprPrecedence::OffsetOf,
ExprKind::Struct(..) => ExprPrecedence::Struct,
ExprKind::Repeat(..) => ExprPrecedence::Repeat,
ExprKind::Yield(..) => ExprPrecedence::Yield,
@@ -1774,6 +1775,7 @@ impl Expr<'_> {
| ExprKind::Loop(..)
| ExprKind::Assign(..)
| ExprKind::InlineAsm(..)
+ | ExprKind::OffsetOf(..)
| ExprKind::AssignOp(..)
| ExprKind::Lit(_)
| ExprKind::ConstBlock(..)
@@ -1818,7 +1820,7 @@ impl Expr<'_> {
pub fn can_have_side_effects(&self) -> bool {
match self.peel_drop_temps().kind {
- ExprKind::Path(_) | ExprKind::Lit(_) => false,
+ ExprKind::Path(_) | ExprKind::Lit(_) | ExprKind::OffsetOf(..) => false,
ExprKind::Type(base, _)
| ExprKind::Unary(_, base)
| ExprKind::Field(base, _)
@@ -1957,10 +1959,10 @@ pub enum ExprKind<'hir> {
/// A unary operation (e.g., `!x`, `*x`).
Unary(UnOp, &'hir Expr<'hir>),
/// A literal (e.g., `1`, `"foo"`).
- Lit(Lit),
+ Lit(&'hir Lit),
/// A cast (e.g., `foo as f64`).
Cast(&'hir Expr<'hir>, &'hir Ty<'hir>),
- /// A type reference (e.g., `Foo`).
+ /// A type ascription (e.g., `x: Foo`). See RFC 3307.
Type(&'hir Expr<'hir>, &'hir Ty<'hir>),
/// Wraps the expression in a terminating scope.
/// This makes it semantically equivalent to `{ let _t = expr; _t }`.
@@ -2022,6 +2024,9 @@ pub enum ExprKind<'hir> {
/// Inline assembly (from `asm!`), with its outputs and inputs.
InlineAsm(&'hir InlineAsm<'hir>),
+ /// Field offset (`offset_of!`)
+ OffsetOf(&'hir Ty<'hir>, &'hir [Ident]),
+
/// A struct or struct-like variant literal expression.
///
/// E.g., `Foo {x: 1, y: 2}`, or `Foo {x: 1, .. base}`,
@@ -3146,7 +3151,6 @@ impl<'hir> Item<'hir> {
(ty, gen)
}
- /// An opaque `impl Trait` type alias, e.g., `type Foo = impl Bar;`.
/// Expect an [`ItemKind::OpaqueTy`] or panic.
#[track_caller]
pub fn expect_opaque_ty(&self) -> &OpaqueTy<'hir> {
@@ -3168,7 +3172,6 @@ impl<'hir> Item<'hir> {
(data, gen)
}
- /// A union definition, e.g., `union Foo<A, B> {x: A, y: B}`.
/// Expect an [`ItemKind::Union`] or panic.
#[track_caller]
pub fn expect_union(&self) -> (&VariantData<'hir>, &'hir Generics<'hir>) {
@@ -3531,12 +3534,20 @@ impl<'hir> OwnerNode<'hir> {
pub fn body_id(&self) -> Option<BodyId> {
match self {
- OwnerNode::TraitItem(TraitItem {
- kind: TraitItemKind::Fn(_, TraitFn::Provided(body_id)),
+ OwnerNode::Item(Item {
+ kind:
+ ItemKind::Static(_, _, body) | ItemKind::Const(_, body) | ItemKind::Fn(_, _, body),
..
})
- | OwnerNode::ImplItem(ImplItem { kind: ImplItemKind::Fn(_, body_id), .. })
- | OwnerNode::Item(Item { kind: ItemKind::Fn(.., body_id), .. }) => Some(*body_id),
+ | OwnerNode::TraitItem(TraitItem {
+ kind:
+ TraitItemKind::Fn(_, TraitFn::Provided(body)) | TraitItemKind::Const(_, Some(body)),
+ ..
+ })
+ | OwnerNode::ImplItem(ImplItem {
+ kind: ImplItemKind::Fn(_, body) | ImplItemKind::Const(_, body),
+ ..
+ }) => Some(*body),
_ => None,
}
}
@@ -3731,12 +3742,27 @@ impl<'hir> Node<'hir> {
pub fn body_id(&self) -> Option<BodyId> {
match self {
- Node::TraitItem(TraitItem {
- kind: TraitItemKind::Fn(_, TraitFn::Provided(body_id)),
+ Node::Item(Item {
+ kind:
+ ItemKind::Static(_, _, body) | ItemKind::Const(_, body) | ItemKind::Fn(_, _, body),
..
})
- | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(_, body_id), .. })
- | Node::Item(Item { kind: ItemKind::Fn(.., body_id), .. }) => Some(*body_id),
+ | Node::TraitItem(TraitItem {
+ kind:
+ TraitItemKind::Fn(_, TraitFn::Provided(body)) | TraitItemKind::Const(_, Some(body)),
+ ..
+ })
+ | Node::ImplItem(ImplItem {
+ kind: ImplItemKind::Fn(_, body) | ImplItemKind::Const(_, body),
+ ..
+ })
+ | Node::Expr(Expr {
+ kind:
+ ExprKind::ConstBlock(AnonConst { body, .. })
+ | ExprKind::Closure(Closure { body, .. })
+ | ExprKind::Repeat(_, ArrayLen::Body(AnonConst { body, .. })),
+ ..
+ }) => Some(*body),
_ => None,
}
}
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 234256ab553..df0047d82e1 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -786,6 +786,10 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
ExprKind::InlineAsm(ref asm) => {
visitor.visit_inline_asm(asm, expression.hir_id);
}
+ ExprKind::OffsetOf(ref container, ref fields) => {
+ visitor.visit_ty(container);
+ walk_list!(visitor, visit_ident, fields.iter().copied());
+ }
ExprKind::Yield(ref subexpression, _) => {
visitor.visit_expr(subexpression);
}
diff --git a/compiler/rustc_hir/src/tests.rs b/compiler/rustc_hir/src/tests.rs
index d4791150947..c7ac01b3334 100644
--- a/compiler/rustc_hir/src/tests.rs
+++ b/compiler/rustc_hir/src/tests.rs
@@ -1,4 +1,5 @@
use crate::definitions::{DefKey, DefPathData, DisambiguatedDefPathData};
+use rustc_data_structures::stable_hasher::Hash64;
use rustc_span::def_id::{DefPathHash, StableCrateId};
use rustc_span::edition::Edition;
use rustc_span::{create_session_if_not_set_then, Symbol};
@@ -24,7 +25,7 @@ fn def_path_hash_depends_on_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);
+ let parent_hash = DefPathHash::new(stable_crate_id, Hash64::ZERO);
let key = DefKey {
parent: None,
diff --git a/compiler/rustc_hir_analysis/Cargo.toml b/compiler/rustc_hir_analysis/Cargo.toml
index fab16b80fb5..f56cedebfb0 100644
--- a/compiler/rustc_hir_analysis/Cargo.toml
+++ b/compiler/rustc_hir_analysis/Cargo.toml
@@ -15,6 +15,7 @@ rustc_attr = { path = "../rustc_attr" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_hir = { path = "../rustc_hir" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_target = { path = "../rustc_target" }
rustc_session = { path = "../rustc_session" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
@@ -23,7 +24,7 @@ rustc_span = { path = "../rustc_span" }
rustc_index = { path = "../rustc_index" }
rustc_infer = { path = "../rustc_infer" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
-rustc_lint = { path = "../rustc_lint" }
+rustc_lint_defs = { path = "../rustc_lint_defs" }
rustc_type_ir = { path = "../rustc_type_ir" }
rustc_feature = { path = "../rustc_feature" }
thin-vec = "0.2.12"
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 8d1156c1771..992316edb63 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -447,14 +447,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
handle_ty_args(has_default, &inf.to_ty())
}
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
- ty::Const::from_opt_const_arg_anon_const(
- tcx,
- ty::WithOptConstParam {
- did: ct.value.def_id,
- const_param_did: Some(param.def_id),
- },
- )
- .into()
+ let did = ct.value.def_id;
+ tcx.feed_anon_const_type(did, tcx.type_of(param.def_id));
+ ty::Const::from_anon_const(tcx, did).into()
}
(&GenericParamDefKind::Const { .. }, hir::GenericArg::Infer(inf)) => {
let ty = tcx
@@ -2061,7 +2056,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
err.note("enum variants can't have type parameters");
let type_name = tcx.item_name(adt_def.did());
let msg = format!(
- "you might have meant to specity type parameters on enum \
+ "you might have meant to specify type parameters on enum \
`{type_name}`"
);
let Some(args) = assoc_segment.args else { return; };
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 0bb98fdf2a2..51ec5dd7a28 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -15,7 +15,7 @@ use rustc_infer::infer::opaque_types::ConstrainOpaqueTypeRegionVisitor;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{DefiningAnchor, RegionVariableOrigin, TyCtxtInferExt};
use rustc_infer::traits::{Obligation, TraitEngineExt as _};
-use rustc_lint::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
+use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
use rustc_middle::hir::nested_filter;
use rustc_middle::middle::stability::EvalResult;
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
@@ -863,7 +863,7 @@ fn check_impl_items_against_trait<'tcx>(
if !missing_items.is_empty() {
let full_impl_span =
tcx.hir().span_with_body(tcx.hir().local_def_id_to_hir_id(impl_id));
- missing_items_err(tcx, tcx.def_span(impl_id), &missing_items, full_impl_span);
+ missing_items_err(tcx, impl_id, &missing_items, full_impl_span);
}
if let Some(missing_items) = must_implement_one_of {
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 5d119a7737a..fe87aae8ed1 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -579,7 +579,7 @@ fn compare_asyncness<'tcx>(
pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
tcx: TyCtxt<'tcx>,
impl_m_def_id: LocalDefId,
-) -> Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed> {
+) -> Result<&'tcx FxHashMap<DefId, ty::EarlyBinder<Ty<'tcx>>>, ErrorGuaranteed> {
let impl_m = tcx.opt_associated_item(impl_m_def_id.to_def_id()).unwrap();
let trait_m = tcx.opt_associated_item(impl_m.trait_item_def_id.unwrap()).unwrap();
let impl_trait_ref =
@@ -782,14 +782,14 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
})
});
debug!(%ty);
- collected_tys.insert(def_id, ty);
+ collected_tys.insert(def_id, ty::EarlyBinder(ty));
}
Err(err) => {
let reported = tcx.sess.delay_span_bug(
return_span,
format!("could not fully resolve: {ty} => {err:?}"),
);
- collected_tys.insert(def_id, tcx.ty_error(reported));
+ collected_tys.insert(def_id, ty::EarlyBinder(tcx.ty_error(reported)));
}
}
}
@@ -1317,7 +1317,7 @@ fn compare_number_of_generics<'tcx>(
impl_count,
kind,
pluralize!(impl_count),
- suffix.unwrap_or_else(String::new),
+ suffix.unwrap_or_default(),
),
);
}
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 8fe4c44fca4..4b3f3cf169d 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -198,7 +198,7 @@ fn report_forbidden_specialization(tcx: TyCtxt<'_>, impl_item: DefId, parent_imp
fn missing_items_err(
tcx: TyCtxt<'_>,
- impl_span: Span,
+ impl_def_id: LocalDefId,
missing_items: &[ty::AssocItem],
full_impl_span: Span,
) {
@@ -211,6 +211,7 @@ fn missing_items_err(
.collect::<Vec<_>>()
.join("`, `");
+ let impl_span = tcx.def_span(impl_def_id);
let mut err = struct_span_err!(
tcx.sess,
impl_span,
@@ -229,7 +230,11 @@ fn missing_items_err(
tcx.sess.source_map().indentation_before(sugg_sp).unwrap_or_else(|| String::new());
for &trait_item in missing_items {
- let snippet = suggestion_signature(trait_item, tcx);
+ let snippet = suggestion_signature(
+ tcx,
+ trait_item,
+ tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity(),
+ );
let code = format!("{}{}\n{}", padding, snippet, padding);
let msg = format!("implement the missing item: `{snippet}`");
let appl = Applicability::HasPlaceholders;
@@ -301,11 +306,11 @@ fn default_body_is_unstable(
/// Re-sugar `ty::GenericPredicates` in a way suitable to be used in structured suggestions.
fn bounds_from_generic_predicates<'tcx>(
tcx: TyCtxt<'tcx>,
- predicates: ty::GenericPredicates<'tcx>,
+ predicates: impl IntoIterator<Item = (ty::Predicate<'tcx>, Span)>,
) -> (String, String) {
let mut types: FxHashMap<Ty<'tcx>, Vec<DefId>> = FxHashMap::default();
let mut projections = vec![];
- for (predicate, _) in predicates.predicates {
+ for (predicate, _) in predicates {
debug!("predicate {:?}", predicate);
let bound_predicate = predicate.kind();
match bound_predicate.skip_binder() {
@@ -367,7 +372,7 @@ fn fn_sig_suggestion<'tcx>(
tcx: TyCtxt<'tcx>,
sig: ty::FnSig<'tcx>,
ident: Ident,
- predicates: ty::GenericPredicates<'tcx>,
+ predicates: impl IntoIterator<Item = (ty::Predicate<'tcx>, Span)>,
assoc: ty::AssocItem,
) -> String {
let args = sig
@@ -436,7 +441,17 @@ pub fn ty_kind_suggestion(ty: Ty<'_>) -> Option<&'static str> {
/// Return placeholder code for the given associated item.
/// Similar to `ty::AssocItem::suggestion`, but appropriate for use as the code snippet of a
/// structured suggestion.
-fn suggestion_signature(assoc: ty::AssocItem, tcx: TyCtxt<'_>) -> String {
+fn suggestion_signature<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ assoc: ty::AssocItem,
+ impl_trait_ref: ty::TraitRef<'tcx>,
+) -> String {
+ let substs = ty::InternalSubsts::identity_for_item(tcx, assoc.def_id).rebase_onto(
+ tcx,
+ assoc.container_id(tcx),
+ impl_trait_ref.with_self_ty(tcx, tcx.types.self_param).substs,
+ );
+
match assoc.kind {
ty::AssocKind::Fn => {
// We skip the binder here because the binder would deanonymize all
@@ -445,16 +460,22 @@ fn suggestion_signature(assoc: ty::AssocItem, tcx: TyCtxt<'_>) -> String {
// regions just fine, showing `fn(&MyType)`.
fn_sig_suggestion(
tcx,
- tcx.fn_sig(assoc.def_id).subst_identity().skip_binder(),
+ tcx.fn_sig(assoc.def_id).subst(tcx, substs).skip_binder(),
assoc.ident(tcx),
- tcx.predicates_of(assoc.def_id),
+ tcx.predicates_of(assoc.def_id).instantiate_own(tcx, substs),
assoc,
)
}
- ty::AssocKind::Type => format!("type {} = Type;", assoc.name),
+ ty::AssocKind::Type => {
+ let (generics, where_clauses) = bounds_from_generic_predicates(
+ tcx,
+ tcx.predicates_of(assoc.def_id).instantiate_own(tcx, substs),
+ );
+ format!("type {}{generics} = /* Type */{where_clauses};", assoc.name)
+ }
ty::AssocKind::Const => {
let ty = tcx.type_of(assoc.def_id).subst_identity();
- let val = ty_kind_suggestion(ty).unwrap_or("value");
+ let val = ty_kind_suggestion(ty).unwrap_or("todo!()");
format!("const {}: {} = {};", assoc.name, ty, val)
}
}
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index 0f40cca9427..611ce13b739 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -74,16 +74,15 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
debug!("visit_implementation_of_copy: self_type={:?} (free)", self_type);
- let span = match tcx.hir().expect_item(impl_did).kind {
- ItemKind::Impl(hir::Impl { polarity: hir::ImplPolarity::Negative(_), .. }) => return,
- ItemKind::Impl(impl_) => impl_.self_ty.span,
- _ => bug!("expected Copy impl item"),
+ let span = match tcx.hir().expect_item(impl_did).expect_impl() {
+ hir::Impl { polarity: hir::ImplPolarity::Negative(_), .. } => return,
+ hir::Impl { self_ty, .. } => self_ty.span,
};
let cause = traits::ObligationCause::misc(span, impl_did);
match type_allowed_to_implement_copy(tcx, param_env, self_type, cause) {
Ok(()) => {}
- Err(CopyImplementationError::InfrigingFields(fields)) => {
+ Err(CopyImplementationError::InfringingFields(fields)) => {
let mut err = struct_span_err!(
tcx.sess,
span,
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index cbbaf8f857d..36e294e8aa2 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -55,7 +55,6 @@ fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
pub fn provide(providers: &mut Providers) {
resolve_bound_vars::provide(providers);
*providers = Providers {
- opt_const_param_of: type_of::opt_const_param_of,
type_of: type_of::type_of,
item_bounds: item_bounds::item_bounds,
explicit_item_bounds: item_bounds::explicit_item_bounds,
@@ -1457,10 +1456,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
}
fn is_foreign_item(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
- match tcx.hir().get_by_def_id(def_id) {
- Node::ForeignItem(..) => true,
- _ => false,
- }
+ matches!(tcx.hir().get_by_def_id(def_id), Node::ForeignItem(..))
}
fn generator_kind(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<hir::GeneratorKind> {
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 9358ed61292..8c414521b76 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -645,9 +645,8 @@ pub(super) fn implied_predicates_with_filter(
};
// Combine the two lists to form the complete set of superbounds:
- let implied_bounds = &*tcx
- .arena
- .alloc_from_iter(superbounds.predicates().into_iter().chain(where_bounds_that_match));
+ let implied_bounds =
+ &*tcx.arena.alloc_from_iter(superbounds.predicates().chain(where_bounds_that_match));
debug!(?implied_bounds);
// Now require that immediate supertraits are converted,
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index e758fe95d9c..3cb217335bd 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -1333,7 +1333,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
// We may fail to resolve higher-ranked lifetimes that are mentioned by APIT.
// AST-based resolution does not care for impl-trait desugaring, which are the
- // responibility of lowering. This may create a mismatch between the resolution
+ // responsibility of lowering. This may create a mismatch between the resolution
// AST found (`region_def_id`) which points to HRTB, and what HIR allows.
// ```
// fn foo(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index c173bd913a8..d7d509e5394 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -1,6 +1,6 @@
use rustc_errors::{Applicability, StashKey};
use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit;
use rustc_hir::intravisit::Visitor;
use rustc_hir::{HirId, Node};
@@ -16,22 +16,81 @@ use super::ItemCtxt;
use super::{bad_placeholder, is_suggestable_infer_ty};
use crate::errors::UnconstrainedOpaqueType;
-/// Computes the relevant generic parameter for a potential generic const argument.
-///
-/// This should be called using the query `tcx.opt_const_param_of`.
-pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<DefId> {
+fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
use hir::*;
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
- match tcx.hir().get(hir_id) {
- Node::AnonConst(_) => (),
- _ => return None,
- };
+ let Node::AnonConst(_) = tcx.hir().get(hir_id) else { panic!() };
let parent_node_id = tcx.hir().parent_id(hir_id);
let parent_node = tcx.hir().get(parent_node_id);
let (generics, arg_idx) = match parent_node {
+ // Easy case: arrays repeat expressions.
+ Node::Ty(&Ty { kind: TyKind::Array(_, ref constant), .. })
+ | Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
+ if constant.hir_id() == hir_id =>
+ {
+ return tcx.types.usize
+ }
+ Node::Ty(&Ty { kind: TyKind::Typeof(ref e), .. }) if e.hir_id == hir_id => {
+ return tcx.typeck(def_id).node_type(e.hir_id)
+ }
+ Node::Expr(&Expr { kind: ExprKind::ConstBlock(ref anon_const), .. })
+ if anon_const.hir_id == hir_id =>
+ {
+ let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
+ return substs.as_inline_const().ty()
+ }
+ Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
+ | Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. })
+ if asm.operands.iter().any(|(op, _op_sp)| match op {
+ hir::InlineAsmOperand::Const { anon_const }
+ | hir::InlineAsmOperand::SymFn { anon_const } => anon_const.hir_id == hir_id,
+ _ => false,
+ }) =>
+ {
+ return tcx.typeck(def_id).node_type(hir_id)
+ }
+ Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => {
+ return tcx
+ .adt_def(tcx.hir().get_parent_item(hir_id))
+ .repr()
+ .discr_type()
+ .to_ty(tcx)
+ }
+ Node::GenericParam(&GenericParam {
+ def_id: param_def_id,
+ kind: GenericParamKind::Const { default: Some(ct), .. },
+ ..
+ }) if ct.hir_id == hir_id => {
+ return tcx.type_of(param_def_id)
+ .no_bound_vars()
+ .expect("const parameter types cannot be generic")
+ }
+
+ Node::TypeBinding(binding @ &TypeBinding { hir_id: binding_id, .. })
+ if let Node::TraitRef(trait_ref) = tcx.hir().get(
+ tcx.hir().parent_id(binding_id)
+ ) =>
+ {
+ let Some(trait_def_id) = trait_ref.trait_def_id() else {
+ return tcx.ty_error_with_message(tcx.def_span(def_id), "Could not find trait");
+ };
+ let assoc_items = tcx.associated_items(trait_def_id);
+ let assoc_item = assoc_items.find_by_name_and_kind(
+ tcx, binding.ident, ty::AssocKind::Const, def_id.to_def_id(),
+ );
+ return if let Some(assoc_item) = assoc_item {
+ tcx.type_of(assoc_item.def_id)
+ .no_bound_vars()
+ .expect("const parameter types cannot be generic")
+ } else {
+ // FIXME(associated_const_equality): add a useful error message here.
+ tcx.ty_error_with_message(tcx.def_span(def_id), "Could not find associated const on trait")
+ }
+ }
+
// This match arm is for when the def_id appears in a GAT whose
// path can't be resolved without typechecking e.g.
//
@@ -86,11 +145,10 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
(generics, arg_index)
} else {
// I dont think it's possible to reach this but I'm not 100% sure - BoxyUwU
- tcx.sess.delay_span_bug(
+ return tcx.ty_error_with_message(
tcx.def_span(def_id),
"unexpected non-GAT usage of an anon const",
);
- return None;
}
}
Node::Expr(&Expr {
@@ -103,7 +161,12 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
// This may fail in case the method/path does not actually exist.
// As there is no relevant param for `def_id`, we simply return
// `None` here.
- let type_dependent_def = tables.type_dependent_def_id(parent_node_id)?;
+ let Some(type_dependent_def) = tables.type_dependent_def_id(parent_node_id) else {
+ return tcx.ty_error_with_message(
+ tcx.def_span(def_id),
+ &format!("unable to find type-dependent def for {:?}", parent_node_id),
+ );
+ };
let idx = segment
.args
.and_then(|args| {
@@ -140,19 +203,17 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
if let Some(path) = get_path_containing_arg_in_pat(pat, hir_id) {
path
} else {
- tcx.sess.delay_span_bug(
+ return tcx.ty_error_with_message(
tcx.def_span(def_id),
&format!("unable to find const parent for {} in pat {:?}", hir_id, pat),
);
- return None;
}
}
_ => {
- tcx.sess.delay_span_bug(
+ return tcx.ty_error_with_message(
tcx.def_span(def_id),
&format!("unexpected const parent path {:?}", parent_node),
);
- return None;
}
};
@@ -171,32 +232,34 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
.position(|ct| ct.hir_id == hir_id)
.map(|idx| (idx, seg)))
}) else {
- tcx.sess.delay_span_bug(
+ return tcx.ty_error_with_message(
tcx.def_span(def_id),
"no arg matching AnonConst in path",
);
- return None;
};
let generics = match tcx.res_generics_def_id(segment.res) {
Some(def_id) => tcx.generics_of(def_id),
None => {
- tcx.sess.delay_span_bug(
+ return tcx.ty_error_with_message(
tcx.def_span(def_id),
&format!("unexpected anon const res {:?} in path: {:?}", segment.res, path),
);
- return None;
}
};
(generics, arg_index)
}
- _ => return None,
+
+ _ => return tcx.ty_error_with_message(
+ tcx.def_span(def_id),
+ &format!("unexpected const parent in type_of(): {parent_node:?}"),
+ ),
};
debug!(?parent_node);
debug!(?generics, ?arg_idx);
- generics
+ if let Some(param_def_id) = generics
.params
.iter()
.filter(|param| param.kind.is_ty_or_const())
@@ -211,6 +274,14 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
}
_ => None,
})
+ {
+ tcx.type_of(param_def_id).no_bound_vars().expect("const parameter types cannot be generic")
+ } else {
+ return tcx.ty_error_with_message(
+ tcx.def_span(def_id),
+ &format!("const generic parameter not found in {generics:?} at position {arg_idx:?}"),
+ );
+ }
}
fn get_path_containing_arg_in_pat<'hir>(
@@ -251,7 +322,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
match tcx.collect_return_position_impl_trait_in_trait_tys(fn_def_id) {
Ok(map) => {
let assoc_item = tcx.associated_item(def_id);
- return ty::EarlyBinder(map[&assoc_item.trait_item_def_id.unwrap()]);
+ return map[&assoc_item.trait_item_def_id.unwrap()];
}
Err(_) => {
return ty::EarlyBinder(tcx.ty_error_with_message(
@@ -415,143 +486,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
tcx.typeck(def_id).node_type(hir_id)
}
- Node::AnonConst(_) if let Some(param) = tcx.opt_const_param_of(def_id) => {
- // We defer to `type_of` of the corresponding parameter
- // for generic arguments.
- tcx.type_of(param).subst_identity()
- }
-
- Node::AnonConst(_) => {
- let parent_node = tcx.hir().get_parent(hir_id);
- match parent_node {
- Node::Ty(Ty { kind: TyKind::Array(_, constant), .. })
- | Node::Expr(Expr { kind: ExprKind::Repeat(_, constant), .. })
- if constant.hir_id() == hir_id =>
- {
- tcx.types.usize
- }
- Node::Ty(Ty { kind: TyKind::Typeof(e), .. }) if e.hir_id == hir_id => {
- tcx.typeck(def_id).node_type(e.hir_id)
- }
-
- Node::Expr(Expr { kind: ExprKind::ConstBlock(anon_const), .. })
- if anon_const.hir_id == hir_id =>
- {
- let substs = InternalSubsts::identity_for_item(tcx, def_id);
- substs.as_inline_const().ty()
- }
-
- Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
- | Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. })
- if asm.operands.iter().any(|(op, _op_sp)| match op {
- hir::InlineAsmOperand::Const { anon_const }
- | hir::InlineAsmOperand::SymFn { anon_const } => {
- anon_const.hir_id == hir_id
- }
- _ => false,
- }) =>
- {
- tcx.typeck(def_id).node_type(hir_id)
- }
-
- Node::Variant(Variant { disr_expr: Some(e), .. }) if e.hir_id == hir_id => {
- tcx.adt_def(tcx.hir().get_parent_item(hir_id)).repr().discr_type().to_ty(tcx)
- }
-
- Node::TypeBinding(TypeBinding {
- hir_id: binding_id,
- kind: TypeBindingKind::Equality { term: Term::Const(e) },
- ident,
- ..
- }) if let Node::TraitRef(trait_ref) = tcx.hir().get_parent(*binding_id)
- && e.hir_id == hir_id =>
- {
- let Some(trait_def_id) = trait_ref.trait_def_id() else {
- return ty::EarlyBinder(tcx.ty_error_with_message(DUMMY_SP, "Could not find trait"));
- };
- let assoc_items = tcx.associated_items(trait_def_id);
- let assoc_item = assoc_items.find_by_name_and_kind(
- tcx,
- *ident,
- ty::AssocKind::Const,
- def_id.to_def_id(),
- );
- if let Some(assoc_item) = assoc_item {
- tcx.type_of(assoc_item.def_id)
- .no_bound_vars()
- .expect("const parameter types cannot be generic")
- } else {
- // FIXME(associated_const_equality): add a useful error message here.
- tcx.ty_error_with_message(
- DUMMY_SP,
- "Could not find associated const on trait",
- )
- }
- }
-
- Node::TypeBinding(TypeBinding {
- hir_id: binding_id,
- gen_args,
- kind,
- ident,
- ..
- }) if let Node::TraitRef(trait_ref) = tcx.hir().get_parent(*binding_id)
- && let Some((idx, _)) =
- gen_args.args.iter().enumerate().find(|(_, arg)| {
- if let GenericArg::Const(ct) = arg {
- ct.value.hir_id == hir_id
- } else {
- false
- }
- }) =>
- {
- let Some(trait_def_id) = trait_ref.trait_def_id() else {
- return ty::EarlyBinder(tcx.ty_error_with_message(DUMMY_SP, "Could not find trait"));
- };
- let assoc_items = tcx.associated_items(trait_def_id);
- let assoc_item = assoc_items.find_by_name_and_kind(
- tcx,
- *ident,
- match kind {
- // I think `<A: T>` type bindings requires that `A` is a type
- TypeBindingKind::Constraint { .. }
- | TypeBindingKind::Equality { term: Term::Ty(..) } => {
- ty::AssocKind::Type
- }
- TypeBindingKind::Equality { term: Term::Const(..) } => {
- ty::AssocKind::Const
- }
- },
- def_id.to_def_id(),
- );
- if let Some(assoc_item) = assoc_item
- && let param = &tcx.generics_of(assoc_item.def_id).params[idx]
- && matches!(param.kind, ty::GenericParamDefKind::Const { .. })
- {
- tcx.type_of(param.def_id)
- .no_bound_vars()
- .expect("const parameter types cannot be generic")
- } else {
- // FIXME(associated_const_equality): add a useful error message here.
- tcx.ty_error_with_message(
- DUMMY_SP,
- "Could not find const param on associated item",
- )
- }
- }
-
- Node::GenericParam(&GenericParam {
- def_id: param_def_id,
- kind: GenericParamKind::Const { default: Some(ct), .. },
- ..
- }) if ct.hir_id == hir_id => tcx.type_of(param_def_id).subst_identity(),
-
- x => tcx.ty_error_with_message(
- DUMMY_SP,
- &format!("unexpected const parent in type_of(): {x:?}"),
- ),
- }
- }
+ Node::AnonConst(_) => anon_const_type_of(tcx, def_id),
Node::GenericParam(param) => match &param.kind {
GenericParamKind::Type { default: Some(ty), .. }
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index 27e56180349..4c28e28f964 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -99,10 +99,10 @@ mod variance;
use rustc_errors::ErrorGuaranteed;
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
+use rustc_fluent_macro::fluent_messages;
use rustc_hir as hir;
use rustc_hir::Node;
use rustc_infer::infer::TyCtxtInferExt;
-use rustc_macros::fluent_messages;
use rustc_middle::middle;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, Ty, TyCtxt};
diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index 0a45119ff05..4d240e90b14 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -105,7 +105,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
if let ty::RegionKind::ReEarlyBound(ebr) = r.kind() {
self.variances[ebr.index as usize] = ty::Invariant;
}
- r.super_visit_with(self)
+ ControlFlow::Continue(())
}
#[instrument(level = "trace", skip(self), ret)]
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 74f5b359021..2db4f1e50d4 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -1551,6 +1551,23 @@ impl<'a> State<'a> {
self.word("asm!");
self.print_inline_asm(asm);
}
+ hir::ExprKind::OffsetOf(container, ref fields) => {
+ self.word("offset_of!(");
+ self.print_type(container);
+ self.word(",");
+ self.space();
+
+ if let Some((&first, rest)) = fields.split_first() {
+ self.print_ident(first);
+
+ for &field in rest {
+ self.word(".");
+ self.print_ident(field);
+ }
+ }
+
+ self.word(")");
+ }
hir::ExprKind::Yield(expr, _) => {
self.word_space("yield");
self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml
index 093f9bb8448..13e1ea31c4d 100644
--- a/compiler/rustc_hir_typeck/Cargo.toml
+++ b/compiler/rustc_hir_typeck/Cargo.toml
@@ -12,6 +12,7 @@ rustc_ast = { path = "../rustc_ast" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_graphviz = { path = "../rustc_graphviz" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_index = { path = "../rustc_index" }
rustc_infer = { path = "../rustc_infer" }
rustc_hir = { path = "../rustc_hir" }
diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl
index 2c537bf4064..6d40df7d0cc 100644
--- a/compiler/rustc_hir_typeck/messages.ftl
+++ b/compiler/rustc_hir_typeck/messages.ftl
@@ -3,21 +3,6 @@ hir_typeck_field_multiply_specified_in_initializer =
.label = used more than once
.previous_use_label = first use of `{$ident}`
-hir_typeck_copy_impl_on_type_with_dtor =
- the trait `Copy` cannot be implemented for this type; the type has a destructor
- .label = `Copy` not allowed on types with destructors
-
-hir_typeck_multiple_relaxed_default_bounds =
- type parameter has more than one relaxed default bound, only one is supported
-
-hir_typeck_copy_impl_on_non_adt =
- the trait `Copy` cannot be implemented for this type
- .label = type is not a structure or enumeration
-
-hir_typeck_trait_object_declared_with_no_traits =
- at least one trait is required for an object type
- .alias_span = this alias does not contain a trait
-
hir_typeck_functional_record_update_on_non_struct =
functional record update syntax requires a struct
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 8fa3bcd68c3..507c24d540c 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -976,7 +976,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Attempt to coerce an expression to a type, and return the
/// adjusted type of the expression, if successful.
/// Adjustments are only recorded if the coercion succeeded.
- /// The expressions *must not* have any pre-existing adjustments.
+ /// The expressions *must not* have any preexisting adjustments.
pub fn try_coerce(
&self,
expr: &hir::Expr<'_>,
@@ -1340,7 +1340,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
}
/// As an optimization, you can create a `CoerceMany` with a
- /// pre-existing slice of expressions. In this case, you are
+ /// preexisting slice of expressions. In this case, you are
/// expected to pass each element in the slice to `coerce(...)` in
/// order. This is used with arrays in particular to avoid
/// needlessly cloning the slice.
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 13442c31649..525acfdaa81 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -17,7 +17,6 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, Article, AssocItem, Ty, TypeAndMut, TypeFoldable};
use rustc_span::symbol::{sym, Symbol};
use rustc_span::{BytePos, Span, DUMMY_SP};
-use rustc_target::abi::FieldIdx;
use rustc_trait_selection::infer::InferCtxtExt as _;
use rustc_trait_selection::traits::ObligationCause;
@@ -875,7 +874,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
variant.fields.len() == 1
})
.filter_map(|variant| {
- let sole_field = &variant.fields[FieldIdx::from_u32(0)];
+ let sole_field = &variant.single_field();
let field_is_local = sole_field.did.is_local();
let field_is_accessible =
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index 3eee2278dca..5be78416e61 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -108,7 +108,7 @@ pub enum ExpectedReturnTypeLabel<'tcx> {
#[derive(Diagnostic)]
#[diag(hir_typeck_missing_parentheses_in_range, code = "E0689")]
-pub struct MissingParentheseInRange {
+pub struct MissingParenthesesInRange {
#[primary_span]
#[label(hir_typeck_missing_parentheses_in_range)]
pub span: Span,
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 6ffa0134f3d..3ffc583d43f 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -38,6 +38,7 @@ use rustc_infer::infer;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::DefineOpaqueTypes;
use rustc_infer::infer::InferOk;
+use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::ObligationCause;
use rustc_middle::middle::stability;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase};
@@ -53,6 +54,8 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_target::abi::FieldIdx;
use rustc_target::spec::abi::Abi::RustIntrinsic;
use rustc_trait_selection::infer::InferCtxtExt;
+use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
+use rustc_trait_selection::traits::ObligationCtxt;
use rustc_trait_selection::traits::{self, ObligationCauseCode};
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -306,6 +309,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.deferred_asm_checks.borrow_mut().push((asm, expr.hir_id));
self.check_expr_asm(asm)
}
+ ExprKind::OffsetOf(container, ref fields) => {
+ self.check_offset_of(container, fields, expr)
+ }
ExprKind::Break(destination, ref expr_opt) => {
self.check_expr_break(destination, expr_opt.as_deref(), expr)
}
@@ -1735,10 +1741,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else {
self.check_expr_has_type_or_error(base_expr, adt_ty, |_| {
let base_ty = self.typeck_results.borrow().expr_ty(*base_expr);
- let same_adt = match (adt_ty.kind(), base_ty.kind()) {
- (ty::Adt(adt, _), ty::Adt(base_adt, _)) if adt == base_adt => true,
- _ => false,
- };
+ let same_adt = matches!((adt_ty.kind(), base_ty.kind()),
+ (ty::Adt(adt, _), ty::Adt(base_adt, _)) if adt == base_adt);
if self.tcx.sess.is_nightly_build() && same_adt {
feature_err(
&self.tcx.sess.parse_sess,
@@ -2449,15 +2453,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
base_did: DefId,
return_ty: Option<Ty<'tcx>>,
) -> ErrorGuaranteed {
- let struct_path = self.tcx().def_path_str(base_did);
- let kind_name = self.tcx().def_descr(base_did);
- let mut err = struct_span_err!(
- self.tcx().sess,
- field.span,
- E0616,
- "field `{field}` of {kind_name} `{struct_path}` is private",
- );
- err.span_label(field.span, "private field");
+ let mut err = self.private_field_err(field, base_did);
+
// Also check if an accessible method exists, which is often what is meant.
if self.method_exists(field, expr_t, expr.hir_id, false, return_ty)
&& !self.expr_in_place(expr.hir_id)
@@ -2697,6 +2694,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err
}
+ fn private_field_err(
+ &self,
+ field: Ident,
+ base_did: DefId,
+ ) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
+ let struct_path = self.tcx().def_path_str(base_did);
+ let kind_name = self.tcx().def_descr(base_did);
+ let mut err = struct_span_err!(
+ self.tcx().sess,
+ field.span,
+ E0616,
+ "field `{field}` of {kind_name} `{struct_path}` is private",
+ );
+ err.span_label(field.span, "private field");
+
+ err
+ }
+
pub(crate) fn get_field_candidates_considering_privacy(
&self,
span: Span,
@@ -2802,6 +2817,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
element_ty
}
None => {
+ // Attempt to *shallowly* search for an impl which matches,
+ // but has nested obligations which are unsatisfied.
+ for (base_t, _) in self.autoderef(base.span, base_t).silence_errors() {
+ if let Some((_, index_ty, element_ty)) =
+ self.find_and_report_unsatisfied_index_impl(expr.hir_id, base, base_t)
+ {
+ self.demand_coerce(idx, idx_t, index_ty, None, AllowTwoPhase::No);
+ return element_ty;
+ }
+ }
+
let mut err = type_error_struct!(
self.tcx.sess,
expr.span,
@@ -2845,6 +2871,82 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
+ /// Try to match an implementation of `Index` against a self type, and report
+ /// the unsatisfied predicates that result from confirming this impl.
+ ///
+ /// Given an index expression, sometimes the `Self` type shallowly but does not
+ /// deeply satisfy an impl predicate. Instead of simply saying that the type
+ /// does not support being indexed, we want to point out exactly what nested
+ /// predicates cause this to be, so that the user can add them to fix their code.
+ fn find_and_report_unsatisfied_index_impl(
+ &self,
+ index_expr_hir_id: HirId,
+ base_expr: &hir::Expr<'_>,
+ base_ty: Ty<'tcx>,
+ ) -> Option<(ErrorGuaranteed, Ty<'tcx>, Ty<'tcx>)> {
+ let index_trait_def_id = self.tcx.lang_items().index_trait()?;
+ let index_trait_output_def_id = self.tcx.get_diagnostic_item(sym::IndexOutput)?;
+
+ let mut relevant_impls = vec![];
+ self.tcx.for_each_relevant_impl(index_trait_def_id, base_ty, |impl_def_id| {
+ relevant_impls.push(impl_def_id);
+ });
+ let [impl_def_id] = relevant_impls[..] else {
+ // Only report unsatisfied impl predicates if there's one impl
+ return None;
+ };
+
+ self.commit_if_ok(|_| {
+ let ocx = ObligationCtxt::new_in_snapshot(self);
+ let impl_substs = self.fresh_substs_for_item(base_expr.span, impl_def_id);
+ let impl_trait_ref =
+ self.tcx.impl_trait_ref(impl_def_id).unwrap().subst(self.tcx, impl_substs);
+ let cause = self.misc(base_expr.span);
+
+ // Match the impl self type against the base ty. If this fails,
+ // we just skip this impl, since it's not particularly useful.
+ let impl_trait_ref = ocx.normalize(&cause, self.param_env, impl_trait_ref);
+ ocx.eq(&cause, self.param_env, impl_trait_ref.self_ty(), base_ty)?;
+
+ // Register the impl's predicates. One of these predicates
+ // must be unsatisfied, or else we wouldn't have gotten here
+ // in the first place.
+ ocx.register_obligations(traits::predicates_for_generics(
+ |idx, span| {
+ traits::ObligationCause::new(
+ base_expr.span,
+ self.body_id,
+ if span.is_dummy() {
+ traits::ExprItemObligation(impl_def_id, index_expr_hir_id, idx)
+ } else {
+ traits::ExprBindingObligation(impl_def_id, span, index_expr_hir_id, idx)
+ },
+ )
+ },
+ self.param_env,
+ self.tcx.predicates_of(impl_def_id).instantiate(self.tcx, impl_substs),
+ ));
+
+ // Normalize the output type, which we can use later on as the
+ // return type of the index expression...
+ let element_ty = ocx.normalize(
+ &cause,
+ self.param_env,
+ self.tcx.mk_projection(index_trait_output_def_id, impl_trait_ref.substs),
+ );
+
+ let errors = ocx.select_where_possible();
+ // There should be at least one error reported. If not, we
+ // will still delay a span bug in `report_fulfillment_errors`.
+ Ok::<_, NoSolution>((
+ self.err_ctxt().report_fulfillment_errors(&errors),
+ impl_trait_ref.substs.type_at(1),
+ element_ty,
+ ))
+ })
+ .ok()
+ }
+
fn point_at_index_if_possible(
&self,
errors: &mut Vec<traits::FulfillmentError<'tcx>>,
@@ -2954,4 +3056,78 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.tcx.mk_unit()
}
}
+
+ fn check_offset_of(
+ &self,
+ container: &'tcx hir::Ty<'tcx>,
+ fields: &[Ident],
+ expr: &'tcx hir::Expr<'tcx>,
+ ) -> Ty<'tcx> {
+ let container = self.to_ty(container).normalized;
+
+ let mut field_indices = Vec::with_capacity(fields.len());
+ let mut current_container = container;
+
+ for &field in fields {
+ let container = self.structurally_resolved_type(expr.span, current_container);
+
+ match container.kind() {
+ ty::Adt(container_def, substs) if !container_def.is_enum() => {
+ let block = self.tcx.hir().local_def_id_to_hir_id(self.body_id);
+ let (ident, def_scope) =
+ self.tcx.adjust_ident_and_get_scope(field, container_def.did(), block);
+
+ let fields = &container_def.non_enum_variant().fields;
+ if let Some((index, field)) = fields
+ .iter_enumerated()
+ .find(|(_, f)| f.ident(self.tcx).normalize_to_macros_2_0() == ident)
+ {
+ let field_ty = self.field_ty(expr.span, field, substs);
+
+ // FIXME: DSTs with static alignment should be allowed
+ self.require_type_is_sized(field_ty, expr.span, traits::MiscObligation);
+
+ if field.vis.is_accessible_from(def_scope, self.tcx) {
+ self.tcx.check_stability(field.did, Some(expr.hir_id), expr.span, None);
+ } else {
+ self.private_field_err(ident, container_def.did()).emit();
+ }
+
+ // Save the index of all fields regardless of their visibility in case
+ // of error recovery.
+ field_indices.push(index);
+ current_container = field_ty;
+
+ continue;
+ }
+ }
+ ty::Tuple(tys) => {
+ let fstr = field.as_str();
+
+ if let Ok(index) = fstr.parse::<usize>() {
+ if fstr == index.to_string() {
+ if let Some(&field_ty) = tys.get(index) {
+ field_indices.push(index.into());
+ current_container = field_ty;
+
+ continue;
+ }
+ }
+ }
+ }
+ _ => (),
+ };
+
+ self.no_such_field_err(field, container, expr.hir_id).emit();
+
+ break;
+ }
+
+ self.typeck_results
+ .borrow_mut()
+ .offset_of_data_mut()
+ .insert(expr.hir_id, (container, field_indices));
+
+ self.tcx.types.usize
+ }
}
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index ee1c6fbfd65..94b6a0f8f47 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -300,6 +300,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
hir::ExprKind::Continue(..)
| hir::ExprKind::Lit(..)
| hir::ExprKind::ConstBlock(..)
+ | hir::ExprKind::OffsetOf(..)
| hir::ExprKind::Err(_) => {}
hir::ExprKind::Loop(blk, ..) => {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index f736f7a9620..2b5af4bc81b 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -420,9 +420,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ast_c: &hir::AnonConst,
param_def_id: DefId,
) -> ty::Const<'tcx> {
- let const_def =
- ty::WithOptConstParam { did: ast_c.def_id, const_param_did: Some(param_def_id) };
- let c = ty::Const::from_opt_const_arg_anon_const(self.tcx, const_def);
+ let did = ast_c.def_id;
+ self.tcx.feed_anon_const_type(did, self.tcx.type_of(param_def_id));
+ let c = ty::Const::from_anon_const(self.tcx, did);
self.register_wf_obligation(
c.into(),
self.tcx.hir().span(ast_c.hir_id),
@@ -827,7 +827,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
QPath::TypeRelative(ref qself, ref segment) => {
// Don't use `self.to_ty`, since this will register a WF obligation.
- // If we're trying to call a non-existent method on a trait
+ // If we're trying to call a nonexistent method on a trait
// (e.g. `MyTrait::missing_method`), then resolution will
// give us a `QPath::TypeRelative` with a trait object as
// `qself`. In that case, we want to avoid registering a WF obligation
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
index f879ccbb3af..56c94505727 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
@@ -164,24 +164,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
{
for param in
[param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
+ .into_iter()
+ .flatten()
{
- if let Some(param) = param {
- let refined_expr = self.point_at_field_if_possible(
- def_id,
- param,
- variant_def_id,
- fields,
- );
-
- match refined_expr {
- None => {}
- Some((refined_expr, _)) => {
- error.obligation.cause.span = refined_expr
- .span
- .find_ancestor_in_same_ctxt(error.obligation.cause.span)
- .unwrap_or(refined_expr.span);
- return true;
- }
+ let refined_expr =
+ self.point_at_field_if_possible(def_id, param, variant_def_id, fields);
+
+ match refined_expr {
+ None => {}
+ Some((refined_expr, _)) => {
+ error.obligation.cause.span = refined_expr
+ .span
+ .find_ancestor_in_same_ctxt(error.obligation.cause.span)
+ .unwrap_or(refined_expr.span);
+ return true;
}
}
}
@@ -334,7 +330,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// expression mentioned.
///
/// `blame_specific_arg_if_possible` will find the most-specific expression anywhere inside
- /// the provided function call expression, and mark it as responsible for the fullfillment
+ /// the provided function call expression, and mark it as responsible for the fulfillment
/// error.
fn blame_specific_arg_if_possible(
&self,
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index c6fd0b61035..3ba679df3ed 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -17,7 +17,6 @@ use rustc_infer::infer;
use rustc_infer::infer::error_reporting::TypeErrCtxt;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
-use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt};
use rustc_session::Session;
use rustc_span::symbol::Ident;
@@ -250,16 +249,12 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
}
fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> {
- if let Some(param) = param {
- if let GenericArgKind::Type(ty) = self.var_for_def(span, param).unpack() {
- return ty;
- }
- unreachable!()
- } else {
- self.next_ty_var(TypeVariableOrigin {
+ match param {
+ Some(param) => self.var_for_def(span, param).as_type().unwrap(),
+ None => self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::TypeInference,
span,
- })
+ }),
}
}
@@ -269,16 +264,12 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
param: Option<&ty::GenericParamDef>,
span: Span,
) -> Const<'tcx> {
- if let Some(param) = param {
- if let GenericArgKind::Const(ct) = self.var_for_def(span, param).unpack() {
- return ct;
- }
- unreachable!()
- } else {
- self.next_const_var(
+ match param {
+ Some(param) => self.var_for_def(span, param).as_const().unwrap(),
+ None => self.next_const_var(
ty,
ConstVariableOrigin { kind: ConstVariableOriginKind::ConstInference, span },
- )
+ ),
}
}
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 5fda4e191c2..eef2b5009c8 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -794,7 +794,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return;
};
- // get all where BoundPredicates here, because they are used in to cases below
+ // get all where BoundPredicates here, because they are used in two cases below
let where_predicates = predicates
.iter()
.filter_map(|p| match p {
@@ -1252,7 +1252,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
node: rustc_ast::LitKind::Int(lit, rustc_ast::LitIntType::Unsuffixed),
span,
}) => {
- let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) else { return false; };
+ let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(*span) else { return false; };
if !(snippet.starts_with("0x") || snippet.starts_with("0X")) {
return false;
}
@@ -1311,7 +1311,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// We have satisfied all requirements to provide a suggestion. Emit it.
err.span_suggestion(
- span,
+ *span,
format!("if you meant to create a null pointer, use `{null_path_str}()`"),
null_path_str + "()",
Applicability::MachineApplicable,
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs
index 3e9a9ce1b31..28c44aa5703 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs
@@ -215,6 +215,7 @@ impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> {
| ExprKind::Continue(..)
| ExprKind::Ret(..)
| ExprKind::InlineAsm(..)
+ | ExprKind::OffsetOf(..)
| ExprKind::Struct(..)
| ExprKind::Repeat(..)
| ExprKind::Yield(..)
@@ -485,6 +486,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DropRangeVisitor<'a, 'tcx> {
| ExprKind::Field(..)
| ExprKind::Index(..)
| ExprKind::InlineAsm(..)
+ | ExprKind::OffsetOf(..)
| ExprKind::Let(..)
| ExprKind::Lit(..)
| ExprKind::Path(..)
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs
index f7b493bc224..d3685d21f25 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs
@@ -268,8 +268,7 @@ impl DropRangesBuilder {
fn node_mut(&mut self, id: PostOrderId) -> &mut NodeInfo {
let size = self.num_values();
- self.nodes.ensure_contains_elem(id, || NodeInfo::new(size));
- &mut self.nodes[id]
+ self.nodes.ensure_contains_elem(id, || NodeInfo::new(size))
}
fn add_control_edge(&mut self, from: PostOrderId, to: PostOrderId) {
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
index f3971080443..8feef332de8 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
@@ -650,7 +650,7 @@ fn check_must_not_suspend_ty<'tcx>(
},
)
}
- // If drop tracking is enabled, we want to look through references, since the referrent
+ // If drop tracking is enabled, we want to look through references, since the referent
// may not be considered live across the await point.
ty::Ref(_region, ty, _mutability) if fcx.sess().opts.unstable_opts.drop_tracking => {
let descr_pre = &format!("{}reference{} to ", data.descr_pre, plural_suffix);
diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs
index 106f5bcd755..0fdb29a5e48 100644
--- a/compiler/rustc_hir_typeck/src/intrinsicck.rs
+++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs
@@ -4,7 +4,7 @@ use rustc_hir as hir;
use rustc_index::vec::Idx;
use rustc_middle::ty::layout::{LayoutError, SizeSkeleton};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
-use rustc_target::abi::{FieldIdx, Pointer, VariantIdx};
+use rustc_target::abi::{Pointer, VariantIdx};
use super::FnCtxt;
@@ -28,7 +28,7 @@ fn unpack_option_like<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
}
if def.variant(data_idx).fields.len() == 1 {
- return def.variant(data_idx).fields[FieldIdx::from_u32(0)].ty(tcx, substs);
+ return def.variant(data_idx).single_field().ty(tcx, substs);
}
}
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 45890abad92..08d3593f91f 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -59,6 +59,7 @@ use rustc_errors::{
struct_span_err, DiagnosticId, DiagnosticMessage, ErrorGuaranteed, MultiSpan,
SubdiagnosticMessage,
};
+use rustc_fluent_macro::fluent_messages;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::Visitor;
@@ -66,7 +67,6 @@ use rustc_hir::{HirIdMap, Node};
use rustc_hir_analysis::astconv::AstConv;
use rustc_hir_analysis::check::check_abi;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use rustc_macros::fluent_messages;
use rustc_middle::traits;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -156,21 +156,9 @@ fn typeck_item_bodies(tcx: TyCtxt<'_>, (): ()) {
tcx.hir().par_body_owners(|body_owner_def_id| tcx.ensure().typeck(body_owner_def_id));
}
-fn typeck_const_arg<'tcx>(
- tcx: TyCtxt<'tcx>,
- (did, param_did): (LocalDefId, DefId),
-) -> &ty::TypeckResults<'tcx> {
- let fallback = move || tcx.type_of(param_did).subst_identity();
- typeck_with_fallback(tcx, did, fallback)
-}
-
fn typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> {
- if let Some(param_did) = tcx.opt_const_param_of(def_id) {
- tcx.typeck_const_arg((def_id, param_did))
- } else {
- let fallback = move || tcx.type_of(def_id.to_def_id()).subst_identity();
- typeck_with_fallback(tcx, def_id, fallback)
- }
+ let fallback = move || tcx.type_of(def_id.to_def_id()).subst_identity();
+ typeck_with_fallback(tcx, def_id, fallback)
}
/// Used only to get `TypeckResults` for type inference during error recovery.
@@ -492,7 +480,6 @@ pub fn provide(providers: &mut Providers) {
method::provide(providers);
*providers = Providers {
typeck_item_bodies,
- typeck_const_arg,
typeck,
diagnostic_only_typeck,
has_typeck_results,
diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs
index 6c861b5930a..f5fca14eca8 100644
--- a/compiler/rustc_hir_typeck/src/mem_categorization.rs
+++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs
@@ -381,6 +381,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
| hir::ExprKind::Struct(..)
| hir::ExprKind::Repeat(..)
| hir::ExprKind::InlineAsm(..)
+ | hir::ExprKind::OffsetOf(..)
| hir::ExprKind::Err(_) => Ok(self.cat_rvalue(expr.hir_id, expr.span, expr_ty)),
}
}
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 900a6fa0d8d..db1f10f645f 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -1530,7 +1530,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
if pick.is_ok() {
let range_span = parent_expr.span.with_hi(expr.span.hi());
- tcx.sess.emit_err(errors::MissingParentheseInRange {
+ tcx.sess.emit_err(errors::MissingParenthesesInRange {
span,
ty_str: ty_str.to_string(),
method_name: item_name.as_str().to_string(),
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index af0bd26dec5..7160d1c67b2 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -1659,7 +1659,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if tcx.sess.teach(&err.get_code().unwrap()) {
err.note(
"This error indicates that a struct pattern attempted to \
- extract a non-existent field from a struct. Struct fields \
+ extract a nonexistent field from a struct. Struct fields \
are identified by the name used before the colon : so struct \
patterns should resemble the declaration of the struct type \
being matched.\n\n\
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index 41a6ad80b65..147b3e74d0f 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -223,7 +223,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let closure_hir_id = self.tcx.hir().local_def_id_to_hir_id(closure_def_id);
if should_do_rust_2021_incompatible_closure_captures_analysis(self.tcx, closure_hir_id) {
- self.perform_2229_migration_anaysis(closure_def_id, body_id, capture_clause, span);
+ self.perform_2229_migration_analysis(closure_def_id, body_id, capture_clause, span);
}
let after_feature_tys = self.final_upvar_tys(closure_def_id);
@@ -731,7 +731,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Perform the migration analysis for RFC 2229, and emit lint
/// `disjoint_capture_drop_reorder` if needed.
- fn perform_2229_migration_anaysis(
+ fn perform_2229_migration_analysis(
&self,
closure_def_id: LocalDefId,
body_id: hir::BodyId,
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index e876fa27593..9432a5840b2 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -70,6 +70,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
wbcx.visit_user_provided_tys();
wbcx.visit_user_provided_sigs();
wbcx.visit_generator_interior_types();
+ wbcx.visit_offset_of_container_types();
wbcx.typeck_results.rvalue_scopes =
mem::take(&mut self.typeck_results.borrow_mut().rvalue_scopes);
@@ -295,7 +296,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
self.visit_field_id(field.hir_id);
}
}
- hir::ExprKind::Field(..) => {
+ hir::ExprKind::Field(..) | hir::ExprKind::OffsetOf(..) => {
self.visit_field_id(e.hir_id);
}
hir::ExprKind::ConstBlock(anon_const) => {
@@ -682,6 +683,28 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
}
}
+ fn visit_offset_of_container_types(&mut self) {
+ let fcx_typeck_results = self.fcx.typeck_results.borrow();
+ assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
+ let common_hir_owner = fcx_typeck_results.hir_owner;
+
+ for (local_id, &(container, ref indices)) in
+ fcx_typeck_results.offset_of_data().items_in_stable_order()
+ {
+ let hir_id = hir::HirId { owner: common_hir_owner, local_id };
+
+ if cfg!(debug_assertions) && container.needs_infer() {
+ span_bug!(
+ hir_id.to_span(self.fcx.tcx),
+ "writeback: `{:?}` has inference variables",
+ container
+ );
+ };
+
+ self.typeck_results.offset_of_data_mut().insert(hir_id, (container, indices.clone()));
+ }
+ }
+
fn resolve<T>(&mut self, x: T, span: &dyn Locatable) -> T
where
T: TypeFoldable<TyCtxt<'tcx>>,
diff --git a/compiler/rustc_incremental/Cargo.toml b/compiler/rustc_incremental/Cargo.toml
index ad89393956e..59a0623c1e1 100644
--- a/compiler/rustc_incremental/Cargo.toml
+++ b/compiler/rustc_incremental/Cargo.toml
@@ -11,6 +11,7 @@ rustc_ast = { path = "../rustc_ast" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_fs_util = { path = "../rustc_fs_util" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_graphviz = { path = "../rustc_graphviz" }
rustc_hir = { path = "../rustc_hir" }
rustc_macros = { path = "../rustc_macros" }
diff --git a/compiler/rustc_incremental/src/lib.rs b/compiler/rustc_incremental/src/lib.rs
index df958e4a61f..11710c368ce 100644
--- a/compiler/rustc_incremental/src/lib.rs
+++ b/compiler/rustc_incremental/src/lib.rs
@@ -33,6 +33,6 @@ pub use persist::LoadResult;
pub use persist::{build_dep_graph, load_dep_graph, DepGraphFuture};
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
-use rustc_macros::fluent_messages;
+use rustc_fluent_macro::fluent_messages;
fluent_messages! { "../messages.ftl" }
diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs
index 1d88dfd20c8..43274091cb8 100644
--- a/compiler/rustc_incremental/src/persist/dirty_clean.rs
+++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs
@@ -139,7 +139,7 @@ pub fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) {
return;
}
- // can't add `#[rustc_clean]` etc without opting in to this feature
+ // can't add `#[rustc_clean]` etc without opting into this feature
if !tcx.features().rustc_attrs {
return;
}
diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs
index d6f83838a04..ec6d61f9e5f 100644
--- a/compiler/rustc_incremental/src/persist/fs.rs
+++ b/compiler/rustc_incremental/src/persist/fs.rs
@@ -601,7 +601,7 @@ fn string_to_timestamp(s: &str) -> Result<SystemTime, ()> {
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);
+ let stable_crate_id = base_n::encode(stable_crate_id.as_u64() as u128, INT_ENCODE_BASE);
let crate_name = format!("{}-{}", crate_name, stable_crate_id);
incr_dir.join(crate_name)
diff --git a/compiler/rustc_index/src/interval.rs b/compiler/rustc_index/src/interval.rs
index d809740c6ab..4605d42a15b 100644
--- a/compiler/rustc_index/src/interval.rs
+++ b/compiler/rustc_index/src/interval.rs
@@ -261,8 +261,7 @@ impl<R: Idx, C: Step + Idx> SparseIntervalMatrix<R, C> {
}
fn ensure_row(&mut self, row: R) -> &mut IntervalSet<C> {
- self.rows.ensure_contains_elem(row, || IntervalSet::new(self.column_size));
- &mut self.rows[row]
+ self.rows.ensure_contains_elem(row, || IntervalSet::new(self.column_size))
}
pub fn union_row(&mut self, row: R, from: &IntervalSet<C>) -> bool
diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs
index ae2f52c513e..18e779f786e 100644
--- a/compiler/rustc_index/src/vec.rs
+++ b/compiler/rustc_index/src/vec.rs
@@ -236,12 +236,16 @@ impl<I: Idx, T> IndexVec<I, T> {
/// `elem`; if that is already true, then has no
/// effect. Otherwise, inserts new values as needed by invoking
/// `fill_value`.
+ ///
+ /// Returns a reference to the `elem` entry.
#[inline]
- pub fn ensure_contains_elem(&mut self, elem: I, fill_value: impl FnMut() -> T) {
+ pub fn ensure_contains_elem(&mut self, elem: I, fill_value: impl FnMut() -> T) -> &mut T {
let min_new_len = elem.index() + 1;
if self.len() < min_new_len {
self.raw.resize_with(min_new_len, fill_value);
}
+
+ &mut self[elem]
}
#[inline]
@@ -446,20 +450,17 @@ impl<I: Idx, J: Idx> IndexSlice<I, J> {
impl<I: Idx, T> IndexVec<I, Option<T>> {
#[inline]
pub fn insert(&mut self, index: I, value: T) -> Option<T> {
- self.ensure_contains_elem(index, || None);
- self[index].replace(value)
+ self.ensure_contains_elem(index, || None).replace(value)
}
#[inline]
pub fn get_or_insert_with(&mut self, index: I, value: impl FnOnce() -> T) -> &mut T {
- self.ensure_contains_elem(index, || None);
- self[index].get_or_insert_with(value)
+ self.ensure_contains_elem(index, || None).get_or_insert_with(value)
}
#[inline]
pub fn remove(&mut self, index: I) -> Option<T> {
- self.ensure_contains_elem(index, || None);
- self[index].take()
+ self.get_mut(index)?.take()
}
}
diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml
index 02ac83a5e8b..9dd5868adc7 100644
--- a/compiler/rustc_infer/Cargo.toml
+++ b/compiler/rustc_infer/Cargo.toml
@@ -12,6 +12,7 @@ rustc_middle = { path = "../rustc_middle" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_hir = { path = "../rustc_hir" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_index = { path = "../rustc_index" }
rustc_macros = { path = "../rustc_macros" }
rustc_serialize = { path = "../rustc_serialize" }
diff --git a/compiler/rustc_infer/messages.ftl b/compiler/rustc_infer/messages.ftl
index c8998ea91bf..fdc4ff0896f 100644
--- a/compiler/rustc_infer/messages.ftl
+++ b/compiler/rustc_infer/messages.ftl
@@ -80,7 +80,7 @@ infer_subtype = ...so that the {$requirement ->
[no_else] `if` missing an `else` returns `()`
[fn_main_correct_type] `main` function has the correct type
[fn_start_correct_type] `#[start]` function has the correct type
- [intristic_correct_type] intrinsic has the correct type
+ [intrinsic_correct_type] intrinsic has the correct type
[method_correct_type] method receiver has the correct type
*[other] types are compatible
}
@@ -93,7 +93,7 @@ infer_subtype_2 = ...so that {$requirement ->
[no_else] `if` missing an `else` returns `()`
[fn_main_correct_type] `main` function has the correct type
[fn_start_correct_type] `#[start]` function has the correct type
- [intristic_correct_type] intrinsic has the correct type
+ [intrinsic_correct_type] intrinsic has the correct type
[method_correct_type] method receiver has the correct type
*[other] types are compatible
}
@@ -341,8 +341,8 @@ infer_await_note = calling an async function returns a future
infer_prlf_defined_with_sub = the lifetime `{$sub_symbol}` defined here...
infer_prlf_defined_without_sub = the lifetime defined here...
-infer_prlf_must_oultive_with_sup = ...must outlive the lifetime `{$sup_symbol}` defined here
-infer_prlf_must_oultive_without_sup = ...must outlive the lifetime defined here
+infer_prlf_must_outlive_with_sup = ...must outlive the lifetime `{$sup_symbol}` defined here
+infer_prlf_must_outlive_without_sup = ...must outlive the lifetime defined here
infer_prlf_known_limitation = this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
infer_opaque_captures_lifetime = hidden type for `{$opaque_ty}` captures lifetime that does not appear in bounds
@@ -380,7 +380,7 @@ infer_oc_no_else = `if` may be missing an `else` clause
infer_oc_no_diverge = `else` clause of `let...else` does not diverge
infer_oc_fn_main_correct_type = `main` function has wrong type
infer_oc_fn_start_correct_type = `#[start]` function has wrong type
-infer_oc_intristic_correct_type = intrinsic has wrong type
+infer_oc_intrinsic_correct_type = intrinsic has wrong type
infer_oc_method_correct_type = mismatched `self` parameter type
infer_oc_closure_selfref = closure/generator type that references itself
infer_oc_cant_coerce = cannot coerce intrinsics to function pointers
diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs
index 65b3dd1a892..b1e819e83f1 100644
--- a/compiler/rustc_infer/src/errors/mod.rs
+++ b/compiler/rustc_infer/src/errors/mod.rs
@@ -71,7 +71,7 @@ pub struct AmbiguousImpl<'a> {
// Copy of `AnnotationRequired` for E0284
#[derive(Diagnostic)]
#[diag(infer_type_annotations_needed, code = "E0284")]
-pub struct AmbigousReturn<'a> {
+pub struct AmbiguousReturn<'a> {
#[primary_span]
pub span: Span,
pub source_kind: &'static str,
@@ -1085,7 +1085,7 @@ pub enum PlaceholderRelationLfNotSatisfied {
span: Span,
#[note(infer_prlf_defined_with_sub)]
sub_span: Span,
- #[note(infer_prlf_must_oultive_with_sup)]
+ #[note(infer_prlf_must_outlive_with_sup)]
sup_span: Span,
sub_symbol: Symbol,
sup_symbol: Symbol,
@@ -1098,7 +1098,7 @@ pub enum PlaceholderRelationLfNotSatisfied {
span: Span,
#[note(infer_prlf_defined_with_sub)]
sub_span: Span,
- #[note(infer_prlf_must_oultive_without_sup)]
+ #[note(infer_prlf_must_outlive_without_sup)]
sup_span: Span,
sub_symbol: Symbol,
#[note(infer_prlf_known_limitation)]
@@ -1110,7 +1110,7 @@ pub enum PlaceholderRelationLfNotSatisfied {
span: Span,
#[note(infer_prlf_defined_without_sub)]
sub_span: Span,
- #[note(infer_prlf_must_oultive_with_sup)]
+ #[note(infer_prlf_must_outlive_with_sup)]
sup_span: Span,
sup_symbol: Symbol,
#[note(infer_prlf_known_limitation)]
@@ -1122,7 +1122,7 @@ pub enum PlaceholderRelationLfNotSatisfied {
span: Span,
#[note(infer_prlf_defined_without_sub)]
sub_span: Span,
- #[note(infer_prlf_must_oultive_without_sup)]
+ #[note(infer_prlf_must_outlive_without_sup)]
sup_span: Span,
#[note(infer_prlf_known_limitation)]
note: (),
@@ -1488,8 +1488,8 @@ pub enum ObligationCauseFailureCode {
#[subdiagnostic]
subdiags: Vec<TypeErrorAdditionalDiags>,
},
- #[diag(infer_oc_intristic_correct_type, code = "E0308")]
- IntristicCorrectType {
+ #[diag(infer_oc_intrinsic_correct_type, code = "E0308")]
+ IntrinsicCorrectType {
#[primary_span]
span: Span,
#[subdiagnostic]
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index e98f68ae5a8..257d3625929 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -467,11 +467,11 @@ impl<'tcx> InferCtxt<'tcx> {
}
}
GenericArgKind::Const(result_value) => {
- if let ty::ConstKind::Bound(debrujin, b) = result_value.kind() {
+ if let ty::ConstKind::Bound(debruijn, b) = result_value.kind() {
// ...in which case we would set `canonical_vars[0]` to `Some(const X)`.
// We only allow a `ty::INNERMOST` index in substitutions.
- assert_eq!(debrujin, ty::INNERMOST);
+ assert_eq!(debruijn, ty::INNERMOST);
opt_values[b] = Some(*original_value);
}
}
diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index fe45b5ebe61..9b670c76a18 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -832,7 +832,7 @@ pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> {
/// Register predicates that must hold in order for this relation to hold. Uses
/// a default obligation cause, [`ObligationEmittingRelation::register_obligations`] should
- /// be used if control over the obligaton causes is required.
+ /// be used if control over the obligation causes is required.
fn register_predicates(&mut self, obligations: impl IntoIterator<Item: ToPredicate<'tcx>>);
/// Register an obligation that both constants must be equal to each other.
diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs
index fe4a2dd3800..f90f7674b55 100644
--- a/compiler/rustc_infer/src/infer/equate.rs
+++ b/compiler/rustc_infer/src/infer/equate.rs
@@ -178,7 +178,7 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
where
T: Relate<'tcx>,
{
- // A binder is equal to itself if it's structually equal to itself
+ // A binder is equal to itself if it's structurally equal to itself
if a == b {
return Ok(a);
}
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 9e5f6d107d1..b0c376a26f6 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -74,7 +74,6 @@ use rustc_middle::ty::{
self, error::TypeError, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
TypeVisitable, TypeVisitableExt,
};
-use rustc_span::DUMMY_SP;
use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span};
use rustc_target::spec::abi;
use std::ops::{ControlFlow, Deref};
@@ -138,7 +137,7 @@ impl Drop for TypeErrCtxt<'_, '_> {
self.infcx
.tcx
.sess
- .delay_span_bug(DUMMY_SP, "used a `TypeErrCtxt` without failing compilation");
+ .delay_good_path_bug("used a `TypeErrCtxt` without raising an error or lint");
}
}
}
@@ -1927,6 +1926,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
{
let span = self.tcx.def_span(def_id);
diag.span_note(span, "this closure does not fulfill the lifetime requirements");
+ self.suggest_for_all_lifetime_closure(span, self.tcx.hir().get_by_def_id(def_id), &exp_found, diag);
}
// It reads better to have the error origin as the final
@@ -2885,7 +2885,7 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
LetElse => ObligationCauseFailureCode::NoDiverge { span, subdiags },
MainFunctionType => ObligationCauseFailureCode::FnMainCorrectType { span },
StartFunctionType => ObligationCauseFailureCode::FnStartCorrectType { span, subdiags },
- IntrinsicType => ObligationCauseFailureCode::IntristicCorrectType { span, subdiags },
+ IntrinsicType => ObligationCauseFailureCode::IntrinsicCorrectType { span, subdiags },
MethodReceiver => ObligationCauseFailureCode::MethodCorrectType { span, subdiags },
// In the case where we have no more specific thing to
@@ -2942,7 +2942,7 @@ impl IntoDiagnosticArg for ObligationCauseAsDiagArg<'_> {
IfExpressionWithNoElse => "no_else",
MainFunctionType => "fn_main_correct_type",
StartFunctionType => "fn_start_correct_type",
- IntrinsicType => "intristic_correct_type",
+ IntrinsicType => "intrinsic_correct_type",
MethodReceiver => "method_correct_type",
_ => "other",
}
diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index 75cc4e257bd..58e3159a4e2 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -1,5 +1,5 @@
use crate::errors::{
- AmbigousReturn, AmbiguousImpl, AnnotationRequired, InferenceBadError, NeedTypeInfoInGenerator,
+ AmbiguousImpl, AmbiguousReturn, AnnotationRequired, InferenceBadError, NeedTypeInfoInGenerator,
SourceKindMultiSuggestion, SourceKindSubdiag,
};
use crate::infer::error_reporting::TypeErrCtxt;
@@ -368,7 +368,7 @@ impl<'tcx> InferCtxt<'tcx> {
bad_label,
}
.into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic),
- TypeAnnotationNeeded::E0284 => AmbigousReturn {
+ TypeAnnotationNeeded::E0284 => AmbiguousReturn {
span,
source_kind,
source_name,
@@ -573,7 +573,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
bad_label: None,
}
.into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic),
- TypeAnnotationNeeded::E0284 => AmbigousReturn {
+ TypeAnnotationNeeded::E0284 => AmbiguousReturn {
span,
source_kind,
source_name: &name,
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
index 22c1e387117..27c3b796d14 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -312,13 +312,10 @@ pub fn suggest_new_region_bound(
Applicability::MaybeIncorrect,
);
}
- } else if opaque.bounds.iter().any(|arg| match arg {
- GenericBound::Outlives(Lifetime { ident, .. })
- if ident.name.to_string() == lifetime_name =>
- {
- true
- }
- _ => false,
+ } else if opaque.bounds.iter().any(|arg| {
+ matches!(arg,
+ GenericBound::Outlives(Lifetime { ident, .. })
+ if ident.name.to_string() == lifetime_name )
}) {
} else {
// get a lifetime name of existing named lifetimes if any
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
index 2875448ee15..ce70bcc5c85 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
@@ -13,7 +13,7 @@ use rustc_hir::intravisit::Visitor;
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::error::ExpectedFound;
use rustc_middle::ty::print::RegionHighlightMode;
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor};
use rustc_span::Span;
use std::ops::ControlFlow;
@@ -81,7 +81,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
self.highlight.highlighting_region(r, self.counter);
self.counter += 1;
}
- r.super_visit_with(self)
+ ControlFlow::Continue(())
}
}
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
index b38bbdfe7bb..e410172c8c8 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
@@ -462,10 +462,7 @@ fn foo(&self) -> Self::T { String::new() }
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 &tcx.hir().expect_item(opaque_local_def_id).kind {
- hir::ItemKind::OpaqueTy(opaque_hir_ty) => opaque_hir_ty,
- _ => bug!("The HirId comes from a `ty::Opaque`"),
- }
+ tcx.hir().expect_item(opaque_local_def_id).expect_opaque_ty()
} else {
return false;
};
diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
index b5aeca12a1f..d885d040707 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
@@ -1,16 +1,15 @@
use hir::def::CtorKind;
use hir::intravisit::{walk_expr, walk_stmt, Visitor};
use rustc_data_structures::fx::FxIndexSet;
-use rustc_errors::Diagnostic;
+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, IsSuggestable, Ty, TypeVisitableExt};
+use rustc_middle::ty::{self as ty, GenericArgKind, IsSuggestable, Ty, TypeVisitableExt};
use rustc_span::{sym, BytePos, Span};
-use rustc_target::abi::FieldIdx;
use crate::errors::{
ConsiderAddingAwait, FnConsiderCasting, FnItemsAreDistinct, FnUniqTypes,
@@ -114,7 +113,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
variant.fields.len() == 1 && variant.ctor_kind() == Some(CtorKind::Fn)
})
.filter_map(|variant| {
- let sole_field = &variant.fields[FieldIdx::from_u32(0)];
+ let sole_field = &variant.single_field();
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 =
@@ -536,6 +535,82 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}
None
}
+
+ /// For "one type is more general than the other" errors on closures, suggest changing the lifetime
+ /// of the parameters to accept all lifetimes.
+ pub(super) fn suggest_for_all_lifetime_closure(
+ &self,
+ span: Span,
+ hir: hir::Node<'_>,
+ exp_found: &ty::error::ExpectedFound<ty::PolyTraitRef<'tcx>>,
+ diag: &mut Diagnostic,
+ ) {
+ // 0. Extract fn_decl from hir
+ let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(hir::Closure { body, fn_decl, .. }), .. }) = hir else { return; };
+ let hir::Body { params, .. } = self.tcx.hir().body(*body);
+
+ // 1. Get the substs of the closure.
+ // 2. Assume exp_found is FnOnce / FnMut / Fn, we can extract function parameters from [1].
+ let Some(expected) = exp_found.expected.skip_binder().substs.get(1) else { return; };
+ let Some(found) = exp_found.found.skip_binder().substs.get(1) else { return; };
+ let expected = expected.unpack();
+ let found = found.unpack();
+ // 3. Extract the tuple type from Fn trait and suggest the change.
+ if let GenericArgKind::Type(expected) = expected &&
+ let GenericArgKind::Type(found) = found &&
+ let ty::Tuple(expected) = expected.kind() &&
+ let ty::Tuple(found)= found.kind() &&
+ expected.len() == found.len() {
+ let mut suggestion = "|".to_string();
+ let mut is_first = true;
+ let mut has_suggestion = false;
+
+ for (((expected, found), param_hir), arg_hir) in expected.iter()
+ .zip(found.iter())
+ .zip(params.iter())
+ .zip(fn_decl.inputs.iter()) {
+ if is_first {
+ is_first = false;
+ } else {
+ suggestion += ", ";
+ }
+
+ if let ty::Ref(expected_region, _, _) = expected.kind() &&
+ let ty::Ref(found_region, _, _) = found.kind() &&
+ expected_region.is_late_bound() &&
+ !found_region.is_late_bound() &&
+ let hir::TyKind::Infer = arg_hir.kind {
+ // If the expected region is late bound, the found region is not, and users are asking compiler
+ // to infer the type, we can suggest adding `: &_`.
+ if param_hir.pat.span == param_hir.ty_span {
+ // for `|x|`, `|_|`, `|x: impl Foo|`
+ let Ok(pat) = self.tcx.sess.source_map().span_to_snippet(param_hir.pat.span) else { return; };
+ suggestion += &format!("{}: &_", pat);
+ } else {
+ // for `|x: ty|`, `|_: ty|`
+ let Ok(pat) = self.tcx.sess.source_map().span_to_snippet(param_hir.pat.span) else { return; };
+ let Ok(ty) = self.tcx.sess.source_map().span_to_snippet(param_hir.ty_span) else { return; };
+ suggestion += &format!("{}: &{}", pat, ty);
+ }
+ has_suggestion = true;
+ } else {
+ let Ok(arg) = self.tcx.sess.source_map().span_to_snippet(param_hir.span) else { return; };
+ // Otherwise, keep it as-is.
+ suggestion += &arg;
+ }
+ }
+ suggestion += "|";
+
+ if has_suggestion {
+ diag.span_suggestion_verbose(
+ span,
+ "consider specifying the type of the closure parameters",
+ suggestion,
+ Applicability::MaybeIncorrect,
+ );
+ }
+ }
+ }
}
impl<'tcx> TypeErrCtxt<'_, 'tcx> {
diff --git a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
index a63cfbc919c..c304cd25c9c 100644
--- a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
+++ b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
@@ -42,7 +42,7 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> {
// Next, we instantiate each bound region in the subtype
// with a fresh region variable. These region variables --
- // but no other pre-existing region variables -- can name
+ // but no other preexisting region variables -- can name
// the placeholders.
let sub_prime = self.infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, sub);
diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
index f298b95ca35..df15cab00b4 100644
--- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
+++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
@@ -131,10 +131,9 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
self.dump_constraints();
}
- let graph = self.construct_graph();
self.expansion(&mut var_data);
self.collect_errors(&mut var_data, errors);
- self.collect_var_errors(&var_data, &graph, errors);
+ self.collect_var_errors(&var_data, errors);
var_data
}
@@ -622,7 +621,6 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
fn collect_var_errors(
&self,
var_data: &LexicalRegionResolutions<'tcx>,
- graph: &RegionGraph<'tcx>,
errors: &mut Vec<RegionResolutionError<'tcx>>,
) {
debug!("collect_var_errors, var_data = {:#?}", var_data.values);
@@ -640,6 +638,10 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
// overlapping locations.
let mut dup_vec = IndexVec::from_elem_n(None, self.num_vars());
+ // Only construct the graph when necessary, because it's moderately
+ // expensive.
+ let mut graph = None;
+
for (node_vid, value) in var_data.values.iter_enumerated() {
match *value {
VarValue::Empty(_) | VarValue::Value(_) => { /* Inference successful */ }
@@ -672,7 +674,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
// influence the constraints on this value for
// richer diagnostics in `static_impl_trait`.
- self.collect_error_for_expanding_node(graph, &mut dup_vec, node_vid, errors);
+ let g = graph.get_or_insert_with(|| self.construct_graph());
+ self.collect_error_for_expanding_node(g, &mut dup_vec, node_vid, errors);
}
}
}
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 66f51328bbe..3e80bb906e4 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -1500,7 +1500,7 @@ impl<'tcx> InferCtxt<'tcx> {
Ok(Some(val)) => Ok(self.tcx.mk_const(val, ty)),
Ok(None) => {
let tcx = self.tcx;
- let def_id = unevaluated.def.did;
+ let def_id = unevaluated.def;
span_bug!(
tcx.def_span(def_id),
"unable to construct a constant value for the unevaluated constant {:?}",
@@ -1547,8 +1547,8 @@ impl<'tcx> InferCtxt<'tcx> {
substs = replace_param_and_infer_substs_with_placeholder(tcx, substs);
}
} else {
- substs = InternalSubsts::identity_for_item(tcx, unevaluated.def.did);
- param_env = tcx.param_env(unevaluated.def.did);
+ substs = InternalSubsts::identity_for_item(tcx, unevaluated.def);
+ param_env = tcx.param_env(unevaluated.def);
}
}
@@ -1577,10 +1577,10 @@ impl<'tcx> InferCtxt<'tcx> {
(TyOrConstInferVar::Ty(ty_var), Ok(inner)) => {
use self::type_variable::TypeVariableValue;
- match inner.try_type_variables_probe_ref(ty_var) {
- Some(TypeVariableValue::Unknown { .. }) => true,
- _ => false,
- }
+ matches!(
+ inner.try_type_variables_probe_ref(ty_var),
+ Some(TypeVariableValue::Unknown { .. })
+ )
}
_ => false,
};
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index 3a0a0494a7e..680465bdab6 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -392,12 +392,7 @@ impl<'tcx> InferCtxt<'tcx> {
/// defining scope.
#[instrument(skip(self), level = "trace", ret)]
fn opaque_type_origin_unchecked(&self, def_id: LocalDefId) -> OpaqueTyOrigin {
- match self.tcx.hir().expect_item(def_id).kind {
- hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => origin,
- ref itemkind => {
- bug!("weird opaque type: {:?}, {:#?}", def_id, itemkind)
- }
- }
+ self.tcx.hir().expect_item(def_id).expect_opaque_ty().origin
}
}
diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs
index ff23087fe8d..cb63d2f18b6 100644
--- a/compiler/rustc_infer/src/infer/outlives/components.rs
+++ b/compiler/rustc_infer/src/infer/outlives/components.rs
@@ -143,7 +143,7 @@ fn compute_components<'tcx>(
// through and constrain Pi.
let mut subcomponents = smallvec![];
let mut subvisited = SsoHashSet::new();
- compute_components_recursive(tcx, ty.into(), &mut subcomponents, &mut subvisited);
+ compute_alias_components_recursive(tcx, ty, &mut subcomponents, &mut subvisited);
out.push(Component::EscapingAlias(subcomponents.into_iter().collect()));
}
}
@@ -193,7 +193,43 @@ fn compute_components<'tcx>(
///
/// This should not be used to get the components of `parent` itself.
/// Use [push_outlives_components] instead.
-pub(super) fn compute_components_recursive<'tcx>(
+pub(super) fn compute_alias_components_recursive<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ alias_ty: Ty<'tcx>,
+ out: &mut SmallVec<[Component<'tcx>; 4]>,
+ visited: &mut SsoHashSet<GenericArg<'tcx>>,
+) {
+ let ty::Alias(kind, alias_ty) = alias_ty.kind() else { bug!() };
+ let opt_variances = if *kind == ty::Opaque { tcx.variances_of(alias_ty.def_id) } else { &[] };
+ for (index, child) in alias_ty.substs.iter().enumerate() {
+ if opt_variances.get(index) == Some(&ty::Bivariant) {
+ continue;
+ }
+ if !visited.insert(child) {
+ continue;
+ }
+ match child.unpack() {
+ GenericArgKind::Type(ty) => {
+ compute_components(tcx, ty, out, visited);
+ }
+ GenericArgKind::Lifetime(lt) => {
+ // Ignore late-bound regions.
+ if !lt.is_late_bound() {
+ out.push(Component::Region(lt));
+ }
+ }
+ GenericArgKind::Const(_) => {
+ compute_components_recursive(tcx, child, out, visited);
+ }
+ }
+ }
+}
+
+/// Collect [Component]s for *all* the substs of `parent`.
+///
+/// This should not be used to get the components of `parent` itself.
+/// Use [push_outlives_components] instead.
+fn compute_components_recursive<'tcx>(
tcx: TyCtxt<'tcx>,
parent: GenericArg<'tcx>,
out: &mut SmallVec<[Component<'tcx>; 4]>,
diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs
index ccf11c61b57..2f5e2e417a6 100644
--- a/compiler/rustc_infer/src/infer/outlives/obligations.rs
+++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs
@@ -344,12 +344,14 @@ where
// the problem is to add `T: 'r`, which isn't true. So, if there are no
// inference variables, we use a verify constraint instead of adding
// edges, which winds up enforcing the same condition.
+ let is_opaque = alias_ty.kind(self.tcx) == ty::Opaque;
if approx_env_bounds.is_empty()
&& trait_bounds.is_empty()
- && (alias_ty.needs_infer() || alias_ty.kind(self.tcx) == ty::Opaque)
+ && (alias_ty.needs_infer() || is_opaque)
{
debug!("no declared bounds");
- self.substs_must_outlive(alias_ty.substs, origin, region);
+ let opt_variances = is_opaque.then(|| self.tcx.variances_of(alias_ty.def_id));
+ self.substs_must_outlive(alias_ty.substs, origin, region, opt_variances);
return;
}
@@ -395,22 +397,31 @@ where
self.delegate.push_verify(origin, GenericKind::Alias(alias_ty), region, verify_bound);
}
+ #[instrument(level = "debug", skip(self))]
fn substs_must_outlive(
&mut self,
substs: SubstsRef<'tcx>,
origin: infer::SubregionOrigin<'tcx>,
region: ty::Region<'tcx>,
+ opt_variances: Option<&[ty::Variance]>,
) {
let constraint = origin.to_constraint_category();
- for k in substs {
+ for (index, k) in substs.iter().enumerate() {
match k.unpack() {
GenericArgKind::Lifetime(lt) => {
- self.delegate.push_sub_region_constraint(
- origin.clone(),
- region,
- lt,
- constraint,
- );
+ let variance = if let Some(variances) = opt_variances {
+ variances[index]
+ } else {
+ ty::Invariant
+ };
+ if variance == ty::Invariant {
+ self.delegate.push_sub_region_constraint(
+ origin.clone(),
+ region,
+ lt,
+ constraint,
+ );
+ }
}
GenericArgKind::Type(ty) => {
self.type_must_outlive(origin.clone(), ty, region, constraint);
diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs
index bae246418b0..e1cb53bc71d 100644
--- a/compiler/rustc_infer/src/infer/outlives/verify.rs
+++ b/compiler/rustc_infer/src/infer/outlives/verify.rs
@@ -1,4 +1,4 @@
-use crate::infer::outlives::components::{compute_components_recursive, Component};
+use crate::infer::outlives::components::{compute_alias_components_recursive, Component};
use crate::infer::outlives::env::RegionBoundPairs;
use crate::infer::region_constraints::VerifyIfEq;
use crate::infer::VerifyBound;
@@ -130,7 +130,12 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
// see the extensive comment in projection_must_outlive
let recursive_bound = {
let mut components = smallvec![];
- compute_components_recursive(self.tcx, alias_ty_as_ty.into(), &mut components, visited);
+ compute_alias_components_recursive(
+ self.tcx,
+ alias_ty_as_ty.into(),
+ &mut components,
+ visited,
+ );
self.bound_from_components(&components, visited)
};
diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs
index 0dd73a6e999..3766c250a9c 100644
--- a/compiler/rustc_infer/src/infer/sub.rs
+++ b/compiler/rustc_infer/src/infer/sub.rs
@@ -210,7 +210,7 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
where
T: Relate<'tcx>,
{
- // A binder is always a subtype of itself if it's structually equal to itself
+ // A binder is always a subtype of itself if it's structurally equal to itself
if a == b {
return Ok(a);
}
diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs
index 738a1237651..e92ba05aa67 100644
--- a/compiler/rustc_infer/src/lib.rs
+++ b/compiler/rustc_infer/src/lib.rs
@@ -35,7 +35,7 @@ extern crate tracing;
extern crate rustc_middle;
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
-use rustc_macros::fluent_messages;
+use rustc_fluent_macro::fluent_messages;
mod errors;
pub mod infer;
diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs
index e01b6caf430..9dd4f0a8e4c 100644
--- a/compiler/rustc_infer/src/traits/mod.rs
+++ b/compiler/rustc_infer/src/traits/mod.rs
@@ -89,10 +89,10 @@ impl<'tcx> PredicateObligation<'tcx> {
impl<'tcx> TraitObligation<'tcx> {
/// Returns `true` if the trait predicate is considered `const` in its ParamEnv.
pub fn is_const(&self) -> bool {
- match (self.predicate.skip_binder().constness, self.param_env.constness()) {
- (ty::BoundConstness::ConstIfConst, hir::Constness::Const) => true,
- _ => false,
- }
+ matches!(
+ (self.predicate.skip_binder().constness, self.param_env.constness()),
+ (ty::BoundConstness::ConstIfConst, hir::Constness::Const)
+ )
}
pub fn derived_cause(
diff --git a/compiler/rustc_infer/src/traits/project.rs b/compiler/rustc_infer/src/traits/project.rs
index ac455055b43..8d0af738dd1 100644
--- a/compiler/rustc_infer/src/traits/project.rs
+++ b/compiler/rustc_infer/src/traits/project.rs
@@ -103,7 +103,7 @@ pub enum ProjectionCacheEntry<'tcx> {
/// if this field is set. Evaluation only
/// cares about the final result, so we don't
/// care about any region constraint side-effects
- /// produced by evaluating the sub-boligations.
+ /// produced by evaluating the sub-obligations.
///
/// Additionally, we will clear out the sub-obligations
/// entirely if we ever evaluate the cache entry (along
diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml
index 98d3ab87f9c..4569c35e182 100644
--- a/compiler/rustc_interface/Cargo.toml
+++ b/compiler/rustc_interface/Cargo.toml
@@ -16,6 +16,7 @@ rustc_attr = { path = "../rustc_attr" }
rustc_borrowck = { path = "../rustc_borrowck" }
rustc_builtin_macros = { path = "../rustc_builtin_macros" }
rustc_expand = { path = "../rustc_expand" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_fs_util = { path = "../rustc_fs_util" }
rustc_macros = { path = "../rustc_macros" }
rustc_parse = { path = "../rustc_parse" }
diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs
index 9664ba8bd8a..51bd8381e93 100644
--- a/compiler/rustc_interface/src/lib.rs
+++ b/compiler/rustc_interface/src/lib.rs
@@ -13,7 +13,7 @@
extern crate tracing;
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
-use rustc_macros::fluent_messages;
+use rustc_fluent_macro::fluent_messages;
mod callbacks;
mod errors;
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 0e4e20c7cd1..de78f26eec6 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -794,9 +794,14 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
}
tcx.ensure().has_ffi_unwind_calls(def_id);
- if tcx.hir().body_const_context(def_id).is_some() {
- tcx.ensure()
- .mir_drops_elaborated_and_const_checked(ty::WithOptConstParam::unknown(def_id));
+ // If we need to codegen, ensure that we emit all errors from
+ // `mir_drops_elaborated_and_const_checked` now, to avoid discovering
+ // them later during codegen.
+ if tcx.sess.opts.output_types.should_codegen()
+ || tcx.hir().body_const_context(def_id).is_some()
+ {
+ tcx.ensure().mir_drops_elaborated_and_const_checked(def_id);
+ tcx.ensure().unused_generic_params(ty::InstanceDef::Item(def_id.to_def_id()));
}
}
});
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 101967503c1..ce0f90bc1cc 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -747,7 +747,7 @@ fn test_unstable_options_tracking_hash() {
tracked!(emit_thin_lto, false);
tracked!(export_executable_symbols, true);
tracked!(fewer_names, Some(true));
- tracked!(flatten_format_args, true);
+ tracked!(flatten_format_args, false);
tracked!(force_unstable_if_unmarked, true);
tracked!(fuel, Some(("abc".to_string(), 99)));
tracked!(function_sections, Some(false));
@@ -768,6 +768,7 @@ fn test_unstable_options_tracking_hash() {
tracked!(merge_functions, Some(MergeFunctions::Disabled));
tracked!(mir_emit_retag, true);
tracked!(mir_enable_passes, vec![("DestProp".to_string(), false)]);
+ tracked!(mir_keep_place_mention, true);
tracked!(mir_opt_level, Some(4));
tracked!(move_size_limit, Some(4096));
tracked!(mutable_noalias, false);
diff --git a/compiler/rustc_lint/Cargo.toml b/compiler/rustc_lint/Cargo.toml
index abe61406c21..539eea3d816 100644
--- a/compiler/rustc_lint/Cargo.toml
+++ b/compiler/rustc_lint/Cargo.toml
@@ -11,6 +11,7 @@ rustc_ast_pretty = { path = "../rustc_ast_pretty" }
rustc_attr = { path = "../rustc_attr" }
rustc_errors = { path = "../rustc_errors" }
rustc_hir = { path = "../rustc_hir" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_target = { path = "../rustc_target" }
rustc_ast = { path = "../rustc_ast" }
rustc_span = { path = "../rustc_span" }
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index db15b176df0..3d1b8f8ed95 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -445,7 +445,7 @@ lint_builtin_incomplete_features = the feature `{$name}` is incomplete and may n
.help = consider using `min_{$name}` instead, which is more stable and complete
lint_builtin_unpermitted_type_init_zeroed = the type `{$ty}` does not permit zero-initialization
-lint_builtin_unpermitted_type_init_unint = the type `{$ty}` does not permit being left uninitialized
+lint_builtin_unpermitted_type_init_uninit = the type `{$ty}` does not permit being left uninitialized
lint_builtin_unpermitted_type_init_label = this code causes undefined behavior when executed
lint_builtin_unpermitted_type_init_label_suggestion = help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 6b387df785e..aeb791901bd 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -22,7 +22,7 @@
use crate::fluent_generated as fluent;
use crate::{
- errors::BuiltinEllpisisInclusiveRangePatterns,
+ errors::BuiltinEllipsisInclusiveRangePatterns,
lints::{
BuiltinAnonymousParams, BuiltinBoxPointers, BuiltinClashingExtern,
BuiltinClashingExternSub, BuiltinConstNoMangle, BuiltinDeprecatedAttrLink,
@@ -166,10 +166,8 @@ declare_lint_pass!(BoxPointers => [BOX_POINTERS]);
impl BoxPointers {
fn check_heap_type(&self, cx: &LateContext<'_>, span: Span, ty: Ty<'_>) {
for leaf in ty.walk() {
- if let GenericArgKind::Type(leaf_ty) = leaf.unpack() {
- if leaf_ty.is_box() {
- cx.emit_spanned_lint(BOX_POINTERS, span, BuiltinBoxPointers { ty });
- }
+ if let GenericArgKind::Type(leaf_ty) = leaf.unpack() && leaf_ty.is_box() {
+ cx.emit_spanned_lint(BOX_POINTERS, span, BuiltinBoxPointers { ty });
}
}
}
@@ -1711,13 +1709,13 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns {
}
}
- let (parenthesise, endpoints) = match &pat.kind {
+ let (parentheses, endpoints) = match &pat.kind {
PatKind::Ref(subpat, _) => (true, matches_ellipsis_pat(&subpat)),
_ => (false, matches_ellipsis_pat(pat)),
};
if let Some((start, end, join)) = endpoints {
- if parenthesise {
+ if parentheses {
self.node_id = Some(pat.id);
let end = expr_to_string(&end);
let replace = match start {
@@ -1725,7 +1723,7 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns {
None => format!("&(..={})", end),
};
if join.edition() >= Edition::Edition2021 {
- cx.sess().emit_err(BuiltinEllpisisInclusiveRangePatterns {
+ cx.sess().emit_err(BuiltinEllipsisInclusiveRangePatterns {
span: pat.span,
suggestion: pat.span,
replace,
@@ -1743,7 +1741,7 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns {
} else {
let replace = "..=";
if join.edition() >= Edition::Edition2021 {
- cx.sess().emit_err(BuiltinEllpisisInclusiveRangePatterns {
+ cx.sess().emit_err(BuiltinEllipsisInclusiveRangePatterns {
span: pat.span,
suggestion: join,
replace: replace.to_string(),
@@ -2560,7 +2558,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
.subst(cx.tcx, substs)
.apply_any_module(cx.tcx, cx.param_env)
{
- // Entirely skip uninhbaited variants.
+ // Entirely skip uninhabited variants.
Some(false) => return None,
// Forward the others, but remember which ones are definitely inhabited.
Some(true) => true,
@@ -2628,7 +2626,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
if let Some(err) = with_no_trimmed_paths!(ty_find_init_error(cx, conjured_ty, init)) {
let msg = match init {
InitKind::Zeroed => fluent::lint_builtin_unpermitted_type_init_zeroed,
- InitKind::Uninit => fluent::lint_builtin_unpermitted_type_init_unint,
+ InitKind::Uninit => fluent::lint_builtin_unpermitted_type_init_uninit,
};
let sub = BuiltinUnpermittedTypeInitSub { err };
cx.emit_spanned_lint(
diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs
index 9af5284df1e..bbae3d368f4 100644
--- a/compiler/rustc_lint/src/errors.rs
+++ b/compiler/rustc_lint/src/errors.rs
@@ -81,7 +81,7 @@ pub struct UnknownToolInScopedLint {
#[derive(Diagnostic)]
#[diag(lint_builtin_ellipsis_inclusive_range_patterns, code = "E0783")]
-pub struct BuiltinEllpisisInclusiveRangePatterns {
+pub struct BuiltinEllipsisInclusiveRangePatterns {
#[primary_span]
pub span: Span,
#[suggestion(style = "short", code = "{replace}", applicability = "machine-applicable")]
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index b3578540516..76f07257907 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -82,9 +82,9 @@ pub use array_into_iter::ARRAY_INTO_ITER;
use rustc_ast as ast;
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
+use rustc_fluent_macro::fluent_messages;
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
-use rustc_macros::fluent_messages;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_session::lint::builtin::{
diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs
index 9efc14849c7..79253cbc8b4 100644
--- a/compiler/rustc_lint/src/nonstandard_style.rs
+++ b/compiler/rustc_lint/src/nonstandard_style.rs
@@ -33,6 +33,11 @@ pub fn method_context(cx: &LateContext<'_>, id: LocalDefId) -> MethodLateContext
}
}
+fn assoc_item_in_trait_impl(cx: &LateContext<'_>, ii: &hir::ImplItem<'_>) -> bool {
+ let item = cx.tcx.associated_item(ii.owner_id);
+ item.trait_item_def_id.is_some()
+}
+
declare_lint! {
/// The `non_camel_case_types` lint detects types, variants, traits and
/// type parameters that don't have camel case names.
@@ -177,6 +182,7 @@ impl EarlyLintPass for NonCamelCaseTypes {
// 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 {
+ // FIXME: this doesn't respect `#[allow(..)]` on the item itself.
if let ast::AssocItemKind::Type(..) = it.kind {
self.check_case(cx, "associated type", &it.ident);
}
@@ -505,7 +511,7 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals {
}
fn check_impl_item(&mut self, cx: &LateContext<'_>, ii: &hir::ImplItem<'_>) {
- if let hir::ImplItemKind::Const(..) = ii.kind {
+ if let hir::ImplItemKind::Const(..) = ii.kind && !assoc_item_in_trait_impl(cx, ii) {
NonUpperCaseGlobals::check_upper_case(cx, "associated constant", &ii.ident);
}
}
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 1159d11e5c0..d677d51881e 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -569,36 +569,50 @@ trait UnusedDelimLint {
}
}
- // Prevent false-positives in cases like `fn x() -> u8 { ({ 0 } + 1) }`
- let lhs_needs_parens = {
+ // Check if LHS needs parens to prevent false-positives in cases like `fn x() -> u8 { ({ 0 } + 1) }`.
+ {
let mut innermost = inner;
loop {
innermost = match &innermost.kind {
- ExprKind::Binary(_, lhs, _rhs) => lhs,
+ ExprKind::Binary(_op, lhs, _rhs) => lhs,
ExprKind::Call(fn_, _params) => fn_,
ExprKind::Cast(expr, _ty) => expr,
ExprKind::Type(expr, _ty) => expr,
ExprKind::Index(base, _subscript) => base,
- _ => break false,
+ _ => break,
};
if !classify::expr_requires_semi_to_be_stmt(innermost) {
- break true;
+ return true;
}
}
- };
+ }
- lhs_needs_parens
- || (followed_by_block
- && match &inner.kind {
- ExprKind::Ret(_)
- | ExprKind::Break(..)
- | ExprKind::Yield(..)
- | ExprKind::Yeet(..) => true,
- ExprKind::Range(_lhs, Some(rhs), _limits) => {
- matches!(rhs.kind, ExprKind::Block(..))
- }
- _ => parser::contains_exterior_struct_lit(&inner),
- })
+ // Check if RHS needs parens to prevent false-positives in cases like `if (() == return) {}`.
+ if !followed_by_block {
+ return false;
+ }
+ let mut innermost = inner;
+ loop {
+ innermost = match &innermost.kind {
+ ExprKind::Unary(_op, expr) => expr,
+ ExprKind::Binary(_op, _lhs, rhs) => rhs,
+ ExprKind::AssignOp(_op, _lhs, rhs) => rhs,
+ ExprKind::Assign(_lhs, rhs, _span) => rhs,
+
+ ExprKind::Ret(_) | ExprKind::Yield(..) | ExprKind::Yeet(..) => return true,
+
+ ExprKind::Break(_label, None) => return false,
+ ExprKind::Break(_label, Some(break_expr)) => {
+ return matches!(break_expr.kind, ExprKind::Block(..));
+ }
+
+ ExprKind::Range(_lhs, Some(rhs), _limits) => {
+ return matches!(rhs.kind, ExprKind::Block(..));
+ }
+
+ _ => return parser::contains_exterior_struct_lit(&inner),
+ }
+ }
}
fn emit_unused_delims_expr(
@@ -636,20 +650,14 @@ trait UnusedDelimLint {
return;
}
let spans = match value.kind {
- ast::ExprKind::Block(ref block, None) if block.stmts.len() == 1 => {
- if let Some(span) = block.stmts[0].span.find_ancestor_inside(value.span) {
- Some((value.span.with_hi(span.lo()), value.span.with_lo(span.hi())))
- } else {
- None
- }
- }
+ ast::ExprKind::Block(ref block, None) if block.stmts.len() == 1 => block.stmts[0]
+ .span
+ .find_ancestor_inside(value.span)
+ .map(|span| (value.span.with_hi(span.lo()), value.span.with_lo(span.hi()))),
ast::ExprKind::Paren(ref expr) => {
- let expr_span = expr.span.find_ancestor_inside(value.span);
- if let Some(expr_span) = expr_span {
- Some((value.span.with_hi(expr_span.lo()), value.span.with_lo(expr_span.hi())))
- } else {
- None
- }
+ expr.span.find_ancestor_inside(value.span).map(|expr_span| {
+ (value.span.with_hi(expr_span.lo()), value.span.with_lo(expr_span.hi()))
+ })
}
_ => return,
};
@@ -928,11 +936,10 @@ impl UnusedParens {
// Otherwise proceed with linting.
_ => {}
}
- let spans = if let Some(inner) = inner.span.find_ancestor_inside(value.span) {
- Some((value.span.with_hi(inner.lo()), value.span.with_lo(inner.hi())))
- } else {
- None
- };
+ let spans = inner
+ .span
+ .find_ancestor_inside(value.span)
+ .map(|inner| (value.span.with_hi(inner.lo()), value.span.with_lo(inner.hi())));
self.emit_unused_delims(cx, value.span, spans, "pattern", keep_space);
}
}
@@ -1043,11 +1050,11 @@ impl EarlyLintPass for UnusedParens {
if self.with_self_ty_parens && b.generic_params.len() > 0 => {}
ast::TyKind::ImplTrait(_, bounds) if bounds.len() > 1 => {}
_ => {
- let spans = if let Some(r) = r.span.find_ancestor_inside(ty.span) {
- Some((ty.span.with_hi(r.lo()), ty.span.with_lo(r.hi())))
- } else {
- None
- };
+ let spans = r
+ .span
+ .find_ancestor_inside(ty.span)
+ .map(|r| (ty.span.with_hi(r.lo()), ty.span.with_lo(r.hi())));
+
self.emit_unused_delims(cx, ty.span, spans, "type", (false, false));
}
}
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 9d6ab0b75df..b223b8c137a 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -1021,7 +1021,7 @@ declare_lint! {
declare_lint! {
/// The `invalid_alignment` lint detects dereferences of misaligned pointers during
- /// constant evluation.
+ /// constant evaluation.
///
/// ### Example
///
@@ -1854,7 +1854,7 @@ declare_lint! {
/// When new methods are added to traits in the standard library, they are
/// usually added in an "unstable" form which is only available on the
/// [nightly channel] with a [`feature` attribute]. If there is any
- /// pre-existing code which extends a trait to have a method with the same
+ /// preexisting code which extends a trait to have a method with the same
/// name, then the names will collide. In the future, when the method is
/// stabilized, this will cause an error due to the ambiguity. This lint
/// is an early-warning to let you know that there may be a collision in
diff --git a/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp
index 448a1f62f69..35d6b9ed7a4 100644
--- a/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp
@@ -39,6 +39,7 @@ enum class LLVMRustArchiveKind {
BSD,
DARWIN,
COFF,
+ AIX_BIG,
};
static Archive::Kind fromRust(LLVMRustArchiveKind Kind) {
@@ -51,6 +52,8 @@ static Archive::Kind fromRust(LLVMRustArchiveKind Kind) {
return Archive::K_DARWIN;
case LLVMRustArchiveKind::COFF:
return Archive::K_COFF;
+ case LLVMRustArchiveKind::AIX_BIG:
+ return Archive::K_AIXBIG;
default:
report_fatal_error("Bad ArchiveKind.");
}
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 08e38b0c9d5..c9acbab253e 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -811,7 +811,7 @@ LLVMRustOptimize(
ModulePassManager MPM;
bool NeedThinLTOBufferPasses = UseThinLTOBuffers;
if (!NoPrepopulatePasses) {
- // The pre-link pipelines don't support O0 and require using budilO0DefaultPipeline() instead.
+ // The pre-link pipelines don't support O0 and require using buildO0DefaultPipeline() instead.
// At the same time, the LTO pipelines do support O0 and using them is required.
bool IsLTO = OptStage == LLVMRustOptStage::ThinLTO || OptStage == LLVMRustOptStage::FatLTO;
if (OptLevel == OptimizationLevel::O0 && !IsLTO) {
diff --git a/compiler/rustc_macros/Cargo.toml b/compiler/rustc_macros/Cargo.toml
index 745983e7e86..1f1201b0035 100644
--- a/compiler/rustc_macros/Cargo.toml
+++ b/compiler/rustc_macros/Cargo.toml
@@ -7,11 +7,7 @@ edition = "2021"
proc-macro = true
[dependencies]
-annotate-snippets = "0.9"
-fluent-bundle = "0.15.2"
-fluent-syntax = "0.11"
synstructure = "0.13.0"
syn = { version = "2", features = ["full"] }
proc-macro2 = "1"
quote = "1"
-unic-langid = { version = "0.9.0", features = ["macros"] }
diff --git a/compiler/rustc_macros/src/diagnostics/mod.rs b/compiler/rustc_macros/src/diagnostics/mod.rs
index 78df0cd1d34..bd84681cbb4 100644
--- a/compiler/rustc_macros/src/diagnostics/mod.rs
+++ b/compiler/rustc_macros/src/diagnostics/mod.rs
@@ -1,12 +1,10 @@
mod diagnostic;
mod diagnostic_builder;
mod error;
-mod fluent;
mod subdiagnostic;
mod utils;
use diagnostic::{DiagnosticDerive, LintDiagnosticDerive};
-pub(crate) use fluent::fluent_messages;
use proc_macro2::TokenStream;
use quote::format_ident;
use subdiagnostic::SubdiagnosticDeriveBuilder;
diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs
index 737500cc257..904f8eb5731 100644
--- a/compiler/rustc_macros/src/lib.rs
+++ b/compiler/rustc_macros/src/lib.rs
@@ -54,60 +54,6 @@ pub fn newtype_index(input: TokenStream) -> TokenStream {
newtype::newtype(input)
}
-/// Implements the `fluent_messages` macro, which performs compile-time validation of the
-/// compiler's Fluent resources (i.e. that the resources parse and don't multiply define the same
-/// messages) and generates constants that make using those messages in diagnostics more ergonomic.
-///
-/// For example, given the following invocation of the macro..
-///
-/// ```ignore (rust)
-/// fluent_messages! { "./typeck.ftl" }
-/// ```
-/// ..where `typeck.ftl` has the following contents..
-///
-/// ```fluent
-/// typeck_field_multiply_specified_in_initializer =
-/// field `{$ident}` specified more than once
-/// .label = used more than once
-/// .label_previous_use = first use of `{$ident}`
-/// ```
-/// ...then the macro parse the Fluent resource, emitting a diagnostic if it fails to do so, and
-/// will generate the following code:
-///
-/// ```ignore (rust)
-/// pub static DEFAULT_LOCALE_RESOURCE: &'static [&'static str] = include_str!("./typeck.ftl");
-///
-/// mod fluent_generated {
-/// mod typeck {
-/// pub const field_multiply_specified_in_initializer: DiagnosticMessage =
-/// DiagnosticMessage::fluent("typeck_field_multiply_specified_in_initializer");
-/// pub const field_multiply_specified_in_initializer_label_previous_use: DiagnosticMessage =
-/// DiagnosticMessage::fluent_attr(
-/// "typeck_field_multiply_specified_in_initializer",
-/// "previous_use_label"
-/// );
-/// }
-/// }
-/// ```
-/// When emitting a diagnostic, the generated constants can be used as follows:
-///
-/// ```ignore (rust)
-/// let mut err = sess.struct_span_err(
-/// span,
-/// fluent::typeck::field_multiply_specified_in_initializer
-/// );
-/// err.span_default_label(span);
-/// err.span_label(
-/// previous_use_span,
-/// fluent::typeck::field_multiply_specified_in_initializer_label_previous_use
-/// );
-/// err.emit();
-/// ```
-#[proc_macro]
-pub fn fluent_messages(input: TokenStream) -> TokenStream {
- diagnostics::fluent_messages(input)
-}
-
decl_derive!([HashStable, attributes(stable_hasher)] => hash_stable::hash_stable_derive);
decl_derive!(
[HashStable_Generic, attributes(stable_hasher)] =>
diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs
index f85ba38003c..a8b25ff66d7 100644
--- a/compiler/rustc_macros/src/query.rs
+++ b/compiler/rustc_macros/src/query.rs
@@ -112,9 +112,6 @@ struct QueryModifiers {
/// Use a separate query provider for local and extern crates
separate_provide_extern: Option<Ident>,
- /// Always remap the ParamEnv's constness before hashing.
- remap_env_constness: Option<Ident>,
-
/// Generate a `feed` method to set the query's value from another query.
feedable: Option<Ident>,
}
@@ -130,7 +127,6 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
let mut eval_always = None;
let mut depth_limit = None;
let mut separate_provide_extern = None;
- let mut remap_env_constness = None;
let mut feedable = None;
while !input.is_empty() {
@@ -189,8 +185,6 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
try_insert!(depth_limit = modifier);
} else if modifier == "separate_provide_extern" {
try_insert!(separate_provide_extern = modifier);
- } else if modifier == "remap_env_constness" {
- try_insert!(remap_env_constness = modifier);
} else if modifier == "feedable" {
try_insert!(feedable = modifier);
} else {
@@ -211,7 +205,6 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
eval_always,
depth_limit,
separate_provide_extern,
- remap_env_constness,
feedable,
})
}
@@ -332,7 +325,6 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
eval_always,
depth_limit,
separate_provide_extern,
- remap_env_constness,
);
if modifiers.cache.is_some() {
diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml
index 4d7c133e09b..0e54d6aa946 100644
--- a/compiler/rustc_metadata/Cargo.toml
+++ b/compiler/rustc_metadata/Cargo.toml
@@ -18,6 +18,7 @@ rustc_attr = { path = "../rustc_attr" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_feature = { path = "../rustc_feature" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_fs_util = { path = "../rustc_fs_util" }
rustc_hir = { path = "../rustc_hir" }
rustc_hir_pretty = { path = "../rustc_hir_pretty" }
diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs
index 81e62eccb8a..9f664d0f0c8 100644
--- a/compiler/rustc_metadata/src/lib.rs
+++ b/compiler/rustc_metadata/src/lib.rs
@@ -28,7 +28,7 @@ extern crate tracing;
pub use rmeta::{provide, provide_extern};
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
-use rustc_macros::fluent_messages;
+use rustc_fluent_macro::fluent_messages;
mod dependency_format;
mod foreign_modules;
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index f7c9379e109..c9ab07f5f27 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -117,7 +117,7 @@ pub(crate) struct CrateMetadata {
/// Additional data used for decoding `HygieneData` (e.g. `SyntaxContext`
/// and `ExpnId`).
- /// Note that we store a `HygieneDecodeContext` for each `CrateMetadat`. This is
+ /// Note that we store a `HygieneDecodeContext` for each `CrateMetadata`. This is
/// because `SyntaxContext` ids are not globally unique, so we need
/// to track which ids we've decoded on a per-crate basis.
hygiene_context: HygieneDecodeContext,
@@ -627,7 +627,7 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Symbol {
let pos = d.read_usize();
let old_pos = d.opaque.position();
- // move to str ofset and read
+ // move to str offset and read
d.opaque.set_position(pos);
let s = d.read_str();
let sym = Symbol::intern(s);
@@ -876,16 +876,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
variant_did,
ctor,
data.discr,
- self.root
- .tables
- .children
- .get(self, index)
- .expect("fields are not encoded for a variant")
- .decode(self)
- .map(|index| ty::FieldDef {
- did: self.local_def_id(index),
- name: self.item_name(index),
- vis: self.get_visibility(index),
+ self.get_associated_item_or_field_def_ids(index)
+ .map(|did| ty::FieldDef {
+ did,
+ name: self.item_name(did.index),
+ vis: self.get_visibility(did.index),
})
.collect(),
adt_kind,
@@ -910,7 +905,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
let variants = if let ty::AdtKind::Enum = adt_kind {
self.root
.tables
- .children
+ .module_children_non_reexports
.get(self, item_id)
.expect("variants are not encoded for an enum")
.decode(self)
@@ -998,9 +993,8 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
let ident = self.item_ident(id, sess);
let res = Res::Def(self.def_kind(id), self.local_def_id(id));
let vis = self.get_visibility(id);
- let span = self.get_span(id, sess);
- ModChild { ident, res, vis, span, reexport_chain: Default::default() }
+ ModChild { ident, res, vis, reexport_chain: Default::default() }
}
/// Iterates over all named children of the given module,
@@ -1023,11 +1017,9 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
}
} else {
// Iterate over all children.
- for child_index in self.root.tables.children.get(self, id).unwrap().decode(self) {
- // FIXME: Do not encode RPITITs as a part of this list.
- if self.root.tables.opt_rpitit_info.get(self, child_index).is_none() {
- yield self.get_mod_child(child_index, sess);
- }
+ let non_reexports = self.root.tables.module_children_non_reexports.get(self, id);
+ for child_index in non_reexports.unwrap().decode(self) {
+ yield self.get_mod_child(child_index, sess);
}
let reexports = self.root.tables.module_children_reexports.get(self, id);
@@ -1059,17 +1051,16 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
.map_or(false, |ident| ident.name == kw::SelfLower)
}
- fn get_associated_item_def_ids(
+ fn get_associated_item_or_field_def_ids(
self,
id: DefIndex,
- sess: &'a Session,
) -> impl Iterator<Item = DefId> + 'a {
self.root
.tables
- .children
+ .associated_item_or_field_def_ids
.get(self, id)
- .expect("associated items not encoded for an item")
- .decode((self, sess))
+ .unwrap_or_else(|| self.missing("associated_item_or_field_def_ids", id))
+ .decode(self)
.map(move |child_index| self.local_def_id(child_index))
}
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 6212597e1ac..4aa3768fc3b 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -276,7 +276,7 @@ provide! { tcx, def_id, other, cdata,
tcx.calculate_dtor(def_id, |_,_| Ok(()))
}
associated_item_def_ids => {
- tcx.arena.alloc_from_iter(cdata.get_associated_item_def_ids(def_id.index, tcx.sess))
+ tcx.arena.alloc_from_iter(cdata.get_associated_item_or_field_def_ids(def_id.index))
}
associated_item => { cdata.get_associated_item(def_id.index, tcx.sess) }
inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) }
@@ -513,14 +513,6 @@ impl CStore {
self.get_crate_data(def.krate).get_ctor(def.index)
}
- pub fn module_children_untracked<'a>(
- &'a self,
- def_id: DefId,
- sess: &'a Session,
- ) -> impl Iterator<Item = ModChild> + 'a {
- self.get_crate_data(def_id.krate).get_module_children(def_id.index, sess)
- }
-
pub fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro {
let _prof_timer = sess.prof.generic_activity("metadata_load_macro");
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index f9e42fdecdc..fd8e49efea0 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -7,7 +7,7 @@ use rustc_ast::Attribute;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
use rustc_data_structures::memmap::{Mmap, MmapMut};
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher};
use rustc_data_structures::sync::{join, par_iter, Lrc, ParallelIterator};
use rustc_data_structures::temp_dir::MaybeTempDir;
use rustc_hir as hir;
@@ -531,7 +531,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
adapted.name_hash = {
let mut hasher: StableHasher = StableHasher::new();
adapted.name.hash(&mut hasher);
- hasher.finish::<u128>()
+ hasher.finish::<Hash128>()
};
Lrc::new(adapted)
} else {
@@ -822,6 +822,8 @@ fn should_encode_span(def_kind: DefKind) -> bool {
| DefKind::TraitAlias
| DefKind::AssocTy
| DefKind::TyParam
+ | DefKind::ConstParam
+ | DefKind::LifetimeParam
| DefKind::Fn
| DefKind::Const
| DefKind::Static(_)
@@ -829,6 +831,8 @@ fn should_encode_span(def_kind: DefKind) -> bool {
| DefKind::AssocFn
| DefKind::AssocConst
| DefKind::Macro(_)
+ | DefKind::ExternCrate
+ | DefKind::Use
| DefKind::AnonConst
| DefKind::InlineConst
| DefKind::OpaqueTy
@@ -836,13 +840,7 @@ fn should_encode_span(def_kind: DefKind) -> bool {
| DefKind::Impl { .. }
| DefKind::Closure
| DefKind::Generator => true,
- DefKind::ConstParam
- | DefKind::ExternCrate
- | DefKind::Use
- | DefKind::ForeignMod
- | DefKind::ImplTraitPlaceholder
- | DefKind::LifetimeParam
- | DefKind::GlobalAsm => false,
+ DefKind::ForeignMod | DefKind::ImplTraitPlaceholder | DefKind::GlobalAsm => false,
}
}
@@ -1366,7 +1364,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
if adt_def.is_enum() {
let module_children = tcx.module_children_non_reexports(local_def_id);
- record_array!(self.tables.children[def_id] <-
+ record_array!(self.tables.module_children_non_reexports[def_id] <-
module_children.iter().map(|def_id| def_id.local_def_index));
} else {
// For non-enum, there is only one variant, and its def_id is the adt's.
@@ -1384,7 +1382,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
record!(self.tables.variant_data[variant.def_id] <- data);
self.tables.constness.set_some(variant.def_id.index, hir::Constness::Const);
- record_array!(self.tables.children[variant.def_id] <- variant.fields.iter().map(|f| {
+ record_array!(self.tables.associated_item_or_field_def_ids[variant.def_id] <- variant.fields.iter().map(|f| {
assert!(f.did.is_local());
f.did.index
}));
@@ -1414,7 +1412,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
record!(self.tables.expn_that_defined[def_id] <- tcx.expn_that_defined(local_def_id));
} else {
let non_reexports = tcx.module_children_non_reexports(local_def_id);
- record_array!(self.tables.children[def_id] <-
+ record_array!(self.tables.module_children_non_reexports[def_id] <-
non_reexports.iter().map(|def_id| def_id.local_def_index));
record_defaulted_array!(self.tables.module_children_reexports[def_id] <-
@@ -1468,8 +1466,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
match impl_item.kind {
ty::AssocKind::Fn => {
- let ast_item = self.tcx.hir().expect_impl_item(def_id.expect_local());
- let hir::ImplItemKind::Fn(ref sig, body) = ast_item.kind else { bug!() };
+ let (sig, body) =
+ self.tcx.hir().expect_impl_item(def_id.expect_local()).expect_fn();
self.tables.asyncness.set_some(def_id.index, sig.header.asyncness);
record_array!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body));
// Can be inside `impl const Trait`, so using sig.header.constness is not reliable
@@ -1538,8 +1536,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
}
record!(self.tables.promoted_mir[def_id.to_def_id()] <- tcx.promoted_mir(def_id));
- let instance =
- ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id.to_def_id()));
+ let instance = ty::InstanceDef::Item(def_id.to_def_id());
let unused = tcx.unused_generic_params(instance);
self.tables.unused_generic_params.set(def_id.local_def_index, unused);
}
@@ -1617,7 +1614,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
debug!("EncodeContext::encode_info_for_item({:?})", def_id);
let record_associated_item_def_ids = |this: &mut Self, def_ids: &[DefId]| {
- record_array!(this.tables.children[def_id] <- def_ids.iter().map(|&def_id| {
+ record_array!(this.tables.associated_item_or_field_def_ids[def_id] <- def_ids.iter().map(|&def_id| {
assert!(def_id.is_local());
def_id.index
}))
@@ -1678,6 +1675,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
hir::ItemKind::Trait(..) => {
record!(self.tables.trait_def[def_id] <- self.tcx.trait_def(def_id));
+ let module_children = tcx.module_children_non_reexports(item.owner_id.def_id);
+ record_array!(self.tables.module_children_non_reexports[def_id] <-
+ module_children.iter().map(|def_id| def_id.local_def_index));
+
let associated_item_def_ids = self.tcx.associated_item_def_ids(def_id);
record_associated_item_def_ids(self, associated_item_def_ids);
for &item_def_id in associated_item_def_ids {
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 68dc22e31e9..ee1c495ed1e 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -360,7 +360,8 @@ define_tables! {
- optional:
attributes: Table<DefIndex, LazyArray<ast::Attribute>>,
- children: Table<DefIndex, LazyArray<DefIndex>>,
+ module_children_non_reexports: Table<DefIndex, LazyArray<DefIndex>>,
+ associated_item_or_field_def_ids: Table<DefIndex, LazyArray<DefIndex>>,
opt_def_kind: Table<DefIndex, DefKind>,
visibility: Table<DefIndex, LazyValue<ty::Visibility<DefIndex>>>,
def_span: Table<DefIndex, LazyValue<Span>>,
@@ -415,7 +416,7 @@ define_tables! {
macro_definition: Table<DefIndex, LazyValue<ast::DelimArgs>>,
proc_macro: Table<DefIndex, MacroKind>,
deduced_param_attrs: Table<DefIndex, LazyArray<DeducedParamAttrs>>,
- trait_impl_trait_tys: Table<DefIndex, LazyValue<FxHashMap<DefId, Ty<'static>>>>,
+ trait_impl_trait_tys: Table<DefIndex, LazyValue<FxHashMap<DefId, ty::EarlyBinder<Ty<'static>>>>>,
doc_link_resolutions: Table<DefIndex, LazyValue<DocLinkResMap>>,
doc_link_traits_in_scope: Table<DefIndex, LazyArray<DefId>>,
}
diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs
index 364fa74ab7b..66e2518fa56 100644
--- a/compiler/rustc_metadata/src/rmeta/table.rs
+++ b/compiler/rustc_metadata/src/rmeta/table.rs
@@ -413,8 +413,8 @@ impl<I: Idx, const N: usize, T: FixedSizeEncoding<ByteArray = [u8; N]>> TableBui
// > Space requirements could perhaps be optimized by using the HAMT `popcnt`
// > trick (i.e. divide things into buckets of 32 or 64 items and then
// > store bit-masks of which item in each bucket is actually serialized).
- self.blocks.ensure_contains_elem(i, || [0; N]);
- value.write_to_bytes(&mut self.blocks[i]);
+ let block = self.blocks.ensure_contains_elem(i, || [0; N]);
+ value.write_to_bytes(block);
}
}
diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml
index 5b2ec9029b1..dfbe8ac0ba3 100644
--- a/compiler/rustc_middle/Cargo.toml
+++ b/compiler/rustc_middle/Cargo.toml
@@ -21,6 +21,7 @@ rustc_errors = { path = "../rustc_errors" }
# Used for intra-doc links
rustc_error_messages = { path = "../rustc_error_messages" }
rustc_feature = { path = "../rustc_feature" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_graphviz = { path = "../rustc_graphviz" }
rustc_hir = { path = "../rustc_hir" }
rustc_index = { path = "../rustc_index" }
diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs
index dd1e254f405..60d7cf59d04 100644
--- a/compiler/rustc_middle/src/arena.rs
+++ b/compiler/rustc_middle/src/arena.rs
@@ -114,7 +114,11 @@ macro_rules! arena_types {
[] dep_kind: rustc_middle::dep_graph::DepKindStruct<'tcx>,
- [decode] trait_impl_trait_tys: rustc_data_structures::fx::FxHashMap<rustc_hir::def_id::DefId, rustc_middle::ty::Ty<'tcx>>,
+ [decode] trait_impl_trait_tys:
+ rustc_data_structures::fx::FxHashMap<
+ rustc_hir::def_id::DefId,
+ rustc_middle::ty::EarlyBinder<rustc_middle::ty::Ty<'tcx>>
+ >,
[] bit_set_u32: rustc_index::bit_set::BitSet<u32>,
[] external_constraints: rustc_middle::traits::solve::ExternalConstraintsData<'tcx>,
[decode] doc_link_resolutions: rustc_hir::def::DocLinkResMap,
diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs
index 865bb70afb5..82e396a9dd3 100644
--- a/compiler/rustc_middle/src/dep_graph/dep_node.rs
+++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs
@@ -357,7 +357,7 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for HirId {
Fingerprint::new(
// `owner` is local, so is completely defined by the local hash
def_path_hash.local_hash(),
- local_id.as_u32().into(),
+ local_id.as_u32() as u64,
)
}
@@ -370,7 +370,7 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for HirId {
#[inline(always)]
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
if tcx.fingerprint_style(dep_node.kind) == FingerprintStyle::HirId {
- let (local_hash, local_id) = Fingerprint::from(dep_node.hash).as_value();
+ let (local_hash, local_id) = Fingerprint::from(dep_node.hash).split();
let def_path_hash = DefPathHash::new(tcx.sess.local_stable_crate_id(), local_hash);
let def_id = tcx
.def_path_hash_to_def_id(def_path_hash, &mut || {
@@ -378,6 +378,7 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for HirId {
})
.expect_local();
let local_id = local_id
+ .as_u64()
.try_into()
.unwrap_or_else(|_| panic!("local id should be u32, found {:?}", local_id));
Some(HirId { owner: OwnerId { def_id }, local_id: ItemLocalId::from_u32(local_id) })
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index e551c76f8db..64aff27744f 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -1199,7 +1199,7 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh {
stable_hasher.finish()
});
- Svh::new(crate_hash.to_smaller_hash())
+ Svh::new(crate_hash)
}
fn upstream_crates(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> {
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index b5b712c367d..c4e41e00520 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -348,14 +348,6 @@ impl<'tcx, R> Canonical<'tcx, QueryResponse<'tcx, R>> {
}
}
-impl<'tcx, R> Canonical<'tcx, ty::ParamEnvAnd<'tcx, R>> {
- #[inline]
- pub fn without_const(mut self) -> Self {
- self.value = self.value.without_const();
- self
- }
-}
-
impl<'tcx, V> Canonical<'tcx, V> {
/// Allows you to map the `value` of a canonical while keeping the
/// same set of bound variables.
@@ -400,10 +392,8 @@ pub type QueryOutlivesConstraint<'tcx> =
(ty::OutlivesPredicate<GenericArg<'tcx>, Region<'tcx>>, ConstraintCategory<'tcx>);
TrivialTypeTraversalAndLiftImpls! {
- for <'tcx> {
- crate::infer::canonical::Certainty,
- crate::infer::canonical::CanonicalTyVarKind,
- }
+ crate::infer::canonical::Certainty,
+ crate::infer::canonical::CanonicalTyVarKind,
}
impl<'tcx> CanonicalVarValues<'tcx> {
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index b4edb02f6c4..76a8367b2c4 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -59,6 +59,7 @@
#![feature(result_option_inspect)]
#![feature(const_option)]
#![feature(trait_alias)]
+#![feature(ptr_alignment_type)]
#![recursion_limit = "512"]
#![allow(rustc::potential_query_instability)]
@@ -74,7 +75,7 @@ extern crate tracing;
extern crate smallvec;
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
-use rustc_macros::fluent_messages;
+use rustc_fluent_macro::fluent_messages;
#[cfg(test)]
mod tests;
@@ -99,13 +100,9 @@ pub mod mir;
pub mod thir;
pub mod traits;
pub mod ty;
+pub mod util;
mod values;
-pub mod util {
- pub mod bug;
- pub mod common;
-}
-
// Allows macros to refer to this crate as `::rustc_middle`
extern crate self as rustc_middle;
diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs
index 89014f62d4d..cd1c6c330bc 100644
--- a/compiler/rustc_middle/src/macros.rs
+++ b/compiler/rustc_middle/src/macros.rs
@@ -43,34 +43,26 @@ macro_rules! span_bug {
#[macro_export]
macro_rules! CloneLiftImpls {
- (for <$tcx:lifetime> { $($ty:ty,)+ }) => {
+ ($($ty:ty,)+) => {
$(
- impl<$tcx> $crate::ty::Lift<$tcx> for $ty {
+ impl<'tcx> $crate::ty::Lift<'tcx> for $ty {
type Lifted = Self;
- fn lift_to_tcx(self, _: $crate::ty::TyCtxt<$tcx>) -> Option<Self> {
+ fn lift_to_tcx(self, _: $crate::ty::TyCtxt<'tcx>) -> Option<Self> {
Some(self)
}
}
)+
};
-
- ($($ty:ty,)+) => {
- CloneLiftImpls! {
- for <'tcx> {
- $($ty,)+
- }
- }
- };
}
/// Used for types that are `Copy` and which **do not care arena
/// allocated data** (i.e., don't need to be folded).
#[macro_export]
macro_rules! TrivialTypeTraversalImpls {
- (for <$tcx:lifetime> { $($ty:ty,)+ }) => {
+ ($($ty:ty,)+) => {
$(
- impl<$tcx> $crate::ty::fold::TypeFoldable<$crate::ty::TyCtxt<$tcx>> for $ty {
- fn try_fold_with<F: $crate::ty::fold::FallibleTypeFolder<$crate::ty::TyCtxt<$tcx>>>(
+ impl<'tcx> $crate::ty::fold::TypeFoldable<$crate::ty::TyCtxt<'tcx>> for $ty {
+ fn try_fold_with<F: $crate::ty::fold::FallibleTypeFolder<$crate::ty::TyCtxt<'tcx>>>(
self,
_: &mut F,
) -> ::std::result::Result<Self, F::Error> {
@@ -78,7 +70,7 @@ macro_rules! TrivialTypeTraversalImpls {
}
#[inline]
- fn fold_with<F: $crate::ty::fold::TypeFolder<$crate::ty::TyCtxt<$tcx>>>(
+ fn fold_with<F: $crate::ty::fold::TypeFolder<$crate::ty::TyCtxt<'tcx>>>(
self,
_: &mut F,
) -> Self {
@@ -86,9 +78,9 @@ macro_rules! TrivialTypeTraversalImpls {
}
}
- impl<$tcx> $crate::ty::visit::TypeVisitable<$crate::ty::TyCtxt<$tcx>> for $ty {
+ impl<'tcx> $crate::ty::visit::TypeVisitable<$crate::ty::TyCtxt<'tcx>> for $ty {
#[inline]
- fn visit_with<F: $crate::ty::visit::TypeVisitor<$crate::ty::TyCtxt<$tcx>>>(
+ fn visit_with<F: $crate::ty::visit::TypeVisitor<$crate::ty::TyCtxt<'tcx>>>(
&self,
_: &mut F)
-> ::std::ops::ControlFlow<F::BreakTy>
@@ -98,14 +90,6 @@ macro_rules! TrivialTypeTraversalImpls {
}
)+
};
-
- ($($ty:ty,)+) => {
- TrivialTypeTraversalImpls! {
- for<'tcx> {
- $($ty,)+
- }
- }
- };
}
#[macro_export]
diff --git a/compiler/rustc_middle/src/metadata.rs b/compiler/rustc_middle/src/metadata.rs
index f3170e0ec0e..674402cb4bf 100644
--- a/compiler/rustc_middle/src/metadata.rs
+++ b/compiler/rustc_middle/src/metadata.rs
@@ -4,7 +4,6 @@ use rustc_hir::def::Res;
use rustc_macros::HashStable;
use rustc_span::def_id::DefId;
use rustc_span::symbol::Ident;
-use rustc_span::Span;
use smallvec::SmallVec;
/// A simplified version of `ImportKind` from resolve.
@@ -41,8 +40,6 @@ pub struct ModChild {
pub res: Res<!>,
/// Visibility of the item.
pub vis: ty::Visibility<DefId>,
- /// Span of the item.
- pub span: Span,
/// Reexport chain linking this module child to its original reexported item.
/// Empty if the module child is a proper item.
pub reexport_chain: SmallVec<[Reexport; 2]>,
diff --git a/compiler/rustc_middle/src/middle/exported_symbols.rs b/compiler/rustc_middle/src/middle/exported_symbols.rs
index c0c0fd07b6e..9041da9a060 100644
--- a/compiler/rustc_middle/src/middle/exported_symbols.rs
+++ b/compiler/rustc_middle/src/middle/exported_symbols.rs
@@ -72,6 +72,6 @@ pub fn metadata_symbol_name(tcx: TyCtxt<'_>) -> String {
format!(
"rust_metadata_{}_{:08x}",
tcx.crate_name(LOCAL_CRATE),
- tcx.sess.local_stable_crate_id().to_u64(),
+ tcx.sess.local_stable_crate_id(),
)
}
diff --git a/compiler/rustc_middle/src/mir/graphviz.rs b/compiler/rustc_middle/src/mir/graphviz.rs
index cf6d46e1e2c..2de73db3a3c 100644
--- a/compiler/rustc_middle/src/mir/graphviz.rs
+++ b/compiler/rustc_middle/src/mir/graphviz.rs
@@ -16,19 +16,16 @@ where
{
let def_ids = dump_mir_def_ids(tcx, single);
- let mirs =
- def_ids
- .iter()
- .flat_map(|def_id| {
- if tcx.is_const_fn_raw(*def_id) {
- vec![tcx.optimized_mir(*def_id), tcx.mir_for_ctfe(*def_id)]
- } else {
- vec![tcx.instance_mir(ty::InstanceDef::Item(ty::WithOptConstParam::unknown(
- *def_id,
- )))]
- }
- })
- .collect::<Vec<_>>();
+ let mirs = def_ids
+ .iter()
+ .flat_map(|def_id| {
+ if tcx.is_const_fn_raw(*def_id) {
+ vec![tcx.optimized_mir(*def_id), tcx.mir_for_ctfe(*def_id)]
+ } else {
+ vec![tcx.instance_mir(ty::InstanceDef::Item(*def_id))]
+ }
+ })
+ .collect::<Vec<_>>();
let use_subgraphs = mirs.len() > 1;
if use_subgraphs {
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs b/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs
index dcb56a1755e..d4dd56a42c1 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs
@@ -5,7 +5,9 @@ use std::hash;
use std::iter;
use std::ops::Range;
+use rustc_serialize::{Decodable, Encodable};
use rustc_target::abi::Size;
+use rustc_type_ir::{TyDecoder, TyEncoder};
use super::AllocRange;
@@ -182,11 +184,39 @@ impl InitMask {
/// The actual materialized blocks of the bitmask, when we can't keep the `InitMask` lazy.
// Note: for performance reasons when interning, some of the fields can be partially
// hashed. (see the `Hash` impl below for more details), so the impl is not derived.
-#[derive(Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable, HashStable)]
+#[derive(Clone, Debug, Eq, PartialEq, HashStable)]
struct InitMaskMaterialized {
blocks: Vec<Block>,
}
+// `Block` is a `u64`, but it is a bitmask not a numeric value. If we were to just derive
+// Encodable and Decodable we would apply varint encoding to the bitmasks, which is slower
+// and also produces more output when the high bits of each `u64` are occupied.
+// Note: There is probably a remaining optimization for masks that do not use an entire
+// `Block`.
+impl<E: TyEncoder> Encodable<E> for InitMaskMaterialized {
+ fn encode(&self, encoder: &mut E) {
+ encoder.emit_usize(self.blocks.len());
+ for block in &self.blocks {
+ encoder.emit_raw_bytes(&block.to_le_bytes());
+ }
+ }
+}
+
+// This implementation is deliberately not derived, see the matching `Encodable` impl.
+impl<D: TyDecoder> Decodable<D> for InitMaskMaterialized {
+ fn decode(decoder: &mut D) -> Self {
+ let num_blocks = decoder.read_usize();
+ let mut blocks = Vec::with_capacity(num_blocks);
+ for _ in 0..num_blocks {
+ let bytes = decoder.read_raw_bytes(8);
+ let block = u64::from_le_bytes(bytes.try_into().unwrap());
+ blocks.push(block);
+ }
+ InitMaskMaterialized { blocks }
+ }
+}
+
// Const allocations are only hashed for interning. However, they can be large, making the hashing
// expensive especially since it uses `FxHash`: it's better suited to short keys, not potentially
// big buffers like the allocation's init mask. We can partially hash some fields when they're
diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs
index 60927eed85d..65d04919357 100644
--- a/compiler/rustc_middle/src/mir/interpret/pointer.rs
+++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs
@@ -102,7 +102,7 @@ impl<T: HasDataLayout> PointerArithmetic for T {}
/// This trait abstracts over the kind of provenance that is associated with a `Pointer`. It is
/// mostly opaque; the `Machine` trait extends it with some more operations that also have access to
/// some global state.
-/// The `Debug` rendering is used to distplay bare provenance, and for the default impl of `fmt`.
+/// The `Debug` rendering is used to display bare provenance, and for the default impl of `fmt`.
pub trait Provenance: Copy + fmt::Debug {
/// Says whether the `offset` field of `Pointer`s with this provenance is the actual physical address.
/// - If `false`, the offset *must* be relative. This means the bytes representing a pointer are
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index 856d821a5cf..ed4ee93e97d 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -42,7 +42,7 @@ impl<'tcx> TyCtxt<'tcx> {
span: Option<Span>,
) -> EvalToConstValueResult<'tcx> {
// Cannot resolve `Unevaluated` constants that contain inference
- // variables. We reject those here since `resolve_opt_const_arg`
+ // variables. We reject those here since `resolve`
// would fail otherwise.
//
// When trying to evaluate constants containing inference variables,
@@ -51,7 +51,7 @@ impl<'tcx> TyCtxt<'tcx> {
bug!("did not expect inference variables here");
}
- match ty::Instance::resolve_opt_const_arg(
+ match ty::Instance::resolve(
self, param_env,
// FIXME: maybe have a separate version for resolving mir::UnevaluatedConst?
ct.def, ct.substs,
@@ -73,7 +73,7 @@ impl<'tcx> TyCtxt<'tcx> {
span: Option<Span>,
) -> EvalToValTreeResult<'tcx> {
// Cannot resolve `Unevaluated` constants that contain inference
- // variables. We reject those here since `resolve_opt_const_arg`
+ // variables. We reject those here since `resolve`
// would fail otherwise.
//
// When trying to evaluate constants containing inference variables,
@@ -82,7 +82,7 @@ impl<'tcx> TyCtxt<'tcx> {
bug!("did not expect inference variables here");
}
- match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) {
+ match ty::Instance::resolve(self, param_env, ct.def, ct.substs) {
Ok(Some(instance)) => {
let cid = GlobalId { instance, promoted: None };
self.const_eval_global_id_for_typeck(param_env, cid, span).inspect(|_| {
@@ -94,14 +94,14 @@ impl<'tcx> TyCtxt<'tcx> {
// used generic parameters is a bug of evaluation, so checking for it
// here does feel somewhat sensible.
if !self.features().generic_const_exprs && ct.substs.has_non_region_param() {
- assert!(matches!(self.def_kind(ct.def.did), DefKind::AnonConst));
- let mir_body = self.mir_for_ctfe_opt_const_arg(ct.def);
+ assert!(matches!(self.def_kind(ct.def), DefKind::AnonConst));
+ let mir_body = self.mir_for_ctfe(ct.def);
if mir_body.is_polymorphic {
- let Some(local_def_id) = ct.def.did.as_local() else { return };
+ let Some(local_def_id) = ct.def.as_local() else { return };
self.struct_span_lint_hir(
lint::builtin::CONST_EVALUATABLE_UNCHECKED,
self.hir().local_def_id_to_hir_id(local_def_id),
- self.def_span(ct.def.did),
+ self.def_span(ct.def),
"cannot use constants which depend on generic parameters in types",
|err| err,
)
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 2ea8602af12..6b6a2e561f5 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -191,20 +191,13 @@ pub struct MirSource<'tcx> {
impl<'tcx> MirSource<'tcx> {
pub fn item(def_id: DefId) -> Self {
- MirSource {
- instance: InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)),
- promoted: None,
- }
+ MirSource { instance: InstanceDef::Item(def_id), promoted: None }
}
pub fn from_instance(instance: InstanceDef<'tcx>) -> Self {
MirSource { instance, promoted: None }
}
- pub fn with_opt_param(self) -> ty::WithOptConstParam<DefId> {
- self.instance.with_opt_param()
- }
-
#[inline]
pub fn def_id(&self) -> DefId {
self.instance.def_id()
@@ -714,9 +707,7 @@ pub enum BindingForm<'tcx> {
}
TrivialTypeTraversalAndLiftImpls! {
- for<'tcx> {
- BindingForm<'tcx>,
- }
+ BindingForm<'tcx>,
}
mod binding_form_impl {
@@ -2050,7 +2041,11 @@ impl<'tcx> Debug for Rvalue<'tcx> {
}
UnaryOp(ref op, ref a) => write!(fmt, "{:?}({:?})", op, a),
Discriminant(ref place) => write!(fmt, "discriminant({:?})", place),
- NullaryOp(ref op, ref t) => write!(fmt, "{:?}({:?})", op, t),
+ NullaryOp(ref op, ref t) => match op {
+ NullOp::SizeOf => write!(fmt, "SizeOf({:?})", t),
+ NullOp::AlignOf => write!(fmt, "AlignOf({:?})", t),
+ NullOp::OffsetOf(fields) => write!(fmt, "OffsetOf({:?}, {:?})", t, fields),
+ },
ThreadLocalRef(did) => ty::tls::with(|tcx| {
let muta = tcx.static_mutability(did).unwrap().prefix_str();
write!(fmt, "&/*tls*/ {}{}", muta, tcx.def_path_str(did))
@@ -2438,16 +2433,6 @@ impl<'tcx> ConstantKind<'tcx> {
Self::Val(val, ty)
}
- /// Literals are converted to `ConstantKindVal`, const generic parameters are eagerly
- /// converted to a constant, everything else becomes `Unevaluated`.
- pub fn from_anon_const(
- tcx: TyCtxt<'tcx>,
- def_id: LocalDefId,
- param_env: ty::ParamEnv<'tcx>,
- ) -> Self {
- Self::from_opt_const_arg_anon_const(tcx, ty::WithOptConstParam::unknown(def_id), param_env)
- }
-
#[instrument(skip(tcx), level = "debug", ret)]
pub fn from_inline_const(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
@@ -2487,28 +2472,25 @@ impl<'tcx> ConstantKind<'tcx> {
ty::InlineConstSubsts::new(tcx, ty::InlineConstSubstsParts { parent_substs, ty })
.substs;
- let uneval = UnevaluatedConst {
- def: ty::WithOptConstParam::unknown(def_id).to_global(),
- substs,
- promoted: None,
- };
+ let uneval = UnevaluatedConst { def: def_id.to_def_id(), substs, promoted: None };
debug_assert!(!uneval.has_free_regions());
Self::Unevaluated(uneval, ty)
}
+ /// Literals are converted to `ConstantKindVal`, const generic parameters are eagerly
+ /// converted to a constant, everything else becomes `Unevaluated`.
#[instrument(skip(tcx), level = "debug", ret)]
- fn from_opt_const_arg_anon_const(
+ pub fn from_anon_const(
tcx: TyCtxt<'tcx>,
- def: ty::WithOptConstParam<LocalDefId>,
+ def: LocalDefId,
param_env: ty::ParamEnv<'tcx>,
) -> Self {
- let body_id = match tcx.hir().get_by_def_id(def.did) {
+ let body_id = match tcx.hir().get_by_def_id(def) {
hir::Node::AnonConst(ac) => ac.body,
- _ => span_bug!(
- tcx.def_span(def.did.to_def_id()),
- "from_anon_const can only process anonymous constants"
- ),
+ _ => {
+ span_bug!(tcx.def_span(def), "from_anon_const can only process anonymous constants")
+ }
};
let expr = &tcx.hir().body(body_id).value;
@@ -2524,7 +2506,7 @@ impl<'tcx> ConstantKind<'tcx> {
};
debug!("expr.kind: {:?}", expr.kind);
- let ty = tcx.type_of(def.def_id_for_type_of()).subst_identity();
+ let ty = tcx.type_of(def).subst_identity();
debug!(?ty);
// FIXME(const_generics): We currently have to special case parameters because `min_const_generics`
@@ -2551,7 +2533,7 @@ impl<'tcx> ConstantKind<'tcx> {
_ => {}
}
- let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def);
let parent_substs = if let Some(parent_hir_id) = tcx.hir().opt_parent_id(hir_id)
&& let Some(parent_did) = parent_hir_id.as_owner()
{
@@ -2561,15 +2543,14 @@ impl<'tcx> ConstantKind<'tcx> {
};
debug!(?parent_substs);
- let did = def.did.to_def_id();
+ let did = def.to_def_id();
let child_substs = InternalSubsts::identity_for_item(tcx, did);
let substs =
tcx.mk_substs_from_iter(parent_substs.into_iter().chain(child_substs.into_iter()));
debug!(?substs);
- let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
- let span = tcx.hir().span(hir_id);
- let uneval = UnevaluatedConst::new(def.to_global(), substs);
+ let span = tcx.def_span(def);
+ let uneval = UnevaluatedConst::new(did, substs);
debug!(?span, ?param_env);
match tcx.const_eval_resolve(param_env, uneval, Some(span)) {
@@ -2583,8 +2564,8 @@ impl<'tcx> ConstantKind<'tcx> {
// new unevaluated const and error hard later in codegen
Self::Unevaluated(
UnevaluatedConst {
- def: def.to_global(),
- substs: InternalSubsts::identity_for_item(tcx, def.did),
+ def: did,
+ substs: InternalSubsts::identity_for_item(tcx, did),
promoted: None,
},
ty,
@@ -2609,7 +2590,7 @@ impl<'tcx> ConstantKind<'tcx> {
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
#[derive(Hash, HashStable, TypeFoldable, TypeVisitable)]
pub struct UnevaluatedConst<'tcx> {
- pub def: ty::WithOptConstParam<DefId>,
+ pub def: DefId,
pub substs: SubstsRef<'tcx>,
pub promoted: Option<Promoted>,
}
@@ -2625,10 +2606,7 @@ impl<'tcx> UnevaluatedConst<'tcx> {
impl<'tcx> UnevaluatedConst<'tcx> {
#[inline]
- pub fn new(
- def: ty::WithOptConstParam<DefId>,
- substs: SubstsRef<'tcx>,
- ) -> UnevaluatedConst<'tcx> {
+ pub fn new(def: DefId, substs: SubstsRef<'tcx>) -> UnevaluatedConst<'tcx> {
UnevaluatedConst { def, substs, promoted: Default::default() }
}
}
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index f592f1515c1..67235f0f524 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -4,7 +4,7 @@ use rustc_attr::InlineAttr;
use rustc_data_structures::base_n;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher};
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc_hir::ItemId;
use rustc_index::vec::Idx;
@@ -313,8 +313,8 @@ impl<'tcx> CodegenUnit<'tcx> {
// avoid collisions and is still reasonably short for filenames.
let mut hasher = StableHasher::new();
human_readable_name.hash(&mut hasher);
- let hash: u128 = hasher.finish();
- let hash = hash & ((1u128 << 80) - 1);
+ let hash: Hash128 = hasher.finish();
+ let hash = hash.as_u128() & ((1u128 << 80) - 1);
base_n::encode(hash, base_n::CASE_INSENSITIVE)
}
@@ -373,7 +373,7 @@ impl<'tcx> CodegenUnit<'tcx> {
// instances into account. The others don't matter for
// the codegen tests and can even make item order
// unstable.
- InstanceDef::Item(def) => def.did.as_local().map(Idx::index),
+ InstanceDef::Item(def) => def.as_local().map(Idx::index),
InstanceDef::VTableShim(..)
| InstanceDef::ReifyShim(..)
| InstanceDef::Intrinsic(..)
@@ -505,22 +505,13 @@ impl<'tcx> CodegenUnitNameBuilder<'tcx> {
// instantiating stuff for upstream crates.
let local_crate_id = if cnum != LOCAL_CRATE {
let local_stable_crate_id = tcx.sess.local_stable_crate_id();
- format!(
- "-in-{}.{:08x}",
- tcx.crate_name(LOCAL_CRATE),
- local_stable_crate_id.to_u64() as u32,
- )
+ format!("-in-{}.{:08x}", tcx.crate_name(LOCAL_CRATE), local_stable_crate_id)
} else {
String::new()
};
let stable_crate_id = tcx.sess.local_stable_crate_id();
- format!(
- "{}.{:08x}{}",
- tcx.crate_name(cnum),
- stable_crate_id.to_u64() as u32,
- local_crate_id,
- )
+ format!("{}.{:08x}{}", tcx.crate_name(cnum), stable_crate_id, local_crate_id)
});
write!(cgu_name, "{}", crate_prefix).unwrap();
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 7e51953599d..89510bbb3aa 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -298,8 +298,7 @@ pub fn write_mir_pretty<'tcx>(
// are shared between mir_for_ctfe and optimized_mir
write_mir_fn(tcx, tcx.mir_for_ctfe(def_id), &mut |_, _| Ok(()), w)?;
} else {
- let instance_mir =
- tcx.instance_mir(ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)));
+ let instance_mir = tcx.instance_mir(ty::InstanceDef::Item(def_id));
render_body(w, instance_mir)?;
}
}
@@ -464,11 +463,7 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
ConstantKind::Ty(ct) => match ct.kind() {
ty::ConstKind::Param(p) => format!("Param({})", p),
ty::ConstKind::Unevaluated(uv) => {
- format!(
- "Unevaluated({}, {:?})",
- self.tcx.def_path_str(uv.def.did),
- uv.substs,
- )
+ format!("Unevaluated({}, {:?})", self.tcx.def_path_str(uv.def), uv.substs,)
}
ty::ConstKind::Value(val) => format!("Value({})", fmt_valtree(&val)),
ty::ConstKind::Error(_) => "Error".to_string(),
@@ -481,7 +476,7 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
ConstantKind::Unevaluated(uv, _) => {
format!(
"Unevaluated({}, {:?}, {:?})",
- self.tcx.def_path_str(uv.def.did),
+ self.tcx.def_path_str(uv.def),
uv.substs,
uv.promoted,
)
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index cfdf1dcf5c0..17eaf3e08d8 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -1,12 +1,12 @@
//! Values computed by queries that use MIR.
-use crate::mir::{Body, ConstantKind, Promoted};
+use crate::mir::ConstantKind;
use crate::ty::{self, OpaqueHiddenType, Ty, TyCtxt};
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::unord::UnordSet;
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::LocalDefId;
use rustc_index::bit_set::BitMatrix;
use rustc_index::vec::{Idx, IndexVec};
use rustc_span::Span;
@@ -454,42 +454,3 @@ pub struct CoverageInfo {
/// The total number of coverage region counter expressions added to the MIR `Body`.
pub num_expressions: u32,
}
-
-/// Shims which make dealing with `WithOptConstParam` easier.
-///
-/// For more information on why this is needed, consider looking
-/// at the docs for `WithOptConstParam` itself.
-impl<'tcx> TyCtxt<'tcx> {
- #[inline]
- pub fn mir_const_qualif_opt_const_arg(
- self,
- def: ty::WithOptConstParam<LocalDefId>,
- ) -> ConstQualifs {
- if let Some(param_did) = def.const_param_did {
- self.mir_const_qualif_const_arg((def.did, param_did))
- } else {
- self.mir_const_qualif(def.did)
- }
- }
-
- #[inline]
- pub fn promoted_mir_opt_const_arg(
- self,
- def: ty::WithOptConstParam<DefId>,
- ) -> &'tcx IndexVec<Promoted, Body<'tcx>> {
- if let Some((did, param_did)) = def.as_const_arg() {
- self.promoted_mir_of_const_arg((did, param_did))
- } else {
- self.promoted_mir(def.did)
- }
- }
-
- #[inline]
- pub fn mir_for_ctfe_opt_const_arg(self, def: ty::WithOptConstParam<DefId>) -> &'tcx Body<'tcx> {
- if let Some((did, param_did)) = def.as_const_arg() {
- self.mir_for_ctfe_of_const_arg((did, param_did))
- } else {
- self.mir_for_ctfe(def.did)
- }
- }
-}
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 135889d0da8..69ce6835ba6 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -251,7 +251,7 @@ pub enum StatementKind<'tcx> {
/// **Needs clarification**: The implication of the above idea would be that assignment implies
/// that the resulting value is initialized. I believe we could commit to this separately from
/// committing to whatever part of the memory model we would need to decide on to make the above
- /// paragragh precise. Do we want to?
+ /// paragraph precise. Do we want to?
///
/// Assignments in which the types of the place and rvalue differ are not well-formed.
///
@@ -331,9 +331,8 @@ pub enum StatementKind<'tcx> {
/// This is especially useful for `let _ = PLACE;` bindings that desugar to a single
/// `PlaceMention(PLACE)`.
///
- /// When executed at runtime this is a nop.
- ///
- /// Disallowed after drop elaboration.
+ /// When executed at runtime, this computes the given place, but then discards
+ /// it without doing a load. It is UB if the place is not pointing to live memory.
PlaceMention(Box<Place<'tcx>>),
/// Encodes a user's type ascription. These need to be preserved
@@ -997,7 +996,7 @@ pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>;
/// This is what is implemented in miri today. Are these the semantics we want for MIR? Is this
/// something we can even decide without knowing more about Rust's memory model?
///
-/// **Needs clarifiation:** Is loading a place that has its variant index set well-formed? Miri
+/// **Needs clarification:** Is loading a place that has its variant index set well-formed? Miri
/// currently implements it, but it seems like this may be something to check against in the
/// validator.
#[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)]
@@ -1115,7 +1114,7 @@ pub enum Rvalue<'tcx> {
CheckedBinaryOp(BinOp, Box<(Operand<'tcx>, Operand<'tcx>)>),
/// Computes a value as described by the operation.
- NullaryOp(NullOp, Ty<'tcx>),
+ NullaryOp(NullOp<'tcx>, Ty<'tcx>),
/// Exactly like `BinaryOp`, but less operands.
///
@@ -1211,12 +1210,14 @@ pub enum AggregateKind<'tcx> {
Generator(DefId, SubstsRef<'tcx>, hir::Movability),
}
-#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
-pub enum NullOp {
+#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
+pub enum NullOp<'tcx> {
/// Returns the size of a value of that type
SizeOf,
/// Returns the minimum alignment of a type
AlignOf,
+ /// Returns the offset of a field
+ OffsetOf(&'tcx List<FieldIdx>),
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index 4f00abf7fab..5ca82413448 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -188,7 +188,9 @@ impl<'tcx> Rvalue<'tcx> {
}
Rvalue::UnaryOp(UnOp::Not | UnOp::Neg, ref operand) => operand.ty(local_decls, tcx),
Rvalue::Discriminant(ref place) => place.ty(local_decls, tcx).ty.discriminant_ty(tcx),
- Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => tcx.types.usize,
+ Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => {
+ tcx.types.usize
+ }
Rvalue::Aggregate(ref ak, ref ops) => match **ak {
AggregateKind::Array(ty) => tcx.mk_array(ty, ops.len() as u64),
AggregateKind::Tuple => {
diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs
index 9881583214e..06874741bb0 100644
--- a/compiler/rustc_middle/src/mir/type_foldable.rs
+++ b/compiler/rustc_middle/src/mir/type_foldable.rs
@@ -16,7 +16,6 @@ TrivialTypeTraversalAndLiftImpls! {
UserTypeAnnotationIndex,
BorrowKind,
CastKind,
- NullOp,
hir::Movability,
BasicBlock,
SwitchTargets,
@@ -25,9 +24,8 @@ TrivialTypeTraversalAndLiftImpls! {
}
TrivialTypeTraversalImpls! {
- for <'tcx> {
- ConstValue<'tcx>,
- }
+ ConstValue<'tcx>,
+ NullOp<'tcx>,
}
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx [InlineAsmTemplatePiece] {
diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs
index 23b28ac5ca9..fa62b7f32b1 100644
--- a/compiler/rustc_middle/src/query/keys.rs
+++ b/compiler/rustc_middle/src/query/keys.rs
@@ -174,14 +174,6 @@ impl AsLocalKey for DefId {
}
}
-impl Key for ty::WithOptConstParam<LocalDefId> {
- type CacheSelector = DefaultCacheSelector<Self>;
-
- fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
- self.did.default_span(tcx)
- }
-}
-
impl Key for SimplifiedType {
type CacheSelector = DefaultCacheSelector<Self>;
@@ -313,7 +305,7 @@ impl<'tcx> Key for (ty::UnevaluatedConst<'tcx>, ty::UnevaluatedConst<'tcx>) {
type CacheSelector = DefaultCacheSelector<Self>;
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
- (self.0).def.did.default_span(tcx)
+ (self.0).def.default_span(tcx)
}
}
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 0cecf8db1af..292718b82aa 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -127,29 +127,6 @@ rustc_queries! {
desc { |tcx| "getting HIR owner attributes in `{}`", tcx.def_path_str(key.to_def_id()) }
}
- /// Computes the `DefId` of the corresponding const parameter in case the `key` is a
- /// const argument and returns `None` otherwise.
- ///
- /// ```ignore (incomplete)
- /// let a = foo::<7>();
- /// // ^ Calling `opt_const_param_of` for this argument,
- ///
- /// fn foo<const N: usize>()
- /// // ^ returns this `DefId`.
- ///
- /// fn bar() {
- /// // ^ While calling `opt_const_param_of` for other bodies returns `None`.
- /// }
- /// ```
- // It looks like caching this query on disk actually slightly
- // worsened performance in #74376.
- //
- // Once const generics are more prevalently used, we might want to
- // consider only caching calls returning `Some`.
- query opt_const_param_of(key: LocalDefId) -> Option<DefId> {
- desc { |tcx| "computing the optional const parameter of `{}`", tcx.def_path_str(key.to_def_id()) }
- }
-
/// Given the def_id of a const-generic parameter, computes the associated default const
/// parameter. e.g. `fn example<const N: usize=3>` called on `N` would return `3`.
query const_param_default(param: DefId) -> ty::EarlyBinder<ty::Const<'tcx>> {
@@ -181,7 +158,7 @@ rustc_queries! {
}
query collect_return_position_impl_trait_in_trait_tys(key: DefId)
- -> Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed>
+ -> Result<&'tcx FxHashMap<DefId, ty::EarlyBinder<Ty<'tcx>>>, ErrorGuaranteed>
{
desc { "comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process" }
cache_on_disk_if { key.is_local() }
@@ -369,26 +346,24 @@ rustc_queries! {
}
/// Fetch the THIR for a given body. If typeck for that body failed, returns an empty `Thir`.
- query thir_body(key: ty::WithOptConstParam<LocalDefId>)
- -> Result<(&'tcx Steal<thir::Thir<'tcx>>, thir::ExprId), ErrorGuaranteed>
- {
+ query thir_body(key: LocalDefId) -> Result<(&'tcx Steal<thir::Thir<'tcx>>, thir::ExprId), ErrorGuaranteed> {
// Perf tests revealed that hashing THIR is inefficient (see #85729).
no_hash
- desc { |tcx| "building THIR for `{}`", tcx.def_path_str(key.did.to_def_id()) }
+ desc { |tcx| "building THIR for `{}`", tcx.def_path_str(key.to_def_id()) }
}
/// Create a THIR tree for debugging.
- query thir_tree(key: ty::WithOptConstParam<LocalDefId>) -> &'tcx String {
+ query thir_tree(key: LocalDefId) -> &'tcx String {
no_hash
arena_cache
- desc { |tcx| "constructing THIR tree for `{}`", tcx.def_path_str(key.did.to_def_id()) }
+ desc { |tcx| "constructing THIR tree for `{}`", tcx.def_path_str(key.to_def_id()) }
}
/// Create a list-like THIR representation for debugging.
- query thir_flat(key: ty::WithOptConstParam<LocalDefId>) -> &'tcx String {
+ query thir_flat(key: LocalDefId) -> &'tcx String {
no_hash
arena_cache
- desc { |tcx| "constructing flat THIR representation for `{}`", tcx.def_path_str(key.did.to_def_id()) }
+ desc { |tcx| "constructing flat THIR representation for `{}`", tcx.def_path_str(key.to_def_id()) }
}
/// Set of all the `DefId`s in this crate that have MIR associated with
@@ -407,31 +382,19 @@ rustc_queries! {
cache_on_disk_if { key.is_local() }
separate_provide_extern
}
- query mir_const_qualif_const_arg(
- key: (LocalDefId, DefId)
- ) -> mir::ConstQualifs {
- desc {
- |tcx| "const checking the const argument `{}`",
- tcx.def_path_str(key.0.to_def_id())
- }
- }
/// Fetch the MIR for a given `DefId` right after it's built - this includes
/// unreachable code.
- query mir_built(key: ty::WithOptConstParam<LocalDefId>) -> &'tcx Steal<mir::Body<'tcx>> {
- desc { |tcx| "building MIR for `{}`", tcx.def_path_str(key.did.to_def_id()) }
+ query mir_built(key: LocalDefId) -> &'tcx Steal<mir::Body<'tcx>> {
+ desc { |tcx| "building MIR for `{}`", tcx.def_path_str(key.to_def_id()) }
}
/// Fetch the MIR for a given `DefId` up till the point where it is
/// ready for const qualification.
///
/// See the README for the `mir` module for details.
- query mir_const(key: ty::WithOptConstParam<LocalDefId>) -> &'tcx Steal<mir::Body<'tcx>> {
- desc {
- |tcx| "preparing {}`{}` for borrow checking",
- if key.const_param_did.is_some() { "the const argument " } else { "" },
- tcx.def_path_str(key.did.to_def_id()),
- }
+ query mir_const(key: LocalDefId) -> &'tcx Steal<mir::Body<'tcx>> {
+ desc { |tcx| "preparing `{}` for borrow checking", tcx.def_path_str(key.to_def_id()) }
no_hash
}
@@ -444,22 +407,10 @@ rustc_queries! {
}
separate_provide_extern
}
- /// Try to build an abstract representation of the given constant.
- query thir_abstract_const_of_const_arg(
- key: (LocalDefId, DefId)
- ) -> Result<Option<ty::Const<'tcx>>, ErrorGuaranteed> {
- desc {
- |tcx|
- "building an abstract representation for the const argument `{}`",
- tcx.def_path_str(key.0.to_def_id()),
- }
- }
- query mir_drops_elaborated_and_const_checked(
- key: ty::WithOptConstParam<LocalDefId>
- ) -> &'tcx Steal<mir::Body<'tcx>> {
+ query mir_drops_elaborated_and_const_checked(key: LocalDefId) -> &'tcx Steal<mir::Body<'tcx>> {
no_hash
- desc { |tcx| "elaborating drops for `{}`", tcx.def_path_str(key.did.to_def_id()) }
+ desc { |tcx| "elaborating drops for `{}`", tcx.def_path_str(key.to_def_id()) }
}
query mir_for_ctfe(
@@ -470,24 +421,12 @@ rustc_queries! {
separate_provide_extern
}
- query mir_for_ctfe_of_const_arg(key: (LocalDefId, DefId)) -> &'tcx mir::Body<'tcx> {
- desc {
- |tcx| "caching MIR for CTFE of the const argument `{}`",
- tcx.def_path_str(key.0.to_def_id())
- }
- }
-
- query mir_promoted(key: ty::WithOptConstParam<LocalDefId>) ->
- (
- &'tcx Steal<mir::Body<'tcx>>,
- &'tcx Steal<IndexVec<mir::Promoted, mir::Body<'tcx>>>
- ) {
+ query mir_promoted(key: LocalDefId) -> (
+ &'tcx Steal<mir::Body<'tcx>>,
+ &'tcx Steal<IndexVec<mir::Promoted, mir::Body<'tcx>>>
+ ) {
no_hash
- desc {
- |tcx| "processing MIR for {}`{}`",
- if key.const_param_did.is_some() { "the const argument " } else { "" },
- tcx.def_path_str(key.did.to_def_id()),
- }
+ desc { |tcx| "promoting constants in MIR for `{}`", tcx.def_path_str(key.to_def_id()) }
}
query closure_typeinfo(key: LocalDefId) -> ty::ClosureTypeInfo<'tcx> {
@@ -544,14 +483,6 @@ rustc_queries! {
cache_on_disk_if { key.is_local() }
separate_provide_extern
}
- query promoted_mir_of_const_arg(
- key: (LocalDefId, DefId)
- ) -> &'tcx IndexVec<mir::Promoted, mir::Body<'tcx>> {
- desc {
- |tcx| "optimizing promoted MIR for the const argument `{}`",
- tcx.def_path_str(key.0.to_def_id()),
- }
- }
/// Erases regions from `ty` to yield a new type.
/// Normally you would just use `tcx.erase_regions(value)`,
@@ -739,9 +670,10 @@ rustc_queries! {
desc { "computing the inferred outlives predicates for items in this crate" }
}
- /// Maps from an impl/trait `DefId` to a list of the `DefId`s of its items.
+ /// Maps from an impl/trait or struct/variant `DefId`
+ /// to a list of the `DefId`s of its associated items or fields.
query associated_item_def_ids(key: DefId) -> &'tcx [DefId] {
- desc { |tcx| "collecting associated items of `{}`", tcx.def_path_str(key) }
+ desc { |tcx| "collecting associated items or fields of `{}`", tcx.def_path_str(key) }
cache_on_disk_if { key.is_local() }
separate_provide_extern
}
@@ -840,12 +772,6 @@ rustc_queries! {
desc { |tcx| "unsafety-checking `{}`", tcx.def_path_str(key.to_def_id()) }
cache_on_disk_if { true }
}
- query unsafety_check_result_for_const_arg(key: (LocalDefId, DefId)) -> &'tcx mir::UnsafetyCheckResult {
- desc {
- |tcx| "unsafety-checking the const argument `{}`",
- tcx.def_path_str(key.0.to_def_id())
- }
- }
/// Unsafety-check this `LocalDefId` with THIR unsafeck. This should be
/// used with `-Zthir-unsafeck`.
@@ -853,12 +779,6 @@ rustc_queries! {
desc { |tcx| "unsafety-checking `{}`", tcx.def_path_str(key.to_def_id()) }
cache_on_disk_if { true }
}
- query thir_check_unsafety_for_const_arg(key: (LocalDefId, DefId)) {
- desc {
- |tcx| "unsafety-checking the const argument `{}`",
- tcx.def_path_str(key.0.to_def_id())
- }
- }
/// Returns the types assumed to be well formed while "inside" of the given item.
///
@@ -960,14 +880,6 @@ rustc_queries! {
desc { |tcx| "type-checking `{}`", tcx.def_path_str(key.to_def_id()) }
cache_on_disk_if { true }
}
- query typeck_const_arg(
- key: (LocalDefId, DefId)
- ) -> &'tcx ty::TypeckResults<'tcx> {
- desc {
- |tcx| "type-checking the const argument `{}`",
- tcx.def_path_str(key.0.to_def_id()),
- }
- }
query diagnostic_only_typeck(key: LocalDefId) -> &'tcx ty::TypeckResults<'tcx> {
desc { |tcx| "type-checking `{}`", tcx.def_path_str(key.to_def_id()) }
cache_on_disk_if { true }
@@ -992,12 +904,6 @@ rustc_queries! {
desc { |tcx| "borrow-checking `{}`", tcx.def_path_str(key.to_def_id()) }
cache_on_disk_if(tcx) { tcx.is_typeck_child(key.to_def_id()) }
}
- query mir_borrowck_const_arg(key: (LocalDefId, DefId)) -> &'tcx mir::BorrowCheckResult<'tcx> {
- desc {
- |tcx| "borrow-checking the const argument`{}`",
- tcx.def_path_str(key.0.to_def_id())
- }
- }
/// Gets a complete map from all types to their inherent impls.
/// Not meant to be used directly outside of coherence.
@@ -1094,7 +1000,6 @@ rustc_queries! {
key: ty::ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>>
) -> Option<mir::DestructuredConstant<'tcx>> {
desc { "destructuring MIR constant"}
- remap_env_constness
}
/// Dereference a constant reference or raw pointer and turn the result into a constant
@@ -1103,7 +1008,6 @@ rustc_queries! {
key: ty::ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>>
) -> mir::ConstantKind<'tcx> {
desc { "dereferencing MIR constant" }
- remap_env_constness
}
query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> ConstValue<'tcx> {
@@ -1346,32 +1250,26 @@ rustc_queries! {
/// `ty.is_copy()`, etc, since that will prune the environment where possible.
query is_copy_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
desc { "computing whether `{}` is `Copy`", env.value }
- remap_env_constness
}
/// Query backing `Ty::is_sized`.
query is_sized_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
desc { "computing whether `{}` is `Sized`", env.value }
- remap_env_constness
}
/// Query backing `Ty::is_freeze`.
query is_freeze_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
desc { "computing whether `{}` is freeze", env.value }
- remap_env_constness
}
/// Query backing `Ty::is_unpin`.
query is_unpin_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
desc { "computing whether `{}` is `Unpin`", env.value }
- remap_env_constness
}
/// Query backing `Ty::needs_drop`.
query needs_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
desc { "computing whether `{}` needs drop", env.value }
- remap_env_constness
}
/// Query backing `Ty::has_significant_drop_raw`.
query has_significant_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
desc { "computing whether `{}` has a significant drop", env.value }
- remap_env_constness
}
/// Query backing `Ty::is_structural_eq_shallow`.
@@ -1411,7 +1309,6 @@ rustc_queries! {
) -> Result<ty::layout::TyAndLayout<'tcx>, ty::layout::LayoutError<'tcx>> {
depth_limit
desc { "computing layout of `{}`", key.value }
- remap_env_constness
}
/// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers.
@@ -1422,7 +1319,6 @@ rustc_queries! {
key: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)>
) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, ty::layout::FnAbiError<'tcx>> {
desc { "computing call ABI of `{}` function pointers", key.value.0 }
- remap_env_constness
}
/// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for
@@ -1434,7 +1330,6 @@ rustc_queries! {
key: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>
) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, ty::layout::FnAbiError<'tcx>> {
desc { "computing call ABI of `{}`", key.value.0 }
- remap_env_constness
}
query dylib_dependency_formats(_: CrateNum)
@@ -1926,7 +1821,6 @@ rustc_queries! {
NoSolution,
> {
desc { "normalizing `{}`", goal.value.value }
- remap_env_constness
}
/// Do not call this query directly: invoke `try_normalize_erasing_regions` instead.
@@ -1934,7 +1828,6 @@ rustc_queries! {
goal: ParamEnvAnd<'tcx, GenericArg<'tcx>>
) -> Result<GenericArg<'tcx>, NoSolution> {
desc { "normalizing `{}`", goal.value }
- remap_env_constness
}
query implied_outlives_bounds(
@@ -1944,7 +1837,6 @@ rustc_queries! {
NoSolution,
> {
desc { "computing implied outlives bounds for `{}`", goal.value.value }
- remap_env_constness
}
/// Do not call this query directly:
@@ -1956,7 +1848,6 @@ rustc_queries! {
NoSolution,
> {
desc { "computing dropck types for `{}`", goal.value.value }
- remap_env_constness
}
/// Do not call this query directly: invoke `infcx.predicate_may_hold()` or
@@ -1984,7 +1875,6 @@ rustc_queries! {
NoSolution,
> {
desc { "evaluating `type_op_ascribe_user_type` `{:?}`", goal.value.value }
- remap_env_constness
}
/// Do not call this query directly: part of the `Eq` type-op
@@ -1995,7 +1885,6 @@ rustc_queries! {
NoSolution,
> {
desc { "evaluating `type_op_eq` `{:?}`", goal.value.value }
- remap_env_constness
}
/// Do not call this query directly: part of the `Subtype` type-op
@@ -2006,7 +1895,6 @@ rustc_queries! {
NoSolution,
> {
desc { "evaluating `type_op_subtype` `{:?}`", goal.value.value }
- remap_env_constness
}
/// Do not call this query directly: part of the `ProvePredicate` type-op
@@ -2027,7 +1915,6 @@ rustc_queries! {
NoSolution,
> {
desc { "normalizing `{}`", goal.value.value.value }
- remap_env_constness
}
/// Do not call this query directly: part of the `Normalize` type-op
@@ -2038,7 +1925,6 @@ rustc_queries! {
NoSolution,
> {
desc { "normalizing `{:?}`", goal.value.value.value }
- remap_env_constness
}
/// Do not call this query directly: part of the `Normalize` type-op
@@ -2049,7 +1935,6 @@ rustc_queries! {
NoSolution,
> {
desc { "normalizing `{:?}`", goal.value.value.value }
- remap_env_constness
}
/// Do not call this query directly: part of the `Normalize` type-op
@@ -2060,7 +1945,6 @@ rustc_queries! {
NoSolution,
> {
desc { "normalizing `{:?}`", goal.value.value.value }
- remap_env_constness
}
query subst_and_check_impossible_predicates(key: (DefId, SubstsRef<'tcx>)) -> bool {
@@ -2082,7 +1966,6 @@ rustc_queries! {
goal: CanonicalTyGoal<'tcx>
) -> MethodAutoderefStepsResult<'tcx> {
desc { "computing autoderef types for `{}`", goal.value.value }
- remap_env_constness
}
query supported_target_features(_: CrateNum) -> &'tcx FxHashMap<String, Option<Symbol>> {
@@ -2127,17 +2010,6 @@ rustc_queries! {
key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)>
) -> Result<Option<ty::Instance<'tcx>>, ErrorGuaranteed> {
desc { "resolving instance `{}`", ty::Instance::new(key.value.0, key.value.1) }
- remap_env_constness
- }
-
- query resolve_instance_of_const_arg(
- key: ty::ParamEnvAnd<'tcx, (LocalDefId, DefId, SubstsRef<'tcx>)>
- ) -> Result<Option<ty::Instance<'tcx>>, ErrorGuaranteed> {
- desc {
- "resolving instance of the const argument `{}`",
- ty::Instance::new(key.value.0.to_def_id(), key.value.2),
- }
- remap_env_constness
}
query reveal_opaque_types_in_bounds(key: &'tcx ty::List<ty::Predicate<'tcx>>) -> &'tcx ty::List<ty::Predicate<'tcx>> {
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index 7d79a13d3fd..8700a98b365 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -20,7 +20,7 @@ use rustc_middle::mir::interpret::AllocId;
use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, Mutability, UnOp};
use rustc_middle::ty::adjustment::PointerCast;
use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, AdtDef, FnSig, Ty, UpvarSubsts};
+use rustc_middle::ty::{self, AdtDef, FnSig, List, Ty, UpvarSubsts};
use rustc_middle::ty::{CanonicalUserType, CanonicalUserTypeAnnotation};
use rustc_span::def_id::LocalDefId;
use rustc_span::{sym, Span, Symbol, DUMMY_SP};
@@ -481,6 +481,11 @@ pub enum ExprKind<'tcx> {
},
/// Inline assembly, i.e. `asm!()`.
InlineAsm(Box<InlineAsmExpr<'tcx>>),
+ /// Field offset (`offset_of!`)
+ OffsetOf {
+ container: Ty<'tcx>,
+ fields: &'tcx List<FieldIdx>,
+ },
/// An expression taking a reference to a thread local.
ThreadLocalRef(DefId),
/// A `yield` expression.
@@ -929,8 +934,8 @@ mod size_asserts {
static_assert_size!(Block, 56);
static_assert_size!(Expr<'_>, 64);
static_assert_size!(ExprKind<'_>, 40);
- static_assert_size!(Pat<'_>, 72);
- static_assert_size!(PatKind<'_>, 56);
+ static_assert_size!(Pat<'_>, 64);
+ static_assert_size!(PatKind<'_>, 48);
static_assert_size!(Stmt<'_>, 56);
static_assert_size!(StmtKind<'_>, 48);
// tidy-alphabetical-end
diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs
index 5614528c4cb..5c7ec31cf93 100644
--- a/compiler/rustc_middle/src/thir/visit.rs
+++ b/compiler/rustc_middle/src/thir/visit.rs
@@ -160,6 +160,7 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp
}
}
}
+ OffsetOf { container: _, fields: _ } => {}
ThreadLocalRef(_) => {}
Yield { value } => visitor.visit_expr(&visitor.thir()[value]),
}
diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs
index f889ce82706..029cf793ad8 100644
--- a/compiler/rustc_middle/src/ty/abstract_const.rs
+++ b/compiler/rustc_middle/src/ty/abstract_const.rs
@@ -1,4 +1,4 @@
-//! A subset of a mir body used for const evaluatability checking.
+//! A subset of a mir body used for const evaluability checking.
use crate::ty::{
self, Const, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
TypeVisitableExt,
@@ -36,15 +36,8 @@ pub type BoundAbstractConst<'tcx> = Result<Option<EarlyBinder<ty::Const<'tcx>>>,
impl<'tcx> TyCtxt<'tcx> {
/// Returns a const without substs applied
- pub fn bound_abstract_const(
- self,
- uv: ty::WithOptConstParam<DefId>,
- ) -> BoundAbstractConst<'tcx> {
- let ac = if let Some((did, param_did)) = uv.as_const_arg() {
- self.thir_abstract_const_of_const_arg((did, param_did))
- } else {
- self.thir_abstract_const(uv.did)
- };
+ pub fn bound_abstract_const(self, uv: DefId) -> BoundAbstractConst<'tcx> {
+ let ac = self.thir_abstract_const(uv);
Ok(ac?.map(|ac| EarlyBinder(ac)))
}
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index 8ef4a46a733..5454d406dd1 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -19,6 +19,7 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_middle::ty::TyCtxt;
use rustc_serialize::{Decodable, Encodable};
use rustc_span::Span;
+use rustc_target::abi::FieldIdx;
pub use rustc_type_ir::{TyDecoder, TyEncoder};
use std::hash::Hash;
use std::intrinsics;
@@ -401,6 +402,15 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<ty
}
}
+impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<FieldIdx> {
+ fn decode(decoder: &mut D) -> &'tcx Self {
+ let len = decoder.read_usize();
+ decoder
+ .interner()
+ .mk_fields_from_iter((0..len).map::<FieldIdx, _>(|_| Decodable::decode(decoder)))
+ }
+}
+
impl_decodable_via_ref! {
&'tcx ty::TypeckResults<'tcx>,
&'tcx ty::List<Ty<'tcx>>,
@@ -412,6 +422,7 @@ impl_decodable_via_ref! {
&'tcx mir::coverage::CodeRegion,
&'tcx ty::List<ty::BoundVariableKind>,
&'tcx ty::List<ty::Predicate<'tcx>>,
+ &'tcx ty::List<FieldIdx>,
}
#[macro_export]
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index bcedae233d9..0a191ff7626 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -53,19 +53,12 @@ impl<'tcx> Const<'tcx> {
/// Literals and const generic parameters are eagerly converted to a constant, everything else
/// becomes `Unevaluated`.
- pub fn from_anon_const(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
- Self::from_opt_const_arg_anon_const(tcx, ty::WithOptConstParam::unknown(def_id))
- }
-
#[instrument(skip(tcx), level = "debug")]
- pub fn from_opt_const_arg_anon_const(
- tcx: TyCtxt<'tcx>,
- def: ty::WithOptConstParam<LocalDefId>,
- ) -> Self {
- let body_id = match tcx.hir().get_by_def_id(def.did) {
+ pub fn from_anon_const(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Self {
+ let body_id = match tcx.hir().get_by_def_id(def) {
hir::Node::AnonConst(ac) => ac.body,
_ => span_bug!(
- tcx.def_span(def.did.to_def_id()),
+ tcx.def_span(def.to_def_id()),
"from_anon_const can only process anonymous constants"
),
};
@@ -73,17 +66,14 @@ impl<'tcx> Const<'tcx> {
let expr = &tcx.hir().body(body_id).value;
debug!(?expr);
- let ty = tcx
- .type_of(def.def_id_for_type_of())
- .no_bound_vars()
- .expect("const parameter types cannot be generic");
+ let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic");
match Self::try_eval_lit_or_param(tcx, ty, expr) {
Some(v) => v,
None => tcx.mk_const(
ty::UnevaluatedConst {
- def: def.to_global(),
- substs: InternalSubsts::identity_for_item(tcx, def.did),
+ def: def.to_def_id(),
+ substs: InternalSubsts::identity_for_item(tcx, def.to_def_id()),
},
ty,
),
diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs
index c0e557d480d..d1dbc531edf 100644
--- a/compiler/rustc_middle/src/ty/consts/int.rs
+++ b/compiler/rustc_middle/src/ty/consts/int.rs
@@ -141,14 +141,18 @@ impl<CTX> crate::ty::HashStable<CTX> for ScalarInt {
impl<S: Encoder> Encodable<S> for ScalarInt {
fn encode(&self, s: &mut S) {
- s.emit_u128(self.data);
- s.emit_u8(self.size.get());
+ let size = self.size.get();
+ s.emit_u8(size);
+ s.emit_raw_bytes(&self.data.to_le_bytes()[..size as usize]);
}
}
impl<D: Decoder> Decodable<D> for ScalarInt {
fn decode(d: &mut D) -> ScalarInt {
- ScalarInt { data: d.read_u128(), size: NonZeroU8::new(d.read_u8()).unwrap() }
+ let mut data = [0u8; 16];
+ let size = d.read_u8();
+ data[..size as usize].copy_from_slice(d.read_raw_bytes(size as usize));
+ ScalarInt { data: u128::from_le_bytes(data), size: NonZeroU8::new(size).unwrap() }
}
}
diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs
index 560caa041a7..1ac2cd13982 100644
--- a/compiler/rustc_middle/src/ty/consts/kind.rs
+++ b/compiler/rustc_middle/src/ty/consts/kind.rs
@@ -17,7 +17,7 @@ use super::ScalarInt;
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
#[derive(Hash, HashStable, TypeFoldable, TypeVisitable)]
pub struct UnevaluatedConst<'tcx> {
- pub def: ty::WithOptConstParam<DefId>,
+ pub def: DefId,
pub substs: SubstsRef<'tcx>,
}
@@ -36,10 +36,7 @@ impl<'tcx> UnevaluatedConst<'tcx> {
impl<'tcx> UnevaluatedConst<'tcx> {
#[inline]
- pub fn new(
- def: ty::WithOptConstParam<DefId>,
- substs: SubstsRef<'tcx>,
- ) -> UnevaluatedConst<'tcx> {
+ pub fn new(def: DefId, substs: SubstsRef<'tcx>) -> UnevaluatedConst<'tcx> {
UnevaluatedConst { def, substs }
}
}
@@ -224,9 +221,9 @@ impl<'tcx> ConstKind<'tcx> {
// FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that
// we can call `infcx.const_eval_resolve` which handles inference variables.
let param_env_and = if (param_env, unevaluated).has_non_region_infer() {
- tcx.param_env(unevaluated.def.did).and(ty::UnevaluatedConst {
+ tcx.param_env(unevaluated.def).and(ty::UnevaluatedConst {
def: unevaluated.def,
- substs: InternalSubsts::identity_for_item(tcx, unevaluated.def.did),
+ substs: InternalSubsts::identity_for_item(tcx, unevaluated.def),
})
} else {
tcx.erase_regions(param_env)
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 63f7cc2ee73..6f122d97a39 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -13,7 +13,7 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
use crate::middle::resolve_bound_vars;
use crate::middle::stability;
use crate::mir::interpret::{self, Allocation, ConstAllocation};
-use crate::mir::{Body, BorrowCheckResult, Local, Place, PlaceElem, ProjectionKind, Promoted};
+use crate::mir::{Body, Local, Place, PlaceElem, ProjectionKind, Promoted};
use crate::query::LocalCrate;
use crate::thir::Thir;
use crate::traits;
@@ -24,7 +24,7 @@ use crate::ty::{
self, AdtDef, AdtDefData, AdtKind, Binder, Const, ConstData, 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,
+ TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, UintTy, Visibility,
};
use crate::ty::{GenericArg, InternalSubsts, SubstsRef};
use rustc_ast::{self as ast, attr};
@@ -141,6 +141,7 @@ pub struct CtxtInterners<'tcx> {
type_: InternedSet<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>,
const_lists: InternedSet<'tcx, List<ty::Const<'tcx>>>,
substs: InternedSet<'tcx, InternalSubsts<'tcx>>,
+ type_lists: InternedSet<'tcx, List<Ty<'tcx>>>,
canonical_var_infos: InternedSet<'tcx, List<CanonicalVarInfo<'tcx>>>,
region: InternedSet<'tcx, RegionKind<'tcx>>,
poly_existential_predicates: InternedSet<'tcx, List<PolyExistentialPredicate<'tcx>>>,
@@ -154,6 +155,7 @@ pub struct CtxtInterners<'tcx> {
layout: InternedSet<'tcx, LayoutS>,
adt_def: InternedSet<'tcx, AdtDefData>,
external_constraints: InternedSet<'tcx, ExternalConstraintsData<'tcx>>,
+ fields: InternedSet<'tcx, List<FieldIdx>>,
}
impl<'tcx> CtxtInterners<'tcx> {
@@ -163,6 +165,7 @@ impl<'tcx> CtxtInterners<'tcx> {
type_: Default::default(),
const_lists: Default::default(),
substs: Default::default(),
+ type_lists: Default::default(),
region: Default::default(),
poly_existential_predicates: Default::default(),
canonical_var_infos: Default::default(),
@@ -176,6 +179,7 @@ impl<'tcx> CtxtInterners<'tcx> {
layout: Default::default(),
adt_def: Default::default(),
external_constraints: Default::default(),
+ fields: Default::default(),
}
}
@@ -447,6 +451,14 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn feed_local_crate(self) -> TyCtxtFeed<'tcx, CrateNum> {
TyCtxtFeed { tcx: self, key: LOCAL_CRATE }
}
+
+ /// In order to break cycles involving `AnonConst`, we need to set the expected type by side
+ /// effect. However, we do not want this as a general capability, so this interface restricts
+ /// to the only allowed case.
+ pub fn feed_anon_const_type(self, key: LocalDefId, value: ty::EarlyBinder<Ty<'tcx>>) {
+ debug_assert_eq!(self.def_kind(key), DefKind::AnonConst);
+ TyCtxtFeed { tcx: self, key }.type_of(value)
+ }
}
impl<'tcx, KEY: Copy> TyCtxtFeed<'tcx, KEY> {
@@ -581,28 +593,6 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
- pub fn typeck_opt_const_arg(
- self,
- def: ty::WithOptConstParam<LocalDefId>,
- ) -> &'tcx TypeckResults<'tcx> {
- if let Some(param_did) = def.const_param_did {
- self.typeck_const_arg((def.did, param_did))
- } else {
- self.typeck(def.did)
- }
- }
-
- pub fn mir_borrowck_opt_const_arg(
- self,
- def: ty::WithOptConstParam<LocalDefId>,
- ) -> &'tcx BorrowCheckResult<'tcx> {
- if let Some(param_did) = def.const_param_did {
- self.mir_borrowck_const_arg((def.did, param_did))
- } else {
- self.mir_borrowck(def.did)
- }
- }
-
pub fn alloc_steal_thir(self, thir: Thir<'tcx>) -> &'tcx Steal<Thir<'tcx>> {
self.arena.alloc(Steal::new(thir))
}
@@ -925,7 +915,7 @@ impl<'tcx> TyCtxt<'tcx> {
crate_name,
// Don't print the whole stable crate id. That's just
// annoying in debug output.
- stable_crate_id.to_u64() >> (8 * 6),
+ stable_crate_id.as_u64() >> (8 * 6),
self.def_path(def_id).to_string_no_crate_verbose()
)
}
@@ -1278,25 +1268,6 @@ macro_rules! nop_lift {
};
}
-// Can't use the macros as we have reuse the `substs` here.
-//
-// See `mk_type_list` for more info.
-impl<'a, 'tcx> Lift<'tcx> for &'a List<Ty<'a>> {
- type Lifted = &'tcx List<Ty<'tcx>>;
- fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
- if self.is_empty() {
- return Some(List::empty());
- }
-
- tcx.interners
- .substs
- .contains_pointer_to(&InternedInSet(self.as_substs()))
- // SAFETY: `self` is interned and therefore valid
- // for the entire lifetime of the `TyCtxt`.
- .then(|| unsafe { mem::transmute::<&'a List<Ty<'a>>, &'tcx List<Ty<'tcx>>>(self) })
- }
-}
-
macro_rules! nop_list_lift {
($set:ident; $ty:ty => $lifted:ty) => {
impl<'a, 'tcx> Lift<'tcx> for &'a List<$ty> {
@@ -1320,6 +1291,7 @@ nop_lift! {const_; Const<'a> => Const<'tcx>}
nop_lift! {const_allocation; ConstAllocation<'a> => ConstAllocation<'tcx>}
nop_lift! {predicate; Predicate<'a> => Predicate<'tcx>}
+nop_list_lift! {type_lists; Ty<'a> => Ty<'tcx>}
nop_list_lift! {poly_existential_predicates; PolyExistentialPredicate<'a> => PolyExistentialPredicate<'tcx>}
nop_list_lift! {predicates; Predicate<'a> => Predicate<'tcx>}
nop_list_lift! {canonical_var_infos; CanonicalVarInfo<'a> => CanonicalVarInfo<'tcx>}
@@ -1329,9 +1301,12 @@ nop_list_lift! {bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariable
// This is the impl for `&'a InternalSubsts<'a>`.
nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>}
-CloneLiftImpls! { for<'tcx> {
- Constness, traits::WellFormedLoc, ImplPolarity, crate::mir::ReturnConstraint,
-} }
+CloneLiftImpls! {
+ Constness,
+ traits::WellFormedLoc,
+ ImplPolarity,
+ crate::mir::ReturnConstraint,
+}
macro_rules! sty_debug_print {
($fmt: expr, $ctxt: expr, $($variant: ident),*) => {{
@@ -1591,12 +1566,14 @@ macro_rules! slice_interners {
slice_interners!(
const_lists: pub mk_const_list(Const<'tcx>),
substs: pub mk_substs(GenericArg<'tcx>),
+ type_lists: pub mk_type_list(Ty<'tcx>),
canonical_var_infos: pub mk_canonical_var_infos(CanonicalVarInfo<'tcx>),
poly_existential_predicates: intern_poly_existential_predicates(PolyExistentialPredicate<'tcx>),
predicates: intern_predicates(Predicate<'tcx>),
projs: pub mk_projs(ProjectionKind),
place_elems: pub mk_place_elems(PlaceElem<'tcx>),
bound_variable_kinds: pub mk_bound_variable_kinds(ty::BoundVariableKind),
+ fields: pub mk_fields(FieldIdx),
);
impl<'tcx> TyCtxt<'tcx> {
@@ -2190,18 +2167,6 @@ impl<'tcx> TyCtxt<'tcx> {
T::collect_and_apply(iter, |xs| self.mk_const_list(xs))
}
- pub fn mk_type_list(self, ts: &[Ty<'tcx>]) -> &'tcx List<Ty<'tcx>> {
- // Actually intern type lists as lists of `GenericArg`s.
- //
- // Transmuting from `Ty<'tcx>` to `GenericArg<'tcx>` is sound
- // as explained in `ty_slice_as_generic_arg`. With this,
- // we guarantee that even when transmuting between `List<Ty<'tcx>>`
- // and `List<GenericArg<'tcx>>`, the uniqueness requirement for
- // lists is upheld.
- let substs = self.mk_substs(ty::subst::ty_slice_as_generic_args(ts));
- substs.try_as_type_list().unwrap()
- }
-
// Unlike various other `mk_*_from_iter` functions, this one uses `I:
// IntoIterator` instead of `I: Iterator`, and it doesn't have a slice
// variant, because of the need to combine `inputs` and `output`. This
@@ -2277,6 +2242,14 @@ impl<'tcx> TyCtxt<'tcx> {
T::collect_and_apply(iter, |xs| self.mk_place_elems(xs))
}
+ pub fn mk_fields_from_iter<I, T>(self, iter: I) -> T::Output
+ where
+ I: Iterator<Item = T>,
+ T: CollectAndApply<FieldIdx, &'tcx List<FieldIdx>>,
+ {
+ T::collect_and_apply(iter, |xs| self.mk_fields(xs))
+ }
+
pub fn mk_substs_trait(
self,
self_ty: Ty<'tcx>,
diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs
index 31d00b65e98..76f61d9ac9c 100644
--- a/compiler/rustc_middle/src/ty/fast_reject.rs
+++ b/compiler/rustc_middle/src/ty/fast_reject.rs
@@ -68,7 +68,7 @@ pub enum TreatParams {
}
/// During fast-rejection, we have the choice of treating projection types
-/// as either simplifyable or not, depending on whether we expect the projection
+/// as either simplifiable or not, depending on whether we expect the projection
/// to be normalized/rigid.
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
pub enum TreatProjections {
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index 5a6ee123811..68002bfcfbd 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -178,7 +178,7 @@ impl FlagComputation {
&ty::Alias(ty::Projection, data) => {
self.add_flags(TypeFlags::HAS_TY_PROJECTION);
- self.add_projection_ty(data);
+ self.add_alias_ty(data);
}
&ty::Alias(ty::Opaque, ty::AliasTy { substs, .. }) => {
@@ -267,7 +267,7 @@ impl FlagComputation {
projection_ty,
term,
})) => {
- self.add_projection_ty(projection_ty);
+ self.add_alias_ty(projection_ty);
self.add_term(term);
}
ty::PredicateKind::WellFormed(arg) => {
@@ -372,8 +372,8 @@ impl FlagComputation {
}
}
- fn add_projection_ty(&mut self, projection_ty: ty::AliasTy<'_>) {
- self.add_substs(projection_ty.substs);
+ fn add_alias_ty(&mut self, alias_ty: ty::AliasTy<'_>) {
+ self.add_substs(alias_ty.substs);
}
fn add_substs(&mut self, substs: &[GenericArg<'_>]) {
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index 203e16bea27..25890eb15cd 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -37,7 +37,8 @@ where
}
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
- let r = r.super_fold_with(self);
+ // This one is a little different, because `super_fold_with` is not
+ // implemented on non-recursive `Region`.
(self.lt_op)(r)
}
diff --git a/compiler/rustc_middle/src/ty/impls_ty.rs b/compiler/rustc_middle/src/ty/impls_ty.rs
index 4c7822acdf7..02baa395c3c 100644
--- a/compiler/rustc_middle/src/ty/impls_ty.rs
+++ b/compiler/rustc_middle/src/ty/impls_ty.rs
@@ -73,34 +73,6 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::subst::GenericArg<'t
}
}
-impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::subst::GenericArgKind<'tcx> {
- fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
- match self {
- // WARNING: We dedup cache the `HashStable` results for `List`
- // while ignoring types and freely transmute
- // between `List<Ty<'tcx>>` and `List<GenericArg<'tcx>>`.
- // See `fn mk_type_list` for more details.
- //
- // We therefore hash types without adding a hash for their discriminant.
- //
- // In order to make it very unlikely for the sequence of bytes being hashed for
- // a `GenericArgKind::Type` to be the same as the sequence of bytes being
- // hashed for one of the other variants, we hash some very high number instead
- // of their actual discriminant since `TyKind` should never start with anything
- // that high.
- ty::subst::GenericArgKind::Type(ty) => ty.hash_stable(hcx, hasher),
- ty::subst::GenericArgKind::Const(ct) => {
- 0xF3u8.hash_stable(hcx, hasher);
- ct.hash_stable(hcx, hasher);
- }
- ty::subst::GenericArgKind::Lifetime(lt) => {
- 0xF5u8.hash_stable(hcx, hasher);
- lt.hash_stable(hcx, hasher);
- }
- }
- }
-}
-
// AllocIds get resolved to whatever they point to (to be stable)
impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::AllocId {
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index e73225f70cc..cc86cba6fda 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -34,7 +34,7 @@ pub enum InstanceDef<'tcx> {
/// - `fn` items
/// - closures
/// - generators
- Item(ty::WithOptConstParam<DefId>),
+ Item(DefId),
/// An intrinsic `fn` item (with `"rust-intrinsic"` or `"platform-intrinsic"` ABI).
///
@@ -143,7 +143,7 @@ impl<'tcx> Instance<'tcx> {
match self.def {
InstanceDef::Item(def) => tcx
- .upstream_monomorphizations_for(def.did)
+ .upstream_monomorphizations_for(def)
.and_then(|monos| monos.get(&self.substs).cloned()),
InstanceDef::DropGlue(_, Some(_)) => tcx.upstream_drop_glue_for(self.substs),
_ => None,
@@ -155,8 +155,8 @@ impl<'tcx> InstanceDef<'tcx> {
#[inline]
pub fn def_id(self) -> DefId {
match self {
- InstanceDef::Item(def) => def.did,
- InstanceDef::VTableShim(def_id)
+ InstanceDef::Item(def_id)
+ | InstanceDef::VTableShim(def_id)
| InstanceDef::ReifyShim(def_id)
| InstanceDef::FnPtrShim(def_id, _)
| InstanceDef::Virtual(def_id, _)
@@ -172,7 +172,7 @@ impl<'tcx> InstanceDef<'tcx> {
/// Returns the `DefId` of instances which might not require codegen locally.
pub fn def_id_if_not_guaranteed_local_codegen(self) -> Option<DefId> {
match self {
- ty::InstanceDef::Item(def) => Some(def.did),
+ ty::InstanceDef::Item(def) => Some(def),
ty::InstanceDef::DropGlue(def_id, Some(_)) | InstanceDef::ThreadLocalShim(def_id) => {
Some(def_id)
}
@@ -189,23 +189,6 @@ impl<'tcx> InstanceDef<'tcx> {
}
#[inline]
- pub fn with_opt_param(self) -> ty::WithOptConstParam<DefId> {
- match self {
- InstanceDef::Item(def) => def,
- InstanceDef::VTableShim(def_id)
- | InstanceDef::ReifyShim(def_id)
- | InstanceDef::FnPtrShim(def_id, _)
- | InstanceDef::Virtual(def_id, _)
- | InstanceDef::Intrinsic(def_id)
- | InstanceDef::ClosureOnceShim { call_once: def_id, track_caller: _ }
- | InstanceDef::DropGlue(def_id, _)
- | InstanceDef::CloneShim(def_id, _)
- | InstanceDef::ThreadLocalShim(def_id)
- | InstanceDef::FnPtrAddrShim(def_id, _) => ty::WithOptConstParam::unknown(def_id),
- }
- }
-
- #[inline]
pub fn get_attrs(
&self,
tcx: TyCtxt<'tcx>,
@@ -222,7 +205,7 @@ impl<'tcx> InstanceDef<'tcx> {
pub fn requires_inline(&self, tcx: TyCtxt<'tcx>) -> bool {
use rustc_hir::definitions::DefPathData;
let def_id = match *self {
- ty::InstanceDef::Item(def) => def.did,
+ ty::InstanceDef::Item(def) => def,
ty::InstanceDef::DropGlue(_, Some(_)) => return false,
ty::InstanceDef::ThreadLocalShim(_) => return false,
_ => return true,
@@ -273,8 +256,7 @@ impl<'tcx> InstanceDef<'tcx> {
pub fn requires_caller_location(&self, tcx: TyCtxt<'_>) -> bool {
match *self {
- InstanceDef::Item(ty::WithOptConstParam { did: def_id, .. })
- | InstanceDef::Virtual(def_id, _) => {
+ InstanceDef::Item(def_id) | InstanceDef::Virtual(def_id, _) => {
tcx.body_codegen_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER)
}
InstanceDef::ClosureOnceShim { call_once: _, track_caller } => track_caller,
@@ -358,7 +340,7 @@ impl<'tcx> Instance<'tcx> {
def_id,
substs
);
- Instance { def: InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)), substs }
+ Instance { def: InstanceDef::Item(def_id), substs }
}
pub fn mono(tcx: TyCtxt<'tcx>, def_id: DefId) -> Instance<'tcx> {
@@ -403,18 +385,21 @@ impl<'tcx> Instance<'tcx> {
/// couldn't complete due to errors elsewhere - this is distinct
/// from `Ok(None)` to avoid misleading diagnostics when an error
/// has already been/will be emitted, for the original cause
+ #[instrument(level = "debug", skip(tcx))]
pub fn resolve(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
def_id: DefId,
substs: SubstsRef<'tcx>,
) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> {
- Instance::resolve_opt_const_arg(
- tcx,
- param_env,
- ty::WithOptConstParam::unknown(def_id),
- substs,
- )
+ // All regions in the result of this query are erased, so it's
+ // fine to erase all of the input regions.
+
+ // HACK(eddyb) erase regions in `substs` first, so that `param_env.and(...)`
+ // below is more likely to ignore the bounds in scope (e.g. if the only
+ // generic parameters mentioned by `substs` were lifetime ones).
+ let substs = tcx.erase_regions(substs);
+ tcx.resolve_instance(tcx.erase_regions(param_env.and((def_id, substs))))
}
pub fn expect_resolve(
@@ -432,31 +417,6 @@ impl<'tcx> Instance<'tcx> {
}
}
- // This should be kept up to date with `resolve`.
- pub fn resolve_opt_const_arg(
- tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
- def: ty::WithOptConstParam<DefId>,
- substs: SubstsRef<'tcx>,
- ) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> {
- // All regions in the result of this query are erased, so it's
- // fine to erase all of the input regions.
-
- // HACK(eddyb) erase regions in `substs` first, so that `param_env.and(...)`
- // below is more likely to ignore the bounds in scope (e.g. if the only
- // generic parameters mentioned by `substs` were lifetime ones).
- let substs = tcx.erase_regions(substs);
-
- // FIXME(eddyb) should this always use `param_env.with_reveal_all()`?
- if let Some((did, param_did)) = def.as_const_arg() {
- tcx.resolve_instance_of_const_arg(
- tcx.erase_regions(param_env.and((did, param_did, substs))),
- )
- } else {
- tcx.resolve_instance(tcx.erase_regions(param_env.and((def.did, substs))))
- }
- }
-
pub fn resolve_for_fn_ptr(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
@@ -470,7 +430,7 @@ impl<'tcx> Instance<'tcx> {
match resolved.def {
InstanceDef::Item(def) if resolved.def.requires_caller_location(tcx) => {
debug!(" => fn pointer created for function with #[track_caller]");
- resolved.def = InstanceDef::ReifyShim(def.did);
+ resolved.def = InstanceDef::ReifyShim(def);
}
InstanceDef::Virtual(def_id, _) => {
debug!(" => fn pointer created for virtual call");
@@ -513,23 +473,23 @@ impl<'tcx> Instance<'tcx> {
if resolved.def.requires_caller_location(tcx)
// 2) The caller location parameter comes from having `#[track_caller]`
// on the implementation, and *not* on the trait method.
- && !tcx.should_inherit_track_caller(def.did)
+ && !tcx.should_inherit_track_caller(def)
// If the method implementation comes from the trait definition itself
// (e.g. `trait Foo { #[track_caller] my_fn() { /* impl */ } }`),
// then we don't need to generate a shim. This check is needed because
// `should_inherit_track_caller` returns `false` if our method
// implementation comes from the trait block, and not an impl block
&& !matches!(
- tcx.opt_associated_item(def.did),
+ tcx.opt_associated_item(def),
Some(ty::AssocItem {
container: ty::AssocItemContainer::TraitContainer,
..
})
)
{
- if tcx.is_closure(def.did) {
+ if tcx.is_closure(def) {
debug!(" => vtable fn pointer created for closure with #[track_caller]: {:?} for method {:?} {:?}",
- def.did, def_id, substs);
+ def, def_id, substs);
// Create a shim for the `FnOnce/FnMut/Fn` method we are calling
// - unlike functions, invoking a closure always goes through a
@@ -537,9 +497,9 @@ impl<'tcx> Instance<'tcx> {
resolved = Instance { def: InstanceDef::ReifyShim(def_id), substs };
} else {
debug!(
- " => vtable fn pointer created for function with #[track_caller]: {:?}", def.did
+ " => vtable fn pointer created for function with #[track_caller]: {:?}", def
);
- resolved.def = InstanceDef::ReifyShim(def.did);
+ resolved.def = InstanceDef::ReifyShim(def);
}
}
}
@@ -714,11 +674,8 @@ fn polymorphize<'tcx>(
debug!("fold_ty: ty={:?}", ty);
match *ty.kind() {
ty::Closure(def_id, substs) => {
- let polymorphized_substs = polymorphize(
- self.tcx,
- ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)),
- substs,
- );
+ let polymorphized_substs =
+ polymorphize(self.tcx, ty::InstanceDef::Item(def_id), substs);
if substs == polymorphized_substs {
ty
} else {
@@ -726,11 +683,8 @@ fn polymorphize<'tcx>(
}
}
ty::Generator(def_id, substs, movability) => {
- let polymorphized_substs = polymorphize(
- self.tcx,
- ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)),
- substs,
- );
+ let polymorphized_substs =
+ polymorphize(self.tcx, ty::InstanceDef::Item(def_id), substs);
if substs == polymorphized_substs {
ty
} else {
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 195d951f9f3..1e2fd86e13d 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -235,7 +235,7 @@ impl IntoDiagnostic<'_, !> for LayoutError<'_> {
}
}
-// FIXME: Once the other errors that embed this error have been converted to translateable
+// FIXME: Once the other errors that embed this error have been converted to translatable
// diagnostics, this Display impl should be removed.
impl<'tcx> fmt::Display for LayoutError<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -458,10 +458,10 @@ impl<'tcx> SizeSkeleton<'tcx> {
}
}
-/// When creating the layout for types with abstract conts in their size (i.e. [usize; 4 * N]),
+/// When creating the layout for types with abstract consts in their size (i.e. [usize; 4 * N]),
/// to ensure that they have a canonical order and can be compared directly we combine all
/// constants, and sort the other terms. This allows comparison of expressions of sizes,
-/// allowing for things like transmutating between types that depend on generic consts.
+/// allowing for things like transmuting between types that depend on generic consts.
/// This returns `None` if multiplication of constants overflows.
fn mul_sorted_consts<'tcx>(
tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_middle/src/ty/list.rs b/compiler/rustc_middle/src/ty/list.rs
index 79365ef281b..30f036e471c 100644
--- a/compiler/rustc_middle/src/ty/list.rs
+++ b/compiler/rustc_middle/src/ty/list.rs
@@ -1,4 +1,5 @@
use crate::arena::Arena;
+use rustc_data_structures::aligned::{align_of, Aligned};
use rustc_serialize::{Encodable, Encoder};
use std::alloc::Layout;
use std::cmp::Ordering;
@@ -198,22 +199,17 @@ impl<'a, T: Copy> IntoIterator for &'a List<T> {
unsafe impl<T: Sync> Sync for List<T> {}
-unsafe impl<'a, T: 'a> rustc_data_structures::tagged_ptr::Pointer for &'a List<T> {
- const BITS: usize = std::mem::align_of::<usize>().trailing_zeros() as usize;
-
- #[inline]
- fn into_usize(self) -> usize {
- self as *const List<T> as usize
- }
-
- #[inline]
- unsafe fn from_usize(ptr: usize) -> &'a List<T> {
- &*(ptr as *const List<T>)
- }
+// Safety:
+// Layouts of `Equivalent<T>` and `List<T>` are the same, modulo opaque tail,
+// thus aligns of `Equivalent<T>` and `List<T>` must be the same.
+unsafe impl<T> Aligned for List<T> {
+ const ALIGN: ptr::Alignment = {
+ #[repr(C)]
+ struct Equivalent<T> {
+ _len: usize,
+ _data: [T; 0],
+ }
- unsafe fn with_ref<R, F: FnOnce(&Self) -> R>(ptr: usize, f: F) -> R {
- // `Self` is `&'a List<T>` which impls `Copy`, so this is fine.
- let ptr = Self::from_usize(ptr);
- f(&ptr)
- }
+ align_of::<Equivalent<T>>()
+ };
}
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 2e516f291bc..42b98540ac7 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -1007,7 +1007,7 @@ impl<'tcx> Term<'tcx> {
_ => None,
},
TermKind::Const(ct) => match ct.kind() {
- ConstKind::Unevaluated(uv) => Some(tcx.mk_alias_ty(uv.def.did, uv.substs)),
+ ConstKind::Unevaluated(uv) => Some(tcx.mk_alias_ty(uv.def, uv.substs)),
_ => None,
},
}
@@ -1471,135 +1471,6 @@ pub struct BoundConst<'tcx> {
pub type PlaceholderConst<'tcx> = Placeholder<BoundVar>;
-/// A `DefId` which, in case it is a const argument, is potentially bundled with
-/// the `DefId` of the generic parameter it instantiates.
-///
-/// This is used to avoid calls to `type_of` for const arguments during typeck
-/// which cause cycle errors.
-///
-/// ```rust
-/// struct A;
-/// impl A {
-/// fn foo<const N: usize>(&self) -> [u8; N] { [0; N] }
-/// // ^ const parameter
-/// }
-/// struct B;
-/// impl B {
-/// fn foo<const M: u8>(&self) -> usize { 42 }
-/// // ^ const parameter
-/// }
-///
-/// fn main() {
-/// let a = A;
-/// let _b = a.foo::<{ 3 + 7 }>();
-/// // ^^^^^^^^^ const argument
-/// }
-/// ```
-///
-/// Let's look at the call `a.foo::<{ 3 + 7 }>()` here. We do not know
-/// which `foo` is used until we know the type of `a`.
-///
-/// We only know the type of `a` once we are inside of `typeck(main)`.
-/// We also end up normalizing the type of `_b` during `typeck(main)` which
-/// requires us to evaluate the const argument.
-///
-/// To evaluate that const argument we need to know its type,
-/// which we would get using `type_of(const_arg)`. This requires us to
-/// resolve `foo` as it can be either `usize` or `u8` in this example.
-/// However, resolving `foo` once again requires `typeck(main)` to get the type of `a`,
-/// which results in a cycle.
-///
-/// In short we must not call `type_of(const_arg)` during `typeck(main)`.
-///
-/// When first creating the `ty::Const` of the const argument inside of `typeck` we have
-/// already resolved `foo` so we know which const parameter this argument instantiates.
-/// This means that we also know the expected result of `type_of(const_arg)` even if we
-/// aren't allowed to call that query: it is equal to `type_of(const_param)` which is
-/// trivial to compute.
-///
-/// If we now want to use that constant in a place which potentially needs its type
-/// we also pass the type of its `const_param`. This is the point of `WithOptConstParam`,
-/// except that instead of a `Ty` we bundle the `DefId` of the const parameter.
-/// Meaning that we need to use `type_of(const_param_did)` if `const_param_did` is `Some`
-/// to get the type of `did`.
-#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift, TyEncodable, TyDecodable)]
-#[derive(PartialEq, Eq, PartialOrd, Ord)]
-#[derive(Hash, HashStable)]
-pub struct WithOptConstParam<T> {
- pub did: T,
- /// The `DefId` of the corresponding generic parameter in case `did` is
- /// a const argument.
- ///
- /// Note that even if `did` is a const argument, this may still be `None`.
- /// All queries taking `WithOptConstParam` start by calling `tcx.opt_const_param_of(def.did)`
- /// to potentially update `param_did` in the case it is `None`.
- pub const_param_did: Option<DefId>,
-}
-
-impl<T> WithOptConstParam<T> {
- /// Creates a new `WithOptConstParam` setting `const_param_did` to `None`.
- #[inline(always)]
- pub fn unknown(did: T) -> WithOptConstParam<T> {
- WithOptConstParam { did, const_param_did: None }
- }
-}
-
-impl WithOptConstParam<LocalDefId> {
- /// Returns `Some((did, param_did))` if `def_id` is a const argument,
- /// `None` otherwise.
- #[inline(always)]
- pub fn try_lookup(did: LocalDefId, tcx: TyCtxt<'_>) -> Option<(LocalDefId, DefId)> {
- tcx.opt_const_param_of(did).map(|param_did| (did, param_did))
- }
-
- /// In case `self` is unknown but `self.did` is a const argument, this returns
- /// a `WithOptConstParam` with the correct `const_param_did`.
- #[inline(always)]
- pub fn try_upgrade(self, tcx: TyCtxt<'_>) -> Option<WithOptConstParam<LocalDefId>> {
- if self.const_param_did.is_none() {
- if let const_param_did @ Some(_) = tcx.opt_const_param_of(self.did) {
- return Some(WithOptConstParam { did: self.did, const_param_did });
- }
- }
-
- None
- }
-
- pub fn to_global(self) -> WithOptConstParam<DefId> {
- WithOptConstParam { did: self.did.to_def_id(), const_param_did: self.const_param_did }
- }
-
- pub fn def_id_for_type_of(self) -> DefId {
- if let Some(did) = self.const_param_did { did } else { self.did.to_def_id() }
- }
-}
-
-impl WithOptConstParam<DefId> {
- pub fn as_local(self) -> Option<WithOptConstParam<LocalDefId>> {
- self.did
- .as_local()
- .map(|did| WithOptConstParam { did, const_param_did: self.const_param_did })
- }
-
- pub fn as_const_arg(self) -> Option<(LocalDefId, DefId)> {
- if let Some(param_did) = self.const_param_did {
- if let Some(did) = self.did.as_local() {
- return Some((did, param_did));
- }
- }
-
- None
- }
-
- pub fn is_local(self) -> bool {
- self.did.is_local()
- }
-
- pub fn def_id_for_type_of(self) -> DefId {
- self.const_param_did.unwrap_or(self.did)
- }
-}
-
/// When type checking, we use the `ParamEnv` to track
/// details about the set of where-clauses that are in scope at this
/// particular point.
@@ -1627,7 +1498,8 @@ struct ParamTag {
}
unsafe impl rustc_data_structures::tagged_ptr::Tag for ParamTag {
- const BITS: usize = 2;
+ const BITS: u32 = 2;
+
#[inline]
fn into_usize(self) -> usize {
match self {
@@ -1637,6 +1509,7 @@ unsafe impl rustc_data_structures::tagged_ptr::Tag for ParamTag {
Self { reveal: traits::Reveal::All, constness: hir::Constness::Const } => 3,
}
}
+
#[inline]
unsafe fn from_usize(ptr: usize) -> Self {
match ptr {
@@ -1850,12 +1723,6 @@ impl<'tcx, T> ParamEnvAnd<'tcx, T> {
pub fn into_parts(self) -> (ParamEnv<'tcx>, T) {
(self.param_env, self.value)
}
-
- #[inline]
- pub fn without_const(mut self) -> Self {
- self.param_env = self.param_env.without_const();
- self
- }
}
#[derive(Copy, Clone, Debug, HashStable, Encodable, Decodable)]
@@ -1969,6 +1836,16 @@ impl VariantDef {
pub fn ctor_def_id(&self) -> Option<DefId> {
self.ctor.map(|(_, def_id)| def_id)
}
+
+ /// Returns the one field in this variant.
+ ///
+ /// `panic!`s if there are no fields or multiple fields.
+ #[inline]
+ pub fn single_field(&self) -> &FieldDef {
+ assert!(self.fields.len() == 1);
+
+ &self.fields[FieldIdx::from_u32(0)]
+ }
}
impl PartialEq for VariantDef {
@@ -2361,7 +2238,7 @@ impl<'tcx> TyCtxt<'tcx> {
match instance {
ty::InstanceDef::Item(def) => {
debug!("calling def_kind on def: {:?}", def);
- let def_kind = self.def_kind(def.did);
+ let def_kind = self.def_kind(def);
debug!("returned from def_kind: {:?}", def_kind);
match def_kind {
DefKind::Const
@@ -2369,13 +2246,10 @@ impl<'tcx> TyCtxt<'tcx> {
| DefKind::AssocConst
| DefKind::Ctor(..)
| DefKind::AnonConst
- | DefKind::InlineConst => self.mir_for_ctfe_opt_const_arg(def),
+ | DefKind::InlineConst => self.mir_for_ctfe(def),
// If the caller wants `mir_for_ctfe` of a function they should not be using
// `instance_mir`, so we'll assume const fn also wants the optimized version.
- _ => {
- assert_eq!(def.const_param_did, None);
- self.optimized_mir(def.did)
- }
+ _ => self.optimized_mir(def),
}
}
ty::InstanceDef::VTableShim(..)
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 72caadaf661..888b3a50b77 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -738,7 +738,9 @@ pub trait PrettyPrinter<'tcx>:
}
}
ty::Placeholder(placeholder) => match placeholder.bound.kind {
- ty::BoundTyKind::Anon => p!(write("Placeholder({:?})", placeholder)),
+ ty::BoundTyKind::Anon => {
+ self.pretty_print_placeholder_var(placeholder.universe, placeholder.bound.var)?
+ }
ty::BoundTyKind::Param(_, name) => p!(write("{}", name)),
},
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
@@ -1172,6 +1174,18 @@ pub trait PrettyPrinter<'tcx>:
}
}
+ fn pretty_print_placeholder_var(
+ &mut self,
+ ui: ty::UniverseIndex,
+ var: ty::BoundVar,
+ ) -> Result<(), Self::Error> {
+ if ui == ty::UniverseIndex::ROOT {
+ write!(self, "!{}", var.index())
+ } else {
+ write!(self, "!{}_{}", ui.index(), var.index())
+ }
+ }
+
fn ty_infer_name(&self, _: ty::TyVid) -> Option<Symbol> {
None
}
@@ -1328,13 +1342,13 @@ pub trait PrettyPrinter<'tcx>:
match ct.kind() {
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }) => {
- match self.tcx().def_kind(def.did) {
+ match self.tcx().def_kind(def) {
DefKind::Const | DefKind::AssocConst => {
- p!(print_value_path(def.did, substs))
+ p!(print_value_path(def, substs))
}
DefKind::AnonConst => {
if def.is_local()
- && let span = self.tcx().def_span(def.did)
+ && let span = self.tcx().def_span(def)
&& let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span)
{
p!(write("{}", snip))
@@ -1344,7 +1358,7 @@ pub trait PrettyPrinter<'tcx>:
// cause printing to enter an infinite recursion if the anon const is in the self type i.e.
// `impl<T: Default> Default for [T; 32 - 1 - 1 - 1] {`
// where we would try to print `<[T; /* print `constant#0` again */] as Default>::{constant#0}`
- p!(write("{}::{}", self.tcx().crate_name(def.did.krate), self.tcx().def_path(def.did).to_string_no_crate_verbose()))
+ p!(write("{}::{}", self.tcx().crate_name(def.krate), self.tcx().def_path(def).to_string_no_crate_verbose()))
}
}
defkind => bug!("`{:?}` has unexpected defkind {:?}", ct, defkind),
@@ -2518,7 +2532,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
self.used_region_names.insert(name);
}
- r.super_visit_with(self)
+ ControlFlow::Continue(())
}
// We collect types in order to prevent really large types from compiling for
diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs
index fa9fea72344..e46cfb8dd16 100644
--- a/compiler/rustc_middle/src/ty/query.rs
+++ b/compiler/rustc_middle/src/ty/query.rs
@@ -76,6 +76,9 @@ use std::ops::Deref;
use std::path::PathBuf;
use std::sync::Arc;
+use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_query_system::ich::StableHashingContext;
+
#[derive(Default)]
pub struct QuerySystem<'tcx> {
pub arenas: QueryArenas<'tcx>,
@@ -202,16 +205,6 @@ macro_rules! separate_provide_extern_default {
};
}
-macro_rules! opt_remap_env_constness {
- ([][$name:ident]) => {};
- ([(remap_env_constness) $($rest:tt)*][$name:ident]) => {
- let $name = $name.without_const();
- };
- ([$other:tt $($modifiers:tt)*][$name:ident]) => {
- opt_remap_env_constness!([$($modifiers)*][$name])
- };
-}
-
macro_rules! define_callbacks {
(
$($(#[$attr:meta])*
@@ -353,7 +346,6 @@ macro_rules! define_callbacks {
#[inline(always)]
pub fn $name(self, key: query_helper_param_ty!($($K)*)) {
let key = key.into_query_param();
- opt_remap_env_constness!([$($modifiers)*][key]);
match try_get_cached(self.tcx, &self.tcx.query_system.caches.$name, &key) {
Some(_) => return,
@@ -372,7 +364,6 @@ macro_rules! define_callbacks {
#[inline(always)]
pub fn $name(self, key: query_helper_param_ty!($($K)*)) {
let key = key.into_query_param();
- opt_remap_env_constness!([$($modifiers)*][key]);
match try_get_cached(self.tcx, &self.tcx.query_system.caches.$name, &key) {
Some(_) => return,
@@ -402,7 +393,6 @@ macro_rules! define_callbacks {
pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V
{
let key = key.into_query_param();
- opt_remap_env_constness!([$($modifiers)*][key]);
restore::<$V>(match try_get_cached(self.tcx, &self.tcx.query_system.caches.$name, &key) {
Some(value) => value,
@@ -490,22 +480,33 @@ macro_rules! define_feedable {
$(impl<'tcx, K: IntoQueryParam<$($K)*> + Copy> TyCtxtFeed<'tcx, K> {
$(#[$attr])*
#[inline(always)]
- pub fn $name(self, value: query_provided::$name<'tcx>) -> $V {
+ pub fn $name(self, value: query_provided::$name<'tcx>) {
let key = self.key().into_query_param();
- opt_remap_env_constness!([$($modifiers)*][key]);
let tcx = self.tcx;
let erased = query_provided_to_value::$name(tcx, value);
let value = restore::<$V>(erased);
let cache = &tcx.query_system.caches.$name;
+ let hasher: Option<fn(&mut StableHashingContext<'_>, &_) -> _> = hash_result!([$($modifiers)*]);
match try_get_cached(tcx, cache, &key) {
Some(old) => {
let old = restore::<$V>(old);
- bug!(
- "Trying to feed an already recorded value for query {} key={key:?}:\nold value: {old:?}\nnew value: {value:?}",
- stringify!($name),
- )
+ if let Some(hasher) = hasher {
+ let (value_hash, old_hash): (Fingerprint, Fingerprint) = tcx.with_stable_hashing_context(|mut hcx|
+ (hasher(&mut hcx, &value), hasher(&mut hcx, &old))
+ );
+ assert_eq!(
+ old_hash, value_hash,
+ "Trying to feed an already recorded value for query {} key={key:?}:\nold value: {old:?}\nnew value: {value:?}",
+ stringify!($name),
+ )
+ } else {
+ bug!(
+ "Trying to feed an already recorded value for query {} key={key:?}:\nold value: {old:?}\nnew value: {value:?}",
+ stringify!($name),
+ )
+ }
}
None => {
let dep_node = dep_graph::DepNode::construct(tcx, dep_graph::DepKind::$name, &key);
@@ -517,7 +518,6 @@ macro_rules! define_feedable {
hash_result!([$($modifiers)*]),
);
cache.complete(key, erased, dep_node_index);
- value
}
}
}
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index 46c931d61dc..c6d10f4741a 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -7,7 +7,7 @@
use crate::ty::error::{ExpectedFound, TypeError};
use crate::ty::{self, Expr, ImplSubject, Term, TermKind, Ty, TyCtxt, TypeFoldable};
use crate::ty::{GenericArg, GenericArgKind, SubstsRef};
-use rustc_hir as ast;
+use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_target::spec::abi;
use std::iter;
@@ -123,8 +123,8 @@ pub fn relate_type_and_mut<'tcx, R: TypeRelation<'tcx>>(
} else {
let mutbl = a.mutbl;
let (variance, info) = match mutbl {
- ast::Mutability::Not => (ty::Covariant, ty::VarianceDiagInfo::None),
- ast::Mutability::Mut => {
+ hir::Mutability::Not => (ty::Covariant, ty::VarianceDiagInfo::None),
+ hir::Mutability::Mut => {
(ty::Invariant, ty::VarianceDiagInfo::Invariant { ty: base_ty, param_index: 0 })
}
};
@@ -239,12 +239,12 @@ impl<'tcx> Relate<'tcx> for ty::BoundConstness {
}
}
-impl<'tcx> Relate<'tcx> for ast::Unsafety {
+impl<'tcx> Relate<'tcx> for hir::Unsafety {
fn relate<R: TypeRelation<'tcx>>(
relation: &mut R,
- a: ast::Unsafety,
- b: ast::Unsafety,
- ) -> RelateResult<'tcx, ast::Unsafety> {
+ a: hir::Unsafety,
+ b: hir::Unsafety,
+ ) -> RelateResult<'tcx, hir::Unsafety> {
if a != b {
Err(TypeError::UnsafetyMismatch(expected_found(relation, a, b)))
} else {
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 5c604bb6db2..8a2258375ab 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -197,7 +197,7 @@ impl<'tcx> fmt::Debug for AliasTy<'tcx> {
// Atomic structs
//
// For things that don't carry any arena-allocated data (and are
-// copy...), just add them to one of these lists as appropriat.
+// copy...), just add them to one of these lists as appropriate.
// For things for which the type library provides traversal implementations
// for all Interners, we only need to provide a Lift implementation:
@@ -276,9 +276,7 @@ TrivialTypeTraversalAndLiftImpls! {
}
TrivialTypeTraversalAndLiftImpls! {
- for<'tcx> {
- ty::ValTree<'tcx>,
- }
+ ty::ValTree<'tcx>,
}
///////////////////////////////////////////////////////////////////////////
@@ -583,24 +581,6 @@ impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Region<'tcx> {
}
}
-impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Region<'tcx> {
- fn try_super_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
- self,
- _folder: &mut F,
- ) -> Result<Self, F::Error> {
- Ok(self)
- }
-}
-
-impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Region<'tcx> {
- fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(
- &self,
- _visitor: &mut V,
- ) -> ControlFlow<V::BreakTy> {
- ControlFlow::Continue(())
- }
-}
-
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
self,
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs
index f05b873432d..a439211ca33 100644
--- a/compiler/rustc_middle/src/ty/subst.rs
+++ b/compiler/rustc_middle/src/ty/subst.rs
@@ -21,7 +21,6 @@ use std::marker::PhantomData;
use std::mem;
use std::num::NonZeroUsize;
use std::ops::{ControlFlow, Deref};
-use std::slice;
/// An entity in the Rust type system, which can be one of
/// several kinds (types, lifetimes, and consts).
@@ -48,38 +47,13 @@ const TYPE_TAG: usize = 0b00;
const REGION_TAG: usize = 0b01;
const CONST_TAG: usize = 0b10;
-#[derive(Debug, TyEncodable, TyDecodable, PartialEq, Eq, PartialOrd, Ord)]
+#[derive(Debug, TyEncodable, TyDecodable, PartialEq, Eq, PartialOrd, Ord, HashStable)]
pub enum GenericArgKind<'tcx> {
Lifetime(ty::Region<'tcx>),
Type(Ty<'tcx>),
Const(ty::Const<'tcx>),
}
-/// This function goes from `&'a [Ty<'tcx>]` to `&'a [GenericArg<'tcx>]`
-///
-/// This is sound as, for types, `GenericArg` is just
-/// `NonZeroUsize::new_unchecked(ty as *const _ as usize)` as
-/// long as we use `0` for the `TYPE_TAG`.
-pub fn ty_slice_as_generic_args<'a, 'tcx>(ts: &'a [Ty<'tcx>]) -> &'a [GenericArg<'tcx>] {
- assert_eq!(TYPE_TAG, 0);
- // SAFETY: the whole slice is valid and immutable.
- // `Ty` and `GenericArg` is explained above.
- unsafe { slice::from_raw_parts(ts.as_ptr().cast(), ts.len()) }
-}
-
-impl<'tcx> List<Ty<'tcx>> {
- /// Allows to freely switch between `List<Ty<'tcx>>` and `List<GenericArg<'tcx>>`.
- ///
- /// As lists are interned, `List<Ty<'tcx>>` and `List<GenericArg<'tcx>>` have
- /// be interned together, see `mk_type_list` for more details.
- #[inline]
- pub fn as_substs(&'tcx self) -> SubstsRef<'tcx> {
- assert_eq!(TYPE_TAG, 0);
- // SAFETY: `List<T>` is `#[repr(C)]`. `Ty` and `GenericArg` is explained above.
- unsafe { &*(self as *const List<Ty<'tcx>> as *const List<GenericArg<'tcx>>) }
- }
-}
-
impl<'tcx> GenericArgKind<'tcx> {
#[inline]
fn pack(self) -> GenericArg<'tcx> {
@@ -180,30 +154,45 @@ impl<'tcx> GenericArg<'tcx> {
}
}
- /// Unpack the `GenericArg` as a region when it is known certainly to be a region.
- pub fn expect_region(self) -> ty::Region<'tcx> {
+ #[inline]
+ pub fn as_type(self) -> Option<Ty<'tcx>> {
+ match self.unpack() {
+ GenericArgKind::Type(ty) => Some(ty),
+ _ => None,
+ }
+ }
+
+ #[inline]
+ pub fn as_region(self) -> Option<ty::Region<'tcx>> {
+ match self.unpack() {
+ GenericArgKind::Lifetime(re) => Some(re),
+ _ => None,
+ }
+ }
+
+ #[inline]
+ pub fn as_const(self) -> Option<ty::Const<'tcx>> {
match self.unpack() {
- GenericArgKind::Lifetime(lt) => lt,
- _ => bug!("expected a region, but found another kind"),
+ GenericArgKind::Const(ct) => Some(ct),
+ _ => None,
}
}
+ /// Unpack the `GenericArg` as a region when it is known certainly to be a region.
+ pub fn expect_region(self) -> ty::Region<'tcx> {
+ self.as_region().unwrap_or_else(|| bug!("expected a region, but found another kind"))
+ }
+
/// Unpack the `GenericArg` as a type when it is known certainly to be a type.
/// This is true in cases where `Substs` is used in places where the kinds are known
/// to be limited (e.g. in tuples, where the only parameters are type parameters).
pub fn expect_ty(self) -> Ty<'tcx> {
- match self.unpack() {
- GenericArgKind::Type(ty) => ty,
- _ => bug!("expected a type, but found another kind"),
- }
+ self.as_type().unwrap_or_else(|| bug!("expected a type, but found another kind"))
}
/// Unpack the `GenericArg` as a const when it is known certainly to be a const.
pub fn expect_const(self) -> ty::Const<'tcx> {
- match self.unpack() {
- GenericArgKind::Const(c) => c,
- _ => bug!("expected a const, but found another kind"),
- }
+ self.as_const().unwrap_or_else(|| bug!("expected a const, but found another kind"))
}
pub fn is_non_region_infer(self) -> bool {
@@ -268,13 +257,16 @@ pub type InternalSubsts<'tcx> = List<GenericArg<'tcx>>;
pub type SubstsRef<'tcx> = &'tcx InternalSubsts<'tcx>;
impl<'tcx> InternalSubsts<'tcx> {
- /// Checks whether all elements of this list are types, if so, transmute.
- pub fn try_as_type_list(&'tcx self) -> Option<&'tcx List<Ty<'tcx>>> {
- self.iter().all(|arg| matches!(arg.unpack(), GenericArgKind::Type(_))).then(|| {
- assert_eq!(TYPE_TAG, 0);
- // SAFETY: All elements are types, see `List<Ty<'tcx>>::as_substs`.
- unsafe { &*(self as *const List<GenericArg<'tcx>> as *const List<Ty<'tcx>>) }
- })
+ /// Converts substs to a type list.
+ ///
+ /// # Panics
+ ///
+ /// If any of the generic arguments are not types.
+ pub fn into_type_list(&self, tcx: TyCtxt<'tcx>) -> &'tcx List<Ty<'tcx>> {
+ tcx.mk_type_list_from_iter(self.iter().map(|arg| match arg.unpack() {
+ GenericArgKind::Type(ty) => ty,
+ _ => bug!("`into_type_list` called on substs with non-types"),
+ }))
}
/// Interpret these substitutions as the substitutions of a closure type.
@@ -379,22 +371,17 @@ impl<'tcx> InternalSubsts<'tcx> {
#[inline]
pub fn types(&'tcx self) -> impl DoubleEndedIterator<Item = Ty<'tcx>> + 'tcx {
- self.iter()
- .filter_map(|k| if let GenericArgKind::Type(ty) = k.unpack() { Some(ty) } else { None })
+ self.iter().filter_map(|k| k.as_type())
}
#[inline]
pub fn regions(&'tcx self) -> impl DoubleEndedIterator<Item = ty::Region<'tcx>> + 'tcx {
- self.iter().filter_map(|k| {
- if let GenericArgKind::Lifetime(lt) = k.unpack() { Some(lt) } else { None }
- })
+ self.iter().filter_map(|k| k.as_region())
}
#[inline]
pub fn consts(&'tcx self) -> impl DoubleEndedIterator<Item = ty::Const<'tcx>> + 'tcx {
- self.iter().filter_map(|k| {
- if let GenericArgKind::Const(ct) = k.unpack() { Some(ct) } else { None }
- })
+ self.iter().filter_map(|k| k.as_const())
}
#[inline]
@@ -410,31 +397,21 @@ impl<'tcx> InternalSubsts<'tcx> {
#[inline]
#[track_caller]
pub fn type_at(&self, i: usize) -> Ty<'tcx> {
- if let GenericArgKind::Type(ty) = self[i].unpack() {
- ty
- } else {
- bug!("expected type for param #{} in {:?}", i, self);
- }
+ self[i].as_type().unwrap_or_else(|| bug!("expected type for param #{} in {:?}", i, self))
}
#[inline]
#[track_caller]
pub fn region_at(&self, i: usize) -> ty::Region<'tcx> {
- if let GenericArgKind::Lifetime(lt) = self[i].unpack() {
- lt
- } else {
- bug!("expected region for param #{} in {:?}", i, self);
- }
+ self[i]
+ .as_region()
+ .unwrap_or_else(|| bug!("expected region for param #{} in {:?}", i, self))
}
#[inline]
#[track_caller]
pub fn const_at(&self, i: usize) -> ty::Const<'tcx> {
- if let GenericArgKind::Const(ct) = self[i].unpack() {
- ct
- } else {
- bug!("expected const for param #{} in {:?}", i, self);
- }
+ self[i].as_const().unwrap_or_else(|| bug!("expected const for param #{} in {:?}", i, self))
}
#[inline]
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index 47943b94c3b..ef8955b1d3a 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -208,6 +208,9 @@ pub struct TypeckResults<'tcx> {
/// Contains the data for evaluating the effect of feature `capture_disjoint_fields`
/// on closure size.
pub closure_size_eval: FxHashMap<LocalDefId, ClosureSizeProfileData<'tcx>>,
+
+ /// Container types and field indices of `offset_of!` expressions
+ offset_of_data: ItemLocalMap<(Ty<'tcx>, Vec<FieldIdx>)>,
}
/// Whenever a value may be live across a generator yield, the type of that value winds up in the
@@ -280,6 +283,7 @@ impl<'tcx> TypeckResults<'tcx> {
generator_interior_predicates: Default::default(),
treat_byte_string_as_slice: Default::default(),
closure_size_eval: Default::default(),
+ offset_of_data: Default::default(),
}
}
@@ -530,6 +534,14 @@ impl<'tcx> TypeckResults<'tcx> {
pub fn coercion_casts(&self) -> &ItemLocalSet {
&self.coercion_casts
}
+
+ pub fn offset_of_data(&self) -> LocalTableInContext<'_, (Ty<'tcx>, Vec<FieldIdx>)> {
+ LocalTableInContext { hir_owner: self.hir_owner, data: &self.offset_of_data }
+ }
+
+ pub fn offset_of_data_mut(&mut self) -> LocalTableInContextMut<'_, (Ty<'tcx>, Vec<FieldIdx>)> {
+ LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.offset_of_data }
+ }
}
/// Validate that the given HirId (respectively its `local_id` part) can be
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index c8a78ec03d9..dbe2eebe336 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -11,7 +11,7 @@ use crate::ty::{
use crate::ty::{GenericArgKind, SubstsRef};
use rustc_apfloat::Float as _;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Res};
@@ -124,7 +124,7 @@ impl IntTypeExt for IntegerType {
impl<'tcx> TyCtxt<'tcx> {
/// Creates a hash of the type `Ty` which will be the same no matter what crate
/// context it's calculated within. This is used by the `type_id` intrinsic.
- pub fn type_id_hash(self, ty: Ty<'tcx>) -> u64 {
+ pub fn type_id_hash(self, ty: Ty<'tcx>) -> Hash64 {
// We want the type_id be independent of the types free regions, so we
// erase them. The erase_regions() call will also anonymize bound
// regions, which is desirable too.
@@ -642,7 +642,7 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
- /// Return the set of types that should be taken into accound when checking
+ /// Return the set of types that should be taken into account when checking
/// trait bounds on a generator's internal state.
pub fn generator_hidden_types(
self,
@@ -694,13 +694,6 @@ impl<'tcx> TyCtxt<'tcx> {
if visitor.found_recursion { Err(expanded_type) } else { Ok(expanded_type) }
}
- pub fn bound_return_position_impl_trait_in_trait_tys(
- self,
- def_id: DefId,
- ) -> ty::EarlyBinder<Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed>> {
- ty::EarlyBinder(self.collect_return_position_impl_trait_in_trait_tys(def_id))
- }
-
pub fn bound_explicit_item_bounds(
self,
def_id: DefId,
@@ -1402,7 +1395,7 @@ pub fn is_trivially_const_drop(ty: Ty<'_>) -> bool {
}
/// Does the equivalent of
-/// ```ignore (ilustrative)
+/// ```ignore (illustrative)
/// let v = self.iter().map(|p| p.fold_with(folder)).collect::<SmallVec<[_; 8]>>();
/// folder.tcx().intern_*(&v)
/// ```
diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs
index 08a62c900f9..1b07f52afca 100644
--- a/compiler/rustc_middle/src/ty/visit.rs
+++ b/compiler/rustc_middle/src/ty/visit.rs
@@ -33,6 +33,14 @@ pub trait TypeVisitableExt<'tcx>: TypeVisitable<TyCtxt<'tcx>> {
}
fn has_type_flags(&self, flags: TypeFlags) -> bool {
+ // N.B. Even though this uses a visitor, the visitor does not actually
+ // recurse through the whole `TypeVisitable` implementor type.
+ //
+ // Instead it stops on the first "level", visiting types, regions,
+ // consts and predicates just fetches their type flags.
+ //
+ // Thus this is a lot faster than it might seem and should be
+ // optimized to a simple field access.
let res =
self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() == Some(FoundFlags);
trace!(?self, ?flags, ?res, "has_type_flags");
@@ -364,7 +372,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ValidateBoundVars<'tcx> {
_ => (),
};
- r.super_visit_with(self)
+ ControlFlow::Continue(())
}
}
diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs
index 182945b9c3d..04a635a6803 100644
--- a/compiler/rustc_middle/src/ty/walk.rs
+++ b/compiler/rustc_middle/src/ty/walk.rs
@@ -194,7 +194,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
| ty::FnDef(_, substs) => {
stack.extend(substs.iter().rev());
}
- ty::Tuple(ts) => stack.extend(ts.as_substs().iter().rev()),
+ ty::Tuple(ts) => stack.extend(ts.iter().rev().map(GenericArg::from)),
ty::GeneratorWitness(ts) => {
stack.extend(ts.skip_binder().iter().rev().map(|ty| ty.into()));
}
diff --git a/compiler/rustc_const_eval/src/util/call_kind.rs b/compiler/rustc_middle/src/util/call_kind.rs
index 995363c0edd..627c84c388c 100644
--- a/compiler/rustc_const_eval/src/util/call_kind.rs
+++ b/compiler/rustc_middle/src/util/call_kind.rs
@@ -2,10 +2,10 @@
//! as well as errors when attempting to call a non-const function in a const
//! context.
+use crate::ty::subst::SubstsRef;
+use crate::ty::{AssocItemContainer, Instance, ParamEnv, Ty, TyCtxt};
use rustc_hir::def_id::DefId;
use rustc_hir::{lang_items, LangItem};
-use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{AssocItemContainer, Instance, ParamEnv, Ty, TyCtxt};
use rustc_span::symbol::Ident;
use rustc_span::{sym, DesugaringKind, Span};
diff --git a/compiler/rustc_const_eval/src/util/find_self_call.rs b/compiler/rustc_middle/src/util/find_self_call.rs
index 33ad128eeeb..0eab0adf07e 100644
--- a/compiler/rustc_const_eval/src/util/find_self_call.rs
+++ b/compiler/rustc_middle/src/util/find_self_call.rs
@@ -1,6 +1,6 @@
-use rustc_middle::mir::*;
-use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, TyCtxt};
+use crate::mir::*;
+use crate::ty::subst::SubstsRef;
+use crate::ty::{self, TyCtxt};
use rustc_span::def_id::DefId;
/// Checks if the specified `local` is used as the `self` parameter of a method call
diff --git a/compiler/rustc_middle/src/util/mod.rs b/compiler/rustc_middle/src/util/mod.rs
new file mode 100644
index 00000000000..53b4257899b
--- /dev/null
+++ b/compiler/rustc_middle/src/util/mod.rs
@@ -0,0 +1,7 @@
+pub mod bug;
+pub mod call_kind;
+pub mod common;
+pub mod find_self_call;
+
+pub use call_kind::{call_kind, CallDesugaringKind, CallKind};
+pub use find_self_call::find_self_call;
diff --git a/compiler/rustc_mir_build/Cargo.toml b/compiler/rustc_mir_build/Cargo.toml
index f24b165d7c2..58449ee9eb4 100644
--- a/compiler/rustc_mir_build/Cargo.toml
+++ b/compiler/rustc_mir_build/Cargo.toml
@@ -14,6 +14,7 @@ rustc_apfloat = { path = "../rustc_apfloat" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_index = { path = "../rustc_index" }
rustc_errors = { path = "../rustc_errors" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_hir = { path = "../rustc_hir" }
rustc_infer = { path = "../rustc_infer" }
rustc_macros = { path = "../rustc_macros" }
diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
index 99291740ac8..fbcfd433724 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
@@ -78,7 +78,7 @@ pub fn as_constant_inner<'tcx>(
ExprKind::NamedConst { def_id, substs, ref user_ty } => {
let user_ty = user_ty.as_ref().and_then(push_cuta);
- let uneval = mir::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs);
+ let uneval = mir::UnevaluatedConst::new(def_id, substs);
let literal = ConstantKind::Unevaluated(uneval, ty);
Constant { user_ty, span, literal }
@@ -90,7 +90,7 @@ pub fn as_constant_inner<'tcx>(
Constant { user_ty: None, span, literal }
}
ExprKind::ConstBlock { did: def_id, substs } => {
- let uneval = mir::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs);
+ let uneval = mir::UnevaluatedConst::new(def_id, substs);
let literal = ConstantKind::Unevaluated(uneval, ty);
Constant { user_ty: None, span, literal }
diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs
index fb775766c65..7ec57add66b 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_place.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs
@@ -557,6 +557,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
| ExprKind::ConstBlock { .. }
| ExprKind::StaticRef { .. }
| ExprKind::InlineAsm { .. }
+ | ExprKind::OffsetOf { .. }
| ExprKind::Yield { .. }
| ExprKind::ThreadLocalRef(_)
| ExprKind::Call { .. } => {
diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
index 8631749a524..fbde0b28f54 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -481,6 +481,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}))))
}
+ ExprKind::OffsetOf { container, fields } => {
+ block.and(Rvalue::NullaryOp(NullOp::OffsetOf(fields), container))
+ }
+
ExprKind::Literal { .. }
| ExprKind::NamedConst { .. }
| ExprKind::NonHirLiteral { .. }
diff --git a/compiler/rustc_mir_build/src/build/expr/category.rs b/compiler/rustc_mir_build/src/build/expr/category.rs
index d33401f0764..d9aa461c19d 100644
--- a/compiler/rustc_mir_build/src/build/expr/category.rs
+++ b/compiler/rustc_mir_build/src/build/expr/category.rs
@@ -67,7 +67,8 @@ impl Category {
| ExprKind::Repeat { .. }
| ExprKind::Assign { .. }
| ExprKind::AssignOp { .. }
- | ExprKind::ThreadLocalRef(_) => Some(Category::Rvalue(RvalueFunc::AsRvalue)),
+ | ExprKind::ThreadLocalRef(_)
+ | ExprKind::OffsetOf { .. } => Some(Category::Rvalue(RvalueFunc::AsRvalue)),
ExprKind::ConstBlock { .. }
| ExprKind::Literal { .. }
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index 05a723a6b67..29ff916d2cc 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -163,13 +163,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
//
// [block: If(lhs)] -true-> [else_block: dest = (rhs)]
// | (false)
- // [shortcurcuit_block: dest = false]
+ // [shortcircuit_block: dest = false]
//
// Or:
//
// [block: If(lhs)] -false-> [else_block: dest = (rhs)]
// | (true)
- // [shortcurcuit_block: dest = true]
+ // [shortcircuit_block: dest = true]
let (shortcircuit_block, mut else_block, join_block) = (
this.cfg.start_new_block(),
@@ -561,7 +561,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
| ExprKind::ZstLiteral { .. }
| ExprKind::ConstParam { .. }
| ExprKind::ThreadLocalRef(_)
- | ExprKind::StaticRef { .. } => {
+ | ExprKind::StaticRef { .. }
+ | ExprKind::OffsetOf { .. } => {
debug_assert!(match Category::of(&expr.kind).unwrap() {
// should be handled above
Category::Rvalue(RvalueFunc::Into) => false,
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index 8a03ea7e2cc..4536ecf17b8 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -77,7 +77,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
| PatKind::Wild
| PatKind::Binding { .. }
| PatKind::Leaf { .. }
- | PatKind::Deref { .. } => self.error_simplifyable(match_pair),
+ | PatKind::Deref { .. } => self.error_simplifiable(match_pair),
}
}
@@ -173,7 +173,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
debug_assert_ne!(
target_blocks[idx.index()],
otherwise_block,
- "no canididates for tested discriminant: {:?}",
+ "no candidates for tested discriminant: {:?}",
discr,
);
Some((discr.val, target_blocks[idx.index()]))
@@ -181,7 +181,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
debug_assert_eq!(
target_blocks[idx.index()],
otherwise_block,
- "found canididates for untested discriminant: {:?}",
+ "found candidates for untested discriminant: {:?}",
discr,
);
None
@@ -499,7 +499,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// However, in some cases, the test may just not be relevant to candidate.
/// For example, suppose we are testing whether `foo.x == 22`, but in one
/// match arm we have `Foo { x: _, ... }`... in that case, the test for
- /// what value `x` has has no particular relevance to this candidate. In
+ /// the value of `x` has no particular relevance to this candidate. In
/// such cases, this function just returns None without doing anything.
/// This is used by the overall `match_candidates` algorithm to structure
/// the match as a whole. See `match_candidates` for more details.
@@ -763,8 +763,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
candidate.match_pairs.extend(consequent_match_pairs);
}
- fn error_simplifyable<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> ! {
- span_bug!(match_pair.pattern.span, "simplifyable pattern found: {:?}", match_pair.pattern)
+ fn error_simplifiable<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> ! {
+ span_bug!(match_pair.pattern.span, "simplifiable pattern found: {:?}", match_pair.pattern)
}
fn const_range_contains(
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index bc50bcbc3d0..b05c3056cba 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -32,38 +32,20 @@ use super::lints;
pub(crate) fn mir_built(
tcx: TyCtxt<'_>,
- def: ty::WithOptConstParam<LocalDefId>,
+ def: LocalDefId,
) -> &rustc_data_structures::steal::Steal<Body<'_>> {
- if let Some(def) = def.try_upgrade(tcx) {
- return tcx.mir_built(def);
- }
-
- let mut body = mir_build(tcx, def);
- if def.const_param_did.is_some() {
- assert!(matches!(body.source.instance, ty::InstanceDef::Item(_)));
- body.source = MirSource::from_instance(ty::InstanceDef::Item(def.to_global()));
- }
-
- tcx.alloc_steal_mir(body)
+ tcx.alloc_steal_mir(mir_build(tcx, def))
}
/// Construct the MIR for a given `DefId`.
-fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_> {
+fn mir_build(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> {
// Ensure unsafeck and abstract const building is ran before we steal the THIR.
- match def {
- ty::WithOptConstParam { did, const_param_did: Some(const_param_did) } => {
- tcx.ensure_with_value().thir_check_unsafety_for_const_arg((did, const_param_did));
- tcx.ensure_with_value().thir_abstract_const_of_const_arg((did, const_param_did));
- }
- ty::WithOptConstParam { did, const_param_did: None } => {
- tcx.ensure_with_value().thir_check_unsafety(did);
- tcx.ensure_with_value().thir_abstract_const(did);
- tcx.ensure_with_value().check_match(did);
- }
- }
+ tcx.ensure_with_value().thir_check_unsafety(def);
+ tcx.ensure_with_value().thir_abstract_const(def);
+ tcx.ensure_with_value().check_match(def);
let body = match tcx.thir_body(def) {
- Err(error_reported) => construct_error(tcx, def.did, error_reported),
+ Err(error_reported) => construct_error(tcx, def, error_reported),
Ok((thir, expr)) => {
// We ran all queries that depended on THIR at the beginning
// of `mir_build`, so now we can steal it
@@ -161,8 +143,7 @@ struct Builder<'a, 'tcx> {
thir: &'a Thir<'tcx>,
cfg: CFG<'tcx>,
- def: ty::WithOptConstParam<LocalDefId>,
- def_id: DefId,
+ def_id: LocalDefId,
hir_id: hir::HirId,
parent_module: DefId,
check_overflow: bool,
@@ -428,26 +409,26 @@ macro_rules! unpack {
fn construct_fn<'tcx>(
tcx: TyCtxt<'tcx>,
- fn_def: ty::WithOptConstParam<LocalDefId>,
+ fn_def: LocalDefId,
thir: &Thir<'tcx>,
expr: ExprId,
fn_sig: ty::FnSig<'tcx>,
) -> Body<'tcx> {
- let span = tcx.def_span(fn_def.did);
- let fn_id = tcx.hir().local_def_id_to_hir_id(fn_def.did);
- let generator_kind = tcx.generator_kind(fn_def.did);
+ let span = tcx.def_span(fn_def);
+ let fn_id = tcx.hir().local_def_id_to_hir_id(fn_def);
+ let generator_kind = tcx.generator_kind(fn_def);
// The representation of thir for `-Zunpretty=thir-tree` relies on
// the entry expression being the last element of `thir.exprs`.
assert_eq!(expr.as_usize(), thir.exprs.len() - 1);
// Figure out what primary body this item has.
- let body_id = tcx.hir().body_owned_by(fn_def.did);
+ let body_id = tcx.hir().body_owned_by(fn_def);
let span_with_body = tcx.hir().span_with_body(fn_id);
let return_ty_span = tcx
.hir()
.fn_decl_by_hir_id(fn_id)
- .unwrap_or_else(|| span_bug!(span, "can't build MIR for {:?}", fn_def.did))
+ .unwrap_or_else(|| span_bug!(span, "can't build MIR for {:?}", fn_def))
.output
.span();
@@ -457,7 +438,7 @@ fn construct_fn<'tcx>(
};
let mut abi = fn_sig.abi;
- if let DefKind::Closure = tcx.def_kind(fn_def.did) {
+ if let DefKind::Closure = tcx.def_kind(fn_def) {
// HACK(eddyb) Avoid having RustCall on closures,
// as it adds unnecessary (and wrong) auto-tupling.
abi = Abi::Rust;
@@ -483,7 +464,7 @@ fn construct_fn<'tcx>(
{
return custom::build_custom_mir(
tcx,
- fn_def.did.to_def_id(),
+ fn_def.to_def_id(),
fn_id,
thir,
expr,
@@ -547,12 +528,12 @@ fn construct_fn<'tcx>(
fn construct_const<'a, 'tcx>(
tcx: TyCtxt<'tcx>,
- def: ty::WithOptConstParam<LocalDefId>,
+ def: LocalDefId,
thir: &'a Thir<'tcx>,
expr: ExprId,
const_ty: Ty<'tcx>,
) -> Body<'tcx> {
- let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def);
// Figure out what primary body this item has.
let (span, const_ty_span) = match tcx.hir().get(hir_id) {
@@ -568,10 +549,10 @@ fn construct_const<'a, 'tcx>(
..
}) => (*span, ty.span),
Node::AnonConst(_) => {
- let span = tcx.def_span(def.did);
+ let span = tcx.def_span(def);
(span, span)
}
- _ => span_bug!(tcx.def_span(def.did), "can't build MIR for {:?}", def.did),
+ _ => span_bug!(tcx.def_span(def), "can't build MIR for {:?}", def),
};
let infcx = tcx.infer_ctxt().build();
@@ -669,7 +650,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
fn new(
thir: &'a Thir<'tcx>,
infcx: InferCtxt<'tcx>,
- def: ty::WithOptConstParam<LocalDefId>,
+ def: LocalDefId,
hir_id: hir::HirId,
span: Span,
arg_count: usize,
@@ -688,20 +669,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
check_overflow |= tcx.sess.overflow_checks();
// Constants always need overflow checks.
check_overflow |= matches!(
- tcx.hir().body_owner_kind(def.did),
+ tcx.hir().body_owner_kind(def),
hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_)
);
let lint_level = LintLevel::Explicit(hir_id);
- let param_env = tcx.param_env(def.did);
+ let param_env = tcx.param_env(def);
let mut builder = Builder {
thir,
tcx,
infcx,
- region_scope_tree: tcx.region_scope_tree(def.did),
+ region_scope_tree: tcx.region_scope_tree(def),
param_env,
- def,
- def_id: def.did.to_def_id(),
+ def_id: def,
hir_id,
parent_module: tcx.parent_module(hir_id).to_def_id(),
check_overflow,
@@ -741,7 +721,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
Body::new(
- MirSource::item(self.def_id),
+ MirSource::item(self.def_id.to_def_id()),
self.cfg.basic_blocks,
self.source_scopes,
self.local_decls,
@@ -779,7 +759,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let tcx = self.tcx;
self.upvars = tcx
- .closure_captures(self.def.did)
+ .closure_captures(self.def_id)
.iter()
.zip(capture_tys)
.enumerate()
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index 03a7f2d70fa..0506f2bf238 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -117,10 +117,10 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
}
/// Handle closures/generators/inline-consts, which is unsafecked with their parent body.
- fn visit_inner_body(&mut self, def: ty::WithOptConstParam<LocalDefId>) {
+ fn visit_inner_body(&mut self, def: 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 hir_context = self.tcx.hir().local_def_id_to_hir_id(def);
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
@@ -323,6 +323,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
| ExprKind::Box { .. }
| ExprKind::If { .. }
| ExprKind::InlineAsm { .. }
+ | ExprKind::OffsetOf { .. }
| ExprKind::LogicalOp { .. }
| ExprKind::Use { .. } => {
// We don't need to save the old value and restore it
@@ -396,18 +397,11 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
movability: _,
fake_reads: _,
}) => {
- let closure_def = if let Some((did, const_param_id)) =
- ty::WithOptConstParam::try_lookup(closure_id, self.tcx)
- {
- ty::WithOptConstParam { did, const_param_did: Some(const_param_id) }
- } else {
- ty::WithOptConstParam::unknown(closure_id)
- };
- self.visit_inner_body(closure_def);
+ self.visit_inner_body(closure_id);
}
ExprKind::ConstBlock { did, substs: _ } => {
let def_id = did.expect_local();
- self.visit_inner_body(ty::WithOptConstParam::unknown(def_id));
+ self.visit_inner_body(def_id);
}
ExprKind::Field { lhs, .. } => {
let lhs = &self.thir[lhs];
@@ -706,14 +700,14 @@ impl UnsafeOpKind {
}
}
-pub fn check_unsafety(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) {
+pub fn thir_check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) {
// THIR unsafeck is gated under `-Z thir-unsafeck`
if !tcx.sess.opts.unstable_opts.thir_unsafeck {
return;
}
// Closures and inline consts are handled by their owner, if it has a body
- if tcx.is_typeck_child(def.did.to_def_id()) {
+ if tcx.is_typeck_child(def.to_def_id()) {
return;
}
@@ -726,7 +720,7 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) {
return;
}
- let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def);
let body_unsafety = tcx.hir().fn_sig_by_hir_id(hir_id).map_or(BodyUnsafety::Safe, |fn_sig| {
if fn_sig.header.unsafety == hir::Unsafety::Unsafe {
BodyUnsafety::Unsafe(fn_sig.span)
@@ -734,7 +728,7 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) {
BodyUnsafety::Safe
}
});
- let body_target_features = &tcx.body_codegen_attrs(def.did.to_def_id()).target_features;
+ let body_target_features = &tcx.body_codegen_attrs(def.to_def_id()).target_features;
let safety_context =
if body_unsafety.is_unsafe() { SafetyContext::UnsafeFn } else { SafetyContext::Safe };
let mut visitor = UnsafetyVisitor {
@@ -746,23 +740,8 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) {
body_target_features,
assignment_info: None,
in_union_destructure: false,
- param_env: tcx.param_env(def.did),
+ param_env: tcx.param_env(def),
inside_adt: false,
};
visitor.visit_expr(&thir[expr]);
}
-
-pub(crate) fn thir_check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
- if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) {
- tcx.thir_check_unsafety_for_const_arg(def)
- } else {
- check_unsafety(tcx, ty::WithOptConstParam::unknown(def_id))
- }
-}
-
-pub(crate) fn thir_check_unsafety_for_const_arg(
- tcx: TyCtxt<'_>,
- (did, param_did): (LocalDefId, DefId),
-) {
- check_unsafety(tcx, ty::WithOptConstParam { did, const_param_did: Some(param_did) })
-}
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index 43e787db41a..dcdeaf008d6 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -384,13 +384,8 @@ impl<'a> IntoDiagnostic<'a> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> {
diag.span_note(span, fluent::mir_build_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,
- };
-
+ let is_variant_list_non_exhaustive = matches!(self.ty.kind(),
+ ty::Adt(def, _) if def.is_variant_list_non_exhaustive() && !def.did().is_local());
if is_variant_list_non_exhaustive {
diag.note(fluent::mir_build_non_exhaustive_type_note);
} else {
diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs
index 3f9236c9dd9..2765a107cf0 100644
--- a/compiler/rustc_mir_build/src/lib.rs
+++ b/compiler/rustc_mir_build/src/lib.rs
@@ -25,7 +25,7 @@ pub mod thir;
use rustc_middle::ty::query::Providers;
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
-use rustc_macros::fluent_messages;
+use rustc_fluent_macro::fluent_messages;
fluent_messages! { "../messages.ftl" }
@@ -35,7 +35,6 @@ pub fn provide(providers: &mut Providers) {
providers.lit_to_mir_constant = build::lit_to_mir_constant;
providers.mir_built = build::mir_built;
providers.thir_check_unsafety = check_unsafety::thir_check_unsafety;
- providers.thir_check_unsafety_for_const_arg = check_unsafety::thir_check_unsafety_for_const_arg;
providers.thir_body = thir::cx::thir_body;
providers.thir_tree = thir::print::thir_tree;
providers.thir_flat = thir::print::thir_flat;
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 8e2e92e6f6a..ce13d522aae 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -664,6 +664,14 @@ impl<'tcx> Cx<'tcx> {
line_spans: asm.line_spans,
})),
+ hir::ExprKind::OffsetOf(_, _) => {
+ let data = self.typeck_results.offset_of_data();
+ let &(container, ref indices) = data.get(expr.hir_id).unwrap();
+ let fields = tcx.mk_fields_from_iter(indices.iter().copied());
+
+ ExprKind::OffsetOf { container, fields }
+ }
+
hir::ExprKind::ConstBlock(ref anon_const) => {
let ty = self.typeck_results().node_type(anon_const.hir_id);
let did = anon_const.def_id.to_def_id();
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index 070544446e3..463f639defe 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -20,25 +20,25 @@ use rustc_span::Span;
pub(crate) fn thir_body(
tcx: TyCtxt<'_>,
- owner_def: ty::WithOptConstParam<LocalDefId>,
+ owner_def: LocalDefId,
) -> Result<(&Steal<Thir<'_>>, ExprId), ErrorGuaranteed> {
let hir = tcx.hir();
- let body = hir.body(hir.body_owned_by(owner_def.did));
+ let body = hir.body(hir.body_owned_by(owner_def));
let mut cx = Cx::new(tcx, owner_def);
if let Some(reported) = cx.typeck_results.tainted_by_errors {
return Err(reported);
}
let expr = cx.mirror_expr(&body.value);
- let owner_id = hir.local_def_id_to_hir_id(owner_def.did);
+ let owner_id = hir.local_def_id_to_hir_id(owner_def);
if let Some(ref fn_decl) = hir.fn_decl_by_hir_id(owner_id) {
- let closure_env_param = cx.closure_env_param(owner_def.did, owner_id);
+ let closure_env_param = cx.closure_env_param(owner_def, owner_id);
let explicit_params = cx.explicit_params(owner_id, fn_decl, body);
cx.thir.params = closure_env_param.into_iter().chain(explicit_params).collect();
// The resume argument may be missing, in that case we need to provide it here.
// It will always be `()` in this case.
- if tcx.def_kind(owner_def.did) == DefKind::Generator && body.params.is_empty() {
+ if tcx.def_kind(owner_def) == DefKind::Generator && body.params.is_empty() {
cx.thir.params.push(Param {
ty: tcx.mk_unit(),
pat: None,
@@ -78,13 +78,12 @@ struct Cx<'tcx> {
}
impl<'tcx> Cx<'tcx> {
- fn new(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalDefId>) -> Cx<'tcx> {
- let typeck_results = tcx.typeck_opt_const_arg(def);
- let did = def.did;
+ fn new(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Cx<'tcx> {
+ let typeck_results = tcx.typeck(def);
let hir = tcx.hir();
- let hir_id = hir.local_def_id_to_hir_id(did);
+ let hir_id = hir.local_def_id_to_hir_id(def);
- let body_type = if hir.body_owner_kind(did).is_fn_or_closure() {
+ let body_type = if hir.body_owner_kind(def).is_fn_or_closure() {
// fetch the fully liberated fn signature (that is, all bound
// types/lifetimes replaced)
BodyTy::Fn(typeck_results.liberated_fn_sigs()[hir_id])
@@ -106,11 +105,11 @@ impl<'tcx> Cx<'tcx> {
Cx {
tcx,
thir: Thir::new(body_type),
- param_env: tcx.param_env(def.did),
- region_scope_tree: tcx.region_scope_tree(def.did),
+ param_env: tcx.param_env(def),
+ region_scope_tree: tcx.region_scope_tree(def),
typeck_results,
rvalue_scopes: &typeck_results.rvalue_scopes,
- body_owner: did.to_def_id(),
+ body_owner: def.to_def_id(),
adjustment_span: None,
apply_adjustments: hir
.attrs(hir_id)
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index bac46db2b1e..2b52d70af2a 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -27,7 +27,7 @@ use rustc_span::hygiene::DesugaringKind;
use rustc_span::Span;
pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) {
- let Ok((thir, expr)) = tcx.thir_body(ty::WithOptConstParam::unknown(def_id)) else { return };
+ let Ok((thir, expr)) = tcx.thir_body(def_id) else { return };
let thir = thir.borrow();
let pattern_arena = TypedArena::default();
let mut visitor = MatchVisitor {
@@ -671,10 +671,8 @@ fn non_exhaustive_match<'p, 'tcx>(
};
};
- let is_variant_list_non_exhaustive = match scrut_ty.kind() {
- ty::Adt(def, _) if def.is_variant_list_non_exhaustive() && !def.did().is_local() => true,
- _ => false,
- };
+ let is_variant_list_non_exhaustive = matches!(scrut_ty.kind(),
+ ty::Adt(def, _) if def.is_variant_list_non_exhaustive() && !def.did().is_local());
adt_defined_here(cx, &mut err, scrut_ty, &witnesses);
err.note(&format!(
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index 32d0404bd07..c99fc73fe8a 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -156,7 +156,7 @@ impl<'tcx> ConstToPat<'tcx> {
if let Some(non_sm_ty) = structural {
if !self.type_may_have_partial_eq_impl(cv.ty()) {
- // fatal avoids ICE from resolution of non-existent method (rare case).
+ // fatal avoids ICE from resolution of nonexistent method (rare case).
self.tcx()
.sess
.emit_fatal(TypeNotStructural { span: self.span, non_sm_ty: non_sm_ty });
diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs
index ed61d6ee78b..b2f2a64e29c 100644
--- a/compiler/rustc_mir_build/src/thir/print.rs
+++ b/compiler/rustc_mir_build/src/thir/print.rs
@@ -3,7 +3,7 @@ use rustc_middle::ty::{self, TyCtxt};
use rustc_span::def_id::LocalDefId;
use std::fmt::{self, Write};
-pub(crate) fn thir_tree(tcx: TyCtxt<'_>, owner_def: ty::WithOptConstParam<LocalDefId>) -> String {
+pub(crate) fn thir_tree(tcx: TyCtxt<'_>, owner_def: LocalDefId) -> String {
match super::cx::thir_body(tcx, owner_def) {
Ok((thir, _)) => {
let thir = thir.steal();
@@ -15,7 +15,7 @@ pub(crate) fn thir_tree(tcx: TyCtxt<'_>, owner_def: ty::WithOptConstParam<LocalD
}
}
-pub(crate) fn thir_flat(tcx: TyCtxt<'_>, owner_def: ty::WithOptConstParam<LocalDefId>) -> String {
+pub(crate) fn thir_flat(tcx: TyCtxt<'_>, owner_def: LocalDefId) -> String {
match super::cx::thir_body(tcx, owner_def) {
Ok((thir, _)) => format!("{:#?}", thir.steal()),
Err(_) => "error".into(),
@@ -519,6 +519,19 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
self.print_inline_asm_expr(&**expr, depth_lvl + 2);
print_indented!(self, "}", depth_lvl);
}
+ OffsetOf { container, fields } => {
+ print_indented!(self, "OffsetOf {", depth_lvl);
+ print_indented!(self, format!("container: {:?}", container), depth_lvl + 1);
+ print_indented!(self, "fields: [", depth_lvl + 1);
+
+ for field in fields.iter() {
+ print_indented!(self, format!("{:?}", field), depth_lvl + 2);
+ print_indented!(self, ",", depth_lvl + 1);
+ }
+
+ print_indented!(self, "]", depth_lvl + 1);
+ print_indented!(self, "}", depth_lvl);
+ }
ThreadLocalRef(def_id) => {
print_indented!(self, "ThreadLocalRef {", depth_lvl);
print_indented!(self, format!("def_id: {:?}", def_id), depth_lvl + 1);
diff --git a/compiler/rustc_mir_dataflow/Cargo.toml b/compiler/rustc_mir_dataflow/Cargo.toml
index 68c61a18d72..4a296bb3367 100644
--- a/compiler/rustc_mir_dataflow/Cargo.toml
+++ b/compiler/rustc_mir_dataflow/Cargo.toml
@@ -13,6 +13,7 @@ tracing = "0.1"
rustc_ast = { path = "../rustc_ast" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_graphviz = { path = "../rustc_graphviz" }
rustc_hir = { path = "../rustc_hir" }
rustc_index = { path = "../rustc_index" }
diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs
index 43caa2ea973..fc4efb943e6 100644
--- a/compiler/rustc_mir_dataflow/src/lib.rs
+++ b/compiler/rustc_mir_dataflow/src/lib.rs
@@ -16,8 +16,8 @@ extern crate rustc_middle;
use rustc_ast::MetaItem;
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
+use rustc_fluent_macro::fluent_messages;
use rustc_hir::def_id::DefId;
-use rustc_macros::fluent_messages;
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::symbol::{sym, Symbol};
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
index 64ed7a29f6f..736ca62cacc 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
@@ -360,7 +360,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
| Rvalue::AddressOf(..)
| Rvalue::Discriminant(..)
| Rvalue::Len(..)
- | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => {}
+ | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => {}
}
}
diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs
index 98bebc9b13b..d8fd06eab86 100644
--- a/compiler/rustc_mir_dataflow/src/value_analysis.rs
+++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs
@@ -366,7 +366,7 @@ where
rustc_index::newtype_index!(
/// This index uniquely identifies a place.
///
- /// Not every place has a `PlaceIndex`, and not every `PlaceIndex` correspondends to a tracked
+ /// Not every place has a `PlaceIndex`, and not every `PlaceIndex` corresponds to a tracked
/// place. However, every tracked place and all places along its projection have a `PlaceIndex`.
pub struct PlaceIndex {}
);
diff --git a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
index 896fcd9cdd6..b29ffcc70f9 100644
--- a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
+++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
@@ -10,7 +10,7 @@ use rustc_middle::mir::patch::MirPatch;
/// they are dropped from an aligned address.
///
/// For example, if we have something like
-/// ```ignore (ilustrative)
+/// ```ignore (illustrative)
/// #[repr(packed)]
/// struct Foo {
/// dealign: u8,
@@ -25,7 +25,7 @@ use rustc_middle::mir::patch::MirPatch;
/// its address is not aligned.
///
/// Instead, we move `foo.data` to a local and drop that:
-/// ```ignore (ilustrative)
+/// ```ignore (illustrative)
/// storage.live(drop_temp)
/// drop_temp = foo.data;
/// drop(drop_temp) -> next
diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs
index 916f2904dda..187d38b385b 100644
--- a/compiler/rustc_mir_transform/src/add_retag.rs
+++ b/compiler/rustc_mir_transform/src/add_retag.rs
@@ -59,7 +59,7 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
let basic_blocks = body.basic_blocks.as_mut();
let local_decls = &body.local_decls;
let needs_retag = |place: &Place<'tcx>| {
- !place.has_deref() // we're not eally interested in stores to "outside" locations, they are hard to keep track of anyway
+ !place.has_deref() // we're not really 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()
};
diff --git a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
index 3d32c586554..57b24c9c552 100644
--- a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
+++ b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
@@ -134,7 +134,12 @@ impl<'tcx> Visitor<'tcx> for ConstMutationChecker<'_, 'tcx> {
// the `self` parameter of a method call (as the terminator of our current
// BasicBlock). If so, we emit a more specific lint.
let method_did = self.target_local.and_then(|target_local| {
- crate::util::find_self_call(self.tcx, &self.body, target_local, loc.block)
+ rustc_middle::util::find_self_call(
+ self.tcx,
+ &self.body,
+ target_local,
+ loc.block,
+ )
});
let lint_loc =
if method_did.is_some() { self.body.terminator_loc(loc.block) } else { loc };
diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs
index d908f6b3a9b..ce6d865a7dc 100644
--- a/compiler/rustc_mir_transform/src/check_unsafety.rs
+++ b/compiler/rustc_mir_transform/src/check_unsafety.rs
@@ -148,7 +148,7 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
if let Some(uv) = maybe_uneval {
if uv.promoted.is_none() {
- let def_id = uv.def.def_id_for_type_of();
+ let def_id = uv.def;
if self.tcx.def_kind(def_id) == DefKind::InlineConst {
let local_def_id = def_id.expect_local();
let UnsafetyCheckResult { violations, used_unsafe_blocks, .. } =
@@ -375,22 +375,7 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> {
}
pub(crate) fn provide(providers: &mut Providers) {
- *providers = Providers {
- unsafety_check_result: |tcx, def_id| {
- if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) {
- tcx.unsafety_check_result_for_const_arg(def)
- } else {
- unsafety_check_result(tcx, ty::WithOptConstParam::unknown(def_id))
- }
- },
- unsafety_check_result_for_const_arg: |tcx, (did, param_did)| {
- unsafety_check_result(
- tcx,
- ty::WithOptConstParam { did, const_param_did: Some(param_did) },
- )
- },
- ..*providers
- };
+ *providers = Providers { unsafety_check_result, ..*providers };
}
/// Context information for [`UnusedUnsafeVisitor`] traversal,
@@ -492,10 +477,7 @@ fn check_unused_unsafe(
unused_unsafes
}
-fn unsafety_check_result(
- tcx: TyCtxt<'_>,
- def: ty::WithOptConstParam<LocalDefId>,
-) -> &UnsafetyCheckResult {
+fn unsafety_check_result(tcx: TyCtxt<'_>, def: LocalDefId) -> &UnsafetyCheckResult {
debug!("unsafety_violations({:?})", def);
// N.B., this borrow is valid because all the consumers of
@@ -510,13 +492,13 @@ fn unsafety_check_result(
});
}
- let param_env = tcx.param_env(def.did);
+ let param_env = tcx.param_env(def);
- let mut checker = UnsafetyChecker::new(body, def.did, tcx, param_env);
+ let mut checker = UnsafetyChecker::new(body, def, tcx, param_env);
checker.visit_body(&body);
- let unused_unsafes = (!tcx.is_typeck_child(def.did.to_def_id()))
- .then(|| check_unused_unsafe(tcx, def.did, &checker.used_unsafe_blocks));
+ let unused_unsafes = (!tcx.is_typeck_child(def.to_def_id()))
+ .then(|| check_unused_unsafe(tcx, def, &checker.used_unsafe_blocks));
tcx.arena.alloc(UnsafetyCheckResult {
violations: checker.violations,
diff --git a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
index 0923824db48..d435d3ee69b 100644
--- a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
+++ b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
@@ -24,7 +24,6 @@ impl<'tcx> MirPass<'tcx> for CleanupPostBorrowck {
for statement in basic_block.statements.iter_mut() {
match statement.kind {
StatementKind::AscribeUserType(..)
- | StatementKind::PlaceMention(..)
| StatementKind::Assign(box (_, Rvalue::Ref(_, BorrowKind::Shallow, _)))
| StatementKind::FakeRead(..) => statement.make_nop(),
_ => (),
diff --git a/compiler/rustc_mir_transform/src/const_debuginfo.rs b/compiler/rustc_mir_transform/src/const_debuginfo.rs
index 6f0ae4f07ab..692b3182f7d 100644
--- a/compiler/rustc_mir_transform/src/const_debuginfo.rs
+++ b/compiler/rustc_mir_transform/src/const_debuginfo.rs
@@ -22,7 +22,7 @@ impl<'tcx> MirPass<'tcx> for ConstDebugInfo {
fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
trace!("running ConstDebugInfo on {:?}", body.source);
- for (local, constant) in find_optimization_oportunities(body) {
+ for (local, constant) in find_optimization_opportunities(body) {
for debuginfo in &mut body.var_debug_info {
if let VarDebugInfoContents::Place(p) = debuginfo.value {
if p.local == local && p.projection.is_empty() {
@@ -45,7 +45,7 @@ struct LocalUseVisitor {
local_assignment_locations: IndexVec<Local, Option<Location>>,
}
-fn find_optimization_oportunities<'tcx>(body: &Body<'tcx>) -> Vec<(Local, Constant<'tcx>)> {
+fn find_optimization_opportunities<'tcx>(body: &Body<'tcx>) -> Vec<(Local, Constant<'tcx>)> {
let mut visitor = LocalUseVisitor {
local_mutating_uses: IndexVec::from_elem(0, &body.local_decls),
local_assignment_locations: IndexVec::from_elem(None, &body.local_decls),
diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs
index c0146e3efb0..c9537f9a61c 100644
--- a/compiler/rustc_mir_transform/src/const_prop.rs
+++ b/compiler/rustc_mir_transform/src/const_prop.rs
@@ -826,7 +826,7 @@ impl Visitor<'_> for CanConstProp {
| NonMutatingUse(NonMutatingUseContext::AddressOf)
| MutatingUse(MutatingUseContext::Borrow)
| MutatingUse(MutatingUseContext::AddressOf) => {
- trace!("local {:?} can't be propagaged because it's used: {:?}", local, context);
+ trace!("local {:?} can't be propagated because it's used: {:?}", local, context);
self.can_const_prop[local] = ConstPropMode::NoPropagation;
}
}
diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs
index 699fe44892b..3a105a2abae 100644
--- a/compiler/rustc_mir_transform/src/const_prop_lint.rs
+++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs
@@ -493,7 +493,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
cond: &Operand<'tcx>,
location: Location,
) -> Option<!> {
- let ref value = self.eval_operand(&cond, location)?;
+ let value = &self.eval_operand(&cond, location)?;
trace!("assertion on {:?} should be {:?}", value, expected);
let expected = Scalar::from_bool(expected);
diff --git a/compiler/rustc_mir_transform/src/coverage/debug.rs b/compiler/rustc_mir_transform/src/coverage/debug.rs
index 725883b83fa..e554c470646 100644
--- a/compiler/rustc_mir_transform/src/coverage/debug.rs
+++ b/compiler/rustc_mir_transform/src/coverage/debug.rs
@@ -292,10 +292,8 @@ impl DebugCounters {
}
pub fn some_block_label(&self, operand: ExpressionOperandId) -> Option<&String> {
- self.some_counters.as_ref().map_or(None, |counters| {
- counters
- .get(&operand)
- .map_or(None, |debug_counter| debug_counter.some_block_label.as_ref())
+ self.some_counters.as_ref().and_then(|counters| {
+ counters.get(&operand).and_then(|debug_counter| debug_counter.some_block_label.as_ref())
})
}
diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs
index 7391a77b0a6..8ff67b5f8d3 100644
--- a/compiler/rustc_mir_transform/src/coverage/graph.rs
+++ b/compiler/rustc_mir_transform/src/coverage/graph.rs
@@ -111,7 +111,7 @@ impl CoverageGraph {
if predecessors.len() > 1 {
"predecessors.len() > 1".to_owned()
} else {
- format!("bb {} is not in precessors: {:?}", bb.index(), predecessors)
+ format!("bb {} is not in predecessors: {:?}", bb.index(), predecessors)
}
);
}
diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs
index 5ecb2d6a631..444b1565d36 100644
--- a/compiler/rustc_mir_transform/src/coverage/mod.rs
+++ b/compiler/rustc_mir_transform/src/coverage/mod.rs
@@ -577,5 +577,10 @@ fn get_body_span<'tcx>(
fn hash_mir_source<'tcx>(tcx: TyCtxt<'tcx>, hir_body: &'tcx rustc_hir::Body<'tcx>) -> u64 {
// FIXME(cjgillot) Stop hashing HIR manually here.
let owner = hir_body.id().hir_id.owner;
- tcx.hir_owner_nodes(owner).unwrap().opt_hash_including_bodies.unwrap().to_smaller_hash()
+ tcx.hir_owner_nodes(owner)
+ .unwrap()
+ .opt_hash_including_bodies
+ .unwrap()
+ .to_smaller_hash()
+ .as_u64()
}
diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs
index 3bd7f31b45d..bf01b45eb40 100644
--- a/compiler/rustc_mir_transform/src/coverage/query.rs
+++ b/compiler/rustc_mir_transform/src/coverage/query.rs
@@ -164,7 +164,6 @@ fn is_inlined(body: &Body<'_>, statement: &Statement<'_>) -> bool {
/// whether that means const mir or runtime mir. For `const fn` this opts for runtime
/// mir.
fn mir_body(tcx: TyCtxt<'_>, def_id: DefId) -> &mir::Body<'_> {
- let id = ty::WithOptConstParam::unknown(def_id);
- let def = ty::InstanceDef::Item(id);
+ let def = ty::InstanceDef::Item(def_id);
tcx.instance_mir(def)
}
diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
index d4db7e2de40..a56c5cc5c12 100644
--- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
+++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
@@ -351,7 +351,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
}
(FlatSet::Bottom, _) | (_, FlatSet::Bottom) => (FlatSet::Bottom, FlatSet::Bottom),
(_, _) => {
- // Could attempt some algebraic simplifcations here.
+ // Could attempt some algebraic simplifications here.
(FlatSet::Top, FlatSet::Top)
}
}
diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs
index 18c407b42d3..7bc5183a00a 100644
--- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs
+++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs
@@ -54,11 +54,10 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS
| StatementKind::Coverage(_)
| StatementKind::Intrinsic(_)
| StatementKind::ConstEvalCounter
+ | StatementKind::PlaceMention(_)
| StatementKind::Nop => (),
- StatementKind::FakeRead(_)
- | StatementKind::PlaceMention(_)
- | StatementKind::AscribeUserType(_, _) => {
+ StatementKind::FakeRead(_) | StatementKind::AscribeUserType(_, _) => {
bug!("{:?} not found in this MIR phase!", &statement.kind)
}
}
diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
index e5c3fa5646a..8ee08c5be34 100644
--- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
+++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
@@ -9,7 +9,7 @@ use rustc_hir::def_id::LocalDefId;
use rustc_index::bit_set::BitSet;
use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::{Body, Local, Location, Operand, Terminator, TerminatorKind, RETURN_PLACE};
-use rustc_middle::ty::{self, DeducedParamAttrs, ParamEnv, Ty, TyCtxt};
+use rustc_middle::ty::{self, DeducedParamAttrs, Ty, TyCtxt};
use rustc_session::config::OptLevel;
/// A visitor that determines which arguments have been mutated. We can't use the mutability field
@@ -198,11 +198,12 @@ pub fn deduced_param_attrs<'tcx>(
// see [1].
//
// [1]: https://github.com/rust-lang/rust/pull/103172#discussion_r999139997
+ let param_env = tcx.param_env_reveal_all_normalized(def_id);
let mut deduced_param_attrs = tcx.arena.alloc_from_iter(
body.local_decls.iter().skip(1).take(body.arg_count).enumerate().map(
|(arg_index, local_decl)| DeducedParamAttrs {
read_only: !deduce_read_only.mutable_args.contains(arg_index)
- && local_decl.ty.is_freeze(tcx, ParamEnv::reveal_all()),
+ && local_decl.ty.is_freeze(tcx, param_env),
},
),
);
diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs
index 39164917770..78758e2db28 100644
--- a/compiler/rustc_mir_transform/src/dest_prop.rs
+++ b/compiler/rustc_mir_transform/src/dest_prop.rs
@@ -69,7 +69,7 @@
//! of this is that such liveness analysis can report more accurate results about whole locals at
//! a time. For example, consider:
//!
-//! ```ignore (syntax-highliting-only)
+//! ```ignore (syntax-highlighting-only)
//! _1 = u;
//! // unrelated code
//! _1.f1 = v;
@@ -360,7 +360,7 @@ struct FilterInformation<'a, 'body, 'alloc, 'tcx> {
}
// We first implement some utility functions which we will expose removing candidates according to
-// different needs. Throughout the livenss filtering, the `candidates` are only ever accessed
+// different needs. Throughout the liveness filtering, the `candidates` are only ever accessed
// through these methods, and not directly.
impl<'alloc> Candidates<'alloc> {
/// Just `Vec::retain`, but the condition is inverted and we add debugging output
@@ -582,10 +582,9 @@ impl WriteInfo {
| StatementKind::Nop
| StatementKind::Coverage(_)
| StatementKind::StorageLive(_)
- | StatementKind::StorageDead(_) => (),
- StatementKind::FakeRead(_)
- | StatementKind::AscribeUserType(_, _)
- | StatementKind::PlaceMention(_) => {
+ | StatementKind::StorageDead(_)
+ | StatementKind::PlaceMention(_) => (),
+ StatementKind::FakeRead(_) | StatementKind::AscribeUserType(_, _) => {
bug!("{:?} not found in this MIR phase", statement)
}
}
diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs
index a702113bd99..1e115be2c2a 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -24,7 +24,7 @@ use std::fmt;
/// In general, the compiler cannot determine at compile time whether a destructor will run or not.
///
/// At a high level, this pass refines Drop to only run the destructor if the
-/// target is initialized. The way this is achievied is by inserting drop flags for every variable
+/// target is initialized. The way this is achieved is by inserting drop flags for every variable
/// that may be dropped, and then using those flags to determine whether a destructor should run.
/// Once this is complete, Drop terminators in the MIR correspond to a call to the "drop glue" or
/// "drop shim" for the type of the dropped place.
diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
index c9b24adba0c..db68adc8bc9 100644
--- a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
+++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
@@ -48,7 +48,7 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool {
return false;
}
- let body = &*tcx.mir_built(ty::WithOptConstParam::unknown(local_def_id)).borrow();
+ let body = &*tcx.mir_built(local_def_id).borrow();
let body_ty = tcx.type_of(def_id).skip_binder();
let body_abi = match body_ty.kind() {
diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs
index 8601c1b2d71..f26c6de9648 100644
--- a/compiler/rustc_mir_transform/src/function_item_references.rs
+++ b/compiler/rustc_mir_transform/src/function_item_references.rs
@@ -3,7 +3,7 @@ use rustc_errors::Applicability;
use rustc_hir::def_id::DefId;
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::*;
-use rustc_middle::ty::{self, EarlyBinder, GenericArgKind, PredicateKind, SubstsRef, Ty, TyCtxt};
+use rustc_middle::ty::{self, EarlyBinder, PredicateKind, SubstsRef, Ty, TyCtxt};
use rustc_session::lint::builtin::FUNCTION_ITEM_REFERENCES;
use rustc_span::{symbol::sym, Span};
use rustc_target::spec::abi::Abi;
@@ -45,14 +45,12 @@ impl<'tcx> Visitor<'tcx> for FunctionItemRefChecker<'_, 'tcx> {
// Handle calls to `transmute`
if self.tcx.is_diagnostic_item(sym::transmute, def_id) {
let arg_ty = args[0].ty(self.body, self.tcx);
- for generic_inner_ty in arg_ty.walk() {
- if let GenericArgKind::Type(inner_ty) = generic_inner_ty.unpack() {
- if let Some((fn_id, fn_substs)) =
- FunctionItemRefChecker::is_fn_ref(inner_ty)
- {
- let span = self.nth_arg_span(&args, 0);
- self.emit_lint(fn_id, fn_substs, source_info, span);
- }
+ for inner_ty in arg_ty.walk().filter_map(|arg| arg.as_type()) {
+ if let Some((fn_id, fn_substs)) =
+ FunctionItemRefChecker::is_fn_ref(inner_ty)
+ {
+ let span = self.nth_arg_span(&args, 0);
+ self.emit_lint(fn_id, fn_substs, source_info, span);
}
}
} else {
@@ -82,24 +80,22 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
let arg_defs = self.tcx.fn_sig(def_id).subst_identity().skip_binder().inputs();
for (arg_num, arg_def) in arg_defs.iter().enumerate() {
// For all types reachable from the argument type in the fn sig
- for generic_inner_ty in arg_def.walk() {
- if let GenericArgKind::Type(inner_ty) = generic_inner_ty.unpack() {
- // If the inner type matches the type bound by `Pointer`
- if inner_ty == bound_ty {
- // Do a substitution using the parameters from the callsite
- let subst_ty = EarlyBinder(inner_ty).subst(self.tcx, substs_ref);
- if let Some((fn_id, fn_substs)) =
- FunctionItemRefChecker::is_fn_ref(subst_ty)
- {
- let mut span = self.nth_arg_span(args, arg_num);
- if span.from_expansion() {
- // The operand's ctxt wouldn't display the lint since it's inside a macro so
- // we have to use the callsite's ctxt.
- let callsite_ctxt = span.source_callsite().ctxt();
- span = span.with_ctxt(callsite_ctxt);
- }
- self.emit_lint(fn_id, fn_substs, source_info, span);
+ for inner_ty in arg_def.walk().filter_map(|arg| arg.as_type()) {
+ // If the inner type matches the type bound by `Pointer`
+ if inner_ty == bound_ty {
+ // Do a substitution using the parameters from the callsite
+ let subst_ty = EarlyBinder(inner_ty).subst(self.tcx, substs_ref);
+ if let Some((fn_id, fn_substs)) =
+ FunctionItemRefChecker::is_fn_ref(subst_ty)
+ {
+ let mut span = self.nth_arg_span(args, arg_num);
+ if span.from_expansion() {
+ // The operand's ctxt wouldn't display the lint since it's inside a macro so
+ // we have to use the callsite's ctxt.
+ let callsite_ctxt = span.source_callsite().ctxt();
+ span = span.with_ctxt(callsite_ctxt);
}
+ self.emit_lint(fn_id, fn_substs, source_info, span);
}
}
}
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index 4c4423721fb..5b3a66bc3d2 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -1399,7 +1399,7 @@ pub(crate) fn mir_generator_witnesses<'tcx>(
) -> GeneratorLayout<'tcx> {
assert!(tcx.sess.opts.unstable_opts.drop_tracking_mir);
- let (body, _) = tcx.mir_promoted(ty::WithOptConstParam::unknown(def_id));
+ let (body, _) = tcx.mir_promoted(def_id);
let body = body.borrow();
let body = &*body;
@@ -1869,7 +1869,7 @@ fn check_must_not_suspend_ty<'tcx>(
},
)
}
- // If drop tracking is enabled, we want to look through references, since the referrent
+ // If drop tracking is enabled, we want to look through references, since the referent
// may not be considered live across the await point.
ty::Ref(_region, ty, _mutability) => {
let descr_pre = &format!("{}reference{} to ", data.descr_pre, plural_suffix);
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index f0cb317f449..1525933aee3 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -350,14 +350,8 @@ impl<'tcx> Inliner<'tcx> {
callsite: &CallSite<'tcx>,
callee_attrs: &CodegenFnAttrs,
) -> Result<(), &'static str> {
- match callee_attrs.inline {
- InlineAttr::Never => return Err("never inline hint"),
- InlineAttr::Always | InlineAttr::Hint => {}
- InlineAttr::None => {
- if self.tcx.sess.mir_opt_level() <= 2 {
- return Err("at mir-opt-level=2, only #[inline] is inlined");
- }
- }
+ if let InlineAttr::Never = callee_attrs.inline {
+ return Err("never inline hint");
}
// Only inline local functions if they would be eligible for cross-crate
diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs
index 8aa3c23d019..8b811d7e870 100644
--- a/compiler/rustc_mir_transform/src/inline/cycle.rs
+++ b/compiler/rustc_mir_transform/src/inline/cycle.rs
@@ -148,8 +148,7 @@ pub(crate) fn mir_inliner_callees<'tcx>(
let guard;
let body = match (instance, instance.def_id().as_local()) {
(InstanceDef::Item(_), Some(def_id)) => {
- let def = ty::WithOptConstParam::unknown(def_id);
- steal = tcx.mir_promoted(def).0;
+ steal = tcx.mir_promoted(def_id).0;
guard = steal.borrow();
&*guard
}
diff --git a/compiler/rustc_mir_transform/src/instcombine.rs b/compiler/rustc_mir_transform/src/instcombine.rs
index 3d06a0a495f..432852a1fdd 100644
--- a/compiler/rustc_mir_transform/src/instcombine.rs
+++ b/compiler/rustc_mir_transform/src/instcombine.rs
@@ -1,11 +1,9 @@
//! Performs various peephole optimizations.
+use crate::simplify::combine_duplicate_switch_targets;
use crate::MirPass;
use rustc_hir::Mutability;
-use rustc_middle::mir::{
- BinOp, Body, CastKind, Constant, ConstantKind, LocalDecls, Operand, Place, ProjectionElem,
- Rvalue, SourceInfo, Statement, StatementKind, SwitchTargets, Terminator, TerminatorKind, UnOp,
-};
+use rustc_middle::mir::*;
use rustc_middle::ty::layout::ValidityRequirement;
use rustc_middle::ty::util::IntTypeExt;
use rustc_middle::ty::{self, ParamEnv, SubstsRef, Ty, TyCtxt};
@@ -46,7 +44,7 @@ impl<'tcx> MirPass<'tcx> for InstCombine {
&mut block.terminator.as_mut().unwrap(),
&mut block.statements,
);
- ctx.combine_duplicate_switch_targets(&mut block.terminator.as_mut().unwrap());
+ combine_duplicate_switch_targets(block.terminator.as_mut().unwrap());
}
}
}
@@ -264,19 +262,6 @@ impl<'tcx> InstCombineContext<'tcx, '_> {
terminator.kind = TerminatorKind::Goto { target: destination_block };
}
- fn combine_duplicate_switch_targets(&self, terminator: &mut Terminator<'tcx>) {
- let TerminatorKind::SwitchInt { targets, .. } = &mut terminator.kind
- else { return };
-
- let otherwise = targets.otherwise();
- if targets.iter().any(|t| t.1 == otherwise) {
- *targets = SwitchTargets::new(
- targets.iter().filter(|t| t.1 != otherwise),
- targets.otherwise(),
- );
- }
- }
-
fn combine_intrinsic_assert(
&self,
terminator: &mut Terminator<'tcx>,
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index fc12d423cb0..6d8b4dc91f4 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -23,7 +23,7 @@ use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::steal::Steal;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{self, Visitor};
use rustc_index::vec::IndexVec;
use rustc_middle::mir::visit::Visitor as _;
@@ -48,6 +48,7 @@ mod add_retag;
mod check_const_item_mutation;
mod check_packed_ref;
pub mod check_unsafety;
+mod remove_place_mention;
// This pass is public to allow external drivers to perform MIR cleanup
pub mod cleanup_post_borrowck;
mod const_debuginfo;
@@ -111,36 +112,17 @@ pub fn provide(providers: &mut Providers) {
*providers = Providers {
mir_keys,
mir_const,
- mir_const_qualif: |tcx, def_id| {
- if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) {
- tcx.mir_const_qualif_const_arg(def)
- } else {
- mir_const_qualif(tcx, ty::WithOptConstParam::unknown(def_id))
- }
- },
- mir_const_qualif_const_arg: |tcx, (did, param_did)| {
- mir_const_qualif(tcx, ty::WithOptConstParam { did, const_param_did: Some(param_did) })
- },
+ mir_const_qualif,
mir_promoted,
mir_drops_elaborated_and_const_checked,
mir_for_ctfe,
- mir_for_ctfe_of_const_arg,
mir_generator_witnesses: generator::mir_generator_witnesses,
optimized_mir,
is_mir_available,
is_ctfe_mir_available: |tcx, did| is_mir_available(tcx, did),
mir_callgraph_reachable: inline::cycle::mir_callgraph_reachable,
mir_inliner_callees: inline::cycle::mir_inliner_callees,
- promoted_mir: |tcx, def_id| {
- if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) {
- tcx.promoted_mir_of_const_arg(def)
- } else {
- promoted_mir(tcx, ty::WithOptConstParam::unknown(def_id))
- }
- },
- promoted_mir_of_const_arg: |tcx, (did, param_did)| {
- promoted_mir(tcx, ty::WithOptConstParam { did, const_param_did: Some(param_did) })
- },
+ promoted_mir,
deduced_param_attrs: deduce_param_attrs::deduced_param_attrs,
..*providers
};
@@ -234,8 +216,8 @@ fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet<LocalDefId> {
set
}
-fn mir_const_qualif(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> ConstQualifs {
- let const_kind = tcx.hir().body_const_context(def.did);
+fn mir_const_qualif(tcx: TyCtxt<'_>, def: LocalDefId) -> ConstQualifs {
+ let const_kind = tcx.hir().body_const_context(def);
// No need to const-check a non-const `fn`.
if const_kind.is_none() {
@@ -253,7 +235,7 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) ->
return Default::default();
}
- let ccx = check_consts::ConstCx { body, tcx, const_kind, param_env: tcx.param_env(def.did) };
+ let ccx = check_consts::ConstCx { body, tcx, const_kind, param_env: tcx.param_env(def) };
let mut validator = check_consts::check::Checker::new(&ccx);
validator.check_body();
@@ -266,22 +248,14 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) ->
/// Make MIR ready for const evaluation. This is run on all MIR, not just on consts!
/// FIXME(oli-obk): it's unclear whether we still need this phase (and its corresponding query).
/// We used to have this for pre-miri MIR based const eval.
-fn mir_const(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> &Steal<Body<'_>> {
- if let Some(def) = def.try_upgrade(tcx) {
- return tcx.mir_const(def);
- }
-
+fn mir_const(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal<Body<'_>> {
// Unsafety check uses the raw mir, so make sure it is run.
if !tcx.sess.opts.unstable_opts.thir_unsafeck {
- if let Some(param_did) = def.const_param_did {
- tcx.ensure_with_value().unsafety_check_result_for_const_arg((def.did, param_did));
- } else {
- tcx.ensure_with_value().unsafety_check_result(def.did);
- }
+ tcx.ensure_with_value().unsafety_check_result(def);
}
// has_ffi_unwind_calls query uses the raw mir, so make sure it is run.
- tcx.ensure_with_value().has_ffi_unwind_calls(def.did);
+ tcx.ensure_with_value().has_ffi_unwind_calls(def);
let mut body = tcx.mir_built(def).steal();
@@ -296,7 +270,7 @@ fn mir_const(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> &Steal<
&Lint(check_const_item_mutation::CheckConstItemMutation),
&Lint(function_item_references::FunctionItemReferences),
// What we need to do constant evaluation.
- &simplify::SimplifyCfg::new("initial"),
+ &simplify::SimplifyCfg::Initial,
&rustc_peek::SanityCheck, // Just a lint
],
None,
@@ -307,16 +281,12 @@ fn mir_const(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> &Steal<
/// Compute the main MIR body and the list of MIR bodies of the promoteds.
fn mir_promoted(
tcx: TyCtxt<'_>,
- def: ty::WithOptConstParam<LocalDefId>,
+ def: LocalDefId,
) -> (&Steal<Body<'_>>, &Steal<IndexVec<Promoted, Body<'_>>>) {
- if let Some(def) = def.try_upgrade(tcx) {
- return tcx.mir_promoted(def);
- }
-
// Ensure that we compute the `mir_const_qualif` for constants at
// this point, before we steal the mir-const result.
// Also this means promotion can rely on all const checks having been done.
- let const_qualifs = tcx.mir_const_qualif_opt_const_arg(def);
+ let const_qualifs = tcx.mir_const_qualif(def);
let mut body = tcx.mir_const(def).steal();
if let Some(error_reported) = const_qualifs.tainted_by_errors {
body.tainted_by_errors = Some(error_reported);
@@ -334,11 +304,7 @@ fn mir_promoted(
pm::run_passes(
tcx,
&mut body,
- &[
- &promote_pass,
- &simplify::SimplifyCfg::new("promote-consts"),
- &coverage::InstrumentCoverage,
- ],
+ &[&promote_pass, &simplify::SimplifyCfg::PromoteConsts, &coverage::InstrumentCoverage],
Some(MirPhase::Analysis(AnalysisPhase::Initial)),
);
@@ -348,38 +314,22 @@ fn mir_promoted(
/// Compute the MIR that is used during CTFE (and thus has no optimizations run on it)
fn mir_for_ctfe(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &Body<'_> {
- if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) {
- tcx.mir_for_ctfe_of_const_arg(def)
- } else {
- tcx.arena.alloc(inner_mir_for_ctfe(tcx, ty::WithOptConstParam::unknown(def_id)))
- }
+ tcx.arena.alloc(inner_mir_for_ctfe(tcx, def_id))
}
-/// Same as `mir_for_ctfe`, but used to get the MIR of a const generic parameter.
-/// The docs on `WithOptConstParam` explain this a bit more, but the TLDR is that
-/// we'd get cycle errors with `mir_for_ctfe`, because typeck would need to typeck
-/// the const parameter while type checking the main body, which in turn would try
-/// to type check the main body again.
-fn mir_for_ctfe_of_const_arg(tcx: TyCtxt<'_>, (did, param_did): (LocalDefId, DefId)) -> &Body<'_> {
- tcx.arena.alloc(inner_mir_for_ctfe(
- tcx,
- ty::WithOptConstParam { did, const_param_did: Some(param_did) },
- ))
-}
-
-fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_> {
+fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> {
// FIXME: don't duplicate this between the optimized_mir/mir_for_ctfe queries
- if tcx.is_constructor(def.did.to_def_id()) {
+ if tcx.is_constructor(def.to_def_id()) {
// There's no reason to run all of the MIR passes on constructors when
// we can just output the MIR we want directly. This also saves const
// qualification and borrow checking the trouble of special casing
// constructors.
- return shim::build_adt_ctor(tcx, def.did.to_def_id());
+ return shim::build_adt_ctor(tcx, def.to_def_id());
}
let context = tcx
.hir()
- .body_const_context(def.did)
+ .body_const_context(def)
.expect("mir_for_ctfe should not be used for runtime functions");
let body = tcx.mir_drops_elaborated_and_const_checked(def).borrow().clone();
@@ -417,29 +367,19 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -
/// Obtain just the main MIR (no promoteds) and run some cleanups on it. This also runs
/// mir borrowck *before* doing so in order to ensure that borrowck can be run and doesn't
/// end up missing the source MIR due to stealing happening.
-fn mir_drops_elaborated_and_const_checked(
- tcx: TyCtxt<'_>,
- def: ty::WithOptConstParam<LocalDefId>,
-) -> &Steal<Body<'_>> {
- if let Some(def) = def.try_upgrade(tcx) {
- return tcx.mir_drops_elaborated_and_const_checked(def);
- }
-
+fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal<Body<'_>> {
if tcx.sess.opts.unstable_opts.drop_tracking_mir
- && let DefKind::Generator = tcx.def_kind(def.did)
+ && let DefKind::Generator = tcx.def_kind(def)
{
- tcx.ensure_with_value().mir_generator_witnesses(def.did);
+ tcx.ensure_with_value().mir_generator_witnesses(def);
}
- let mir_borrowck = tcx.mir_borrowck_opt_const_arg(def);
+ let mir_borrowck = tcx.mir_borrowck(def);
- let is_fn_like = tcx.def_kind(def.did).is_fn_like();
+ let is_fn_like = tcx.def_kind(def).is_fn_like();
if is_fn_like {
- let did = def.did.to_def_id();
- let def = ty::WithOptConstParam::unknown(did);
-
// Do not compute the mir call graph without said call graph actually being used.
if inline::Inline.is_enabled(&tcx.sess) {
- tcx.ensure_with_value().mir_inliner_callees(ty::InstanceDef::Item(def));
+ tcx.ensure_with_value().mir_inliner_callees(ty::InstanceDef::Item(def.to_def_id()));
}
}
@@ -467,10 +407,7 @@ fn run_analysis_to_runtime_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>
pm::run_passes(
tcx,
body,
- &[
- &remove_uninit_drops::RemoveUninitDrops,
- &simplify::SimplifyCfg::new("remove-false-edges"),
- ],
+ &[&remove_uninit_drops::RemoveUninitDrops, &simplify::SimplifyCfg::RemoveFalseEdges],
None,
);
check_consts::post_drop_elaboration::check_live_drops(tcx, &body); // FIXME: make this a MIR lint
@@ -492,7 +429,7 @@ fn run_analysis_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let passes: &[&dyn MirPass<'tcx>] = &[
&cleanup_post_borrowck::CleanupPostBorrowck,
&remove_noop_landing_pads::RemoveNoopLandingPads,
- &simplify::SimplifyCfg::new("early-opt"),
+ &simplify::SimplifyCfg::EarlyOpt,
&deref_separator::Derefer,
];
@@ -524,8 +461,11 @@ fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
/// Returns the sequence of passes that do the initial cleanup of runtime MIR.
fn run_runtime_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
- let passes: &[&dyn MirPass<'tcx>] =
- &[&lower_intrinsics::LowerIntrinsics, &simplify::SimplifyCfg::new("elaborate-drops")];
+ let passes: &[&dyn MirPass<'tcx>] = &[
+ &lower_intrinsics::LowerIntrinsics,
+ &remove_place_mention::RemovePlaceMention,
+ &simplify::SimplifyCfg::ElaborateDrops,
+ ];
pm::run_passes(tcx, body, passes, Some(MirPhase::Runtime(RuntimePhase::PostCleanup)));
@@ -551,7 +491,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
&lower_slice_len::LowerSliceLenCalls, // has to be done before inlining, otherwise actual call will be almost always inlined. Also simple, so can just do first
&unreachable_prop::UnreachablePropagation,
&uninhabited_enum_branching::UninhabitedEnumBranching,
- &o1(simplify::SimplifyCfg::new("after-uninhabited-enum-branching")),
+ &o1(simplify::SimplifyCfg::AfterUninhabitedEnumBranching),
&inline::Inline,
&remove_storage_markers::RemoveStorageMarkers,
&remove_zsts::RemoveZsts,
@@ -564,23 +504,23 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
&multiple_return_terminators::MultipleReturnTerminators,
&instcombine::InstCombine,
&separate_const_switch::SeparateConstSwitch,
- &simplify::SimplifyLocals::new("before-const-prop"),
+ &simplify::SimplifyLocals::BeforeConstProp,
&copy_prop::CopyProp,
&const_prop::ConstProp,
&dataflow_const_prop::DataflowConstProp,
//
// Const-prop runs unconditionally, but doesn't mutate the MIR at mir-opt-level=0.
&const_debuginfo::ConstDebugInfo,
- &o1(simplify_branches::SimplifyConstCondition::new("after-const-prop")),
+ &o1(simplify_branches::SimplifyConstCondition::AfterConstProp),
&early_otherwise_branch::EarlyOtherwiseBranch,
&simplify_comparison_integral::SimplifyComparisonIntegral,
&dead_store_elimination::DeadStoreElimination,
&dest_prop::DestinationPropagation,
- &o1(simplify_branches::SimplifyConstCondition::new("final")),
+ &o1(simplify_branches::SimplifyConstCondition::Final),
&o1(remove_noop_landing_pads::RemoveNoopLandingPads),
- &o1(simplify::SimplifyCfg::new("final")),
+ &o1(simplify::SimplifyCfg::Final),
&nrvo::RenameReturnPlace,
- &simplify::SimplifyLocals::new("final"),
+ &simplify::SimplifyLocals::Final,
&multiple_return_terminators::MultipleReturnTerminators,
&deduplicate_blocks::DeduplicateBlocks,
&large_enums::EnumSizeOpt { discrepancy: 128 },
@@ -595,7 +535,6 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
/// Optimize the MIR and prepare it for codegen.
fn optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> &Body<'_> {
- assert_eq!(ty::WithOptConstParam::try_lookup(did, tcx), None);
tcx.arena.alloc(inner_optimized_mir(tcx, did))
}
@@ -617,8 +556,7 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> {
Some(other) => panic!("do not use `optimized_mir` for constants: {:?}", other),
}
debug!("about to call mir_drops_elaborated...");
- let body =
- tcx.mir_drops_elaborated_and_const_checked(ty::WithOptConstParam::unknown(did)).steal();
+ let body = tcx.mir_drops_elaborated_and_const_checked(did).steal();
let mut body = remap_mir_for_const_eval_select(tcx, body, hir::Constness::NotConst);
debug!("body: {:#?}", body);
run_optimization_passes(tcx, &mut body);
@@ -628,15 +566,12 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> {
/// Fetch all the promoteds of an item and prepare their MIR bodies to be ready for
/// constant evaluation once all substitutions become known.
-fn promoted_mir(
- tcx: TyCtxt<'_>,
- def: ty::WithOptConstParam<LocalDefId>,
-) -> &IndexVec<Promoted, Body<'_>> {
- if tcx.is_constructor(def.did.to_def_id()) {
+fn promoted_mir(tcx: TyCtxt<'_>, def: LocalDefId) -> &IndexVec<Promoted, Body<'_>> {
+ if tcx.is_constructor(def.to_def_id()) {
return tcx.arena.alloc(IndexVec::new());
}
- let tainted_by_errors = tcx.mir_borrowck_opt_const_arg(def).tainted_by_errors;
+ let tainted_by_errors = tcx.mir_borrowck(def).tainted_by_errors;
let mut promoted = tcx.mir_promoted(def).1.steal();
for body in &mut promoted {
diff --git a/compiler/rustc_mir_transform/src/remove_place_mention.rs b/compiler/rustc_mir_transform/src/remove_place_mention.rs
new file mode 100644
index 00000000000..8be1c37572d
--- /dev/null
+++ b/compiler/rustc_mir_transform/src/remove_place_mention.rs
@@ -0,0 +1,23 @@
+//! This pass removes `PlaceMention` statement, which has no effect at codegen.
+
+use crate::MirPass;
+use rustc_middle::mir::*;
+use rustc_middle::ty::TyCtxt;
+
+pub struct RemovePlaceMention;
+
+impl<'tcx> MirPass<'tcx> for RemovePlaceMention {
+ fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
+ !sess.opts.unstable_opts.mir_keep_place_mention
+ }
+
+ fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+ trace!("Running RemovePlaceMention on {:?}", body.source);
+ for data in body.basic_blocks.as_mut_preserves_cfg() {
+ data.statements.retain(|statement| match statement.kind {
+ StatementKind::PlaceMention(..) | StatementKind::Nop => false,
+ _ => true,
+ })
+ }
+ }
+}
diff --git a/compiler/rustc_mir_transform/src/separate_const_switch.rs b/compiler/rustc_mir_transform/src/separate_const_switch.rs
index ef367faf6a7..2479856b727 100644
--- a/compiler/rustc_mir_transform/src/separate_const_switch.rs
+++ b/compiler/rustc_mir_transform/src/separate_const_switch.rs
@@ -303,8 +303,7 @@ fn find_determining_place<'tcx>(
| Rvalue::NullaryOp(_, _)
| Rvalue::ShallowInitBox(_, _)
| Rvalue::UnaryOp(_, Operand::Constant(_))
- | Rvalue::Cast(_, Operand::Constant(_), _)
- => return None,
+ | Rvalue::Cast(_, Operand::Constant(_), _) => return None,
}
}
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index 2787fe2ce42..4396a83e8b8 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -95,7 +95,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
&add_moves_for_packed_drops::AddMovesForPackedDrops,
&deref_separator::Derefer,
&remove_noop_landing_pads::RemoveNoopLandingPads,
- &simplify::SimplifyCfg::new("make_shim"),
+ &simplify::SimplifyCfg::MakeShim,
&add_call_guards::CriticalCallEdges,
&abort_unwinding_calls::AbortUnwindingCalls,
],
diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs
index c79e1cf0805..e1ca7c107b9 100644
--- a/compiler/rustc_mir_transform/src/simplify.rs
+++ b/compiler/rustc_mir_transform/src/simplify.rs
@@ -36,13 +36,31 @@ use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use smallvec::SmallVec;
-pub struct SimplifyCfg {
- label: String,
+pub enum SimplifyCfg {
+ Initial,
+ PromoteConsts,
+ RemoveFalseEdges,
+ EarlyOpt,
+ ElaborateDrops,
+ Final,
+ MakeShim,
+ AfterUninhabitedEnumBranching,
}
impl SimplifyCfg {
- pub fn new(label: &str) -> Self {
- SimplifyCfg { label: format!("SimplifyCfg-{}", label) }
+ pub fn name(&self) -> &'static str {
+ match self {
+ SimplifyCfg::Initial => "SimplifyCfg-initial",
+ SimplifyCfg::PromoteConsts => "SimplifyCfg-promote-consts",
+ SimplifyCfg::RemoveFalseEdges => "SimplifyCfg-remove-false-edges",
+ SimplifyCfg::EarlyOpt => "SimplifyCfg-early-opt",
+ SimplifyCfg::ElaborateDrops => "SimplifyCfg-elaborate-drops",
+ SimplifyCfg::Final => "SimplifyCfg-final",
+ SimplifyCfg::MakeShim => "SimplifyCfg-make_shim",
+ SimplifyCfg::AfterUninhabitedEnumBranching => {
+ "SimplifyCfg-after-uninhabited-enum-branching"
+ }
+ }
}
}
@@ -57,11 +75,11 @@ pub fn simplify_cfg<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
impl<'tcx> MirPass<'tcx> for SimplifyCfg {
fn name(&self) -> &str {
- &self.label
+ &self.name()
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
- debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, body.source);
+ debug!("SimplifyCfg({:?}) - simplifying {:?}", self.name(), body.source);
simplify_cfg(tcx, body);
}
}
@@ -260,6 +278,18 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
}
}
+pub fn combine_duplicate_switch_targets(terminator: &mut Terminator<'_>) {
+ if let TerminatorKind::SwitchInt { targets, .. } = &mut terminator.kind {
+ let otherwise = targets.otherwise();
+ if targets.iter().any(|t| t.1 == otherwise) {
+ *targets = SwitchTargets::new(
+ targets.iter().filter(|t| t.1 != otherwise),
+ targets.otherwise(),
+ );
+ }
+ }
+}
+
pub fn remove_duplicate_unreachable_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
struct OptApplier<'tcx> {
tcx: TyCtxt<'tcx>,
@@ -280,6 +310,8 @@ pub fn remove_duplicate_unreachable_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut B
}
}
+ combine_duplicate_switch_targets(terminator);
+
self.super_terminator(terminator, location);
}
}
@@ -423,19 +455,17 @@ fn save_unreachable_coverage(
));
}
-pub struct SimplifyLocals {
- label: String,
-}
-
-impl SimplifyLocals {
- pub fn new(label: &str) -> SimplifyLocals {
- SimplifyLocals { label: format!("SimplifyLocals-{}", label) }
- }
+pub enum SimplifyLocals {
+ BeforeConstProp,
+ Final,
}
impl<'tcx> MirPass<'tcx> for SimplifyLocals {
- fn name(&self) -> &str {
- &self.label
+ fn name(&self) -> &'static str {
+ match &self {
+ SimplifyLocals::BeforeConstProp => "SimplifyLocals-before-const-prop",
+ SimplifyLocals::Final => "SimplifyLocals-final",
+ }
}
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs
index 8164b305278..c65a7ec6783 100644
--- a/compiler/rustc_mir_transform/src/simplify_branches.rs
+++ b/compiler/rustc_mir_transform/src/simplify_branches.rs
@@ -2,20 +2,17 @@ use crate::MirPass;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
-/// A pass that replaces a branch with a goto when its condition is known.
-pub struct SimplifyConstCondition {
- label: String,
-}
-
-impl SimplifyConstCondition {
- pub fn new(label: &str) -> Self {
- SimplifyConstCondition { label: format!("SimplifyConstCondition-{}", label) }
- }
+pub enum SimplifyConstCondition {
+ AfterConstProp,
+ Final,
}
-
+/// A pass that replaces a branch with a goto when its condition is known.
impl<'tcx> MirPass<'tcx> for SimplifyConstCondition {
- fn name(&self) -> &str {
- &self.label
+ fn name(&self) -> &'static str {
+ match self {
+ SimplifyConstCondition::AfterConstProp => "SimplifyConstCondition-after-const-prop",
+ SimplifyConstCondition::Final => "SimplifyConstCondition-final",
+ }
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs
index be026402dd5..9d9c5d54038 100644
--- a/compiler/rustc_mir_transform/src/ssa.rs
+++ b/compiler/rustc_mir_transform/src/ssa.rs
@@ -21,7 +21,7 @@ pub struct SsaLocals {
/// We often encounter MIR bodies with 1 or 2 basic blocks. In those cases, it's unnecessary to
/// actually compute dominators, we can just compare block indices because bb0 is always the first
-/// block, and in any body all other blocks are always always dominated by bb0.
+/// block, and in any body all other blocks are always dominated by bb0.
struct SmallDominators {
inner: Option<Dominators<BasicBlock>>,
}
diff --git a/compiler/rustc_monomorphize/Cargo.toml b/compiler/rustc_monomorphize/Cargo.toml
index c8af10576b4..5ecd68c79bb 100644
--- a/compiler/rustc_monomorphize/Cargo.toml
+++ b/compiler/rustc_monomorphize/Cargo.toml
@@ -13,6 +13,7 @@ tracing = "0.1"
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_hir = { path = "../rustc_hir" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_index = { path = "../rustc_index" }
rustc_macros = { path = "../rustc_macros" }
rustc_middle = { path = "../rustc_middle" }
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 7bcff7e07fb..2ed628871d2 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -402,7 +402,7 @@ fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec<MonoItem<
}
/// Collect all monomorphized items reachable from `starting_point`, and emit a note diagnostic if a
-/// post-monorphization error is encountered during a collection step.
+/// post-monomorphization error is encountered during a collection step.
#[instrument(skip(tcx, visited, recursion_depths, recursion_limit, inlining_map), level = "debug")]
fn collect_items_rec<'tcx>(
tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs
index 5000fb71937..aea9f719027 100644
--- a/compiler/rustc_monomorphize/src/lib.rs
+++ b/compiler/rustc_monomorphize/src/lib.rs
@@ -10,8 +10,8 @@ extern crate tracing;
extern crate rustc_middle;
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
+use rustc_fluent_macro::fluent_messages;
use rustc_hir::lang_items::LangItem;
-use rustc_macros::fluent_messages;
use rustc_middle::traits;
use rustc_middle::ty::adjustment::CustomCoerceUnsized;
use rustc_middle::ty::query::{Providers, TyCtxtAt};
diff --git a/compiler/rustc_monomorphize/src/partitioning/default.rs b/compiler/rustc_monomorphize/src/partitioning/default.rs
index 482b78d42e3..bd24deb590a 100644
--- a/compiler/rustc_monomorphize/src/partitioning/default.rs
+++ b/compiler/rustc_monomorphize/src/partitioning/default.rs
@@ -16,17 +16,20 @@ use super::PartitioningCx;
use crate::collector::InliningMap;
use crate::partitioning::merging;
use crate::partitioning::{
- MonoItemPlacement, Partitioner, PostInliningPartitioning, PreInliningPartitioning,
+ MonoItemPlacement, Partition, PostInliningPartitioning, PreInliningPartitioning,
};
pub struct DefaultPartitioning;
-impl<'tcx> Partitioner<'tcx> for DefaultPartitioning {
- fn place_root_mono_items(
+impl<'tcx> Partition<'tcx> for DefaultPartitioning {
+ fn place_root_mono_items<I>(
&mut self,
cx: &PartitioningCx<'_, 'tcx>,
- mono_items: &mut dyn Iterator<Item = MonoItem<'tcx>>,
- ) -> PreInliningPartitioning<'tcx> {
+ mono_items: &mut I,
+ ) -> PreInliningPartitioning<'tcx>
+ where
+ I: Iterator<Item = MonoItem<'tcx>>,
+ {
let mut roots = FxHashSet::default();
let mut codegen_units = FxHashMap::default();
let is_incremental_build = cx.tcx.sess.opts.incremental.is_some();
@@ -89,7 +92,7 @@ impl<'tcx> Partitioner<'tcx> for DefaultPartitioning {
}
PreInliningPartitioning {
- codegen_units: codegen_units.into_values().map(|codegen_unit| codegen_unit).collect(),
+ codegen_units: codegen_units.into_values().collect(),
roots,
internalization_candidates,
}
@@ -267,7 +270,7 @@ fn characteristic_def_id_of_mono_item<'tcx>(
match mono_item {
MonoItem::Fn(instance) => {
let def_id = match instance.def {
- ty::InstanceDef::Item(def) => def.did,
+ ty::InstanceDef::Item(def) => def,
ty::InstanceDef::VTableShim(..)
| ty::InstanceDef::ReifyShim(..)
| ty::InstanceDef::FnPtrShim(..)
@@ -421,10 +424,9 @@ fn mono_item_visibility<'tcx>(
};
let def_id = match instance.def {
- InstanceDef::Item(def) => def.did,
- InstanceDef::DropGlue(def_id, Some(_)) => def_id,
+ InstanceDef::Item(def_id) | InstanceDef::DropGlue(def_id, Some(_)) => def_id,
- // We match the visiblity of statics here
+ // We match the visibility of statics here
InstanceDef::ThreadLocalShim(def_id) => {
return static_visibility(tcx, can_be_internalized, def_id);
}
diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs
index 18aa0742c09..993e35c7fd2 100644
--- a/compiler/rustc_monomorphize/src/partitioning/mod.rs
+++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs
@@ -118,18 +118,81 @@ use crate::errors::{
CouldntDumpMonoStats, SymbolAlreadyDefined, UnknownCguCollectionMode, UnknownPartitionStrategy,
};
+enum Partitioner {
+ Default(default::DefaultPartitioning),
+ // Other partitioning strategies can go here.
+ Unknown,
+}
+
+impl<'tcx> Partition<'tcx> for Partitioner {
+ fn place_root_mono_items<I>(
+ &mut self,
+ cx: &PartitioningCx<'_, 'tcx>,
+ mono_items: &mut I,
+ ) -> PreInliningPartitioning<'tcx>
+ where
+ I: Iterator<Item = MonoItem<'tcx>>,
+ {
+ match self {
+ Partitioner::Default(partitioner) => partitioner.place_root_mono_items(cx, mono_items),
+ Partitioner::Unknown => cx.tcx.sess.emit_fatal(UnknownPartitionStrategy),
+ }
+ }
+
+ fn merge_codegen_units(
+ &mut self,
+ cx: &PartitioningCx<'_, 'tcx>,
+ initial_partitioning: &mut PreInliningPartitioning<'tcx>,
+ ) {
+ match self {
+ Partitioner::Default(partitioner) => {
+ partitioner.merge_codegen_units(cx, initial_partitioning)
+ }
+ Partitioner::Unknown => cx.tcx.sess.emit_fatal(UnknownPartitionStrategy),
+ }
+ }
+
+ fn place_inlined_mono_items(
+ &mut self,
+ cx: &PartitioningCx<'_, 'tcx>,
+ initial_partitioning: PreInliningPartitioning<'tcx>,
+ ) -> PostInliningPartitioning<'tcx> {
+ match self {
+ Partitioner::Default(partitioner) => {
+ partitioner.place_inlined_mono_items(cx, initial_partitioning)
+ }
+ Partitioner::Unknown => cx.tcx.sess.emit_fatal(UnknownPartitionStrategy),
+ }
+ }
+
+ fn internalize_symbols(
+ &mut self,
+ cx: &PartitioningCx<'_, 'tcx>,
+ post_inlining_partitioning: &mut PostInliningPartitioning<'tcx>,
+ ) {
+ match self {
+ Partitioner::Default(partitioner) => {
+ partitioner.internalize_symbols(cx, post_inlining_partitioning)
+ }
+ Partitioner::Unknown => cx.tcx.sess.emit_fatal(UnknownPartitionStrategy),
+ }
+ }
+}
+
pub struct PartitioningCx<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
target_cgu_count: usize,
inlining_map: &'a InliningMap<'tcx>,
}
-trait Partitioner<'tcx> {
- fn place_root_mono_items(
+trait Partition<'tcx> {
+ fn place_root_mono_items<I>(
&mut self,
cx: &PartitioningCx<'_, 'tcx>,
- mono_items: &mut dyn Iterator<Item = MonoItem<'tcx>>,
- ) -> PreInliningPartitioning<'tcx>;
+ mono_items: &mut I,
+ ) -> PreInliningPartitioning<'tcx>
+ where
+ I: Iterator<Item = MonoItem<'tcx>>;
fn merge_codegen_units(
&mut self,
@@ -150,26 +213,27 @@ trait Partitioner<'tcx> {
);
}
-fn get_partitioner<'tcx>(tcx: TyCtxt<'tcx>) -> Box<dyn Partitioner<'tcx>> {
+fn get_partitioner(tcx: TyCtxt<'_>) -> Partitioner {
let strategy = match &tcx.sess.opts.unstable_opts.cgu_partitioning_strategy {
None => "default",
Some(s) => &s[..],
};
match strategy {
- "default" => Box::new(default::DefaultPartitioning),
- _ => {
- tcx.sess.emit_fatal(UnknownPartitionStrategy);
- }
+ "default" => Partitioner::Default(default::DefaultPartitioning),
+ _ => Partitioner::Unknown,
}
}
-pub fn partition<'tcx>(
+pub fn partition<'tcx, I>(
tcx: TyCtxt<'tcx>,
- mono_items: &mut dyn Iterator<Item = MonoItem<'tcx>>,
+ mono_items: &mut I,
max_cgu_count: usize,
inlining_map: &InliningMap<'tcx>,
-) -> Vec<CodegenUnit<'tcx>> {
+) -> Vec<CodegenUnit<'tcx>>
+where
+ I: Iterator<Item = MonoItem<'tcx>>,
+{
let _prof_timer = tcx.prof.generic_activity("cgu_partitioning");
let mut partitioner = get_partitioner(tcx);
@@ -182,7 +246,9 @@ pub fn partition<'tcx>(
partitioner.place_root_mono_items(cx, mono_items)
};
- initial_partitioning.codegen_units.iter_mut().for_each(|cgu| cgu.create_size_estimate(tcx));
+ for cgu in &mut initial_partitioning.codegen_units {
+ cgu.create_size_estimate(tcx);
+ }
debug_dump(tcx, "INITIAL PARTITIONING:", initial_partitioning.codegen_units.iter());
@@ -202,7 +268,9 @@ pub fn partition<'tcx>(
partitioner.place_inlined_mono_items(cx, initial_partitioning)
};
- post_inlining.codegen_units.iter_mut().for_each(|cgu| cgu.create_size_estimate(tcx));
+ for cgu in &mut post_inlining.codegen_units {
+ cgu.create_size_estimate(tcx);
+ }
debug_dump(tcx, "POST INLINING:", post_inlining.codegen_units.iter());
@@ -380,7 +448,7 @@ fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> (&DefIdSet, &[Co
|| {
let mut codegen_units = partition(
tcx,
- &mut items.iter().cloned(),
+ &mut items.iter().copied(),
tcx.sess.codegen_units(),
&inlining_map,
);
diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs
index 63263a642ac..ddc62d9c390 100644
--- a/compiler/rustc_monomorphize/src/polymorphize.rs
+++ b/compiler/rustc_monomorphize/src/polymorphize.rs
@@ -232,7 +232,7 @@ impl<'a, 'tcx> MarkUsedGenericParams<'a, 'tcx> {
/// a closure, generator or constant).
#[instrument(level = "debug", skip(self, def_id, substs))]
fn visit_child_body(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) {
- let instance = ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id));
+ let instance = ty::InstanceDef::Item(def_id);
let unused = self.tcx.unused_generic_params(instance);
debug!(?self.unused_parameters, ?unused);
for (i, arg) in substs.iter().enumerate() {
@@ -272,10 +272,10 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
// Avoid considering `T` unused when constants are of the form:
// `<Self as Foo<T>>::foo::promoted[p]`
if let Some(p) = promoted {
- if self.def_id == def.did && !self.tcx.generics_of(def.did).has_self {
+ if self.def_id == def && !self.tcx.generics_of(def).has_self {
// If there is a promoted, don't look at the substs - since it will always contain
// the generic parameters, instead, traverse the promoted MIR.
- let promoted = self.tcx.promoted_mir(def.did);
+ let promoted = self.tcx.promoted_mir(def);
self.visit_body(&promoted[p]);
}
}
@@ -305,9 +305,9 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for MarkUsedGenericParams<'a, 'tcx> {
ControlFlow::Continue(())
}
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs })
- if matches!(self.tcx.def_kind(def.did), DefKind::AnonConst) =>
+ if matches!(self.tcx.def_kind(def), DefKind::AnonConst) =>
{
- self.visit_child_body(def.did, substs);
+ self.visit_child_body(def, substs);
ControlFlow::Continue(())
}
_ => c.super_visit_with(self),
diff --git a/compiler/rustc_parse/Cargo.toml b/compiler/rustc_parse/Cargo.toml
index 3eb158c817c..1bd9f66290d 100644
--- a/compiler/rustc_parse/Cargo.toml
+++ b/compiler/rustc_parse/Cargo.toml
@@ -12,6 +12,7 @@ rustc_ast_pretty = { path = "../rustc_ast_pretty" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_feature = { path = "../rustc_feature" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_lexer = { path = "../rustc_lexer" }
rustc_macros = { path = "../rustc_macros" }
rustc_session = { path = "../rustc_session" }
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index 9e856c9f212..ad9b20f9c76 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -67,7 +67,7 @@ pub(crate) fn parse_token_trees<'a>(
match token_trees {
Ok(stream) if unmatched_delims.is_empty() => Ok(stream),
_ => {
- // Return error if there are unmatched delimiters or unclosng delimiters.
+ // Return error if there are unmatched delimiters or unclosed delimiters.
// We emit delimiter mismatch errors first, then emit the unclosing delimiter mismatch
// because the delimiter mismatch is more likely to be the root cause of error
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index 17466cd0e6d..507f6e4182e 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -20,7 +20,7 @@ use rustc_ast_pretty::pprust;
use rustc_data_structures::sync::Lrc;
use rustc_errors::{Applicability, Diagnostic, FatalError, Level, PResult};
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
-use rustc_macros::fluent_messages;
+use rustc_fluent_macro::fluent_messages;
use rustc_session::parse::ParseSess;
use rustc_span::{FileName, SourceFile, Span};
diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs
index e3e7c63e344..e1db19557cf 100644
--- a/compiler/rustc_parse/src/parser/attr.rs
+++ b/compiler/rustc_parse/src/parser/attr.rs
@@ -45,10 +45,10 @@ impl<'a> Parser<'a> {
Some(InnerAttrForbiddenReason::AfterOuterDocComment {
prev_doc_comment_span: prev_outer_attr_sp.unwrap(),
})
- } else if let Some(prev_outer_attr_sp) = prev_outer_attr_sp {
- Some(InnerAttrForbiddenReason::AfterOuterAttribute { prev_outer_attr_sp })
} else {
- None
+ prev_outer_attr_sp.map(|prev_outer_attr_sp| {
+ InnerAttrForbiddenReason::AfterOuterAttribute { prev_outer_attr_sp }
+ })
};
let inner_parse_policy = InnerAttrPolicy::Forbidden(inner_error_reason);
just_parsed_doc_comment = false;
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index e03ce5d7120..c14c7f2fa0d 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -570,15 +570,13 @@ impl<'a> Parser<'a> {
let expect = tokens_to_string(&expected);
let actual = super::token_descr(&self.token);
let (msg_exp, (label_sp, label_exp)) = if expected.len() > 1 {
+ let fmt = format!("expected one of {expect}, found {actual}");
let short_expect = if expected.len() > 6 {
format!("{} possible tokens", expected.len())
} else {
- expect.clone()
+ expect
};
- (
- format!("expected one of {expect}, found {actual}"),
- (self.prev_token.span.shrink_to_hi(), format!("expected one of {short_expect}")),
- )
+ (fmt, (self.prev_token.span.shrink_to_hi(), format!("expected one of {short_expect}")))
} else if expected.is_empty() {
(
format!("unexpected token: {actual}"),
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 6422b8ac1ba..f5fef6ad019 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -2577,14 +2577,12 @@ impl<'a> Parser<'a> {
}
fn recover_self_param(&mut self) -> bool {
- match self
- .parse_outer_attributes()
- .and_then(|_| self.parse_self_param())
- .map_err(|e| e.cancel())
- {
- Ok(Some(_)) => true,
- _ => false,
- }
+ matches!(
+ self.parse_outer_attributes()
+ .and_then(|_| self.parse_self_param())
+ .map_err(|e| e.cancel()),
+ Ok(Some(_))
+ )
}
}
diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs
index 7a4d53ed8bb..adb0d372a40 100644
--- a/compiler/rustc_parse/src/parser/nonterminal.rs
+++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -20,12 +20,10 @@ impl<'a> Parser<'a> {
pub fn nonterminal_may_begin_with(kind: NonterminalKind, token: &Token) -> bool {
/// Checks whether the non-terminal may contain a single (non-keyword) identifier.
fn may_be_ident(nt: &token::Nonterminal) -> bool {
- match *nt {
- token::NtItem(_) | token::NtBlock(_) | token::NtVis(_) | token::NtLifetime(_) => {
- false
- }
- _ => true,
- }
+ !matches!(
+ *nt,
+ token::NtItem(_) | token::NtBlock(_) | token::NtVis(_) | token::NtLifetime(_)
+ )
}
match kind {
diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs
index 72402a20090..2f397e303e5 100644
--- a/compiler/rustc_parse/src/validate_attr.rs
+++ b/compiler/rustc_parse/src/validate_attr.rs
@@ -68,7 +68,7 @@ pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Meta
}
} else {
// The non-error case can happen with e.g. `#[foo = 1+1]`. The error case can
- // happen with e.g. `#[foo = include_str!("non-existent-file.rs")]`; in that
+ // happen with e.g. `#[foo = include_str!("nonexistent-file.rs")]`; in that
// case we delay the error because an earlier error will have already been
// reported.
let msg = format!("unexpected expression: `{}`", pprust::expr_to_string(expr));
diff --git a/compiler/rustc_passes/Cargo.toml b/compiler/rustc_passes/Cargo.toml
index 44f991f8c15..0413b5b4fb9 100644
--- a/compiler/rustc_passes/Cargo.toml
+++ b/compiler/rustc_passes/Cargo.toml
@@ -12,6 +12,7 @@ rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_expand = { path = "../rustc_expand" }
rustc_hir = { path = "../rustc_hir" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_index = { path = "../rustc_index" }
rustc_session = { path = "../rustc_session" }
rustc_target = { path = "../rustc_target" }
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index b354dca7cc4..055682a1509 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -627,9 +627,9 @@ passes_attr_application_struct_enum_union =
attribute should be applied to a struct, enum, or union
.label = not a struct, enum, or union
-passes_attr_application_struct_enum_function_union =
- attribute should be applied to a struct, enum, function, or union
- .label = not a struct, enum, function, or union
+passes_attr_application_struct_enum_function_method_union =
+ attribute should be applied to a struct, enum, function, associated function, or union
+ .label = not a struct, enum, function, associated function, or union
passes_transparent_incompatible =
transparent {$target} cannot have other repr hints
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 80a93da2b45..085a28626ea 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -1728,7 +1728,9 @@ impl CheckAttrVisitor<'_> {
}
}
sym::align => {
- if let (Target::Fn, false) = (target, self.tcx.features().fn_align) {
+ if let (Target::Fn | Target::Method(MethodKind::Inherent), false) =
+ (target, self.tcx.features().fn_align)
+ {
feature_err(
&self.tcx.sess.parse_sess,
sym::fn_align,
@@ -1739,10 +1741,14 @@ impl CheckAttrVisitor<'_> {
}
match target {
- Target::Struct | Target::Union | Target::Enum | Target::Fn => continue,
+ Target::Struct
+ | Target::Union
+ | Target::Enum
+ | Target::Fn
+ | Target::Method(_) => continue,
_ => {
self.tcx.sess.emit_err(
- errors::AttrApplication::StructEnumFunctionUnion {
+ errors::AttrApplication::StructEnumFunctionMethodUnion {
hint_span: hint.span(),
span,
},
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 5cfe691df17..3ae5b45d330 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -237,6 +237,37 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
}
}
+ fn handle_offset_of(&mut self, expr: &'tcx hir::Expr<'tcx>) {
+ let data = self.typeck_results().offset_of_data();
+ let &(container, ref indices) =
+ data.get(expr.hir_id).expect("no offset_of_data for offset_of");
+
+ let body_did = self.typeck_results().hir_owner.to_def_id();
+ let param_env = self.tcx.param_env(body_did);
+
+ let mut current_ty = container;
+
+ for &index in indices {
+ match current_ty.kind() {
+ ty::Adt(def, subst) => {
+ let field = &def.non_enum_variant().fields[index];
+
+ self.insert_def_id(field.did);
+ let field_ty = field.ty(self.tcx, subst);
+
+ current_ty = self.tcx.normalize_erasing_regions(param_env, field_ty);
+ }
+ // we don't need to mark tuple fields as live,
+ // but we may need to mark subfields
+ ty::Tuple(tys) => {
+ current_ty =
+ self.tcx.normalize_erasing_regions(param_env, tys[index.as_usize()]);
+ }
+ _ => span_bug!(expr.span, "named field access on non-ADT"),
+ }
+ }
+ }
+
fn mark_live_symbols(&mut self) {
let mut scanned = LocalDefIdSet::default();
while let Some(id) = self.worklist.pop() {
@@ -405,6 +436,9 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
hir::ExprKind::Closure(cls) => {
self.insert_def_id(cls.def_id.to_def_id());
}
+ hir::ExprKind::OffsetOf(..) => {
+ self.handle_offset_of(expr);
+ }
_ => (),
}
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 139ba8c9677..e8603b3a2f1 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -1355,8 +1355,8 @@ pub enum AttrApplication {
#[label]
span: Span,
},
- #[diag(passes_attr_application_struct_enum_function_union, code = "E0517")]
- StructEnumFunctionUnion {
+ #[diag(passes_attr_application_struct_enum_function_method_union, code = "E0517")]
+ StructEnumFunctionMethodUnion {
#[primary_span]
hint_span: Span,
#[label]
diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs
index 47e032758f2..dc5e454074d 100644
--- a/compiler/rustc_passes/src/hir_stats.rs
+++ b/compiler/rustc_passes/src/hir_stats.rs
@@ -302,7 +302,8 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
[
ConstBlock, Array, Call, MethodCall, Tup, Binary, Unary, Lit, Cast, Type,
DropTemps, Let, If, Loop, Match, Closure, Block, Assign, AssignOp, Field, Index,
- Path, AddrOf, Break, Continue, Ret, InlineAsm, Struct, Repeat, Yield, Err
+ Path, AddrOf, Break, Continue, Ret, InlineAsm, OffsetOf, Struct, Repeat, Yield,
+ Err
]
);
hir_visit::walk_expr(self, e)
@@ -568,7 +569,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
Array, ConstBlock, Call, MethodCall, Tup, Binary, Unary, Lit, Cast, Type, Let,
If, While, ForLoop, Loop, Match, Closure, Block, Async, Await, TryBlock, Assign,
AssignOp, Field, Index, Range, Underscore, Path, AddrOf, Break, Continue, Ret,
- InlineAsm, FormatArgs, MacCall, Struct, Repeat, Paren, Try, Yield, Yeet, IncludedBytes, Err
+ InlineAsm, FormatArgs, OffsetOf, MacCall, Struct, Repeat, Paren, Try, Yield, Yeet, IncludedBytes, Err
]
);
ast_visit::walk_expr(self, e)
diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs
index b7e07aff42b..eca3bae9a1c 100644
--- a/compiler/rustc_passes/src/lib.rs
+++ b/compiler/rustc_passes/src/lib.rs
@@ -19,7 +19,7 @@ extern crate rustc_middle;
extern crate tracing;
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
-use rustc_macros::fluent_messages;
+use rustc_fluent_macro::fluent_messages;
use rustc_middle::ty::query::Providers;
mod check_attr;
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index a8471ce3b6f..b39a8c5598f 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -473,6 +473,7 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
| hir::ExprKind::Struct(..)
| hir::ExprKind::Repeat(..)
| hir::ExprKind::InlineAsm(..)
+ | hir::ExprKind::OffsetOf(..)
| hir::ExprKind::Type(..)
| hir::ExprKind::Err(_)
| hir::ExprKind::Path(hir::QPath::TypeRelative(..))
@@ -1129,7 +1130,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
| hir::ExprKind::ConstBlock(..)
| hir::ExprKind::Err(_)
| hir::ExprKind::Path(hir::QPath::TypeRelative(..))
- | hir::ExprKind::Path(hir::QPath::LangItem(..)) => succ,
+ | hir::ExprKind::Path(hir::QPath::LangItem(..))
+ | hir::ExprKind::OffsetOf(..) => succ,
// Note that labels have been resolved, so we don't need to look
// at the label ident
@@ -1418,6 +1420,7 @@ fn check_expr<'tcx>(this: &mut Liveness<'_, 'tcx>, expr: &'tcx Expr<'tcx>) {
| hir::ExprKind::ConstBlock(..)
| hir::ExprKind::Block(..)
| hir::ExprKind::AddrOf(..)
+ | hir::ExprKind::OffsetOf(..)
| hir::ExprKind::Struct(..)
| hir::ExprKind::Repeat(..)
| hir::ExprKind::Closure { .. }
diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs
index c398467f03e..cf8d9300a11 100644
--- a/compiler/rustc_passes/src/naked_functions.rs
+++ b/compiler/rustc_passes/src/naked_functions.rs
@@ -203,6 +203,7 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
| ExprKind::Break(..)
| ExprKind::Continue(..)
| ExprKind::Ret(..)
+ | ExprKind::OffsetOf(..)
| ExprKind::Struct(..)
| ExprKind::Repeat(..)
| ExprKind::Yield(..) => {
diff --git a/compiler/rustc_plugin_impl/Cargo.toml b/compiler/rustc_plugin_impl/Cargo.toml
index fa27bfc61d1..c930b3365fd 100644
--- a/compiler/rustc_plugin_impl/Cargo.toml
+++ b/compiler/rustc_plugin_impl/Cargo.toml
@@ -12,6 +12,7 @@ rustc_errors = { path = "../rustc_errors" }
rustc_lint = { path = "../rustc_lint" }
rustc_macros = { path = "../rustc_macros" }
rustc_metadata = { path = "../rustc_metadata" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_ast = { path = "../rustc_ast" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
diff --git a/compiler/rustc_plugin_impl/src/lib.rs b/compiler/rustc_plugin_impl/src/lib.rs
index 672189e22cf..faa7495ef9f 100644
--- a/compiler/rustc_plugin_impl/src/lib.rs
+++ b/compiler/rustc_plugin_impl/src/lib.rs
@@ -12,8 +12,8 @@
#![deny(rustc::diagnostic_outside_of_impl)]
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
+use rustc_fluent_macro::fluent_messages;
use rustc_lint::LintStore;
-use rustc_macros::fluent_messages;
mod errors;
pub mod load;
diff --git a/compiler/rustc_privacy/Cargo.toml b/compiler/rustc_privacy/Cargo.toml
index 744cb77dd00..08c4067705c 100644
--- a/compiler/rustc_privacy/Cargo.toml
+++ b/compiler/rustc_privacy/Cargo.toml
@@ -9,6 +9,7 @@ rustc_attr = { path = "../rustc_attr" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_hir = { path = "../rustc_hir" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_macros = { path = "../rustc_macros" }
rustc_middle = { path = "../rustc_middle" }
rustc_session = { path = "../rustc_session" }
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index dcebfca08fa..9567329192d 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -17,12 +17,12 @@ use rustc_attr as attr;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::intern::Interned;
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
+use rustc_fluent_macro::fluent_messages;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{AssocItemKind, HirIdSet, ItemId, Node, PatKind};
-use rustc_macros::fluent_messages;
use rustc_middle::bug;
use rustc_middle::hir::nested_filter;
use rustc_middle::middle::privacy::{EffectiveVisibilities, Level};
diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs
index 30477c7bd44..c05323c2d6c 100644
--- a/compiler/rustc_query_impl/src/on_disk_cache.rs
+++ b/compiler/rustc_query_impl/src/on_disk_cache.rs
@@ -1,6 +1,7 @@
use crate::QueryCtxt;
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
use rustc_data_structures::memmap::Mmap;
+use rustc_data_structures::stable_hasher::Hash64;
use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, RwLock};
use rustc_data_structures::unhash::UnhashMap;
use rustc_data_structures::unord::UnordSet;
@@ -138,7 +139,7 @@ impl AbsoluteBytePos {
/// is the only thing available when decoding the cache's [Footer].
#[derive(Encodable, Decodable, Clone, Debug)]
struct EncodedSourceFileId {
- file_name_hash: u64,
+ file_name_hash: Hash64,
stable_crate_id: StableCrateId,
}
@@ -299,7 +300,7 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> {
interpret_alloc_index.reserve(new_n - n);
for idx in n..new_n {
let id = encoder.interpret_allocs[idx];
- let pos = encoder.position() as u32;
+ let pos: u32 = encoder.position().try_into().unwrap();
interpret_alloc_index.push(pos);
interpret::specialized_encode_alloc_id(&mut encoder, tcx, id);
}
@@ -667,7 +668,7 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for ExpnId {
#[cfg(debug_assertions)]
{
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
- let local_hash: u64 = decoder.tcx.with_stable_hashing_context(|mut hcx| {
+ let local_hash = decoder.tcx.with_stable_hashing_context(|mut hcx| {
let mut hasher = StableHasher::new();
expn_id.expn_data().hash_stable(&mut hcx, &mut hasher);
hasher.finish()
@@ -744,7 +745,7 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Symbol {
let pos = d.read_usize();
let old_pos = d.opaque.position();
- // move to str ofset and read
+ // move to str offset and read
d.opaque.set_position(pos);
let s = d.read_str();
let sym = Symbol::intern(s);
@@ -806,7 +807,9 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx UnordSet<LocalDefId>
}
}
-impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx FxHashMap<DefId, Ty<'tcx>> {
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>>
+ for &'tcx FxHashMap<DefId, ty::EarlyBinder<Ty<'tcx>>>
+{
fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
RefDecodable::decode(d)
}
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index afbead7d1ae..32222df25d4 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -5,7 +5,7 @@
use crate::on_disk_cache::{CacheDecoder, CacheEncoder, EncodedDepNodeIndex};
use crate::profiling_support::QueryKeyStringCache;
use crate::{on_disk_cache, Queries};
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
use rustc_data_structures::sync::{AtomicU64, Lock};
use rustc_errors::{Diagnostic, Handler};
use rustc_middle::dep_graph::{
@@ -342,7 +342,7 @@ pub(crate) fn create_query_frame<
let mut hasher = StableHasher::new();
std::mem::discriminant(&kind).hash_stable(&mut hcx, &mut hasher);
key.hash_stable(&mut hcx, &mut hasher);
- hasher.finish::<u64>()
+ hasher.finish::<Hash64>()
})
};
let ty_adt_id = key.ty_adt_id();
diff --git a/compiler/rustc_query_impl/src/profiling_support.rs b/compiler/rustc_query_impl/src/profiling_support.rs
index 4743170e9bf..08b588a8c94 100644
--- a/compiler/rustc_query_impl/src/profiling_support.rs
+++ b/compiler/rustc_query_impl/src/profiling_support.rs
@@ -4,7 +4,7 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::profiling::SelfProfiler;
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, LOCAL_CRATE};
use rustc_hir::definitions::DefPathData;
-use rustc_middle::ty::{TyCtxt, WithOptConstParam};
+use rustc_middle::ty::TyCtxt;
use rustc_query_system::query::QueryCache;
use std::fmt::Debug;
use std::io::Write;
@@ -151,37 +151,6 @@ impl SpecIntoSelfProfilingString for LocalDefId {
}
}
-impl<T: SpecIntoSelfProfilingString> SpecIntoSelfProfilingString for WithOptConstParam<T> {
- fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId {
- // We print `WithOptConstParam` values as tuples to make them shorter
- // and more readable, without losing information:
- //
- // "WithOptConstParam { did: foo::bar, const_param_did: Some(foo::baz) }"
- // becomes "(foo::bar, foo::baz)" and
- // "WithOptConstParam { did: foo::bar, const_param_did: None }"
- // becomes "(foo::bar, _)".
-
- let did = StringComponent::Ref(self.did.to_self_profile_string(builder));
-
- let const_param_did = if let Some(const_param_did) = self.const_param_did {
- let const_param_did = builder.def_id_to_string_id(const_param_did);
- StringComponent::Ref(const_param_did)
- } else {
- StringComponent::Value("_")
- };
-
- let components = [
- StringComponent::Value("("),
- did,
- StringComponent::Value(", "),
- const_param_did,
- StringComponent::Value(")"),
- ];
-
- builder.profiler.alloc_string(&components[..])
- }
-}
-
impl<T0, T1> SpecIntoSelfProfilingString for (T0, T1)
where
T0: SpecIntoSelfProfilingString,
@@ -231,7 +200,7 @@ pub(crate) fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>(
// locked while doing so. Instead we copy out the
// `(query_key, dep_node_index)` pairs and release the lock again.
let mut query_keys_and_indices = Vec::new();
- query_cache.iter(&mut |k, _, i| query_keys_and_indices.push((k.clone(), i)));
+ query_cache.iter(&mut |k, _, i| query_keys_and_indices.push((*k, i)));
// Now actually allocate the strings. If allocating the strings
// generates new entries in the query cache, we'll miss them but
diff --git a/compiler/rustc_query_system/Cargo.toml b/compiler/rustc_query_system/Cargo.toml
index 12b4a114313..34e57637976 100644
--- a/compiler/rustc_query_system/Cargo.toml
+++ b/compiler/rustc_query_system/Cargo.toml
@@ -12,6 +12,7 @@ rustc_ast = { path = "../rustc_ast" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_feature = { path = "../rustc_feature" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_hir = { path = "../rustc_hir" }
rustc_index = { path = "../rustc_index" }
rustc_macros = { path = "../rustc_macros" }
diff --git a/compiler/rustc_query_system/messages.ftl b/compiler/rustc_query_system/messages.ftl
index 870e824039c..0d01123ad88 100644
--- a/compiler/rustc_query_system/messages.ftl
+++ b/compiler/rustc_query_system/messages.ftl
@@ -1,4 +1,4 @@
-query_system_reentrant = internal compiler error: re-entrant incremental verify failure, suppressing message
+query_system_reentrant = internal compiler error: reentrant incremental verify failure, suppressing message
query_system_increment_compilation = internal compiler error: encountered incremental compilation error with {$dep_node}
.help = This is a known issue with the compiler. Run {$run_cmd} to allow your project to compile
diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs
index a9a2e6dd04c..fd9e685ab80 100644
--- a/compiler/rustc_query_system/src/dep_graph/graph.rs
+++ b/compiler/rustc_query_system/src/dep_graph/graph.rs
@@ -249,7 +249,7 @@ impl<K: DepKind> DepGraph<K> {
/// get an ICE. Normally, we would have tried (and failed) to mark
/// some other query green (e.g. `item_children`) which was used
/// to obtain `C`, which would prevent us from ever trying to force
- /// a non-existent `D`.
+ /// a nonexistent `D`.
///
/// It might be possible to enforce that all `DepNode`s read during
/// deserialization already exist in the previous `DepGraph`. In
diff --git a/compiler/rustc_query_system/src/dep_graph/query.rs b/compiler/rustc_query_system/src/dep_graph/query.rs
index 27b3b5e1366..9dcc41e2726 100644
--- a/compiler/rustc_query_system/src/dep_graph/query.rs
+++ b/compiler/rustc_query_system/src/dep_graph/query.rs
@@ -24,10 +24,7 @@ impl<K: DepKind> DepGraphQuery<K> {
pub fn push(&mut self, index: DepNodeIndex, node: DepNode<K>, edges: &[DepNodeIndex]) {
let source = self.graph.add_node(node);
- if index.index() >= self.dep_index_to_index.len() {
- self.dep_index_to_index.resize(index.index() + 1, None);
- }
- self.dep_index_to_index[index] = Some(source);
+ self.dep_index_to_index.insert(index, source);
self.indices.insert(node, source);
for &target in edges.iter() {
diff --git a/compiler/rustc_query_system/src/ich/impls_syntax.rs b/compiler/rustc_query_system/src/ich/impls_syntax.rs
index 0bc811eb044..8865ecf3e05 100644
--- a/compiler/rustc_query_system/src/ich/impls_syntax.rs
+++ b/compiler/rustc_query_system/src/ich/impls_syntax.rs
@@ -75,7 +75,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for SourceFile {
ref normalized_pos,
} = *self;
- (name_hash as u64).hash_stable(hcx, hasher);
+ name_hash.hash_stable(hcx, hasher);
src_hash.hash_stable(hcx, hasher);
diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs
index bb812b006e9..8c9e9cfad60 100644
--- a/compiler/rustc_query_system/src/lib.rs
+++ b/compiler/rustc_query_system/src/lib.rs
@@ -16,7 +16,7 @@ extern crate rustc_data_structures;
extern crate rustc_macros;
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
-use rustc_macros::fluent_messages;
+use rustc_fluent_macro::fluent_messages;
pub mod cache;
pub mod dep_graph;
diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs
index c8d77938510..bb9ea50a1ea 100644
--- a/compiler/rustc_query_system/src/query/config.rs
+++ b/compiler/rustc_query_system/src/query/config.rs
@@ -63,7 +63,7 @@ pub trait QueryConfig<Qcx: QueryContext>: Copy {
fn handle_cycle_error(self) -> HandleCycleError;
fn hash_result(self) -> HashResult<Self::Value>;
- // Just here for convernience and checking that the key matches the kind, don't override this.
+ // Just here for convenience and checking that the key matches the kind, don't override this.
fn construct_dep_node(self, tcx: Qcx::DepContext, key: &Self::Key) -> DepNode<Qcx::DepKind> {
DepNode::construct(tcx, self.dep_kind(), key)
}
diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs
index 312b0e1688d..fa1f51b04da 100644
--- a/compiler/rustc_query_system/src/query/mod.rs
+++ b/compiler/rustc_query_system/src/query/mod.rs
@@ -16,6 +16,7 @@ pub use self::config::{HashResult, QueryConfig, TryLoadFromDisk};
use crate::dep_graph::DepKind;
use crate::dep_graph::{DepNodeIndex, HasDepContext, SerializedDepNodeIndex};
+use rustc_data_structures::stable_hasher::Hash64;
use rustc_data_structures::sync::Lock;
use rustc_errors::Diagnostic;
use rustc_hir::def::DefKind;
@@ -37,7 +38,7 @@ pub struct QueryStackFrame<D: DepKind> {
/// This hash is used to deterministically pick
/// a query to remove cycles in the parallel compiler.
#[cfg(parallel_compiler)]
- hash: u64,
+ hash: Hash64,
}
impl<D: DepKind> QueryStackFrame<D> {
@@ -49,7 +50,7 @@ impl<D: DepKind> QueryStackFrame<D> {
def_kind: Option<DefKind>,
dep_kind: D,
ty_adt_id: Option<DefId>,
- _hash: impl FnOnce() -> u64,
+ _hash: impl FnOnce() -> Hash64,
) -> Self {
Self {
description,
diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs
index 20310483d7e..bce01debc53 100644
--- a/compiler/rustc_query_system/src/query/plumbing.rs
+++ b/compiler/rustc_query_system/src/query/plumbing.rs
@@ -410,9 +410,28 @@ where
// as its feeding query had. So if the fed query is red, so is its feeder, which will
// get evaluated first, and re-feed the query.
if let Some((cached_result, _)) = cache.lookup(&key) {
- panic!(
- "fed query later has its value computed. The already cached value: {}",
- (query.format_value())(&cached_result)
+ let Some(hasher) = query.hash_result() else {
+ panic!(
+ "no_hash fed query later has its value computed.\n\
+ Remove `no_hash` modifier to allow recomputation.\n\
+ The already cached value: {}",
+ (query.format_value())(&cached_result)
+ );
+ };
+
+ let (old_hash, new_hash) = qcx.dep_context().with_stable_hashing_context(|mut hcx| {
+ (hasher(&mut hcx, &cached_result), hasher(&mut hcx, &result))
+ });
+ let formatter = query.format_value();
+ debug_assert_eq!(
+ old_hash,
+ new_hash,
+ "Computed query value for {:?}({:?}) is inconsistent with fed value,\n\
+ computed={:#?}\nfed={:#?}",
+ query.dep_kind(),
+ key,
+ formatter(&result),
+ formatter(&cached_result),
);
}
}
@@ -573,7 +592,7 @@ where
// from disk. Re-hashing results is fairly expensive, so we can't
// currently afford to verify every hash. This subset should still
// give us some coverage of potential bugs though.
- let try_verify = prev_fingerprint.as_value().1 % 32 == 0;
+ let try_verify = prev_fingerprint.split().1.as_u64() % 32 == 0;
if std::intrinsics::unlikely(
try_verify || qcx.dep_context().sess().opts.unstable_opts.incremental_verify_ich,
) {
@@ -691,7 +710,7 @@ fn incremental_verify_ich_failed<Tcx>(
// which may result in another fingerprint mismatch while we're in the middle
// of processing this one. To avoid a double-panic (which kills the process
// before we can print out the query static), we print out a terse
- // but 'safe' message if we detect a re-entrant call to this method.
+ // but 'safe' message if we detect a reentrant call to this method.
thread_local! {
static INSIDE_VERIFY_PANIC: Cell<bool> = const { Cell::new(false) };
};
diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml
index 5c4ec44d2b8..1c16d85f1b9 100644
--- a/compiler/rustc_resolve/Cargo.toml
+++ b/compiler/rustc_resolve/Cargo.toml
@@ -16,6 +16,7 @@ rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_expand = { path = "../rustc_expand" }
rustc_feature = { path = "../rustc_feature" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_hir = { path = "../rustc_hir" }
rustc_index = { path = "../rustc_index" }
rustc_macros = { path = "../rustc_macros" }
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index ff0f1f55975..967c9e22fb2 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -197,10 +197,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
pub(crate) fn build_reduced_graph_external(&mut self, module: Module<'a>) {
- // Query `module_children` is not used because hashing spans in its result is expensive.
- let children =
- Vec::from_iter(self.cstore().module_children_untracked(module.def_id(), self.tcx.sess));
- for child in children {
+ for child in self.tcx.module_children(module.def_id()) {
let parent_scope = ParentScope::module(module, self);
BuildReducedGraphVisitor { r: self, parent_scope }
.build_reduced_graph_for_external_crate_res(child);
@@ -929,9 +926,15 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
}
/// Builds the reduced graph for a single item in an external crate.
- fn build_reduced_graph_for_external_crate_res(&mut self, child: ModChild) {
+ fn build_reduced_graph_for_external_crate_res(&mut self, child: &ModChild) {
let parent = self.parent_scope.module;
- let ModChild { ident, res, vis, span, .. } = child;
+ let ModChild { ident, res, vis, ref reexport_chain } = *child;
+ let span = self.r.def_span(
+ reexport_chain
+ .first()
+ .and_then(|reexport| reexport.id())
+ .unwrap_or_else(|| res.def_id()),
+ );
let res = res.expect_non_local();
let expansion = self.parent_scope.expansion;
// Record primary definitions.
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 0c9d306081e..4b7048eac04 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -663,15 +663,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
Ident::with_dummy_span(name),
Namespace::ValueNS,
&parent_scope,
- &|res: Res| match res {
- Res::Def(
- DefKind::Ctor(CtorOf::Variant, CtorKind::Const)
- | DefKind::Ctor(CtorOf::Struct, CtorKind::Const)
- | DefKind::Const
- | DefKind::AssocConst,
- _,
- ) => true,
- _ => false,
+ &|res: Res| {
+ matches!(
+ res,
+ Res::Def(
+ DefKind::Ctor(CtorOf::Variant, CtorKind::Const)
+ | DefKind::Ctor(CtorOf::Struct, CtorKind::Const)
+ | DefKind::Const
+ | DefKind::AssocConst,
+ _,
+ )
+ )
},
);
@@ -1867,15 +1869,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
Some(LexicalScopeBinding::Item(name_binding)) => Some(name_binding.span),
_ => None,
};
- let suggestion = if let Some(span) = match_span {
- Some((
+ let suggestion = match_span.map(|span| {
+ (
vec![(span, String::from(""))],
format!("`{}` is defined here, but is not a type", ident),
Applicability::MaybeIncorrect,
- ))
- } else {
- None
- };
+ )
+ });
(format!("use of undeclared type `{}`", ident), suggestion)
} else {
diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs
index bed579f6b92..87067189a77 100644
--- a/compiler/rustc_resolve/src/effective_visibilities.rs
+++ b/compiler/rustc_resolve/src/effective_visibilities.rs
@@ -175,7 +175,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> {
/// to not update anything and we can skip it.
///
/// We are checking this condition only if the correct value of private visibility is
- /// cheaply available, otherwise it does't make sense performance-wise.
+ /// cheaply available, otherwise it doesn't make sense performance-wise.
///
/// `None` is returned if the update can be skipped,
/// and cheap private visibility is returned otherwise.
diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs
index afa796cb645..af0ec236df0 100644
--- a/compiler/rustc_resolve/src/errors.rs
+++ b/compiler/rustc_resolve/src/errors.rs
@@ -22,7 +22,7 @@ pub(crate) struct UnderscoreLifetimeNameCannotBeUsedHere(#[primary_span] pub(cra
#[derive(Diagnostic)]
#[diag(resolve_crate_may_not_be_imported)]
-pub(crate) struct CrateMayNotBeImprted(#[primary_span] pub(crate) Span);
+pub(crate) struct CrateMayNotBeImported(#[primary_span] pub(crate) Span);
#[derive(Diagnostic)]
#[diag(resolve_crate_root_imports_must_be_named_explicitly)]
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index 3c22d51c3d4..d7c518fbdd0 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -1276,13 +1276,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
next_binding = binding;
}
- reexports.push(ModChild {
- ident,
- res,
- vis: binding.vis,
- span: binding.span,
- reexport_chain,
- });
+ reexports.push(ModChild { ident, res, vis: binding.vis, reexport_chain });
}
});
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 90a2fa89cd2..a97857e05e2 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -1079,7 +1079,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
for rib in self.lifetime_ribs.iter().rev() {
match rib.kind {
// We are inside a `PolyTraitRef`. The lifetimes are
- // to be intoduced in that (maybe implicit) `for<>` binder.
+ // to be introduced in that (maybe implicit) `for<>` binder.
LifetimeRibKind::Generics {
binder,
kind: LifetimeBinderKind::PolyTrait,
@@ -3803,7 +3803,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
// use std::u8; // bring module u8 in scope
// fn f() -> u8 { // OK, resolves to primitive u8, not to std::u8
// u8::max_value() // OK, resolves to associated function <u8>::max_value,
- // // not to non-existent std::u8::max_value
+ // // not to nonexistent std::u8::max_value
// }
//
// Such behavior is required for backward compatibility.
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 37fbfad2de6..e824a6ddc07 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -91,7 +91,7 @@ fn import_candidate_to_enum_paths(suggestion: &ImportSuggestion) -> (String, Str
/// Description of an elided lifetime.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub(super) struct MissingLifetime {
- /// Used to overwrite the resolution with the suggestion, to avoid cascasing errors.
+ /// Used to overwrite the resolution with the suggestion, to avoid cascading errors.
pub id: NodeId,
/// Where to suggest adding the lifetime.
pub span: Span,
@@ -408,7 +408,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
}
let Some(path_last_segment) = path.last() else { return };
let item_str = path_last_segment.ident;
- // Emit help message for fake-self from other languages (e.g., `this` in Javascript).
+ // Emit help message for fake-self from other languages (e.g., `this` in JavaScript).
if ["this", "my"].contains(&item_str.as_str()) {
err.span_suggestion_short(
span,
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index b820d56b8af..282f12bd3c0 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -33,6 +33,7 @@ use rustc_errors::{
Applicability, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, SubdiagnosticMessage,
};
use rustc_expand::base::{DeriveResolutions, SyntaxExtension, SyntaxExtensionKind};
+use rustc_fluent_macro::fluent_messages;
use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{self, CtorOf, DefKind, DocLinkResMap, LifetimeRes, PartialRes, PerNS};
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, LocalDefIdSet};
@@ -40,7 +41,6 @@ use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
use rustc_hir::definitions::DefPathData;
use rustc_hir::TraitCandidate;
use rustc_index::vec::IndexVec;
-use rustc_macros::fluent_messages;
use rustc_metadata::creader::{CStore, CrateLoader};
use rustc_middle::metadata::ModChild;
use rustc_middle::middle::privacy::EffectiveVisibilities;
diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs
index 9eae99be2e9..d433391f272 100644
--- a/compiler/rustc_resolve/src/rustdoc.rs
+++ b/compiler/rustc_resolve/src/rustdoc.rs
@@ -367,6 +367,7 @@ fn preprocess_link(link: &str) -> Box<str> {
let link = link.strip_suffix("{}").unwrap_or(link);
let link = link.strip_suffix("[]").unwrap_or(link);
let link = if link != "!" { link.strip_suffix('!').unwrap_or(link) } else { link };
+ let link = link.trim();
strip_generics_from_path(link).unwrap_or_else(|_| link.into())
}
diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml
index 9e337dde995..15dbfbfd387 100644
--- a/compiler/rustc_session/Cargo.toml
+++ b/compiler/rustc_session/Cargo.toml
@@ -10,6 +10,7 @@ tracing = "0.1"
rustc_errors = { path = "../rustc_errors" }
rustc_feature = { path = "../rustc_feature" }
rustc_hir = { path = "../rustc_hir" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_target = { path = "../rustc_target" }
rustc_serialize = { path = "../rustc_serialize" }
rustc_data_structures = { path = "../rustc_data_structures" }
diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs
index 968728905e7..590a68c6600 100644
--- a/compiler/rustc_session/src/lib.rs
+++ b/compiler/rustc_session/src/lib.rs
@@ -19,7 +19,7 @@ pub mod errors;
extern crate tracing;
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
-use rustc_macros::fluent_messages;
+use rustc_fluent_macro::fluent_messages;
pub mod cgu_reuse_tracker;
pub mod utils;
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 46c992dfefd..98bcacbe7ff 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1452,9 +1452,9 @@ options! {
fewer_names: Option<bool> = (None, parse_opt_bool, [TRACKED],
"reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR) \
(default: no)"),
- flatten_format_args: bool = (false, parse_bool, [TRACKED],
+ flatten_format_args: bool = (true, parse_bool, [TRACKED],
"flatten nested format_args!() and literals into a simplified format_args!() call \
- (default: no)"),
+ (default: yes)"),
force_unstable_if_unmarked: bool = (false, parse_bool, [TRACKED],
"force all crates to be `rustc_private` unstable (default: no)"),
fuel: Option<(String, u64)> = (None, parse_optimization_fuel, [TRACKED],
@@ -1558,6 +1558,9 @@ options! {
"use like `-Zmir-enable-passes=+DestProp,-InstCombine`. Forces the specified passes to be \
enabled, overriding all other checks. Passes that are not specified are enabled or \
disabled by other flags as usual."),
+ mir_keep_place_mention: bool = (false, parse_bool, [TRACKED],
+ "keep place mention MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 \
+ (default: no)"),
#[rustc_lint_opt_deny_field_access("use `Session::mir_opt_level` instead of this field")]
mir_opt_level: Option<usize> = (None, parse_opt_number, [TRACKED],
"MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds)"),
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 340bb158e17..14a8e8ff727 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -811,7 +811,7 @@ impl Session {
}
pub fn generate_proc_macro_decls_symbol(&self, stable_crate_id: StableCrateId) -> String {
- format!("__rustc_proc_macro_decls_{:08x}__", stable_crate_id.to_u64())
+ format!("__rustc_proc_macro_decls_{:08x}__", stable_crate_id.as_u64())
}
pub fn target_filesearch(&self, kind: PathKind) -> filesearch::FileSearch<'_> {
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index 4dad3c6bce7..09cb6fd22d5 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -128,6 +128,18 @@ fn rustc_place_to_place(place: &rustc_middle::mir::Place<'_>) -> stable_mir::mir
stable_mir::mir::Place { local: place.local.as_usize() }
}
+fn rustc_unwind_to_unwind(
+ unwind: &rustc_middle::mir::UnwindAction,
+) -> stable_mir::mir::UnwindAction {
+ use rustc_middle::mir::UnwindAction;
+ match unwind {
+ UnwindAction::Continue => stable_mir::mir::UnwindAction::Continue,
+ UnwindAction::Unreachable => stable_mir::mir::UnwindAction::Unreachable,
+ UnwindAction::Terminate => stable_mir::mir::UnwindAction::Terminate,
+ UnwindAction::Cleanup(bb) => stable_mir::mir::UnwindAction::Cleanup(bb.as_usize()),
+ }
+}
+
fn rustc_terminator_to_terminator(
terminator: &rustc_middle::mir::Terminator<'_>,
) -> stable_mir::mir::Terminator {
@@ -151,7 +163,15 @@ fn rustc_terminator_to_terminator(
Return => Terminator::Return,
Unreachable => Terminator::Unreachable,
Drop { .. } => todo!(),
- Call { .. } => todo!(),
+ Call { func, args, destination, target, unwind, from_hir_call: _, fn_span: _ } => {
+ Terminator::Call {
+ func: rustc_op_to_op(func),
+ args: args.iter().map(|arg| rustc_op_to_op(arg)).collect(),
+ destination: rustc_place_to_place(destination),
+ target: target.map(|t| t.as_usize()),
+ unwind: rustc_unwind_to_unwind(unwind),
+ }
+ }
Assert { .. } => todo!(),
Yield { .. } => todo!(),
GeneratorDrop => todo!(),
diff --git a/compiler/rustc_smir/src/stable_mir/mir/body.rs b/compiler/rustc_smir/src/stable_mir/mir/body.rs
index c504065c993..bd5e6b68a12 100644
--- a/compiler/rustc_smir/src/stable_mir/mir/body.rs
+++ b/compiler/rustc_smir/src/stable_mir/mir/body.rs
@@ -33,7 +33,7 @@ pub enum Terminator {
args: Vec<Operand>,
destination: Place,
target: Option<usize>,
- cleanup: Option<usize>,
+ unwind: UnwindAction,
},
Assert {
cond: Operand,
@@ -45,6 +45,14 @@ pub enum Terminator {
}
#[derive(Clone, Debug)]
+pub enum UnwindAction {
+ Continue,
+ Unreachable,
+ Terminate,
+ Cleanup(usize),
+}
+
+#[derive(Clone, Debug)]
pub enum Statement {
Assign(Place, Operand),
Nop,
diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs
index b2c58caff2e..6004009c6ff 100644
--- a/compiler/rustc_span/src/def_id.rs
+++ b/compiler/rustc_span/src/def_id.rs
@@ -1,12 +1,11 @@
use crate::{HashStableContext, Symbol};
use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
+use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher, ToStableHashKey};
use rustc_data_structures::unhash::Unhasher;
use rustc_data_structures::AtomicRef;
use rustc_index::vec::Idx;
use rustc_macros::HashStable_Generic;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
-use std::borrow::Borrow;
use std::fmt;
use std::hash::{BuildHasherDefault, Hash, Hasher};
@@ -105,20 +104,20 @@ impl DefPathHash {
/// originates from.
#[inline]
pub fn stable_crate_id(&self) -> StableCrateId {
- StableCrateId(self.0.as_value().0)
+ StableCrateId(self.0.split().0)
}
/// Returns the crate-local part of the [DefPathHash].
///
/// Used for tests.
#[inline]
- pub fn local_hash(&self) -> u64 {
- self.0.as_value().1
+ pub fn local_hash(&self) -> Hash64 {
+ self.0.split().1
}
/// Builds a new [DefPathHash] with the given [StableCrateId] and
/// `local_hash`, where `local_hash` must be unique within its crate.
- pub fn new(stable_crate_id: StableCrateId, local_hash: u64) -> DefPathHash {
+ pub fn new(stable_crate_id: StableCrateId, local_hash: Hash64) -> DefPathHash {
DefPathHash(Fingerprint::new(stable_crate_id.0, local_hash))
}
}
@@ -129,13 +128,6 @@ impl Default for DefPathHash {
}
}
-impl Borrow<Fingerprint> for DefPathHash {
- #[inline]
- fn borrow(&self) -> &Fingerprint {
- &self.0
- }
-}
-
/// A [`StableCrateId`] is a 64-bit hash of a crate name, together with all
/// `-Cmetadata` arguments, and some other data. It is to [`CrateNum`] what [`DefPathHash`] is to
/// [`DefId`]. It is stable across compilation sessions.
@@ -147,15 +139,11 @@ impl Borrow<Fingerprint> for DefPathHash {
///
/// For more information on the possibility of hash collisions in rustc,
/// see the discussion in [`DefId`].
-#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)]
-#[derive(HashStable_Generic, Encodable, Decodable)]
-pub struct StableCrateId(pub(crate) u64);
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
+#[derive(Hash, HashStable_Generic, Encodable, Decodable)]
+pub struct StableCrateId(pub(crate) Hash64);
impl StableCrateId {
- pub fn to_u64(self) -> u64 {
- self.0
- }
-
/// Computes the stable ID for a crate with the given name and
/// `-Cmetadata` arguments.
pub fn new(crate_name: Symbol, is_exe: bool, mut metadata: Vec<String>) -> StableCrateId {
@@ -197,6 +185,17 @@ impl StableCrateId {
StableCrateId(hasher.finish())
}
+
+ #[inline]
+ pub fn as_u64(self) -> u64 {
+ self.0.as_u64()
+ }
+}
+
+impl fmt::LowerHex for StableCrateId {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::LowerHex::fmt(&self.0, f)
+ }
}
rustc_index::newtype_index! {
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index 08c4414034a..f8741d85934 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -33,7 +33,7 @@ use crate::def_id::{CrateNum, DefId, StableCrateId, CRATE_DEF_ID, LOCAL_CRATE};
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::stable_hasher::HashingControls;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
use rustc_data_structures::sync::{Lock, Lrc};
use rustc_data_structures::unhash::UnhashMap;
use rustc_index::vec::IndexVec;
@@ -123,15 +123,15 @@ impl ExpnHash {
/// originates from.
#[inline]
pub fn stable_crate_id(self) -> StableCrateId {
- StableCrateId(self.0.as_value().0)
+ StableCrateId(self.0.split().0)
}
/// Returns the crate-local part of the [ExpnHash].
///
/// Used for tests.
#[inline]
- pub fn local_hash(self) -> u64 {
- self.0.as_value().1
+ pub fn local_hash(self) -> Hash64 {
+ self.0.split().1
}
#[inline]
@@ -141,7 +141,7 @@ impl ExpnHash {
/// Builds a new [ExpnHash] with the given [StableCrateId] and
/// `local_hash`, where `local_hash` must be unique within its crate.
- fn new(stable_crate_id: StableCrateId, local_hash: u64) -> ExpnHash {
+ fn new(stable_crate_id: StableCrateId, local_hash: Hash64) -> ExpnHash {
ExpnHash(Fingerprint::new(stable_crate_id.0, local_hash))
}
}
@@ -350,7 +350,7 @@ pub struct HygieneData {
/// would have collisions without a disambiguator.
/// The keys of this map are always computed with `ExpnData.disambiguator`
/// set to 0.
- expn_data_disambiguators: FxHashMap<u64, u32>,
+ expn_data_disambiguators: FxHashMap<Hash64, u32>,
}
impl HygieneData {
@@ -1040,7 +1040,7 @@ impl ExpnData {
}
#[inline]
- fn hash_expn(&self, ctx: &mut impl HashStableContext) -> u64 {
+ fn hash_expn(&self, ctx: &mut impl HashStableContext) -> Hash64 {
let mut hasher = StableHasher::new();
self.hash_stable(ctx, &mut hasher);
hasher.finish()
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index aa8859ed1a3..8a900ca427e 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -59,7 +59,7 @@ pub mod fatal_error;
pub mod profiling;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{Hash128, Hash64, HashStable, StableHasher};
use rustc_data_structures::sync::{Lock, Lrc};
use std::borrow::Cow;
@@ -282,22 +282,22 @@ impl RealFileName {
pub enum FileName {
Real(RealFileName),
/// Call to `quote!`.
- QuoteExpansion(u64),
+ QuoteExpansion(Hash64),
/// Command line.
- Anon(u64),
+ Anon(Hash64),
/// Hack in `src/librustc_ast/parse.rs`.
// FIXME(jseyfried)
- MacroExpansion(u64),
- ProcMacroSourceCode(u64),
+ MacroExpansion(Hash64),
+ ProcMacroSourceCode(Hash64),
/// Strings provided as `--cfg [cfgspec]` stored in a `crate_cfg`.
- CfgSpec(u64),
+ CfgSpec(Hash64),
/// Strings provided as crate attributes in the CLI.
- CliCrateAttr(u64),
+ CliCrateAttr(Hash64),
/// Custom sources for explicit parser calls from plugins and drivers.
Custom(String),
DocTest(PathBuf, isize),
/// Post-substitution inline assembly from LLVM.
- InlineAsm(u64),
+ InlineAsm(Hash64),
}
impl From<PathBuf> for FileName {
@@ -1044,17 +1044,26 @@ impl fmt::Debug for Span {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// Use the global `SourceMap` to print the span. If that's not
// available, fall back to printing the raw values.
- with_session_globals(|session_globals| {
- if let Some(source_map) = &*session_globals.source_map.borrow() {
- write!(f, "{} ({:?})", source_map.span_to_diagnostic_string(*self), self.ctxt())
- } else {
- f.debug_struct("Span")
- .field("lo", &self.lo())
- .field("hi", &self.hi())
- .field("ctxt", &self.ctxt())
- .finish()
- }
- })
+
+ fn fallback(span: Span, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("Span")
+ .field("lo", &span.lo())
+ .field("hi", &span.hi())
+ .field("ctxt", &span.ctxt())
+ .finish()
+ }
+
+ if SESSION_GLOBALS.is_set() {
+ with_session_globals(|session_globals| {
+ if let Some(source_map) = &*session_globals.source_map.borrow() {
+ write!(f, "{} ({:?})", source_map.span_to_diagnostic_string(*self), self.ctxt())
+ } else {
+ fallback(*self, f)
+ }
+ })
+ } else {
+ fallback(*self, f)
+ }
}
}
@@ -1343,7 +1352,7 @@ pub struct SourceFile {
/// Locations of characters removed during normalization.
pub normalized_pos: Vec<NormalizedPos>,
/// A hash of the filename, used for speeding up hashing in incremental compilation.
- pub name_hash: u128,
+ pub name_hash: Hash128,
/// Indicates which crate this `SourceFile` was imported from.
pub cnum: CrateNum,
}
@@ -1472,7 +1481,7 @@ impl<D: Decoder> Decodable<D> for SourceFile {
};
let multibyte_chars: Vec<MultiByteChar> = Decodable::decode(d);
let non_narrow_chars: Vec<NonNarrowChar> = Decodable::decode(d);
- let name_hash: u128 = Decodable::decode(d);
+ let name_hash = Decodable::decode(d);
let normalized_pos: Vec<NormalizedPos> = Decodable::decode(d);
let cnum: CrateNum = Decodable::decode(d);
SourceFile {
@@ -1514,7 +1523,7 @@ impl SourceFile {
let name_hash = {
let mut hasher: StableHasher = StableHasher::new();
name.hash(&mut hasher);
- hasher.finish::<u128>()
+ hasher.finish()
};
let end_pos = start_pos.to_usize() + src.len();
assert!(end_pos <= u32::MAX as usize);
@@ -1663,10 +1672,11 @@ impl SourceFile {
if let Some(ref src) = self.src {
Some(Cow::from(get_until_newline(src, begin)))
- } else if let Some(src) = self.external_src.borrow().get_source() {
- Some(Cow::Owned(String::from(get_until_newline(src, begin))))
} else {
- None
+ self.external_src
+ .borrow()
+ .get_source()
+ .map(|src| Cow::Owned(String::from(get_until_newline(src, begin))))
}
}
@@ -2159,9 +2169,7 @@ where
};
Hash::hash(&TAG_VALID_SPAN, hasher);
- // We truncate the stable ID hash and line and column numbers. The chances
- // of causing a collision this way should be minimal.
- Hash::hash(&(file.name_hash as u64), hasher);
+ Hash::hash(&file.name_hash, hasher);
// Hash both the length and the end location (line/column) of a span. If we
// hash only the length, for example, then two otherwise equal spans with
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 88e3674f899..1294a8b8e6b 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -13,7 +13,7 @@ pub use crate::hygiene::{ExpnData, ExpnKind};
pub use crate::*;
use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::stable_hasher::StableHasher;
+use rustc_data_structures::stable_hasher::{Hash128, Hash64, StableHasher};
use rustc_data_structures::sync::{AtomicU32, Lrc, MappedReadGuard, ReadGuard, RwLock};
use std::cmp;
use std::hash::Hash;
@@ -138,7 +138,7 @@ impl FileLoader for RealFileLoader {
pub struct StableSourceFileId {
/// A hash of the source file's [`FileName`]. This is hash so that it's size
/// is more predictable than if we included the actual [`FileName`] value.
- pub file_name_hash: u64,
+ pub file_name_hash: Hash64,
/// The [`CrateNum`] of the crate this source file was originally parsed for.
/// We cannot include this information in the hash because at the time
@@ -331,7 +331,7 @@ impl SourceMap {
&self,
filename: FileName,
src_hash: SourceFileHash,
- name_hash: u128,
+ name_hash: Hash128,
source_len: usize,
cnum: CrateNum,
file_local_lines: Lock<SourceFileLines>,
@@ -483,7 +483,7 @@ impl SourceMap {
self.span_to_string(sp, FileNameDisplayPreference::Remapped)
}
- /// Format the span location suitable for pretty printing anotations with relative line numbers
+ /// Format the span location suitable for pretty printing annotations with relative line numbers
pub fn span_to_relative_line_string(&self, sp: Span, relative_to: Span) -> String {
if self.files.borrow().source_files.is_empty() || sp.is_dummy() || relative_to.is_dummy() {
return "no-location".to_string();
@@ -777,7 +777,7 @@ impl SourceMap {
/// Given a 'Span', tries to tell if it's wrapped by "<>" or "()"
/// the algorithm searches if the next character is '>' or ')' after skipping white space
- /// then searches the previous charactoer to match '<' or '(' after skipping white space
+ /// then searches the previous character to match '<' or '(' after skipping white space
/// return true if wrapped by '<>' or '()'
pub fn span_wrapped_by_angle_or_parentheses(&self, span: Span) -> bool {
self.span_to_source(span, |src, start_index, end_index| {
@@ -906,10 +906,8 @@ impl SourceMap {
let snippet = if let Some(ref src) = local_begin.sf.src {
Some(&src[start_index..])
- } else if let Some(src) = src.get_source() {
- Some(&src[start_index..])
} else {
- None
+ src.get_source().map(|src| &src[start_index..])
};
match snippet {
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 6bfae377152..9891915d076 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -204,6 +204,7 @@ symbols! {
HashSet,
Hasher,
Implied,
+ IndexOutput,
Input,
Into,
IntoDiagnostic,
@@ -1036,6 +1037,7 @@ symbols! {
object_safe_for_dispatch,
of,
offset,
+ offset_of,
omit_gdb_pretty_printer_section,
on,
on_unimplemented,
@@ -1986,8 +1988,9 @@ impl Interner {
name
}
- // Get the symbol as a string. `Symbol::as_str()` should be used in
- // preference to this function.
+ /// Get the symbol as a string.
+ ///
+ /// [`Symbol::as_str()`] should be used in preference to this function.
fn get(&self, symbol: Symbol) -> &str {
self.0.lock().strings[symbol.0.as_usize()]
}
diff --git a/compiler/rustc_span/src/tests.rs b/compiler/rustc_span/src/tests.rs
index 5b3915c3338..a242ad6d1d7 100644
--- a/compiler/rustc_span/src/tests.rs
+++ b/compiler/rustc_span/src/tests.rs
@@ -3,8 +3,12 @@ use super::*;
#[test]
fn test_lookup_line() {
let source = "abcdefghijklm\nabcdefghij\n...".to_owned();
- let sf =
- SourceFile::new(FileName::Anon(0), source, BytePos(3), SourceFileHashAlgorithm::Sha256);
+ let sf = SourceFile::new(
+ FileName::Anon(Hash64::ZERO),
+ source,
+ BytePos(3),
+ SourceFileHashAlgorithm::Sha256,
+ );
sf.lines(|lines| assert_eq!(lines, &[BytePos(3), BytePos(17), BytePos(28)]));
assert_eq!(sf.lookup_line(BytePos(0)), None);
diff --git a/compiler/rustc_symbol_mangling/Cargo.toml b/compiler/rustc_symbol_mangling/Cargo.toml
index 4e447eab02e..052ef8bb94c 100644
--- a/compiler/rustc_symbol_mangling/Cargo.toml
+++ b/compiler/rustc_symbol_mangling/Cargo.toml
@@ -15,6 +15,7 @@ twox-hash = "1.6.3"
rustc_span = { path = "../rustc_span" }
rustc_middle = { path = "../rustc_middle" }
rustc_hir = { path = "../rustc_hir" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_target = { path = "../rustc_target" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_session = { path = "../rustc_session" }
diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs
index 5cbca81926b..6a0ca06f69c 100644
--- a/compiler/rustc_symbol_mangling/src/legacy.rs
+++ b/compiler/rustc_symbol_mangling/src/legacy.rs
@@ -1,4 +1,4 @@
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
use rustc_hir::def_id::CrateNum;
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
use rustc_middle::ty::print::{PrettyPrinter, Print, Printer};
@@ -93,7 +93,7 @@ fn get_symbol_hash<'tcx>(
item_type: Ty<'tcx>,
instantiating_crate: Option<CrateNum>,
-) -> u64 {
+) -> Hash64 {
let def_id = instance.def_id();
let substs = instance.substs;
debug!("get_symbol_hash(def_id={:?}, parameters={:?})", def_id, substs);
@@ -138,7 +138,7 @@ fn get_symbol_hash<'tcx>(
});
// 64 bits should be enough to avoid collisions.
- hasher.finish::<u64>()
+ hasher.finish::<Hash64>()
})
}
@@ -176,7 +176,7 @@ impl SymbolPath {
}
}
- fn finish(mut self, hash: u64) -> String {
+ fn finish(mut self, hash: Hash64) -> String {
self.finalize_pending_component();
// E = end name-sequence
let _ = write!(self.result, "17h{hash:016x}E");
diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs
index c2fd3304f2b..c97406868b6 100644
--- a/compiler/rustc_symbol_mangling/src/lib.rs
+++ b/compiler/rustc_symbol_mangling/src/lib.rs
@@ -101,9 +101,9 @@ extern crate rustc_middle;
extern crate tracing;
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
+use rustc_fluent_macro::fluent_messages;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
-use rustc_macros::fluent_messages;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::mir::mono::{InstantiationMode, MonoItem};
diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
index 1a679f32ca5..a9152b8113f 100644
--- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
+++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
@@ -406,7 +406,7 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String {
// Crate disambiguator and name
s.push('C');
- s.push_str(&to_disambiguator(tcx.stable_crate_id(def_path.krate).to_u64()));
+ s.push_str(&to_disambiguator(tcx.stable_crate_id(def_path.krate).as_u64()));
let crate_name = tcx.crate_name(def_path.krate).to_string();
let _ = write!(s, "{}{}", crate_name.len(), &crate_name);
@@ -814,16 +814,10 @@ fn transform_substs<'tcx>(
substs: SubstsRef<'tcx>,
options: TransformTyOptions,
) -> SubstsRef<'tcx> {
- let substs = substs.iter().map(|subst| {
- if let GenericArgKind::Type(ty) = subst.unpack() {
- if is_c_void_ty(tcx, ty) {
- tcx.mk_unit().into()
- } else {
- transform_ty(tcx, ty, options).into()
- }
- } else {
- subst
- }
+ let substs = substs.iter().map(|subst| match subst.unpack() {
+ GenericArgKind::Type(ty) if is_c_void_ty(tcx, ty) => tcx.mk_unit().into(),
+ GenericArgKind::Type(ty) => transform_ty(tcx, ty, options).into(),
+ _ => subst,
});
tcx.mk_substs_from_iter(substs)
}
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index ee883285531..2235524129e 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -731,7 +731,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
fn path_crate(self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
self.push("C");
let stable_crate_id = self.tcx.def_path_hash(cnum.as_def_id()).stable_crate_id();
- self.push_disambiguator(stable_crate_id.to_u64());
+ self.push_disambiguator(stable_crate_id.as_u64());
let name = self.tcx.crate_name(cnum);
self.push_ident(name.as_str());
Ok(self)
diff --git a/compiler/rustc_target/src/abi/call/avr.rs b/compiler/rustc_target/src/abi/call/avr.rs
index e20f01355a4..b01dac8c70d 100644
--- a/compiler/rustc_target/src/abi/call/avr.rs
+++ b/compiler/rustc_target/src/abi/call/avr.rs
@@ -10,7 +10,7 @@
//! > self-consistent and sensible LLVM IR generation, but does not
//! > conform to any particular ABI.
//! >
-//! > - Doxygen Doxumentation of `clang::DefaultABIInfo`
+//! > - Doxygen Documentation of `clang::DefaultABIInfo`
//!
//! This calling convention may not match AVR-GCC in all cases.
//!
diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs
index 8d2e92cc76c..589cd3cf96b 100644
--- a/compiler/rustc_target/src/abi/mod.rs
+++ b/compiler/rustc_target/src/abi/mod.rs
@@ -124,6 +124,21 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
{
Ty::is_unit(self)
}
+
+ pub fn offset_of_subfield<C>(self, cx: &C, indices: impl Iterator<Item = usize>) -> Size
+ where
+ Ty: TyAbiInterface<'a, C>,
+ {
+ let mut layout = self;
+ let mut offset = Size::ZERO;
+
+ for index in indices {
+ offset += layout.fields.offset(index);
+ layout = layout.field(cx, index);
+ }
+
+ offset
+ }
}
impl<'a, Ty> TyAndLayout<'a, Ty> {
diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs
index 5c6dcc0aba9..4c7f64b2078 100644
--- a/compiler/rustc_target/src/spec/apple_base.rs
+++ b/compiler/rustc_target/src/spec/apple_base.rs
@@ -19,6 +19,7 @@ pub enum Arch {
I386,
I686,
X86_64,
+ X86_64h,
X86_64_sim,
X86_64_macabi,
Arm64_macabi,
@@ -36,6 +37,7 @@ impl Arch {
I386 => "i386",
I686 => "i686",
X86_64 | X86_64_sim | X86_64_macabi => "x86_64",
+ X86_64h => "x86_64h",
}
}
@@ -44,13 +46,13 @@ impl Arch {
Armv7 | Armv7k | Armv7s => "arm",
Arm64 | Arm64_32 | Arm64_macabi | Arm64_sim => "aarch64",
I386 | I686 => "x86",
- X86_64 | X86_64_sim | X86_64_macabi => "x86_64",
+ X86_64 | X86_64_sim | X86_64_macabi | X86_64h => "x86_64",
})
}
fn target_abi(self) -> &'static str {
match self {
- Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | I686 | X86_64 => "",
+ Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | I686 | X86_64 | X86_64h => "",
X86_64_macabi | Arm64_macabi => "macabi",
// x86_64-apple-ios is a simulator target, even though it isn't
// declared that way in the target like the other ones...
@@ -67,6 +69,10 @@ impl Arch {
Arm64_32 => "apple-s4",
I386 | I686 => "yonah",
X86_64 | X86_64_sim => "core2",
+ // Note: `core-avx2` is slightly more advanced than `x86_64h`, see
+ // comments (and disabled features) in `x86_64h_apple_darwin` for
+ // details.
+ X86_64h => "core-avx2",
X86_64_macabi => "core2",
Arm64_macabi => "apple-a12",
Arm64_sim => "apple-a12",
@@ -182,8 +188,13 @@ fn deployment_target(var_name: &str) -> Option<(u32, u32)> {
}
fn macos_default_deployment_target(arch: Arch) -> (u32, u32) {
- // Note: Arm64_sim is not included since macOS has no simulator.
- if matches!(arch, Arm64 | Arm64_macabi) { (11, 0) } else { (10, 7) }
+ match arch {
+ // Note: Arm64_sim is not included since macOS has no simulator.
+ Arm64 | Arm64_macabi => (11, 0),
+ // x86_64h-apple-darwin only supports macOS 10.8 and later
+ X86_64h => (10, 8),
+ _ => (10, 7),
+ }
}
fn macos_deployment_target(arch: Arch) -> (u32, u32) {
@@ -227,7 +238,7 @@ fn link_env_remove(arch: Arch, os: &'static str) -> StaticCow<[StaticCow<str>]>
// of the linking environment that's wrong and reversed.
match arch {
Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | I686 | X86_64 | X86_64_sim
- | Arm64_sim => {
+ | X86_64h | Arm64_sim => {
cvs!["MACOSX_DEPLOYMENT_TARGET"]
}
X86_64_macabi | Arm64_macabi => cvs!["IPHONEOS_DEPLOYMENT_TARGET"],
diff --git a/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs
index ebd74012dcd..9bcd56bed00 100644
--- a/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs
@@ -3,6 +3,7 @@ use crate::spec::{Target, TargetOptions};
pub fn target() -> Target {
let mut base = super::linux_gnu_base::opts();
+ base.cpu = "M68020".into();
base.max_atomic_width = Some(32);
Target {
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 4e5a821f0f6..10d38c34919 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -1112,6 +1112,7 @@ supported_targets! {
("aarch64-apple-darwin", aarch64_apple_darwin),
("x86_64-apple-darwin", x86_64_apple_darwin),
+ ("x86_64h-apple-darwin", x86_64h_apple_darwin),
("i686-apple-darwin", i686_apple_darwin),
// FIXME(#106649): Remove aarch64-fuchsia in favor of aarch64-unknown-fuchsia
@@ -2285,13 +2286,13 @@ impl Target {
}
}
} );
- ($key_name:ident, falliable_list) => ( {
+ ($key_name:ident, fallible_list) => ( {
let name = (stringify!($key_name)).replace("_", "-");
obj.remove(&name).and_then(|j| {
if let Some(v) = j.as_array() {
match v.iter().map(|a| FromStr::from_str(a.as_str().unwrap())).collect() {
Ok(l) => { base.$key_name = l },
- // FIXME: `falliable_list` can't re-use the `key!` macro for list
+ // FIXME: `fallible_list` can't re-use the `key!` macro for list
// elements and the error messages from that macro, so it has a bad
// generic message instead
Err(_) => return Some(Err(
@@ -2610,7 +2611,7 @@ impl Target {
key!(has_thumb_interworking, bool);
key!(debuginfo_kind, DebuginfoKind)?;
key!(split_debuginfo, SplitDebuginfo)?;
- key!(supported_split_debuginfo, falliable_list)?;
+ key!(supported_split_debuginfo, fallible_list)?;
key!(supported_sanitizers, SanitizerSet)?;
key!(default_adjusted_cabi, Option<Abi>)?;
key!(generate_arange_section, bool);
diff --git a/compiler/rustc_target/src/spec/thumb_base.rs b/compiler/rustc_target/src/spec/thumb_base.rs
index 4dcf47fe465..2220b9326c9 100644
--- a/compiler/rustc_target/src/spec/thumb_base.rs
+++ b/compiler/rustc_target/src/spec/thumb_base.rs
@@ -12,7 +12,7 @@
//
// We have opted for these instead of one target per processor (e.g., `cortex-m0`, `cortex-m3`,
// etc) because the differences between some processors like the cortex-m0 and cortex-m1 are almost
-// non-existent from the POV of codegen so it doesn't make sense to have separate targets for them.
+// nonexistent from the POV of codegen so it doesn't make sense to have separate targets for them.
// And if differences exist between two processors under the same target, rustc flags can be used to
// optimize for one processor or the other.
//
diff --git a/compiler/rustc_target/src/spec/x86_64h_apple_darwin.rs b/compiler/rustc_target/src/spec/x86_64h_apple_darwin.rs
new file mode 100644
index 00000000000..54f7490b2c0
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64h_apple_darwin.rs
@@ -0,0 +1,44 @@
+use super::apple_base::{macos_llvm_target, opts, Arch};
+use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet};
+use crate::spec::{StackProbeType, Target, TargetOptions};
+
+pub fn target() -> Target {
+ let arch = Arch::X86_64h;
+ let mut base = opts("macos", arch);
+ base.max_atomic_width = Some(128);
+ base.frame_pointer = FramePointer::Always;
+ base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]);
+ base.stack_probes = StackProbeType::X86;
+ base.supported_sanitizers =
+ SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK | SanitizerSet::THREAD;
+
+ // x86_64h is core2-avx without a few of the features which would otherwise
+ // be guaranteed, so we need to disable those. This imitates clang's logic:
+ // - https://github.com/llvm/llvm-project/blob/bd1f7c417/clang/lib/Driver/ToolChains/Arch/X86.cpp#L77-L78
+ // - https://github.com/llvm/llvm-project/blob/bd1f7c417/clang/lib/Driver/ToolChains/Arch/X86.cpp#L133-L141
+ //
+ // FIXME: Sadly, turning these off here disables them in such a way that they
+ // aren't re-enabled by `-Ctarget-cpu=native` (on a machine that has them).
+ // It would be nice if this were not the case, but fixing it seems tricky
+ // (and given that the main use-case for this target is for use in universal
+ // binaries, probably not that important).
+ base.features = "-rdrnd,-aes,-pclmul,-rtm,-fsgsbase".into();
+ // Double-check that the `cpu` is what we expect (if it's not the list above
+ // may need updating).
+ assert_eq!(
+ base.cpu, "core-avx2",
+ "you need to adjust the feature list in x86_64h-apple-darwin if you change this",
+ );
+
+ Target {
+ // Clang automatically chooses a more specific target based on
+ // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
+ // correctly, we do too.
+ llvm_target: macos_llvm_target(arch).into(),
+ pointer_width: 64,
+ data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+ .into(),
+ arch: arch.target_arch(),
+ options: TargetOptions { mcount: "\u{1}mcount".into(), ..base },
+ }
+}
diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml
index d3eba43b47e..a81459317be 100644
--- a/compiler/rustc_trait_selection/Cargo.toml
+++ b/compiler/rustc_trait_selection/Cargo.toml
@@ -14,6 +14,7 @@ rustc_ast = { path = "../rustc_ast" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_hir = { path = "../rustc_hir" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_index = { path = "../rustc_index" }
rustc_infer = { path = "../rustc_infer" }
rustc_macros = { path = "../rustc_macros" }
diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs
index f866cb016e2..ed3994be987 100644
--- a/compiler/rustc_trait_selection/src/lib.rs
+++ b/compiler/rustc_trait_selection/src/lib.rs
@@ -37,7 +37,7 @@ extern crate rustc_middle;
extern crate smallvec;
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
-use rustc_macros::fluent_messages;
+use rustc_fluent_macro::fluent_messages;
pub mod errors;
pub mod infer;
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
index 10d817f75ac..bacb0e32efc 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
@@ -51,7 +51,7 @@ pub(super) enum CandidateSource {
BuiltinImpl,
/// An assumption from the environment.
///
- /// More precicely we've used the `n-th` assumption in the `param_env`.
+ /// More precisely we've used the `n-th` assumption in the `param_env`.
///
/// ## Examples
///
@@ -241,7 +241,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
// HACK: `_: Trait` is ambiguous, because it may be satisfied via a builtin rule,
// object bound, alias bound, etc. We are unable to determine this until we can at
- // least structually resolve the type one layer.
+ // least structurally resolve the type one layer.
if goal.predicate.self_ty().is_ty_var() {
return vec![Candidate {
source: CandidateSource::BuiltinImpl,
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
index c29b5b04e00..bd52957d162 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
@@ -57,6 +57,14 @@ pub struct EvalCtxt<'a, 'tcx> {
pub(super) search_graph: &'a mut SearchGraph<'tcx>,
pub(super) nested_goals: NestedGoals<'tcx>,
+
+ // Has this `EvalCtxt` errored out with `NoSolution` in `try_evaluate_added_goals`?
+ //
+ // If so, then it can no longer be used to make a canonical query response,
+ // since subsequent calls to `try_evaluate_added_goals` have possibly dropped
+ // ambiguous goals. Instead, a probe needs to be introduced somewhere in the
+ // evaluation code.
+ tainted: Result<(), NoSolution>,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
@@ -121,6 +129,7 @@ impl<'tcx> InferCtxtEvalExt<'tcx> for InferCtxt<'tcx> {
max_input_universe: ty::UniverseIndex::ROOT,
var_values: CanonicalVarValues::dummy(),
nested_goals: NestedGoals::new(),
+ tainted: Ok(()),
};
let result = ecx.evaluate_goal(IsNormalizesToHack::No, goal);
@@ -172,6 +181,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
max_input_universe: canonical_goal.max_universe,
search_graph,
nested_goals: NestedGoals::new(),
+ tainted: Ok(()),
};
ecx.compute_goal(goal)
})
@@ -391,6 +401,10 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
},
);
+ if response.is_err() {
+ self.tainted = Err(NoSolution);
+ }
+
self.nested_goals = goals;
response
}
@@ -404,6 +418,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
max_input_universe: self.max_input_universe,
search_graph: self.search_graph,
nested_goals: self.nested_goals.clone(),
+ tainted: self.tainted,
};
self.infcx.probe(|_| f(&mut ecx))
}
@@ -649,7 +664,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
// FIXME(transmutability): This really should be returning nested goals for `Answer::If*`
match rustc_transmute::TransmuteTypeEnv::new(self.infcx).is_transmutable(
ObligationCause::dummy(),
- ty::Binder::dummy(src_and_dst),
+ src_and_dst,
scope,
assume,
) {
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
index ada868705c7..2dea36811d8 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
@@ -11,12 +11,13 @@
use super::{CanonicalGoal, Certainty, EvalCtxt, Goal};
use crate::solve::canonicalize::{CanonicalizeMode, Canonicalizer};
use crate::solve::{CanonicalResponse, QueryResult, Response};
+use rustc_index::vec::IndexVec;
use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
use rustc_infer::infer::canonical::CanonicalVarValues;
use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints};
use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::solve::{ExternalConstraints, ExternalConstraintsData};
-use rustc_middle::ty::{self, GenericArgKind};
+use rustc_middle::ty::{self, BoundVar, GenericArgKind};
use rustc_span::DUMMY_SP;
use std::iter;
use std::ops::Deref;
@@ -50,6 +51,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
certainty: Certainty,
) -> QueryResult<'tcx> {
let goals_certainty = self.try_evaluate_added_goals()?;
+ assert_eq!(
+ self.tainted,
+ Ok(()),
+ "EvalCtxt is tainted -- nested goals may have been dropped in a \
+ previous call to `try_evaluate_added_goals!`"
+ );
+
let certainty = certainty.unify_with(goals_certainty);
let external_constraints = self.compute_external_query_constraints()?;
@@ -139,25 +147,25 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
//
// We therefore instantiate the existential variable in the canonical response with the
// inference variable of the input right away, which is more performant.
- let mut opt_values = vec![None; response.variables.len()];
+ let mut opt_values = IndexVec::from_elem_n(None, response.variables.len());
for (original_value, result_value) in iter::zip(original_values, var_values.var_values) {
match result_value.unpack() {
GenericArgKind::Type(t) => {
if let &ty::Bound(debruijn, b) = t.kind() {
assert_eq!(debruijn, ty::INNERMOST);
- opt_values[b.var.index()] = Some(*original_value);
+ opt_values[b.var] = Some(*original_value);
}
}
GenericArgKind::Lifetime(r) => {
if let ty::ReLateBound(debruijn, br) = *r {
assert_eq!(debruijn, ty::INNERMOST);
- opt_values[br.var.index()] = Some(*original_value);
+ opt_values[br.var] = Some(*original_value);
}
}
GenericArgKind::Const(c) => {
- if let ty::ConstKind::Bound(debrujin, b) = c.kind() {
- assert_eq!(debrujin, ty::INNERMOST);
- opt_values[b.index()] = Some(*original_value);
+ if let ty::ConstKind::Bound(debruijn, b) = c.kind() {
+ assert_eq!(debruijn, ty::INNERMOST);
+ opt_values[b] = Some(*original_value);
}
}
}
@@ -176,11 +184,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
// As an optimization we sometimes avoid creating a new inference variable here.
//
// All new inference variables we create start out in the current universe of the caller.
- // This is conceptionally wrong as these inference variables would be able to name
+ // This is conceptually wrong as these inference variables would be able to name
// more placeholders then they should be able to. However the inference variables have
// to "come from somewhere", so by equating them with the original values of the caller
// later on, we pull them down into their correct universe again.
- if let Some(v) = opt_values[index] {
+ if let Some(v) = opt_values[BoundVar::from_usize(index)] {
v
} else {
self.infcx.instantiate_canonical_var(DUMMY_SP, info, |_| prev_universe)
diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs
index 14cb43b89c3..3a2acbeb32e 100644
--- a/compiler/rustc_trait_selection/src/solve/project_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs
@@ -198,7 +198,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
let term: ty::EarlyBinder<ty::Term<'tcx>> = if is_const {
let identity_substs =
ty::InternalSubsts::identity_for_item(tcx, assoc_def.item.def_id);
- let did = ty::WithOptConstParam::unknown(assoc_def.item.def_id);
+ let did = assoc_def.item.def_id;
let kind =
ty::ConstKind::Unevaluated(ty::UnevaluatedConst::new(did, identity_substs));
ty.map_bound(|ty| tcx.mk_const(kind, ty).into())
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index abd11a15ac2..1abcc80d01a 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -591,7 +591,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
Some(self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS))
}
- // These types cannot be structurally decomposed into constitutent
+ // These types cannot be structurally decomposed into constituent
// types, and therefore have no built-in auto impl.
ty::Dynamic(..)
| ty::Param(..)
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index 182d995c4eb..222af4c2ace 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -796,10 +796,9 @@ impl<'tcx> AutoTraitFinder<'tcx> {
Ok(Some(valtree)) => Ok(selcx.tcx().mk_const(valtree, c.ty())),
Ok(None) => {
let tcx = self.tcx;
- let def_id = unevaluated.def.did;
let reported =
tcx.sess.emit_err(UnableToConstructConstantValue {
- span: tcx.def_span(def_id),
+ span: tcx.def_span(unevaluated.def),
unevaluated: unevaluated,
});
Err(ErrorHandled::Reported(reported))
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index 345e84990ed..9d99d30d45c 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -44,7 +44,7 @@ pub fn is_const_evaluatable<'tcx>(
let ct = tcx.expand_abstract_consts(unexpanded_ct);
let is_anon_ct = if let ty::ConstKind::Unevaluated(uv) = ct.kind() {
- tcx.def_kind(uv.def.did) == DefKind::AnonConst
+ tcx.def_kind(uv.def) == DefKind::AnonConst
} else {
false
};
@@ -119,7 +119,7 @@ pub fn is_const_evaluatable<'tcx>(
tcx.sess
.struct_span_fatal(
// Slightly better span than just using `span` alone
- if span == rustc_span::DUMMY_SP { tcx.def_span(uv.def.did) } else { span },
+ if span == rustc_span::DUMMY_SP { tcx.def_span(uv.def) } else { span },
"failed to evaluate generic const expression",
)
.note("the crate this constant originates from uses `#![feature(generic_const_exprs)]`")
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 1b741b7302b..ae21dcd2a36 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -467,7 +467,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
}
- self.tcx.sess.delay_span_bug(DUMMY_SP, "expected fullfillment errors")
+ self.tcx.sess.delay_span_bug(DUMMY_SP, "expected fulfillment errors")
}
/// Reports that an overflow has occurred and halts compilation. We
@@ -742,7 +742,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
{
// Recompute the safe transmute reason and use that for the error reporting
self.get_safe_transmute_error_and_reason(
- trait_predicate,
obligation.clone(),
trait_ref,
span,
@@ -1477,7 +1476,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
};
let mut err =
self.tcx.sess.struct_span_err(span, "unconstrained generic constant");
- let const_span = self.tcx.def_span(uv.def.did);
+ let const_span = self.tcx.def_span(uv.def);
match self.tcx.sess.source_map().span_to_snippet(const_span) {
Ok(snippet) => err.help(&format!(
"try adding a `where` bound using this expression: `where [(); {}]:`",
@@ -1629,7 +1628,6 @@ trait InferCtxtPrivExt<'tcx> {
fn get_safe_transmute_error_and_reason(
&self,
- trait_predicate: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
obligation: Obligation<'tcx, ty::Predicate<'tcx>>,
trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
span: Span,
@@ -1773,7 +1771,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
.tcx
.mk_const(
ty::UnevaluatedConst {
- def: ty::WithOptConstParam::unknown(data.projection_ty.def_id),
+ def: data.projection_ty.def_id,
substs: data.projection_ty.substs,
},
ct.ty(),
@@ -2058,7 +2056,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
if candidates.iter().any(|c| matches!(c.similarity, CandidateSimilarity::Exact { .. })) {
// If any of the candidates is a perfect match, we don't want to show all of them.
// This is particularly relevant for the case of numeric types (as they all have the
- // same cathegory).
+ // same category).
candidates.retain(|c| matches!(c.similarity, CandidateSimilarity::Exact { .. }));
}
candidates
@@ -2921,18 +2919,20 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
fn get_safe_transmute_error_and_reason(
&self,
- trait_predicate: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
obligation: Obligation<'tcx, ty::Predicate<'tcx>>,
trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
span: Span,
) -> (String, Option<String>) {
- let src_and_dst = trait_predicate.map_bound(|p| rustc_transmute::Types {
- dst: p.trait_ref.substs.type_at(0),
- src: p.trait_ref.substs.type_at(1),
- });
- let scope = trait_ref.skip_binder().substs.type_at(2);
+ // Erase regions because layout code doesn't particularly care about regions.
+ let trait_ref = self.tcx.erase_regions(self.tcx.erase_late_bound_regions(trait_ref));
+
+ let src_and_dst = rustc_transmute::Types {
+ dst: trait_ref.substs.type_at(0),
+ src: trait_ref.substs.type_at(1),
+ };
+ let scope = trait_ref.substs.type_at(2);
let Some(assume) =
- rustc_transmute::Assume::from_const(self.infcx.tcx, obligation.param_env, trait_ref.skip_binder().substs.const_at(3)) else {
+ rustc_transmute::Assume::from_const(self.infcx.tcx, obligation.param_env, trait_ref.substs.const_at(3)) else {
span_bug!(span, "Unable to construct rustc_transmute::Assume where it was previously possible");
};
match rustc_transmute::TransmuteTypeEnv::new(self.infcx).is_transmutable(
@@ -2942,24 +2942,27 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
assume,
) {
rustc_transmute::Answer::No(reason) => {
- let dst = trait_ref.skip_binder().substs.type_at(0);
- let src = trait_ref.skip_binder().substs.type_at(1);
- let custom_err_msg = format!("`{src}` cannot be safely transmuted into `{dst}` in the defining scope of `{scope}`").to_string();
+ let dst = trait_ref.substs.type_at(0);
+ let src = trait_ref.substs.type_at(1);
+ let custom_err_msg = format!(
+ "`{src}` cannot be safely transmuted into `{dst}` in the defining scope of `{scope}`"
+ );
let reason_msg = match reason {
rustc_transmute::Reason::SrcIsUnspecified => {
- format!("`{src}` does not have a well-specified layout").to_string()
+ format!("`{src}` does not have a well-specified layout")
}
+
rustc_transmute::Reason::DstIsUnspecified => {
- format!("`{dst}` does not have a well-specified layout").to_string()
+ format!("`{dst}` does not have a well-specified layout")
}
+
rustc_transmute::Reason::DstIsBitIncompatible => {
format!("At least one value of `{src}` isn't a bit-valid value of `{dst}`")
- .to_string()
}
+
rustc_transmute::Reason::DstIsPrivate => format!(
"`{dst}` is or contains a type or field that is not visible in that scope"
- )
- .to_string(),
+ ),
// FIXME(bryangarza): Include the number of bytes of src and dst
rustc_transmute::Reason::DstIsTooBig => {
format!("The size of `{src}` is smaller than the size of `{dst}`")
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index fb75ec76729..73207f183a1 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -1381,7 +1381,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
}
- // Issue #104961, we need to add parentheses properly for compond expressions
+ // Issue #104961, we need to add parentheses properly for compound expressions
// for example, `x.starts_with("hi".to_string() + "you")`
// should be `x.starts_with(&("hi".to_string() + "you"))`
let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else { return false; };
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 26cadab3e9f..43196d1e629 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -540,8 +540,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
use ty::ConstKind::Unevaluated;
match (c1.kind(), c2.kind()) {
(Unevaluated(a), Unevaluated(b))
- if a.def.did == b.def.did
- && tcx.def_kind(a.def.did) == DefKind::AssocConst =>
+ if a.def == b.def && tcx.def_kind(a.def) == DefKind::AssocConst =>
{
if let Ok(new_obligations) = infcx
.at(&obligation.cause, obligation.param_env)
diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs
index af567c07438..63949843aed 100644
--- a/compiler/rustc_trait_selection/src/traits/misc.rs
+++ b/compiler/rustc_trait_selection/src/traits/misc.rs
@@ -14,7 +14,7 @@ use rustc_span::DUMMY_SP;
use super::outlives_bounds::InferCtxtExt;
pub enum CopyImplementationError<'tcx> {
- InfrigingFields(Vec<(&'tcx ty::FieldDef, Ty<'tcx>, InfringingFieldsReason<'tcx>)>),
+ InfringingFields(Vec<(&'tcx ty::FieldDef, Ty<'tcx>, InfringingFieldsReason<'tcx>)>),
NotAnAdt,
HasDestructor,
}
@@ -125,7 +125,7 @@ pub fn type_allowed_to_implement_copy<'tcx>(
}
if !infringing.is_empty() {
- return Err(CopyImplementationError::InfrigingFields(infringing));
+ return Err(CopyImplementationError::InfringingFields(infringing));
}
if adt.has_dtor(tcx) {
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 8a203dec86b..4c9df5d9d0a 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -203,7 +203,7 @@ fn do_normalize_predicates<'tcx>(
}
};
- debug!("do_normalize_predictes: normalized predicates = {:?}", predicates);
+ debug!("do_normalize_predicates: normalized predicates = {:?}", predicates);
// We can use the `elaborated_env` here; the region code only
// cares about declarations like `'a: 'b`.
@@ -450,7 +450,7 @@ fn is_impossible_method(tcx: TyCtxt<'_>, (impl_def_id, trait_item_def_id): (DefI
{
return ControlFlow::Break(());
}
- r.super_visit_with(self)
+ ControlFlow::Continue(())
}
fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
if let ty::ConstKind::Param(param) = ct.kind()
diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
index cff3d277a78..e01a57ea4fe 100644
--- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
@@ -55,7 +55,18 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> {
) -> Vec<OutlivesBound<'tcx>> {
let ty = self.resolve_vars_if_possible(ty);
let ty = OpportunisticRegionResolver::new(self).fold_ty(ty);
- assert!(!ty.needs_infer());
+
+ // We do not expect existential variables in implied bounds.
+ // We may however encounter unconstrained lifetime variables in invalid
+ // code. See #110161 for context.
+ assert!(!ty.has_non_region_infer());
+ if ty.needs_infer() {
+ self.tcx.sess.delay_span_bug(
+ self.tcx.def_span(body_id),
+ "skipped implied_outlives_bounds due to unconstrained lifetimes",
+ );
+ return vec![];
+ }
let span = self.tcx.def_span(body_id);
let result = param_env
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 826fc63ca06..6ba05387173 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -2131,9 +2131,8 @@ fn confirm_impl_candidate<'cx, 'tcx>(
let ty = tcx.type_of(assoc_ty.item.def_id);
let is_const = matches!(tcx.def_kind(assoc_ty.item.def_id), DefKind::AssocConst);
let term: ty::EarlyBinder<ty::Term<'tcx>> = if is_const {
- let identity_substs =
- crate::traits::InternalSubsts::identity_for_item(tcx, assoc_ty.item.def_id);
- let did = ty::WithOptConstParam::unknown(assoc_ty.item.def_id);
+ let did = assoc_ty.item.def_id;
+ let identity_substs = crate::traits::InternalSubsts::identity_for_item(tcx, did);
let kind = ty::ConstKind::Unevaluated(ty::UnevaluatedConst::new(did, identity_substs));
ty.map_bound(|ty| tcx.mk_const(kind, ty).into())
} else {
@@ -2277,11 +2276,10 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
obligation.param_env,
cause.clone(),
obligation.recursion_depth + 1,
- tcx.bound_return_position_impl_trait_in_trait_tys(impl_fn_def_id)
- .map_bound(|tys| {
- tys.map_or_else(|guar| tcx.ty_error(guar), |tys| tys[&obligation.predicate.def_id])
- })
- .subst(tcx, impl_fn_substs),
+ tcx.collect_return_position_impl_trait_in_trait_tys(impl_fn_def_id).map_or_else(
+ |guar| tcx.ty_error(guar),
+ |tys| tys[&obligation.predicate.def_id].subst(tcx, impl_fn_substs),
+ ),
&mut obligations,
);
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
index b63da28e274..baa2fbb6751 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
@@ -32,14 +32,8 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> {
fn perform_query(
tcx: TyCtxt<'tcx>,
- mut canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
+ canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
) -> Fallible<CanonicalQueryResponse<'tcx, ()>> {
- match canonicalized.value.value.predicate.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => {
- canonicalized.value.param_env.remap_constness_with(pred.constness);
- }
- _ => canonicalized.value.param_env = canonicalized.value.param_env.without_const(),
- }
tcx.type_op_prove_predicate(canonicalized)
}
}
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 1f5bbc178f7..a019d00461b 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -775,7 +775,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation: &TraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
- if obligation.has_non_region_param() {
+ if obligation.predicate.has_non_region_param() {
return;
}
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 5e60bc01bb6..3bba11262f5 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -275,33 +275,35 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
) -> Result<ImplSourceBuiltinData<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
debug!(?obligation, "confirm_transmutability_candidate");
- let predicate = obligation.predicate;
-
- let type_at = |i| predicate.map_bound(|p| p.trait_ref.substs.type_at(i));
- let const_at = |i| predicate.skip_binder().trait_ref.substs.const_at(i);
-
- let src_and_dst = predicate.map_bound(|p| rustc_transmute::Types {
- dst: p.trait_ref.substs.type_at(0),
- src: p.trait_ref.substs.type_at(1),
- });
-
- let scope = type_at(2).skip_binder();
-
- let Some(assume) =
- rustc_transmute::Assume::from_const(self.infcx.tcx, obligation.param_env, const_at(3)) else {
- return Err(Unimplemented);
- };
-
- let cause = obligation.cause.clone();
+ // We erase regions here because transmutability calls layout queries,
+ // which does not handle inference regions and doesn't particularly
+ // care about other regions. Erasing late-bound regions is equivalent
+ // to instantiating the binder with placeholders then erasing those
+ // placeholder regions.
+ let predicate =
+ self.tcx().erase_regions(self.tcx().erase_late_bound_regions(obligation.predicate));
+
+ let Some(assume) = rustc_transmute::Assume::from_const(
+ self.infcx.tcx,
+ obligation.param_env,
+ predicate.trait_ref.substs.const_at(3)
+ ) else {
+ return Err(Unimplemented);
+ };
let mut transmute_env = rustc_transmute::TransmuteTypeEnv::new(self.infcx);
-
- let maybe_transmutable = transmute_env.is_transmutable(cause, src_and_dst, scope, assume);
-
- use rustc_transmute::Answer;
+ let maybe_transmutable = transmute_env.is_transmutable(
+ obligation.cause.clone(),
+ rustc_transmute::Types {
+ dst: predicate.trait_ref.substs.type_at(0),
+ src: predicate.trait_ref.substs.type_at(1),
+ },
+ predicate.trait_ref.substs.type_at(2),
+ assume,
+ );
match maybe_transmutable {
- Answer::Yes => Ok(ImplSourceBuiltinData { nested: vec![] }),
+ rustc_transmute::Answer::Yes => Ok(ImplSourceBuiltinData { nested: vec![] }),
_ => Err(Unimplemented),
}
}
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 6bb53418bea..081e4d7cfa4 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -888,7 +888,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let c1 = tcx.expand_abstract_consts(c1);
let c2 = tcx.expand_abstract_consts(c2);
debug!(
- "evalaute_predicate_recursively: equating consts:\nc1= {:?}\nc2= {:?}",
+ "evaluate_predicate_recursively: equating consts:\nc1= {:?}\nc2= {:?}",
c1, c2
);
@@ -896,8 +896,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
use ty::ConstKind::Unevaluated;
match (c1.kind(), c2.kind()) {
(Unevaluated(a), Unevaluated(b))
- if a.def.did == b.def.did
- && tcx.def_kind(a.def.did) == DefKind::AssocConst =>
+ if a.def == b.def && tcx.def_kind(a.def) == DefKind::AssocConst =>
{
if let Ok(InferOk { obligations, value: () }) = self
.infcx
diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs
index 20357d4d250..7792ceabe7e 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -243,16 +243,11 @@ pub fn get_vtable_index_of_object_method<'tcx, N>(
) -> Option<usize> {
// Count number of methods preceding the one we are selecting and
// add them to the total offset.
- if let Some(index) = tcx
- .own_existential_vtable_entries(object.upcast_trait_ref.def_id())
+ tcx.own_existential_vtable_entries(object.upcast_trait_ref.def_id())
.iter()
.copied()
.position(|def_id| def_id == method_def_id)
- {
- Some(object.vtable_base + index)
- } else {
- None
- }
+ .map(|index| object.vtable_base + index)
}
pub fn closure_trait_ref_and_return_type<'tcx>(
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 3d026506a5a..40e19abc0d0 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -170,29 +170,20 @@ pub fn predicate_obligations<'tcx>(
ty::PredicateKind::WellFormed(arg) => {
wf.compute(arg);
}
- ty::PredicateKind::ObjectSafe(_) => {}
- ty::PredicateKind::ClosureKind(..) => {}
- ty::PredicateKind::Subtype(ty::SubtypePredicate { a, b, a_is_expected: _ }) => {
- wf.compute(a.into());
- wf.compute(b.into());
- }
- ty::PredicateKind::Coerce(ty::CoercePredicate { a, b }) => {
- wf.compute(a.into());
- wf.compute(b.into());
- }
+
ty::PredicateKind::ConstEvaluatable(ct) => {
wf.compute(ct.into());
}
- ty::PredicateKind::ConstEquate(c1, c2) => {
- wf.compute(c1.into());
- wf.compute(c2.into());
- }
- ty::PredicateKind::Ambiguous => {}
- ty::PredicateKind::TypeWellFormedFromEnv(..) => {
- bug!("TypeWellFormedFromEnv is only used for Chalk")
- }
- ty::PredicateKind::AliasRelate(..) => {
- bug!("We should only wf check where clauses and `AliasRelate` is not a `Clause`")
+
+ ty::PredicateKind::ObjectSafe(_)
+ | ty::PredicateKind::ClosureKind(..)
+ | ty::PredicateKind::Subtype(..)
+ | ty::PredicateKind::Coerce(..)
+ | ty::PredicateKind::ConstEquate(..)
+ | ty::PredicateKind::Ambiguous
+ | ty::PredicateKind::AliasRelate(..)
+ | ty::PredicateKind::TypeWellFormedFromEnv(..) => {
+ bug!("We should only wf check where clauses, unexpected predicate: {predicate:?}")
}
}
@@ -487,7 +478,7 @@ impl<'tcx> WfPredicates<'tcx> {
match ct.kind() {
ty::ConstKind::Unevaluated(uv) => {
if !ct.has_escaping_bound_vars() {
- let obligations = self.nominal_obligations(uv.def.did, uv.substs);
+ let obligations = self.nominal_obligations(uv.def, uv.substs);
self.out.extend(obligations);
let predicate =
diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs
index 2be72879b7b..4d225e36b22 100644
--- a/compiler/rustc_traits/src/chalk/lowering.rs
+++ b/compiler/rustc_traits/src/chalk/lowering.rs
@@ -60,6 +60,20 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Substitution<RustInterner<'tcx>>> for Subst
}
}
+impl<'tcx> LowerInto<'tcx, chalk_ir::Substitution<RustInterner<'tcx>>>
+ for &'tcx ty::List<Ty<'tcx>>
+{
+ fn lower_into(
+ self,
+ interner: RustInterner<'tcx>,
+ ) -> chalk_ir::Substitution<RustInterner<'tcx>> {
+ chalk_ir::Substitution::from_iter(
+ interner,
+ self.iter().map(|ty| GenericArg::from(ty).lower_into(interner)),
+ )
+ }
+}
+
impl<'tcx> LowerInto<'tcx, SubstsRef<'tcx>> for &chalk_ir::Substitution<RustInterner<'tcx>> {
fn lower_into(self, interner: RustInterner<'tcx>) -> SubstsRef<'tcx> {
interner
@@ -351,9 +365,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty<RustInterner<'tcx>>> for Ty<'tcx> {
ty::GeneratorWitness(_) => unimplemented!(),
ty::GeneratorWitnessMIR(..) => unimplemented!(),
ty::Never => chalk_ir::TyKind::Never,
- ty::Tuple(types) => {
- chalk_ir::TyKind::Tuple(types.len(), types.as_substs().lower_into(interner))
- }
+ ty::Tuple(types) => chalk_ir::TyKind::Tuple(types.len(), types.lower_into(interner)),
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),
@@ -435,7 +447,7 @@ impl<'tcx> LowerInto<'tcx, Ty<'tcx>> for &chalk_ir::Ty<RustInterner<'tcx>> {
TyKind::GeneratorWitness(..) => unimplemented!(),
TyKind::Never => ty::Never,
TyKind::Tuple(_len, substitution) => {
- ty::Tuple(substitution.lower_into(interner).try_as_type_list().unwrap())
+ ty::Tuple(substitution.lower_into(interner).into_type_list(interner.tcx))
}
TyKind::Slice(ty) => ty::Slice(ty.lower_into(interner)),
TyKind::Raw(mutbl, ty) => ty::RawPtr(ty::TypeAndMut {
@@ -998,7 +1010,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for BoundVarsCollector<'tcx> {
_ => (),
};
- r.super_visit_with(self)
+ ControlFlow::Continue(())
}
}
@@ -1048,7 +1060,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for NamedBoundVarSubstitutor<'a, 'tcx> {
_ => (),
};
- r.super_fold_with(self)
+ r
}
}
@@ -1142,7 +1154,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ParamsSubstitutor<'tcx> {
}
},
- _ => r.super_fold_with(self),
+ _ => r,
}
}
}
@@ -1223,6 +1235,6 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for PlaceholdersCollector {
_ => (),
};
- r.super_visit_with(self)
+ ControlFlow::Continue(())
}
}
diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs
index e0fd487b3d3..19622112f2a 100644
--- a/compiler/rustc_traits/src/type_op.rs
+++ b/compiler/rustc_traits/src/type_op.rs
@@ -89,6 +89,7 @@ fn relate_mir_and_user_substs<'tcx>(
def_id: hir::def_id::DefId,
user_substs: UserSubsts<'tcx>,
) -> Result<(), NoSolution> {
+ let param_env = param_env.without_const();
let UserSubsts { user_self_ty, substs } = user_substs;
let tcx = ocx.infcx.tcx;
let cause = ObligationCause::dummy_with_span(span);
diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs
index 2a89494c80b..a6d88b1342a 100644
--- a/compiler/rustc_transmute/src/layout/tree.rs
+++ b/compiler/rustc_transmute/src/layout/tree.rs
@@ -196,7 +196,7 @@ pub(crate) mod rustc {
fn from(err: LayoutError<'tcx>) -> Self {
match err {
LayoutError::Unknown(..) => Self::Unknown,
- err @ _ => unimplemented!("{:?}", err),
+ err => unimplemented!("{:?}", err),
}
}
}
diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs
index a93a42987ed..8be02c1d988 100644
--- a/compiler/rustc_transmute/src/lib.rs
+++ b/compiler/rustc_transmute/src/lib.rs
@@ -64,7 +64,6 @@ mod rustc {
use rustc_infer::infer::InferCtxt;
use rustc_macros::{TypeFoldable, TypeVisitable};
use rustc_middle::traits::ObligationCause;
- use rustc_middle::ty::Binder;
use rustc_middle::ty::Const;
use rustc_middle::ty::ParamEnv;
use rustc_middle::ty::Ty;
@@ -92,15 +91,13 @@ mod rustc {
pub fn is_transmutable(
&mut self,
cause: ObligationCause<'tcx>,
- src_and_dst: Binder<'tcx, Types<'tcx>>,
+ types: Types<'tcx>,
scope: Ty<'tcx>,
assume: crate::Assume,
) -> crate::Answer<crate::layout::rustc::Ref<'tcx>> {
- let src = src_and_dst.map_bound(|types| types.src).skip_binder();
- let dst = src_and_dst.map_bound(|types| types.dst).skip_binder();
crate::maybe_transmutable::MaybeTransmutableQuery::new(
- src,
- dst,
+ types.src,
+ types.dst,
scope,
assume,
self.infcx.tcx,
diff --git a/compiler/rustc_ty_utils/Cargo.toml b/compiler/rustc_ty_utils/Cargo.toml
index 52fbd3ae047..51885c9b47e 100644
--- a/compiler/rustc_ty_utils/Cargo.toml
+++ b/compiler/rustc_ty_utils/Cargo.toml
@@ -9,6 +9,7 @@ rustc_middle = { path = "../rustc_middle" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_hir = { path = "../rustc_hir" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_infer = { path = "../rustc_infer" }
rustc_macros = { path = "../rustc_macros" }
rustc_span = { path = "../rustc_span" }
diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs
index b67607a4db6..b08a92570ed 100644
--- a/compiler/rustc_ty_utils/src/consts.rs
+++ b/compiler/rustc_ty_utils/src/consts.rs
@@ -132,7 +132,7 @@ fn recurse_build<'tcx>(
tcx.mk_const(val, node.ty)
}
&ExprKind::NamedConst { def_id, substs, user_ty: _ } => {
- let uneval = ty::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs);
+ let uneval = ty::UnevaluatedConst::new(def_id, substs);
tcx.mk_const(uneval, node.ty)
}
ExprKind::ConstParam { param, .. } => tcx.mk_const(*param, node.ty),
@@ -256,6 +256,7 @@ fn recurse_build<'tcx>(
ExprKind::VarRef { .. }
| ExprKind::UpvarRef { .. }
| ExprKind::StaticRef { .. }
+ | ExprKind::OffsetOf { .. }
| ExprKind::ThreadLocalRef(_) => {
error(GenericConstantTooComplexSub::OperationNotSupported(node.span))?
}
@@ -347,6 +348,7 @@ impl<'a, 'tcx> IsThirPolymorphic<'a, 'tcx> {
| thir::ExprKind::ZstLiteral { .. }
| thir::ExprKind::StaticRef { .. }
| thir::ExprKind::InlineAsm(_)
+ | thir::ExprKind::OffsetOf { .. }
| thir::ExprKind::ThreadLocalRef(_)
| thir::ExprKind::Yield { .. } => false,
}
@@ -391,52 +393,36 @@ impl<'a, 'tcx> visit::Visitor<'a, 'tcx> for IsThirPolymorphic<'a, 'tcx> {
/// Builds an abstract const, do not use this directly, but use `AbstractConst::new` instead.
pub fn thir_abstract_const(
tcx: TyCtxt<'_>,
- def: ty::WithOptConstParam<LocalDefId>,
+ def: LocalDefId,
) -> Result<Option<ty::Const<'_>>, ErrorGuaranteed> {
- if tcx.features().generic_const_exprs {
- match tcx.def_kind(def.did) {
- // FIXME(generic_const_exprs): We currently only do this for anonymous constants,
- // meaning that we do not look into associated constants. I(@lcnr) am not yet sure whether
- // we want to look into them or treat them as opaque projections.
- //
- // Right now we do neither of that and simply always fail to unify them.
- DefKind::AnonConst | DefKind::InlineConst => (),
- _ => return Ok(None),
- }
-
- let body = tcx.thir_body(def)?;
- let (body, body_id) = (&*body.0.borrow(), body.1);
+ if !tcx.features().generic_const_exprs {
+ return Ok(None);
+ }
- let mut is_poly_vis = IsThirPolymorphic { is_poly: false, thir: body };
- visit::walk_expr(&mut is_poly_vis, &body[body_id]);
- if !is_poly_vis.is_poly {
- return Ok(None);
- }
+ match tcx.def_kind(def) {
+ // FIXME(generic_const_exprs): We currently only do this for anonymous constants,
+ // meaning that we do not look into associated constants. I(@lcnr) am not yet sure whether
+ // we want to look into them or treat them as opaque projections.
+ //
+ // Right now we do neither of that and simply always fail to unify them.
+ DefKind::AnonConst | DefKind::InlineConst => (),
+ _ => return Ok(None),
+ }
- let root_span = body.exprs[body_id].span;
+ let body = tcx.thir_body(def)?;
+ let (body, body_id) = (&*body.0.borrow(), body.1);
- Some(recurse_build(tcx, body, body_id, root_span)).transpose()
- } else {
- Ok(None)
+ let mut is_poly_vis = IsThirPolymorphic { is_poly: false, thir: body };
+ visit::walk_expr(&mut is_poly_vis, &body[body_id]);
+ if !is_poly_vis.is_poly {
+ return Ok(None);
}
+
+ let root_span = body.exprs[body_id].span;
+
+ Some(recurse_build(tcx, body, body_id, root_span)).transpose()
}
pub fn provide(providers: &mut ty::query::Providers) {
- *providers = ty::query::Providers {
- destructure_const,
- thir_abstract_const: |tcx, def_id| {
- if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) {
- tcx.thir_abstract_const_of_const_arg(def)
- } else {
- thir_abstract_const(tcx, ty::WithOptConstParam::unknown(def_id))
- }
- },
- thir_abstract_const_of_const_arg: |tcx, (did, param_did)| {
- thir_abstract_const(
- tcx,
- ty::WithOptConstParam { did, const_param_did: Some(param_did) },
- )
- },
- ..*providers
- };
+ *providers = ty::query::Providers { destructure_const, thir_abstract_const, ..*providers };
}
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 0a6c118093e..21cc3c9517e 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -1,5 +1,5 @@
use rustc_errors::ErrorGuaranteed;
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::DefId;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::traits::CodegenObligationError;
use rustc_middle::ty::subst::SubstsRef;
@@ -14,54 +14,26 @@ fn resolve_instance<'tcx>(
tcx: TyCtxt<'tcx>,
key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)>,
) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> {
- let (param_env, (did, substs)) = key.into_parts();
- if let Some(did) = did.as_local() {
- if let Some(param_did) = tcx.opt_const_param_of(did) {
- return tcx.resolve_instance_of_const_arg(param_env.and((did, param_did, substs)));
- }
- }
-
- inner_resolve_instance(tcx, param_env.and((ty::WithOptConstParam::unknown(did), substs)))
-}
-
-fn resolve_instance_of_const_arg<'tcx>(
- tcx: TyCtxt<'tcx>,
- key: ty::ParamEnvAnd<'tcx, (LocalDefId, DefId, SubstsRef<'tcx>)>,
-) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> {
- let (param_env, (did, const_param_did, substs)) = key.into_parts();
- inner_resolve_instance(
- tcx,
- param_env.and((
- ty::WithOptConstParam { did: did.to_def_id(), const_param_did: Some(const_param_did) },
- substs,
- )),
- )
-}
-
-fn inner_resolve_instance<'tcx>(
- tcx: TyCtxt<'tcx>,
- key: ty::ParamEnvAnd<'tcx, (ty::WithOptConstParam<DefId>, SubstsRef<'tcx>)>,
-) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> {
let (param_env, (def, substs)) = key.into_parts();
- let result = if let Some(trait_def_id) = tcx.trait_of_item(def.did) {
+ let result = if let Some(trait_def_id) = tcx.trait_of_item(def) {
debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env);
resolve_associated_item(
tcx,
- def.did,
+ def,
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 ty = tcx.type_of(def);
let item_type =
tcx.subst_and_normalize_erasing_regions(substs, param_env, ty.skip_binder());
let def = match *item_type.kind() {
ty::FnDef(def_id, ..) if tcx.is_intrinsic(def_id) => {
debug!(" => intrinsic");
- ty::InstanceDef::Intrinsic(def.did)
+ ty::InstanceDef::Intrinsic(def)
}
ty::FnDef(def_id, substs) if Some(def_id) == tcx.lang_items().drop_in_place_fn() => {
let ty = substs.type_at(0);
@@ -206,15 +178,11 @@ fn resolve_associated_item<'tcx>(
Some(ty::Instance::new(leaf_def.item.def_id, substs))
}
traits::ImplSource::Generator(generator_data) => Some(Instance {
- def: ty::InstanceDef::Item(ty::WithOptConstParam::unknown(
- generator_data.generator_def_id,
- )),
+ def: ty::InstanceDef::Item(generator_data.generator_def_id),
substs: generator_data.substs,
}),
traits::ImplSource::Future(future_data) => Some(Instance {
- def: ty::InstanceDef::Item(ty::WithOptConstParam::unknown(
- future_data.generator_def_id,
- )),
+ def: ty::InstanceDef::Item(future_data.generator_def_id),
substs: future_data.substs,
}),
traits::ImplSource::Closure(closure_data) => {
@@ -234,15 +202,12 @@ fn resolve_associated_item<'tcx>(
_ => None,
},
traits::ImplSource::Object(ref data) => {
- if let Some(index) = traits::get_vtable_index_of_object_method(tcx, data, trait_item_id)
- {
- Some(Instance {
+ traits::get_vtable_index_of_object_method(tcx, data, trait_item_id).map(|index| {
+ Instance {
def: ty::InstanceDef::Virtual(trait_item_id, index),
substs: rcvr_substs,
- })
- } else {
- None
- }
+ }
+ })
}
traits::ImplSource::Builtin(..) => {
let lang_items = tcx.lang_items();
@@ -301,6 +266,5 @@ fn resolve_associated_item<'tcx>(
}
pub fn provide(providers: &mut ty::query::Providers) {
- *providers =
- ty::query::Providers { resolve_instance, resolve_instance_of_const_arg, ..*providers };
+ *providers = ty::query::Providers { resolve_instance, ..*providers };
}
diff --git a/compiler/rustc_ty_utils/src/layout_sanity_check.rs b/compiler/rustc_ty_utils/src/layout_sanity_check.rs
index a5311dbd1b7..ed513cb3c7f 100644
--- a/compiler/rustc_ty_utils/src/layout_sanity_check.rs
+++ b/compiler/rustc_ty_utils/src/layout_sanity_check.rs
@@ -285,7 +285,7 @@ pub(super) fn sanity_check_layout<'tcx>(
{
// These are never actually accessed anyway, so we can skip the coherence check
// for them. They also fail that check, since they have
- // `Aggregate`/`Uninhbaited` ABI even when the main type is
+ // `Aggregate`/`Uninhabited` ABI even when the main type is
// `Scalar`/`ScalarPair`. (Note that sometimes, variants with fields have size
// 0, and sometimes, variants without fields have non-0 size.)
continue;
diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs
index 2613445f39b..9d5a72a73cd 100644
--- a/compiler/rustc_ty_utils/src/lib.rs
+++ b/compiler/rustc_ty_utils/src/lib.rs
@@ -19,7 +19,7 @@ extern crate rustc_middle;
extern crate tracing;
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
-use rustc_macros::fluent_messages;
+use rustc_fluent_macro::fluent_messages;
use rustc_middle::ty::query::Providers;
mod abi;
diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs
index de7fd003176..5f436f7c9fd 100644
--- a/compiler/rustc_ty_utils/src/needs_drop.rs
+++ b/compiler/rustc_ty_utils/src/needs_drop.rs
@@ -243,7 +243,7 @@ fn drop_tys_helper<'tcx>(
} else {
let field_tys = adt_def.all_fields().map(|field| {
let r = tcx.type_of(field.did).subst(tcx, substs);
- debug!("drop_tys_helper: Subst into {:?} with {:?} gettng {:?}", field, substs, r);
+ debug!("drop_tys_helper: Subst into {:?} with {:?} getting {:?}", field, substs, r);
r
});
if only_significant {
diff --git a/compiler/rustc_ty_utils/src/structural_match.rs b/compiler/rustc_ty_utils/src/structural_match.rs
index a55bb7e7e90..9cb0fc10594 100644
--- a/compiler/rustc_ty_utils/src/structural_match.rs
+++ b/compiler/rustc_ty_utils/src/structural_match.rs
@@ -13,7 +13,7 @@ use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
/// 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 infcx = &tcx.infer_ctxt().build();
let cause = ObligationCause::dummy();
let ocx = ObligationCtxt::new(infcx);
diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs
index 3a053d4c6a9..371c6119122 100644
--- a/compiler/rustc_type_ir/src/fold.rs
+++ b/compiler/rustc_type_ir/src/fold.rs
@@ -16,8 +16,10 @@
//! - Types of interest, for which the methods delegate to the folder.
//! - All other types, including generic containers like `Vec` and `Option`.
//! It defines a "skeleton" of how they should be folded.
-//! - `TypeSuperFoldable`. This is implemented only for each type of interest,
-//! and defines the folding "skeleton" for these types.
+//! - `TypeSuperFoldable`. This is implemented only for recursive types of
+//! interest, and defines the folding "skeleton" for these types. (This
+//! excludes `Region` because it is non-recursive, i.e. it never contains
+//! other types of interest.)
//! - `TypeFolder`/`FallibleTypeFolder`. One of these is implemented for each
//! folder. This defines how types of interest are folded.
//!
@@ -72,9 +74,9 @@ pub trait TypeFoldable<I: Interner>: TypeVisitable<I> {
// This trait is implemented for types of interest.
pub trait TypeSuperFoldable<I: Interner>: TypeFoldable<I> {
- /// Provides a default fold for a type of interest. This should only be
- /// called within `TypeFolder` methods, when a non-custom traversal is
- /// desired for the value of the type of interest passed to that method.
+ /// Provides a default fold for a recursive type of interest. This should
+ /// only be called within `TypeFolder` methods, when a non-custom traversal
+ /// is desired for the value of the type of interest passed to that method.
/// For example, in `MyFolder::try_fold_ty(ty)`, it is valid to call
/// `ty.try_super_fold_with(self)`, but any other folding should be done
/// with `xyz.try_fold_with(self)`.
@@ -118,11 +120,11 @@ pub trait TypeFolder<I: Interner>: FallibleTypeFolder<I, Error = !> {
t.super_fold_with(self)
}
- fn fold_region(&mut self, r: I::Region) -> I::Region
- where
- I::Region: TypeSuperFoldable<I>,
- {
- r.super_fold_with(self)
+ // The default region folder is a no-op because `Region` is non-recursive
+ // and has no `super_visit_with` method to call. That also explains the
+ // lack of `I::Region: TypeSuperFoldable<I>` bound on this method.
+ fn fold_region(&mut self, r: I::Region) -> I::Region {
+ r
}
fn fold_const(&mut self, c: I::Const) -> I::Const
@@ -167,11 +169,11 @@ pub trait FallibleTypeFolder<I: Interner>: Sized {
t.try_super_fold_with(self)
}
- fn try_fold_region(&mut self, r: I::Region) -> Result<I::Region, Self::Error>
- where
- I::Region: TypeSuperFoldable<I>,
- {
- r.try_super_fold_with(self)
+ // The default region folder is a no-op because `Region` is non-recursive
+ // and has no `super_visit_with` method to call. That also explains the
+ // lack of `I::Region: TypeSuperFoldable<I>` bound on this method.
+ fn try_fold_region(&mut self, r: I::Region) -> Result<I::Region, Self::Error> {
+ Ok(r)
}
fn try_fold_const(&mut self, c: I::Const) -> Result<I::Const, Self::Error>
@@ -216,10 +218,7 @@ where
Ok(self.fold_ty(t))
}
- fn try_fold_region(&mut self, r: I::Region) -> Result<I::Region, !>
- where
- I::Region: TypeSuperFoldable<I>,
- {
+ fn try_fold_region(&mut self, r: I::Region) -> Result<I::Region, !> {
Ok(self.fold_region(r))
}
diff --git a/compiler/rustc_type_ir/src/macros.rs b/compiler/rustc_type_ir/src/macros.rs
index 6c181039730..8c3cb228322 100644
--- a/compiler/rustc_type_ir/src/macros.rs
+++ b/compiler/rustc_type_ir/src/macros.rs
@@ -33,144 +33,3 @@ macro_rules! TrivialTypeTraversalImpls {
)+
};
}
-
-macro_rules! EnumTypeTraversalImpl {
- (impl<$($p:tt),*> TypeFoldable<$tcx:tt> for $s:path {
- $($variants:tt)*
- } $(where $($wc:tt)*)*) => {
- impl<$($p),*> $crate::fold::TypeFoldable<$tcx> for $s
- $(where $($wc)*)*
- {
- fn try_fold_with<V: $crate::fold::FallibleTypeFolder<$tcx>>(
- self,
- folder: &mut V,
- ) -> ::std::result::Result<Self, V::Error> {
- EnumTypeTraversalImpl!(@FoldVariants(self, folder) input($($variants)*) output())
- }
- }
- };
-
- (impl<$($p:tt),*> TypeVisitable<$tcx:tt> for $s:path {
- $($variants:tt)*
- } $(where $($wc:tt)*)*) => {
- impl<$($p),*> $crate::visit::TypeVisitable<$tcx> for $s
- $(where $($wc)*)*
- {
- fn visit_with<V: $crate::visit::TypeVisitor<$tcx>>(
- &self,
- visitor: &mut V,
- ) -> ::std::ops::ControlFlow<V::BreakTy> {
- EnumTypeTraversalImpl!(@VisitVariants(self, visitor) input($($variants)*) output())
- }
- }
- };
-
- (@FoldVariants($this:expr, $folder:expr) input() output($($output:tt)*)) => {
- Ok(match $this {
- $($output)*
- })
- };
-
- (@FoldVariants($this:expr, $folder:expr)
- input( ($variant:path) ( $($variant_arg:ident),* ) , $($input:tt)*)
- output( $($output:tt)*) ) => {
- EnumTypeTraversalImpl!(
- @FoldVariants($this, $folder)
- input($($input)*)
- output(
- $variant ( $($variant_arg),* ) => {
- $variant (
- $($crate::fold::TypeFoldable::try_fold_with($variant_arg, $folder)?),*
- )
- }
- $($output)*
- )
- )
- };
-
- (@FoldVariants($this:expr, $folder:expr)
- input( ($variant:path) { $($variant_arg:ident),* $(,)? } , $($input:tt)*)
- output( $($output:tt)*) ) => {
- EnumTypeTraversalImpl!(
- @FoldVariants($this, $folder)
- input($($input)*)
- output(
- $variant { $($variant_arg),* } => {
- $variant {
- $($variant_arg: $crate::fold::TypeFoldable::fold_with(
- $variant_arg, $folder
- )?),* }
- }
- $($output)*
- )
- )
- };
-
- (@FoldVariants($this:expr, $folder:expr)
- input( ($variant:path), $($input:tt)*)
- output( $($output:tt)*) ) => {
- EnumTypeTraversalImpl!(
- @FoldVariants($this, $folder)
- input($($input)*)
- output(
- $variant => { $variant }
- $($output)*
- )
- )
- };
-
- (@VisitVariants($this:expr, $visitor:expr) input() output($($output:tt)*)) => {
- match $this {
- $($output)*
- }
- };
-
- (@VisitVariants($this:expr, $visitor:expr)
- input( ($variant:path) ( $($variant_arg:ident),* ) , $($input:tt)*)
- output( $($output:tt)*) ) => {
- EnumTypeTraversalImpl!(
- @VisitVariants($this, $visitor)
- input($($input)*)
- output(
- $variant ( $($variant_arg),* ) => {
- $($crate::visit::TypeVisitable::visit_with(
- $variant_arg, $visitor
- )?;)*
- ::std::ops::ControlFlow::Continue(())
- }
- $($output)*
- )
- )
- };
-
- (@VisitVariants($this:expr, $visitor:expr)
- input( ($variant:path) { $($variant_arg:ident),* $(,)? } , $($input:tt)*)
- output( $($output:tt)*) ) => {
- EnumTypeTraversalImpl!(
- @VisitVariants($this, $visitor)
- input($($input)*)
- output(
- $variant { $($variant_arg),* } => {
- $($crate::visit::TypeVisitable::visit_with(
- $variant_arg, $visitor
- )?;)*
- ::std::ops::ControlFlow::Continue(())
- }
- $($output)*
- )
- )
- };
-
- (@VisitVariants($this:expr, $visitor:expr)
- input( ($variant:path), $($input:tt)*)
- output( $($output:tt)*) ) => {
- EnumTypeTraversalImpl!(
- @VisitVariants($this, $visitor)
- input($($input)*)
- output(
- $variant => { ::std::ops::ControlFlow::Continue(()) }
- $($output)*
- )
- )
- };
-}
diff --git a/compiler/rustc_type_ir/src/structural_impls.rs b/compiler/rustc_type_ir/src/structural_impls.rs
index 3ebe241042f..c90c86b7690 100644
--- a/compiler/rustc_type_ir/src/structural_impls.rs
+++ b/compiler/rustc_type_ir/src/structural_impls.rs
@@ -70,30 +70,40 @@ impl<I: Interner, A: TypeVisitable<I>, B: TypeVisitable<I>, C: TypeVisitable<I>>
}
}
-EnumTypeTraversalImpl! {
- impl<I, T> TypeFoldable<I> for Option<T> {
- (Some)(a),
- (None),
- } where I: Interner, T: TypeFoldable<I>
-}
-EnumTypeTraversalImpl! {
- impl<I, T> TypeVisitable<I> for Option<T> {
- (Some)(a),
- (None),
- } where I: Interner, T: TypeVisitable<I>
-}
-
-EnumTypeTraversalImpl! {
- impl<I, T, E> TypeFoldable<I> for Result<T, E> {
- (Ok)(a),
- (Err)(a),
- } where I: Interner, T: TypeFoldable<I>, E: TypeFoldable<I>,
-}
-EnumTypeTraversalImpl! {
- impl<I, T, E> TypeVisitable<I> for Result<T, E> {
- (Ok)(a),
- (Err)(a),
- } where I: Interner, T: TypeVisitable<I>, E: TypeVisitable<I>,
+impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Option<T> {
+ fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
+ Ok(match self {
+ Some(v) => Some(v.try_fold_with(folder)?),
+ None => None,
+ })
+ }
+}
+
+impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Option<T> {
+ fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+ match self {
+ Some(v) => v.visit_with(visitor),
+ None => ControlFlow::Continue(()),
+ }
+ }
+}
+
+impl<I: Interner, T: TypeFoldable<I>, E: TypeFoldable<I>> TypeFoldable<I> for Result<T, E> {
+ fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
+ Ok(match self {
+ Ok(v) => Ok(v.try_fold_with(folder)?),
+ Err(e) => Err(e.try_fold_with(folder)?),
+ })
+ }
+}
+
+impl<I: Interner, T: TypeVisitable<I>, E: TypeVisitable<I>> TypeVisitable<I> for Result<T, E> {
+ fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+ match self {
+ Ok(v) => v.visit_with(visitor),
+ Err(e) => e.visit_with(visitor),
+ }
+ }
}
impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Rc<T> {
diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs
index 62e699eefd7..4c1f2dd0e53 100644
--- a/compiler/rustc_type_ir/src/sty.rs
+++ b/compiler/rustc_type_ir/src/sty.rs
@@ -203,6 +203,10 @@ pub enum TyKind<I: Interner> {
/// `for<'a, T> &'a (): Trait<T>` and then convert the introduced bound variables
/// back to inference variables in a new inference context when inside of the query.
///
+ /// It is conventional to render anonymous bound types like `^N` or `^D_N`,
+ /// where `N` is the bound variable's anonymous index into the binder, and
+ /// `D` is the debruijn index, or totally omitted if the debruijn index is zero.
+ ///
/// See the `rustc-dev-guide` for more details about
/// [higher-ranked trait bounds][1] and [canonical queries][2].
///
@@ -212,6 +216,12 @@ pub enum TyKind<I: Interner> {
/// A placeholder type, used during higher ranked subtyping to instantiate
/// bound variables.
+ ///
+ /// It is conventional to render anonymous placeholer types like `!N` or `!U_N`,
+ /// where `N` is the placeholder variable's anonymous index (which corresponds
+ /// to the bound variable's index from the binder from which it was instantiated),
+ /// and `U` is the universe index in which it is instantiated, or totally omitted
+ /// if the universe index is zero.
Placeholder(I::PlaceholderType),
/// A type variable used during type checking.
diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs
index 62239fd2006..878c7aec6c1 100644
--- a/compiler/rustc_type_ir/src/visit.rs
+++ b/compiler/rustc_type_ir/src/visit.rs
@@ -13,8 +13,11 @@
//! - Types of interest, for which the methods delegate to the visitor.
//! - All other types, including generic containers like `Vec` and `Option`.
//! It defines a "skeleton" of how they should be visited.
-//! - `TypeSuperVisitable`. This is implemented only for each type of interest,
-//! and defines the visiting "skeleton" for these types.
+//! - `TypeSuperVisitable`. This is implemented only for recursive types of
+//! interest, and defines the visiting "skeleton" for these types. (This
+//! excludes `Region` because it is non-recursive, i.e. it never contains
+//! other types of interest.)
+//!
//! - `TypeVisitor`. This is implemented for each visitor. This defines how
//! types of interest are visited.
//!
@@ -62,12 +65,13 @@ pub trait TypeVisitable<I: Interner>: fmt::Debug + Clone {
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>;
}
+// This trait is implemented for types of interest.
pub trait TypeSuperVisitable<I: Interner>: TypeVisitable<I> {
- /// Provides a default visit for a type of interest. This should only be
- /// called within `TypeVisitor` methods, when a non-custom traversal is
- /// desired for the value of the type of interest passed to that method.
- /// For example, in `MyVisitor::visit_ty(ty)`, it is valid to call
- /// `ty.super_visit_with(self)`, but any other visiting should be done
+ /// Provides a default visit for a recursive type of interest. This should
+ /// only be called within `TypeVisitor` methods, when a non-custom
+ /// traversal is desired for the value of the type of interest passed to
+ /// that method. For example, in `MyVisitor::visit_ty(ty)`, it is valid to
+ /// call `ty.super_visit_with(self)`, but any other visiting should be done
/// with `xyz.visit_with(self)`.
fn super_visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>;
}
@@ -92,11 +96,11 @@ pub trait TypeVisitor<I: Interner>: Sized {
t.super_visit_with(self)
}
- fn visit_region(&mut self, r: I::Region) -> ControlFlow<Self::BreakTy>
- where
- I::Region: TypeSuperVisitable<I>,
- {
- r.super_visit_with(self)
+ // The default region visitor is a no-op because `Region` is non-recursive
+ // and has no `super_visit_with` method to call. That also explains the
+ // lack of `I::Region: TypeSuperVisitable<I>` bound.
+ fn visit_region(&mut self, _r: I::Region) -> ControlFlow<Self::BreakTy> {
+ ControlFlow::Continue(())
}
fn visit_const(&mut self, c: I::Const) -> ControlFlow<Self::BreakTy>