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
This commit is contained in:
commit
2fd3007cbc
56 changed files with 589 additions and 102 deletions
|
@ -504,7 +504,8 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
|
|||
| Rvalue::Cast(..)
|
||||
| Rvalue::BinaryOp(..)
|
||||
| Rvalue::Aggregate(..)
|
||||
| Rvalue::ShallowInitBox(..) => {
|
||||
| Rvalue::ShallowInitBox(..)
|
||||
| Rvalue::WrapUnsafeBinder(..) => {
|
||||
// No modification is possible through these r-values.
|
||||
return ValueOrPlace::TOP;
|
||||
}
|
||||
|
|
|
@ -575,6 +575,9 @@ impl WriteInfo {
|
|||
self.add_operand(op);
|
||||
}
|
||||
}
|
||||
Rvalue::WrapUnsafeBinder(op, _) => {
|
||||
self.add_operand(op);
|
||||
}
|
||||
Rvalue::ThreadLocalRef(_)
|
||||
| Rvalue::NullaryOp(_, _)
|
||||
| Rvalue::Ref(_, _, _)
|
||||
|
|
|
@ -476,6 +476,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||
}
|
||||
ProjectionElem::OpaqueCast(ty) => ProjectionElem::OpaqueCast(ty),
|
||||
ProjectionElem::Subtype(ty) => ProjectionElem::Subtype(ty),
|
||||
ProjectionElem::UnwrapUnsafeBinder(ty) => {
|
||||
ProjectionElem::UnwrapUnsafeBinder(ty)
|
||||
}
|
||||
// This should have been replaced by a `ConstantIndex` earlier.
|
||||
ProjectionElem::Index(_) => return None,
|
||||
};
|
||||
|
@ -713,6 +716,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||
}
|
||||
ProjectionElem::OpaqueCast(ty) => ProjectionElem::OpaqueCast(ty),
|
||||
ProjectionElem::Subtype(ty) => ProjectionElem::Subtype(ty),
|
||||
ProjectionElem::UnwrapUnsafeBinder(ty) => ProjectionElem::UnwrapUnsafeBinder(ty),
|
||||
};
|
||||
|
||||
Some(self.insert(Value::Projection(value, proj)))
|
||||
|
@ -867,6 +871,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||
self.simplify_place_projection(place, location);
|
||||
return self.new_pointer(*place, AddressKind::Address(mutbl));
|
||||
}
|
||||
Rvalue::WrapUnsafeBinder(ref mut op, _) => {
|
||||
return self.simplify_operand(op, location);
|
||||
}
|
||||
|
||||
// Operations.
|
||||
Rvalue::Len(ref mut place) => return self.simplify_len(place, location),
|
||||
|
@ -931,6 +938,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||
ProjectionElem::Downcast(symbol, idx) => ProjectionElem::Downcast(symbol, idx),
|
||||
ProjectionElem::OpaqueCast(idx) => ProjectionElem::OpaqueCast(idx),
|
||||
ProjectionElem::Subtype(idx) => ProjectionElem::Subtype(idx),
|
||||
ProjectionElem::UnwrapUnsafeBinder(ty) => ProjectionElem::UnwrapUnsafeBinder(ty),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -444,7 +444,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
|||
| Rvalue::Cast(..)
|
||||
| Rvalue::ShallowInitBox(..)
|
||||
| Rvalue::Discriminant(..)
|
||||
| Rvalue::NullaryOp(..) => {}
|
||||
| Rvalue::NullaryOp(..)
|
||||
| Rvalue::WrapUnsafeBinder(..) => {}
|
||||
}
|
||||
|
||||
// FIXME we need to revisit this for #67176
|
||||
|
@ -546,7 +547,9 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
|||
let val: Value<'_> = match *rvalue {
|
||||
ThreadLocalRef(_) => return None,
|
||||
|
||||
Use(ref operand) => self.eval_operand(operand)?.into(),
|
||||
Use(ref operand) | WrapUnsafeBinder(ref operand, _) => {
|
||||
self.eval_operand(operand)?.into()
|
||||
}
|
||||
|
||||
CopyForDeref(place) => self.eval_place(place)?.into(),
|
||||
|
||||
|
|
|
@ -293,7 +293,8 @@ impl<'tcx> Validator<'_, 'tcx> {
|
|||
// Recurse directly.
|
||||
ProjectionElem::ConstantIndex { .. }
|
||||
| ProjectionElem::Subtype(_)
|
||||
| ProjectionElem::Subslice { .. } => {}
|
||||
| ProjectionElem::Subslice { .. }
|
||||
| ProjectionElem::UnwrapUnsafeBinder(_) => {}
|
||||
|
||||
// Never recurse.
|
||||
ProjectionElem::OpaqueCast(..) | ProjectionElem::Downcast(..) => {
|
||||
|
@ -426,7 +427,9 @@ impl<'tcx> Validator<'_, 'tcx> {
|
|||
|
||||
fn validate_rvalue(&mut self, rvalue: &Rvalue<'tcx>) -> Result<(), Unpromotable> {
|
||||
match rvalue {
|
||||
Rvalue::Use(operand) | Rvalue::Repeat(operand, _) => {
|
||||
Rvalue::Use(operand)
|
||||
| Rvalue::Repeat(operand, _)
|
||||
| Rvalue::WrapUnsafeBinder(operand, _) => {
|
||||
self.validate_operand(operand)?;
|
||||
}
|
||||
Rvalue::CopyForDeref(place) => {
|
||||
|
|
|
@ -807,6 +807,25 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
)
|
||||
}
|
||||
}
|
||||
ProjectionElem::UnwrapUnsafeBinder(unwrapped_ty) => {
|
||||
let binder_ty = place_ref.ty(&self.body.local_decls, self.tcx);
|
||||
let ty::UnsafeBinder(binder_ty) = *binder_ty.ty.kind() else {
|
||||
self.fail(
|
||||
location,
|
||||
format!("WrapUnsafeBinder does not produce a ty::UnsafeBinder"),
|
||||
);
|
||||
return;
|
||||
};
|
||||
let binder_inner_ty = self.tcx.instantiate_bound_regions_with_erased(*binder_ty);
|
||||
if !self.mir_assign_valid_types(unwrapped_ty, binder_inner_ty) {
|
||||
self.fail(
|
||||
location,
|
||||
format!(
|
||||
"Cannot unwrap unsafe binder {binder_ty:?} into type {unwrapped_ty:?}"
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
self.super_projection_elem(place_ref, elem, context, location);
|
||||
|
@ -1362,6 +1381,24 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
| Rvalue::RawPtr(_, _)
|
||||
| Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::UbChecks, _)
|
||||
| Rvalue::Discriminant(_) => {}
|
||||
|
||||
Rvalue::WrapUnsafeBinder(op, ty) => {
|
||||
let unwrapped_ty = op.ty(self.body, self.tcx);
|
||||
let ty::UnsafeBinder(binder_ty) = *ty.kind() else {
|
||||
self.fail(
|
||||
location,
|
||||
format!("WrapUnsafeBinder does not produce a ty::UnsafeBinder"),
|
||||
);
|
||||
return;
|
||||
};
|
||||
let binder_inner_ty = self.tcx.instantiate_bound_regions_with_erased(*binder_ty);
|
||||
if !self.mir_assign_valid_types(unwrapped_ty, binder_inner_ty) {
|
||||
self.fail(
|
||||
location,
|
||||
format!("Cannot wrap {unwrapped_ty:?} into unsafe binder {binder_ty:?}"),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
self.super_rvalue(rvalue, location);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue