diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2025-02-01 16:41:03 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-02-01 16:41:03 +0100 |
| commit | 2fd3007cbcfd54edd82f2e4f4058afdf07ea8e60 (patch) | |
| tree | 708d75cf765925fdaff37a7e858137c68b2547c3 /compiler/rustc_middle | |
| parent | e08cd3cf05e5bfa3323cc21ea8f81f4a15a2f969 (diff) | |
| parent | 442b9a93872096a6e51e23f36f14f2dacf5520ce (diff) | |
| download | rust-2fd3007cbcfd54edd82f2e4f4058afdf07ea8e60.tar.gz rust-2fd3007cbcfd54edd82f2e4f4058afdf07ea8e60.zip | |
Rollup merge of #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: - https://github.com/rust-lang/rust/issues/130516
Diffstat (limited to 'compiler/rustc_middle')
| -rw-r--r-- | compiler/rustc_middle/src/mir/pretty.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/statement.rs | 12 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/syntax.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/tcx.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/type_foldable.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/visit.rs | 13 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/thir.rs | 13 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/thir/visit.rs | 3 |
8 files changed, 62 insertions, 4 deletions
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index a318bacb866..09d7e60e199 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -1248,6 +1248,10 @@ impl<'tcx> Debug for Rvalue<'tcx> { ShallowInitBox(ref place, ref ty) => { with_no_trimmed_paths!(write!(fmt, "ShallowInitBox({place:?}, {ty})")) } + + WrapUnsafeBinder(ref op, ty) => { + with_no_trimmed_paths!(write!(fmt, "wrap_binder!({op:?}; {ty})")) + } } } } @@ -1308,6 +1312,9 @@ fn pre_fmt_projection(projection: &[PlaceElem<'_>], fmt: &mut Formatter<'_>) -> ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => {} + ProjectionElem::UnwrapUnsafeBinder(_) => { + write!(fmt, "unwrap_binder!(")?; + } } } @@ -1356,6 +1363,9 @@ fn post_fmt_projection(projection: &[PlaceElem<'_>], fmt: &mut Formatter<'_>) -> ProjectionElem::Subslice { from, to, from_end: false } => { write!(fmt, "[{from:?}..{to:?}]")?; } + ProjectionElem::UnwrapUnsafeBinder(ty) => { + write!(fmt, "; {ty})")?; + } } } diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index 609d5647d04..d345c99f902 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -62,7 +62,8 @@ impl<V, T> ProjectionElem<V, T> { | Self::Subtype(_) | Self::ConstantIndex { .. } | Self::Subslice { .. } - | Self::Downcast(_, _) => false, + | Self::Downcast(_, _) + | Self::UnwrapUnsafeBinder(..) => false, } } @@ -76,7 +77,8 @@ impl<V, T> ProjectionElem<V, T> { | Self::Subtype(_) | Self::ConstantIndex { .. } | Self::Subslice { .. } - | Self::Downcast(_, _) => true, + | Self::Downcast(_, _) + | Self::UnwrapUnsafeBinder(..) => true, } } @@ -102,6 +104,9 @@ impl<V, T> ProjectionElem<V, T> { | Self::Subtype(_) | Self::OpaqueCast(_) | Self::Subslice { .. } => false, + + // FIXME(unsafe_binders): Figure this out. + Self::UnwrapUnsafeBinder(..) => false, } } } @@ -443,7 +448,8 @@ impl<'tcx> Rvalue<'tcx> { | Rvalue::UnaryOp(_, _) | Rvalue::Discriminant(_) | Rvalue::Aggregate(_, _) - | Rvalue::ShallowInitBox(_, _) => true, + | Rvalue::ShallowInitBox(_, _) + | Rvalue::WrapUnsafeBinder(_, _) => true, } } } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 90a2f175bc9..2da25f480c6 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1276,6 +1276,10 @@ pub enum ProjectionElem<V, T> { /// requiring an intermediate variable. OpaqueCast(T), + /// 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(T), + /// A `Subtype(T)` projection is applied to any `StatementKind::Assign` where /// type of lvalue doesn't match the type of rvalue, the primary goal is making subtyping /// explicit during optimizations and codegen. @@ -1493,6 +1497,9 @@ pub enum Rvalue<'tcx> { /// optimizations and codegen backends that previously had to handle deref operations anywhere /// in a place. CopyForDeref(Place<'tcx>), + + /// Wraps a value in an unsafe binder. + WrapUnsafeBinder(Operand<'tcx>, Ty<'tcx>), } #[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index 4d11492e94d..49449426fa4 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -146,6 +146,11 @@ impl<'tcx> PlaceTy<'tcx> { ProjectionElem::Subtype(ty) => { PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty)) } + + // FIXME(unsafe_binders): Rename `handle_opaque_cast_and_subtype` to be more general. + ProjectionElem::UnwrapUnsafeBinder(ty) => { + PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty)) + } }; debug!("projection_ty self: {:?} elem: {:?} yields: {:?}", self, elem, answer); answer @@ -241,6 +246,7 @@ impl<'tcx> Rvalue<'tcx> { }, Rvalue::ShallowInitBox(_, ty) => Ty::new_box(tcx, ty), Rvalue::CopyForDeref(ref place) => place.ty(local_decls, tcx).ty, + Rvalue::WrapUnsafeBinder(_, ty) => ty, } } diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs index b59b9e55fe8..9893dd0484c 100644 --- a/compiler/rustc_middle/src/mir/type_foldable.rs +++ b/compiler/rustc_middle/src/mir/type_foldable.rs @@ -1,6 +1,7 @@ //! `TypeFoldable` implementations for MIR types use rustc_ast::InlineAsmTemplatePiece; +use rustc_hir::UnsafeBinderCastKind; use rustc_hir::def_id::LocalDefId; use super::*; @@ -21,6 +22,7 @@ TrivialTypeTraversalImpls! { SwitchTargets, CoroutineKind, CoroutineSavedLocal, + UnsafeBinderCastKind, } TrivialTypeTraversalImpls! { diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 6319a7e65b9..8d04bbb95bd 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -781,6 +781,11 @@ macro_rules! make_mir_visitor { self.visit_operand(operand, location); self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)); } + + Rvalue::WrapUnsafeBinder(op, ty) => { + self.visit_operand(op, location); + self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)); + } } } @@ -1151,6 +1156,11 @@ macro_rules! visit_place_fns { self.visit_ty(&mut new_ty, TyContext::Location(location)); if ty != new_ty { Some(PlaceElem::Subtype(new_ty)) } else { None } } + PlaceElem::UnwrapUnsafeBinder(ty) => { + let mut new_ty = ty; + self.visit_ty(&mut new_ty, TyContext::Location(location)); + if ty != new_ty { Some(PlaceElem::UnwrapUnsafeBinder(new_ty)) } else { None } + } PlaceElem::Deref | PlaceElem::ConstantIndex { .. } | PlaceElem::Subslice { .. } @@ -1219,7 +1229,8 @@ macro_rules! visit_place_fns { match elem { ProjectionElem::OpaqueCast(ty) | ProjectionElem::Subtype(ty) - | ProjectionElem::Field(_, ty) => { + | ProjectionElem::Field(_, ty) + | ProjectionElem::UnwrapUnsafeBinder(ty) => { self.visit_ty(ty, TyContext::Location(location)); } ProjectionElem::Index(local) => { diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 86014c34b45..d56046136c7 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -489,6 +489,19 @@ pub enum ExprKind<'tcx> { user_ty: UserTy<'tcx>, user_ty_span: Span, }, + /// An unsafe binder cast on a place, e.g. `unwrap_binder!(*ptr)`. + PlaceUnwrapUnsafeBinder { + source: ExprId, + }, + /// An unsafe binder cast on a value, e.g. `unwrap_binder!(rvalue())`, + /// which makes a temporary. + ValueUnwrapUnsafeBinder { + source: ExprId, + }, + /// Construct an unsafe binder, e.g. `wrap_binder(&ref)`. + WrapUnsafeBinder { + source: ExprId, + }, /// A closure definition. Closure(Box<ClosureExpr<'tcx>>), /// A literal. diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index 64bac12b266..2aeb13942a3 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -136,6 +136,9 @@ pub fn walk_expr<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>( | ValueTypeAscription { source, user_ty: _, user_ty_span: _ } => { visitor.visit_expr(&visitor.thir()[source]) } + PlaceUnwrapUnsafeBinder { source } + | ValueUnwrapUnsafeBinder { source } + | WrapUnsafeBinder { source } => visitor.visit_expr(&visitor.thir()[source]), Closure(box ClosureExpr { closure_id: _, args: _, |
