Skip to content

Commit 59ed54f

Browse files
Implement MIR projection for unsafe binder cast
1 parent b1c170f commit 59ed54f

File tree

24 files changed

+138
-28
lines changed

24 files changed

+138
-28
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1662,7 +1662,7 @@ impl GenBlockKind {
16621662
}
16631663

16641664
/// Whether we're unwrapping or wrapping an unsafe binder
1665-
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1665+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
16661666
#[derive(Encodable, Decodable, HashStable_Generic)]
16671667
pub enum UnsafeBinderCastKind {
16681668
// e.g. `&i32` -> `unsafe<'a> &'a i32`

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3977,7 +3977,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
39773977
ProjectionElem::ConstantIndex { .. }
39783978
| ProjectionElem::Subslice { .. }
39793979
| ProjectionElem::Subtype(_)
3980-
| ProjectionElem::Index(_) => kind,
3980+
| ProjectionElem::Index(_)
3981+
| ProjectionElem::UnsafeBinderCast(..) => kind,
39813982
},
39823983
place_ty.projection_ty(tcx, elem),
39833984
)

compiler/rustc_borrowck/src/diagnostics/mod.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
244244
ProjectionElem::Downcast(..) => (),
245245
ProjectionElem::OpaqueCast(..) => (),
246246
ProjectionElem::Subtype(..) => (),
247+
ProjectionElem::UnsafeBinderCast(..) => (),
247248
ProjectionElem::Field(field, _ty) => {
248249
// FIXME(project-rfc_2229#36): print capture precisely here.
249250
if let Some(field) = self.is_upvar_field_projection(PlaceRef {
@@ -324,9 +325,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
324325
PlaceRef { local, projection: proj_base }.ty(self.body, self.infcx.tcx)
325326
}
326327
ProjectionElem::Downcast(..) => place.ty(self.body, self.infcx.tcx),
327-
ProjectionElem::Subtype(ty) | ProjectionElem::OpaqueCast(ty) => {
328-
PlaceTy::from_ty(*ty)
329-
}
328+
ProjectionElem::Subtype(ty)
329+
| ProjectionElem::OpaqueCast(ty)
330+
| ProjectionElem::UnsafeBinderCast(_, ty) => PlaceTy::from_ty(*ty),
330331
ProjectionElem::Field(_, field_type) => PlaceTy::from_ty(*field_type),
331332
},
332333
};

compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
168168
| ProjectionElem::ConstantIndex { .. }
169169
| ProjectionElem::OpaqueCast { .. }
170170
| ProjectionElem::Subslice { .. }
171-
| ProjectionElem::Downcast(..),
171+
| ProjectionElem::Downcast(..)
172+
| ProjectionElem::UnsafeBinderCast(..),
172173
],
173174
} => bug!("Unexpected immutable place."),
174175
}

compiler/rustc_borrowck/src/lib.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1716,7 +1716,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
17161716
// So it's safe to skip these.
17171717
ProjectionElem::OpaqueCast(_)
17181718
| ProjectionElem::Subtype(_)
1719-
| ProjectionElem::Downcast(_, _) => (),
1719+
| ProjectionElem::Downcast(_, _)
1720+
| ProjectionElem::UnsafeBinderCast(_, _) => (),
17201721
}
17211722

