diff options
| -rw-r--r-- | compiler/rustc_middle/src/mir/mod.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/syntax.rs | 32 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/tcx.rs | 15 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/build/expr/as_place.rs | 92 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/build/expr/into.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/build/matches/test.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/build/matches/util.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_mir_dataflow/src/value_analysis.rs | 4 |
9 files changed, 105 insertions, 52 deletions
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 364c1b375ae..a646860ed45 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1517,7 +1517,7 @@ impl<'tcx> StatementKind<'tcx> { /////////////////////////////////////////////////////////////////////////// // Places -impl<V, T> ProjectionElem<V, T> { +impl<V, T, U> ProjectionElem<V, T, U> { /// Returns `true` if the target of this projection may refer to a different region of memory /// than the base. fn is_indirect(&self) -> bool { @@ -1546,7 +1546,7 @@ impl<V, T> ProjectionElem<V, T> { /// Alias for projections as they appear in `UserTypeProjection`, where we /// need neither the `V` parameter for `Index` nor the `T` for `Field`. -pub type ProjectionKind = ProjectionElem<(), ()>; +pub type ProjectionKind = ProjectionElem<(), (), ()>; rustc_index::newtype_index! { /// A [newtype'd][wrapper] index type in the MIR [control-flow graph][CFG] diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index fed943169df..004dd004c72 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -877,9 +877,9 @@ pub struct Place<'tcx> { #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] -pub enum ProjectionElem<V, T> { +pub enum ProjectionElem<V, T1, T2> { Deref, - Field(Field, T), + Field(Field, T1), /// Index into a slice/array. /// /// Note that this does not also dereference, and so it does not exactly correspond to slice @@ -935,12 +935,36 @@ pub enum ProjectionElem<V, T> { /// Like an explicit cast from an opaque type to a concrete type, but without /// requiring an intermediate variable. - OpaqueCast(T), + OpaqueCast(T2), } /// Alias for projections as they appear in places, where the base is a place /// and the index is a local. -pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>; +pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>, Ty<'tcx>>; + +/// Alias for projections that appear in `PlaceBuilder::UpVar`, for which +/// we cannot provide any field types. +pub type UpvarProjectionElem<'tcx> = ProjectionElem<Local, (), Ty<'tcx>>; + +impl<'tcx> From<PlaceElem<'tcx>> for UpvarProjectionElem<'tcx> { + fn from(elem: PlaceElem<'tcx>) -> Self { + match elem { + ProjectionElem::Deref => ProjectionElem::Deref, + ProjectionElem::Field(field, _) => ProjectionElem::Field(field, ()), + ProjectionElem::Index(v) => ProjectionElem::Index(v), + ProjectionElem::ConstantIndex { offset, min_length, from_end } => { + ProjectionElem::ConstantIndex { offset, min_length, from_end } + } + ProjectionElem::Subslice { from, to, from_end } => { + ProjectionElem::Subslice { from, to, from_end } + } + ProjectionElem::Downcast(opt_sym, variant_idx) => { + ProjectionElem::Downcast(opt_sym, variant_idx) + } + ProjectionElem::OpaqueCast(ty) => ProjectionElem::OpaqueCast(ty), + } + } +} /////////////////////////////////////////////////////////////////////////// // Operands diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index fa3adafd4b8..e3ca1f41d7e 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -28,8 +28,8 @@ impl<'tcx> PlaceTy<'tcx> { /// `place_ty.field_ty(tcx, f)` computes the type at a given field /// of a record or enum-variant. (Most clients of `PlaceTy` can /// instead just extract the relevant type directly from their - /// `PlaceElem`, but some instances of `ProjectionElem<V, T>` do - /// not carry a `Ty` for `T`.) + /// `PlaceElem`, but some instances of `ProjectionElem<V, T1, T2>` do + /// not carry a `Ty` for `T1` or `T2`.) /// /// Note that the resulting type has not been normalized. pub fn field_ty(self, tcx: TyCtxt<'tcx>, f: Field) -> Ty<'tcx> { @@ -64,17 +64,18 @@ impl<'tcx> PlaceTy<'tcx> { /// `Ty` or downcast variant corresponding to that projection. /// The `handle_field` callback must map a `Field` to its `Ty`, /// (which should be trivial when `T` = `Ty`). - pub fn projection_ty_core<V, T>( + pub fn projection_ty_core<V, T1, T2>( self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, - elem: &ProjectionElem<V, T>, - mut handle_field: impl FnMut(&Self, Field, T) -> Ty<'tcx>, - mut handle_opaque_cast: impl FnMut(&Self, T) -> Ty<'tcx>, + elem: &ProjectionElem<V, T1, T2>, + mut handle_field: impl FnMut(&Self, Field, T1) -> Ty<'tcx>, + mut handle_opaque_cast: impl FnMut(&Self, T2) -> Ty<'tcx>, ) -> PlaceTy<'tcx> where V: ::std::fmt::Debug, - T: ::std::fmt::Debug + Copy, + T1: ::std::fmt::Debug + Copy, + T2: ::std::fmt::Debug + Copy, { if self.variant_index.is_some() && !matches!(elem, ProjectionElem::Field(..)) { bug!("cannot use non field projection on downcasted place") 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 bf417dae785..bd27b6c2beb 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -19,6 +19,7 @@ use rustc_target::abi::VariantIdx; use rustc_index::vec::Idx; use std::assert_matches::assert_matches; +use std::convert::From; use std::iter; /// `PlaceBuilder` is used to create places during MIR construction. It allows you to "build up" a @@ -66,7 +67,7 @@ pub(in crate::build) enum PlaceBuilder<'tcx> { /// /// Note: in contrast to `PlaceBuilder::Local` we have not yet determined all `Field` types /// and will only do so once converting to `PlaceBuilder::Local`. - UpVar(UpVar, Vec<PlaceElem<'tcx>>), + UpVar(UpVar, Vec<UpvarProjectionElem<'tcx>>), } #[derive(Copy, Clone, Debug, PartialEq)] @@ -82,7 +83,7 @@ pub(crate) struct UpVar { /// part of a path that is captured by a closure. We stop applying projections once we see the first /// projection that isn't captured by a closure. fn convert_to_hir_projections_and_truncate_for_capture<'tcx>( - mir_projections: &[PlaceElem<'tcx>], + mir_projections: &[UpvarProjectionElem<'tcx>], ) -> Vec<HirProjectionKind> { let mut hir_projections = Vec::new(); let mut variant = None; @@ -156,7 +157,7 @@ fn is_ancestor_or_same_capture( fn find_capture_matching_projections<'a, 'tcx>( upvars: &'a CaptureMap<'tcx>, var_hir_id: LocalVarId, - projections: &[PlaceElem<'tcx>], + projections: &[UpvarProjectionElem<'tcx>], ) -> Option<(usize, &'a Capture<'tcx>)> { let hir_projections = convert_to_hir_projections_and_truncate_for_capture(projections); @@ -212,8 +213,7 @@ fn to_upvars_resolved_place_builder<'tcx>( capture.captured_place.place.base_ty, projection, &capture.captured_place.place.projections, - ) - .collect::<Vec<_>>(); + ); let upvar_resolved_place_builder = PlaceBuilder::construct_local_place_builder( cx, @@ -222,6 +222,37 @@ fn to_upvars_resolved_place_builder<'tcx>( upvar_projection, ); + debug_assert!({ + let builder = upvar_resolved_place_builder.clone(); + let mut valid_conversion = true; + match builder { + PlaceBuilder::Local(_, projections) => { + for proj in projections.iter() { + match proj { + ProjectionElem::Field(_, field_ty) => { + if matches!(field_ty.kind(), ty::Infer(..)) { + debug!( + "field ty should have been converted for projection {:?} in PlaceBuilder {:?}", + proj, + upvar_resolved_place_builder.clone() + ); + + valid_conversion = false; + break; + } + } + _ => {} + } + } + } + PlaceBuilder::UpVar(..) => { + unreachable!() + } + } + + valid_conversion + }); + Some(upvar_resolved_place_builder) } @@ -233,14 +264,14 @@ fn to_upvars_resolved_place_builder<'tcx>( /// projection kinds are unsupported. fn strip_prefix<'a, 'tcx>( mut base_ty: Ty<'tcx>, - projections: &'a [PlaceElem<'tcx>], + projections: &'a [UpvarProjectionElem<'tcx>], prefix_projections: &[HirProjection<'tcx>], -) -> impl Iterator<Item = PlaceElem<'tcx>> + 'a { +) -> Vec<UpvarProjectionElem<'tcx>> { let mut iter = projections .iter() - .copied() // Filter out opaque casts, they are unnecessary in the prefix. - .filter(|elem| !matches!(elem, ProjectionElem::OpaqueCast(..))); + .filter(|elem| !matches!(elem, ProjectionElem::OpaqueCast(..))) + .map(|elem| *elem); for projection in prefix_projections { debug!(?projection, ?projection.ty); @@ -261,7 +292,8 @@ fn strip_prefix<'a, 'tcx>( base_ty = projection.ty; } - iter + + iter.collect::<Vec<_>>() } impl<'tcx> PlaceBuilder<'tcx> { @@ -292,11 +324,11 @@ impl<'tcx> PlaceBuilder<'tcx> { &self, cx: &Builder<'_, 'tcx>, ) -> Option<PlaceBuilder<'tcx>> { - let PlaceBuilder::Upvar( Upvar {var_hir_id, closure_def_id }, projection) = self else { + let PlaceBuilder::UpVar( UpVar {var_hir_id, closure_def_id }, projection) = self else { return None; }; - to_upvars_resolved_place_builder(cx, var_hir_id, closure_def_id, &projection) + to_upvars_resolved_place_builder(cx, *var_hir_id, *closure_def_id, &projection) } pub(crate) fn get_local_projection(&self) -> &[PlaceElem<'tcx>] { @@ -309,19 +341,16 @@ impl<'tcx> PlaceBuilder<'tcx> { } #[instrument(skip(cx), level = "debug")] - pub(crate) fn field( - self, - cx: &Builder<'_, 'tcx>, - f: Field, - default_field_ty: Ty<'tcx>, - ) -> Self { + pub(crate) fn field(self, cx: &Builder<'_, 'tcx>, f: Field) -> Self { let field_ty = match self { PlaceBuilder::Local(..) => { let base_place = self.clone(); - PlaceBuilder::try_compute_field_ty(cx, f, base_place) - .unwrap_or_else(|| default_field_ty) + PlaceBuilder::compute_field_ty(cx, f, base_place) + } + PlaceBuilder::UpVar(..) => { + let dummy_ty = cx.tcx.mk_ty_infer(ty::FreshTy(0)); + dummy_ty } - PlaceBuilder::UpVar(..) => default_field_ty, }; self.project(ProjectionElem::Field(f, field_ty)) @@ -347,7 +376,7 @@ impl<'tcx> PlaceBuilder<'tcx> { PlaceBuilder::Local(local, proj) } PlaceBuilder::UpVar(upvar, mut proj) => { - proj.push(elem); + proj.push(elem.into()); PlaceBuilder::UpVar(upvar, proj) } }; @@ -363,8 +392,8 @@ impl<'tcx> PlaceBuilder<'tcx> { *local, Vec::from_iter(proj.iter().copied().chain([elem.into()])), ), - PlaceBuilder::Upvar(upvar, proj) => PlaceBuilder::UpVar( - upvar, + PlaceBuilder::UpVar(upvar, proj) => PlaceBuilder::UpVar( + *upvar, Vec::from_iter(proj.iter().copied().chain([elem.into()])), ), } @@ -378,11 +407,11 @@ impl<'tcx> PlaceBuilder<'tcx> { /// Fallible as the root of this place may be an upvar for /// which no base type can be determined. #[instrument(skip(cx), level = "debug")] - fn try_compute_field_ty( + fn compute_field_ty( cx: &Builder<'_, 'tcx>, field: Field, base_place: PlaceBuilder<'tcx>, - ) -> Option<Ty<'tcx>> { + ) -> Ty<'tcx> { let field_idx = field.as_usize(); let PlaceTy { ty, variant_index } = base_place.to_place(cx).ty(&cx.local_decls, cx.tcx); let base_ty = cx.tcx.normalize_erasing_regions(cx.param_env, ty); @@ -442,7 +471,7 @@ impl<'tcx> PlaceBuilder<'tcx> { _ => bug!("couldn't create field type, unexpected base type: {:?}", base_ty), }; - Some(cx.tcx.normalize_erasing_regions(cx.param_env, field_ty)) + cx.tcx.normalize_erasing_regions(cx.param_env, field_ty) } /// Creates a `PlaceBuilder::Local` from a `PlaceBuilder::UpVar` whose upvars @@ -455,7 +484,7 @@ impl<'tcx> PlaceBuilder<'tcx> { cx: &Builder<'_, 'tcx>, local: Local, mut local_projection: Vec<PlaceElem<'tcx>>, - upvar_projection: Vec<PlaceElem<'tcx>>, + upvar_projection: Vec<UpvarProjectionElem<'tcx>>, ) -> Self { // We iterate through `upvar_projection` and whenever we find a `ProjectionElem::Field` we use // the ancestor projections, i.e. those projection elements that come before the field projection, @@ -464,11 +493,10 @@ impl<'tcx> PlaceBuilder<'tcx> { for proj in upvar_projection.iter() { debug!("proj: {:?}, local_projection: {:?}", proj, local_projection); match *proj { - ProjectionElem::Field(field, default_field_ty) => { + ProjectionElem::Field(field, _) => { let ancestor_proj = local_projection.to_vec(); let base_place = PlaceBuilder::Local(local, ancestor_proj); - let field_ty = PlaceBuilder::try_compute_field_ty(cx, field, base_place) - .unwrap_or_else(|| default_field_ty); + let field_ty = PlaceBuilder::compute_field_ty(cx, field, base_place); debug!(?field_ty); local_projection.push(ProjectionElem::Field(field, field_ty)); @@ -593,7 +621,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { place_builder = place_builder.downcast(*adt_def, variant_index); } } - block.and(place_builder.field(this, name, expr.ty)) + block.and(place_builder.field(this, name)) } ExprKind::Deref { arg } => { let place_builder = unpack!( diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 12cd0e65a11..e5c2f4f4cbe 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -355,12 +355,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // base-supplied field, generate an operand that // reads it from the base. iter::zip(field_names, &**field_types) - .map(|(n, ty)| match fields_map.get(&n) { + .map(|(n, _ty)| match fields_map.get(&n) { Some(v) => v.clone(), None => { let place_builder = place_builder.clone(); this.consume_by_copy_or_move( - place_builder.field(this, n, *ty).to_place(this), + place_builder.field(this, n).to_place(this), ) } }) diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index 7b932eda744..c669016e0ed 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -760,7 +760,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let downcast_place = match_pair.place.downcast(adt_def, variant_index); // `(x as Variant)` let consequent_match_pairs = subpatterns.iter().map(|subpattern| { // e.g., `(x as Variant).0` - let place = downcast_place.clone().field(self, subpattern.field, subpattern.pattern.ty); + let place = downcast_place.clone().field(self, subpattern.field); // e.g., `(x as Variant).0 @ P1` MatchPair::new(place, &subpattern.pattern, self) }); diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs index 30f4e49d8ba..27a7b03465f 100644 --- a/compiler/rustc_mir_build/src/build/matches/util.rs +++ b/compiler/rustc_mir_build/src/build/matches/util.rs @@ -17,7 +17,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { subpatterns .iter() .map(|fieldpat| { - let place = place.clone().field(self, fieldpat.field, fieldpat.pattern.ty); + let place = place.clone().field(self, fieldpat.field); MatchPair::new(place, &fieldpat.pattern, self) }) diff --git a/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs b/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs index 7806e8f45d3..5cfbbb1ac01 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs @@ -18,7 +18,7 @@ use rustc_middle::ty::Ty; pub struct AbstractOperand; #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub struct AbstractType; -pub type AbstractElem = ProjectionElem<AbstractOperand, AbstractType>; +pub type AbstractElem = ProjectionElem<AbstractOperand, AbstractType, AbstractType>; pub trait Lift { type Abstract; diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index cc69a1bb02d..b09503a3093 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -777,10 +777,10 @@ pub enum TrackElem { Field(Field), } -impl<V, T> TryFrom<ProjectionElem<V, T>> for TrackElem { +impl<V, T1, T2> TryFrom<ProjectionElem<V, T1, T2>> for TrackElem { type Error = (); - fn try_from(value: ProjectionElem<V, T>) -> Result<Self, Self::Error> { + fn try_from(value: ProjectionElem<V, T1, T2>) -> Result<Self, Self::Error> { match value { ProjectionElem::Field(field, _) => Ok(TrackElem::Field(field)), _ => Err(()), |
