Skip to content

Commit d2cbe21

Browse files
committed
Handle type params in insig dtors
1 parent 1c98988 commit d2cbe21

File tree

3 files changed

+61
-27
lines changed

3 files changed

+61
-27
lines changed

Diff for: compiler/rustc_ty_utils/src/needs_drop.rs

+16-10
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use rustc_data_structures::fx::FxHashSet;
44
use rustc_hir::def_id::DefId;
55
use rustc_middle::ty::subst::Subst;
6+
use rustc_middle::ty::subst::SubstsRef;
67
use rustc_middle::ty::util::{needs_drop_components, AlwaysRequiresDrop};
78
use rustc_middle::ty::{self, Ty, TyCtxt};
89
use rustc_session::Limit;
@@ -12,7 +13,7 @@ type NeedsDropResult<T> = Result<T, AlwaysRequiresDrop>;
1213

1314
fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
1415
let adt_components =
15-
move |adt_def: &ty::AdtDef| tcx.adt_drop_tys(adt_def.did).map(|tys| tys.iter());
16+
move |adt_def: &ty::AdtDef, _| tcx.adt_drop_tys(adt_def.did).map(|tys| tys.iter());
1617

1718
// If we don't know a type doesn't need drop, for example if it's a type
1819
// parameter without a `Copy` bound, then we conservatively return that it
@@ -28,8 +29,9 @@ fn has_significant_drop_raw<'tcx>(
2829
tcx: TyCtxt<'tcx>,
2930
query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
3031
) -> bool {
31-
let significant_drop_fields =
32-
move |adt_def: &ty::AdtDef| tcx.adt_significant_drop_tys(adt_def.did).map(|tys| tys.iter());
32+
let significant_drop_fields = move |adt_def: &ty::AdtDef, _| {
33+
tcx.adt_significant_drop_tys(adt_def.did).map(|tys| tys.iter())
34+
};
3335
let res = NeedsDropTypes::new(tcx, query.param_env, query.value, significant_drop_fields)
3436
.next()
3537
.is_some();
@@ -74,7 +76,7 @@ impl<'tcx, F> NeedsDropTypes<'tcx, F> {
7476

7577
impl<'tcx, F, I> Iterator for NeedsDropTypes<'tcx, F>
7678
where
77-
F: Fn(&ty::AdtDef) -> NeedsDropResult<I>,
79+
F: Fn(&ty::AdtDef, SubstsRef<'tcx>) -> NeedsDropResult<I>,
7880
I: Iterator<Item = Ty<'tcx>>,
7981
{
8082
type Item = NeedsDropResult<Ty<'tcx>>;
@@ -138,7 +140,7 @@ where
138140
// `ManuallyDrop`. If it's a struct or enum without a `Drop`
139141
// impl then check whether the field types need `Drop`.
140142
ty::Adt(adt_def, substs) => {
141-
let tys = match (self.adt_components)(adt_def) {
143+
let tys = match (self.adt_components)(adt_def, substs) {
142144
Err(e) => return Some(Err(e)),
143145
Ok(tys) => tys,
144146
};
@@ -185,12 +187,12 @@ enum DtorType {
185187
// Depending on the implentation of `adt_has_dtor`, it is used to check if the
186188
// ADT has a destructor or if the ADT only has a significant destructor. For
187189
// understanding significant destructor look at `adt_significant_drop_tys`.
188-
fn adt_drop_tys_helper(
189-
tcx: TyCtxt<'_>,
190+
fn adt_drop_tys_helper<'tcx>(
191+
tcx: TyCtxt<'tcx>,
190192
def_id: DefId,
191193
adt_has_dtor: impl Fn(&ty::AdtDef) -> Option<DtorType>,
192-
) -> Result<&ty::List<Ty<'_>>, AlwaysRequiresDrop> {
193-
let adt_components = move |adt_def: &ty::AdtDef| {
194+
) -> Result<&ty::List<Ty<'tcx>>, AlwaysRequiresDrop> {
195+
let adt_components = move |adt_def: &ty::AdtDef, substs: SubstsRef<'tcx>| {
194196
if adt_def.is_manually_drop() {
195197
debug!("adt_drop_tys: `{:?}` is manually drop", adt_def);
196198
return Ok(Vec::new().into_iter());
@@ -202,7 +204,11 @@ fn adt_drop_tys_helper(
202204
}
203205
DtorType::Insignificant => {
204206
debug!("adt_drop_tys: `{:?}` drop is insignificant", adt_def);
205-
return Ok(Vec::new().into_iter());
207+
208+
// Since the destructor is insignificant, we just want to make sure all of
209+
// the passed in type parameters are also insignificant.
210+
// Eg: Vec<T> dtor is insignificant when T=i32 but significant when T=Mutex.
211+
return Ok(substs.types().collect::<Vec<Ty<'_>>>().into_iter());
206212
}
207213
}
208214
} else if adt_def.is_union() {

Diff for: src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.fixed

+6-4
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@
99

1010
struct InsignificantDropPoint {
1111
x: i32,
12-
y: Mutex<T>,
12+
y: Mutex<i32>,
1313
}
1414

1515
impl Drop for InsignificantDropPoint {
1616
#[rustc_insignificant_dtor]
1717
fn drop(&mut self) {}
1818
}
1919

20-
struct SigDrop { x: () }
20+
struct SigDrop;
2121

2222
impl Drop for SigDrop {
2323
fn drop(&mut self) {}
@@ -45,9 +45,10 @@ fn insign_dtor() {
4545

4646
// `SigDrop` implements drop and therefore needs to be migrated.
4747
fn significant_drop_needs_migration() {
48-
let t = (SigDrop { x: () }, SigDrop { x: () });
48+
let t = (SigDrop {}, SigDrop {});
4949

5050
let c = || {
51+
let _ = &t;
5152
//~^ ERROR: drop order
5253
//~| NOTE: for more information, see
5354
//~| HELP: add a dummy let to cause `t` to be fully captured
@@ -64,10 +65,11 @@ fn significant_drop_needs_migration() {
6465
// consdered to have an significant drop. Since the elements
6566
// of `GenericStruct` implement drop, migration is required.
6667
fn generic_struct_with_significant_drop_needs_migration() {
67-
let t = Wrapper(GenericStruct(SigDrop { x: () }, SigDrop { x: () }), 5);
68+
let t = Wrapper(GenericStruct(SigDrop {}, SigDrop {}), 5);
6869

6970
// move is used to force i32 to be copied instead of being a ref
7071
let c = move || {
72+
let _ = &t;
7173
//~^ ERROR: drop order
7274
//~| NOTE: for more information, see
7375
//~| HELP: add a dummy let to cause `t` to be fully captured

Diff for: src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.stderr

+39-13
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,45 @@
1-
error[E0107]: missing generics for struct `Mutex`
2-
--> $DIR/insignificant_drop_attr_migrations.rs:12:8
1+
error: changes to closure capture in Rust 2021 will affect drop order
2+
--> $DIR/insignificant_drop_attr_migrations.rs:50:13
33
|
4-
LL | y: Mutex,
5-
| ^^^^^ expected 1 generic argument
4+
LL | let c = || {
5+
| ^^
6+
...
7+
LL | let _t = t.0;
8+
| --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
9+
...
10+
LL | }
11+
| - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
612
|
7-
note: struct defined here, with 1 generic parameter: `T`
8-
--> $SRC_DIR/std/src/sync/mutex.rs:LL:COL
13+
note: the lint level is defined here
14+
--> $DIR/insignificant_drop_attr_migrations.rs:3:9
915
|
10-
LL | pub struct Mutex<T: ?Sized> {
11-
| ^^^^^ -
12-
help: add missing generic argument
16+
LL | #![deny(rust_2021_incompatible_closure_captures)]
17+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
18+
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
19+
help: add a dummy let to cause `t` to be fully captured
20+
|
21+
LL ~ let c = || {
22+
LL + let _ = &t;
23+
|
24+
25+
error: changes to closure capture in Rust 2021 will affect drop order
26+
--> $DIR/insignificant_drop_attr_migrations.rs:70:13
27+
|
28+
LL | let c = move || {
29+
| ^^^^^^^
30+
...
31+
LL | let _t = t.1;
32+
| --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1`
33+
...
34+
LL | }
35+
| - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure
36+
|
37+
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
38+
help: add a dummy let to cause `t` to be fully captured
39+
|
40+
LL ~ let c = move || {
41+
LL + let _ = &t;
1342
|
14-
LL | y: Mutex<T>,
15-
| ~~~~~~~~
1643

17-
error: aborting due to previous error
44+
error: aborting due to 2 previous errors
1845

19-
For more information about this error, try `rustc --explain E0107`.

0 commit comments

Comments
 (0)