Skip to content

Commit b0f3844

Browse files
The rest of the owl
1 parent 96a66b0 commit b0f3844

File tree

58 files changed

+402
-93
lines changed

Some content is hidden

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

58 files changed

+402
-93
lines changed

compiler/rustc_ast/src/ast.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1668,7 +1668,7 @@ impl GenBlockKind {
16681668
}
16691669

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

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

+2-1
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

+4-3
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

+2-1
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

+8-2
Original file line numberDiff line numberDiff line change
@@ -1685,7 +1685,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
16851685
// So it's safe to skip these.
16861686
ProjectionElem::OpaqueCast(_)
16871687
| ProjectionElem::Subtype(_)
1688-
| ProjectionElem::Downcast(_, _) => (),
1688+
| ProjectionElem::Downcast(_, _)
1689+
| ProjectionElem::UnsafeBinderCast(_, _) => (),
16891690
}
16901691

16911692
place_ty = place_ty.projection_ty(tcx, elem);
@@ -1919,6 +1920,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
19191920
// FIXME: is this true even if P is an adt with a dtor?
19201921
{ }
19211922

1923+
ProjectionElem::UnsafeBinderCast(..) => {
1924+
check_parent_of_field(self, location, place_base, span, state);
1925+
}
1926+
19221927
// assigning to (*P) requires P to be initialized
19231928
ProjectionElem::Deref => {
19241929
self.check_if_full_path_is_moved(
@@ -2299,7 +2304,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
22992304
| ProjectionElem::Subslice { .. }
23002305
| ProjectionElem::Subtype(..)
23012306
| ProjectionElem::OpaqueCast { .. }
2302-
| ProjectionElem::Downcast(..) => {
2307+
| ProjectionElem::Downcast(..)
2308+
| ProjectionElem::UnsafeBinderCast(..) => {
23032309
let upvar_field_projection = self.is_upvar_field_projection(place);
23042310
if let Some(field) = upvar_field_projection {
23052311
let upvar = &self.upvars[field.index()];

compiler/rustc_borrowck/src/places_conflict.rs

+6-1
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

+4
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

+44-1
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,48 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
693693
.unwrap();
694694
PlaceTy::from_ty(ty)
695695
}
696+
ProjectionElem::UnsafeBinderCast(kind, ty) => match kind {
697+
hir::UnsafeBinderCastKind::Wrap => {
698+
let ty::UnsafeBinder(binder_ty) = *ty.kind() else {
699+
bug!();
700+
};
701+
let expected_ty = self.typeck.infcx.instantiate_binder_with_fresh_vars(
702+
self.body().source_info(location).span,
703+
BoundRegionConversionTime::HigherRankedType,
704+
binder_ty.into(),
705+
);
706+
self.typeck
707+
.relate_types(
708+
expected_ty,
709+
self.get_ambient_variance(context),
710+
base_ty,
711+
location.to_locations(),
712+
ConstraintCategory::TypeAnnotation,
713+
)
714+
.unwrap();
715+
PlaceTy::from_ty(ty)
716+
}
717+
hir::UnsafeBinderCastKind::Unwrap => {
718+
let ty::UnsafeBinder(binder_ty) = *base_ty.kind() else {
719+
bug!();
720+
};
721+
let found_ty = self.typeck.infcx.instantiate_binder_with_fresh_vars(
722+
self.body().source_info(location).span,
723+
BoundRegionConversionTime::HigherRankedType,
724+
binder_ty.into(),
725+
);
726+
self.typeck
727+
.relate_types(
728+
ty,
729+
self.get_ambient_variance(context),
730+
found_ty,
731+
location.to_locations(),
732+
ConstraintCategory::TypeAnnotation,
733+
)
734+
.unwrap();
735+
PlaceTy::from_ty(ty)
736+
}
737+
},
696738
}
697739
}
698740

@@ -2679,7 +2721,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
26792721
| ProjectionElem::OpaqueCast(..)
26802722
| ProjectionElem::Index(..)
26812723
| ProjectionElem::ConstantIndex { .. }
2682-
| ProjectionElem::Subslice { .. } => {
2724+
| ProjectionElem::Subslice { .. }
2725+
| ProjectionElem::UnsafeBinderCast(..) => {
26832726
// other field access
26842727
}
26852728
ProjectionElem::Subtype(_) => {

compiler/rustc_codegen_cranelift/src/base.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -983,7 +983,9 @@ pub(crate) fn codegen_place<'tcx>(
983983
cplace = cplace.place_deref(fx);
984984
}
985985
PlaceElem::OpaqueCast(ty) => bug!("encountered OpaqueCast({ty}) in codegen"),
986-
PlaceElem::Subtype(ty) => cplace = cplace.place_transmute_type(fx, fx.monomorphize(ty)),
986+
PlaceElem::Subtype(ty) | PlaceElem::UnsafeBinderCast(_, ty) => {
987+
cplace = cplace.place_transmute_type(fx, fx.monomorphize(ty));
988+
}
987989
PlaceElem::Field(field, _ty) => {
988990
cplace = cplace.place_field(fx, field);
989991
}

compiler/rustc_codegen_ssa/src/mir/place.rs

+3
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);

compiler/rustc_const_eval/src/check_consts/qualifs.rs

+2-1
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);

compiler/rustc_const_eval/src/interpret/projection.rs

+1
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,7 @@ where
381381
OpaqueCast(ty) => {
382382
span_bug!(self.cur_span(), "OpaqueCast({ty}) encountered after borrowck")
383383
}
384+
UnsafeBinderCast(_, target) => base.transmute(self.layout_of(target)?, self)?,
384385
// We don't want anything happening here, this is here as a dummy.
385386
Subtype(_) => base.transmute(base.layout(), self)?,
386387
Field(field, _) => self.project_field(base, field.index())?,

compiler/rustc_hir_typeck/src/expr.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1655,8 +1655,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16551655
hir_ty: Option<&'tcx hir::Ty<'tcx>>,
16561656
expected: Expectation<'tcx>,
16571657
) -> Ty<'tcx> {
1658-
self.dcx().span_err(inner_expr.span, "unsafe binder casts are not fully implemented");
1659-
16601658
match kind {
16611659
hir::UnsafeBinderCastKind::Wrap => {
16621660
let ascribed_ty =

compiler/rustc_middle/src/mir/pretty.rs

+11
Original file line numberDiff line numberDiff line change
@@ -1286,6 +1286,14 @@ fn pre_fmt_projection(projection: &[PlaceElem<'_>], fmt: &mut Formatter<'_>) ->
12861286
ProjectionElem::Index(_)
12871287
| ProjectionElem::ConstantIndex { .. }
12881288
| ProjectionElem::Subslice { .. } => {}
1289+
ProjectionElem::UnsafeBinderCast(kind, _) => match kind {
1290+
hir::UnsafeBinderCastKind::Wrap => {
1291+
write!(fmt, "wrap_unsafe_binder!(")?;
1292+
}
1293+
rustc_ast::UnsafeBinderCastKind::Unwrap => {
1294+
write!(fmt, "unwrap_unsafe_binder!(")?;
1295+
}
1296+
},
12891297
}
12901298
}
12911299

@@ -1334,6 +1342,9 @@ fn post_fmt_projection(projection: &[PlaceElem<'_>], fmt: &mut Formatter<'_>) ->
13341342
ProjectionElem::Subslice { from, to, from_end: false } => {
13351343
write!(fmt, "[{from:?}..{to:?}]")?;
13361344
}
1345+
ProjectionElem::UnsafeBinderCast(_, ty) => {
1346+
write!(fmt, "; {ty})")?;
1347+
}
13371348
}
13381349
}
13391350

