Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions compiler/rustc_borrowck/src/places_conflict.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,11 @@ fn place_projection_conflict<'tcx>(
debug!("place_element_conflict: DISJOINT-OR-EQ-OPAQUE");
Overlap::EqualOrDisjoint
}
(ProjectionElem::UnwrapUnsafeBinder(_), ProjectionElem::UnwrapUnsafeBinder(_)) => {
// casts to other types may always conflict irrespective of the type being cast to.
debug!("place_element_conflict: DISJOINT-OR-EQ-OPAQUE");
Overlap::EqualOrDisjoint
}
(ProjectionElem::Field(f1, _), ProjectionElem::Field(f2, _)) => {
if f1 == f2 {
// same field (e.g., `a.y` vs. `a.y`) - recur.
Expand Down Expand Up @@ -510,6 +515,7 @@ fn place_projection_conflict<'tcx>(
| ProjectionElem::Index(..)
| ProjectionElem::ConstantIndex { .. }
| ProjectionElem::OpaqueCast { .. }
| ProjectionElem::UnwrapUnsafeBinder { .. }
| ProjectionElem::Subslice { .. }
| ProjectionElem::Downcast(..),
_,
Expand All @@ -518,9 +524,5 @@ fn place_projection_conflict<'tcx>(
pi1_elem,
pi2_elem
),

(ProjectionElem::UnwrapUnsafeBinder(_), _) => {
todo!()
}
}
}
8 changes: 7 additions & 1 deletion compiler/rustc_const_eval/src/interpret/validity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -991,7 +991,6 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
// Nothing to check.
interp_ok(true)
}
ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"),
// The above should be all the primitive types. The rest is compound, we
// check them by visiting their fields/variants.
ty::Adt(..)
Expand All @@ -1002,6 +1001,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
| ty::Dynamic(..)
| ty::Closure(..)
| ty::Pat(..)
| ty::UnsafeBinder(_)
| ty::CoroutineClosure(..)
| ty::Coroutine(..) => interp_ok(false),
// Some types only occur during typechecking, they have no layout.
Expand Down Expand Up @@ -1536,6 +1536,12 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
BackendRepr::Memory { .. } => unreachable!()
}
}
ty::UnsafeBinder(base) => {
// First check that the base type is valid
let base = self.ecx.tcx.instantiate_bound_regions_with_erased((*base).into());
let inner_layout = self.ecx.layout_of(base)?;
self.visit_value(&val.transmute(inner_layout, self.ecx)?)?;
}
ty::Adt(adt, _) if adt.is_maybe_dangling() => {
let old_may_dangle = mem::replace(&mut self.may_dangle, true);

Expand Down
6 changes: 4 additions & 2 deletions compiler/rustc_mir_transform/src/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -879,7 +879,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
let ty::UnsafeBinder(binder_ty) = *binder_ty.ty.kind() else {
self.fail(
location,
format!("WrapUnsafeBinder does not produce a ty::UnsafeBinder"),
format!("WrapUnsafeBinder does not produce a ty::UnsafeBinder, found {binder_ty:?}"),
);
return;
};
Expand Down Expand Up @@ -1442,7 +1442,9 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
let ty::UnsafeBinder(binder_ty) = *ty.kind() else {
self.fail(
location,
format!("WrapUnsafeBinder does not produce a ty::UnsafeBinder"),
format!(
"WrapUnsafeBinder does not produce a ty::UnsafeBinder, found {ty:?}"
),
);
return;
};
Expand Down
9 changes: 9 additions & 0 deletions compiler/rustc_public/src/mir/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,9 @@ pub enum Rvalue {
/// deref operation, immediately followed by one or more projections.
CopyForDeref(Place),

/// Wraps a value in an unsafe binder.
WrapUnsafeBinder(Operand, Ty),

/// Computes the discriminant of the place, returning it as an integer.
/// Returns zero for types without discriminant.
///
Expand Down Expand Up @@ -650,6 +653,7 @@ impl Rvalue {
AggregateKind::RawPtr(ty, mutability) => Ok(Ty::new_ptr(ty, mutability)),
},
Rvalue::CopyForDeref(place) => place.ty(locals),
Rvalue::WrapUnsafeBinder(_, ty) => Ok(*ty),
}
}
}
Expand Down Expand Up @@ -835,6 +839,10 @@ pub enum ProjectionElem {
/// Like an explicit cast from an opaque type to a concrete type, but without
/// requiring an intermediate variable.
OpaqueCast(Ty),

/// A transmute from an unsafe binder to the type that it wraps. This is a projection
/// of a place, so it doesn't necessarily constitute a move out of the binder.
UnwrapUnsafeBinder(Ty),
}

