diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs index 60676ac6b8644..cdae794775432 100644 --- a/compiler/rustc_borrowck/src/places_conflict.rs +++ b/compiler/rustc_borrowck/src/places_conflict.rs @@ -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. @@ -510,6 +515,7 @@ fn place_projection_conflict<'tcx>( | ProjectionElem::Index(..) | ProjectionElem::ConstantIndex { .. } | ProjectionElem::OpaqueCast { .. } + | ProjectionElem::UnwrapUnsafeBinder { .. } | ProjectionElem::Subslice { .. } | ProjectionElem::Downcast(..), _, @@ -518,9 +524,5 @@ fn place_projection_conflict<'tcx>( pi1_elem, pi2_elem ), - - (ProjectionElem::UnwrapUnsafeBinder(_), _) => { - todo!() - } } } diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index bb461ccb6f370..c7e0ec29a47a9 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -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(..) @@ -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. @@ -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); diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 746662e6a302f..128da3a73c050 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -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; }; @@ -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; }; diff --git a/compiler/rustc_public/src/mir/body.rs b/compiler/rustc_public/src/mir/body.rs index f9b5f9af951e5..c6d5af49525e4 100644 --- a/compiler/rustc_public/src/mir/body.rs +++ b/compiler/rustc_public/src/mir/body.rs @@ -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. /// @@ -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), } } } @@ -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)] @@ -1069,6 +1077,7 @@ impl ProjectionElem { } ProjectionElem::Downcast(_) => Ok(ty), ProjectionElem::OpaqueCast(ty) => Ok(*ty), + ProjectionElem::UnwrapUnsafeBinder(ty) => Ok(*ty), } } diff --git a/compiler/rustc_public/src/mir/pretty.rs b/compiler/rustc_public/src/mir/pretty.rs index dec4044fd260b..c69853572a684 100644 --- a/compiler/rustc_public/src/mir/pretty.rs +++ b/compiler/rustc_public/src/mir/pretty.rs @@ -364,6 +364,9 @@ fn pretty_rvalue(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:?})") } diff --git a/compiler/rustc_public/src/mir/visit.rs b/compiler/rustc_public/src/mir/visit.rs index 5a3afc9937351..c6b297b4ca2cb 100644 --- a/compiler/rustc_public/src/mir/visit.rs +++ b/compiler/rustc_public/src/mir/visit.rs @@ -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 { .. }) }; @@ -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), } } }; @@ -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), } } }; diff --git a/compiler/rustc_public/src/ty.rs b/compiler/rustc_public/src/ty.rs index 59b4c6bee5c03..44c134c015a34 100644 --- a/compiler/rustc_public/src/ty.rs +++ b/compiler/rustc_public/src/ty.rs @@ -561,6 +561,7 @@ pub enum RigidTy { Ref(Region, Ty, Mutability), FnDef(FnDef, GenericArgs), FnPtr(PolyFnSig), + UnsafeBinder(Binder), Closure(ClosureDef, GenericArgs), Coroutine(CoroutineDef, GenericArgs), CoroutineClosure(CoroutineClosureDef, GenericArgs), diff --git a/compiler/rustc_public/src/unstable/convert/internal.rs b/compiler/rustc_public/src/unstable/convert/internal.rs index 165ad737fccb8..2d367c1f582cc 100644 --- a/compiler/rustc_public/src/unstable/convert/internal.rs +++ b/compiler/rustc_public/src/unstable/convert/internal.rs @@ -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)) } @@ -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)) + } } } } diff --git a/compiler/rustc_public/src/unstable/convert/stable/mir.rs b/compiler/rustc_public/src/unstable/convert/stable/mir.rs index 7e76d5a91ac66..5af9238fe8c6b 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/mir.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/mir.rs @@ -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), + ), } } } @@ -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)) + } } } } diff --git a/compiler/rustc_public/src/unstable/convert/stable/ty.rs b/compiler/rustc_public/src/unstable/convert/stable/ty.rs index 80453d838b880..dde4425eadb32 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/ty.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/ty.rs @@ -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() diff --git a/compiler/rustc_public/src/visitor.rs b/compiler/rustc_public/src/visitor.rs index acc3334769613..fe2e11bf97668 100644 --- a/compiler/rustc_public/src/visitor.rs +++ b/compiler/rustc_public/src/visitor.rs @@ -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)