Skip to content

Commit 50d4440

Browse files
Implement MIR and drop semantics for unsafe binders
1 parent 3c1e750 commit 50d4440

File tree

50 files changed

+543
-94
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+543
-94
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1655,7 +1655,7 @@ impl GenBlockKind {
16551655
}
16561656

16571657
/// Whether we're unwrapping or wrapping an unsafe binder
1658-
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1658+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
16591659
#[derive(Encodable, Decodable, HashStable_Generic)]
16601660
pub enum UnsafeBinderCastKind {
16611661
// 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
@@ -3976,7 +3976,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
39763976
ProjectionElem::ConstantIndex { .. }
39773977
| ProjectionElem::Subslice { .. }
39783978
| ProjectionElem::Subtype(_)
3979-
| ProjectionElem::Index(_) => kind,
3979+
| ProjectionElem::Index(_)
3980+
| ProjectionElem::UnsafeBinderCast(..) => kind,
39803981
},
39813982
place_ty.projection_ty(tcx, elem),
39823983
)

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
@@ -167,7 +167,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
167167
| ProjectionElem::ConstantIndex { .. }
168168
| ProjectionElem::OpaqueCast { .. }
169169
| ProjectionElem::Subslice { .. }
170-
| ProjectionElem::Downcast(..),
170+
| ProjectionElem::Downcast(..)
171+
| ProjectionElem::UnsafeBinderCast(..),
171172
],
172173
} => bug!("Unexpected immutable place."),
173174
}

compiler/rustc_borrowck/src/lib.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1690,7 +1690,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
16901690
// So it's safe to skip these.
16911691
ProjectionElem::OpaqueCast(_)
16921692
| ProjectionElem::Subtype(_)
1693-
| ProjectionElem::Downcast(_, _) => (),
1693+
| ProjectionElem::Downcast(_, _)
1694+
| ProjectionElem::UnsafeBinderCast(_, _) => (),
16941695
}
16951696

16961697
place_ty = place_ty.projection_ty(tcx, elem);
@@ -1924,6 +1925,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
19241925
// FIXME: is this true even if P is an adt with a dtor?
19251926
{ }
19261927

1928+
ProjectionElem::UnsafeBinderCast(..) => {
1929+
check_parent_of_field(self, location, place_base, span, state);
1930+
}
1931+
19271932
// assigning to (*P) requires P to be initialized
19281933
ProjectionElem::Deref => {
19291934
self.check_if_full_path_is_moved(
@@ -2304,7 +2309,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
23042309
| ProjectionElem::Subslice { .. }
23052310
| ProjectionElem::Subtype(..)
23062311
| ProjectionElem::OpaqueCast { .. }
2307-
| ProjectionElem::Downcast(..) => {
2312+
| ProjectionElem::Downcast(..)
2313+
| ProjectionElem::UnsafeBinderCast(..) => {
23082314
let upvar_field_projection = self.is_upvar_field_projection(place);
23092315
if let Some(field) = upvar_field_projection {
23102316
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
@@ -249,7 +249,8 @@ fn place_components_conflict<'tcx>(
249249
| (ProjectionElem::Subslice { .. }, _, _)
250250
| (ProjectionElem::OpaqueCast { .. }, _, _)
251251
| (ProjectionElem::Subtype(_), _, _)
252-
| (ProjectionElem::Downcast { .. }, _, _) => {
252+
| (ProjectionElem::Downcast { .. }, _, _)
253+
| (ProjectionElem::UnsafeBinderCast(..), _, _) => {
253254
// Recursive case. This can still be disjoint on a
254255
// further iteration if this a shallow access and
255256
// there's a deref later on, e.g., a borrow
@@ -518,5 +519,9 @@ fn place_projection_conflict<'tcx>(
518519
pi1_elem,
519520
pi2_elem
520521
),
522+
523+
(ProjectionElem::UnsafeBinderCast(..), _) => {
524+
todo!()
525+
}
521526
}
522527
}

compiler/rustc_borrowck/src/prefixes.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ impl<'tcx> Iterator for Prefixes<'tcx> {
6666
self.next = Some(cursor_base);
6767
return Some(cursor);
6868
}
69+
ProjectionElem::UnsafeBinderCast(..) => {
70+
self.next = Some(cursor_base);
71+
return Some(cursor);
72+
}
6973
ProjectionElem::Downcast(..)
7074
| ProjectionElem::Subslice { .. }
7175
| ProjectionElem::OpaqueCast { .. }

compiler/rustc_borrowck/src/type_check/mod.rs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,46 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
284284
)
285285
.unwrap();
286286
}
287+
ProjectionElem::UnsafeBinderCast(kind, ty) => match kind {
288+
hir::UnsafeBinderCastKind::Wrap => {
289+
let ty::UnsafeBinder(binder_ty) = *ty.kind() else {
290+
unreachable!();
291+
};
292+
let expected_ty = self.typeck.infcx.instantiate_binder_with_fresh_vars(
293+
self.body().source_info(location).span,
294+
BoundRegionConversionTime::HigherRankedType,
295+
binder_ty.into(),
296+
);
297+
self.typeck
298+
.relate_types(
299+
expected_ty,
300+
context.ambient_variance(),
301+
base_ty.ty,
302+
location.to_locations(),
303+
ConstraintCategory::TypeAnnotation,
304+
)
305+
.unwrap();
306+
}
307+
hir::UnsafeBinderCastKind::Unwrap => {
308+
let ty::UnsafeBinder(binder_ty) = *base_ty.ty.kind() else {
309+
unreachable!();
310+
};
311+
let found_ty = self.typeck.infcx.instantiate_binder_with_fresh_vars(
312+
self.body().source_info(location).span,
313+
BoundRegionConversionTime::HigherRankedType,
314+
binder_ty.into(),
315+
);
316+
self.typeck
317+
.relate_types(
318+
ty,
319+
context.ambient_variance(),
320+
found_ty,
321+
location.to_locations(),
322+
ConstraintCategory::TypeAnnotation,
323+
)
324+
.unwrap();
325+
}
326+
},
287327
ProjectionElem::Subtype(_) => {
288328
bug!("ProjectionElem::Subtype shouldn't exist in borrowck")
289329
}
@@ -2413,7 +2453,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
24132453
| ProjectionElem::OpaqueCast(..)
24142454
| ProjectionElem::Index(..)
24152455
| ProjectionElem::ConstantIndex { .. }
2416-
| ProjectionElem::Subslice { .. } => {
2456+
| ProjectionElem::Subslice { .. }
2457+
| ProjectionElem::UnsafeBinderCast(..) => {
24172458
// other field access
24182459
}
24192460
ProjectionElem::Subtype(_) => {

compiler/rustc_codegen_cranelift/src/base.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -977,7 +977,9 @@ pub(crate) fn codegen_place<'tcx>(
977977
cplace = cplace.place_deref(fx);
978978
}
979979
PlaceElem::OpaqueCast(ty) => bug!("encountered OpaqueCast({ty}) in codegen"),
980-
PlaceElem::Subtype(ty) => cplace = cplace.place_transmute_type(fx, fx.monomorphize(ty)),
980+
PlaceElem::Subtype(ty) | PlaceElem::UnsafeBinderCast(_, ty) => {
981+
cplace = cplace.place_transmute_type(fx, fx.monomorphize(ty));
982+
}
981983
PlaceElem::Field(field, _ty) => {
982984
cplace = cplace.place_field(fx, field);
983985
}

compiler/rustc_codegen_ssa/src/mir/place.rs

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

0 commit comments

Comments
 (0)