Skip to content

Commit d8aad82

Browse files
committed
Adress reviewer concerns
1 parent fbf691c commit d8aad82

3 files changed

Lines changed: 93 additions & 38 deletions

File tree

compiler/rustc_ty_utils/src/needs_drop.rs

Lines changed: 77 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,16 @@ fn needs_drop_raw<'tcx>(
2323
// needs drop.
2424
let adt_has_dtor =
2525
|adt_def: ty::AdtDef<'tcx>| adt_def.destructor(tcx).map(|_| DtorType::Significant);
26-
let res =
27-
drop_tys_helper(tcx, query.value, query.typing_env, adt_has_dtor, false, false, false)
28-
.filter(filter_array_elements(tcx, query.typing_env))
29-
.next()
30-
.is_some();
26+
let res = drop_tys_helper(
27+
tcx,
28+
query.value,
29+
query.typing_env,
30+
adt_has_dtor,
31+
DropTysOptions::default(),
32+
)
33+
.filter(filter_array_elements(tcx, query.typing_env))
34+
.next()
35+
.is_some();
3136

3237
debug!("needs_drop_raw({:?}) = {:?}", query, res);
3338
res
@@ -42,11 +47,16 @@ fn needs_async_drop_raw<'tcx>(
4247
// it needs async drop.
4348
let adt_has_async_dtor =
4449
|adt_def: ty::AdtDef<'tcx>| adt_def.async_destructor(tcx).map(|_| DtorType::Significant);
45-
let res =
46-
drop_tys_helper(tcx, query.value, query.typing_env, adt_has_async_dtor, false, false, true)
47-
.filter(filter_array_elements_async(tcx, query.typing_env))
48-
.next()
49-
.is_some();
50+
let res = drop_tys_helper(
51+
tcx,
52+
query.value,
53+
query.typing_env,
54+
adt_has_async_dtor,
55+
DropTysOptions::default().recurse_into_box_for_async_drop(),
56+
)
57+
.filter(filter_array_elements_async(tcx, query.typing_env))
58+
.next()
59+
.is_some();
5060

5161
debug!("needs_async_drop_raw({:?}) = {:?}", query, res);
5262
res
@@ -90,9 +100,7 @@ fn has_significant_drop_raw<'tcx>(
90100
query.value,
91101
query.typing_env,
92102
adt_consider_insignificant_dtor(tcx),
93-
true,
94-
false,
95-
false,
103+
DropTysOptions::default().only_significant(),
96104
)
97105
.filter(filter_array_elements(tcx, query.typing_env))
98106
.next()
@@ -323,6 +331,30 @@ enum DtorType {
323331
Significant,
324332
}
325333

