Skip to content

Commit ad978e5

Browse files
committed
Separate complex multispan into some notes
1 parent c269525 commit ad978e5

File tree

3 files changed

+144
-54
lines changed

3 files changed

+144
-54
lines changed

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

Lines changed: 114 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1570,36 +1570,121 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
15701570
format!("does not implement `{}`", trait_ref.print_only_trait_path())
15711571
};
15721572

1573-
let mut explain_yield = |interior_span: Span,
1574-
yield_span: Span,
1575-
scope_span: Option<Span>| {
1576-
let mut span = MultiSpan::from_span(yield_span);
1577-
if let Ok(snippet) = source_map.span_to_snippet(interior_span) {
1578-
span.push_span_label(
1579-
yield_span,
1580-
format!("{} occurs here, with `{}` maybe used later", await_or_yield, snippet),
1581-
);
1582-
// If available, use the scope span to annotate the drop location.
1583-
if let Some(scope_span) = scope_span {
1584-
span.push_span_label(
1585-
source_map.end_point(scope_span),
1586-
format!("`{}` is later dropped here", snippet),
1587-
);
1573+
let mut explain_yield =
1574+
|interior_span: Span, yield_span: Span, scope_span: Option<Span>| {
1575+
let mut span = MultiSpan::from_span(yield_span);
1576+
if let Ok(snippet) = source_map.span_to_snippet(interior_span) {
1577+
// #70935: If snippet contains newlines, display "the value" instead
1578+
// so that we do not emit complex diagnostics.
1579+
let snippet = &format!("`{}`", snippet);
1580+
let snippet = if snippet.contains('\n') { "the value" } else { snippet };
1581+
// The multispan can be complex here, like:
1582+
// note: future is not `Send` as this value is used across an await
1583+
// --> $DIR/issue-70935-complex-spans.rs:13:9
1584+
// |
1585+
// LL | baz(|| async{
1586+
// | __________^___-
1587+
// | | _________|
1588+
// | ||
1589+
// LL | || foo(tx.clone());
1590+
// LL | || }).await;
1591+
// | || - ^- value is later dropped here
1592+
// | ||_________|______|
1593+
// | |__________| await occurs here, with value maybe used later
1594+
// | has type `closure` which is not `Send`
1595+
// = note: the return type of a function must have a statically known size
1596+
// So, detect it and separate into some notes, like:
1597+
// note: future is not `Send` as this value is used across an await
1598+
// --> $DIR/issue-70935-complex-spans.rs:13:9
1599+
// |
1600+
// LL | / baz(|| async{
1601+
// LL | | foo(tx.clone());
1602+
// LL | | }).await;
1603+
// | |________________^
1604+
// note: first, await occurs here, with the value maybe used later
1605+
// --> $DIR/issue-70935-complex-spans.rs:13:9
1606+
// |
1607+
// LL | / baz(|| async{
1608+
// LL | | foo(tx.clone());
1609+
// LL | | }).await;
1610+
// | |________________^
1611+
// note: ...but, the value is later dropped here
1612+
// --> $DIR/issue-70935-complex-spans.rs:15:17
1613+
// |
1614+
// LL | }).await;
1615+
// | ^
1616+
// = note: the return type of a function must have a statically known size
1617+
1618+
// If available, use the scope span to annotate the drop location.
1619+
if let Some(scope_span) = scope_span {
1620+
let scope_span = source_map.end_point(scope_span);
1621+
let is_overlapped =
1622+
yield_span.overlaps(scope_span) || yield_span.overlaps(interior_span);
1623+
if is_overlapped {
1624+
err.span_note(
1625+
span,
1626+
&format!(
1627+
"{} {} as this value is used across {}",
1628+
future_or_generator, trait_explanation, an_await_or_yield
1629+
),
1630+
);
1631+
err.span_note(
1632+
yield_span,
1633+
&format!(
1634+
"first, {} occurs here, with {} maybe used later",
1635+
await_or_yield, snippet
1636+
),
1637+
);
1638+
err.span_note(
1639+
scope_span,
1640+
&format!("...but, {} is later dropped here", snippet),
1641+
);
1642+
} else {
1643+
span.push_span_label(
1644+
yield_span,
1645+
format!(
1646+
"{} occurs here, with {} maybe used later",
1647+
await_or_yield, snippet
1648+
),
1649+
);
1650+
span.push_span_label(
1651+
scope_span,
1652+
format!("{} is later dropped here", snippet),
1653+
);
1654+
span.push_span_label(
1655+
interior_span,
1656+
format!("has type `{}` which {}", target_ty, trait_explanation),
1657+
);
1658+
err.span_note(
1659+
span,
1660+
&format!(
1661+
"{} {} as this value is used across {}",
1662+
future_or_generator, trait_explanation, an_await_or_yield
1663+
),
1664+
);
1665+
}
1666+
} else {
1667+
span.push_span_label(
1668+
yield_span,
1669+
format!(
1670+
"{} occurs here, with {} maybe used later",
1671+
await_or_yield, snippet
1672+
),
1673+
);
1674+
span.push_span_label(
1675+
interior_span,
1676+
format!("has type `{}` which {}", target_ty, trait_explanation),
1677+
);
1678+
err.span_note(
1679+
span,
1680+
&format!(
1681+
"{} {} as this value is used across {}",
1682+
future_or_generator, trait_explanation, an_await_or_yield
1683+
),
1684+
);
1685+
}
15881686
}
1589-
}
1590-
span.push_span_label(
1591-
interior_span,
1592-
format!("has type `{}` which {}", target_ty, trait_explanation),
1593-
);
1594-
1595-
err.span_note(
1596-
span,
1597-
&format!(
1598-
"{} {} as this value is used across {}",
1599-
future_or_generator, trait_explanation, an_await_or_yield
1600-
),
1601-
);
1602-
};
1687+
};
16031688
match interior_or_upvar_span {
16041689
GeneratorInteriorOrUpvar::Interior(interior_span) => {
16051690
if let Some((scope_span, yield_span, expr, from_awaited_ty)) = interior_extra_info {
Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,29 @@
11
error: future cannot be sent between threads safely
22
--> $DIR/issue-70935-complex-spans.rs:10:45
33
|
4-
LL | fn foo(tx: std::sync::mpsc::Sender<i32>) -> impl Future + Send {
5-
| ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
6-
LL |
7-
LL | / async move {
8-
LL | | baz(|| async{
9-
LL | | foo(tx.clone());
10-
LL | | }).await;
11-
LL | | }
12-
| |_____- this returned value is of type `impl std::future::Future`
4+
LL | fn foo(tx: std::sync::mpsc::Sender<i32>) -> impl Future + Send {
5+
| ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
136
|
14-
= help: the trait `std::marker::Sync` is not implemented for `std::sync::mpsc::Sender<i32>`
7+
= help: the trait `Sync` is not implemented for `Sender<i32>`
158
note: future is not `Send` as this value is used across an await
169
--> $DIR/issue-70935-complex-spans.rs:13:9
1710
|
18-
LL | baz(|| async{
19-
| __________^___-
20-
| | _________|
21-
| ||
22-
LL | || foo(tx.clone());
23-
LL | || }).await;
24-
| || - ^- value is later dropped here
25-
| ||_________|______|
26-
| |__________| await occurs here, with value maybe used later
27-
| has type `[closure@$DIR/issue-70935-complex-spans.rs:13:13: 15:10 tx:&std::sync::mpsc::Sender<i32>]` which is not `Send`
28-
= note: the return type of a function must have a statically known size
11+
LL | / baz(|| async{
12+
LL | | foo(tx.clone());
13+
LL | | }).await;
14+
| |________________^
15+
note: first, await occurs here, with the value maybe used later
16+
--> $DIR/issue-70935-complex-spans.rs:13:9
17+
|
18+
LL | / baz(|| async{
19+
LL | | foo(tx.clone());
20+
LL | | }).await;
21+
| |________________^
22+
note: ...but, the value is later dropped here
23+
--> $DIR/issue-70935-complex-spans.rs:15:17
24+
|
25+
LL | }).await;
26+
| ^
2927

3028
error: aborting due to previous error
3129

src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,17 @@ note: future is not `Send` as this value is used across an await
1212
--> $DIR/issue-65436-raw-ptr-not-send.rs:14:9
1313
|
1414
LL | bar(Foo(std::ptr::null())).await;
15-
| ^^^^^^^^----------------^^^^^^^^- `std::ptr::null()` is later dropped here
16-
| | |
17-
| | has type `*const u8` which is not `Send`
18-
| await occurs here, with `std::ptr::null()` maybe used later
15+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
16+
note: first, await occurs here, with `std::ptr::null()` maybe used later
17+
--> $DIR/issue-65436-raw-ptr-not-send.rs:14:9
18+
|
19+
LL | bar(Foo(std::ptr::null())).await;
20+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
21+
note: ...but, `std::ptr::null()` is later dropped here
22+
--> $DIR/issue-65436-raw-ptr-not-send.rs:14:41
23+
|
24+
LL | bar(Foo(std::ptr::null())).await;
25+
| ^
1926
help: consider moving this into a `let` binding to create a shorter lived borrow
2027
--> $DIR/issue-65436-raw-ptr-not-send.rs:14:13
2128
|

0 commit comments

Comments
 (0)