diff options
| author | bors <bors@rust-lang.org> | 2025-10-02 01:54:48 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2025-10-02 01:54:48 +0000 |
| commit | 42b384ec0dfcd528d99a4db0a337d9188a9eecaa (patch) | |
| tree | 3514e6cac9bc43fb0b255776653d322956ff4b75 /compiler/rustc_middle/src | |
| parent | 3369e82c6bc03c5cdb66f730dba6f738b74c8e1d (diff) | |
| parent | 413f095a85adb21331f6e64cf030ead124a6ba07 (diff) | |
| download | rust-42b384ec0dfcd528d99a4db0a337d9188a9eecaa.tar.gz rust-42b384ec0dfcd528d99a4db0a337d9188a9eecaa.zip | |
Auto merge of #147055 - beepster4096:subtype_is_not_a_projection, r=lcnr
Turn ProjectionElem::Subtype into CastKind::Subtype I noticed that drop elaboration can't, in general, handle `ProjectionElem::SubType`. It creates a disjoint move path that overlaps with other move paths. (`Subslice` does too, and I'm working on a different PR to make that special case less fragile.) If its skipped and treated as the same move path as its parent then `MovePath.place` has multiple possible projections. (It would probably make sense to remove all `Subtype` projections for the canonical place but it doesn't make sense to have this special case for a problem that doesn't actually occur in real MIR.) The only reason this doesn't break is that `Subtype` is always the sole projection of the local its applied to. For the same reason, it works fine as a `CastKind` so I figured that makes more sense than documenting and validating this hidden invariant. cc rust-lang/rust#112651, rust-lang/rust#133258 r? Icnr (bc you've been the main person dealing with `Subtype` it looks like)
Diffstat (limited to 'compiler/rustc_middle/src')
| -rw-r--r-- | compiler/rustc_middle/src/mir/pretty.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/statement.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/syntax.rs | 24 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/visit.rs | 6 |
4 files changed, 14 insertions, 28 deletions
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 96148fd5b92..350d75c2ee7 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -1274,7 +1274,6 @@ fn pre_fmt_projection(projection: &[PlaceElem<'_>], fmt: &mut Formatter<'_>) -> for &elem in projection.iter().rev() { match elem { ProjectionElem::OpaqueCast(_) - | ProjectionElem::Subtype(_) | ProjectionElem::Downcast(_, _) | ProjectionElem::Field(_, _) => { write!(fmt, "(")?; @@ -1300,9 +1299,6 @@ fn post_fmt_projection(projection: &[PlaceElem<'_>], fmt: &mut Formatter<'_>) -> ProjectionElem::OpaqueCast(ty) => { write!(fmt, " as {ty})")?; } - ProjectionElem::Subtype(ty) => { - write!(fmt, " as subtype {ty})")?; - } ProjectionElem::Downcast(Some(name), _index) => { write!(fmt, " as {name})")?; } diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index 28294b47e90..e009fe05b53 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -222,7 +222,6 @@ impl<'tcx> PlaceTy<'tcx> { fty, )), ProjectionElem::OpaqueCast(ty) => PlaceTy::from_ty(handle_opaque_cast_and_subtype(ty)), - ProjectionElem::Subtype(ty) => PlaceTy::from_ty(handle_opaque_cast_and_subtype(ty)), // FIXME(unsafe_binders): Rename `handle_opaque_cast_and_subtype` to be more general. ProjectionElem::UnwrapUnsafeBinder(ty) => { @@ -244,7 +243,6 @@ impl<V, T> ProjectionElem<V, T> { Self::Field(_, _) | Self::Index(_) | Self::OpaqueCast(_) - | Self::Subtype(_) | Self::ConstantIndex { .. } | Self::Subslice { .. } | Self::Downcast(_, _) @@ -259,7 +257,6 @@ impl<V, T> ProjectionElem<V, T> { Self::Deref | Self::Index(_) => false, Self::Field(_, _) | Self::OpaqueCast(_) - | Self::Subtype(_) | Self::ConstantIndex { .. } | Self::Subslice { .. } | Self::Downcast(_, _) @@ -286,7 +283,6 @@ impl<V, T> ProjectionElem<V, T> { | Self::Field(_, _) => true, Self::ConstantIndex { from_end: true, .. } | Self::Index(_) - | Self::Subtype(_) | Self::OpaqueCast(_) | Self::Subslice { .. } => false, @@ -319,7 +315,6 @@ impl<V, T> ProjectionElem<V, T> { ProjectionElem::Subslice { from, to, from_end } } ProjectionElem::OpaqueCast(ty) => ProjectionElem::OpaqueCast(t(ty)), - ProjectionElem::Subtype(ty) => ProjectionElem::Subtype(t(ty)), ProjectionElem::UnwrapUnsafeBinder(ty) => ProjectionElem::UnwrapUnsafeBinder(t(ty)), ProjectionElem::Index(val) => ProjectionElem::Index(v(val)?), }) @@ -706,7 +701,8 @@ impl<'tcx> Rvalue<'tcx> { | CastKind::PtrToPtr | CastKind::PointerCoercion(_, _) | CastKind::PointerWithExposedProvenance - | CastKind::Transmute, + | CastKind::Transmute + | CastKind::Subtype, _, _, ) diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index e6c8512564e..a823c365394 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1275,18 +1275,6 @@ pub enum ProjectionElem<V, T> { /// A transmute from an unsafe binder to the type that it wraps. This is a projection /// of a place, so it doesn't necessarily constitute a move out of the binder. UnwrapUnsafeBinder(T), - - /// A `Subtype(T)` projection is applied to any `StatementKind::Assign` where - /// type of lvalue doesn't match the type of rvalue, the primary goal is making subtyping - /// explicit during optimizations and codegen. - /// - /// This projection doesn't impact the runtime behavior of the program except for potentially changing - /// some type metadata of the interpreter or codegen backend. - /// - /// This goal is achieved with mir_transform pass `Subtyper`, which runs right after - /// borrowchecker, as we only care about subtyping that can affect trait selection and - /// `TypeId`. - Subtype(T), } /// Alias for projections as they appear in places, where the base is a place @@ -1513,6 +1501,18 @@ pub enum CastKind { /// MIR is well-formed if the input and output types have different sizes, /// but running a transmute between differently-sized types is UB. Transmute, + + /// A `Subtype` cast is applied to any `StatementKind::Assign` where + /// type of lvalue doesn't match the type of rvalue, the primary goal is making subtyping + /// explicit during optimizations and codegen. + /// + /// This cast doesn't impact the runtime behavior of the program except for potentially changing + /// some type metadata of the interpreter or codegen backend. + /// + /// This goal is achieved with mir_transform pass `Subtyper`, which runs right after + /// borrowchecker, as we only care about subtyping that can affect trait selection and + /// `TypeId`. + Subtype, } /// Represents how a [`CastKind::PointerCoercion`] was constructed. diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 81df239dee4..f3923477800 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -1166,11 +1166,6 @@ macro_rules! visit_place_fns { self.visit_ty(&mut new_ty, TyContext::Location(location)); if ty != new_ty { Some(PlaceElem::OpaqueCast(new_ty)) } else { None } } - PlaceElem::Subtype(ty) => { - let mut new_ty = ty; - self.visit_ty(&mut new_ty, TyContext::Location(location)); - if ty != new_ty { Some(PlaceElem::Subtype(new_ty)) } else { None } - } PlaceElem::UnwrapUnsafeBinder(ty) => { let mut new_ty = ty; self.visit_ty(&mut new_ty, TyContext::Location(location)); @@ -1244,7 +1239,6 @@ macro_rules! visit_place_fns { ) { match elem { ProjectionElem::OpaqueCast(ty) - | ProjectionElem::Subtype(ty) | ProjectionElem::Field(_, ty) | ProjectionElem::UnwrapUnsafeBinder(ty) => { self.visit_ty(ty, TyContext::Location(location)); |
