Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 2fd3007

Browse files
authored
Rollup merge of rust-lang#130514 - compiler-errors:unsafe-binders, r=oli-obk
Implement MIR lowering for unsafe binders This is the final bit of the unsafe binders puzzle. It implements MIR, CTFE, and codegen for unsafe binders, and enforces that (for now) they are `Copy`. Later on, I'll introduce a new trait that relaxes this requirement to being "is `Copy` or `ManuallyDrop<T>`" which more closely models how we treat union fields. Namely, wrapping unsafe binders is now `Rvalue::WrapUnsafeBinder`, which acts much like an `Rvalue::Aggregate`. Unwrapping unsafe binders are implemented as a MIR projection `ProjectionElem::UnwrapUnsafeBinder`, which acts much like `ProjectionElem::Field`. Tracking: - rust-lang#130516
2 parents e08cd3c + 442b9a9 commit 2fd3007

File tree

56 files changed

+589
-102
lines changed

Some content is hidden

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

56 files changed

+589
-102
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1657,7 +1657,7 @@ impl GenBlockKind {
16571657
}
16581658

16591659
/// Whether we're unwrapping or wrapping an unsafe binder
1660-
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1660+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
16611661
#[derive(Encodable, Decodable, HashStable_Generic)]
16621662
pub enum UnsafeBinderCastKind {
16631663
// 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
@@ -3915,7 +3915,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
39153915
ProjectionElem::ConstantIndex { .. }
39163916
| ProjectionElem::Subslice { .. }
39173917
| ProjectionElem::Subtype(_)
3918-
| ProjectionElem::Index(_) => kind,
3918+
| ProjectionElem::Index(_)
3919+
| ProjectionElem::UnwrapUnsafeBinder(_) => kind,
39193920
},
39203921
place_ty.projection_ty(tcx, elem),
39213922
)

compiler/rustc_borrowck/src/diagnostics/mod.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
370370
ProjectionElem::Downcast(..) => (),
371371
ProjectionElem::OpaqueCast(..) => (),
372372
ProjectionElem::Subtype(..) => (),
373+
ProjectionElem::UnwrapUnsafeBinder(_) => (),
373374
ProjectionElem::Field(field, _ty) => {
374375
// FIXME(project-rfc_2229#36): print capture precisely here.
375376
if let Some(field) = self.is_upvar_field_projection(PlaceRef {
@@ -450,9 +451,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
450451
PlaceRef { local, projection: proj_base }.ty(self.body, self.infcx.tcx)
451452
}
452453
ProjectionElem::Downcast(..) => place.ty(self.body, self.infcx.tcx),
453-
ProjectionElem::Subtype(ty) | ProjectionElem::OpaqueCast(ty) => {
454-
PlaceTy::from_ty(*ty)
455-
}
454+
ProjectionElem::Subtype(ty)
455+
| ProjectionElem::OpaqueCast(ty)
456+
| ProjectionElem::UnwrapUnsafeBinder(ty) => PlaceTy::from_ty(*ty),
456457
ProjectionElem::Field(_, field_type) => PlaceTy::from_ty(*field_type),
457458
},
458459
};

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::UnwrapUnsafeBinder(_),
171172
],
172173
} => bug!("Unexpected immutable place."),
173174
}

compiler/rustc_borrowck/src/lib.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1398,6 +1398,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
13981398
self.consume_operand(location, (operand, span), state);
13991399
}
14001400
}
1401+
1402+
Rvalue::WrapUnsafeBinder(op, _) => {
1403+
self.consume_operand(location, (op, span), state);
1404+
}
14011405
}
14021406
}
14031407

@@ -1770,7 +1774,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
17701774
// So it's safe to skip these.
17711775
ProjectionElem::OpaqueCast(_)
17721776
| ProjectionElem::Subtype(_)
1773-
| ProjectionElem::Downcast(_, _) => (),
1777+
| ProjectionElem::Downcast(_, _)
1778+
| ProjectionElem::UnwrapUnsafeBinder(_) => (),
17741779
}
17751780

17761781
place_ty = place_ty.projection_ty(tcx, elem);
@@ -2004,6 +2009,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
20042009
// FIXME: is this true even if P is an adt with a dtor?
20052010
{ }
20062011