334+
#[derive(Copy, Clone, Default)]
335+
struct DropTysOptions {
336+
only_significant: bool,
337+
exhaustive: bool,
338+
async_drop_recurses_into_box: bool,
339+
}
340+
341+
impl DropTysOptions {
342+
fn only_significant(mut self) -> Self {
343+
self.only_significant = true;
344+
self
345+
}
346+
347+
fn exhaustive(mut self) -> Self {
348+
self.exhaustive = true;
349+
self
350+
}
351+
352+
fn recurse_into_box_for_async_drop(mut self) -> Self {
353+
self.async_drop_recurses_into_box = true;
354+
self
355+
}
356+
}
357+
326358
// This is a helper function for `adt_drop_tys` and `adt_significant_drop_tys`.
327359
// Depending on the implantation of `adt_has_dtor`, it is used to check if the
328360
// ADT has a destructor or if the ADT only has a significant destructor. For
@@ -332,9 +364,7 @@ fn drop_tys_helper<'tcx>(
332364
ty: Ty<'tcx>,
333365
typing_env: ty::TypingEnv<'tcx>,
334366
adt_has_dtor: impl Fn(ty::AdtDef<'tcx>) -> Option<DtorType>,
335-
only_significant: bool,
336-
exhaustive: bool,
337-
async_drop_recurses_into_box: bool,
367+
options: DropTysOptions,
338368
) -> impl Iterator<Item = NeedsDropResult<Ty<'tcx>>> {
339369
fn with_query_cache<'tcx>(
340370
tcx: TyCtxt<'tcx>,
@@ -357,14 +387,32 @@ fn drop_tys_helper<'tcx>(
357387
if adt_def.is_manually_drop() {
358388
debug!("drop_tys_helper: `{:?}` is manually drop", adt_def);
359389
Ok(Vec::new())
360-
} else if async_drop_recurses_into_box && adt_def.is_box() {
361-
let boxed_ty = args.type_at(0);
362-
let allocator_ty = args.get(1).map(|arg| arg.expect_ty());
363-
let boxed_ty = match boxed_ty.kind() {
364-
ty::Dynamic(..) | ty::Error(_) => None,
365-
_ => Some(boxed_ty),
390+
} else if options.async_drop_recurses_into_box && adt_def.is_box() {
391+
let box_components = match args.as_slice() {
392+
[boxed_ty, allocator_ty] => {
393+
let boxed_ty = boxed_ty.expect_ty();
394+
let allocator_ty = allocator_ty.expect_ty();
395+
match boxed_ty.kind() {
396+
// FIXME(async_drop): boxed dyn pointees are deliberately skipped here
397+
// because async drop glue does not yet dispatch through dyn metadata.
398+
// Once that is supported, this should include the boxed pointee too.
399+
ty::Dynamic(..) | ty::Error(_) => vec![allocator_ty],
400+
_ => vec![boxed_ty, allocator_ty],
401+
}
402+
}
403+
[boxed_ty] => {
404+
let boxed_ty = boxed_ty.expect_ty();
405+
match boxed_ty.kind() {
406+
ty::Dynamic(..) | ty::Error(_) => Vec::new(),
407+
_ => vec![boxed_ty],
408+
}
409+
}
410+
_ => {
411+
debug!(?args, "drop_tys_helper: `Box` has unexpected generic args");
412+
Vec::new()
413+
}
366414
};
367-
Ok([boxed_ty, allocator_ty].into_iter().flatten().collect())
415+
Ok(box_components)
368416
} else if let Some(dtor_info) = adt_has_dtor(adt_def) {
369417
match dtor_info {
370418
DtorType::Significant => {
@@ -392,7 +440,7 @@ fn drop_tys_helper<'tcx>(
392440
);
393441
r
394442
});
395-
if only_significant {
443+
if options.only_significant {
396444
// We can't recurse through the query system here because we might induce a cycle
397445
Ok(field_tys.collect())
398446
} else {
@@ -406,7 +454,7 @@ fn drop_tys_helper<'tcx>(
406454
.map(|v| v.into_iter())
407455
};
408456

409-
NeedsDropTypes::new(tcx, typing_env, ty, exhaustive, adt_components)
457+
NeedsDropTypes::new(tcx, typing_env, ty, options.exhaustive, adt_components)
410458
}
411459

412460
fn adt_consider_insignificant_dtor<'tcx>(
@@ -445,9 +493,7 @@ fn adt_drop_tys<'tcx>(
445493
tcx.type_of(def_id).instantiate_identity().skip_norm_wip(),
446494
ty::TypingEnv::non_body_analysis(tcx, def_id),
447495
adt_has_dtor,
448-
false,
449-
false,
450-
false,
496+
DropTysOptions::default(),
451497
)
452498
.collect::<Result<Vec<_>, _>>()
453499
.map(|components| tcx.mk_type_list(&components))
@@ -466,9 +512,7 @@ fn adt_async_drop_tys<'tcx>(
466512
tcx.type_of(def_id).instantiate_identity().skip_norm_wip(),
467513
ty::TypingEnv::non_body_analysis(tcx, def_id),
468514
adt_has_dtor,
469-
false,
470-
false,
471-
true,
515+
DropTysOptions::default().recurse_into_box_for_async_drop(),
472516
)
473517
.collect::<Result<Vec<_>, _>>()
474518
.map(|components| tcx.mk_type_list(&components))
@@ -486,9 +530,7 @@ fn adt_significant_drop_tys(
486530
tcx.type_of(def_id).instantiate_identity().skip_norm_wip(), // identical to `tcx.make_adt(def, identity_args)`
487531
ty::TypingEnv::non_body_analysis(tcx, def_id),
488532
adt_consider_insignificant_dtor(tcx),
489-
true,
490-
false,
491-
false,
533+
DropTysOptions::default().only_significant(),
492534
)
493535
.collect::<Result<Vec<_>, _>>()
494536
.map(|components| tcx.mk_type_list(&components))
@@ -505,9 +547,7 @@ fn list_significant_drop_tys<'tcx>(
505547
key.value,
506548
key.typing_env,
507549
adt_consider_insignificant_dtor(tcx),
508-
true,
509-
true,
510-
false,
550+
DropTysOptions::default().only_significant().exhaustive(),
511551
)
512552
.filter_map(|res| res.ok())
513553
.collect::<Vec<_>>(),

tests/ui/async-await/async-drop/async-drop-box.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//@ run-pass
22
//@ check-run-results
33
// struct `Foo` has both sync and async drop.
4-
// `Foo` is always inside `Box`
4+
// `Foo` is always inside `Box`.
55
// Sync version is called in sync context, async version is called in async function.
66

77
#![feature(async_drop)]
@@ -27,6 +27,10 @@ struct Foo {
2727
my_resource_handle: usize,
2828
}
2929

30+
trait DynFoo {}
31+
32+
impl DynFoo for Foo {}
33+
3034
impl Foo {
3135
fn new(my_resource_handle: usize) -> Self {
3236
let out = Foo {
@@ -55,13 +59,21 @@ fn main() {
5559
}
5660
println!("Middle");
5761
block_on(bar(10));
62+
println!("Dyn");
63+
block_on(bar_dyn(20));
5864
println!("Done")
5965
}
6066

6167
async fn bar(ident_base: usize) {
6268
let _first = Box::new(Foo::new(ident_base));
6369
}
6470

71+
async fn bar_dyn(ident_base: usize) {
72+
// FIXME(async_drop): boxed dyn pointees should eventually use async drop
73+
// glue in async contexts. For now this documents the sync-drop fallback.
74+
let _first: Box<dyn DynFoo> = Box::new(Foo::new(ident_base));
75+
}
76+
6577
fn block_on<F>(fut_unpin: F) -> F::Output
6678
where
6779
F: Future,

tests/ui/async-await/async-drop/async-drop-box.run.stdout

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,7 @@ Foo::drop() : 7
33
Middle
44
Foo::new() : 10
55
Foo::async drop() : 10
6+
Dyn
7+
Foo::new() : 20
8+
Foo::drop() : 20
69
Done

0 commit comments

Comments
 (0)