Skip to content

Commit 69b356c

Browse files
Fix drop elaboration and move analysis for unsafe binders
1 parent 59ed54f commit 69b356c

File tree

9 files changed

+56
-14
lines changed

9 files changed

+56
-14
lines changed

compiler/rustc_borrowck/src/lib.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -1945,13 +1945,16 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
19451945
ProjectionElem::OpaqueCast(_) |
19461946
ProjectionElem::ConstantIndex { .. } |
19471947
// assigning to P[i] requires P to be valid.
1948-
ProjectionElem::Downcast(_/*adt_def*/, _/*variant_idx*/) |
1949-
ProjectionElem::UnsafeBinderCast(..) =>
1948+
ProjectionElem::Downcast(_/*adt_def*/, _/*variant_idx*/) =>
19501949
// assigning to (P->variant) is okay if assigning to `P` is okay
19511950
//
19521951
// FIXME: is this true even if P is an adt with a dtor?
19531952
{ }
19541953

1954+
ProjectionElem::UnsafeBinderCast(..) => {
1955+
check_parent_of_field(self, location, place_base, span, state);
1956+
}
1957+
19551958
// assigning to (*P) requires P to be initialized
19561959
ProjectionElem::Deref => {
19571960
self.check_if_full_path_is_moved(

compiler/rustc_borrowck/src/prefixes.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,15 @@ 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 { .. }
7276
| ProjectionElem::ConstantIndex { .. }
73-
| ProjectionElem::Index(_)
74-
| ProjectionElem::UnsafeBinderCast(..) => {
77+
| ProjectionElem::Index(_) => {
7578
cursor = cursor_base;
7679
}
7780
ProjectionElem::Subtype(..) => {

compiler/rustc_mir_dataflow/src/elaborate_drops.rs

+23-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::{fmt, iter};
22

33
use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx};
4+
use rustc_hir::UnsafeBinderCastKind;
45
use rustc_hir::lang_items::LangItem;
56
use rustc_index::Idx;
67
use rustc_middle::mir::patch::MirPatch;
@@ -151,6 +152,11 @@ pub trait DropElaborator<'a, 'tcx>: fmt::Debug {
151152
///
152153
/// This is only relevant for array patterns, which can move out of individual array elements.
153154
fn array_subpath(&self, path: Self::Path, index: u64, size: u64) -> Option<Self::Path>;
155+
156+
/// Returns the subpath of casting an unsafe binder.
157+
///
158+
/// If this returns `None`, elements of `path` will not get a dedicated drop flag.
159+
fn unsafe_binder_subpath(&self, path: Self::Path) -> Option<Self::Path>;
154160
}
155161

156162
#[derive(Debug)]
@@ -846,7 +852,7 @@ where
846852
/// ADT, both in the success case or if one of the destructors fail.
847853
fn open_drop(&mut self) -> BasicBlock {
848854
let ty = self.place_ty(self.place);
849-
match ty.kind() {
855+
match *ty.kind() {
850856
ty::Closure(_, args) => self.open_drop_for_tuple(args.as_closure().upvar_tys()),
851857
ty::CoroutineClosure(_, args) => {
852858
self.open_drop_for_tuple(args.as_coroutine_closure().upvar_tys())
@@ -859,13 +865,26 @@ where
859865
// See librustc_body/transform/coroutine.rs for more details.
860866
ty::Coroutine(_, args) => self.open_drop_for_tuple(args.as_coroutine().upvar_tys()),
861867
ty::Tuple(fields) => self.open_drop_for_tuple(fields),
862-
ty::Adt(def, args) => self.open_drop_for_adt(*def, args),
868+
ty::Adt(def, args) => self.open_drop_for_adt(def, args),
863869
ty::Dynamic(..) => self.complete_drop(self.succ, self.unwind),
864870
ty::Array(ety, size) => {
865871
let size = size.try_to_target_usize(self.tcx());
866-
self.open_drop_for_array(*ety, size)
872+
self.open_drop_for_array(ety, size)
873+
}
874+
ty::Slice(ety) => self.drop_loop_pair(ety),
875+
ty::UnsafeBinder(binder) => {
876+
let ty = self.tcx().instantiate_bound_regions_with_erased(binder.into());
877+
let fields = vec![(
878+
self.place.project_deeper(
879+
&[ProjectionElem::UnsafeBinderCast(UnsafeBinderCastKind::Unwrap, ty)],
880+
self.tcx(),
881+
),
882+
self.elaborator.unsafe_binder_subpath(self.path),
883+
)];
884+
885+
let (succ, unwind) = self.drop_ladder_bottom();
886+
self.drop_ladder(fields, succ, unwind).0
867887
}
868-
ty::Slice(ety) => self.drop_loop_pair(*ety),
869888

870889
_ => span_bug!(self.source_info.span, "open drop from non-ADT `{:?}`", ty),
871890
}

compiler/rustc_mir_dataflow/src/move_paths/builder.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::mem;
22

3+
use rustc_hir::UnsafeBinderCastKind;
34
use rustc_index::IndexVec;
45
use rustc_middle::mir::tcx::{PlaceTy, RvalueInitializationState};
56
use rustc_middle::mir::*;
@@ -208,7 +209,7 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {
208209
| ty::Infer(_)
209210
| ty::Error(_)
210211
| ty::Placeholder(_) => bug!(
211-
"When Place contains ProjectionElem::Field it's type shouldn't be {place_ty:#?}"
212+
"When Place contains ProjectionElem::Field its type shouldn't be {place_ty:#?}"
212213
),
213214
},
214215
ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => {
@@ -226,15 +227,18 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {
226227
}
227228
_ => bug!("Unexpected type {place_ty:#?}"),
228229
},
230+
ProjectionElem::UnsafeBinderCast(UnsafeBinderCastKind::Unwrap, _) => {}
231+
ProjectionElem::UnsafeBinderCast(UnsafeBinderCastKind::Wrap, _) => {
232+
union_path.get_or_insert(base);
233+
}
229234
// `OpaqueCast`:Only transmutes the type, so no moves there.
230235
// `Downcast` :Only changes information about a `Place` without moving.
231236
// `Subtype` :Only transmutes the type, so moves.
232237
// `UnsafeBinderCast`: Only transmutes the place without moving.
233238
// So it's safe to skip these.
234239
ProjectionElem::OpaqueCast(_)
235240
| ProjectionElem::Subtype(_)
236-
| ProjectionElem::Downcast(_, _)
237-
| ProjectionElem::UnsafeBinderCast(_, _) => (),
241+
| ProjectionElem::Downcast(_, _) => (),
238242
}
239243
let elem_ty = PlaceTy::from_ty(place_ty).projection_ty(tcx, elem).ty;
240244
if !(self.filter)(elem_ty) {

compiler/rustc_mir_transform/src/elaborate_drops.rs

+6
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,12 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for ElaborateDropsCtxt<'a, 'tcx> {
221221
})
222222
}
223223

224+
fn unsafe_binder_subpath(&self, path: Self::Path) -> Option<Self::Path> {
225+
rustc_mir_dataflow::move_path_children_matching(self.move_data(), path, |e| {
226+
matches!(e, ProjectionElem::UnsafeBinderCast(..))
227+
})
228+
}
229+
224230
fn get_drop_flag(&mut self, path: Self::Path) -> Option<Operand<'tcx>> {
225231
self.drop_flag(path).map(Operand::Copy)
226232
}

compiler/rustc_mir_transform/src/gvn.rs

+3
Original file line numberDiff line numberDiff line change
@@ -931,6 +931,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
931931
ProjectionElem::Downcast(symbol, idx) => ProjectionElem::Downcast(symbol, idx),
932932
ProjectionElem::OpaqueCast(idx) => ProjectionElem::OpaqueCast(idx),
933933
ProjectionElem::Subtype(idx) => ProjectionElem::Subtype(idx),
934+
ProjectionElem::UnsafeBinderCast(kind, ty) => {
935+
ProjectionElem::UnsafeBinderCast(kind, ty)
936+
}
934937
})
935938
}
936939

