Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make disjoint_capture_migration an edition lint. #86673

Merged
merged 2 commits into from
Jun 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions compiler/rustc_lint_defs/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3001,8 +3001,7 @@ declare_lint! {

declare_lint! {
/// The `disjoint_capture_migration` lint detects variables that aren't completely
/// captured when the feature `capture_disjoint_fields` is enabled and it affects the Drop
/// order of at least one path starting at this variable.
/// captured in Rust 2021 and affect the Drop order of at least one path starting at this variable.
/// It can also detect when a variable implements a trait, but one of its field does not and
/// the field is captured by a closure and used with the assumption that said field implements
/// the same trait as the root variable.
Expand Down Expand Up @@ -3039,16 +3038,16 @@ declare_lint! {
///
/// ### Explanation
///
/// In the above example `p.y` will be dropped at the end of `f` instead of with `c` if
/// the feature `capture_disjoint_fields` is enabled.
/// In the above example, `p.y` will be dropped at the end of `f` instead of
/// with `c` in Rust 2021.
///
/// ### Example of auto-trait
///
/// ```rust,compile_fail
/// #![deny(disjoint_capture_migration)]
/// use std::thread;
///
/// struct Pointer (*mut i32);
/// struct Pointer(*mut i32);
/// unsafe impl Send for Pointer {}
///
/// fn main() {
Expand All @@ -3064,12 +3063,16 @@ declare_lint! {
///
/// ### Explanation
///
/// In the above example `fptr.0` is captured when feature `capture_disjoint_fields` is enabled.
/// In the above example, only `fptr.0` is captured in Rust 2021.
/// The field is of type *mut i32 which doesn't implement Send, making the code invalid as the
/// field cannot be sent between thread safely.
pub DISJOINT_CAPTURE_MIGRATION,
Allow,
"Drop reorder and auto traits error because of `capture_disjoint_fields`"
"detects closures affected by Rust 2021 changes",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2021),
explain_reason: false,
};
}

declare_lint_pass!(UnusedDocComment => [UNUSED_DOC_COMMENTS]);
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_lint_defs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,11 @@ pub struct FutureIncompatibleInfo {
/// The reason for the lint used by diagnostics to provide
/// the right help message
pub reason: FutureIncompatibilityReason,
/// Whether to explain the reason to the user.
///
/// Set to false for lints that already include a more detailed
/// explanation.
pub explain_reason: bool,
/// Information about a future breakage, which will
/// be emitted in JSON messages to be displayed by Cargo
/// for upstream deps
Expand Down Expand Up @@ -185,6 +190,7 @@ impl FutureIncompatibleInfo {
FutureIncompatibleInfo {
reference: "",
reason: FutureIncompatibilityReason::FutureReleaseError,
explain_reason: true,
future_breakage: None,
}
}
Expand Down
11 changes: 8 additions & 3 deletions compiler/rustc_middle/src/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -398,9 +398,14 @@ pub fn struct_lint_level<'s, 'd>(
it will become a hard error in a future release!"
.to_owned()
};
let citation = format!("for more information, see {}", future_incompatible.reference);
err.warn(&explanation);
err.note(&citation);
if future_incompatible.explain_reason {
err.warn(&explanation);
}
if !future_incompatible.reference.is_empty() {
let citation =
format!("for more information, see {}", future_incompatible.reference);
err.note(&citation);
}
}

// Finally, run `decorate`. This function is also responsible for emitting the diagnostic.
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_typeck/src/check/upvar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -494,11 +494,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|lint| {
let mut diagnostics_builder = lint.build(
format!(
"{} affected for closure because of `capture_disjoint_fields`",
"{} will change in Rust 2021",
reasons
)
.as_str(),
);
diagnostics_builder.note("for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>");
let closure_body_span = self.tcx.hir().span(body_id.hir_id);
let (sugg, app) =
match self.tcx.sess.source_map().span_to_snippet(closure_body_span) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fn test_send_trait() {
let mut f = 10;
let fptr = SendPointer(&mut f as *mut i32);
thread::spawn(move || { let _ = &fptr; unsafe {
//~^ ERROR: `Send` trait implementation affected for closure because of `capture_disjoint_fields`
//~^ ERROR: `Send` trait implementation
//~| HELP: add a dummy let to cause `fptr` to be fully captured
*fptr.0 = 20;
} });
Expand All @@ -28,7 +28,7 @@ fn test_sync_trait() {
let f = CustomInt(&mut f as *mut i32);
let fptr = SyncPointer(f);
thread::spawn(move || { let _ = &fptr; unsafe {
//~^ ERROR: `Sync`, `Send` trait implementation affected for closure because of `capture_disjoint_fields`
//~^ ERROR: `Sync`, `Send` trait implementation
//~| HELP: add a dummy let to cause `fptr` to be fully captured
*fptr.0.0 = 20;
} });
Expand All @@ -49,7 +49,7 @@ impl Clone for U {
fn test_clone_trait() {
let f = U(S(String::from("Hello World")), T(0));
let c = || { let _ = &f;
//~^ ERROR: `Clone` trait implementation, and drop order affected for closure because of `capture_disjoint_fields`
//~^ ERROR: `Clone` trait implementation, and drop order
//~| HELP: add a dummy let to cause `f` to be fully captured
let f_1 = f.1;
println!("{:?}", f_1.0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fn test_send_trait() {
let mut f = 10;
let fptr = SendPointer(&mut f as *mut i32);
thread::spawn(move || unsafe {
//~^ ERROR: `Send` trait implementation affected for closure because of `capture_disjoint_fields`
//~^ ERROR: `Send` trait implementation
//~| HELP: add a dummy let to cause `fptr` to be fully captured
*fptr.0 = 20;
});
Expand All @@ -28,7 +28,7 @@ fn test_sync_trait() {
let f = CustomInt(&mut f as *mut i32);
let fptr = SyncPointer(f);
thread::spawn(move || unsafe {
//~^ ERROR: `Sync`, `Send` trait implementation affected for closure because of `capture_disjoint_fields`
//~^ ERROR: `Sync`, `Send` trait implementation
//~| HELP: add a dummy let to cause `fptr` to be fully captured
*fptr.0.0 = 20;
});
Expand All @@ -49,7 +49,7 @@ impl Clone for U {
fn test_clone_trait() {
let f = U(S(String::from("Hello World")), T(0));
let c = || {
//~^ ERROR: `Clone` trait implementation, and drop order affected for closure because of `capture_disjoint_fields`
//~^ ERROR: `Clone` trait implementation, and drop order
//~| HELP: add a dummy let to cause `f` to be fully captured
let f_1 = f.1;
println!("{:?}", f_1.0);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: `Send` trait implementation affected for closure because of `capture_disjoint_fields`
error: `Send` trait implementation will change in Rust 2021
--> $DIR/auto_traits.rs:13:19
|
LL | thread::spawn(move || unsafe {
Expand All @@ -14,6 +14,7 @@ note: the lint level is defined here
|
LL | #![deny(disjoint_capture_migration)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= 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 `fptr` to be fully captured
|
LL | thread::spawn(move || { let _ = &fptr; unsafe {
Expand All @@ -23,7 +24,7 @@ LL | *fptr.0 = 20;
LL | } });
|

error: `Sync`, `Send` trait implementation affected for closure because of `capture_disjoint_fields`
error: `Sync`, `Send` trait implementation will change in Rust 2021
--> $DIR/auto_traits.rs:30:19
|
LL | thread::spawn(move || unsafe {
Expand All @@ -34,6 +35,7 @@ LL | | *fptr.0.0 = 20;
LL | | });
| |_____^
|
= 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 `fptr` to be fully captured
|
LL | thread::spawn(move || { let _ = &fptr; unsafe {
Expand All @@ -43,7 +45,7 @@ LL | *fptr.0.0 = 20;
LL | } });
|

error: `Clone` trait implementation, and drop order affected for closure because of `capture_disjoint_fields`
error: `Clone` trait implementation, and drop order will change in Rust 2021
--> $DIR/auto_traits.rs:51:13
|
LL | let c = || {
Expand All @@ -55,6 +57,7 @@ LL | | println!("{:?}", f_1.0);
LL | | };
| |_____^
|
= 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 `f` to be fully captured
|
LL | let c = || { let _ = &f;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ fn test1_all_need_migration() {
let t2 = (String::new(), String::new());

let c = || { let _ = (&t, &t1, &t2);
//~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured

let _t = t.0;
Expand All @@ -32,7 +33,8 @@ fn test2_only_precise_paths_need_migration() {
let t2 = (String::new(), String::new());

let c = || { let _ = (&t, &t1);
//~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
//~^ 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;
let _t1 = t1.0;
Expand All @@ -48,7 +50,8 @@ 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 affected for closure because of `capture_disjoint_fields`
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
println!("{}", t1.1);
Expand All @@ -66,7 +69,8 @@ fn test4_only_non_copy_types_need_migration() {
let t1 = (0i32, 0i32);

let c = || { let _ = &t;
//~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
let _t1 = t1.0;
Expand All @@ -84,7 +88,8 @@ fn test5_only_drop_types_need_migration() {
let s = S(0i32, 0i32);

let c = || { let _ = &t;
//~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
let _s = s.0;
Expand All @@ -99,7 +104,8 @@ 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 affected for closure because of `capture_disjoint_fields`
//~^ 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);
};
Expand All @@ -114,7 +120,8 @@ fn test7_drop_non_drop_aggregate_need_migration() {
let t = (String::new(), String::new(), 0i32);

let c = || { let _ = &t;
//~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ fn test1_all_need_migration() {
let t2 = (String::new(), String::new());

let c = || {
//~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured

let _t = t.0;
Expand All @@ -32,7 +33,8 @@ fn test2_only_precise_paths_need_migration() {
let t2 = (String::new(), String::new());

let c = || {
//~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
//~^ 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;
let _t1 = t1.0;
Expand All @@ -48,7 +50,8 @@ fn test3_only_by_value_need_migration() {
let t = (String::new(), String::new());
let t1 = (String::new(), String::new());
let c = || {
//~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
println!("{}", t1.1);
Expand All @@ -66,7 +69,8 @@ fn test4_only_non_copy_types_need_migration() {
let t1 = (0i32, 0i32);

let c = || {
//~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
let _t1 = t1.0;
Expand All @@ -84,7 +88,8 @@ fn test5_only_drop_types_need_migration() {
let s = S(0i32, 0i32);

let c = || {
//~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
let _s = s.0;
Expand All @@ -99,7 +104,8 @@ 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 affected for closure because of `capture_disjoint_fields`
//~^ 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);
};
Expand All @@ -114,7 +120,8 @@ fn test7_drop_non_drop_aggregate_need_migration() {
let t = (String::new(), String::new(), 0i32);

let c = || {
//~^ ERROR: drop order affected for closure because of `capture_disjoint_fields`
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
};
Expand Down
Loading