diff options
Diffstat (limited to 'compiler/rustc_mir_build/src')
22 files changed, 348 insertions, 285 deletions
diff --git a/compiler/rustc_mir_build/src/builder/block.rs b/compiler/rustc_mir_build/src/builder/block.rs index ba63a97de89..7c76e02fcef 100644 --- a/compiler/rustc_mir_build/src/builder/block.rs +++ b/compiler/rustc_mir_build/src/builder/block.rs @@ -244,7 +244,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { StmtKind::Let { remainder_scope, init_scope, - ref pattern, + pattern, initializer, lint_level, else_block: None, @@ -331,8 +331,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let expr = &this.thir[expr_id]; let tail_result_is_ignored = destination_ty.is_unit() || this.block_context.currently_ignores_tail_results(); - this.block_context - .push(BlockFrame::TailExpr { tail_result_is_ignored, span: expr.span }); + this.block_context.push(BlockFrame::TailExpr { + info: BlockTailInfo { tail_result_is_ignored, span: expr.span }, + }); block = this.expr_into_dest(destination, block, expr_id).into_block(); let popped = this.block_context.pop(); diff --git a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs index eab414e150f..19669021eef 100644 --- a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs @@ -1,6 +1,5 @@ use rustc_abi::{FieldIdx, VariantIdx}; use rustc_middle::mir::interpret::Scalar; -use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::*; use rustc_middle::thir::*; use rustc_middle::ty; diff --git a/compiler/rustc_mir_build/src/builder/expr/as_operand.rs b/compiler/rustc_mir_build/src/builder/expr/as_operand.rs index 63e9b1dc6cd..2059610ee47 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_operand.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_operand.rs @@ -142,7 +142,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Overwrite temp local info if we have something more interesting to record. if !matches!(local_info, LocalInfo::Boring) { let decl_info = - this.local_decls[operand].local_info.as_mut().assert_crate_local(); + this.local_decls[operand].local_info.as_mut().unwrap_crate_local(); if let LocalInfo::Boring | LocalInfo::BlockTailTemp(_) = **decl_info { **decl_info = local_info; } diff --git a/compiler/rustc_mir_build/src/builder/expr/as_place.rs b/compiler/rustc_mir_build/src/builder/expr/as_place.rs index 308ca442b40..581f45db6c4 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_place.rs @@ -216,11 +216,11 @@ fn to_upvars_resolved_place_builder<'tcx>( /// Supports only HIR projection kinds that represent a path that might be /// captured by a closure or a coroutine, i.e., an `Index` or a `Subslice` /// projection kinds are unsupported. -fn strip_prefix<'a, 'tcx>( +fn strip_prefix<'tcx>( mut base_ty: Ty<'tcx>, - projections: &'a [PlaceElem<'tcx>], + projections: &[PlaceElem<'tcx>], prefix_projections: &[HirProjection<'tcx>], -) -> impl Iterator<Item = PlaceElem<'tcx>> + 'a { +) -> impl Iterator<Item = PlaceElem<'tcx>> { let mut iter = projections .iter() .copied() diff --git a/compiler/rustc_mir_build/src/builder/expr/as_temp.rs b/compiler/rustc_mir_build/src/builder/expr/as_temp.rs index 2927f5b0c45..0bd61168fba 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_temp.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_temp.rs @@ -85,7 +85,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { _ => LocalInfo::Boring, }; - **local_decl.local_info.as_mut().assert_crate_local() = local_info; + **local_decl.local_info.as_mut().unwrap_crate_local() = local_info; this.local_decls.push(local_decl) }; debug!(?temp); diff --git a/compiler/rustc_mir_build/src/builder/expr/into.rs b/compiler/rustc_mir_build/src/builder/expr/into.rs index 65dd061003d..72443e2f60d 100644 --- a/compiler/rustc_mir_build/src/builder/expr/into.rs +++ b/compiler/rustc_mir_build/src/builder/expr/into.rs @@ -482,15 +482,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }), } } - thir::InlineAsmOperand::SymFn { value, span } => { - mir::InlineAsmOperand::SymFn { - value: Box::new(ConstOperand { - span, - user_ty: None, - const_: value, - }), - } - } + thir::InlineAsmOperand::SymFn { value } => mir::InlineAsmOperand::SymFn { + value: Box::new(this.as_constant(&this.thir[value])), + }, thir::InlineAsmOperand::SymStatic { def_id } => { mir::InlineAsmOperand::SymStatic { def_id } } @@ -518,10 +512,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } let asm_macro = match asm_macro { - AsmMacro::Asm => InlineAsmMacro::Asm, - AsmMacro::GlobalAsm => { - span_bug!(expr_span, "unexpected global_asm! in inline asm") - } + AsmMacro::Asm | AsmMacro::GlobalAsm => InlineAsmMacro::Asm, AsmMacro::NakedAsm => InlineAsmMacro::NakedAsm, }; diff --git a/compiler/rustc_mir_build/src/builder/expr/stmt.rs b/compiler/rustc_mir_build/src/builder/expr/stmt.rs index 58090d3748b..7f8a0a34c31 100644 --- a/compiler/rustc_mir_build/src/builder/expr/stmt.rs +++ b/compiler/rustc_mir_build/src/builder/expr/stmt.rs @@ -164,8 +164,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } this.block_context.push(BlockFrame::TailExpr { - tail_result_is_ignored: true, - span: expr.span, + info: BlockTailInfo { tail_result_is_ignored: true, span: expr.span }, }); Some(expr.span) } else { diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs index ee331713736..10b43390eb2 100644 --- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use rustc_middle::mir::*; -use rustc_middle::thir::{self, *}; +use rustc_middle::thir::*; use rustc_middle::ty::{self, Ty, TypeVisitableExt}; use crate::builder::Builder; @@ -134,7 +134,7 @@ impl<'tcx> MatchPairTree<'tcx> { PatKind::Constant { value } => TestCase::Constant { value }, PatKind::AscribeUserType { - ascription: thir::Ascription { ref annotation, variance }, + ascription: Ascription { ref annotation, variance }, ref subpattern, .. } => { diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs index ed577f7adeb..d05d5b151ff 100644 --- a/compiler/rustc_mir_build/src/builder/matches/mod.rs +++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs @@ -722,7 +722,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if let LocalInfo::User(BindingForm::Var(VarBindingForm { opt_match_place: Some((ref mut match_place, _)), .. - })) = **self.local_decls[local].local_info.as_mut().assert_crate_local() + })) = **self.local_decls[local].local_info.as_mut().unwrap_crate_local() { *match_place = Some(place); } else { @@ -926,12 +926,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Note that the variance doesn't apply here, as we are tracking the effect // of `user_ty` on any bindings contained with subpattern. - let projection = UserTypeProjection { - base: self.canonical_user_type_annotations.push(annotation.clone()), - projs: Vec::new(), - }; - let subpattern_user_ty = - pattern_user_ty.push_projection(&projection, annotation.span); + let base_user_ty = self.canonical_user_type_annotations.push(annotation.clone()); + let subpattern_user_ty = pattern_user_ty.push_user_type(base_user_ty); self.visit_primary_bindings(subpattern, subpattern_user_ty, f) } diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs index e04c70b5883..94955954934 100644 --- a/compiler/rustc_mir_build/src/builder/mod.rs +++ b/compiler/rustc_mir_build/src/builder/mod.rs @@ -61,7 +61,9 @@ pub fn build_mir<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Body<'tcx> { Ok((thir, expr)) => { let build_mir = |thir: &Thir<'tcx>| match thir.body_type { thir::BodyTy::Fn(fn_sig) => construct_fn(tcx, def, thir, expr, fn_sig), - thir::BodyTy::Const(ty) => construct_const(tcx, def, thir, expr, ty), + thir::BodyTy::Const(ty) | thir::BodyTy::GlobalAsm(ty) => { + construct_const(tcx, def, thir, expr, ty) + } }; // this must run before MIR dump, because @@ -112,16 +114,7 @@ enum BlockFrame { /// Evaluation is currently within the tail expression of a block. /// /// Example: `{ STMT_1; STMT_2; EXPR }` - TailExpr { - /// If true, then the surrounding context of the block ignores - /// the result of evaluating the block's tail expression. - /// - /// Example: `let _ = { STMT_1; EXPR };` - tail_result_is_ignored: bool, - - /// `Span` of the tail expression. - span: Span, - }, + TailExpr { info: BlockTailInfo }, /// Generic mark meaning that the block occurred as a subexpression /// where the result might be used. @@ -277,9 +270,7 @@ impl BlockContext { match bf { BlockFrame::SubExpr => continue, BlockFrame::Statement { .. } => break, - &BlockFrame::TailExpr { tail_result_is_ignored, span } => { - return Some(BlockTailInfo { tail_result_is_ignored, span }); - } + &BlockFrame::TailExpr { info } => return Some(info), } } @@ -302,9 +293,9 @@ impl BlockContext { // otherwise: use accumulated is_ignored state. Some( - BlockFrame::TailExpr { tail_result_is_ignored: ignored, .. } - | BlockFrame::Statement { ignores_expr_result: ignored }, - ) => *ignored, + BlockFrame::TailExpr { info: BlockTailInfo { tail_result_is_ignored: ign, .. } } + | BlockFrame::Statement { ignores_expr_result: ign }, + ) => *ign, } } } @@ -465,11 +456,10 @@ fn construct_fn<'tcx>( assert_eq!(expr.as_usize(), thir.exprs.len() - 1); // Figure out what primary body this item has. - let body = tcx.hir().body_owned_by(fn_def); + let body = 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) + .hir_fn_decl_by_hir_id(fn_id) .unwrap_or_else(|| span_bug!(span, "can't build MIR for {:?}", fn_def)) .output .span(); @@ -588,6 +578,7 @@ fn construct_const<'a, 'tcx>( let span = tcx.def_span(def); (span, span) } + Node::Item(hir::Item { kind: hir::ItemKind::GlobalAsm { .. }, span, .. }) => (*span, *span), _ => span_bug!(tcx.def_span(def), "can't build MIR for {:?}", def), }; @@ -758,7 +749,7 @@ 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), + tcx.hir_body_owner_kind(def), hir::BodyOwnerKind::Const { .. } | hir::BodyOwnerKind::Static(_) ); @@ -968,7 +959,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } => { self.local_decls[local].mutability = mutability; self.local_decls[local].source_info.scope = self.source_scope; - **self.local_decls[local].local_info.as_mut().assert_crate_local() = + **self.local_decls[local].local_info.as_mut().unwrap_crate_local() = if let Some(kind) = param.self_kind { LocalInfo::User(BindingForm::ImplicitSelf(kind)) } else { @@ -1033,7 +1024,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let parent_id = self.source_scopes[original_source_scope] .local_data .as_ref() - .assert_crate_local() + .unwrap_crate_local() .lint_root; self.maybe_new_source_scope(pattern_span, arg_hir_id, parent_id); } diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs index d3551ea3a97..81561239491 100644 --- a/compiler/rustc_mir_build/src/builder/scope.rs +++ b/compiler/rustc_mir_build/src/builder/scope.rs @@ -604,7 +604,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let source_scope = self.source_scope; if let LintLevel::Explicit(current_hir_id) = lint_level { let parent_id = - self.source_scopes[source_scope].local_data.as_ref().assert_crate_local().lint_root; + self.source_scopes[source_scope].local_data.as_ref().unwrap_crate_local().lint_root; self.maybe_new_source_scope(region_scope.1.span, current_hir_id, parent_id); } self.push_scope(region_scope); @@ -992,7 +992,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { lint_root: if let LintLevel::Explicit(lint_root) = lint_level { lint_root } else { - self.source_scopes[parent].local_data.as_ref().assert_crate_local().lint_root + self.source_scopes[parent].local_data.as_ref().unwrap_crate_local().lint_root }, }; self.source_scopes.push(SourceScopeData { diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 2b9b948763f..c2eafd0a74e 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -2,6 +2,7 @@ use std::borrow::Cow; use std::mem; use std::ops::Bound; +use rustc_ast::AsmMacro; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::DiagArgValue; use rustc_hir::def::DefKind; @@ -554,12 +555,12 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { _ => self.requires_unsafe(expr.span, UseOfExternStatic), } } - } else if self.thir[arg].ty.is_unsafe_ptr() { + } else if self.thir[arg].ty.is_raw_ptr() { self.requires_unsafe(expr.span, DerefOfRawPointer); } } ExprKind::InlineAsm(box InlineAsmExpr { - asm_macro: _, + asm_macro: AsmMacro::Asm | AsmMacro::NakedAsm, ref operands, template: _, options: _, @@ -583,7 +584,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { } Out { expr: None, reg: _, late: _ } | Const { value: _, span: _ } - | SymFn { value: _, span: _ } + | SymFn { value: _ } | SymStatic { def_id: _ } => {} Label { block } => { // Label blocks are safe context. @@ -751,7 +752,7 @@ impl UnsafeOpKind { span: Span, suggest_unsafe_block: bool, ) { - let parent_id = tcx.hir().get_parent_item(hir_id); + let parent_id = tcx.hir_get_parent_item(hir_id); let parent_owner = tcx.hir_owner_node(parent_id); let should_suggest = parent_owner.fn_sig().is_some_and(|sig| { // Do not suggest for safe target_feature functions @@ -759,7 +760,7 @@ impl UnsafeOpKind { }); let unsafe_not_inherited_note = if should_suggest { suggest_unsafe_block.then(|| { - let body_span = tcx.hir().body(parent_owner.body_id().unwrap()).value.span; + let body_span = tcx.hir_body(parent_owner.body_id().unwrap()).value.span; UnsafeNotInheritedLintNote { signature_span: tcx.def_span(parent_id.def_id), body_span, @@ -921,13 +922,13 @@ impl UnsafeOpKind { hir_context: HirId, unsafe_op_in_unsafe_fn_allowed: bool, ) { - let note_non_inherited = tcx.hir().parent_iter(hir_context).find(|(id, node)| { + let note_non_inherited = tcx.hir_parent_iter(hir_context).find(|(id, node)| { if let hir::Node::Expr(block) = node && let hir::ExprKind::Block(block, _) = block.kind && let hir::BlockCheckMode::UnsafeBlock(_) = block.rules { true - } else if let Some(sig) = tcx.hir().fn_sig_by_hir_id(*id) + } else if let Some(sig) = tcx.hir_fn_sig_by_hir_id(*id) && matches!(sig.header.safety, hir::HeaderSafety::Normal(hir::Safety::Unsafe)) { true @@ -1145,7 +1146,7 @@ pub(crate) fn check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) { let thir = &thir.steal(); let hir_id = tcx.local_def_id_to_hir_id(def); - let safety_context = tcx.hir().fn_sig_by_hir_id(hir_id).map_or(SafetyContext::Safe, |fn_sig| { + let safety_context = tcx.hir_fn_sig_by_hir_id(hir_id).map_or(SafetyContext::Safe, |fn_sig| { match fn_sig.header.safety { // We typeck the body as safe, but otherwise treat it as unsafe everywhere else. // Call sites to other SafeTargetFeatures functions are checked explicitly and don't need diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 07bdc59756a..f1753be845d 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -601,8 +601,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NonExhaustivePatternsTypeNo let def_span = self .cx .tcx - .hir() - .get_if_local(def.did()) + .hir_get_if_local(def.did()) .and_then(|node| node.ident()) .map(|ident| ident.span) .unwrap_or_else(|| self.cx.tcx.def_span(def.did())); @@ -1113,9 +1112,6 @@ pub(crate) struct Rust2024IncompatiblePatSugg { pub(crate) suggestion: Vec<(Span, String)>, pub(crate) ref_pattern_count: usize, pub(crate) binding_mode_count: usize, - /// Internal state: the ref-mutability of the default binding mode at the subpattern being - /// lowered, with the span where it was introduced. `None` for a by-value default mode. - pub(crate) default_mode_span: Option<(Span, ty::Mutability)>, /// Labels for where incompatibility-causing by-ref default binding modes were introduced. pub(crate) default_mode_labels: FxIndexMap<Span, ty::Mutability>, } diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index f303053390c..b3210813703 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -48,7 +48,7 @@ pub(crate) fn lit_to_const<'tcx>( ty::ValTree::from_raw_bytes(tcx, bytes) } (ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => { - ty::ValTree::from_scalar_int((*n).into()) + ty::ValTree::from_scalar_int(tcx, (*n).into()) } (ast::LitKind::CStr(data, _), ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::CStr)) => { @@ -57,23 +57,23 @@ pub(crate) fn lit_to_const<'tcx>( } (ast::LitKind::Int(n, _), ty::Uint(ui)) if !neg => { let scalar_int = trunc(n.get(), *ui); - ty::ValTree::from_scalar_int(scalar_int) + ty::ValTree::from_scalar_int(tcx, scalar_int) } (ast::LitKind::Int(n, _), ty::Int(i)) => { let scalar_int = trunc( if neg { (n.get() as i128).overflowing_neg().0 as u128 } else { n.get() }, i.to_unsigned(), ); - ty::ValTree::from_scalar_int(scalar_int) + ty::ValTree::from_scalar_int(tcx, scalar_int) } - (ast::LitKind::Bool(b), ty::Bool) => ty::ValTree::from_scalar_int((*b).into()), + (ast::LitKind::Bool(b), ty::Bool) => ty::ValTree::from_scalar_int(tcx, (*b).into()), (ast::LitKind::Float(n, _), ty::Float(fty)) => { let bits = parse_float_into_scalar(*n, *fty, neg).unwrap_or_else(|| { tcx.dcx().bug(format!("couldn't parse float literal: {:?}", lit_input.lit)) }); - ty::ValTree::from_scalar_int(bits) + ty::ValTree::from_scalar_int(tcx, bits) } - (ast::LitKind::Char(c), ty::Char) => ty::ValTree::from_scalar_int((*c).into()), + (ast::LitKind::Char(c), ty::Char) => ty::ValTree::from_scalar_int(tcx, (*c).into()), (ast::LitKind::Err(guar), _) => return ty::Const::new_error(tcx, *guar), _ => return ty::Const::new_misc_error(tcx), }; diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 54da6924db4..88877d05ffa 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -429,9 +429,7 @@ impl<'tcx> ThirBuildCx<'tcx> { let user_provided_types = self.typeck_results.user_provided_types(); let user_ty = user_provided_types.get(fun.hir_id).copied().map(|mut u_ty| { - if let ty::UserTypeKind::TypeOf(ref mut did, _) = - &mut u_ty.value.kind - { + if let ty::UserTypeKind::TypeOf(did, _) = &mut u_ty.value.kind { *did = adt_def.did(); } Box::new(u_ty) @@ -739,13 +737,8 @@ impl<'tcx> ThirBuildCx<'tcx> { InlineAsmOperand::Const { value, span } } - hir::InlineAsmOperand::SymFn { ref anon_const } => { - let value = - mir::Const::from_unevaluated(tcx, anon_const.def_id.to_def_id()) - .instantiate_identity(); - let span = tcx.def_span(anon_const.def_id); - - InlineAsmOperand::SymFn { value, span } + hir::InlineAsmOperand::SymFn { expr } => { + InlineAsmOperand::SymFn { value: self.mirror_expr(expr) } } hir::InlineAsmOperand::SymStatic { path: _, def_id } => { InlineAsmOperand::SymStatic { def_id } @@ -828,7 +821,6 @@ impl<'tcx> ThirBuildCx<'tcx> { }, hir::ExprKind::Match(discr, arms, match_source) => ExprKind::Match { scrutinee: self.mirror_expr(discr), - scrutinee_hir_id: discr.hir_id, arms: arms.iter().map(|a| self.convert_arm(a)).collect(), match_source, }, diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index a01609012b8..2e069cae426 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -22,8 +22,7 @@ pub(crate) fn thir_body( tcx: TyCtxt<'_>, owner_def: LocalDefId, ) -> Result<(&Steal<Thir<'_>>, ExprId), ErrorGuaranteed> { - let hir = tcx.hir(); - let body = hir.body_owned_by(owner_def); + let body = tcx.hir_body_owned_by(owner_def); let mut cx = ThirBuildCx::new(tcx, owner_def); if let Some(reported) = cx.typeck_results.tainted_by_errors { return Err(reported); @@ -31,7 +30,7 @@ pub(crate) fn thir_body( let expr = cx.mirror_expr(body.value); let owner_id = tcx.local_def_id_to_hir_id(owner_def); - if let Some(fn_decl) = hir.fn_decl_by_hir_id(owner_id) { + if let Some(fn_decl) = tcx.hir_fn_decl_by_hir_id(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(); @@ -77,23 +76,29 @@ impl<'tcx> ThirBuildCx<'tcx> { let hir = tcx.hir(); let hir_id = tcx.local_def_id_to_hir_id(def); - 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]) - } else { - // Get the revealed type of this const. This is *not* the adjusted - // type of its body, which may be a subtype of this type. For - // example: - // - // fn foo(_: &()) {} - // static X: fn(&'static ()) = foo; - // - // The adjusted type of the body of X is `for<'a> fn(&'a ())` which - // is not the same as the type of X. We need the type of the return - // place to be the type of the constant because NLL typeck will - // equate them. - BodyTy::Const(typeck_results.node_type(hir_id)) + let body_type = match tcx.hir_body_owner_kind(def) { + rustc_hir::BodyOwnerKind::Fn | rustc_hir::BodyOwnerKind::Closure => { + // fetch the fully liberated fn signature (that is, all bound + // types/lifetimes replaced) + BodyTy::Fn(typeck_results.liberated_fn_sigs()[hir_id]) + } + rustc_hir::BodyOwnerKind::Const { .. } | rustc_hir::BodyOwnerKind::Static(_) => { + // Get the revealed type of this const. This is *not* the adjusted + // type of its body, which may be a subtype of this type. For + // example: + // + // fn foo(_: &()) {} + // static X: fn(&'static ()) = foo; + // + // The adjusted type of the body of X is `for<'a> fn(&'a ())` which + // is not the same as the type of X. We need the type of the return + // place to be the type of the constant because NLL typeck will + // equate them. + BodyTy::Const(typeck_results.node_type(hir_id)) + } + rustc_hir::BodyOwnerKind::GlobalAsm => { + BodyTy::GlobalAsm(typeck_results.node_type(hir_id)) + } }; Self { @@ -160,12 +165,12 @@ impl<'tcx> ThirBuildCx<'tcx> { }) } - fn explicit_params<'a>( - &'a mut self, + fn explicit_params( + &mut self, owner_id: HirId, fn_decl: &'tcx hir::FnDecl<'tcx>, body: &'tcx hir::Body<'tcx>, - ) -> impl Iterator<Item = Param<'tcx>> + 'a { + ) -> impl Iterator<Item = Param<'tcx>> { let fn_sig = self.typeck_results.liberated_fn_sigs()[owner_id]; body.params.iter().enumerate().map(move |(index, param)| { 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 697cb7cf37a..d60ae6484af 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -10,7 +10,6 @@ use rustc_hir::{self as hir, BindingMode, ByRef, HirId}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::Level; use rustc_middle::bug; -use rustc_middle::middle::limits::get_limit_size; use rustc_middle::thir::visit::Visitor; use rustc_middle::thir::*; use rustc_middle::ty::print::with_no_trimmed_paths; @@ -25,7 +24,7 @@ use rustc_session::lint::builtin::{ }; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::hygiene::DesugaringKind; -use rustc_span::{Ident, Span, sym}; +use rustc_span::{Ident, Span}; use rustc_trait_selection::infer::InferCtxtExt; use tracing::instrument; @@ -152,7 +151,7 @@ impl<'p, 'tcx> Visitor<'p, 'tcx> for MatchVisitor<'p, 'tcx> { } return; } - ExprKind::Match { scrutinee, scrutinee_hir_id: _, box ref arms, match_source } => { + ExprKind::Match { scrutinee, box ref arms, match_source } => { self.check_match(scrutinee, arms, match_source, ex.span); } ExprKind::Let { box ref pat, expr } => { @@ -404,18 +403,11 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { arms: &[MatchArm<'p, 'tcx>], scrut_ty: Ty<'tcx>, ) -> Result<UsefulnessReport<'p, 'tcx>, ErrorGuaranteed> { - let pattern_complexity_limit = - get_limit_size(cx.tcx.hir().krate_attrs(), cx.tcx.sess, sym::pattern_complexity); - let report = rustc_pattern_analysis::rustc::analyze_match( - &cx, - &arms, - scrut_ty, - pattern_complexity_limit, - ) - .map_err(|err| { - self.error = Err(err); - err - })?; + let report = + rustc_pattern_analysis::rustc::analyze_match(&cx, &arms, scrut_ty).map_err(|err| { + self.error = Err(err); + err + })?; // Warn unreachable subpatterns. for (arm, is_useful) in report.arm_usefulness.iter() { @@ -1049,7 +1041,7 @@ fn find_fallback_pattern_typo<'tcx>( let mut imported = vec![]; let mut imported_spans = vec![]; let (infcx, param_env) = cx.tcx.infer_ctxt().build_with_typing_env(cx.typing_env); - let parent = cx.tcx.hir().get_parent_item(hir_id); + let parent = cx.tcx.hir_get_parent_item(hir_id); for item in cx.tcx.hir_crate_items(()).free_items() { if let DefKind::Use = cx.tcx.def_kind(item.owner_id) { @@ -1105,7 +1097,7 @@ fn find_fallback_pattern_typo<'tcx>( } } if let Some((i, &const_name)) = - accessible.iter().enumerate().find(|(_, &const_name)| const_name == name) + accessible.iter().enumerate().find(|&(_, &const_name)| const_name == name) { // The pattern name is an exact match, so the pattern needed to be imported. lint.wanted_constant = Some(WantedConstant { @@ -1123,7 +1115,7 @@ fn find_fallback_pattern_typo<'tcx>( const_path: name.to_string(), }); } else if let Some(i) = - imported.iter().enumerate().find(|(_, &const_name)| const_name == name).map(|(i, _)| i) + imported.iter().enumerate().find(|&(_, &const_name)| const_name == name).map(|(i, _)| i) { // The const with the exact name wasn't re-exported from an import in this // crate, we point at the import. @@ -1145,7 +1137,7 @@ fn find_fallback_pattern_typo<'tcx>( } else { // Look for local bindings for people that might have gotten confused with how // `let` and `const` works. - for (_, node) in cx.tcx.hir().parent_iter(hir_id) { + for (_, node) in cx.tcx.hir_parent_iter(hir_id) { match node { hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Let(let_stmt), .. }) => { if let hir::PatKind::Binding(_, _, binding_name, _) = let_stmt.pat.kind { @@ -1498,7 +1490,7 @@ fn report_adt_defined_here<'tcx>( return None; }; let adt_def_span = - tcx.hir().get_if_local(def.did()).and_then(|node| node.ident()).map(|ident| ident.span); + tcx.hir_get_if_local(def.did()).and_then(|node| node.ident()).map(|ident| ident.span); let adt_def_span = if point_at_non_local_ty { adt_def_span.unwrap_or_else(|| tcx.def_span(def.did())) } else { 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 551ec5cf4e9..667d59d858e 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 @@ -148,7 +148,7 @@ impl<'tcx> ConstToPat<'tcx> { if let ty::GenericArgKind::Type(ty) = arg.unpack() && let ty::Param(param_ty) = ty.kind() { - let def_id = self.tcx.hir().enclosing_body_owner(self.id); + let def_id = self.tcx.hir_enclosing_body_owner(self.id); let generics = self.tcx.generics_of(def_id); let param = generics.type_param(*param_ty, self.tcx); let span = self.tcx.def_span(param.def_id); diff --git a/compiler/rustc_mir_build/src/thir/pattern/migration.rs b/compiler/rustc_mir_build/src/thir/pattern/migration.rs new file mode 100644 index 00000000000..bd7787b643d --- /dev/null +++ b/compiler/rustc_mir_build/src/thir/pattern/migration.rs @@ -0,0 +1,182 @@ +//! Automatic migration of Rust 2021 patterns to a form valid in both Editions 2021 and 2024. + +use rustc_data_structures::fx::FxIndexMap; +use rustc_errors::MultiSpan; +use rustc_hir::{BindingMode, ByRef, HirId, Mutability}; +use rustc_lint as lint; +use rustc_middle::span_bug; +use rustc_middle::ty::{self, Rust2024IncompatiblePatInfo, Ty, TyCtxt}; +use rustc_span::{Ident, Span}; + +use crate::errors::{Rust2024IncompatiblePat, Rust2024IncompatiblePatSugg}; +use crate::fluent_generated as fluent; + +/// For patterns flagged for migration during HIR typeck, this handles constructing and emitting +/// a diagnostic suggestion. +pub(super) struct PatMigration<'a> { + suggestion: Vec<(Span, String)>, + ref_pattern_count: usize, + binding_mode_count: usize, + /// Internal state: the ref-mutability of the default binding mode at the subpattern being + /// lowered, with the span where it was introduced. `None` for a by-value default mode. + default_mode_span: Option<(Span, ty::Mutability)>, + /// Labels for where incompatibility-causing by-ref default binding modes were introduced. + // FIXME(ref_pat_eat_one_layer_2024_structural): To track the default binding mode, we duplicate + // logic from HIR typeck (in order to avoid needing to store all changes to the dbm in + // TypeckResults). Since the default binding mode acts differently under this feature gate, the + // labels will be wrong. + default_mode_labels: FxIndexMap<Span, Mutability>, + /// Information collected from typeck, including spans for subpatterns invalid in Rust 2024. + info: &'a Rust2024IncompatiblePatInfo, +} + +impl<'a> PatMigration<'a> { + pub(super) fn new(info: &'a Rust2024IncompatiblePatInfo) -> Self { + PatMigration { + suggestion: Vec::new(), + ref_pattern_count: 0, + binding_mode_count: 0, + default_mode_span: None, + default_mode_labels: Default::default(), + info, + } + } + + /// On Rust 2024, this emits a hard error. On earlier Editions, this emits the + /// future-incompatibility lint `rust_2024_incompatible_pat`. + pub(super) fn emit<'tcx>(self, tcx: TyCtxt<'tcx>, pat_id: HirId) { + let mut spans = + MultiSpan::from_spans(self.info.primary_labels.iter().map(|(span, _)| *span).collect()); + for (span, label) in self.info.primary_labels.iter() { + spans.push_span_label(*span, label.clone()); + } + let sugg = Rust2024IncompatiblePatSugg { + suggest_eliding_modes: self.info.suggest_eliding_modes, + suggestion: self.suggestion, + ref_pattern_count: self.ref_pattern_count, + binding_mode_count: self.binding_mode_count, + default_mode_labels: self.default_mode_labels, + }; + // If a relevant span is from at least edition 2024, this is a hard error. + let is_hard_error = spans.primary_spans().iter().any(|span| span.at_least_rust_2024()); + if is_hard_error { + let mut err = + tcx.dcx().struct_span_err(spans, fluent::mir_build_rust_2024_incompatible_pat); + if let Some(info) = lint::builtin::RUST_2024_INCOMPATIBLE_PAT.future_incompatible { + // provide the same reference link as the lint + err.note(format!("for more information, see {}", info.reference)); + } + err.arg("bad_modifiers", self.info.bad_modifiers); + err.arg("bad_ref_pats", self.info.bad_ref_pats); + err.arg("is_hard_error", true); + err.subdiagnostic(sugg); + err.emit(); + } else { + tcx.emit_node_span_lint( + lint::builtin::RUST_2024_INCOMPATIBLE_PAT, + pat_id, + spans, + Rust2024IncompatiblePat { + sugg, + bad_modifiers: self.info.bad_modifiers, + bad_ref_pats: self.info.bad_ref_pats, + is_hard_error, + }, + ); + } + } + + /// Tracks when we're lowering a pattern that implicitly dereferences the scrutinee. + /// This should only be called when the pattern type adjustments list `adjustments` is + /// non-empty. Returns the prior default binding mode; this should be followed by a call to + /// [`PatMigration::leave_ref`] to restore it when we leave the pattern. + pub(super) fn visit_implicit_derefs<'tcx>( + &mut self, + pat_span: Span, + adjustments: &[Ty<'tcx>], + ) -> Option<(Span, Mutability)> { + let implicit_deref_mutbls = adjustments.iter().map(|ref_ty| { + let &ty::Ref(_, _, mutbl) = ref_ty.kind() else { + span_bug!(pat_span, "pattern implicitly dereferences a non-ref type"); + }; + mutbl + }); + + if !self.info.suggest_eliding_modes { + // If we can't fix the pattern by eliding modifiers, we'll need to make the pattern + // fully explicit. i.e. we'll need to suggest reference patterns for this. + let suggestion_str: String = + implicit_deref_mutbls.clone().map(|mutbl| mutbl.ref_prefix_str()).collect(); + self.suggestion.push((pat_span.shrink_to_lo(), suggestion_str)); + self.ref_pattern_count += adjustments.len(); + } + + // Remember if this changed the default binding mode, in case we want to label it. + let min_mutbl = implicit_deref_mutbls.min().unwrap(); + if self.default_mode_span.is_none_or(|(_, old_mutbl)| min_mutbl < old_mutbl) { + // This changes the default binding mode to `ref` or `ref mut`. Return the old mode so + // it can be reinstated when we leave the pattern. + self.default_mode_span.replace((pat_span, min_mutbl)) + } else { + // This does not change the default binding mode; it was already `ref` or `ref mut`. + self.default_mode_span + } + } + + /// Tracks the default binding mode when we're lowering a `&` or `&mut` pattern. + /// Returns the prior default binding mode; this should be followed by a call to + /// [`PatMigration::leave_ref`] to restore it when we leave the pattern. + pub(super) fn visit_explicit_deref(&mut self) -> Option<(Span, Mutability)> { + if let Some((default_mode_span, default_ref_mutbl)) = self.default_mode_span { + // If this eats a by-ref default binding mode, label the binding mode. + self.default_mode_labels.insert(default_mode_span, default_ref_mutbl); + } + // Set the default binding mode to by-value and return the old default binding mode so it + // can be reinstated when we leave the pattern. + self.default_mode_span.take() + } + + /// Restores the default binding mode after lowering a pattern that could change it. + /// This should follow a call to either [`PatMigration::visit_explicit_deref`] or + /// [`PatMigration::visit_implicit_derefs`]. + pub(super) fn leave_ref(&mut self, old_mode_span: Option<(Span, Mutability)>) { + self.default_mode_span = old_mode_span + } + + /// Determines if a binding is relevant to the diagnostic and adjusts the notes/suggestion if + /// so. Bindings are relevant if they have a modifier under a by-ref default mode (invalid in + /// Rust 2024) or if we need to suggest a binding modifier for them. + pub(super) fn visit_binding( + &mut self, + pat_span: Span, + mode: BindingMode, + explicit_ba: BindingMode, + ident: Ident, + ) { + if explicit_ba != BindingMode::NONE + && let Some((default_mode_span, default_ref_mutbl)) = self.default_mode_span + { + // If this overrides a by-ref default binding mode, label the binding mode. + self.default_mode_labels.insert(default_mode_span, default_ref_mutbl); + // If our suggestion is to elide redundnt modes, this will be one of them. + if self.info.suggest_eliding_modes { + self.suggestion.push((pat_span.with_hi(ident.span.lo()), String::new())); + self.binding_mode_count += 1; + } + } + if !self.info.suggest_eliding_modes + && explicit_ba.0 == ByRef::No + && let ByRef::Yes(mutbl) = mode.0 + { + // If we can't fix the pattern by eliding modifiers, we'll need to make the pattern + // fully explicit. i.e. we'll need to suggest reference patterns for this. + let sugg_str = match mutbl { + Mutability::Not => "ref ", + Mutability::Mut => "ref mut ", + }; + self.suggestion + .push((pat_span.with_lo(ident.span.lo()).shrink_to_lo(), sugg_str.to_owned())); + self.binding_mode_count += 1; + } + } +} diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 83fef7b0de6..8dc3f998e09 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -2,18 +2,17 @@ mod check_match; mod const_to_pat; +mod migration; use std::cmp::Ordering; use std::sync::Arc; use rustc_abi::{FieldIdx, Integer}; -use rustc_errors::MultiSpan; use rustc_errors::codes::*; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::pat_util::EnumerateAndAdjustIterator; -use rustc_hir::{self as hir, ByRef, Mutability, RangeEnd}; +use rustc_hir::{self as hir, RangeEnd}; use rustc_index::Idx; -use rustc_lint as lint; use rustc_middle::mir::interpret::LitToConstInput; use rustc_middle::thir::{ Ascription, FieldPat, LocalVarId, Pat, PatKind, PatRange, PatRangeBoundary, @@ -26,8 +25,8 @@ use rustc_span::{ErrorGuaranteed, Span}; use tracing::{debug, instrument}; pub(crate) use self::check_match::check_match; +use self::migration::PatMigration; use crate::errors::*; -use crate::fluent_generated as fluent; struct PatCtxt<'a, 'tcx> { tcx: TyCtxt<'tcx>, @@ -35,7 +34,7 @@ struct PatCtxt<'a, 'tcx> { typeck_results: &'a ty::TypeckResults<'tcx>, /// Used by the Rust 2024 migration lint. - rust_2024_migration_suggestion: Option<Rust2024IncompatiblePatSugg>, + rust_2024_migration: Option<PatMigration<'a>>, } pub(super) fn pat_from_hir<'a, 'tcx>( @@ -44,59 +43,19 @@ pub(super) fn pat_from_hir<'a, 'tcx>( typeck_results: &'a ty::TypeckResults<'tcx>, pat: &'tcx hir::Pat<'tcx>, ) -> Box<Pat<'tcx>> { - let migration_info = typeck_results.rust_2024_migration_desugared_pats().get(pat.hir_id); let mut pcx = PatCtxt { tcx, typing_env, typeck_results, - rust_2024_migration_suggestion: migration_info.and_then(|info| { - Some(Rust2024IncompatiblePatSugg { - suggest_eliding_modes: info.suggest_eliding_modes, - suggestion: Vec::new(), - ref_pattern_count: 0, - binding_mode_count: 0, - default_mode_span: None, - default_mode_labels: Default::default(), - }) - }), + rust_2024_migration: typeck_results + .rust_2024_migration_desugared_pats() + .get(pat.hir_id) + .map(PatMigration::new), }; let result = pcx.lower_pattern(pat); debug!("pat_from_hir({:?}) = {:?}", pat, result); - if let Some(info) = migration_info - && let Some(sugg) = pcx.rust_2024_migration_suggestion - { - let mut spans = - MultiSpan::from_spans(info.primary_labels.iter().map(|(span, _)| *span).collect()); - for (span, label) in &info.primary_labels { - spans.push_span_label(*span, label.clone()); - } - // If a relevant span is from at least edition 2024, this is a hard error. - let is_hard_error = spans.primary_spans().iter().any(|span| span.at_least_rust_2024()); - if is_hard_error { - let mut err = - tcx.dcx().struct_span_err(spans, fluent::mir_build_rust_2024_incompatible_pat); - if let Some(lint_info) = lint::builtin::RUST_2024_INCOMPATIBLE_PAT.future_incompatible { - // provide the same reference link as the lint - err.note(format!("for more information, see {}", lint_info.reference)); - } - err.arg("bad_modifiers", info.bad_modifiers); - err.arg("bad_ref_pats", info.bad_ref_pats); - err.arg("is_hard_error", true); - err.subdiagnostic(sugg); - err.emit(); - } else { - tcx.emit_node_span_lint( - lint::builtin::RUST_2024_INCOMPATIBLE_PAT, - pat.hir_id, - spans, - Rust2024IncompatiblePat { - sugg, - bad_modifiers: info.bad_modifiers, - bad_ref_pats: info.bad_ref_pats, - is_hard_error, - }, - ); - } + if let Some(m) = pcx.rust_2024_migration { + m.emit(tcx, pat.hir_id); } result } @@ -106,31 +65,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let adjustments: &[Ty<'tcx>] = self.typeck_results.pat_adjustments().get(pat.hir_id).map_or(&[], |v| &**v); + // Track the default binding mode for the Rust 2024 migration suggestion. let mut opt_old_mode_span = None; - if let Some(s) = &mut self.rust_2024_migration_suggestion + if let Some(s) = &mut self.rust_2024_migration && !adjustments.is_empty() { - let implicit_deref_mutbls = adjustments.iter().map(|ref_ty| { - let &ty::Ref(_, _, mutbl) = ref_ty.kind() else { - span_bug!(pat.span, "pattern implicitly dereferences a non-ref type"); - }; - mutbl - }); - - if !s.suggest_eliding_modes { - let suggestion_str: String = - implicit_deref_mutbls.clone().map(|mutbl| mutbl.ref_prefix_str()).collect(); - s.suggestion.push((pat.span.shrink_to_lo(), suggestion_str)); - s.ref_pattern_count += adjustments.len(); - } - - // Remember if this changed the default binding mode, in case we want to label it. - let min_mutbl = implicit_deref_mutbls.min().unwrap(); - if s.default_mode_span.is_none_or(|(_, old_mutbl)| min_mutbl < old_mutbl) { - opt_old_mode_span = Some(s.default_mode_span); - s.default_mode_span = Some((pat.span, min_mutbl)); - } - }; + opt_old_mode_span = s.visit_implicit_derefs(pat.span, adjustments); + } // When implicit dereferences have been inserted in this pattern, the unadjusted lowered // pattern has the type that results *after* dereferencing. For example, in this code: @@ -169,10 +110,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { }) }); - if let Some(s) = &mut self.rust_2024_migration_suggestion - && let Some(old_mode_span) = opt_old_mode_span + if let Some(s) = &mut self.rust_2024_migration + && !adjustments.is_empty() { - s.default_mode_span = old_mode_span; + s.leave_ref(opt_old_mode_span); } adjusted_pat @@ -189,7 +130,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { // Lower the endpoint into a temporary `PatKind` that will then be // deconstructed to obtain the constant value and other data. - let mut kind: PatKind<'tcx> = self.lower_lit(expr); + let mut kind: PatKind<'tcx> = self.lower_pat_expr(expr); // Unpeel any ascription or inline-const wrapper nodes. loop { @@ -353,7 +294,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { hir::PatKind::Never => PatKind::Never, - hir::PatKind::Expr(value) => self.lower_lit(value), + hir::PatKind::Expr(value) => self.lower_pat_expr(value), hir::PatKind::Range(ref lo_expr, ref hi_expr, end) => { let (lo_expr, hi_expr) = (lo_expr.as_deref(), hi_expr.as_deref()); @@ -368,16 +309,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { } hir::PatKind::Ref(subpattern, _) => { // Track the default binding mode for the Rust 2024 migration suggestion. - let old_mode_span = self.rust_2024_migration_suggestion.as_mut().and_then(|s| { - if let Some((default_mode_span, default_ref_mutbl)) = s.default_mode_span { - // If this eats a by-ref default binding mode, label the binding mode. - s.default_mode_labels.insert(default_mode_span, default_ref_mutbl); - } - s.default_mode_span.take() - }); + let opt_old_mode_span = + self.rust_2024_migration.as_mut().and_then(|s| s.visit_explicit_deref()); let subpattern = self.lower_pattern(subpattern); - if let Some(s) = &mut self.rust_2024_migration_suggestion { - s.default_mode_span = old_mode_span; + if let Some(s) = &mut self.rust_2024_migration { + s.leave_ref(opt_old_mode_span); } PatKind::Deref { subpattern } } @@ -408,32 +344,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { .get(pat.hir_id) .expect("missing binding mode"); - if let Some(s) = &mut self.rust_2024_migration_suggestion { - if explicit_ba != hir::BindingMode::NONE - && let Some((default_mode_span, default_ref_mutbl)) = s.default_mode_span - { - // If this overrides a by-ref default binding mode, label the binding mode. - s.default_mode_labels.insert(default_mode_span, default_ref_mutbl); - // If our suggestion is to elide redundnt modes, this will be one of them. - if s.suggest_eliding_modes { - s.suggestion.push((pat.span.with_hi(ident.span.lo()), String::new())); - s.binding_mode_count += 1; - } - } - if !s.suggest_eliding_modes - && explicit_ba.0 == ByRef::No - && let ByRef::Yes(mutbl) = mode.0 - { - let sugg_str = match mutbl { - Mutability::Not => "ref ", - Mutability::Mut => "ref mut ", - }; - s.suggestion.push(( - pat.span.with_lo(ident.span.lo()).shrink_to_lo(), - sugg_str.to_owned(), - )); - s.binding_mode_count += 1; - } + if let Some(s) = &mut self.rust_2024_migration { + s.visit_binding(pat.span, mode, explicit_ba, ident); } // A ref x pattern is the same node used for x, and as such it has @@ -638,54 +550,57 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let ty = self.typeck_results.node_type(id); let res = self.typeck_results.qpath_res(qpath, id); - let pat_from_kind = |kind| Box::new(Pat { span, ty, kind }); - - let (def_id, is_associated_const) = match res { - Res::Def(DefKind::Const, def_id) => (def_id, false), - Res::Def(DefKind::AssocConst, def_id) => (def_id, true), + let (def_id, user_ty) = match res { + Res::Def(DefKind::Const, def_id) => (def_id, None), + Res::Def(DefKind::AssocConst, def_id) => { + (def_id, self.typeck_results.user_provided_types().get(id)) + } - _ => return pat_from_kind(self.lower_variant_or_leaf(res, id, span, ty, vec![])), + _ => { + // The path isn't the name of a constant, so it must actually + // be a unit struct or unit variant (e.g. `Option::None`). + let kind = self.lower_variant_or_leaf(res, id, span, ty, vec![]); + return Box::new(Pat { span, ty, kind }); + } }; + // Lower the named constant to a THIR pattern. let args = self.typeck_results.node_args(id); let c = ty::Const::new_unevaluated(self.tcx, ty::UnevaluatedConst { def: def_id, args }); let subpattern = self.const_to_pat(c, ty, id, span); - let pattern = Box::new(Pat { - span, - ty, - kind: PatKind::ExpandedConstant { subpattern, def_id, is_inline: false }, - }); - if !is_associated_const { - return pattern; - } + // Wrap the pattern in a marker node to indicate that it is the result + // of lowering a named constant. This marker is used for improved + // diagnostics in some situations, but has no effect at runtime. + let mut pattern = { + let kind = PatKind::ExpandedConstant { subpattern, def_id, is_inline: false }; + Box::new(Pat { span, ty, kind }) + }; - let user_provided_types = self.typeck_results.user_provided_types(); - if let Some(&user_ty) = user_provided_types.get(id) { + // If this is an associated constant with an explicit user-written + // type, add an ascription node (e.g. `<Foo<'a> as MyTrait>::CONST`). + if let Some(&user_ty) = user_ty { let annotation = CanonicalUserTypeAnnotation { user_ty: Box::new(user_ty), span, inferred_ty: self.typeck_results.node_type(id), }; - Box::new(Pat { - span, - kind: PatKind::AscribeUserType { - subpattern: pattern, - ascription: Ascription { - annotation, - // Note that use `Contravariant` here. See the - // `variance` field documentation for details. - variance: ty::Contravariant, - }, + let kind = PatKind::AscribeUserType { + subpattern: pattern, + ascription: Ascription { + annotation, + // Note that we use `Contravariant` here. See the + // `variance` field documentation for details. + variance: ty::Contravariant, }, - ty, - }) - } else { - pattern + }; + pattern = Box::new(Pat { span, kind, ty }); } + + pattern } - /// Converts inline const patterns. + /// Lowers an inline const block (e.g. `const { 1 + 1 }`) to a pattern. fn lower_inline_const( &mut self, block: &'tcx hir::ConstBlock, @@ -705,14 +620,17 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let ct = ty::UnevaluatedConst { def: def_id.to_def_id(), args }; let subpattern = self.const_to_pat(ty::Const::new_unevaluated(self.tcx, ct), ty, id, span); + + // Wrap the pattern in a marker node to indicate that it is the result + // of lowering an inline const block. PatKind::ExpandedConstant { subpattern, def_id: def_id.to_def_id(), is_inline: true } } - /// Converts literals, paths and negation of literals to patterns. - /// The special case for negation exists to allow things like `-128_i8` - /// which would overflow if we tried to evaluate `128_i8` and then negate - /// afterwards. - fn lower_lit(&mut self, expr: &'tcx hir::PatExpr<'tcx>) -> PatKind<'tcx> { + /// Lowers the kinds of "expression" that can appear in a HIR pattern: + /// - Paths (e.g. `FOO`, `foo::BAR`, `Option::None`) + /// - Inline const blocks (e.g. `const { 1 + 1 }`) + /// - Literals, possibly negated (e.g. `-128u8`, `"hello"`) + fn lower_pat_expr(&mut self, expr: &'tcx hir::PatExpr<'tcx>) -> PatKind<'tcx> { let (lit, neg) = match &expr.kind { hir::PatExprKind::Path(qpath) => { return self.lower_path(qpath, expr.hir_id, expr.span).kind; diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index 9ab87dd99ff..cd56d93afcf 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -921,10 +921,10 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { print_indented!(self, format!("span: {:?}", span), depth_lvl + 1); print_indented!(self, "}", depth_lvl + 1); } - InlineAsmOperand::SymFn { value, span } => { + InlineAsmOperand::SymFn { value } => { print_indented!(self, "InlineAsmOperand::SymFn {", depth_lvl); - print_indented!(self, format!("value: {:?}", *value), depth_lvl + 1); - print_indented!(self, format!("span: {:?}", span), depth_lvl + 1); + print_indented!(self, "value: ", depth_lvl + 1); + self.print_expr(*value, depth_lvl + 2); print_indented!(self, "}", depth_lvl + 1); } InlineAsmOperand::SymStatic { def_id } => { diff --git a/compiler/rustc_mir_build/src/thir/util.rs b/compiler/rustc_mir_build/src/thir/util.rs index 4dff093afd0..60a47a94e3a 100644 --- a/compiler/rustc_mir_build/src/thir/util.rs +++ b/compiler/rustc_mir_build/src/thir/util.rs @@ -16,7 +16,7 @@ pub(crate) fn user_args_applied_to_ty_of_hir_id<'tcx>( let ty = typeck_results.node_type(hir_id); match ty.kind() { ty::Adt(adt_def, ..) => { - if let ty::UserTypeKind::TypeOf(ref mut did, _) = &mut user_ty.value.kind { + if let ty::UserTypeKind::TypeOf(did, _) = &mut user_ty.value.kind { *did = adt_def.did(); } Some(user_ty) |