2012+
ProjectionElem::UnwrapUnsafeBinder(_) => {
2013+
check_parent_of_field(self, location, place_base, span, state);
2014+
}
2015+
20072016
// assigning to (*P) requires P to be initialized
20082017
ProjectionElem::Deref => {
20092018
self.check_if_full_path_is_moved(
@@ -2384,7 +2393,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
23842393
| ProjectionElem::Subslice { .. }
23852394
| ProjectionElem::Subtype(..)
23862395
| ProjectionElem::OpaqueCast { .. }
2387-
| ProjectionElem::Downcast(..) => {
2396+
| ProjectionElem::Downcast(..)
2397+
| ProjectionElem::UnwrapUnsafeBinder(_) => {
23882398
let upvar_field_projection = self.is_upvar_field_projection(place);
23892399
if let Some(field) = upvar_field_projection {
23902400
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::UnwrapUnsafeBinder(_), _, _) => {
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::UnwrapUnsafeBinder(_), _) => {
525+
todo!()
526+
}
522527
}
523528
}

compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,10 @@ impl<'a, 'tcx> LoanInvalidationsGenerator<'a, 'tcx> {
325325
self.consume_operand(location, operand);
326326
}
327327
}
328+
329+
Rvalue::WrapUnsafeBinder(op, _) => {
330+
self.consume_operand(location, op);
331+
}
328332
}
329333
}
330334

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::UnwrapUnsafeBinder(_) => {
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: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,25 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
302302
)
303303
.unwrap();
304304
}
305+
ProjectionElem::UnwrapUnsafeBinder(ty) => {
306+
let ty::UnsafeBinder(binder_ty) = *base_ty.ty.kind() else {
307+
unreachable!();
308+
};
309+
let found_ty = self.typeck.infcx.instantiate_binder_with_fresh_vars(
310+
self.body().source_info(location).span,
311+
BoundRegionConversionTime::HigherRankedType,
312+
binder_ty.into(),
313+
);
314+
self.typeck
315+
.relate_types(
316+
ty,
317+
context.ambient_variance(),
318+
found_ty,
319+
location.to_locations(),
320+
ConstraintCategory::Boring,
321+
)
322+
.unwrap();
323+
}
305324
ProjectionElem::Subtype(_) => {
306325
bug!("ProjectionElem::Subtype shouldn't exist in borrowck")
307326
}
@@ -2233,6 +2252,27 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
22332252
self.check_operand(right, location);
22342253
}
22352254

2255+
Rvalue::WrapUnsafeBinder(op, ty) => {
2256+
self.check_operand(op, location);
2257+
let operand_ty = op.ty(self.body, self.tcx());
2258+
2259+
let ty::UnsafeBinder(binder_ty) = *ty.kind() else {
2260+
unreachable!();
2261+
};
2262+
let expected_ty = self.infcx.instantiate_binder_with_fresh_vars(
2263+
self.body().source_info(location).span,
2264+
BoundRegionConversionTime::HigherRankedType,
2265+
binder_ty.into(),
2266+
);
2267+
self.sub_types(
2268+
operand_ty,
2269+
expected_ty,
2270+
location.to_locations(),
2271+
ConstraintCategory::Boring,
2272+
)
2273+
.unwrap();
2274+
}
2275+
22362276
Rvalue::RawPtr(..)
22372277
| Rvalue::ThreadLocalRef(..)
22382278
| Rvalue::Len(..)
@@ -2258,7 +2298,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
22582298
| Rvalue::NullaryOp(..)
22592299
| Rvalue::CopyForDeref(..)
22602300
| Rvalue::UnaryOp(..)
2261-
| Rvalue::Discriminant(..) => None,
2301+
| Rvalue::Discriminant(..)
2302+
| Rvalue::WrapUnsafeBinder(..) => None,
22622303

22632304
Rvalue::Aggregate(aggregate, _) => match **aggregate {
22642305
AggregateKind::Adt(_, _, _, user_ty, _) => user_ty,
@@ -2450,7 +2491,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
24502491
| ProjectionElem::OpaqueCast(..)
24512492
| ProjectionElem::Index(..)
24522493
| ProjectionElem::ConstantIndex { .. }
2453-
| ProjectionElem::Subslice { .. } => {
2494+
| ProjectionElem::Subslice { .. }
2495+
| ProjectionElem::UnwrapUnsafeBinder(_) => {
24542496
// other field access
24552497
}
24562498
ProjectionElem::Subtype(_) => {

compiler/rustc_codegen_cranelift/src/base.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -925,6 +925,10 @@ fn codegen_stmt<'tcx>(
925925
}
926926
crate::discriminant::codegen_set_discriminant(fx, lval, variant_index);
927927
}
928+
Rvalue::WrapUnsafeBinder(ref operand, _to_ty) => {
929+
let operand = codegen_operand(fx, operand);
930+
lval.write_cvalue_transmute(fx, operand);
931+
}
928932
}
929933
}
930934
StatementKind::StorageLive(_)
@@ -993,7 +997,9 @@ pub(crate) fn codegen_place<'tcx>(
993997
cplace = cplace.place_deref(fx);
994998
}
995999
PlaceElem::OpaqueCast(ty) => bug!("encountered OpaqueCast({ty}) in codegen"),
996-
PlaceElem::Subtype(ty) => cplace = cplace.place_transmute_type(fx, fx.monomorphize(ty)),
1000+
PlaceElem::Subtype(ty) | PlaceElem::UnwrapUnsafeBinder(ty) => {
1001+
cplace = cplace.place_transmute_type(fx, fx.monomorphize(ty));
1002+
}
9971003
PlaceElem::Field(field, _ty) => {
9981004
cplace = cplace.place_field(fx, field);
9991005
}

0 commit comments

Comments
 (0)