compiler/rustc_middle/src/mir/statement.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ impl<V, T> ProjectionElem<V, T> {
6262
| Self::Subtype(_)
6363
| Self::ConstantIndex { .. }
6464
| Self::Subslice { .. }
65-
| Self::Downcast(_, _) => false,
65+
| Self::Downcast(_, _)
66+
| Self::UnsafeBinderCast(..) => false,
6667
}
6768
}
6869

@@ -76,7 +77,8 @@ impl<V, T> ProjectionElem<V, T> {
7677
| Self::Subtype(_)
7778
| Self::ConstantIndex { .. }
7879
| Self::Subslice { .. }
79-
| Self::Downcast(_, _) => true,
80+
| Self::Downcast(_, _)
81+
| Self::UnsafeBinderCast(..) => true,
8082
}
8183
}
8284

@@ -102,6 +104,9 @@ impl<V, T> ProjectionElem<V, T> {
102104
| Self::Subtype(_)
103105
| Self::OpaqueCast(_)
104106
| Self::Subslice { .. } => false,
107+
108+
// FIXME(unsafe_binders): Figure this out.
109+
Self::UnsafeBinderCast(..) => false,
105110
}
106111
}
107112
}

compiler/rustc_middle/src/mir/syntax.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
use rustc_abi::{FieldIdx, VariantIdx};
77
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece, Mutability};
88
use rustc_data_structures::packed::Pu128;
9-
use rustc_hir::CoroutineKind;
109
use rustc_hir::def_id::DefId;
10+
use rustc_hir::{CoroutineKind, UnsafeBinderCastKind};
1111
use rustc_index::IndexVec;
1212
use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
1313
use rustc_span::def_id::LocalDefId;
@@ -1210,6 +1210,8 @@ pub enum ProjectionElem<V, T> {
12101210
/// requiring an intermediate variable.
12111211
OpaqueCast(T),
12121212

1213+
UnsafeBinderCast(UnsafeBinderCastKind, T),
1214+
12131215
/// A `Subtype(T)` projection is applied to any `StatementKind::Assign` where
12141216
/// type of lvalue doesn't match the type of rvalue, the primary goal is making subtyping
12151217
/// explicit during optimizations and codegen.

compiler/rustc_middle/src/mir/tcx.rs

+5
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,11 @@ impl<'tcx> PlaceTy<'tcx> {
111111
ProjectionElem::Subtype(ty) => {
112112
PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty))
113113
}
114+
115+
// FIXME(unsafe_binders): Rename `handle_opaque_cast_and_subtype` to be more general.
116+
ProjectionElem::UnsafeBinderCast(_, ty) => {
117+
PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty))
118+
}
114119
};
115120
debug!("projection_ty self: {:?} elem: {:?} yields: {:?}", self, elem, answer);
116121
answer

