Skip to content

Commit e4a4137

Browse files
Implement MIR projection for unsafe binder cast
1 parent 99e5ad9 commit e4a4137

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

16091609
/// Whether we're unwrapping or wrapping an unsafe binder
1610-
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1610+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
16111611
#[derive(Encodable, Decodable, HashStable_Generic)]
16121612
pub enum UnsafeBinderCastKind {
16131613
// 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
@@ -1728,7 +1728,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
17281728
// So it's safe to skip these.
17291729
ProjectionElem::OpaqueCast(_)
17301730
| ProjectionElem::Subtype(_)
1731-
| ProjectionElem::Downcast(_, _) => (),
1731+
| ProjectionElem::Downcast(_, _)
1732+
| ProjectionElem::UnsafeBinderCast(_, _) => (),
17321733
}
17331734

17341735
place_ty = place_ty.projection_ty(tcx, elem);
@@ -1956,7 +1957,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
19561957
ProjectionElem::OpaqueCast(_) |
19571958
ProjectionElem::ConstantIndex { .. } |
19581959
// assigning to P[i] requires P to be valid.
1959-
ProjectionElem::Downcast(_/*adt_def*/, _/*variant_idx*/) =>
1960+
ProjectionElem::Downcast(_/*adt_def*/, _/*variant_idx*/) |
1961+
ProjectionElem::UnsafeBinderCast(..) =>
19601962
// assigning to (P->variant) is okay if assigning to `P` is okay
19611963
//
19621964
// FIXME: is this true even if P is an adt with a dtor?
@@ -2345,7 +2347,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
23452347
| ProjectionElem::Subslice { .. }
23462348
| ProjectionElem::Subtype(..)
23472349
| ProjectionElem::OpaqueCast { .. }
2348-
| ProjectionElem::Downcast(..) => {
2350+
| ProjectionElem::Downcast(..)
2351+
| ProjectionElem::UnsafeBinderCast(..) => {
23492352
let upvar_field_projection = self.is_upvar_field_projection(place);
23502353
if let Some(field) = upvar_field_projection {
23512354
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

@@ -2746,7 +2788,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
27462788
| ProjectionElem::OpaqueCast(..)
27472789
| ProjectionElem::Index(..)
27482790
| ProjectionElem::ConstantIndex { .. }
2749-
| ProjectionElem::Subslice { .. } => {
2791+
| ProjectionElem::Subslice { .. }
2792+
| ProjectionElem::UnsafeBinderCast(..) => {
27502793
// other field access
27512794
}
27522795
ProjectionElem::Subtype(_) => {

compiler/rustc_codegen_ssa/src/mir/place.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
498498
bug!("encountered OpaqueCast({ty}) in codegen")
499499
}
500500
mir::ProjectionElem::Subtype(ty) => cg_base.project_type(bx, self.monomorphize(ty)),
501+
mir::ProjectionElem::UnsafeBinderCast(_, ty) => {
502+
cg_base.project_type(bx, self.monomorphize(ty))
503+
}
501504
mir::ProjectionElem::Index(index) => {
502505
let index = &mir::Operand::Copy(mir::Place::from(index));
503506
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
@@ -341,7 +341,8 @@ where
341341
| ProjectionElem::ConstantIndex { .. }
342342
| ProjectionElem::Subslice { .. }
343343
| ProjectionElem::Downcast(_, _)
344-
| ProjectionElem::Index(_) => {}
344+
| ProjectionElem::Index(_)
345+
| ProjectionElem::UnsafeBinderCast(..) => {}
345346
}
346347

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

0 commit comments

Comments
 (0)