diff --git a/compiler/rustc_mir_build/src/thir/cx/block.rs b/compiler/rustc_mir_build/src/thir/cx/block.rs index 57ddb8eddb8e7..7cdd70a7fc272 100644 --- a/compiler/rustc_mir_build/src/thir/cx/block.rs +++ b/compiler/rustc_mir_build/src/thir/cx/block.rs @@ -2,8 +2,6 @@ use rustc_hir as hir; use rustc_index::Idx; use rustc_middle::middle::region; use rustc_middle::thir::*; -use rustc_middle::ty; -use rustc_middle::ty::CanonicalUserTypeAnnotation; use tracing::debug; use crate::thir::cx::ThirBuildCx; @@ -73,29 +71,9 @@ impl<'tcx> ThirBuildCx<'tcx> { let else_block = local.els.map(|els| self.mirror_block(els)); - let mut pattern = self.pattern_from_hir(local.pat); + let pattern = self.pattern_from_hir_with_annotation(local.pat, local.ty); debug!(?pattern); - if let Some(ty) = &local.ty - && let Some(&user_ty) = - self.typeck_results.user_provided_types().get(ty.hir_id) - { - debug!("mirror_stmts: user_ty={:?}", user_ty); - let annotation = CanonicalUserTypeAnnotation { - user_ty: Box::new(user_ty), - span: ty.span, - inferred_ty: self.typeck_results.node_type(ty.hir_id), - }; - pattern = Box::new(Pat { - ty: pattern.ty, - span: pattern.span, - kind: PatKind::AscribeUserType { - ascription: Ascription { annotation, variance: ty::Covariant }, - subpattern: pattern, - }, - }); - } - let span = match local.init { Some(init) => local.span.with_hi(init.span.hi()), None => local.span, diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index d26dfac0c2abd..79e85a243f400 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -12,9 +12,6 @@ use rustc_hir::{self as hir, HirId, find_attr}; use rustc_middle::bug; use rustc_middle::thir::*; use rustc_middle::ty::{self, TyCtxt}; -use tracing::instrument; - -use crate::thir::pattern::pat_from_hir; /// Query implementation for [`TyCtxt::thir_body`]. pub(crate) fn thir_body( @@ -111,9 +108,22 @@ impl<'tcx> ThirBuildCx<'tcx> { } } - #[instrument(level = "debug", skip(self))] - fn pattern_from_hir(&mut self, p: &'tcx hir::Pat<'tcx>) -> Box> { - pat_from_hir(self.tcx, self.typing_env, self.typeck_results, p) + fn pattern_from_hir(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box> { + self.pattern_from_hir_with_annotation(pat, None) + } + + fn pattern_from_hir_with_annotation( + &mut self, + pat: &'tcx hir::Pat<'tcx>, + let_stmt_type: Option<&hir::Ty<'tcx>>, + ) -> Box> { + crate::thir::pattern::pat_from_hir( + self.tcx, + self.typing_env, + self.typeck_results, + pat, + let_stmt_type, + ) } fn closure_env_param(&self, owner_def: LocalDefId, expr_id: HirId) -> Option> { diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 0310003e7d58e..76890316ba440 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -38,11 +38,14 @@ struct PatCtxt<'tcx> { rust_2024_migration: Option>, } +#[instrument(level = "debug", skip(tcx, typing_env, typeck_results), ret)] pub(super) fn pat_from_hir<'tcx>( tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, typeck_results: &'tcx ty::TypeckResults<'tcx>, pat: &'tcx hir::Pat<'tcx>, + // Present if `pat` came from a let statement with an explicit type annotation + let_stmt_type: Option<&hir::Ty<'tcx>>, ) -> Box> { let mut pcx = PatCtxt { tcx, @@ -53,12 +56,35 @@ pub(super) fn pat_from_hir<'tcx>( .get(pat.hir_id) .map(PatMigration::new), }; - let result = pcx.lower_pattern(pat); - debug!("pat_from_hir({:?}) = {:?}", pat, result); + + let mut thir_pat = pcx.lower_pattern(pat); + + // If this pattern came from a let statement with an explicit type annotation + // (e.g. `let x: Foo = ...`), retain that user type information in the THIR pattern. + if let Some(let_stmt_type) = let_stmt_type + && let Some(&user_ty) = typeck_results.user_provided_types().get(let_stmt_type.hir_id) + { + debug!(?user_ty); + let annotation = CanonicalUserTypeAnnotation { + user_ty: Box::new(user_ty), + span: let_stmt_type.span, + inferred_ty: typeck_results.node_type(let_stmt_type.hir_id), + }; + thir_pat = Box::new(Pat { + ty: thir_pat.ty, + span: thir_pat.span, + kind: PatKind::AscribeUserType { + ascription: Ascription { annotation, variance: ty::Covariant }, + subpattern: thir_pat, + }, + }); + } + if let Some(m) = pcx.rust_2024_migration { m.emit(tcx, pat.hir_id); } - result + + thir_pat } impl<'tcx> PatCtxt<'tcx> {