#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
Expand Down Expand Up @@ -1069,6 +1077,7 @@ impl ProjectionElem {
}
ProjectionElem::Downcast(_) => Ok(ty),
ProjectionElem::OpaqueCast(ty) => Ok(*ty),
ProjectionElem::UnwrapUnsafeBinder(ty) => Ok(*ty),
}
}

Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_public/src/mir/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,9 @@ fn pretty_rvalue<W: Write>(writer: &mut W, rval: &Rvalue) -> io::Result<()> {
Rvalue::CopyForDeref(deref) => {
write!(writer, "CopyForDeref({deref:?})")
}
Rvalue::WrapUnsafeBinder(operand, ty) => {
write!(writer, "wrap_binder!({operand:?}; {ty:?})")
}
Rvalue::Discriminant(place) => {
write!(writer, "discriminant({place:?})")
}
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_public/src/mir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,10 @@ macro_rules! make_mir_visitor {
Rvalue::CopyForDeref(place) | Rvalue::Discriminant(place) | Rvalue::Len(place) => {
self.visit_place(place, PlaceContext::NON_MUTATING, location);
}
Rvalue::WrapUnsafeBinder(operand, ty) => {
self.visit_operand(operand, location);
self.visit_ty(ty, location);
}
Rvalue::Ref(region, kind, place) => {
self.visit_region(region, location);
let pcx = PlaceContext { is_mut: matches!(kind, BorrowKind::Mut { .. }) };
Expand Down Expand Up @@ -468,6 +472,7 @@ macro_rules! visit_place_fns {
ProjectionElem::Subslice { from: _, to: _, from_end: _ } => {}
ProjectionElem::Downcast(_idx) => {}
ProjectionElem::OpaqueCast(ty) => self.visit_ty(ty, location),
ProjectionElem::UnwrapUnsafeBinder(ty) => self.visit_ty(ty, location),
}
}
};
Expand Down Expand Up @@ -508,6 +513,7 @@ macro_rules! visit_place_fns {
ProjectionElem::Subslice { from: _, to: _, from_end: _ } => {}
ProjectionElem::Downcast(_idx) => {}
ProjectionElem::OpaqueCast(ty) => self.visit_ty(ty, location),
ProjectionElem::UnwrapUnsafeBinder(ty) => self.visit_ty(ty, location),
}
}
};
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_public/src/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,7 @@ pub enum RigidTy {
Ref(Region, Ty, Mutability),
FnDef(FnDef, GenericArgs),
FnPtr(PolyFnSig),
UnsafeBinder(Binder<Ty>),
Closure(ClosureDef, GenericArgs),
Coroutine(CoroutineDef, GenericArgs),
CoroutineClosure(CoroutineClosureDef, GenericArgs),
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_public/src/unstable/convert/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ impl RustcInternal for RigidTy {
let (sig_tys, hdr) = sig.internal(tables, tcx).split();
rustc_ty::TyKind::FnPtr(sig_tys, hdr)
}
RigidTy::UnsafeBinder(binder) => {
rustc_ty::TyKind::UnsafeBinder(binder.internal(tables, tcx).into())
}
RigidTy::Closure(def, args) => {
rustc_ty::TyKind::Closure(def.0.internal(tables, tcx), args.internal(tables, tcx))
}
Expand Down Expand Up @@ -736,6 +739,9 @@ impl RustcInternal for ProjectionElem {
ProjectionElem::OpaqueCast(ty) => {
rustc_middle::mir::PlaceElem::OpaqueCast(ty.internal(tables, tcx))
}
ProjectionElem::UnwrapUnsafeBinder(ty) => {
rustc_middle::mir::PlaceElem::UnwrapUnsafeBinder(ty.internal(tables, tcx))
}
}
}
}
Expand Down
9 changes: 7 additions & 2 deletions compiler/rustc_public/src/unstable/convert/stable/mir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,10 @@ impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> {
crate::mir::Rvalue::Aggregate(agg_kind.stable(tables, cx), operands)
}
CopyForDeref(place) => crate::mir::Rvalue::CopyForDeref(place.stable(tables, cx)),
WrapUnsafeBinder(..) => todo!("FIXME(unsafe_binders):"),
WrapUnsafeBinder(operand, ty) => crate::mir::Rvalue::WrapUnsafeBinder(
operand.stable(tables, cx),
ty.stable(tables, cx),
),
}
}
}
Expand Down Expand Up @@ -446,7 +449,9 @@ impl<'tcx> Stable<'tcx> for mir::PlaceElem<'tcx> {
// found at https://github.com/rust-lang/rust/pull/117517#issuecomment-1811683486
Downcast(_, idx) => crate::mir::ProjectionElem::Downcast(idx.stable(tables, cx)),
OpaqueCast(ty) => crate::mir::ProjectionElem::OpaqueCast(ty.stable(tables, cx)),
UnwrapUnsafeBinder(..) => todo!("FIXME(unsafe_binders):"),
UnwrapUnsafeBinder(ty) => {
crate::mir::ProjectionElem::UnwrapUnsafeBinder(ty.stable(tables, cx))
}
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_public/src/unstable/convert/stable/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -453,8 +453,9 @@ impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> {
ty::FnPtr(sig_tys, hdr) => {
TyKind::RigidTy(RigidTy::FnPtr(sig_tys.with(*hdr).stable(tables, cx)))
}
// FIXME(unsafe_binders):
ty::UnsafeBinder(_) => todo!(),
ty::UnsafeBinder(binder) => {
TyKind::RigidTy(RigidTy::UnsafeBinder(binder.stable(tables, cx)))
}
ty::Dynamic(existential_predicates, region) => TyKind::RigidTy(RigidTy::Dynamic(
existential_predicates
.iter()
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_public/src/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ impl Visitable for RigidTy {
| RigidTy::CoroutineClosure(_, args)
| RigidTy::FnDef(_, args) => args.visit(visitor),
RigidTy::FnPtr(sig) => sig.visit(visitor),
RigidTy::UnsafeBinder(binder) => binder.visit(visitor),
RigidTy::Dynamic(pred, r) => {
pred.visit(visitor)?;
r.visit(visitor)
Expand Down
Loading