Separate complex multispan into some notes
This commit is contained in:
parent
c2695255a5
commit
ad978e5572
3 changed files with 144 additions and 54 deletions
|
@ -1570,36 +1570,121 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
format!("does not implement `{}`", trait_ref.print_only_trait_path())
|
format!("does not implement `{}`", trait_ref.print_only_trait_path())
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut explain_yield = |interior_span: Span,
|
let mut explain_yield =
|
||||||
yield_span: Span,
|
|interior_span: Span, yield_span: Span, scope_span: Option<Span>| {
|
||||||
scope_span: Option<Span>| {
|
let mut span = MultiSpan::from_span(yield_span);
|
||||||
let mut span = MultiSpan::from_span(yield_span);
|
if let Ok(snippet) = source_map.span_to_snippet(interior_span) {
|
||||||
if let Ok(snippet) = source_map.span_to_snippet(interior_span) {
|
// #70935: If snippet contains newlines, display "the value" instead
|
||||||
span.push_span_label(
|
// so that we do not emit complex diagnostics.
|
||||||
yield_span,
|
let snippet = &format!("`{}`", snippet);
|
||||||
format!("{} occurs here, with `{}` maybe used later", await_or_yield, snippet),
|
let snippet = if snippet.contains('\n') { "the value" } else { snippet };
|
||||||
);
|
// The multispan can be complex here, like:
|
||||||
// If available, use the scope span to annotate the drop location.
|
// note: future is not `Send` as this value is used across an await
|
||||||
if let Some(scope_span) = scope_span {
|
// --> $DIR/issue-70935-complex-spans.rs:13:9
|
||||||
span.push_span_label(
|
// |
|
||||||
source_map.end_point(scope_span),
|
// LL | baz(|| async{
|
||||||
format!("`{}` is later dropped here", snippet),
|
// | __________^___-
|
||||||
);
|
// | | _________|
|
||||||
}
|
// | ||
|
||||||
}
|
// LL | || foo(tx.clone());
|
||||||
span.push_span_label(
|
// LL | || }).await;
|
||||||
interior_span,
|
// | || - ^- value is later dropped here
|
||||||
format!("has type `{}` which {}", target_ty, trait_explanation),
|
// | ||_________|______|
|
||||||
);
|
// | |__________| 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
|
||||||
|
|
||||||
err.span_note(
|
// If available, use the scope span to annotate the drop location.
|
||||||
span,
|
if let Some(scope_span) = scope_span {
|
||||||
&format!(
|
let scope_span = source_map.end_point(scope_span);
|
||||||
"{} {} as this value is used across {}",
|
let is_overlapped =
|
||||||
future_or_generator, trait_explanation, an_await_or_yield
|
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
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
match interior_or_upvar_span {
|
match interior_or_upvar_span {
|
||||||
GeneratorInteriorOrUpvar::Interior(interior_span) => {
|
GeneratorInteriorOrUpvar::Interior(interior_span) => {
|
||||||
if let Some((scope_span, yield_span, expr, from_awaited_ty)) = interior_extra_info {
|
if let Some((scope_span, yield_span, expr, from_awaited_ty)) = interior_extra_info {
|
||||||
|
|
|
@ -1,31 +1,29 @@
|
||||||
error: future cannot be sent between threads safely
|
error: future cannot be sent between threads safely
|
||||||
--> $DIR/issue-70935-complex-spans.rs:10:45
|
--> $DIR/issue-70935-complex-spans.rs:10:45
|
||||||
|
|
|
|
||||||
LL | fn foo(tx: std::sync::mpsc::Sender<i32>) -> impl Future + Send {
|
LL | fn foo(tx: std::sync::mpsc::Sender<i32>) -> impl Future + Send {
|
||||||
| ^^^^^^^^^^^^^^^^^^ future created by async block is not `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<i32>`
|
= help: the trait `Sync` is not implemented for `Sender<i32>`
|
||||||
note: future is not `Send` as this value is used across an await
|
note: future is not `Send` as this value is used across an await
|
||||||
--> $DIR/issue-70935-complex-spans.rs:13:9
|
--> $DIR/issue-70935-complex-spans.rs:13:9
|
||||||
|
|
|
|
||||||
LL | baz(|| async{
|
LL | / baz(|| async{
|
||||||
| __________^___-
|
LL | | foo(tx.clone());
|
||||||
| | _________|
|
LL | | }).await;
|
||||||
| ||
|
| |________________^
|
||||||
LL | || foo(tx.clone());
|
note: first, await occurs here, with the value maybe used later
|
||||||
LL | || }).await;
|
--> $DIR/issue-70935-complex-spans.rs:13:9
|
||||||
| || - ^- value is later dropped here
|
|
|
||||||
| ||_________|______|
|
LL | / baz(|| async{
|
||||||
| |__________| await occurs here, with value maybe used later
|
LL | | foo(tx.clone());
|
||||||
| has type `[closure@$DIR/issue-70935-complex-spans.rs:13:13: 15:10 tx:&std::sync::mpsc::Sender<i32>]` which is not `Send`
|
LL | | }).await;
|
||||||
= note: the return type of a function must have a statically known size
|
| |________________^
|
||||||
|
note: ...but, the value is later dropped here
|
||||||
|
--> $DIR/issue-70935-complex-spans.rs:15:17
|
||||||
|
|
|
||||||
|
LL | }).await;
|
||||||
|
| ^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -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
|
--> $DIR/issue-65436-raw-ptr-not-send.rs:14:9
|
||||||
|
|
|
|
||||||
LL | bar(Foo(std::ptr::null())).await;
|
LL | bar(Foo(std::ptr::null())).await;
|
||||||
| ^^^^^^^^----------------^^^^^^^^- `std::ptr::null()` is later dropped here
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
| | |
|
note: first, await occurs here, with `std::ptr::null()` maybe used later
|
||||||
| | has type `*const u8` which is not `Send`
|
--> $DIR/issue-65436-raw-ptr-not-send.rs:14:9
|
||||||
| await occurs here, with `std::ptr::null()` maybe used later
|
|
|
||||||
|
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
|
help: consider moving this into a `let` binding to create a shorter lived borrow
|
||||||
--> $DIR/issue-65436-raw-ptr-not-send.rs:14:13
|
--> $DIR/issue-65436-raw-ptr-not-send.rs:14:13
|
||||||
|
|
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue