mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 07:14:28 +00:00
Auto merge of #89144 - sexxi-goose:insig_stdlib, r=nikomatsakis
2229: Mark insignificant dtor in stdlib I looked at all public [stdlib Drop implementations](https://doc.rust-lang.org/stable/std/ops/trait.Drop.html#implementors) and categorized them into Insigificant/Maybe/Significant Drop. Reasons are noted here: https://docs.google.com/spreadsheets/d/19edb9r5lo2UqMrCOVjV0fwcSdS-R7qvKNL76q7tO8VA/edit#gid=1838773501 One thing missing from this PR is tagging HashMap as insigificant destructor as that needs some discussion. r? `@Mark-Simulacrum` cc `@nikomatsakis`
This commit is contained in:
commit
05044c2e6c
@ -3,6 +3,7 @@
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::ty::subst::Subst;
|
||||
use rustc_middle::ty::subst::SubstsRef;
|
||||
use rustc_middle::ty::util::{needs_drop_components, AlwaysRequiresDrop};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_session::Limit;
|
||||
@ -12,7 +13,7 @@ type NeedsDropResult<T> = Result<T, AlwaysRequiresDrop>;
|
||||
|
||||
fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
|
||||
let adt_components =
|
||||
move |adt_def: &ty::AdtDef| tcx.adt_drop_tys(adt_def.did).map(|tys| tys.iter());
|
||||
move |adt_def: &ty::AdtDef, _| tcx.adt_drop_tys(adt_def.did).map(|tys| tys.iter());
|
||||
|
||||
// If we don't know a type doesn't need drop, for example if it's a type
|
||||
// parameter without a `Copy` bound, then we conservatively return that it
|
||||
@ -28,8 +29,9 @@ fn has_significant_drop_raw<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
|
||||
) -> bool {
|
||||
let significant_drop_fields =
|
||||
move |adt_def: &ty::AdtDef| tcx.adt_significant_drop_tys(adt_def.did).map(|tys| tys.iter());
|
||||
let significant_drop_fields = move |adt_def: &ty::AdtDef, _| {
|
||||
tcx.adt_significant_drop_tys(adt_def.did).map(|tys| tys.iter())
|
||||
};
|
||||
let res = NeedsDropTypes::new(tcx, query.param_env, query.value, significant_drop_fields)
|
||||
.next()
|
||||
.is_some();
|
||||
@ -74,7 +76,7 @@ impl<'tcx, F> NeedsDropTypes<'tcx, F> {
|
||||
|
||||
impl<'tcx, F, I> Iterator for NeedsDropTypes<'tcx, F>
|
||||
where
|
||||
F: Fn(&ty::AdtDef) -> NeedsDropResult<I>,
|
||||
F: Fn(&ty::AdtDef, SubstsRef<'tcx>) -> NeedsDropResult<I>,
|
||||
I: Iterator<Item = Ty<'tcx>>,
|
||||
{
|
||||
type Item = NeedsDropResult<Ty<'tcx>>;
|
||||
@ -138,7 +140,7 @@ where
|
||||
// `ManuallyDrop`. If it's a struct or enum without a `Drop`
|
||||
// impl then check whether the field types need `Drop`.
|
||||
ty::Adt(adt_def, substs) => {
|
||||
let tys = match (self.adt_components)(adt_def) {
|
||||
let tys = match (self.adt_components)(adt_def, substs) {
|
||||
Err(e) => return Some(Err(e)),
|
||||
Ok(tys) => tys,
|
||||
};
|
||||
@ -171,22 +173,44 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
enum DtorType {
|
||||
/// Type has a `Drop` but it is considered insignificant.
|
||||
/// Check the query `adt_significant_drop_tys` for understanding
|
||||
/// "significant" / "insignificant".
|
||||
Insignificant,
|
||||
|
||||
/// Type has a `Drop` implentation.
|
||||
Significant,
|
||||
}
|
||||
|
||||
// This is a helper function for `adt_drop_tys` and `adt_significant_drop_tys`.
|
||||
// Depending on the implentation of `adt_has_dtor`, it is used to check if the
|
||||
// ADT has a destructor or if the ADT only has a significant destructor. For
|
||||
// understanding significant destructor look at `adt_significant_drop_tys`.
|
||||
fn adt_drop_tys_helper(
|
||||
tcx: TyCtxt<'_>,
|
||||
fn adt_drop_tys_helper<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
adt_has_dtor: impl Fn(&ty::AdtDef) -> bool,
|
||||
) -> Result<&ty::List<Ty<'_>>, AlwaysRequiresDrop> {
|
||||
let adt_components = move |adt_def: &ty::AdtDef| {
|
||||
adt_has_dtor: impl Fn(&ty::AdtDef) -> Option<DtorType>,
|
||||
) -> Result<&ty::List<Ty<'tcx>>, AlwaysRequiresDrop> {
|
||||
let adt_components = move |adt_def: &ty::AdtDef, substs: SubstsRef<'tcx>| {
|
||||
if adt_def.is_manually_drop() {
|
||||
debug!("adt_drop_tys: `{:?}` is manually drop", adt_def);
|
||||
return Ok(Vec::new().into_iter());
|
||||
} else if adt_has_dtor(adt_def) {
|
||||
} else if let Some(dtor_info) = adt_has_dtor(adt_def) {
|
||||
match dtor_info {
|
||||
DtorType::Significant => {
|
||||
debug!("adt_drop_tys: `{:?}` implements `Drop`", adt_def);
|
||||
return Err(AlwaysRequiresDrop);
|
||||
}
|
||||
DtorType::Insignificant => {
|
||||
debug!("adt_drop_tys: `{:?}` drop is insignificant", adt_def);
|
||||
|
||||
// Since the destructor is insignificant, we just want to make sure all of
|
||||
// the passed in type parameters are also insignificant.
|
||||
// Eg: Vec<T> dtor is insignificant when T=i32 but significant when T=Mutex.
|
||||
return Ok(substs.types().collect::<Vec<Ty<'_>>>().into_iter());
|
||||
}
|
||||
}
|
||||
} else if adt_def.is_union() {
|
||||
debug!("adt_drop_tys: `{:?}` is a union", adt_def);
|
||||
return Ok(Vec::new().into_iter());
|
||||
@ -204,7 +228,10 @@ fn adt_drop_tys_helper(
|
||||
}
|
||||
|
||||
fn adt_drop_tys(tcx: TyCtxt<'_>, def_id: DefId) -> Result<&ty::List<Ty<'_>>, AlwaysRequiresDrop> {
|
||||
let adt_has_dtor = |adt_def: &ty::AdtDef| adt_def.destructor(tcx).is_some();
|
||||
// This is for the "needs_drop" query, that considers all `Drop` impls, therefore all dtors are
|
||||
// significant.
|
||||
let adt_has_dtor =
|
||||
|adt_def: &ty::AdtDef| adt_def.destructor(tcx).map(|_| DtorType::Significant);
|
||||
adt_drop_tys_helper(tcx, def_id, adt_has_dtor)
|
||||
}
|
||||
|
||||
@ -213,10 +240,22 @@ fn adt_significant_drop_tys(
|
||||
def_id: DefId,
|
||||
) -> Result<&ty::List<Ty<'_>>, AlwaysRequiresDrop> {
|
||||
let adt_has_dtor = |adt_def: &ty::AdtDef| {
|
||||
adt_def
|
||||
.destructor(tcx)
|
||||
.map(|dtor| !tcx.has_attr(dtor.did, sym::rustc_insignificant_dtor))
|
||||
.unwrap_or(false)
|
||||
let is_marked_insig = tcx.has_attr(adt_def.did, sym::rustc_insignificant_dtor);
|
||||
if is_marked_insig {
|
||||
// In some cases like `std::collections::HashMap` where the struct is a wrapper around
|
||||
// a type that is a Drop type, and the wrapped type (eg: `hashbrown::HashMap`) lies
|
||||
// outside stdlib, we might choose to still annotate the the wrapper (std HashMap) with
|
||||
// `rustc_insignificant_dtor`, even if the type itself doesn't have a `Drop` impl.
|
||||
Some(DtorType::Insignificant)
|
||||
} else if adt_def.destructor(tcx).is_some() {
|
||||
// There is a Drop impl and the type isn't marked insignificant, therefore Drop must be
|
||||
// significant.
|
||||
Some(DtorType::Significant)
|
||||
} else {
|
||||
// No destructor found nor the type is annotated with `rustc_insignificant_dtor`, we
|
||||
// treat this as the simple case of Drop impl for type.
|
||||
None
|
||||
}
|
||||
};
|
||||
adt_drop_tys_helper(tcx, def_id, adt_has_dtor)
|
||||
}
|
||||
|
@ -155,6 +155,7 @@ pub(super) const MIN_LEN: usize = node::MIN_LEN_AFTER_SPLIT;
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "BTreeMap")]
|
||||
#[rustc_insignificant_dtor]
|
||||
pub struct BTreeMap<K, V> {
|
||||
root: Option<Root<K, V>>,
|
||||
length: usize,
|
||||
@ -331,6 +332,7 @@ impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for IterMut<'_, K, V> {
|
||||
/// [`into_iter`]: IntoIterator::into_iter
|
||||
/// [`IntoIterator`]: core::iter::IntoIterator
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_insignificant_dtor]
|
||||
pub struct IntoIter<K, V> {
|
||||
range: LazyLeafRange<marker::Dying, K, V>,
|
||||
length: usize,
|
||||
|
@ -46,6 +46,7 @@ mod tests;
|
||||
/// [`VecDeque`]: super::vec_deque::VecDeque
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "LinkedList")]
|
||||
#[rustc_insignificant_dtor]
|
||||
pub struct LinkedList<T> {
|
||||
head: Option<NonNull<Node<T>>>,
|
||||
tail: Option<NonNull<Node<T>>>,
|
||||
|
@ -90,6 +90,7 @@ const MAXIMUM_ZST_CAPACITY: usize = 1 << (usize::BITS - 1); // Largest possible
|
||||
/// [`make_contiguous`]: VecDeque::make_contiguous
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "vecdeque_type")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_insignificant_dtor]
|
||||
pub struct VecDeque<
|
||||
T,
|
||||
#[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
|
||||
|
@ -305,6 +305,7 @@ struct RcBox<T: ?Sized> {
|
||||
/// [get_mut]: Rc::get_mut
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "Rc")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_insignificant_dtor]
|
||||
pub struct Rc<T: ?Sized> {
|
||||
ptr: NonNull<RcBox<T>>,
|
||||
phantom: PhantomData<RcBox<T>>,
|
||||
|
@ -22,6 +22,7 @@ use core::slice::{self};
|
||||
/// let iter: std::vec::IntoIter<_> = v.into_iter();
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_insignificant_dtor]
|
||||
pub struct IntoIter<
|
||||
T,
|
||||
#[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
|
||||
|
@ -396,6 +396,7 @@ mod spec_extend;
|
||||
/// [owned slice]: Box
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "vec_type")]
|
||||
#[rustc_insignificant_dtor]
|
||||
pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
|
||||
buf: RawVec<T, A>,
|
||||
len: usize,
|
||||
|
@ -10,6 +10,7 @@ use crate::{
|
||||
|
||||
/// A by-value [array] iterator.
|
||||
#[stable(feature = "array_value_iter", since = "1.51.0")]
|
||||
#[rustc_insignificant_dtor]
|
||||
pub struct IntoIter<T, const N: usize> {
|
||||
/// This is the array we are iterating over.
|
||||
///
|
||||
|
@ -205,6 +205,7 @@ use crate::sys;
|
||||
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "hashmap_type")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_insignificant_dtor]
|
||||
pub struct HashMap<K, V, S = RandomState> {
|
||||
base: base::HashMap<K, V, S>,
|
||||
}
|
||||
|
@ -4,6 +4,14 @@
|
||||
|
||||
use std::thread;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Foo(i32);
|
||||
impl Drop for Foo {
|
||||
fn drop(&mut self) {
|
||||
println!("{:?} dropped", self.0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Test Send Trait Migration */
|
||||
struct SendPointer(*mut i32);
|
||||
unsafe impl Send for SendPointer {}
|
||||
@ -42,19 +50,19 @@ fn test_sync_trait() {
|
||||
}
|
||||
|
||||
/* Test Clone Trait Migration */
|
||||
struct S(String);
|
||||
struct S(Foo);
|
||||
struct T(i32);
|
||||
|
||||
struct U(S, T);
|
||||
|
||||
impl Clone for U {
|
||||
fn clone(&self) -> Self {
|
||||
U(S(String::from("Hello World")), T(0))
|
||||
U(S(Foo(0)), T(0))
|
||||
}
|
||||
}
|
||||
|
||||
fn test_clone_trait() {
|
||||
let f = U(S(String::from("Hello World")), T(0));
|
||||
let f = U(S(Foo(0)), T(0));
|
||||
let c = || {
|
||||
let _ = &f;
|
||||
//~^ ERROR: `Clone` trait implementation for closure and drop order
|
||||
|
@ -4,6 +4,14 @@
|
||||
|
||||
use std::thread;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Foo(i32);
|
||||
impl Drop for Foo {
|
||||
fn drop(&mut self) {
|
||||
println!("{:?} dropped", self.0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Test Send Trait Migration */
|
||||
struct SendPointer(*mut i32);
|
||||
unsafe impl Send for SendPointer {}
|
||||
@ -42,19 +50,19 @@ fn test_sync_trait() {
|
||||
}
|
||||
|
||||
/* Test Clone Trait Migration */
|
||||
struct S(String);
|
||||
struct S(Foo);
|
||||
struct T(i32);
|
||||
|
||||
struct U(S, T);
|
||||
|
||||
impl Clone for U {
|
||||
fn clone(&self) -> Self {
|
||||
U(S(String::from("Hello World")), T(0))
|
||||
U(S(Foo(0)), T(0))
|
||||
}
|
||||
}
|
||||
|
||||
fn test_clone_trait() {
|
||||
let f = U(S(String::from("Hello World")), T(0));
|
||||
let f = U(S(Foo(0)), T(0));
|
||||
let c = || {
|
||||
//~^ ERROR: `Clone` trait implementation for closure and drop order
|
||||
//~| NOTE: in Rust 2018, this closure implements `Clone` as `f` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f.1` does not implement `Clone`
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: changes to closure capture in Rust 2021 will affect `Send` trait implementation for closure
|
||||
--> $DIR/auto_traits.rs:14:19
|
||||
--> $DIR/auto_traits.rs:22:19
|
||||
|
|
||||
LL | thread::spawn(move || unsafe {
|
||||
| ^^^^^^^^^^^^^^ in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr.0` does not implement `Send`
|
||||
@ -24,7 +24,7 @@ LL | *fptr.0 = 20;
|
||||
...
|
||||
|
||||
error: changes to closure capture in Rust 2021 will affect `Sync`, `Send` trait implementation for closure
|
||||
--> $DIR/auto_traits.rs:34:19
|
||||
--> $DIR/auto_traits.rs:42:19
|
||||
|
|
||||
LL | thread::spawn(move || unsafe {
|
||||
| ^^^^^^^^^^^^^^ in Rust 2018, this closure implements `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send`
|
||||
@ -44,7 +44,7 @@ LL | *fptr.0.0 = 20;
|
||||
...
|
||||
|
||||
error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure and drop order
|
||||
--> $DIR/auto_traits.rs:58:13
|
||||
--> $DIR/auto_traits.rs:66:13
|
||||
|
|
||||
LL | let c = || {
|
||||
| ^^ in Rust 2018, this closure implements `Clone` as `f` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f.1` does not implement `Clone`
|
||||
|
@ -3,6 +3,14 @@
|
||||
// check-pass
|
||||
#![warn(rust_2021_compatibility)]
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Foo(i32);
|
||||
impl Drop for Foo {
|
||||
fn drop(&mut self) {
|
||||
println!("{:?} dropped", self.0);
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! m {
|
||||
(@ $body:expr) => {{
|
||||
let f = || $body;
|
||||
@ -15,11 +23,11 @@ macro_rules! m {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let a = (1.to_string(), 2.to_string());
|
||||
let a = (Foo(0), Foo(1));
|
||||
m!({
|
||||
let _ = &a;
|
||||
//~^ HELP: add a dummy
|
||||
let x = a.0;
|
||||
println!("{}", x);
|
||||
println!("{:?}", x);
|
||||
});
|
||||
}
|
||||
|
@ -3,6 +3,14 @@
|
||||
// check-pass
|
||||
#![warn(rust_2021_compatibility)]
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Foo(i32);
|
||||
impl Drop for Foo {
|
||||
fn drop(&mut self) {
|
||||
println!("{:?} dropped", self.0);
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! m {
|
||||
(@ $body:expr) => {{
|
||||
let f = || $body;
|
||||
@ -15,10 +23,10 @@ macro_rules! m {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let a = (1.to_string(), 2.to_string());
|
||||
let a = (Foo(0), Foo(1));
|
||||
m!({
|
||||
//~^ HELP: add a dummy
|
||||
let x = a.0;
|
||||
println!("{}", x);
|
||||
println!("{:?}", x);
|
||||
});
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
warning: changes to closure capture in Rust 2021 will affect drop order
|
||||
--> $DIR/closure-body-macro-fragment.rs:8:17
|
||||
--> $DIR/closure-body-macro-fragment.rs:16:17
|
||||
|
|
||||
LL | let f = || $body;
|
||||
| _________________^
|
||||
@ -15,7 +15,7 @@ LL | / m!({
|
||||
LL | |
|
||||
LL | | let x = a.0;
|
||||
| | --- in Rust 2018, this closure captures all of `a`, but in Rust 2021, it will only capture `a.0`
|
||||
LL | | println!("{}", x);
|
||||
LL | | println!("{:?}", x);
|
||||
LL | | });
|
||||
| |_______- in this macro invocation
|
||||
|
|
||||
|
@ -1,169 +1,38 @@
|
||||
// run-pass
|
||||
// run-rustfix
|
||||
|
||||
#![deny(rust_2021_incompatible_closure_captures)]
|
||||
//~^ NOTE: the lint level is defined here
|
||||
#![allow(unused)]
|
||||
|
||||
// Test cases for types that implement an insignificant drop (stlib defined)
|
||||
|
||||
// `t` needs Drop because one of its elements needs drop,
|
||||
// therefore precise capture might affect drop ordering
|
||||
fn test1_all_need_migration() {
|
||||
let t = (String::new(), String::new());
|
||||
let t1 = (String::new(), String::new());
|
||||
let t2 = (String::new(), String::new());
|
||||
macro_rules! test_insig_dtor_for_type {
|
||||
($t: ty, $disambiguator: ident) => {
|
||||
mod $disambiguator {
|
||||
use std::collections::*;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Mutex;
|
||||
|
||||
let c = || {
|
||||
let _ = (&t, &t1, &t2);
|
||||
//~^ ERROR: drop order
|
||||
//~| NOTE: for more information, see
|
||||
//~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
|
||||
fn test_for_type(t: $t) {
|
||||
let tup = (Mutex::new(0), t);
|
||||
|
||||
let _t = t.0;
|
||||
//~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
|
||||
let _t1 = t1.0;
|
||||
//~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0`
|
||||
let _t2 = t2.0;
|
||||
//~^ NOTE: in Rust 2018, this closure captures all of `t2`, but in Rust 2021, it will only capture `t2.0`
|
||||
let _c = || tup.0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
c();
|
||||
}
|
||||
//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
|
||||
//~| in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
|
||||
//~| in Rust 2018, `t2` is dropped here, but in Rust 2021, only `t2.0` will be dropped here as part of the closure
|
||||
|
||||
// String implements drop and therefore should be migrated.
|
||||
// But in this test cases, `t2` is completely captured and when it is dropped won't be affected
|
||||
fn test2_only_precise_paths_need_migration() {
|
||||
let t = (String::new(), String::new());
|
||||
let t1 = (String::new(), String::new());
|
||||
let t2 = (String::new(), String::new());
|
||||
test_insig_dtor_for_type!(i32, prim_i32);
|
||||
test_insig_dtor_for_type!(Vec<i32>, vec_i32);
|
||||
test_insig_dtor_for_type!(String, string);
|
||||
test_insig_dtor_for_type!(Vec<String>, vec_string);
|
||||
test_insig_dtor_for_type!(HashMap<String, String>, hash_map);
|
||||
test_insig_dtor_for_type!(BTreeMap<String, i32>, btree_map);
|
||||
test_insig_dtor_for_type!(LinkedList<String>, linked_list);
|
||||
test_insig_dtor_for_type!(Rc<i32>, rc_i32);
|
||||
test_insig_dtor_for_type!(Rc<String>, rc_string);
|
||||
test_insig_dtor_for_type!(std::vec::IntoIter<String>, vec_into_iter);
|
||||
test_insig_dtor_for_type!(btree_map::IntoIter<String, String>, btree_map_into_iter);
|
||||
test_insig_dtor_for_type!(std::array::IntoIter<String, 5>, array_into_iter);
|
||||
|
||||
let c = || {
|
||||
let _ = (&t, &t1);
|
||||
//~^ ERROR: drop order
|
||||
//~| NOTE: for more information, see
|
||||
//~| HELP: add a dummy let to cause `t`, `t1` to be fully captured
|
||||
let _t = t.0;
|
||||
//~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
|
||||
let _t1 = t1.0;
|
||||
//~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0`
|
||||
let _t2 = t2;
|
||||
};
|
||||
|
||||
c();
|
||||
}
|
||||
//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
|
||||
//~| in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
|
||||
|
||||
// If a variable would've not been captured by value then it would've not been
|
||||
// dropped with the closure and therefore doesn't need migration.
|
||||
fn test3_only_by_value_need_migration() {
|
||||
let t = (String::new(), String::new());
|
||||
let t1 = (String::new(), String::new());
|
||||
let c = || {
|
||||
let _ = &t;
|
||||
//~^ ERROR: drop order
|
||||
//~| NOTE: for more information, see
|
||||
//~| HELP: add a dummy let to cause `t` to be fully captured
|
||||
let _t = t.0;
|
||||
//~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
|
||||
println!("{}", t1.1);
|
||||
};
|
||||
|
||||
c();
|
||||
}
|
||||
//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
|
||||
|
||||
// Copy types get copied into the closure instead of move. Therefore we don't need to
|
||||
// migrate then as their drop order isn't tied to the closure.
|
||||
fn test4_only_non_copy_types_need_migration() {
|
||||
let t = (String::new(), String::new());
|
||||
|
||||
// `t1` is Copy because all of its elements are Copy
|
||||
let t1 = (0i32, 0i32);
|
||||
|
||||
let c = || {
|
||||
let _ = &t;
|
||||
//~^ ERROR: drop order
|
||||
//~| NOTE: for more information, see
|
||||
//~| HELP: add a dummy let to cause `t` to be fully captured
|
||||
let _t = t.0;
|
||||
//~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
|
||||
let _t1 = t1.0;
|
||||
};
|
||||
|
||||
c();
|
||||
}
|
||||
//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
|
||||
|
||||
fn test5_only_drop_types_need_migration() {
|
||||
struct S(i32, i32);
|
||||
|
||||
let t = (String::new(), String::new());
|
||||
|
||||
// `s` doesn't implement Drop or any elements within it, and doesn't need migration
|
||||
let s = S(0i32, 0i32);
|
||||
|
||||
let c = || {
|
||||
let _ = &t;
|
||||
//~^ ERROR: drop order
|
||||
//~| NOTE: for more information, see
|
||||
//~| HELP: add a dummy let to cause `t` to be fully captured
|
||||
let _t = t.0;
|
||||
//~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
|
||||
let _s = s.0;
|
||||
};
|
||||
|
||||
c();
|
||||
}
|
||||
//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
|
||||
|
||||
// Since we are using a move closure here, both `t` and `t1` get moved
|
||||
// even though they are being used by ref inside the closure.
|
||||
fn test6_move_closures_non_copy_types_might_need_migration() {
|
||||
let t = (String::new(), String::new());
|
||||
let t1 = (String::new(), String::new());
|
||||
let c = move || {
|
||||
let _ = (&t1, &t);
|
||||
//~^ ERROR: drop order
|
||||
//~| NOTE: for more information, see
|
||||
//~| HELP: add a dummy let to cause `t1`, `t` to be fully captured
|
||||
println!("{} {}", t1.1, t.1);
|
||||
//~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1`
|
||||
//~| NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.1`
|
||||
};
|
||||
|
||||
c();
|
||||
}
|
||||
//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure
|
||||
//~| in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.1` will be dropped here as part of the closure
|
||||
|
||||
// Test migration analysis in case of Drop + Non Drop aggregates.
|
||||
// Note we need migration here only because the non-copy (because Drop type) is captured,
|
||||
// otherwise we won't need to, since we can get away with just by ref capture in that case.
|
||||
fn test7_drop_non_drop_aggregate_need_migration() {
|
||||
let t = (String::new(), String::new(), 0i32);
|
||||
|
||||
let c = || {
|
||||
let _ = &t;
|
||||
//~^ ERROR: drop order
|
||||
//~| NOTE: for more information, see
|
||||
//~| HELP: add a dummy let to cause `t` to be fully captured
|
||||
let _t = t.0;
|
||||
//~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
|
||||
};
|
||||
|
||||
c();
|
||||
}
|
||||
//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
|
||||
|
||||
fn main() {
|
||||
test1_all_need_migration();
|
||||
test2_only_precise_paths_need_migration();
|
||||
test3_only_by_value_need_migration();
|
||||
test4_only_non_copy_types_need_migration();
|
||||
test5_only_drop_types_need_migration();
|
||||
test6_move_closures_non_copy_types_might_need_migration();
|
||||
test7_drop_non_drop_aggregate_need_migration();
|
||||
}
|
||||
fn main() {}
|
||||
|
@ -1,162 +1,38 @@
|
||||
// run-pass
|
||||
// run-rustfix
|
||||
|
||||
#![deny(rust_2021_incompatible_closure_captures)]
|
||||
//~^ NOTE: the lint level is defined here
|
||||
#![allow(unused)]
|
||||
|
||||
// Test cases for types that implement an insignificant drop (stlib defined)
|
||||
|
||||
// `t` needs Drop because one of its elements needs drop,
|
||||
// therefore precise capture might affect drop ordering
|
||||
fn test1_all_need_migration() {
|
||||
let t = (String::new(), String::new());
|
||||
let t1 = (String::new(), String::new());
|
||||
let t2 = (String::new(), String::new());
|
||||
macro_rules! test_insig_dtor_for_type {
|
||||
($t: ty, $disambiguator: ident) => {
|
||||
mod $disambiguator {
|
||||
use std::collections::*;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Mutex;
|
||||
|
||||
let c = || {
|
||||
//~^ ERROR: drop order
|
||||
//~| NOTE: for more information, see
|
||||
//~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
|
||||
fn test_for_type(t: $t) {
|
||||
let tup = (Mutex::new(0), t);
|
||||
|
||||
let _t = t.0;
|
||||
//~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
|
||||
let _t1 = t1.0;
|
||||
//~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0`
|
||||
let _t2 = t2.0;
|
||||
//~^ NOTE: in Rust 2018, this closure captures all of `t2`, but in Rust 2021, it will only capture `t2.0`
|
||||
let _c = || tup.0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
c();
|
||||
}
|
||||
//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
|
||||
//~| in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
|
||||
//~| in Rust 2018, `t2` is dropped here, but in Rust 2021, only `t2.0` will be dropped here as part of the closure
|
||||
|
||||
// String implements drop and therefore should be migrated.
|
||||
// But in this test cases, `t2` is completely captured and when it is dropped won't be affected
|
||||
fn test2_only_precise_paths_need_migration() {
|
||||
let t = (String::new(), String::new());
|
||||
let t1 = (String::new(), String::new());
|
||||
let t2 = (String::new(), String::new());
|
||||
test_insig_dtor_for_type!(i32, prim_i32);
|
||||
test_insig_dtor_for_type!(Vec<i32>, vec_i32);
|
||||
test_insig_dtor_for_type!(String, string);
|
||||
test_insig_dtor_for_type!(Vec<String>, vec_string);
|
||||
test_insig_dtor_for_type!(HashMap<String, String>, hash_map);
|
||||
test_insig_dtor_for_type!(BTreeMap<String, i32>, btree_map);
|
||||
test_insig_dtor_for_type!(LinkedList<String>, linked_list);
|
||||
test_insig_dtor_for_type!(Rc<i32>, rc_i32);
|
||||
test_insig_dtor_for_type!(Rc<String>, rc_string);
|
||||
test_insig_dtor_for_type!(std::vec::IntoIter<String>, vec_into_iter);
|
||||
test_insig_dtor_for_type!(btree_map::IntoIter<String, String>, btree_map_into_iter);
|
||||
test_insig_dtor_for_type!(std::array::IntoIter<String, 5>, array_into_iter);
|
||||
|
||||
let c = || {
|
||||
//~^ ERROR: drop order
|
||||
//~| NOTE: for more information, see
|
||||
//~| HELP: add a dummy let to cause `t`, `t1` to be fully captured
|
||||
let _t = t.0;
|
||||
//~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
|
||||
let _t1 = t1.0;
|
||||
//~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0`
|
||||
let _t2 = t2;
|
||||
};
|
||||
|
||||
c();
|
||||
}
|
||||
//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
|
||||
//~| in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
|
||||
|
||||
// If a variable would've not been captured by value then it would've not been
|
||||
// dropped with the closure and therefore doesn't need migration.
|
||||
fn test3_only_by_value_need_migration() {
|
||||
let t = (String::new(), String::new());
|
||||
let t1 = (String::new(), String::new());
|
||||
let c = || {
|
||||
//~^ ERROR: drop order
|
||||
//~| NOTE: for more information, see
|
||||
//~| HELP: add a dummy let to cause `t` to be fully captured
|
||||
let _t = t.0;
|
||||
//~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
|
||||
println!("{}", t1.1);
|
||||
};
|
||||
|
||||
c();
|
||||
}
|
||||
//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
|
||||
|
||||
// Copy types get copied into the closure instead of move. Therefore we don't need to
|
||||
// migrate then as their drop order isn't tied to the closure.
|
||||
fn test4_only_non_copy_types_need_migration() {
|
||||
let t = (String::new(), String::new());
|
||||
|
||||
// `t1` is Copy because all of its elements are Copy
|
||||
let t1 = (0i32, 0i32);
|
||||
|
||||
let c = || {
|
||||
//~^ ERROR: drop order
|
||||
//~| NOTE: for more information, see
|
||||
//~| HELP: add a dummy let to cause `t` to be fully captured
|
||||
let _t = t.0;
|
||||
//~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
|
||||
let _t1 = t1.0;
|
||||
};
|
||||
|
||||
c();
|
||||
}
|
||||
//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
|
||||
|
||||
fn test5_only_drop_types_need_migration() {
|
||||
struct S(i32, i32);
|
||||
|
||||
let t = (String::new(), String::new());
|
||||
|
||||
// `s` doesn't implement Drop or any elements within it, and doesn't need migration
|
||||
let s = S(0i32, 0i32);
|
||||
|
||||
let c = || {
|
||||
//~^ ERROR: drop order
|
||||
//~| NOTE: for more information, see
|
||||
//~| HELP: add a dummy let to cause `t` to be fully captured
|
||||
let _t = t.0;
|
||||
//~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
|
||||
let _s = s.0;
|
||||
};
|
||||
|
||||
c();
|
||||
}
|
||||
//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
|
||||
|
||||
// Since we are using a move closure here, both `t` and `t1` get moved
|
||||
// even though they are being used by ref inside the closure.
|
||||
fn test6_move_closures_non_copy_types_might_need_migration() {
|
||||
let t = (String::new(), String::new());
|
||||
let t1 = (String::new(), String::new());
|
||||
let c = move || {
|
||||
//~^ ERROR: drop order
|
||||
//~| NOTE: for more information, see
|
||||
//~| HELP: add a dummy let to cause `t1`, `t` to be fully captured
|
||||
println!("{} {}", t1.1, t.1);
|
||||
//~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1`
|
||||
//~| NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.1`
|
||||
};
|
||||
|
||||
c();
|
||||
}
|
||||
//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure
|
||||
//~| in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.1` will be dropped here as part of the closure
|
||||
|
||||
// Test migration analysis in case of Drop + Non Drop aggregates.
|
||||
// Note we need migration here only because the non-copy (because Drop type) is captured,
|
||||
// otherwise we won't need to, since we can get away with just by ref capture in that case.
|
||||
fn test7_drop_non_drop_aggregate_need_migration() {
|
||||
let t = (String::new(), String::new(), 0i32);
|
||||
|
||||
let c = || {
|
||||
//~^ ERROR: drop order
|
||||
//~| NOTE: for more information, see
|
||||
//~| HELP: add a dummy let to cause `t` to be fully captured
|
||||
let _t = t.0;
|
||||
//~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
|
||||
};
|
||||
|
||||
c();
|
||||
}
|
||||
//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
|
||||
|
||||
fn main() {
|
||||
test1_all_need_migration();
|
||||
test2_only_precise_paths_need_migration();
|
||||
test3_only_by_value_need_migration();
|
||||
test4_only_non_copy_types_need_migration();
|
||||
test5_only_drop_types_need_migration();
|
||||
test6_move_closures_non_copy_types_might_need_migration();
|
||||
test7_drop_non_drop_aggregate_need_migration();
|
||||
}
|
||||
fn main() {}
|
||||
|
@ -1,161 +0,0 @@
|
||||
error: changes to closure capture in Rust 2021 will affect drop order
|
||||
--> $DIR/insignificant_drop.rs:15:13
|
||||
|
|
||||
LL | let c = || {
|
||||
| ^^
|
||||
...
|
||||
LL | let _t = t.0;
|
||||
| --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
|
||||
LL |
|
||||
LL | let _t1 = t1.0;
|
||||
| ---- in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0`
|
||||
LL |
|
||||
LL | let _t2 = t2.0;
|
||||
| ---- in Rust 2018, this closure captures all of `t2`, but in Rust 2021, it will only capture `t2.0`
|
||||
...
|
||||
LL | }
|
||||
| -
|
||||
| |
|
||||
| in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
|
||||
| in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
|
||||
| in Rust 2018, `t2` is dropped here, but in Rust 2021, only `t2.0` will be dropped here as part of the closure
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/insignificant_drop.rs:3:9
|
||||
|
|
||||
LL | #![deny(rust_2021_incompatible_closure_captures)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
|
||||
help: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
|
||||
|
|
||||
LL ~ let c = || {
|
||||
LL + let _ = (&t, &t1, &t2);
|
||||
|
|
||||
|
||||
error: changes to closure capture in Rust 2021 will affect drop order
|
||||
--> $DIR/insignificant_drop.rs:41:13
|
||||
|
|
||||
LL | let c = || {
|
||||
| ^^
|
||||
...
|
||||
LL | let _t = t.0;
|
||||
| --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
|
||||
LL |
|
||||
LL | let _t1 = t1.0;
|
||||
| ---- in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0`
|
||||
...
|
||||
LL | }
|
||||
| -
|
||||
| |
|
||||
| in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
|
||||
| in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
|
||||
|
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
|
||||
help: add a dummy let to cause `t`, `t1` to be fully captured
|
||||
|
|
||||
LL ~ let c = || {
|
||||
LL + let _ = (&t, &t1);
|
||||
|
|
||||
|
||||
error: changes to closure capture in Rust 2021 will affect drop order
|
||||
--> $DIR/insignificant_drop.rs:62:13
|
||||
|
|
||||
LL | let c = || {
|
||||
| ^^
|
||||
...
|
||||
LL | let _t = t.0;
|
||||
| --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
|
||||
...
|
||||
LL | }
|
||||
| - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
|
||||
|
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
|
||||
help: add a dummy let to cause `t` to be fully captured
|
||||
|
|
||||
LL ~ let c = || {
|
||||
LL + let _ = &t;
|
||||
|
|
||||
|
||||
error: changes to closure capture in Rust 2021 will affect drop order
|
||||
--> $DIR/insignificant_drop.rs:83:13
|
||||
|
|
||||
LL | let c = || {
|
||||
| ^^
|
||||
...
|
||||
LL | let _t = t.0;
|
||||
| --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
|
||||
...
|
||||
LL | }
|
||||
| - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
|
||||
|
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
|
||||
help: add a dummy let to cause `t` to be fully captured
|
||||
|
|
||||
LL ~ let c = || {
|
||||
LL + let _ = &t;
|
||||
|
|
||||
|
||||
error: changes to closure capture in Rust 2021 will affect drop order
|
||||
--> $DIR/insignificant_drop.rs:104:13
|
||||
|
|
||||
LL | let c = || {
|
||||
| ^^
|
||||
...
|
||||
LL | let _t = t.0;
|
||||
| --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
|
||||
...
|
||||
LL | }
|
||||
| - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
|
||||
|
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
|
||||
help: add a dummy let to cause `t` to be fully captured
|
||||
|
|
||||
LL ~ let c = || {
|
||||
LL + let _ = &t;
|
||||
|
|
||||
|
||||
error: changes to closure capture in Rust 2021 will affect drop order
|
||||
--> $DIR/insignificant_drop.rs:122:13
|
||||
|
|
||||
LL | let c = move || {
|
||||
| ^^^^^^^
|
||||
...
|
||||
LL | println!("{} {}", t1.1, t.1);
|
||||
| ---- --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1`
|
||||
| |
|
||||
| in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.1`
|
||||
...
|
||||
LL | }
|
||||
| -
|
||||
| |
|
||||
| in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.1` will be dropped here as part of the closure
|
||||
| in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure
|
||||
|
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
|
||||
help: add a dummy let to cause `t1`, `t` to be fully captured
|
||||
|
|
||||
LL ~ let c = move || {
|
||||
LL + let _ = (&t1, &t);
|
||||
|
|
||||
|
||||
error: changes to closure capture in Rust 2021 will affect drop order
|
||||
--> $DIR/insignificant_drop.rs:142:13
|
||||
|
|
||||
LL | let c = || {
|
||||
| ^^
|
||||
...
|
||||
LL | let _t = t.0;
|
||||
| --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
|
||||
...
|
||||
LL | }
|
||||
| - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
|
||||
|
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
|
||||
help: add a dummy let to cause `t` to be fully captured
|
||||
|
|
||||
LL ~ let c = || {
|
||||
LL + let _ = &t;
|
||||
|
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
@ -5,13 +5,15 @@
|
||||
#![feature(rustc_attrs)]
|
||||
#![allow(unused)]
|
||||
|
||||
use std::sync::Mutex;
|
||||
|
||||
#[rustc_insignificant_dtor]
|
||||
struct InsignificantDropPoint {
|
||||
x: i32,
|
||||
y: i32,
|
||||
y: Mutex<i32>,
|
||||
}
|
||||
|
||||
impl Drop for InsignificantDropPoint {
|
||||
#[rustc_insignificant_dtor]
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
@ -21,15 +23,15 @@ impl Drop for SigDrop {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
#[rustc_insignificant_dtor]
|
||||
struct GenericStruct<T>(T, T);
|
||||
|
||||
struct Wrapper<T>(GenericStruct<T>, i32);
|
||||
|
||||
impl<T> Drop for GenericStruct<T> {
|
||||
#[rustc_insignificant_dtor]
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
struct Wrapper<T>(GenericStruct<T>, i32);
|
||||
|
||||
// `SigDrop` implements drop and therefore needs to be migrated.
|
||||
fn significant_drop_needs_migration() {
|
||||
let t = (SigDrop {}, SigDrop {});
|
||||
|
@ -5,13 +5,15 @@
|
||||
#![feature(rustc_attrs)]
|
||||
#![allow(unused)]
|
||||
|
||||
use std::sync::Mutex;
|
||||
|
||||
#[rustc_insignificant_dtor]
|
||||
struct InsignificantDropPoint {
|
||||
x: i32,
|
||||
y: i32,
|
||||
y: Mutex<i32>,
|
||||
}
|
||||
|
||||
impl Drop for InsignificantDropPoint {
|
||||
#[rustc_insignificant_dtor]
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
@ -21,15 +23,15 @@ impl Drop for SigDrop {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
#[rustc_insignificant_dtor]
|
||||
struct GenericStruct<T>(T, T);
|
||||
|
||||
struct Wrapper<T>(GenericStruct<T>, i32);
|
||||
|
||||
impl<T> Drop for GenericStruct<T> {
|
||||
#[rustc_insignificant_dtor]
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
struct Wrapper<T>(GenericStruct<T>, i32);
|
||||
|
||||
// `SigDrop` implements drop and therefore needs to be migrated.
|
||||
fn significant_drop_needs_migration() {
|
||||
let t = (SigDrop {}, SigDrop {});
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: changes to closure capture in Rust 2021 will affect drop order
|
||||
--> $DIR/insignificant_drop_attr_migrations.rs:37:13
|
||||
--> $DIR/insignificant_drop_attr_migrations.rs:39:13
|
||||
|
|
||||
LL | let c = || {
|
||||
| ^^
|
||||
@ -23,7 +23,7 @@ LL + let _ = &t;
|
||||
|
|
||||
|
||||
error: changes to closure capture in Rust 2021 will affect drop order
|
||||
--> $DIR/insignificant_drop_attr_migrations.rs:57:13
|
||||
--> $DIR/insignificant_drop_attr_migrations.rs:59:13
|
||||
|
|
||||
LL | let c = move || {
|
||||
| ^^^^^^^
|
||||
|
@ -3,6 +3,7 @@
|
||||
#![deny(rust_2021_incompatible_closure_captures)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![allow(unused)]
|
||||
#[rustc_insignificant_dtor]
|
||||
|
||||
struct InsignificantDropPoint {
|
||||
x: i32,
|
||||
@ -10,7 +11,6 @@ struct InsignificantDropPoint {
|
||||
}
|
||||
|
||||
impl Drop for InsignificantDropPoint {
|
||||
#[rustc_insignificant_dtor]
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
|
@ -5,8 +5,17 @@
|
||||
#![deny(rust_2021_incompatible_closure_captures)]
|
||||
//~^ NOTE: the lint level is defined here
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Foo(i32);
|
||||
impl Drop for Foo {
|
||||
fn drop(&mut self) {
|
||||
println!("{:?} dropped", self.0);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let a = ("hey".to_string(), "123".to_string());
|
||||
let a = (Foo(0), Foo(1));
|
||||
let _ = || { let _ = &a; dbg!(a.0) };
|
||||
//~^ ERROR: drop order
|
||||
//~| NOTE: will only capture `a.0`
|
||||
|
@ -5,8 +5,17 @@
|
||||
#![deny(rust_2021_incompatible_closure_captures)]
|
||||
//~^ NOTE: the lint level is defined here
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Foo(i32);
|
||||
impl Drop for Foo {
|
||||
fn drop(&mut self) {
|
||||
println!("{:?} dropped", self.0);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let a = ("hey".to_string(), "123".to_string());
|
||||
let a = (Foo(0), Foo(1));
|
||||
let _ = || dbg!(a.0);
|
||||
//~^ ERROR: drop order
|
||||
//~| NOTE: will only capture `a.0`
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: changes to closure capture in Rust 2021 will affect drop order
|
||||
--> $DIR/macro.rs:10:13
|
||||
--> $DIR/macro.rs:19:13
|
||||
|
|
||||
LL | let _ = || dbg!(a.0);
|
||||
| ^^^^^^^^---^
|
||||
|
@ -4,7 +4,22 @@
|
||||
|
||||
use std::thread;
|
||||
|
||||
struct S(String);
|
||||
#[derive(Debug)]
|
||||
struct Foo(String);
|
||||
impl Drop for Foo {
|
||||
fn drop(&mut self) {
|
||||
println!("{:?} dropped", self.0);
|
||||
}
|
||||
}
|
||||
|
||||
impl Foo {
|
||||
fn from(s: &str) -> Self {
|
||||
Self(String::from(s))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct S(Foo);
|
||||
|
||||
#[derive(Clone)]
|
||||
struct T(i32);
|
||||
@ -13,13 +28,13 @@ struct U(S, T);
|
||||
|
||||
impl Clone for U {
|
||||
fn clone(&self) -> Self {
|
||||
U(S(String::from("Hello World")), T(0))
|
||||
U(S(Foo::from("Hello World")), T(0))
|
||||
}
|
||||
}
|
||||
|
||||
fn test_multi_issues() {
|
||||
let f1 = U(S(String::from("foo")), T(0));
|
||||
let f2 = U(S(String::from("bar")), T(0));
|
||||
let f1 = U(S(Foo::from("foo")), T(0));
|
||||
let f2 = U(S(Foo::from("bar")), T(0));
|
||||
let c = || {
|
||||
let _ = (&f1, &f2);
|
||||
//~^ ERROR: `Clone` trait implementation for closure and drop order
|
||||
@ -39,7 +54,7 @@ fn test_multi_issues() {
|
||||
//~^ NOTE: in Rust 2018, `f2` is dropped here, but in Rust 2021, only `f2.1` will be dropped here as part of the closure
|
||||
|
||||
fn test_capturing_all_disjoint_fields_individually() {
|
||||
let f1 = U(S(String::from("foo")), T(0));
|
||||
let f1 = U(S(Foo::from("foo")), T(0));
|
||||
let c = || {
|
||||
let _ = &f1;
|
||||
//~^ ERROR: `Clone` trait implementation for closure
|
||||
@ -60,12 +75,12 @@ struct U1(S, T, S);
|
||||
|
||||
impl Clone for U1 {
|
||||
fn clone(&self) -> Self {
|
||||
U1(S(String::from("foo")), T(0), S(String::from("bar")))
|
||||
U1(S(Foo::from("foo")), T(0), S(Foo::from("bar")))
|
||||
}
|
||||
}
|
||||
|
||||
fn test_capturing_several_disjoint_fields_individually_1() {
|
||||
let f1 = U1(S(String::from("foo")), T(0), S(String::from("bar")));
|
||||
let f1 = U1(S(Foo::from("foo")), T(0), S(Foo::from("bar")));
|
||||
let c = || {
|
||||
let _ = &f1;
|
||||
//~^ ERROR: `Clone` trait implementation for closure
|
||||
@ -85,7 +100,7 @@ fn test_capturing_several_disjoint_fields_individually_1() {
|
||||
}
|
||||
|
||||
fn test_capturing_several_disjoint_fields_individually_2() {
|
||||
let f1 = U1(S(String::from("foo")), T(0), S(String::from("bar")));
|
||||
let f1 = U1(S(Foo::from("foo")), T(0), S(Foo::from("bar")));
|
||||
let c = || {
|
||||
let _ = &f1;
|
||||
//~^ ERROR: `Clone` trait implementation for closure and drop order
|
||||
|
@ -4,7 +4,22 @@
|
||||
|
||||
use std::thread;
|
||||
|
||||
struct S(String);
|
||||
#[derive(Debug)]
|
||||
struct Foo(String);
|
||||
impl Drop for Foo {
|
||||
fn drop(&mut self) {
|
||||
println!("{:?} dropped", self.0);
|
||||
}
|
||||
}
|
||||
|
||||
impl Foo {
|
||||
fn from(s: &str) -> Self {
|
||||
Self(String::from(s))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct S(Foo);
|
||||
|
||||
#[derive(Clone)]
|
||||
struct T(i32);
|
||||
@ -13,13 +28,13 @@ struct U(S, T);
|
||||
|
||||
impl Clone for U {
|
||||
fn clone(&self) -> Self {
|
||||
U(S(String::from("Hello World")), T(0))
|
||||
U(S(Foo::from("Hello World")), T(0))
|
||||
}
|
||||
}
|
||||
|
||||
fn test_multi_issues() {
|
||||
let f1 = U(S(String::from("foo")), T(0));
|
||||
let f2 = U(S(String::from("bar")), T(0));
|
||||
let f1 = U(S(Foo::from("foo")), T(0));
|
||||
let f2 = U(S(Foo::from("bar")), T(0));
|
||||
let c = || {
|
||||
//~^ ERROR: `Clone` trait implementation for closure and drop order
|
||||
//~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
|
||||
@ -38,7 +53,7 @@ fn test_multi_issues() {
|
||||
//~^ NOTE: in Rust 2018, `f2` is dropped here, but in Rust 2021, only `f2.1` will be dropped here as part of the closure
|
||||
|
||||
fn test_capturing_all_disjoint_fields_individually() {
|
||||
let f1 = U(S(String::from("foo")), T(0));
|
||||
let f1 = U(S(Foo::from("foo")), T(0));
|
||||
let c = || {
|
||||
//~^ ERROR: `Clone` trait implementation for closure
|
||||
//~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
|
||||
@ -58,12 +73,12 @@ struct U1(S, T, S);
|
||||
|
||||
impl Clone for U1 {
|
||||
fn clone(&self) -> Self {
|
||||
U1(S(String::from("foo")), T(0), S(String::from("bar")))
|
||||
U1(S(Foo::from("foo")), T(0), S(Foo::from("bar")))
|
||||
}
|
||||
}
|
||||
|
||||
fn test_capturing_several_disjoint_fields_individually_1() {
|
||||
let f1 = U1(S(String::from("foo")), T(0), S(String::from("bar")));
|
||||
let f1 = U1(S(Foo::from("foo")), T(0), S(Foo::from("bar")));
|
||||
let c = || {
|
||||
//~^ ERROR: `Clone` trait implementation for closure
|
||||
//~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
|
||||
@ -82,7 +97,7 @@ fn test_capturing_several_disjoint_fields_individually_1() {
|
||||
}
|
||||
|
||||
fn test_capturing_several_disjoint_fields_individually_2() {
|
||||
let f1 = U1(S(String::from("foo")), T(0), S(String::from("bar")));
|
||||
let f1 = U1(S(Foo::from("foo")), T(0), S(Foo::from("bar")));
|
||||
let c = || {
|
||||
//~^ ERROR: `Clone` trait implementation for closure and drop order
|
||||
//~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure and drop order
|
||||
--> $DIR/multi_diagnostics.rs:23:13
|
||||
--> $DIR/multi_diagnostics.rs:38:13
|
||||
|
|
||||
LL | let c = || {
|
||||
| ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
|
||||
@ -26,7 +26,7 @@ LL + let _ = (&f1, &f2);
|
||||
|
|
||||
|
||||
error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure
|
||||
--> $DIR/multi_diagnostics.rs:42:13
|
||||
--> $DIR/multi_diagnostics.rs:57:13
|
||||
|
|
||||
LL | let c = || {
|
||||
| ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
|
||||
@ -42,7 +42,7 @@ LL + let _ = &f1;
|
||||
|
|
||||
|
||||
error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure
|
||||
--> $DIR/multi_diagnostics.rs:67:13
|
||||
--> $DIR/multi_diagnostics.rs:82:13
|
||||
|
|
||||
LL | let c = || {
|
||||
| ^^
|
||||
@ -64,7 +64,7 @@ LL + let _ = &f1;
|
||||
|
|
||||
|
||||
error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure and drop order
|
||||
--> $DIR/multi_diagnostics.rs:86:13
|
||||
--> $DIR/multi_diagnostics.rs:101:13
|
||||
|
|
||||
LL | let c = || {
|
||||
| ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
|
||||
@ -89,7 +89,7 @@ LL + let _ = &f1;
|
||||
|
|
||||
|
||||
error: changes to closure capture in Rust 2021 will affect `Sync`, `Send` trait implementation for closure
|
||||
--> $DIR/multi_diagnostics.rs:119:19
|
||||
--> $DIR/multi_diagnostics.rs:134:19
|
||||
|
|
||||
LL | thread::spawn(move || unsafe {
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
@ -165,7 +165,7 @@ fn test7_move_closures_non_copy_types_might_need_migration() {
|
||||
fn test8_drop_order_and_blocks() {
|
||||
{
|
||||
let tuple =
|
||||
(String::from("foo"), String::from("bar"));
|
||||
(Foo(0), Foo(1));
|
||||
{
|
||||
let c = || {
|
||||
let _ = &tuple;
|
||||
@ -184,7 +184,7 @@ fn test8_drop_order_and_blocks() {
|
||||
|
||||
fn test9_drop_order_and_nested_closures() {
|
||||
let tuple =
|
||||
(String::from("foo"), String::from("bar"));
|
||||
(Foo(0), Foo(1));
|
||||
let b = || {
|
||||
let c = || {
|
||||
let _ = &tuple;
|
||||
@ -202,6 +202,19 @@ fn test9_drop_order_and_nested_closures() {
|
||||
b();
|
||||
}
|
||||
|
||||
// Test that we migrate if drop order of Vec<T> would be affected if T is a significant drop type
|
||||
fn test10_vec_of_significant_drop_type() {
|
||||
|
||||
let tup = (Foo(0), vec![Foo(3)]);
|
||||
|
||||
let _c = || { let _ = &tup; tup.0 };
|
||||
//~^ ERROR: drop order
|
||||
//~| NOTE: for more information, see
|
||||
//~| HELP: add a dummy let to cause `tup` to be fully captured
|
||||
//~| NOTE: in Rust 2018, this closure captures all of `tup`, but in Rust 2021, it will only capture `tup.0`
|
||||
}
|
||||
//~^ NOTE: in Rust 2018, `tup` is dropped here, but in Rust 2021, only `tup.0` will be dropped here as part of the closure
|
||||
|
||||
fn main() {
|
||||
test1_all_need_migration();
|
||||
test2_only_precise_paths_need_migration();
|
||||
@ -212,4 +225,5 @@ fn main() {
|
||||
test7_move_closures_non_copy_types_might_need_migration();
|
||||
test8_drop_order_and_blocks();
|
||||
test9_drop_order_and_nested_closures();
|
||||
test10_vec_of_significant_drop_type();
|
||||
}
|
||||
|
@ -158,7 +158,7 @@ fn test7_move_closures_non_copy_types_might_need_migration() {
|
||||
fn test8_drop_order_and_blocks() {
|
||||
{
|
||||
let tuple =
|
||||
(String::from("foo"), String::from("bar"));
|
||||
(Foo(0), Foo(1));
|
||||
{
|
||||
let c = || {
|
||||
//~^ ERROR: drop order
|
||||
@ -176,7 +176,7 @@ fn test8_drop_order_and_blocks() {
|
||||
|
||||
fn test9_drop_order_and_nested_closures() {
|
||||
let tuple =
|
||||
(String::from("foo"), String::from("bar"));
|
||||
(Foo(0), Foo(1));
|
||||
let b = || {
|
||||
let c = || {
|
||||
//~^ ERROR: drop order
|
||||
@ -193,6 +193,19 @@ fn test9_drop_order_and_nested_closures() {
|
||||
b();
|
||||
}
|
||||
|
||||
// Test that we migrate if drop order of Vec<T> would be affected if T is a significant drop type
|
||||
fn test10_vec_of_significant_drop_type() {
|
||||
|
||||
let tup = (Foo(0), vec![Foo(3)]);
|
||||
|
||||
let _c = || tup.0;
|
||||
//~^ ERROR: drop order
|
||||
//~| NOTE: for more information, see
|
||||
//~| HELP: add a dummy let to cause `tup` to be fully captured
|
||||
//~| NOTE: in Rust 2018, this closure captures all of `tup`, but in Rust 2021, it will only capture `tup.0`
|
||||
}
|
||||
//~^ NOTE: in Rust 2018, `tup` is dropped here, but in Rust 2021, only `tup.0` will be dropped here as part of the closure
|
||||
|
||||
fn main() {
|
||||
test1_all_need_migration();
|
||||
test2_only_precise_paths_need_migration();
|
||||
@ -203,4 +216,5 @@ fn main() {
|
||||
test7_move_closures_non_copy_types_might_need_migration();
|
||||
test8_drop_order_and_blocks();
|
||||
test9_drop_order_and_nested_closures();
|
||||
test10_vec_of_significant_drop_type();
|
||||
}
|
||||
|
@ -195,5 +195,22 @@ LL ~ let c = || {
|
||||
LL + let _ = &tuple;
|
||||
|
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
error: changes to closure capture in Rust 2021 will affect drop order
|
||||
--> $DIR/significant_drop.rs:201:18
|
||||
|
|
||||
LL | let _c = || tup.0;
|
||||
| ^^^-----
|
||||
| |
|
||||
| in Rust 2018, this closure captures all of `tup`, but in Rust 2021, it will only capture `tup.0`
|
||||
...
|
||||
LL | }
|
||||
| - in Rust 2018, `tup` is dropped here, but in Rust 2021, only `tup.0` will be dropped here as part of the closure
|
||||
|
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
|
||||
help: add a dummy let to cause `tup` to be fully captured
|
||||
|
|
||||
LL | let _c = || { let _ = &tup; tup.0 };
|
||||
| +++++++++++++++ +
|
||||
|
||||
error: aborting due to 10 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user