提交 df64c5d2 编写于 作者: T Tyler Mandry

Incorporate feedback into diagnostics

上级 00795a99
...@@ -1318,7 +1318,8 @@ fn note_obligation_cause_for_async_await( ...@@ -1318,7 +1318,8 @@ fn note_obligation_cause_for_async_await(
_ => false, _ => false,
}) })
.unwrap_or(false); .unwrap_or(false);
let await_or_yield = if is_async { "await" } else { "yield" }; let (await_or_yield, an_await_or_yield) =
if is_async { ("await", "an await") } else { ("yield", "a yield") };
let future_or_generator = if is_async { "future" } else { "generator" }; let future_or_generator = if is_async { "future" } else { "generator" };
// Special case the primary error message when send or sync is the trait that was // Special case the primary error message when send or sync is the trait that was
...@@ -1364,38 +1365,26 @@ fn note_obligation_cause_for_async_await( ...@@ -1364,38 +1365,26 @@ fn note_obligation_cause_for_async_await(
span.push_span_label(original_span, message); span.push_span_label(original_span, message);
err.set_span(span); err.set_span(span);
format!("{} is not {}", future_or_generator, trait_name) format!("is not {}", trait_name)
} else { } else {
format!( format!("does not implement `{}`", trait_ref.print_only_trait_path())
"{} does not implement `{}`",
future_or_generator,
trait_ref.print_only_trait_path()
)
};
let push_target_span_with_fallback = |span: &mut MultiSpan, fallback: &str| {
if target_ty.is_impl_trait() {
// It's not very useful to tell the user the type if it's opaque.
span.push_span_label(target_span, fallback.to_string());
} else {
span.push_span_label(target_span, format!("has type `{}`", target_ty));
}
}; };
if let Some(await_span) = from_awaited_ty { if let Some(await_span) = from_awaited_ty {
// The type causing this obligation is one being awaited at await_span. // The type causing this obligation is one being awaited at await_span.
let mut span = MultiSpan::from_span(await_span); let mut span = MultiSpan::from_span(await_span);
if target_span == await_span { span.push_span_label(
push_target_span_with_fallback(&mut span, "await occurs here"); await_span,
} else { format!("await occurs here on type `{}`, which {}", target_ty, trait_explanation),
span.push_span_label(await_span, "await occurs here".to_string()); );
push_target_span_with_fallback(&mut span, "created here");
}
err.span_note( err.span_note(
span, span,
&format!("{} as this value is used in an await", trait_explanation), &format!(
"future {not_trait} as it awaits another future which {not_trait}",
not_trait = trait_explanation
),
); );
} else { } else {
// Look at the last interior type to get a span for the `.await`. // Look at the last interior type to get a span for the `.await`.
...@@ -1410,7 +1399,10 @@ fn note_obligation_cause_for_async_await( ...@@ -1410,7 +1399,10 @@ fn note_obligation_cause_for_async_await(
format!("{} occurs here, with `{}` maybe used later", await_or_yield, snippet), format!("{} occurs here, with `{}` maybe used later", await_or_yield, snippet),
); );
push_target_span_with_fallback(&mut span, "created here"); span.push_span_label(
target_span,
format!("has type `{}` which {}", target_ty, trait_explanation),
);
// If available, use the scope span to annotate the drop location. // If available, use the scope span to annotate the drop location.
if let Some(scope_span) = scope_span { if let Some(scope_span) = scope_span {
...@@ -1423,8 +1415,8 @@ fn note_obligation_cause_for_async_await( ...@@ -1423,8 +1415,8 @@ fn note_obligation_cause_for_async_await(
err.span_note( err.span_note(
span, span,
&format!( &format!(
"{} as this value is used across an {}", "{} {} as this value is used across {}",
trait_explanation, await_or_yield future_or_generator, trait_explanation, an_await_or_yield
), ),
); );
} }
......
...@@ -12,7 +12,7 @@ note: future is not `Send` as this value is used across an await ...@@ -12,7 +12,7 @@ note: future is not `Send` as this value is used across an await
--> $DIR/async-fn-nonsend.rs:24:5 --> $DIR/async-fn-nonsend.rs:24:5
| |
LL | let x = non_send(); LL | let x = non_send();
| - created here | - has type `impl std::fmt::Debug` which is not `Send`
LL | drop(x); LL | drop(x);
LL | fut().await; LL | fut().await;
| ^^^^^^^^^^^ await occurs here, with `x` maybe used later | ^^^^^^^^^^^ await occurs here, with `x` maybe used later
...@@ -33,7 +33,7 @@ note: future is not `Send` as this value is used across an await ...@@ -33,7 +33,7 @@ note: future is not `Send` as this value is used across an await
--> $DIR/async-fn-nonsend.rs:33:20 --> $DIR/async-fn-nonsend.rs:33:20
| |
LL | match Some(non_send()) { LL | match Some(non_send()) {
| ---------- created here | ---------- has type `impl std::fmt::Debug` which is not `Send`
LL | Some(_) => fut().await, LL | Some(_) => fut().await,
| ^^^^^^^^^^^ await occurs here, with `non_send()` maybe used later | ^^^^^^^^^^^ await occurs here, with `non_send()` maybe used later
... ...
...@@ -54,7 +54,7 @@ note: future is not `Send` as this value is used across an await ...@@ -54,7 +54,7 @@ note: future is not `Send` as this value is used across an await
--> $DIR/async-fn-nonsend.rs:42:9 --> $DIR/async-fn-nonsend.rs:42:9
| |
LL | let f: &mut std::fmt::Formatter = panic!(); LL | let f: &mut std::fmt::Formatter = panic!();
| - has type `&mut std::fmt::Formatter<'_>` | - has type `&mut std::fmt::Formatter<'_>` which is not `Send`
LL | if non_sync().fmt(f).unwrap() == () { LL | if non_sync().fmt(f).unwrap() == () {
LL | fut().await; LL | fut().await;
| ^^^^^^^^^^^ await occurs here, with `f` maybe used later | ^^^^^^^^^^^ await occurs here, with `f` maybe used later
......
...@@ -12,7 +12,7 @@ note: future is not `Sync` as this value is used across an await ...@@ -12,7 +12,7 @@ note: future is not `Sync` as this value is used across an await
--> $DIR/issue-64130-1-sync.rs:15:5 --> $DIR/issue-64130-1-sync.rs:15:5
| |
LL | let x = Foo; LL | let x = Foo;
| - has type `Foo` | - has type `Foo` which is not `Sync`
LL | baz().await; LL | baz().await;
| ^^^^^^^^^^^ await occurs here, with `x` maybe used later | ^^^^^^^^^^^ await occurs here, with `x` maybe used later
LL | } LL | }
......
...@@ -12,7 +12,7 @@ note: future is not `Send` as this value is used across an await ...@@ -12,7 +12,7 @@ note: future is not `Send` as this value is used across an await
--> $DIR/issue-64130-2-send.rs:15:5 --> $DIR/issue-64130-2-send.rs:15:5
| |
LL | let x = Foo; LL | let x = Foo;
| - has type `Foo` | - has type `Foo` which is not `Send`
LL | baz().await; LL | baz().await;
| ^^^^^^^^^^^ await occurs here, with `x` maybe used later | ^^^^^^^^^^^ await occurs here, with `x` maybe used later
LL | } LL | }
......
...@@ -16,7 +16,7 @@ note: future does not implement `Qux` as this value is used across an await ...@@ -16,7 +16,7 @@ note: future does not implement `Qux` as this value is used across an await
--> $DIR/issue-64130-3-other.rs:18:5 --> $DIR/issue-64130-3-other.rs:18:5
| |
LL | let x = Foo; LL | let x = Foo;
| - has type `Foo` | - has type `Foo` which does not implement `Qux`
LL | baz().await; LL | baz().await;
| ^^^^^^^^^^^ await occurs here, with `x` maybe used later | ^^^^^^^^^^^ await occurs here, with `x` maybe used later
LL | } LL | }
......
...@@ -18,7 +18,7 @@ note: future is not `Send` as this value is used across an await ...@@ -18,7 +18,7 @@ note: future is not `Send` as this value is used across an await
--> $DIR/issue-64130-4-async-move.rs:21:26 --> $DIR/issue-64130-4-async-move.rs:21:26
| |
LL | match client.status() { LL | match client.status() {
| ------ has type `&Client` | ------ has type `&Client` which is not `Send`
LL | 200 => { LL | 200 => {
LL | let _x = get().await; LL | let _x = get().await;
| ^^^^^^^^^^^ await occurs here, with `client` maybe used later | ^^^^^^^^^^^ await occurs here, with `client` maybe used later
......
...@@ -12,7 +12,7 @@ note: future is not `Send` as this value is used across an await ...@@ -12,7 +12,7 @@ note: future is not `Send` as this value is used across an await
--> $DIR/issue-64130-non-send-future-diags.rs:15:5 --> $DIR/issue-64130-non-send-future-diags.rs:15:5
| |
LL | let g = x.lock().unwrap(); LL | let g = x.lock().unwrap();
| - has type `std::sync::MutexGuard<'_, u32>` | - has type `std::sync::MutexGuard<'_, u32>` which is not `Send`
LL | baz().await; LL | baz().await;
| ^^^^^^^^^^^ await occurs here, with `g` maybe used later | ^^^^^^^^^^^ await occurs here, with `g` maybe used later
LL | } LL | }
......
...@@ -12,7 +12,7 @@ note: future is not `Send` as this value is used across an await ...@@ -12,7 +12,7 @@ note: future is not `Send` as this value is used across an await
--> $DIR/issue-67252-unnamed-future.rs:20:9 --> $DIR/issue-67252-unnamed-future.rs:20:9
| |
LL | let _a = std::ptr::null_mut::<()>(); // `*mut ()` is not `Send` LL | let _a = std::ptr::null_mut::<()>(); // `*mut ()` is not `Send`
| -- has type `*mut ()` | -- has type `*mut ()` which is not `Send`
LL | AFuture.await; LL | AFuture.await;
| ^^^^^^^^^^^^^ await occurs here, with `_a` maybe used later | ^^^^^^^^^^^^^ await occurs here, with `_a` maybe used later
LL | }); LL | });
......
...@@ -49,6 +49,8 @@ fn make_non_send_future2() -> impl Future<Output = Arc<RefCell<i32>>> { ...@@ -49,6 +49,8 @@ fn make_non_send_future2() -> impl Future<Output = Arc<RefCell<i32>>> {
ready2(Arc::new(RefCell::new(0))) ready2(Arc::new(RefCell::new(0)))
} }
// Ideally this test would have diagnostics similar to the test above, but right
// now it doesn't.
fn test2() { fn test2() {
let send_fut = async { let send_fut = async {
let non_send_fut = make_non_send_future2(); let non_send_fut = make_non_send_future2();
......
...@@ -8,13 +8,11 @@ LL | require_send(send_fut); ...@@ -8,13 +8,11 @@ LL | require_send(send_fut);
| ^^^^^^^^^^^^ future created by async block is not `Send` | ^^^^^^^^^^^^ future created by async block is not `Send`
| |
= help: the trait `std::marker::Sync` is not implemented for `std::cell::RefCell<i32>` = help: the trait `std::marker::Sync` is not implemented for `std::cell::RefCell<i32>`
note: future is not `Send` as this value is used in an await note: future is not `Send` as it awaits another future which is not `Send`
--> $DIR/issue-68112.rs:31:17 --> $DIR/issue-68112.rs:31:17
| |
LL | let non_send_fut = make_non_send_future1();
| ------------ created here
LL | let _ = non_send_fut.await; LL | let _ = non_send_fut.await;
| ^^^^^^^^^^^^ await occurs here | ^^^^^^^^^^^^ await occurs here on type `impl std::future::Future`, which is not `Send`
error: future cannot be sent between threads safely error: future cannot be sent between threads safely
--> $DIR/issue-68112.rs:43:5 --> $DIR/issue-68112.rs:43:5
...@@ -26,14 +24,14 @@ LL | require_send(send_fut); ...@@ -26,14 +24,14 @@ LL | require_send(send_fut);
| ^^^^^^^^^^^^ future created by async block is not `Send` | ^^^^^^^^^^^^ future created by async block is not `Send`
| |
= help: the trait `std::marker::Sync` is not implemented for `std::cell::RefCell<i32>` = help: the trait `std::marker::Sync` is not implemented for `std::cell::RefCell<i32>`
note: future is not `Send` as this value is used in an await note: future is not `Send` as it awaits another future which is not `Send`
--> $DIR/issue-68112.rs:40:17 --> $DIR/issue-68112.rs:40:17
| |
LL | let _ = make_non_send_future1().await; LL | let _ = make_non_send_future1().await;
| ^^^^^^^^^^^^^^^^^^^^^^^ await occurs here | ^^^^^^^^^^^^^^^^^^^^^^^ await occurs here on type `impl std::future::Future`, which is not `Send`
error[E0277]: `std::cell::RefCell<i32>` cannot be shared between threads safely error[E0277]: `std::cell::RefCell<i32>` cannot be shared between threads safely
--> $DIR/issue-68112.rs:58:5 --> $DIR/issue-68112.rs:60:5
| |
LL | fn require_send(_: impl Send) {} LL | fn require_send(_: impl Send) {}
| ------------ ---- required by this bound in `require_send` | ------------ ---- required by this bound in `require_send`
...@@ -49,8 +47,8 @@ LL | require_send(send_fut); ...@@ -49,8 +47,8 @@ LL | require_send(send_fut);
= note: required because it appears within the type `impl std::future::Future` = note: required because it appears within the type `impl std::future::Future`
= note: required because it appears within the type `impl std::future::Future` = note: required because it appears within the type `impl std::future::Future`
= note: required because it appears within the type `{std::future::ResumeTy, impl std::future::Future, (), i32, Ready<i32>}` = note: required because it appears within the type `{std::future::ResumeTy, impl std::future::Future, (), i32, Ready<i32>}`
= note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:53:26: 57:6 {std::future::ResumeTy, impl std::future::Future, (), i32, Ready<i32>}]` = note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:55:26: 59:6 {std::future::ResumeTy, impl std::future::Future, (), i32, Ready<i32>}]`
= note: required because it appears within the type `std::future::from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:53:26: 57:6 {std::future::ResumeTy, impl std::future::Future, (), i32, Ready<i32>}]>` = note: required because it appears within the type `std::future::from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:55:26: 59:6 {std::future::ResumeTy, impl std::future::Future, (), i32, Ready<i32>}]>`
= note: required because it appears within the type `impl std::future::Future` = note: required because it appears within the type `impl std::future::Future`
error: aborting due to 3 previous errors error: aborting due to 3 previous errors
......
...@@ -14,7 +14,7 @@ note: future is not `Send` as this value is used across an await ...@@ -14,7 +14,7 @@ note: future is not `Send` as this value is used across an await
LL | bar(Foo(std::ptr::null())).await; LL | bar(Foo(std::ptr::null())).await;
| ^^^^^^^^----------------^^^^^^^^- `std::ptr::null()` is later dropped here | ^^^^^^^^----------------^^^^^^^^- `std::ptr::null()` is later dropped here
| | | | | |
| | has type `*const u8` | | has type `*const u8` which is not `Send`
| await occurs here, with `std::ptr::null()` maybe used later | await occurs here, with `std::ptr::null()` maybe used later
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
......
...@@ -8,11 +8,11 @@ LL | require_send(send_gen); ...@@ -8,11 +8,11 @@ LL | require_send(send_gen);
| ^^^^^^^^^^^^ generator is not `Send` | ^^^^^^^^^^^^ generator is not `Send`
| |
= help: the trait `std::marker::Sync` is not implemented for `std::cell::RefCell<i32>` = help: the trait `std::marker::Sync` is not implemented for `std::cell::RefCell<i32>`
note: generator is not `Send` as this value is used across an yield note: generator is not `Send` as this value is used across a yield
--> $DIR/issue-68112.rs:31:9 --> $DIR/issue-68112.rs:31:9
| |
LL | let _non_send_gen = make_non_send_generator(); LL | let _non_send_gen = make_non_send_generator();
| ------------- created here | ------------- has type `impl std::ops::Generator` which is not `Send`
LL | yield; LL | yield;
| ^^^^^ yield occurs here, with `_non_send_gen` maybe used later | ^^^^^ yield occurs here, with `_non_send_gen` maybe used later
LL | }; LL | };
......
...@@ -21,11 +21,11 @@ LL | assert_sync(|| { ...@@ -21,11 +21,11 @@ LL | assert_sync(|| {
| ^^^^^^^^^^^ generator is not `Sync` | ^^^^^^^^^^^ generator is not `Sync`
| |
= help: within `[generator@$DIR/not-send-sync.rs:9:17: 13:6 {std::cell::Cell<i32>, ()}]`, the trait `std::marker::Sync` is not implemented for `std::cell::Cell<i32>` = help: within `[generator@$DIR/not-send-sync.rs:9:17: 13:6 {std::cell::Cell<i32>, ()}]`, the trait `std::marker::Sync` is not implemented for `std::cell::Cell<i32>`
note: generator is not `Sync` as this value is used across an yield note: generator is not `Sync` as this value is used across a yield
--> $DIR/not-send-sync.rs:12:9 --> $DIR/not-send-sync.rs:12:9
| |
LL | let a = Cell::new(2); LL | let a = Cell::new(2);
| - has type `std::cell::Cell<i32>` | - has type `std::cell::Cell<i32>` which is not `Sync`
LL | yield; LL | yield;
| ^^^^^ yield occurs here, with `a` maybe used later | ^^^^^ yield occurs here, with `a` maybe used later
LL | }); LL | });
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册