Skip to content

Commit 3ccd62d

Browse files
Implement MIR projection for unsafe binder cast
1 parent ce76ef3 commit 3ccd62d

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
@@ -1608,7 +1608,7 @@ impl GenBlockKind {
16081608
}
16091609

16101610
/// Whether we're unwrapping or wrapping an unsafe binder
1611-
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1611+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
16121612
#[derive(Encodable, Decodable, HashStable_Generic)]
16131613
pub enum UnsafeBinderCastKind {
16141614
// 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
@@ -3950,7 +3950,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
39503950
ProjectionElem::ConstantIndex { .. }
39513951
| ProjectionElem::Subslice { .. }
39523952
| ProjectionElem::Subtype(_)
3953-
| ProjectionElem::Index(_) => kind,
3953+
| ProjectionElem::Index(_)
3954+
| ProjectionElem::UnsafeBinderCast(..) => kind,
39543955
},
39553956
place_ty.projection_ty(tcx, elem),
39563957
)

compiler/rustc_borrowck/src/diagnostics/mod.rs

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

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
@@ -1724,7 +1724,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
17241724
// So it's safe to skip these.
17251725
ProjectionElem::OpaqueCast(_)
17261726
| ProjectionElem::Subtype(_)
1727-
| ProjectionElem::Downcast(_, _) => (),
1727+
| ProjectionElem::Downcast(_, _)
1728+
| ProjectionElem::UnsafeBinderCast(_, _) => (),
17281729
}
17291730

17301731
place_ty = place_ty.projection_ty(tcx, elem);
@@ -1952,7 +1953,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
19521953
ProjectionElem::OpaqueCast(_) |
19531954
ProjectionElem::ConstantIndex { .. } |
19541955
// assigning to P[i] requires P to be valid.
1955-
ProjectionElem::Downcast(_/*adt_def*/, _/*variant_idx*/) =>
1956+
ProjectionElem::Downcast(_/*adt_def*/, _/*variant_idx*/) |
1957+
ProjectionElem::UnsafeBinderCast(..) =>
19561958
// assigning to (P->variant) is okay if assigning to `P` is okay
19571959
//
19581960
// FIXME: is this true even if P is an adt with a dtor?
@@ -2341,7 +2343,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
23412343
| ProjectionElem::Subslice { .. }
23422344
| ProjectionElem::Subtype(..)
23432345
| ProjectionElem::OpaqueCast { .. }
2344-
| ProjectionElem::Downcast(..) => {
2346+
| ProjectionElem::Downcast(..)
2347+
| ProjectionElem::UnsafeBinderCast(..) => {
23452348
let upvar_field_projection = self.is_upvar_field_projection(place);
23462349
if let Some(field) = upvar_field_projection {
23472350
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
continue 'cursor;
7677
}

compiler/rustc_borrowck/src/type_check/mod.rs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,48 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
742742
.unwrap();
743743
PlaceTy::from_ty(ty)
744744
}
745+
ProjectionElem::UnsafeBinderCast(kind, ty) => match kind {
746+
hir::UnsafeBinderCastKind::Wrap => {
747+
let ty::UnsafeBinder(binder_ty) = *ty.kind() else {
748+
bug!();
749+
};
750+
let expected_ty = self.cx.infcx.instantiate_binder_with_fresh_vars(
751+
self.body().source_info(location).span,
752+
BoundRegionConversionTime::HigherRankedType,
753+
binder_ty.into(),
754+
);
755+
self.cx
756+
.relate_types(
757+
expected_ty,
758+
self.get_ambient_variance(context),
759+
base_ty,
760+
location.to_locations(),
761+
ConstraintCategory::TypeAnnotation,
762+
)
763+
.unwrap();
764+
PlaceTy::from_ty(ty)
765+
}
766+
hir::UnsafeBinderCastKind::Unwrap => {
767+
let ty::UnsafeBinder(binder_ty) = *base_ty.kind() else {
768+
bug!();
769+
};
770+
let found_ty = self.cx.infcx.instantiate_binder_with_fresh_vars(
771+
self.body().source_info(location).span,
772+
BoundRegionConversionTime::HigherRankedType,
773+
binder_ty.into(),
774+
);
775+
self.cx
776+
.relate_types(
777+
ty,
778+
self.get_ambient_variance(context),
779+
found_ty,
780+
location.to_locations(),
781+
ConstraintCategory::TypeAnnotation,
782+
)
783+
.unwrap();
784+
PlaceTy::from_ty(ty)
785+
}
786+
},
745787
}
746788
}
747789

@@ -2744,7 +2786,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
27442786
| ProjectionElem::OpaqueCast(..)
27452787
| ProjectionElem::Index(..)
27462788
| ProjectionElem::ConstantIndex { .. }
2747-
| ProjectionElem::Subslice { .. } => {
2789+
| ProjectionElem::Subslice { .. }
2790+
| ProjectionElem::UnsafeBinderCast(..) => {
27482791
// other field access
27492792
}
27502793
ProjectionElem::Subtype(_) => {

compiler/rustc_codegen_ssa/src/mir/place.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
497497
bug!("encountered OpaqueCast({ty}) in codegen")
498498
}
499499
mir::ProjectionElem::Subtype(ty) => cg_base.project_type(bx, self.monomorphize(ty)),
500+
mir::ProjectionElem::UnsafeBinderCast(_, ty) => {
501+
cg_base.project_type(bx, self.monomorphize(ty))
502+
}
500503
mir::ProjectionElem::Index(index) => {
501504
let index = &mir::Operand::Copy(mir::Place::from(index));
502505
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
@@ -337,7 +337,8 @@ where
337337
| ProjectionElem::ConstantIndex { .. }
338338
| ProjectionElem::Subslice { .. }
339339
| ProjectionElem::Downcast(_, _)
340-
| ProjectionElem::Index(_) => {}
340+
| ProjectionElem::Index(_)
341+
| ProjectionElem::UnsafeBinderCast(..) => {}
341342
}
342343

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

0 commit comments

Comments
 (0)