have better explanation for relate_types
This commit is contained in:
parent
6f0c5ee2d4
commit
5d753abb30
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
@ -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})")?;
|
||||
|
@ -1077,9 +1077,12 @@ pub enum ProjectionElem<V, T> {
|
||||
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`.
|
||||
|
@ -69,7 +69,7 @@ impl<'tcx> PlaceTy<'tcx> {
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
elem: &ProjectionElem<V, T>,
|
||||
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
|
||||
|
@ -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(_)
|
||||
|
@ -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 };
|
||||
|
@ -1 +0,0 @@
|
||||
Subproject commit 9434648ba82a0519222677bcc3fdf8b4f1ac5ced
|
@ -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 };
|
||||
|
@ -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];
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user