17221723
place_ty = place_ty.projection_ty(tcx, elem);
@@ -1944,7 +1945,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
19441945
ProjectionElem::OpaqueCast(_) |
19451946
ProjectionElem::ConstantIndex { .. } |
19461947
// assigning to P[i] requires P to be valid.
1947-
ProjectionElem::Downcast(_/*adt_def*/, _/*variant_idx*/) =>
1948+
ProjectionElem::Downcast(_/*adt_def*/, _/*variant_idx*/) |
1949+
ProjectionElem::UnsafeBinderCast(..) =>
19481950
// assigning to (P->variant) is okay if assigning to `P` is okay
19491951
//
19501952
// FIXME: is this true even if P is an adt with a dtor?
@@ -2330,7 +2332,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
23302332
| ProjectionElem::Subslice { .. }
23312333
| ProjectionElem::Subtype(..)
23322334
| ProjectionElem::OpaqueCast { .. }
2333-
| ProjectionElem::Downcast(..) => {
2335+
| ProjectionElem::Downcast(..)
2336+
| ProjectionElem::UnsafeBinderCast(..) => {
23342337
let upvar_field_projection = self.is_upvar_field_projection(place);
23352338
if let Some(field) = upvar_field_projection {
23362339
let upvar = &self.upvars[field.index()];

compiler/rustc_borrowck/src/places_conflict.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,8 @@ fn place_components_conflict<'tcx>(
250250
| (ProjectionElem::Subslice { .. }, _, _)
251251
| (ProjectionElem::OpaqueCast { .. }, _, _)
252252
| (ProjectionElem::Subtype(_), _, _)
253-
| (ProjectionElem::Downcast { .. }, _, _) => {
253+
| (ProjectionElem::Downcast { .. }, _, _)
254+
| (ProjectionElem::UnsafeBinderCast(..), _, _) => {
254255
// Recursive case. This can still be disjoint on a
255256
// further iteration if this a shallow access and
256257
// there's a deref later on, e.g., a borrow
@@ -519,5 +520,9 @@ fn place_projection_conflict<'tcx>(
519520
pi1_elem,
520521
pi2_elem
521522
),
523+
524+
(ProjectionElem::UnsafeBinderCast(..), _) => {
525+
todo!()
526+
}
522527
}
523528
}

compiler/rustc_borrowck/src/prefixes.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ impl<'tcx> Iterator for Prefixes<'tcx> {
7070
| ProjectionElem::Subslice { .. }
7171
| ProjectionElem::OpaqueCast { .. }
7272
| ProjectionElem::ConstantIndex { .. }
73-
| ProjectionElem::Index(_) => {
73+
| ProjectionElem::Index(_)
74+
| ProjectionElem::UnsafeBinderCast(..) => {
7475
cursor = cursor_base;
7576
}
7677
ProjectionElem::Subtype(..) => {

compiler/rustc_borrowck/src/type_check/mod.rs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,48 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
719719
.unwrap();
720720
PlaceTy::from_ty(ty)
721721
}
722+
ProjectionElem::UnsafeBinderCast(kind, ty) => match kind {
723+
hir::UnsafeBinderCastKind::Wrap => {
724+
let ty::UnsafeBinder(binder_ty) = *ty.kind() else {
725+
bug!();
726+
};
727+
let expected_ty = self.cx.infcx.instantiate_binder_with_fresh_vars(
728+
self.body().source_info(location).span,
729+
BoundRegionConversionTime::HigherRankedType,
730+
binder_ty.into(),
731+
);
732+
self.cx
733+
.relate_types(
734+
expected_ty,
735+
self.get_ambient_variance(context),
736+
base_ty,
737+
location.to_locations(),
738+
ConstraintCategory::TypeAnnotation,
739+
)
740+
.unwrap();
741+
PlaceTy::from_ty(ty)
742+
}
743+
hir::UnsafeBinderCastKind::Unwrap => {
744+
let ty::UnsafeBinder(binder_ty) = *base_ty.kind() else {
745+
bug!();
746+
};
747+
let found_ty = self.cx.infcx.instantiate_binder_with_fresh_vars(
748+
self.body().source_info(location).span,
749+
BoundRegionConversionTime::HigherRankedType,
750+
binder_ty.into(),
751+
);
752+
self.cx
753+
.relate_types(
754+
ty,
755+
self.get_ambient_variance(context),
756+
found_ty,
757+
location.to_locations(),
758+
ConstraintCategory::TypeAnnotation,
759+
)
760+
.unwrap();
761+
PlaceTy::from_ty(ty)
762+
}
763+
},
722764
}
723765
}
724766

@@ -2705,7 +2747,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
27052747
| ProjectionElem::OpaqueCast(..)
27062748
| ProjectionElem::Index(..)
27072749
| ProjectionElem::ConstantIndex { .. }
2708-
| ProjectionElem::Subslice { .. } => {
2750+
| ProjectionElem::Subslice { .. }
2751+
| ProjectionElem::UnsafeBinderCast(..) => {
27092752
// other field access
27102753
}
27112754
ProjectionElem::Subtype(_) => {

compiler/rustc_codegen_ssa/src/mir/place.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
504504
bug!("encountered OpaqueCast({ty}) in codegen")
505505
}
506506
mir::ProjectionElem::Subtype(ty) => cg_base.project_type(bx, self.monomorphize(ty)),
507+
mir::ProjectionElem::UnsafeBinderCast(_, ty) => {
508+
cg_base.project_type(bx, self.monomorphize(ty))
509+
}
507510
mir::ProjectionElem::Index(index) => {
508511
let index = &mir::Operand::Copy(mir::Place::from(index));
509512
let index = self.codegen_operand(bx, index);

compiler/rustc_const_eval/src/check_consts/qualifs.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,8 @@ where
297297
| ProjectionElem::ConstantIndex { .. }
298298
| ProjectionElem::Subslice { .. }
299299
| ProjectionElem::Downcast(_, _)
300-
| ProjectionElem::Index(_) => {}
300+
| ProjectionElem::Index(_)
301+
| ProjectionElem::UnsafeBinderCast(..) => {}
301302
}
302303

303304
let base_ty = place_base.ty(cx.body, cx.tcx);

0 commit comments

Comments
 (0)