diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index ed36ca6a29b..e7b1a489f5d 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -716,11 +716,9 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { } PlaceTy::from_ty(fty) } - ProjectionElem::Subtype(_) => PlaceTy::from_ty(Ty::new_error_with_message( - tcx, - self.last_span, - "ProjectionElem::Subtype shouldn't exist in borrowck", - )), + ProjectionElem::Subtype(_) => { + bug!("ProjectionElem::Subtype shouldn't exist in borrowck") + } ProjectionElem::OpaqueCast(ty) => { let ty = self.sanitize_type(place, ty); let ty = self.cx.normalize(ty, location); diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs index 09033cfb23f..45893a4f3ac 100644 --- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs +++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs @@ -674,7 +674,7 @@ impl<'tcx> CPlace<'tcx> { } } - /// Used for `ProjectionElem::Subtype`, ty has to be monomorphized before + /// Used for `ProjectionElem::Subtype`, `ty` has to be monomorphized before /// passed on. pub(crate) fn place_transmute_type( self, diff --git a/compiler/rustc_const_eval/src/util/compare_types.rs b/compiler/rustc_const_eval/src/util/compare_types.rs index dd4c67e8d6b..265ca0c7884 100644 --- a/compiler/rustc_const_eval/src/util/compare_types.rs +++ b/compiler/rustc_const_eval/src/util/compare_types.rs @@ -30,9 +30,9 @@ pub fn is_equal_up_to_subtyping<'tcx>( /// Returns whether `src` is a subtype of `dest`, i.e. `src <: dest`. /// -/// For almost all of the use cases variance should be `Covariant`, -/// in `MirPhase` >= `MirPhase::Runtime(RuntimePhase::Initial` variance should -/// be `Invariant`. +/// When validating assignments, the variance should be `Covariant`. When checking +/// during `MirPhase` >= `MirPhase::Runtime(RuntimePhase::Initial)` variance should be `Invariant` +/// because we want to check for type equality. /// /// This mostly ignores opaque types as it can be used in constraining contexts /// while still computing the final underlying type. diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 6fec4517b8c..9361d32a0d5 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -1127,7 +1127,7 @@ fn post_fmt_projection(projection: &[PlaceElem<'_>], fmt: &mut Formatter<'_>) -> write!(fmt, " as {ty})")?; } ProjectionElem::Subtype(ty) => { - write!(fmt, "as {ty})")?; + write!(fmt, " as subtype {ty})")?; } ProjectionElem::Downcast(Some(name), _index) => { write!(fmt, " as {name})")?; diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index e7db6a67240..49f4def6dfb 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1077,9 +1077,12 @@ pub enum ProjectionElem { OpaqueCast(T), /// A `Subtype(T)` projection is applied to any `StatementKind::Assign` where - /// type of lvalue doesn't match type of rvalue, primary goal being making subtyping + /// 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`. diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index f534f0f5f3c..44ae75e2de7 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -69,7 +69,7 @@ impl<'tcx> PlaceTy<'tcx> { param_env: ty::ParamEnv<'tcx>, elem: &ProjectionElem, mut handle_field: impl FnMut(&Self, FieldIdx, T) -> Ty<'tcx>, - mut handle_opaque_cast: impl FnMut(&Self, T) -> Ty<'tcx>, + mut handle_opaque_cast_and_subtype: impl FnMut(&Self, T) -> Ty<'tcx>, ) -> PlaceTy<'tcx> where V: ::std::fmt::Debug, @@ -110,8 +110,12 @@ impl<'tcx> PlaceTy<'tcx> { PlaceTy { ty: self.ty, variant_index: Some(index) } } ProjectionElem::Field(f, fty) => PlaceTy::from_ty(handle_field(&self, f, fty)), - ProjectionElem::OpaqueCast(ty) => PlaceTy::from_ty(handle_opaque_cast(&self, ty)), - ProjectionElem::Subtype(_) => PlaceTy::from_ty(self.ty), + ProjectionElem::OpaqueCast(ty) => { + PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty)) + } + ProjectionElem::Subtype(ty) => { + PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty)) + } }; debug!("projection_ty self: {:?} elem: {:?} yields: {:?}", self, elem, answer); answer diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index 4447ff0798c..7a5b3585d59 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -112,8 +112,6 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { let mut union_path = None; for (place_ref, elem) in data.rev_lookup.un_derefer.iter_projections(place.as_ref()) { - // We don't care creating `MovePath` for `ProjectionElem::Subtype(T)` because it's for debugging/validating - // purposes it's movement doesn't affect anything. let body = self.builder.body; let tcx = self.builder.tcx; let place_ty = place_ref.ty(body, tcx).ty; @@ -229,8 +227,9 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { } _ => bug!("Unexpected type {place_ty:#?}"), }, - // `OpaqueCast` only transmutes the type, so no moves there and - // `Downcast` only changes information about a `Place` without moving + // `OpaqueCast`:Only transmutes the type, so no moves there. + // `Downcast` :Only changes information about a `Place` without moving. + // `Subtype` :Only transmutes the type, so moves. // So it's safe to skip these. ProjectionElem::OpaqueCast(_) | ProjectionElem::Subtype(_) diff --git a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs index 594bb9bf142..1cc049d5a22 100644 --- a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs +++ b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs @@ -24,24 +24,31 @@ impl<'a, 'tcx> MutVisitor<'tcx> for SubTypeChecker<'a, 'tcx> { rvalue: &mut Rvalue<'tcx>, location: Location, ) { - let place_ty = place.ty(self.local_decls, self.tcx); + let mut place_ty = place.ty(self.local_decls, self.tcx).ty; let mut rval_ty = rvalue.ty(self.local_decls, self.tcx); - if place_ty.ty != rval_ty { - // Not erasing this causes `Free Regions` errors in validator, - // when rval is `ReStatic`. - rval_ty = self.tcx.erase_regions_ty(rval_ty); + // Not erasing this causes `Free Regions` errors in validator, + // when rval is `ReStatic`. + rval_ty = self.tcx.erase_regions_ty(rval_ty); + place_ty = self.tcx.erase_regions(place_ty); + if place_ty != rval_ty { let temp = self .patcher .new_temp(rval_ty, self.local_decls[place.as_ref().local].source_info.span); let new_place = Place::from(temp); self.patcher.add_assign(location, new_place, rvalue.clone()); - let subtyped = - new_place.project_deeper(&[ProjectionElem::Subtype(place_ty.ty)], self.tcx); + let subtyped = new_place.project_deeper(&[ProjectionElem::Subtype(place_ty)], self.tcx); *rvalue = Rvalue::Use(Operand::Move(subtyped)); } } } +// Aim here is to do this kind of transformation: +// +// let place: place_ty = rval; +// // gets transformed to +// let temp: rval_ty = rval; +// let place: place_ty = temp as place_ty; +// pub fn subtype_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let patch = MirPatch::new(body); let mut checker = SubTypeChecker { tcx, patcher: patch, local_decls: &body.local_decls }; diff --git a/src/tools/stable-mir-dev b/src/tools/stable-mir-dev deleted file mode 160000 index 9434648ba82..00000000000 --- a/src/tools/stable-mir-dev +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9434648ba82a0519222677bcc3fdf8b4f1ac5ced diff --git a/tests/mir-opt/inline/inline_generator.main.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_generator.main.Inline.panic-abort.diff index 1c2077ef5a3..4a816e024c5 100644 --- a/tests/mir-opt/inline/inline_generator.main.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_generator.main.Inline.panic-abort.diff @@ -37,7 +37,7 @@ - _4 = g() -> [return: bb1, unwind unreachable]; + StorageLive(_5); + _5 = {generator@$DIR/inline_generator.rs:16:5: 16:8 (#0)}; -+ _4 = move (_5as {generator@$DIR/inline_generator.rs:16:5: 16:8}); ++ _4 = move (_5 as subtype {generator@$DIR/inline_generator.rs:16:5: 16:8}); + StorageDead(_5); + _3 = &mut _4; + _2 = Pin::<&mut {generator@$DIR/inline_generator.rs:16:5: 16:8}> { pointer: move _3 }; diff --git a/tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff index 689bfcb0a6a..2b910cd6543 100644 --- a/tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff @@ -40,7 +40,7 @@ - bb1: { + StorageLive(_5); + _5 = {generator@$DIR/inline_generator.rs:16:5: 16:8 (#0)}; -+ _4 = move (_5as {generator@$DIR/inline_generator.rs:16:5: 16:8}); ++ _4 = move (_5 as subtype {generator@$DIR/inline_generator.rs:16:5: 16:8}); + StorageDead(_5); _3 = &mut _4; - _2 = Pin::<&mut {generator@$DIR/inline_generator.rs:16:5: 16:8}>::new(move _3) -> [return: bb2, unwind: bb5]; diff --git a/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-abort.mir b/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-abort.mir index e5c9815c780..ec894fa511a 100644 --- a/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-abort.mir +++ b/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-abort.mir @@ -22,7 +22,6 @@ fn main() -> () { let _24: i32; let mut _26: *const i32; let _27: (); - let mut _29: for<'a> fn(&'a i32) -> &'a i32; scope 1 { debug x => _1; let _3: &mut i32; @@ -106,8 +105,7 @@ fn main() -> () { StorageLive(_14); _14 = {closure@main::{closure#0}}; Retag(_14); - _29 = move _14 as for<'a> fn(&'a i32) -> &'a i32 (PointerCoercion(ClosureFnPointer(Normal))); - _13 = move (_29as for<'a> fn(&'a i32) -> &'a i32); + _13 = move _14 as for<'a> fn(&'a i32) -> &'a i32 (PointerCoercion(ClosureFnPointer(Normal))); StorageDead(_14); StorageLive(_15); StorageLive(_16); diff --git a/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir b/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir index f08cf6f3d78..d89124f699b 100644 --- a/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir +++ b/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir @@ -22,7 +22,6 @@ fn main() -> () { let _24: i32; let mut _26: *const i32; let _27: (); - let mut _29: for<'a> fn(&'a i32) -> &'a i32; scope 1 { debug x => _1; let _3: &mut i32; @@ -106,8 +105,7 @@ fn main() -> () { StorageLive(_14); _14 = {closure@main::{closure#0}}; Retag(_14); - _29 = move _14 as for<'a> fn(&'a i32) -> &'a i32 (PointerCoercion(ClosureFnPointer(Normal))); - _13 = move (_29as for<'a> fn(&'a i32) -> &'a i32); + _13 = move _14 as for<'a> fn(&'a i32) -> &'a i32 (PointerCoercion(ClosureFnPointer(Normal))); StorageDead(_14); StorageLive(_15); StorageLive(_16);