From c2695255a51f0f9507be7c531fdbeef237179b44 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sun, 2 Aug 2020 01:29:21 +0900 Subject: [PATCH 1/6] Avoid complex diagnostics in snippets which contain newlines --- .../async-await/issue-70935-complex-spans.rs | 25 +++++++++++++++ .../issue-70935-complex-spans.stderr | 31 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 src/test/ui/async-await/issue-70935-complex-spans.rs create mode 100644 src/test/ui/async-await/issue-70935-complex-spans.stderr diff --git a/src/test/ui/async-await/issue-70935-complex-spans.rs b/src/test/ui/async-await/issue-70935-complex-spans.rs new file mode 100644 index 0000000000000..2965a7e0654a4 --- /dev/null +++ b/src/test/ui/async-await/issue-70935-complex-spans.rs @@ -0,0 +1,25 @@ +// edition:2018 +// #70935: Check if we do not emit snippet +// with newlines which lead complex diagnostics. + +use std::future::Future; + +async fn baz(_c: impl FnMut() -> T) where T: Future { +} + +fn foo(tx: std::sync::mpsc::Sender) -> impl Future + Send { + //~^ ERROR: future cannot be sent between threads safely + async move { + baz(|| async{ + foo(tx.clone()); + }).await; + } +} + +fn bar(_s: impl Future + Send) { +} + +fn main() { + let (tx, _rx) = std::sync::mpsc::channel(); + bar(foo(tx)); +} diff --git a/src/test/ui/async-await/issue-70935-complex-spans.stderr b/src/test/ui/async-await/issue-70935-complex-spans.stderr new file mode 100644 index 0000000000000..d9ce038f72b1a --- /dev/null +++ b/src/test/ui/async-await/issue-70935-complex-spans.stderr @@ -0,0 +1,31 @@ +error: future cannot be sent between threads safely + --> $DIR/issue-70935-complex-spans.rs:10:45 + | +LL | fn foo(tx: std::sync::mpsc::Sender) -> impl Future + Send { + | ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` +LL | +LL | / async move { +LL | | baz(|| async{ +LL | | foo(tx.clone()); +LL | | }).await; +LL | | } + | |_____- this returned value is of type `impl std::future::Future` + | + = help: the trait `std::marker::Sync` is not implemented for `std::sync::mpsc::Sender` +note: future is not `Send` as this value is used across an await + --> $DIR/issue-70935-complex-spans.rs:13:9 + | +LL | baz(|| async{ + | __________^___- + | | _________| + | || +LL | || foo(tx.clone()); +LL | || }).await; + | || - ^- value is later dropped here + | ||_________|______| + | |__________| await occurs here, with value maybe used later + | has type `[closure@$DIR/issue-70935-complex-spans.rs:13:13: 15:10 tx:&std::sync::mpsc::Sender]` which is not `Send` + = note: the return type of a function must have a statically known size + +error: aborting due to previous error + From ad978e55722bdf35e5beb32fcaa52de39650f132 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sun, 11 Oct 2020 03:05:57 +0900 Subject: [PATCH 2/6] Separate complex multispan into some notes --- .../src/traits/error_reporting/suggestions.rs | 143 ++++++++++++++---- .../issue-70935-complex-spans.stderr | 40 +++-- .../issue-65436-raw-ptr-not-send.stderr | 15 +- 3 files changed, 144 insertions(+), 54 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index c0881befe2481..56eb5e3686a86 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1570,36 +1570,121 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { format!("does not implement `{}`", trait_ref.print_only_trait_path()) }; - let mut explain_yield = |interior_span: Span, - yield_span: Span, - scope_span: Option| { - let mut span = MultiSpan::from_span(yield_span); - if let Ok(snippet) = source_map.span_to_snippet(interior_span) { - span.push_span_label( - yield_span, - format!("{} occurs here, with `{}` maybe used later", await_or_yield, snippet), - ); - // If available, use the scope span to annotate the drop location. - if let Some(scope_span) = scope_span { - span.push_span_label( - source_map.end_point(scope_span), - format!("`{}` is later dropped here", snippet), - ); + let mut explain_yield = + |interior_span: Span, yield_span: Span, scope_span: Option| { + let mut span = MultiSpan::from_span(yield_span); + if let Ok(snippet) = source_map.span_to_snippet(interior_span) { + // #70935: If snippet contains newlines, display "the value" instead + // so that we do not emit complex diagnostics. + let snippet = &format!("`{}`", snippet); + let snippet = if snippet.contains('\n') { "the value" } else { snippet }; + // The multispan can be complex here, like: + // note: future is not `Send` as this value is used across an await + // --> $DIR/issue-70935-complex-spans.rs:13:9 + // | + // LL | baz(|| async{ + // | __________^___- + // | | _________| + // | || + // LL | || foo(tx.clone()); + // LL | || }).await; + // | || - ^- value is later dropped here + // | ||_________|______| + // | |__________| await occurs here, with value maybe used later + // | has type `closure` which is not `Send` + // = note: the return type of a function must have a statically known size + // So, detect it and separate into some notes, like: + // note: future is not `Send` as this value is used across an await + // --> $DIR/issue-70935-complex-spans.rs:13:9 + // | + // LL | / baz(|| async{ + // LL | | foo(tx.clone()); + // LL | | }).await; + // | |________________^ + // note: first, await occurs here, with the value maybe used later + // --> $DIR/issue-70935-complex-spans.rs:13:9 + // | + // LL | / baz(|| async{ + // LL | | foo(tx.clone()); + // LL | | }).await; + // | |________________^ + // note: ...but, the value is later dropped here + // --> $DIR/issue-70935-complex-spans.rs:15:17 + // | + // LL | }).await; + // | ^ + // = note: the return type of a function must have a statically known size + + // If available, use the scope span to annotate the drop location. + if let Some(scope_span) = scope_span { + let scope_span = source_map.end_point(scope_span); + let is_overlapped = + yield_span.overlaps(scope_span) || yield_span.overlaps(interior_span); + if is_overlapped { + err.span_note( + span, + &format!( + "{} {} as this value is used across {}", + future_or_generator, trait_explanation, an_await_or_yield + ), + ); + err.span_note( + yield_span, + &format!( + "first, {} occurs here, with {} maybe used later", + await_or_yield, snippet + ), + ); + err.span_note( + scope_span, + &format!("...but, {} is later dropped here", snippet), + ); + } else { + span.push_span_label( + yield_span, + format!( + "{} occurs here, with {} maybe used later", + await_or_yield, snippet + ), + ); + span.push_span_label( + scope_span, + format!("{} is later dropped here", snippet), + ); + span.push_span_label( + interior_span, + format!("has type `{}` which {}", target_ty, trait_explanation), + ); + err.span_note( + span, + &format!( + "{} {} as this value is used across {}", + future_or_generator, trait_explanation, an_await_or_yield + ), + ); + } + } else { + span.push_span_label( + yield_span, + format!( + "{} occurs here, with {} maybe used later", + await_or_yield, snippet + ), + ); + span.push_span_label( + interior_span, + format!("has type `{}` which {}", target_ty, trait_explanation), + ); + err.span_note( + span, + &format!( + "{} {} as this value is used across {}", + future_or_generator, trait_explanation, an_await_or_yield + ), + ); + } } - } - span.push_span_label( - interior_span, - format!("has type `{}` which {}", target_ty, trait_explanation), - ); - - err.span_note( - span, - &format!( - "{} {} as this value is used across {}", - future_or_generator, trait_explanation, an_await_or_yield - ), - ); - }; + }; match interior_or_upvar_span { GeneratorInteriorOrUpvar::Interior(interior_span) => { if let Some((scope_span, yield_span, expr, from_awaited_ty)) = interior_extra_info { diff --git a/src/test/ui/async-await/issue-70935-complex-spans.stderr b/src/test/ui/async-await/issue-70935-complex-spans.stderr index d9ce038f72b1a..c55f8abc42d9b 100644 --- a/src/test/ui/async-await/issue-70935-complex-spans.stderr +++ b/src/test/ui/async-await/issue-70935-complex-spans.stderr @@ -1,31 +1,29 @@ error: future cannot be sent between threads safely --> $DIR/issue-70935-complex-spans.rs:10:45 | -LL | fn foo(tx: std::sync::mpsc::Sender) -> impl Future + Send { - | ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` -LL | -LL | / async move { -LL | | baz(|| async{ -LL | | foo(tx.clone()); -LL | | }).await; -LL | | } - | |_____- this returned value is of type `impl std::future::Future` +LL | fn foo(tx: std::sync::mpsc::Sender) -> impl Future + Send { + | ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` | - = help: the trait `std::marker::Sync` is not implemented for `std::sync::mpsc::Sender` + = help: the trait `Sync` is not implemented for `Sender` note: future is not `Send` as this value is used across an await --> $DIR/issue-70935-complex-spans.rs:13:9 | -LL | baz(|| async{ - | __________^___- - | | _________| - | || -LL | || foo(tx.clone()); -LL | || }).await; - | || - ^- value is later dropped here - | ||_________|______| - | |__________| await occurs here, with value maybe used later - | has type `[closure@$DIR/issue-70935-complex-spans.rs:13:13: 15:10 tx:&std::sync::mpsc::Sender]` which is not `Send` - = note: the return type of a function must have a statically known size +LL | / baz(|| async{ +LL | | foo(tx.clone()); +LL | | }).await; + | |________________^ +note: first, await occurs here, with the value maybe used later + --> $DIR/issue-70935-complex-spans.rs:13:9 + | +LL | / baz(|| async{ +LL | | foo(tx.clone()); +LL | | }).await; + | |________________^ +note: ...but, the value is later dropped here + --> $DIR/issue-70935-complex-spans.rs:15:17 + | +LL | }).await; + | ^ error: aborting due to previous error diff --git a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr index e4b2725686a0f..6ffbcd7ea65f0 100644 --- a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr +++ b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr @@ -12,10 +12,17 @@ note: future is not `Send` as this value is used across an await --> $DIR/issue-65436-raw-ptr-not-send.rs:14:9 | LL | bar(Foo(std::ptr::null())).await; - | ^^^^^^^^----------------^^^^^^^^- `std::ptr::null()` is later dropped here - | | | - | | has type `*const u8` which is not `Send` - | await occurs here, with `std::ptr::null()` maybe used later + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: first, await occurs here, with `std::ptr::null()` maybe used later + --> $DIR/issue-65436-raw-ptr-not-send.rs:14:9 + | +LL | bar(Foo(std::ptr::null())).await; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...but, `std::ptr::null()` is later dropped here + --> $DIR/issue-65436-raw-ptr-not-send.rs:14:41 + | +LL | bar(Foo(std::ptr::null())).await; + | ^ help: consider moving this into a `let` binding to create a shorter lived borrow --> $DIR/issue-65436-raw-ptr-not-send.rs:14:13 | From 66226ca1574fb936743a32f8b584fcfd1712a385 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sun, 11 Oct 2020 04:48:17 +0900 Subject: [PATCH 3/6] Address some code reviews --- .../src/traits/error_reporting/suggestions.rs | 179 +++++++++--------- .../issue-70935-complex-spans.stderr | 11 +- .../issue-65436-raw-ptr-not-send.stderr | 9 +- 3 files changed, 89 insertions(+), 110 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 56eb5e3686a86..e0c46a65b56a0 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1570,99 +1570,66 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { format!("does not implement `{}`", trait_ref.print_only_trait_path()) }; - let mut explain_yield = - |interior_span: Span, yield_span: Span, scope_span: Option| { - let mut span = MultiSpan::from_span(yield_span); - if let Ok(snippet) = source_map.span_to_snippet(interior_span) { - // #70935: If snippet contains newlines, display "the value" instead - // so that we do not emit complex diagnostics. - let snippet = &format!("`{}`", snippet); - let snippet = if snippet.contains('\n') { "the value" } else { snippet }; - // The multispan can be complex here, like: - // note: future is not `Send` as this value is used across an await - // --> $DIR/issue-70935-complex-spans.rs:13:9 - // | - // LL | baz(|| async{ - // | __________^___- - // | | _________| - // | || - // LL | || foo(tx.clone()); - // LL | || }).await; - // | || - ^- value is later dropped here - // | ||_________|______| - // | |__________| await occurs here, with value maybe used later - // | has type `closure` which is not `Send` - // = note: the return type of a function must have a statically known size - // So, detect it and separate into some notes, like: - // note: future is not `Send` as this value is used across an await - // --> $DIR/issue-70935-complex-spans.rs:13:9 - // | - // LL | / baz(|| async{ - // LL | | foo(tx.clone()); - // LL | | }).await; - // | |________________^ - // note: first, await occurs here, with the value maybe used later - // --> $DIR/issue-70935-complex-spans.rs:13:9 - // | - // LL | / baz(|| async{ - // LL | | foo(tx.clone()); - // LL | | }).await; - // | |________________^ - // note: ...but, the value is later dropped here - // --> $DIR/issue-70935-complex-spans.rs:15:17 - // | - // LL | }).await; - // | ^ - // = note: the return type of a function must have a statically known size - - // If available, use the scope span to annotate the drop location. - if let Some(scope_span) = scope_span { - let scope_span = source_map.end_point(scope_span); - let is_overlapped = - yield_span.overlaps(scope_span) || yield_span.overlaps(interior_span); - if is_overlapped { - err.span_note( - span, - &format!( - "{} {} as this value is used across {}", - future_or_generator, trait_explanation, an_await_or_yield - ), - ); - err.span_note( - yield_span, - &format!( - "first, {} occurs here, with {} maybe used later", - await_or_yield, snippet - ), - ); - err.span_note( - scope_span, - &format!("...but, {} is later dropped here", snippet), - ); - } else { - span.push_span_label( - yield_span, - format!( - "{} occurs here, with {} maybe used later", - await_or_yield, snippet - ), - ); - span.push_span_label( - scope_span, - format!("{} is later dropped here", snippet), - ); - span.push_span_label( - interior_span, - format!("has type `{}` which {}", target_ty, trait_explanation), - ); - err.span_note( - span, - &format!( - "{} {} as this value is used across {}", - future_or_generator, trait_explanation, an_await_or_yield - ), - ); - } + let mut explain_yield = |interior_span: Span, + yield_span: Span, + scope_span: Option| { + let mut span = MultiSpan::from_span(yield_span); + if let Ok(snippet) = source_map.span_to_snippet(interior_span) { + // #70935: If snippet contains newlines, display "the value" instead + // so that we do not emit complex diagnostics. + let snippet = &format!("`{}`", snippet); + let snippet = if snippet.contains('\n') { "the value" } else { snippet }; + // The multispan can be complex here, like: + // note: future is not `Send` as this value is used across an await + // --> $DIR/issue-70935-complex-spans.rs:13:9 + // | + // LL | baz(|| async{ + // | __________^___- + // | | _________| + // | || + // LL | || foo(tx.clone()); + // LL | || }).await; + // | || - ^- value is later dropped here + // | ||_________|______| + // | |__________| await occurs here, with value maybe used later + // | has type `closure` which is not `Send` + // + // So, detect it and separate into some notes, like: + // + // note: future is not `Send` as this value is used across an await + // --> $DIR/issue-70935-complex-spans.rs:13:9 + // | + // LL | / baz(|| async{ + // LL | | foo(tx.clone()); + // LL | | }).await; + // | |________________^ first, await occurs here, with the value maybe used later... + // note: the value is later dropped here + // --> $DIR/issue-70935-complex-spans.rs:15:17 + // | + // LL | }).await; + // | ^ + // + // If available, use the scope span to annotate the drop location. + if let Some(scope_span) = scope_span { + let scope_span = source_map.end_point(scope_span); + let is_overlapped = + yield_span.overlaps(scope_span) || yield_span.overlaps(interior_span); + if is_overlapped { + span.push_span_label( + yield_span, + format!( + "first, {} occurs here, with {} maybe used later...", + await_or_yield, snippet + ), + ); + err.span_note( + span, + &format!( + "{} {} as this value is used across {}", + future_or_generator, trait_explanation, an_await_or_yield + ), + ); + err.span_note(scope_span, &format!("{} is later dropped here", snippet)); } else { span.push_span_label( yield_span, @@ -1671,6 +1638,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { await_or_yield, snippet ), ); + span.push_span_label( + scope_span, + format!("{} is later dropped here", snippet), + ); span.push_span_label( interior_span, format!("has type `{}` which {}", target_ty, trait_explanation), @@ -1683,8 +1654,28 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ), ); } + } else { + span.push_span_label( + yield_span, + format!( + "{} occurs here, with {} maybe used later", + await_or_yield, snippet + ), + ); + span.push_span_label( + interior_span, + format!("has type `{}` which {}", target_ty, trait_explanation), + ); + err.span_note( + span, + &format!( + "{} {} as this value is used across {}", + future_or_generator, trait_explanation, an_await_or_yield + ), + ); } - }; + } + }; match interior_or_upvar_span { GeneratorInteriorOrUpvar::Interior(interior_span) => { if let Some((scope_span, yield_span, expr, from_awaited_ty)) = interior_extra_info { diff --git a/src/test/ui/async-await/issue-70935-complex-spans.stderr b/src/test/ui/async-await/issue-70935-complex-spans.stderr index c55f8abc42d9b..6b599b5d603d9 100644 --- a/src/test/ui/async-await/issue-70935-complex-spans.stderr +++ b/src/test/ui/async-await/issue-70935-complex-spans.stderr @@ -11,15 +11,8 @@ note: future is not `Send` as this value is used across an await LL | / baz(|| async{ LL | | foo(tx.clone()); LL | | }).await; - | |________________^ -note: first, await occurs here, with the value maybe used later - --> $DIR/issue-70935-complex-spans.rs:13:9 - | -LL | / baz(|| async{ -LL | | foo(tx.clone()); -LL | | }).await; - | |________________^ -note: ...but, the value is later dropped here + | |________________^ first, await occurs here, with the value maybe used later... +note: the value is later dropped here --> $DIR/issue-70935-complex-spans.rs:15:17 | LL | }).await; diff --git a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr index 6ffbcd7ea65f0..9d3b10c866391 100644 --- a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr +++ b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr @@ -12,13 +12,8 @@ note: future is not `Send` as this value is used across an await --> $DIR/issue-65436-raw-ptr-not-send.rs:14:9 | LL | bar(Foo(std::ptr::null())).await; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: first, await occurs here, with `std::ptr::null()` maybe used later - --> $DIR/issue-65436-raw-ptr-not-send.rs:14:9 - | -LL | bar(Foo(std::ptr::null())).await; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...but, `std::ptr::null()` is later dropped here + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ first, await occurs here, with `std::ptr::null()` maybe used later... +note: `std::ptr::null()` is later dropped here --> $DIR/issue-65436-raw-ptr-not-send.rs:14:41 | LL | bar(Foo(std::ptr::null())).await; From 2da86a1bfd77f5fa99d94cf33c868a74172eeac2 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 22 Oct 2020 14:15:40 +0900 Subject: [PATCH 4/6] Add "this has type `{}` which {}" note --- .../src/traits/error_reporting/suggestions.rs | 4 ++++ src/test/ui/async-await/issue-70935-complex-spans.stderr | 8 ++++++++ .../issues/issue-65436-raw-ptr-not-send.stderr | 5 +++++ 3 files changed, 17 insertions(+) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index e0c46a65b56a0..83ce7f1f55e9a 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1630,6 +1630,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ), ); err.span_note(scope_span, &format!("{} is later dropped here", snippet)); + err.span_note( + interior_span, + &format!("this has type `{}` which {}", target_ty, trait_explanation), + ); } else { span.push_span_label( yield_span, diff --git a/src/test/ui/async-await/issue-70935-complex-spans.stderr b/src/test/ui/async-await/issue-70935-complex-spans.stderr index 6b599b5d603d9..8451fb840992c 100644 --- a/src/test/ui/async-await/issue-70935-complex-spans.stderr +++ b/src/test/ui/async-await/issue-70935-complex-spans.stderr @@ -17,6 +17,14 @@ note: the value is later dropped here | LL | }).await; | ^ +note: this has type `[closure@$DIR/issue-70935-complex-spans.rs:13:13: 15:10]` which is not `Send` + --> $DIR/issue-70935-complex-spans.rs:13:13 + | +LL | baz(|| async{ + | _____________^ +LL | | foo(tx.clone()); +LL | | }).await; + | |_________^ error: aborting due to previous error diff --git a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr index 9d3b10c866391..b733437a51da3 100644 --- a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr +++ b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr @@ -18,6 +18,11 @@ note: `std::ptr::null()` is later dropped here | LL | bar(Foo(std::ptr::null())).await; | ^ +note: this has type `*const u8` which is not `Send` + --> $DIR/issue-65436-raw-ptr-not-send.rs:14:17 + | +LL | bar(Foo(std::ptr::null())).await; + | ^^^^^^^^^^^^^^^^ help: consider moving this into a `let` binding to create a shorter lived borrow --> $DIR/issue-65436-raw-ptr-not-send.rs:14:13 | From 54d9ffc0b9c2e1057f63648d20f9f65e30e7d48f Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 2 Nov 2020 16:54:53 +0900 Subject: [PATCH 5/6] Only separate notes if span is multiline --- .../src/traits/error_reporting/suggestions.rs | 19 ++++++++++++++----- .../issue-65436-raw-ptr-not-send.stderr | 9 +++------ 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 83ce7f1f55e9a..1e826bac3aa08 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1629,11 +1629,20 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { future_or_generator, trait_explanation, an_await_or_yield ), ); - err.span_note(scope_span, &format!("{} is later dropped here", snippet)); - err.span_note( - interior_span, - &format!("this has type `{}` which {}", target_ty, trait_explanation), - ); + if source_map.is_multiline(interior_span) { + err.span_note(scope_span, &format!("{} is later dropped here", snippet)); + err.span_note( + interior_span, + &format!("this has type `{}` which {}", target_ty, trait_explanation), + ); + } else { + let mut span = MultiSpan::from_span(scope_span); + span.push_span_label( + interior_span, + format!("has type `{}` which {}", target_ty, trait_explanation), + ); + err.span_note(span, &format!("{} is later dropped here", snippet)); + } } else { span.push_span_label( yield_span, diff --git a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr index b733437a51da3..5568dab86556a 100644 --- a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr +++ b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr @@ -17,12 +17,9 @@ note: `std::ptr::null()` is later dropped here --> $DIR/issue-65436-raw-ptr-not-send.rs:14:41 | LL | bar(Foo(std::ptr::null())).await; - | ^ -note: this has type `*const u8` which is not `Send` - --> $DIR/issue-65436-raw-ptr-not-send.rs:14:17 - | -LL | bar(Foo(std::ptr::null())).await; - | ^^^^^^^^^^^^^^^^ + | ---------------- ^ + | | + | has type `*const u8` which is not `Send` help: consider moving this into a `let` binding to create a shorter lived borrow --> $DIR/issue-65436-raw-ptr-not-send.rs:14:13 | From 8d651013e43aee25edb9ea82977756d9238a6fee Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 2 Nov 2020 16:59:11 +0900 Subject: [PATCH 6/6] Fix format --- .../src/traits/error_reporting/suggestions.rs | 185 +++++++++--------- 1 file changed, 95 insertions(+), 90 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 1e826bac3aa08..1c6e661782f4b 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1570,78 +1570,107 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { format!("does not implement `{}`", trait_ref.print_only_trait_path()) }; - let mut explain_yield = |interior_span: Span, - yield_span: Span, - scope_span: Option| { - let mut span = MultiSpan::from_span(yield_span); - if let Ok(snippet) = source_map.span_to_snippet(interior_span) { - // #70935: If snippet contains newlines, display "the value" instead - // so that we do not emit complex diagnostics. - let snippet = &format!("`{}`", snippet); - let snippet = if snippet.contains('\n') { "the value" } else { snippet }; - // The multispan can be complex here, like: - // note: future is not `Send` as this value is used across an await - // --> $DIR/issue-70935-complex-spans.rs:13:9 - // | - // LL | baz(|| async{ - // | __________^___- - // | | _________| - // | || - // LL | || foo(tx.clone()); - // LL | || }).await; - // | || - ^- value is later dropped here - // | ||_________|______| - // | |__________| await occurs here, with value maybe used later - // | has type `closure` which is not `Send` - // - // So, detect it and separate into some notes, like: - // - // note: future is not `Send` as this value is used across an await - // --> $DIR/issue-70935-complex-spans.rs:13:9 - // | - // LL | / baz(|| async{ - // LL | | foo(tx.clone()); - // LL | | }).await; - // | |________________^ first, await occurs here, with the value maybe used later... - // note: the value is later dropped here - // --> $DIR/issue-70935-complex-spans.rs:15:17 - // | - // LL | }).await; - // | ^ - // - // If available, use the scope span to annotate the drop location. - if let Some(scope_span) = scope_span { - let scope_span = source_map.end_point(scope_span); - let is_overlapped = - yield_span.overlaps(scope_span) || yield_span.overlaps(interior_span); - if is_overlapped { - span.push_span_label( - yield_span, - format!( - "first, {} occurs here, with {} maybe used later...", - await_or_yield, snippet - ), - ); - err.span_note( - span, - &format!( - "{} {} as this value is used across {}", - future_or_generator, trait_explanation, an_await_or_yield - ), - ); - if source_map.is_multiline(interior_span) { - err.span_note(scope_span, &format!("{} is later dropped here", snippet)); + let mut explain_yield = + |interior_span: Span, yield_span: Span, scope_span: Option| { + let mut span = MultiSpan::from_span(yield_span); + if let Ok(snippet) = source_map.span_to_snippet(interior_span) { + // #70935: If snippet contains newlines, display "the value" instead + // so that we do not emit complex diagnostics. + let snippet = &format!("`{}`", snippet); + let snippet = if snippet.contains('\n') { "the value" } else { snippet }; + // The multispan can be complex here, like: + // note: future is not `Send` as this value is used across an await + // --> $DIR/issue-70935-complex-spans.rs:13:9 + // | + // LL | baz(|| async{ + // | __________^___- + // | | _________| + // | || + // LL | || foo(tx.clone()); + // LL | || }).await; + // | || - ^- value is later dropped here + // | ||_________|______| + // | |__________| await occurs here, with value maybe used later + // | has type `closure` which is not `Send` + // + // So, detect it and separate into some notes, like: + // + // note: future is not `Send` as this value is used across an await + // --> $DIR/issue-70935-complex-spans.rs:13:9 + // | + // LL | / baz(|| async{ + // LL | | foo(tx.clone()); + // LL | | }).await; + // | |________________^ first, await occurs here, with the value maybe used later... + // note: the value is later dropped here + // --> $DIR/issue-70935-complex-spans.rs:15:17 + // | + // LL | }).await; + // | ^ + // + // If available, use the scope span to annotate the drop location. + if let Some(scope_span) = scope_span { + let scope_span = source_map.end_point(scope_span); + let is_overlapped = + yield_span.overlaps(scope_span) || yield_span.overlaps(interior_span); + if is_overlapped { + span.push_span_label( + yield_span, + format!( + "first, {} occurs here, with {} maybe used later...", + await_or_yield, snippet + ), + ); err.span_note( - interior_span, - &format!("this has type `{}` which {}", target_ty, trait_explanation), + span, + &format!( + "{} {} as this value is used across {}", + future_or_generator, trait_explanation, an_await_or_yield + ), ); + if source_map.is_multiline(interior_span) { + err.span_note( + scope_span, + &format!("{} is later dropped here", snippet), + ); + err.span_note( + interior_span, + &format!( + "this has type `{}` which {}", + target_ty, trait_explanation + ), + ); + } else { + let mut span = MultiSpan::from_span(scope_span); + span.push_span_label( + interior_span, + format!("has type `{}` which {}", target_ty, trait_explanation), + ); + err.span_note(span, &format!("{} is later dropped here", snippet)); + } } else { - let mut span = MultiSpan::from_span(scope_span); + span.push_span_label( + yield_span, + format!( + "{} occurs here, with {} maybe used later", + await_or_yield, snippet + ), + ); + span.push_span_label( + scope_span, + format!("{} is later dropped here", snippet), + ); span.push_span_label( interior_span, format!("has type `{}` which {}", target_ty, trait_explanation), ); - err.span_note(span, &format!("{} is later dropped here", snippet)); + err.span_note( + span, + &format!( + "{} {} as this value is used across {}", + future_or_generator, trait_explanation, an_await_or_yield + ), + ); } } else { span.push_span_label( @@ -1651,10 +1680,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { await_or_yield, snippet ), ); - span.push_span_label( - scope_span, - format!("{} is later dropped here", snippet), - ); span.push_span_label( interior_span, format!("has type `{}` which {}", target_ty, trait_explanation), @@ -1667,28 +1692,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ), ); } - } else { - span.push_span_label( - yield_span, - format!( - "{} occurs here, with {} maybe used later", - await_or_yield, snippet - ), - ); - span.push_span_label( - interior_span, - format!("has type `{}` which {}", target_ty, trait_explanation), - ); - err.span_note( - span, - &format!( - "{} {} as this value is used across {}", - future_or_generator, trait_explanation, an_await_or_yield - ), - ); } - } - }; + }; match interior_or_upvar_span { GeneratorInteriorOrUpvar::Interior(interior_span) => { if let Some((scope_span, yield_span, expr, from_awaited_ty)) = interior_extra_info {