]> git.lizzy.rs Git - rust.git/commitdiff
use non-ascribed type as field type in mir
authorb-naber <bn263@gmx.de>
Wed, 2 Nov 2022 12:39:47 +0000 (13:39 +0100)
committerb-naber <bn263@gmx.de>
Wed, 23 Nov 2022 18:59:00 +0000 (19:59 +0100)
compiler/rustc_mir_build/src/build/matches/simplify.rs
compiler/rustc_mir_build/src/build/matches/util.rs

index f6b1955fdec4d89814844bbedf3845de14616f83..fb9f19b7b9066070420c6ff8e8c9e5f3a7adf321 100644 (file)
@@ -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(())
             }
 
index bd435f9ab0095a4b86e10703a3127c31bbd068b5..6a07b07ee12781f10acab82da32b6ffcfbdf160a 100644 (file)
@@ -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<MatchPair<'pat, 'tcx>> {
+        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::<Vec<_>>()[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]>,