compiler/rustc_middle/src/mir/type_foldable.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! `TypeFoldable` implementations for MIR types
22
33
use rustc_ast::InlineAsmTemplatePiece;
4+
use rustc_hir::UnsafeBinderCastKind;
45
use rustc_hir::def_id::LocalDefId;
56

67
use super::*;
@@ -20,6 +21,7 @@ TrivialTypeTraversalImpls! {
2021
SwitchTargets,
2122
CoroutineKind,
2223
CoroutineSavedLocal,
24+
UnsafeBinderCastKind,
2325
}
2426

2527
TrivialTypeTraversalImpls! {

compiler/rustc_middle/src/mir/visit.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -1148,6 +1148,15 @@ macro_rules! visit_place_fns {
11481148
self.visit_ty(&mut new_ty, TyContext::Location(location));
11491149
if ty != new_ty { Some(PlaceElem::Subtype(new_ty)) } else { None }
11501150
}
1151+
PlaceElem::UnsafeBinderCast(kind, ty) => {
1152+
let mut new_ty = ty;
1153+
self.visit_ty(&mut new_ty, TyContext::Location(location));
1154+
if ty != new_ty {
1155+
Some(PlaceElem::UnsafeBinderCast(kind, new_ty))
1156+
} else {
1157+
None
1158+
}
1159+
}
11511160
PlaceElem::Deref
11521161
| PlaceElem::ConstantIndex { .. }
11531162
| PlaceElem::Subslice { .. }
@@ -1216,7 +1225,8 @@ macro_rules! visit_place_fns {
12161225
match elem {
12171226
ProjectionElem::OpaqueCast(ty)
12181227
| ProjectionElem::Subtype(ty)
1219-
| ProjectionElem::Field(_, ty) => {
1228+
| ProjectionElem::Field(_, ty)
1229+
| ProjectionElem::UnsafeBinderCast(_, ty) => {
12201230
self.visit_ty(ty, TyContext::Location(location));
12211231
}
12221232
ProjectionElem::Index(local) => {

compiler/rustc_middle/src/thir.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use rustc_abi::{FieldIdx, Integer, Size, VariantIdx};
1616
use rustc_ast::{AsmMacro, InlineAsmOptions, InlineAsmTemplatePiece};
1717
use rustc_hir as hir;
1818
use rustc_hir::def_id::DefId;
19-
use rustc_hir::{BindingMode, ByRef, HirId, MatchSource, RangeEnd};
19+
use rustc_hir::{BindingMode, ByRef, HirId, MatchSource, RangeEnd, UnsafeBinderCastKind};
2020
use rustc_index::{IndexVec, newtype_index};
2121
use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeVisitable};
2222
use rustc_middle::middle::region;
@@ -489,6 +489,16 @@ pub enum ExprKind<'tcx> {
489489
user_ty: UserTy<'tcx>,
490490
user_ty_span: Span,
491491
},
492+
/// An unsafe binder cast on a place, e.g. `unwrap_unsafe_binder!(x)`.
493+
PlaceUnsafeBinderCast {
494+
kind: UnsafeBinderCastKind,
495+
source: ExprId,
496+
},
497+
/// An unsafe binder cast on a value, e.g. `wrap_unsafe_binder!(1; unsafe<> i32)`.
498+
ValueUnsafeBinderCast {
499+
kind: UnsafeBinderCastKind,
500+
source: ExprId,
501+
},
492502
/// A closure definition.
493503
Closure(Box<ClosureExpr<'tcx>>),
494504
/// A literal.

compiler/rustc_middle/src/thir/visit.rs

+3
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,9 @@ pub fn walk_expr<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>(
136136
| ValueTypeAscription { source, user_ty: _, user_ty_span: _ } => {
137137
visitor.visit_expr(&visitor.thir()[source])
138138
}
139+
PlaceUnsafeBinderCast { source, kind: _ } | ValueUnsafeBinderCast { source, kind: _ } => {
140+
visitor.visit_expr(&visitor.thir()[source])
141+
}
139142
Closure(box ClosureExpr {
140143
closure_id: _,
141144
args: _,

0 commit comments

Comments
 (0)