diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index 99e91bbe089..77ecdd08f78 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -1318,7 +1318,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { _ => 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" }; // Special case the primary error message when send or sync is the trait that was @@ -1364,38 +1365,26 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { span.push_span_label(original_span, message); err.set_span(span); - format!("{} is not {}", future_or_generator, trait_name) + format!("is not {}", trait_name) } else { - format!( - "{} 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)); - } + format!("does not implement `{}`", trait_ref.print_only_trait_path()) }; if let Some(await_span) = from_awaited_ty { // The type causing this obligation is one being awaited at await_span. let mut span = MultiSpan::from_span(await_span); - if target_span == await_span { - push_target_span_with_fallback(&mut span, "await occurs here"); - } else { - span.push_span_label(await_span, "await occurs here".to_string()); - push_target_span_with_fallback(&mut span, "created here"); - } + span.push_span_label( + await_span, + format!("await occurs here on type `{}`, which {}", target_ty, trait_explanation), + ); err.span_note( 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 { // Look at the last interior type to get a span for the `.await`. @@ -1410,7 +1399,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { 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 let Some(scope_span) = scope_span { @@ -1423,8 +1415,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { err.span_note( span, &format!( - "{} as this value is used across an {}", - trait_explanation, await_or_yield + "{} {} as this value is used across {}", + future_or_generator, trait_explanation, an_await_or_yield ), ); } diff --git a/src/test/ui/async-await/async-fn-nonsend.stderr b/src/test/ui/async-await/async-fn-nonsend.stderr index 176c62fcd7d..d36d59f1f68 100644 --- a/src/test/ui/async-await/async-fn-nonsend.stderr +++ b/src/test/ui/async-await/async-fn-nonsend.stderr @@ -12,7 +12,7 @@ note: future is not `Send` as this value is used across an await --> $DIR/async-fn-nonsend.rs:24:5 | LL | let x = non_send(); - | - created here + | - has type `impl std::fmt::Debug` which is not `Send` LL | drop(x); LL | fut().await; | ^^^^^^^^^^^ 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 --> $DIR/async-fn-nonsend.rs:33:20 | LL | match Some(non_send()) { - | ---------- created here + | ---------- has type `impl std::fmt::Debug` which is not `Send` LL | Some(_) => fut().await, | ^^^^^^^^^^^ 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 --> $DIR/async-fn-nonsend.rs:42:9 | 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 | fut().await; | ^^^^^^^^^^^ await occurs here, with `f` maybe used later diff --git a/src/test/ui/async-await/issue-64130-1-sync.stderr b/src/test/ui/async-await/issue-64130-1-sync.stderr index b7a88c10e74..42e9e4642ce 100644 --- a/src/test/ui/async-await/issue-64130-1-sync.stderr +++ b/src/test/ui/async-await/issue-64130-1-sync.stderr @@ -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 | LL | let x = Foo; - | - has type `Foo` + | - has type `Foo` which is not `Sync` LL | baz().await; | ^^^^^^^^^^^ await occurs here, with `x` maybe used later LL | } diff --git a/src/test/ui/async-await/issue-64130-2-send.stderr b/src/test/ui/async-await/issue-64130-2-send.stderr index ec183088771..f6f834618d3 100644 --- a/src/test/ui/async-await/issue-64130-2-send.stderr +++ b/src/test/ui/async-await/issue-64130-2-send.stderr @@ -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 | LL | let x = Foo; - | - has type `Foo` + | - has type `Foo` which is not `Send` LL | baz().await; | ^^^^^^^^^^^ await occurs here, with `x` maybe used later LL | } diff --git a/src/test/ui/async-await/issue-64130-3-other.stderr b/src/test/ui/async-await/issue-64130-3-other.stderr index 6b40cc9184d..3475b66b375 100644 --- a/src/test/ui/async-await/issue-64130-3-other.stderr +++ b/src/test/ui/async-await/issue-64130-3-other.stderr @@ -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 | LL | let x = Foo; - | - has type `Foo` + | - has type `Foo` which does not implement `Qux` LL | baz().await; | ^^^^^^^^^^^ await occurs here, with `x` maybe used later LL | } diff --git a/src/test/ui/async-await/issue-64130-4-async-move.stderr b/src/test/ui/async-await/issue-64130-4-async-move.stderr index edde947764a..fc231d394c1 100644 --- a/src/test/ui/async-await/issue-64130-4-async-move.stderr +++ b/src/test/ui/async-await/issue-64130-4-async-move.stderr @@ -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 | LL | match client.status() { - | ------ has type `&Client` + | ------ has type `&Client` which is not `Send` LL | 200 => { LL | let _x = get().await; | ^^^^^^^^^^^ await occurs here, with `client` maybe used later diff --git a/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr b/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr index 0f4441edb13..f72757339cc 100644 --- a/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr +++ b/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr @@ -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 | 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; | ^^^^^^^^^^^ await occurs here, with `g` maybe used later LL | } diff --git a/src/test/ui/async-await/issue-67252-unnamed-future.stderr b/src/test/ui/async-await/issue-67252-unnamed-future.stderr index cec40b55101..b43478ee207 100644 --- a/src/test/ui/async-await/issue-67252-unnamed-future.stderr +++ b/src/test/ui/async-await/issue-67252-unnamed-future.stderr @@ -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 | LL | let _a = std::ptr::null_mut::<()>(); // `*mut ()` is not `Send` - | -- has type `*mut ()` + | -- has type `*mut ()` which is not `Send` LL | AFuture.await; | ^^^^^^^^^^^^^ await occurs here, with `_a` maybe used later LL | }); diff --git a/src/test/ui/async-await/issue-68112.rs b/src/test/ui/async-await/issue-68112.rs index 604cc51921e..11b17836808 100644 --- a/src/test/ui/async-await/issue-68112.rs +++ b/src/test/ui/async-await/issue-68112.rs @@ -49,6 +49,8 @@ fn make_non_send_future2() -> impl Future>> { 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() { let send_fut = async { let non_send_fut = make_non_send_future2(); diff --git a/src/test/ui/async-await/issue-68112.stderr b/src/test/ui/async-await/issue-68112.stderr index c0659bf944b..78462868ede 100644 --- a/src/test/ui/async-await/issue-68112.stderr +++ b/src/test/ui/async-await/issue-68112.stderr @@ -8,13 +8,11 @@ LL | require_send(send_fut); | ^^^^^^^^^^^^ future created by async block is not `Send` | = help: the trait `std::marker::Sync` is not implemented for `std::cell::RefCell` -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 | -LL | let non_send_fut = make_non_send_future1(); - | ------------ created here 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 --> $DIR/issue-68112.rs:43:5 @@ -26,14 +24,14 @@ LL | require_send(send_fut); | ^^^^^^^^^^^^ future created by async block is not `Send` | = help: the trait `std::marker::Sync` is not implemented for `std::cell::RefCell` -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 | 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` cannot be shared between threads safely - --> $DIR/issue-68112.rs:58:5 + --> $DIR/issue-68112.rs:60:5 | LL | fn require_send(_: impl Send) {} | ------------ ---- required by this bound in `require_send` @@ -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 `{std::future::ResumeTy, impl std::future::Future, (), i32, Ready}` - = 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}]` - = 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}]>` + = 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}]` + = 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}]>` = note: required because it appears within the type `impl std::future::Future` error: aborting due to 3 previous errors 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 a04ae7220ec..49cd30e11a0 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 @@ -14,7 +14,7 @@ note: future is not `Send` as this value is used across an await LL | bar(Foo(std::ptr::null())).await; | ^^^^^^^^----------------^^^^^^^^- `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 help: consider moving this into a `let` binding to create a shorter lived borrow --> $DIR/issue-65436-raw-ptr-not-send.rs:14:13 diff --git a/src/test/ui/generator/issue-68112.stderr b/src/test/ui/generator/issue-68112.stderr index f40771d2826..4148b503ba8 100644 --- a/src/test/ui/generator/issue-68112.stderr +++ b/src/test/ui/generator/issue-68112.stderr @@ -8,11 +8,11 @@ LL | require_send(send_gen); | ^^^^^^^^^^^^ generator is not `Send` | = help: the trait `std::marker::Sync` is not implemented for `std::cell::RefCell` -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 | LL | let _non_send_gen = make_non_send_generator(); - | ------------- created here + | ------------- has type `impl std::ops::Generator` which is not `Send` LL | yield; | ^^^^^ yield occurs here, with `_non_send_gen` maybe used later LL | }; diff --git a/src/test/ui/generator/not-send-sync.stderr b/src/test/ui/generator/not-send-sync.stderr index fb59ef5f433..5df2c1b52fb 100644 --- a/src/test/ui/generator/not-send-sync.stderr +++ b/src/test/ui/generator/not-send-sync.stderr @@ -21,11 +21,11 @@ LL | assert_sync(|| { | ^^^^^^^^^^^ generator is not `Sync` | = help: within `[generator@$DIR/not-send-sync.rs:9:17: 13:6 {std::cell::Cell, ()}]`, the trait `std::marker::Sync` is not implemented for `std::cell::Cell` -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 | LL | let a = Cell::new(2); - | - has type `std::cell::Cell` + | - has type `std::cell::Cell` which is not `Sync` LL | yield; | ^^^^^ yield occurs here, with `a` maybe used later LL | });