diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs index f6b1955fdec..fb9f19b7b90 100644 --- a/compiler/rustc_mir_build/src/build/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs @@ -294,7 +294,9 @@ fn simplify_match_pair<'pat>( PatKind::Leaf { ref subpatterns } => { // tuple struct, match subpats (if any) - candidate.match_pairs.extend(self.field_match_pairs(match_pair.place, subpatterns)); + candidate + .match_pairs + .extend(self.field_match_pairs_tuple_struct(match_pair.place, subpatterns)); Ok(()) } diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs index bd435f9ab00..6a07b07ee12 100644 --- a/compiler/rustc_mir_build/src/build/matches/util.rs +++ b/compiler/rustc_mir_build/src/build/matches/util.rs @@ -25,6 +25,51 @@ pub(crate) fn field_match_pairs<'pat>( .collect() } + #[instrument(skip(self), level = "debug")] + pub(crate) fn field_match_pairs_tuple_struct<'pat>( + &mut self, + place_builder: PlaceBuilder<'tcx>, + subpatterns: &'pat [FieldPat<'tcx>], + ) -> Vec> { + let place_ty = place_builder + .try_ty(&self.local_decls, self) + .map(|ty| self.tcx.normalize_erasing_regions(self.param_env, ty)); + debug!(?place_ty); + + subpatterns + .iter() + .map(|fieldpat| { + // NOTE: With type ascriptions it can happen that we get errors + // during borrow-checking on higher-ranked types if we use the + // ascribed type as the field type, so we try to get the actual field + // type from the `Place`, if possible, see issue #96514 + let field_ty = if let Some(place_ty) = place_ty { + let field_idx = fieldpat.field.as_usize(); + let field_ty = match place_ty.kind() { + ty::Adt(adt_def, substs) => { + adt_def.all_fields().collect::>()[field_idx].ty(self.tcx, substs) + } + ty::Tuple(elems) => elems.to_vec()[field_idx], + _ => bug!( + "no field available, place_ty: {:#?}, kind: {:?}", + place_ty, + place_ty.kind() + ), + }; + + self.tcx.normalize_erasing_regions(self.param_env, field_ty) + } else { + fieldpat.pattern.ty + }; + + let place = place_builder.clone().field(fieldpat.field, field_ty); + debug!(?place, ?field_ty); + + MatchPair::new(place, &fieldpat.pattern, self) + }) + .collect() + } + pub(crate) fn prefix_slice_suffix<'pat>( &mut self, match_pairs: &mut SmallVec<[MatchPair<'pat, 'tcx>; 1]>,