compiler/rustc_mir_transform/src/shim.rs

+3
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,9 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> {
393393
fn array_subpath(&self, _path: Self::Path, _index: u64, _size: u64) -> Option<Self::Path> {
394394
None
395395
}
396+
fn unsafe_binder_subpath(&self, _path: Self::Path) -> Option<Self::Path> {
397+
None
398+
}
396399
}
397400

398401
fn build_thread_local_shim<'tcx>(

compiler/rustc_trait_selection/src/traits/select/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2357,8 +2357,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
23572357
| ty::Never
23582358
| ty::Char => ty::Binder::dummy(Vec::new()),
23592359

2360-
// TODO: binder needs opening
2361-
ty::UnsafeBinder(_) => todo!(),
2360+
// FIXME(unsafe_binders): Squash the double binder for now, I guess.
2361+
ty::UnsafeBinder(_) => return Err(SelectionError::Unimplemented),
23622362

23632363
// Treat this like `struct str([u8]);`
23642364
ty::Str => ty::Binder::dummy(vec![Ty::new_slice(self.tcx(), self.tcx().types.u8)]),

compiler/rustc_ty_utils/src/instance.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ fn resolve_instance_raw<'tcx>(
4949
| ty::Adt(..)
5050
| ty::Dynamic(..)
5151
| ty::Array(..)
52-
| ty::Slice(..) => {}
52+
| ty::Slice(..)
53+
| ty::UnsafeBinder(..) => {}
5354
// Drop shims can only be built from ADTs.
5455
_ => return Ok(None),
5556
}

0 commit comments

Comments
 (0)