Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
have better explanation for relate_types
  • Loading branch information
ouz-a authored and Mark-Simulacrum committed Dec 4, 2023
commit 63976da0e8dbeecbbe9ad5f74441d5ee48945f32
8 changes: 3 additions & 5 deletions compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_cranelift/src/value_and_place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_const_eval/src/util/compare_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/mir/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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})")?;
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_middle/src/mir/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Expand Down
10 changes: 7 additions & 3 deletions compiler/rustc_middle/src/mir/tcx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down
7 changes: 3 additions & 4 deletions compiler/rustc_mir_dataflow/src/move_paths/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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(_)
Expand Down
21 changes: 14 additions & 7 deletions compiler/rustc_mir_transform/src/add_subtyping_projections.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
Expand Down
1 change: 0 additions & 1 deletion src/tools/stable-mir-dev
Submodule stable-mir-dev deleted from 943464
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down