diff options
| -rw-r--r-- | compiler/rustc_mir_build/src/build/expr/as_place.rs | 56 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/build/matches/simplify.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/build/matches/util.rs | 18 |
3 files changed, 35 insertions, 49 deletions
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 b6f2e3de668..b682b0c3bd4 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -7,6 +7,7 @@ use rustc_hir::def_id::LocalDefId; use rustc_middle::hir::place::Projection as HirProjection; use rustc_middle::hir::place::ProjectionKind as HirProjectionKind; use rustc_middle::middle::region; +use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::AssertKind::BoundsCheck; use rustc_middle::mir::*; use rustc_middle::thir::*; @@ -324,56 +325,35 @@ impl<'tcx> PlaceBuilder<'tcx> { } } - pub fn try_ty<D>(&self, local_decls: &D, cx: &Builder<'_, 'tcx>) -> Option<Ty<'tcx>> + pub fn try_compute_ty<D>( + &self, + local_decls: &D, + cx: &Builder<'_, 'tcx>, + ) -> Option<PlaceTy<'tcx>> where D: HasLocalDecls<'tcx>, { - let tcx = cx.tcx; - - let project_ty = |ty: Ty<'tcx>, elem: &PlaceElem<'tcx>| -> Ty<'tcx> { - match elem { - ProjectionElem::Deref => { - ty.builtin_deref(true) - .unwrap_or_else(|| { - bug!("deref projection of non-dereferenceable ty {:?}", ty) - }) - .ty - } - ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } => { - ty.builtin_index().unwrap() - } - ProjectionElem::Subslice { from, to, from_end } => match ty.kind() { - ty::Slice(..) => ty, - ty::Array(inner, _) if !from_end => tcx.mk_array(*inner, (to - from) as u64), - ty::Array(inner, size) if *from_end => { - let size = size.eval_usize(tcx, ty::ParamEnv::empty()); - let len = size - (*from as u64) - (*to as u64); - tcx.mk_array(*inner, len) - } - _ => bug!("cannot subslice non-array type: `{:?}`", ty), - }, - ProjectionElem::Downcast(..) => ty, - ProjectionElem::Field(_, ty) | ProjectionElem::OpaqueCast(ty) => *ty, - } - }; - match self.base { - PlaceBase::Local(local) => { - let base_ty = local_decls.local_decls()[local].ty; - Some(self.projection.iter().fold(base_ty, |ty, &elem| project_ty(ty, &elem))) - } + PlaceBase::Local(_) => Some(self.clone().into_place(cx).ty(local_decls, cx.tcx)), PlaceBase::Upvar { .. } => { match to_upvars_resolved_place_builder(self.clone(), cx) { Ok(resolved_place_builder) => { // `base` is guaranteed to be `PlaceBase::Local` now, so recursive call is ok - resolved_place_builder.try_ty(local_decls, cx) + resolved_place_builder.try_compute_ty(local_decls, cx) } Err(place_builder) => { match &place_builder.projection[..] { - &[ProjectionElem::OpaqueCast(base_ty), ref projections @ ..] => Some( - projections.iter().fold(base_ty, |ty, &elem| project_ty(ty, &elem)), - ), + &[ProjectionElem::OpaqueCast(base_ty), ref projections @ ..] => { + let place_ty = projections + .iter() + .fold(PlaceTy::from_ty(base_ty), |place_ty, &elem| { + place_ty.projection_ty(cx.tcx, elem) + }); + + debug!(?place_ty); + Some(place_ty) + } _ => None, // would need a base `Ty` for these } } diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs index fb9f19b7b90..36aa7693e82 100644 --- a/compiler/rustc_mir_build/src/build/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs @@ -272,9 +272,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { || !adt_def.is_variant_list_non_exhaustive()); if irrefutable { let place_builder = match_pair.place.downcast(adt_def, variant_index); - candidate - .match_pairs - .extend(self.field_match_pairs(place_builder, subpatterns)); + let field_match_pairs = + self.field_match_pairs(place_builder.clone(), subpatterns); + candidate.match_pairs.extend(field_match_pairs); Ok(()) } else { Err(match_pair) @@ -294,9 +294,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { PatKind::Leaf { ref subpatterns } => { // tuple struct, match subpats (if any) - candidate - .match_pairs - .extend(self.field_match_pairs_tuple_struct(match_pair.place, subpatterns)); + candidate.match_pairs.extend(self.field_match_pairs(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 6a07b07ee12..7423b5e1ae3 100644 --- a/compiler/rustc_mir_build/src/build/matches/util.rs +++ b/compiler/rustc_mir_build/src/build/matches/util.rs @@ -31,10 +31,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { 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); + let place_ty_and_variant_idx = + place_builder.try_compute_ty(&self.local_decls, self).map(|place_ty| { + ( + self.tcx.normalize_erasing_regions(self.param_env, place_ty.ty), + place_ty.variant_index, + ) + }); + debug!(?place_ty_and_variant_idx); subpatterns .iter() @@ -43,9 +47,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // 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_ty = if let Some((place_ty, opt_variant_idx)) = place_ty_and_variant_idx { let field_idx = fieldpat.field.as_usize(); let field_ty = match place_ty.kind() { + ty::Adt(adt_def, substs) if adt_def.is_enum() => { + let variant_idx = opt_variant_idx.unwrap(); + adt_def.variant(variant_idx).fields[field_idx].ty(self.tcx, substs) + } ty::Adt(adt_def, substs) => { adt_def.all_fields().collect::<Vec<_>>()[field_idx].ty(self.tcx, substs) } |
