mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
Auto merge of #87956 - m-ou-se:closure-migration-macro-body, r=Aaron1011
Fix closure migration suggestion when the body is a macro. Fixes https://github.com/rust-lang/rust/issues/87955 Before: ``` warning: changes to closure capture in Rust 2021 will affect drop order --> src/main.rs:5:13 | 5 | let _ = || panic!(a.0); | ^^^^^^^^^^---^ | | | in Rust 2018, closure captures all of `a`, but in Rust 2021, it only captures `a.0` 6 | } | - in Rust 2018, `a` would be dropped here, but in Rust 2021, only `a.0` would be dropped here alongside the closure | help: add a dummy let to cause `a` to be fully captured | 20~ ($msg:expr $(,)?) => ({ let _ = &a; 21+ $crate::rt::begin_panic($msg) 22~ }), | ``` After: ``` warning: changes to closure capture in Rust 2021 will affect drop order --> src/main.rs:5:13 | 5 | let _ = || panic!(a.0); | ^^^^^^^^^^---^ | | | in Rust 2018, closure captures all of `a`, but in Rust 2021, it only captures `a.0` 6 | } | - in Rust 2018, `a` would be dropped here, but in Rust 2021, only `a.0` would be dropped here alongside the closure | help: add a dummy let to cause `a` to be fully captured | 5 | let _ = || { let _ = &a; panic!(a.0) }; | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ```
This commit is contained in:
commit
2fc3c69e54
@ -47,7 +47,7 @@ use rustc_middle::ty::{
|
||||
};
|
||||
use rustc_session::lint;
|
||||
use rustc_span::sym;
|
||||
use rustc_span::{MultiSpan, Span, Symbol};
|
||||
use rustc_span::{MultiSpan, Span, Symbol, DUMMY_SP};
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
|
||||
use rustc_data_structures::stable_map::FxHashMap;
|
||||
@ -644,8 +644,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
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) =
|
||||
|
||||
let mut closure_body_span = self.tcx.hir().span(body_id.hir_id);
|
||||
|
||||
// If the body was entirely expanded from a macro
|
||||
// invocation, i.e. the body is not contained inside the
|
||||
// closure span, then we walk up the expansion until we
|
||||
// find the span before the expansion.
|
||||
while !closure_body_span.is_dummy() && !closure_span.contains(closure_body_span) {
|
||||
closure_body_span = closure_body_span.parent().unwrap_or(DUMMY_SP);
|
||||
}
|
||||
|
||||
let (span, sugg, app) =
|
||||
match self.tcx.sess.source_map().span_to_snippet(closure_body_span) {
|
||||
Ok(s) => {
|
||||
let trimmed = s.trim_start();
|
||||
@ -666,9 +676,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
} else {
|
||||
format!("{{ {}; {} }}", migration_string, s)
|
||||
};
|
||||
(sugg, Applicability::MachineApplicable)
|
||||
(closure_body_span, sugg, Applicability::MachineApplicable)
|
||||
}
|
||||
Err(_) => (migration_string.clone(), Applicability::HasPlaceholders),
|
||||
Err(_) => (closure_span, migration_string.clone(), Applicability::HasPlaceholders),
|
||||
};
|
||||
|
||||
let diagnostic_msg = format!(
|
||||
@ -677,7 +687,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
);
|
||||
|
||||
diagnostics_builder.span_suggestion(
|
||||
closure_body_span,
|
||||
span,
|
||||
&diagnostic_msg,
|
||||
sugg,
|
||||
app,
|
||||
|
@ -0,0 +1,16 @@
|
||||
// run-rustfix
|
||||
|
||||
// See https://github.com/rust-lang/rust/issues/87955
|
||||
|
||||
#![deny(rust_2021_incompatible_closure_captures)]
|
||||
//~^ NOTE: the lint level is defined here
|
||||
|
||||
fn main() {
|
||||
let a = ("hey".to_string(), "123".to_string());
|
||||
let _ = || { let _ = &a; dbg!(a.0) };
|
||||
//~^ ERROR: drop order
|
||||
//~| NOTE: only captures `a.0`
|
||||
//~| NOTE: for more information, see
|
||||
//~| HELP: add a dummy let to cause `a` to be fully captured
|
||||
}
|
||||
//~^ NOTE: dropped here
|
@ -0,0 +1,16 @@
|
||||
// run-rustfix
|
||||
|
||||
// See https://github.com/rust-lang/rust/issues/87955
|
||||
|
||||
#![deny(rust_2021_incompatible_closure_captures)]
|
||||
//~^ NOTE: the lint level is defined here
|
||||
|
||||
fn main() {
|
||||
let a = ("hey".to_string(), "123".to_string());
|
||||
let _ = || dbg!(a.0);
|
||||
//~^ ERROR: drop order
|
||||
//~| NOTE: only captures `a.0`
|
||||
//~| NOTE: for more information, see
|
||||
//~| HELP: add a dummy let to cause `a` to be fully captured
|
||||
}
|
||||
//~^ NOTE: dropped here
|
@ -0,0 +1,24 @@
|
||||
error: changes to closure capture in Rust 2021 will affect drop order
|
||||
--> $DIR/macro.rs:10:13
|
||||
|
|
||||
LL | let _ = || dbg!(a.0);
|
||||
| ^^^^^^^^---^
|
||||
| |
|
||||
| in Rust 2018, closure captures all of `a`, but in Rust 2021, it only captures `a.0`
|
||||
...
|
||||
LL | }
|
||||
| - in Rust 2018, `a` would be dropped here, but in Rust 2021, only `a.0` would be dropped here alongside the closure
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/macro.rs:5: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 `a` to be fully captured
|
||||
|
|
||||
LL | let _ = || { let _ = &a; dbg!(a.0) };
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: aborting due to previous error
|
||||
|
Loading…
Reference in New Issue
Block a user