Greatly improve error reporting for futures and generators in note_obligation_cause_code

Most futures don't go through this code path, because they're caught by
`maybe_note_obligation_cause_for_async_await`. But all generators do,
and `maybe_note` is imperfect and doesn't catch all futures. Improve the error message for those it misses.

At some point, we may want to consider unifying this with the code for `maybe_note_async_await`,
so that `async_await` notes all parent constraints, and `note_obligation` can point to yield points.
But both functions are quite complicated, and it's not clear to me how to combine them;
this seems like a good incremental improvement.
This commit is contained in:
Joshua Nelson 2022-06-19 13:59:36 -05:00
parent cdcc53b7dc
commit 1deca0425d
21 changed files with 389 additions and 72 deletions

View file

@ -8,6 +8,7 @@
use crate::traits::normalize_to;
use hir::HirId;
use rustc_ast::Movability;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::{
@ -2397,24 +2398,104 @@ fn note_obligation_cause_code<T>(
{
let parent_trait_ref =
self.resolve_vars_if_possible(data.parent_trait_pred);
let ty = parent_trait_ref.skip_binder().self_ty();
matches!(ty.kind(), ty::Generator(..))
|| matches!(ty.kind(), ty::Closure(..))
let nested_ty = parent_trait_ref.skip_binder().self_ty();
matches!(nested_ty.kind(), ty::Generator(..))
|| matches!(nested_ty.kind(), ty::Closure(..))
} else {
false
}
};
let future_trait = self.tcx.lang_items().future_trait().unwrap();
let opaque_ty_is_future = |def_id| {
self.tcx.explicit_item_bounds(def_id).iter().any(|(predicate, _)| {
if let ty::PredicateKind::Trait(trait_predicate) =
predicate.kind().skip_binder()
{
trait_predicate.trait_ref.def_id == future_trait
} else {
false
}
})
};
let from_generator = tcx.lang_items().from_generator_fn().unwrap();
// Don't print the tuple of capture types
if !is_upvar_tys_infer_tuple {
let msg = format!("required because it appears within the type `{}`", ty);
match ty.kind() {
ty::Adt(def, _) => match self.tcx.opt_item_ident(def.did()) {
Some(ident) => err.span_note(ident.span, &msg),
None => err.note(&msg),
},
_ => err.note(&msg),
};
'print: {
if !is_upvar_tys_infer_tuple {
let msg = format!("required because it appears within the type `{}`", ty);
match ty.kind() {
ty::Adt(def, _) => {
// `gen_future` is used in all async functions; it doesn't add any additional info.
if self.tcx.is_diagnostic_item(sym::gen_future, def.did()) {
break 'print;
}
match self.tcx.opt_item_ident(def.did()) {
Some(ident) => err.span_note(ident.span, &msg),
None => err.note(&msg),
}
}
ty::Opaque(def_id, _) => {
// Avoid printing the future from `core::future::from_generator`, it's not helpful
if tcx.parent(*def_id) == from_generator {
break 'print;
}
// If the previous type is `from_generator`, this is the future generated by the body of an async function.
// Avoid printing it twice (it was already printed in the `ty::Generator` arm below).
let is_future = opaque_ty_is_future(def_id);
debug!(
?obligated_types,
?is_future,
"note_obligation_cause_code: check for async fn"
);
if opaque_ty_is_future(def_id)
&& obligated_types.last().map_or(false, |ty| match ty.kind() {
ty::Opaque(last_def_id, _) => {
tcx.parent(*last_def_id) == from_generator
}
_ => false,
})
{
break 'print;
}
err.span_note(self.tcx.def_span(def_id), &msg)
}
ty::GeneratorWitness(bound_tys) => {
use std::fmt::Write;
// FIXME: this is kind of an unusual format for rustc, can we make it more clear?
// Maybe we should just remove this note altogether?
// FIXME: only print types which don't meet the trait requirement
let mut msg =
"required because it captures the following types: ".to_owned();
for ty in bound_tys.skip_binder() {
write!(msg, "`{}`, ", ty).unwrap();
}
err.note(msg.trim_end_matches(", "))
}
ty::Generator(def_id, _, movability) => {
let sp = self.tcx.def_span(def_id);
// Special-case this to say "async block" instead of `[static generator]`.
let kind = if *movability == Movability::Static {
"async block"
} else {
"generator"
};
err.span_note(
sp,
&format!("required because it's used within this {}", kind),
)
}
ty::Closure(def_id, _) => err.span_note(
self.tcx.def_span(def_id),
&format!("required because it's used within this closure"),
),
_ => err.note(&msg),
};
}
}
obligated_types.push(ty);

View file

@ -42,15 +42,27 @@ LL | require_send(send_fut);
|
= help: the trait `Sync` is not implemented for `RefCell<i32>`
= note: required because of the requirements on the impl of `Send` for `Arc<RefCell<i32>>`
= note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:47:31: 47:36]`
= note: required because it appears within the type `std::future::from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:47:31: 47:36]>`
= note: required because it appears within the type `impl Future<Output = Arc<RefCell<i32>>>`
= note: required because it appears within the type `impl Future<Output = Arc<RefCell<i32>>>`
= note: required because it appears within the type `impl Future<Output = Arc<RefCell<i32>>>`
= note: required because it appears within the type `{ResumeTy, impl Future<Output = Arc<RefCell<i32>>>, (), i32, Ready<i32>}`
= note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:55:26: 59:6]`
= note: required because it appears within the type `std::future::from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:55:26: 59:6]>`
= note: required because it appears within the type `impl Future<Output = ()>`
note: required because it's used within this async block
--> $DIR/issue-68112.rs:47:31
|
LL | async fn ready2<T>(t: T) -> T { t }
| ^^^^^
note: required because it appears within the type `impl Future<Output = Arc<RefCell<i32>>>`
--> $DIR/issue-68112.rs:48:31
|
LL | fn make_non_send_future2() -> impl Future<Output = Arc<RefCell<i32>>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: required because it captures the following types: `ResumeTy`, `impl Future<Output = Arc<RefCell<i32>>>`, `()`, `i32`, `Ready<i32>`
note: required because it's used within this async block
--> $DIR/issue-68112.rs:55:26
|
LL | let send_fut = async {
| __________________________^
LL | | let non_send_fut = make_non_send_future2();
LL | | let _ = non_send_fut.await;
LL | | ready(0).await;
LL | | };
| |_____^
note: required by a bound in `require_send`
--> $DIR/issue-68112.rs:11:25
|

View file

@ -0,0 +1,40 @@
error[E0277]: `Sender<i32>` cannot be shared between threads safely
--> $DIR/issue-70935-complex-spans.rs:13:45
|
LL | fn foo(tx: std::sync::mpsc::Sender<i32>) -> impl Future + Send {
| ^^^^^^^^^^^^^^^^^^ `Sender<i32>` cannot be shared between threads safely
|
= help: the trait `Sync` is not implemented for `Sender<i32>`
= note: required because of the requirements on the impl of `Send` for `&Sender<i32>`
note: required because it's used within this closure
--> $DIR/issue-70935-complex-spans.rs:25:13
|
LL | baz(|| async{
| _____________^
LL | | foo(tx.clone());
LL | | }).await;
| |_________^
note: required because it's used within this async block
--> $DIR/issue-70935-complex-spans.rs:9:67
|
LL | async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> {
| ___________________________________________________________________^
LL | |
LL | | }
| |_^
= note: required because it captures the following types: `ResumeTy`, `impl Future<Output = ()>`, `()`
note: required because it's used within this async block
--> $DIR/issue-70935-complex-spans.rs:23:16
|
LL | async move {
| ________________^
LL | |
LL | | baz(|| async{
LL | | foo(tx.clone());
LL | | }).await;
LL | | }
| |_____^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View file

@ -1,12 +1,12 @@
error: future cannot be sent between threads safely
--> $DIR/issue-70935-complex-spans.rs:10:45
--> $DIR/issue-70935-complex-spans.rs:13:45
|
LL | fn foo(tx: std::sync::mpsc::Sender<i32>) -> impl Future + Send {
| ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
|
= help: the trait `Sync` is not implemented for `Sender<i32>`
note: future is not `Send` as this value is used across an await
--> $DIR/issue-70935-complex-spans.rs:15:11
--> $DIR/issue-70935-complex-spans.rs:27:11
|
LL | baz(|| async{
| _____________-
@ -14,9 +14,9 @@ LL | | foo(tx.clone());
LL | | }).await;
| | - ^^^^^^ await occurs here, with the value maybe used later
| |_________|
| has type `[closure@$DIR/issue-70935-complex-spans.rs:13:13: 15:10]` which is not `Send`
| has type `[closure@$DIR/issue-70935-complex-spans.rs:25:13: 27:10]` which is not `Send`
note: the value is later dropped here
--> $DIR/issue-70935-complex-spans.rs:15:17
--> $DIR/issue-70935-complex-spans.rs:27:17
|
LL | }).await;
| ^

View file

@ -1,16 +1,28 @@
// edition:2018
// revisions: normal drop_tracking
// [drop_tracking]compile-flags:-Zdrop-tracking
// #70935: Check if we do not emit snippet
// with newlines which lead complex diagnostics.
use std::future::Future;
async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> {
//[drop_tracking]~^ within this async block
}
fn foo(tx: std::sync::mpsc::Sender<i32>) -> impl Future + Send {
//~^ ERROR: future cannot be sent between threads safely
//[normal]~^ ERROR: future cannot be sent between threads safely
//[drop_tracking]~^^ ERROR: `Sender<i32>` cannot be shared
//[drop_tracking]~| NOTE: cannot be shared
//[drop_tracking]~| NOTE: requirements on the impl of `Send`
//[drop_tracking]~| NOTE: captures the following types
//[drop_tracking]~| NOTE: in this expansion
//[drop_tracking]~| NOTE: in this expansion
//[drop_tracking]~| NOTE: in this expansion
//[drop_tracking]~| NOTE: in this expansion
async move {
baz(|| async{
//[drop_tracking]~^ within this async block
baz(|| async{ //[drop_tracking]~ NOTE: used within this closure
foo(tx.clone());
}).await;
}

View file

@ -5,9 +5,15 @@
fn main() {
gimme_send(foo());
//~^ ERROR cannot be sent between threads safely
//~| NOTE cannot be sent
//~| NOTE bound introduced by
//~| NOTE appears within the type
//~| NOTE captures the following types
}
fn gimme_send<T: Send>(t: T) {
//~^ NOTE required by this bound
//~| NOTE required by a bound
drop(t);
}
@ -20,6 +26,8 @@ fn drop(&mut self) {}
impl !Send for NotSend {}
async fn foo() {
//~^ NOTE used within this async block
//~| NOTE within this `impl Future
let mut x = (NotSend {},);
drop(x.0);
x.0 = NotSend {};

View file

@ -11,13 +11,21 @@ LL | async fn foo() {
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `NotSend`
= note: required because it appears within the type `(NotSend,)`
= note: required because it appears within the type `{ResumeTy, (NotSend,), impl Future<Output = ()>, ()}`
= note: required because it appears within the type `[static generator@$DIR/partial-drop-partial-reinit.rs:22:16: 27:2]`
= note: required because it appears within the type `std::future::from_generator::GenFuture<[static generator@$DIR/partial-drop-partial-reinit.rs:22:16: 27:2]>`
= note: required because it appears within the type `impl Future<Output = ()>`
= note: required because it appears within the type `impl Future<Output = ()>`
= note: required because it captures the following types: `ResumeTy`, `(NotSend,)`, `impl Future<Output = ()>`, `()`
note: required because it's used within this async block
--> $DIR/partial-drop-partial-reinit.rs:28:16
|
LL | async fn foo() {
| ________________^
LL | |
LL | |
LL | | let mut x = (NotSend {},);
... |
LL | | bar().await;
LL | | }
| |_^
note: required by a bound in `gimme_send`
--> $DIR/partial-drop-partial-reinit.rs:10:18
--> $DIR/partial-drop-partial-reinit.rs:14:18
|
LL | fn gimme_send<T: Send>(t: T) {
| ^^^^ required by this bound in `gimme_send`

View file

@ -6,7 +6,15 @@ LL | let t = thread::spawn(|| {
|
= help: the trait `Sync` is not implemented for `std::sync::mpsc::Receiver<()>`
= note: required because of the requirements on the impl of `Send` for `&std::sync::mpsc::Receiver<()>`
= note: required because it appears within the type `[closure@$DIR/closure-move-sync.rs:6:27: 9:6]`
note: required because it's used within this closure
--> $DIR/closure-move-sync.rs:6:27
|
LL | let t = thread::spawn(|| {
| ___________________________^
LL | | recv.recv().unwrap();
LL | |
LL | | });
| |_____^
note: required by a bound in `spawn`
--> $SRC_DIR/std/src/thread/mod.rs:LL:COL
|
@ -21,7 +29,11 @@ LL | thread::spawn(|| tx.send(()).unwrap());
|
= help: the trait `Sync` is not implemented for `Sender<()>`
= note: required because of the requirements on the impl of `Send` for `&Sender<()>`
= note: required because it appears within the type `[closure@$DIR/closure-move-sync.rs:18:19: 18:42]`
note: required because it's used within this closure
--> $DIR/closure-move-sync.rs:18:19
|
LL | thread::spawn(|| tx.send(()).unwrap());
| ^^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `spawn`
--> $SRC_DIR/std/src/thread/mod.rs:LL:COL
|

View file

@ -20,6 +20,10 @@ pub fn make_gen1<T>(t: T) -> Ready<T> {
}
fn require_send(_: impl Send) {}
//~^ NOTE required by a bound
//~| NOTE required by a bound
//~| NOTE required by this bound
//~| NOTE required by this bound
fn make_non_send_generator() -> impl Generator<Return = Arc<RefCell<i32>>> {
make_gen1(Arc::new(RefCell::new(0)))
@ -28,29 +32,39 @@ fn make_non_send_generator() -> impl Generator<Return = Arc<RefCell<i32>>> {
fn test1() {
let send_gen = || {
let _non_send_gen = make_non_send_generator();
//~^ NOTE not `Send`
yield;
};
//~^ NOTE yield occurs here
//~| NOTE value is used across a yield
}; //~ NOTE later dropped here
require_send(send_gen);
//~^ ERROR generator cannot be sent between threads
//~| NOTE not `Send`
}
pub fn make_gen2<T>(t: T) -> impl Generator<Return = T> {
|| {
//~^ NOTE appears within the type
//~| NOTE expansion of desugaring
|| { //~ NOTE used within this generator
yield;
t
}
}
fn make_non_send_generator2() -> impl Generator<Return = Arc<RefCell<i32>>> {
fn make_non_send_generator2() -> impl Generator<Return = Arc<RefCell<i32>>> { //~ NOTE appears within the type
//~^ NOTE expansion of desugaring
make_gen2(Arc::new(RefCell::new(0)))
}
fn test2() {
let send_gen = || {
let send_gen = || { //~ NOTE used within this generator
let _non_send_gen = make_non_send_generator2();
yield;
};
require_send(send_gen);
//~^ ERROR `RefCell<i32>` cannot be shared between threads safely
//~| NOTE `RefCell<i32>` cannot be shared between threads safely
//~| NOTE requirements on the impl
//~| NOTE captures the following types
}
fn main() {}

View file

@ -1,17 +1,19 @@
error: generator cannot be sent between threads safely
--> $DIR/issue-68112.rs:33:5
--> $DIR/issue-68112.rs:40:5
|
LL | require_send(send_gen);
| ^^^^^^^^^^^^ generator is not `Send`
|
= help: the trait `Sync` is not implemented for `RefCell<i32>`
note: generator is not `Send` as this value is used across a yield
--> $DIR/issue-68112.rs:31:9
--> $DIR/issue-68112.rs:36:9
|
LL | let _non_send_gen = make_non_send_generator();
| ------------- has type `impl Generator<Return = Arc<RefCell<i32>>>` which is not `Send`
LL |
LL | yield;
| ^^^^^ yield occurs here, with `_non_send_gen` maybe used later
...
LL | };
| - `_non_send_gen` is later dropped here
note: required by a bound in `require_send`
@ -21,18 +23,41 @@ LL | fn require_send(_: impl Send) {}
| ^^^^ required by this bound in `require_send`
error[E0277]: `RefCell<i32>` cannot be shared between threads safely
--> $DIR/issue-68112.rs:52:5
--> $DIR/issue-68112.rs:63:5
|
LL | require_send(send_gen);
| ^^^^^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
|
= help: the trait `Sync` is not implemented for `RefCell<i32>`
= note: required because of the requirements on the impl of `Send` for `Arc<RefCell<i32>>`
= note: required because it appears within the type `[generator@$DIR/issue-68112.rs:38:5: 41:6]`
= note: required because it appears within the type `impl Generator<Return = Arc<RefCell<i32>>>`
= note: required because it appears within the type `impl Generator<Return = Arc<RefCell<i32>>>`
= note: required because it appears within the type `{impl Generator<Return = Arc<RefCell<i32>>>, ()}`
= note: required because it appears within the type `[generator@$DIR/issue-68112.rs:48:20: 51:6]`
note: required because it's used within this generator
--> $DIR/issue-68112.rs:48:5
|
LL | / || {
LL | | yield;
LL | | t
LL | | }
| |_____^
note: required because it appears within the type `impl Generator<Return = Arc<RefCell<i32>>>`
--> $DIR/issue-68112.rs:45:30
|
LL | pub fn make_gen2<T>(t: T) -> impl Generator<Return = T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
note: required because it appears within the type `impl Generator<Return = Arc<RefCell<i32>>>`
--> $DIR/issue-68112.rs:53:34
|
LL | fn make_non_send_generator2() -> impl Generator<Return = Arc<RefCell<i32>>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: required because it captures the following types: `impl Generator<Return = Arc<RefCell<i32>>>`, `()`
note: required because it's used within this generator
--> $DIR/issue-68112.rs:59:20
|
LL | let send_gen = || {
| ____________________^
LL | | let _non_send_gen = make_non_send_generator2();
LL | | yield;
LL | | };
| |_____^
note: required by a bound in `require_send`
--> $DIR/issue-68112.rs:22:25
|

View file

@ -6,7 +6,16 @@ LL | assert_send(|| {
|
= help: the trait `Sync` is not implemented for `Cell<i32>`
= note: required because of the requirements on the impl of `Send` for `&Cell<i32>`
= note: required because it appears within the type `[generator@$DIR/not-send-sync.rs:16:17: 20:6]`
note: required because it's used within this generator
--> $DIR/not-send-sync.rs:16:17
|
LL | assert_send(|| {
| _________________^
LL | |
LL | | drop(&a);
LL | | yield;
LL | | });
| |_____^
note: required by a bound in `assert_send`
--> $DIR/not-send-sync.rs:7:23
|

View file

@ -28,11 +28,34 @@ LL | require_send(send_gen);
|
= help: the trait `Sync` is not implemented for `RefCell<i32>`
= note: required because of the requirements on the impl of `Send` for `Arc<RefCell<i32>>`
= note: required because it appears within the type `[make_gen2<Arc<RefCell<i32>>>::{closure#0} upvar_tys=(Arc<RefCell<i32>>) {()}]`
= note: required because it appears within the type `Opaque(DefId(0:39 ~ generator_print_verbose_1[749a]::make_gen2::{opaque#0}), [std::sync::Arc<std::cell::RefCell<i32>>])`
= note: required because it appears within the type `Opaque(DefId(0:42 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), [])`
= note: required because it appears within the type `{Opaque(DefId(0:42 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), []), ()}`
= note: required because it appears within the type `[test2::{closure#0} upvar_tys=() {Opaque(DefId(0:42 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), []), ()}]`
note: required because it's used within this generator
--> $DIR/generator-print-verbose-1.rs:42:5
|
LL | / || {
LL | | yield;
LL | | t
LL | | }
| |_____^
note: required because it appears within the type `Opaque(DefId(0:39 ~ generator_print_verbose_1[749a]::make_gen2::{opaque#0}), [std::sync::Arc<std::cell::RefCell<i32>>])`
--> $DIR/generator-print-verbose-1.rs:41:30
|
LL | pub fn make_gen2<T>(t: T) -> impl Generator<Return = T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
note: required because it appears within the type `Opaque(DefId(0:42 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), [])`
--> $DIR/generator-print-verbose-1.rs:47:34
|
LL | fn make_non_send_generator2() -> impl Generator<Return = Arc<RefCell<i32>>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: required because it captures the following types: `Opaque(DefId(0:42 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), [])`, `()`
note: required because it's used within this generator
--> $DIR/generator-print-verbose-1.rs:52:20
|
LL | let send_gen = || {
| ____________________^
LL | | let _non_send_gen = make_non_send_generator2();
LL | | yield;
LL | | };
| |_____^
note: required by a bound in `require_send`
--> $DIR/generator-print-verbose-1.rs:26:25
|

View file

@ -6,7 +6,16 @@ LL | assert_send(|| {
|
= help: the trait `Sync` is not implemented for `Cell<i32>`
= note: required because of the requirements on the impl of `Send` for `&'_#4r Cell<i32>`
= note: required because it appears within the type `[main::{closure#1} upvar_tys=(&'_#4r Cell<i32>) _#17t]`
note: required because it's used within this generator
--> $DIR/generator-print-verbose-2.rs:19:17
|
LL | assert_send(|| {
| _________________^
LL | |
LL | | drop(&a);
LL | | yield;
LL | | });
| |_____^
note: required by a bound in `assert_send`
--> $DIR/generator-print-verbose-2.rs:10:23
|

View file

@ -3,23 +3,37 @@
// Fast path, main can see the concrete type returned.
fn before() -> impl Fn(i32) {
//~^ NOTE within this `impl Fn
//~| NOTE within the type `impl Fn
//~| NOTE expansion of desugaring
let p = Rc::new(Cell::new(0));
move |x| p.set(x)
move |x| p.set(x) //~ NOTE used within this closure
}
fn send<T: Send>(_: T) {}
//~^ NOTE required by a bound
//~| NOTE required by a bound
//~| NOTE required by this bound
//~| NOTE required by this bound
fn main() {
send(before());
//~^ ERROR `Rc<Cell<i32>>` cannot be sent between threads safely
//~| NOTE `Rc<Cell<i32>>` cannot be sent between threads safely
//~| NOTE required by a bound
send(after());
//~^ ERROR `Rc<Cell<i32>>` cannot be sent between threads safely
//~| NOTE `Rc<Cell<i32>>` cannot be sent between threads safely
//~| NOTE required by a bound
}
// Deferred path, main has to wait until typeck finishes,
// to check if the return type of after is Send.
fn after() -> impl Fn(i32) {
//~^ NOTE within this `impl Fn(i32)`
//~| NOTE in this expansion
//~| NOTE appears within the type
let p = Rc::new(Cell::new(0));
move |x| p.set(x)
move |x| p.set(x) //~ NOTE used within this closure
}

View file

@ -1,5 +1,5 @@
error[E0277]: `Rc<Cell<i32>>` cannot be sent between threads safely
--> $DIR/auto-trait-leak2.rs:13:10
--> $DIR/auto-trait-leak2.rs:20:10
|
LL | fn before() -> impl Fn(i32) {
| ------------ within this `impl Fn(i32)`
@ -10,16 +10,24 @@ LL | send(before());
| required by a bound introduced by this call
|
= help: within `impl Fn(i32)`, the trait `Send` is not implemented for `Rc<Cell<i32>>`
= note: required because it appears within the type `[closure@$DIR/auto-trait-leak2.rs:7:5: 7:22]`
= note: required because it appears within the type `impl Fn(i32)`
note: required because it's used within this closure
--> $DIR/auto-trait-leak2.rs:10:5
|
LL | move |x| p.set(x)
| ^^^^^^^^^^^^^^^^^
note: required because it appears within the type `impl Fn(i32)`
--> $DIR/auto-trait-leak2.rs:5:16
|
LL | fn before() -> impl Fn(i32) {
| ^^^^^^^^^^^^
note: required by a bound in `send`
--> $DIR/auto-trait-leak2.rs:10:12
--> $DIR/auto-trait-leak2.rs:13:12
|
LL | fn send<T: Send>(_: T) {}
| ^^^^ required by this bound in `send`
error[E0277]: `Rc<Cell<i32>>` cannot be sent between threads safely
--> $DIR/auto-trait-leak2.rs:16:10
--> $DIR/auto-trait-leak2.rs:25:10
|
LL | send(after());
| ---- ^^^^^^^ `Rc<Cell<i32>>` cannot be sent between threads safely
@ -30,10 +38,18 @@ LL | fn after() -> impl Fn(i32) {
| ------------ within this `impl Fn(i32)`
|
= help: within `impl Fn(i32)`, the trait `Send` is not implemented for `Rc<Cell<i32>>`
= note: required because it appears within the type `[closure@$DIR/auto-trait-leak2.rs:24:5: 24:22]`
= note: required because it appears within the type `impl Fn(i32)`
note: required because it's used within this closure
--> $DIR/auto-trait-leak2.rs:38:5
|
LL | move |x| p.set(x)
| ^^^^^^^^^^^^^^^^^
note: required because it appears within the type `impl Fn(i32)`
--> $DIR/auto-trait-leak2.rs:33:15
|
LL | fn after() -> impl Fn(i32) {
| ^^^^^^^^^^^^
note: required by a bound in `send`
--> $DIR/auto-trait-leak2.rs:10:12
--> $DIR/auto-trait-leak2.rs:13:12
|
LL | fn send<T: Send>(_: T) {}
| ^^^^ required by this bound in `send`

View file

@ -7,7 +7,11 @@ LL | catch_unwind(|| { x.set(23); });
= help: within `Cell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<i32>`
= note: required because it appears within the type `Cell<i32>`
= note: required because of the requirements on the impl of `UnwindSafe` for `&Cell<i32>`
= note: required because it appears within the type `[closure@$DIR/interior-mutability.rs:5:18: 5:35]`
note: required because it's used within this closure
--> $DIR/interior-mutability.rs:5:18
|
LL | catch_unwind(|| { x.set(23); });
| ^^^^^^^^^^^^^^^^^
note: required by a bound in `catch_unwind`
--> $SRC_DIR/std/src/panic.rs:LL:COL
|

View file

@ -7,7 +7,11 @@ LL | bar(move|| foo(x));
| `Rc<usize>` cannot be sent between threads safely
|
= help: within `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:22]`, the trait `Send` is not implemented for `Rc<usize>`
= note: required because it appears within the type `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:22]`
note: required because it's used within this closure
--> $DIR/kindck-nonsendable-1.rs:9:9
|
LL | bar(move|| foo(x));
| ^^^^^^^^^^^^^
note: required by a bound in `bar`
--> $DIR/kindck-nonsendable-1.rs:5:21
|

View file

@ -22,7 +22,16 @@ note: required because it appears within the type `Foo`
|
LL | struct Foo {
| ^^^
= note: required because it appears within the type `[closure@$DIR/no-send-res-ports.rs:25:19: 29:6]`
note: required because it's used within this closure
--> $DIR/no-send-res-ports.rs:25:19
|
LL | thread::spawn(move|| {
| ___________________^
LL | |
LL | | let y = x;
LL | | println!("{:?}", y);
LL | | });
| |_____^
note: required by a bound in `spawn`
--> $SRC_DIR/std/src/thread/mod.rs:LL:COL
|

View file

@ -10,7 +10,14 @@ LL |
LL | let hello = hello.clone();
| ^^^^^ within `[closure@$DIR/not-clone-closure.rs:7:17: 9:6]`, the trait `Clone` is not implemented for `S`
|
= note: required because it appears within the type `[closure@$DIR/not-clone-closure.rs:7:17: 9:6]`
note: required because it's used within this closure
--> $DIR/not-clone-closure.rs:7:17
|
LL | let hello = move || {
| _________________^
LL | | println!("Hello {}", a.0);
LL | | };
| |_____^
help: consider annotating `S` with `#[derive(Clone)]`
|
LL | #[derive(Clone)]

View file

@ -4,7 +4,9 @@
mod m {
use std::rc::Rc;
type Foo = impl std::fmt::Debug;
type Foo = impl std::fmt::Debug; //~ NOTE appears within the type
//~^ within this `Foo`
//~| expansion of desugaring
pub fn foo() -> Foo {
Rc::new(22_u32)
@ -12,8 +14,12 @@ pub fn foo() -> Foo {
}
fn is_send<T: Send>(_: T) {}
//~^ required by this bound
//~| required by a bound
fn main() {
is_send(m::foo());
//~^ ERROR: `Rc<u32>` cannot be sent between threads safely [E0277]
//~| NOTE cannot be sent
//~| NOTE required by a bound
}

View file

@ -1,5 +1,5 @@
error[E0277]: `Rc<u32>` cannot be sent between threads safely
--> $DIR/auto-trait-leakage2.rs:17:13
--> $DIR/auto-trait-leakage2.rs:21:13
|
LL | type Foo = impl std::fmt::Debug;
| -------------------- within this `Foo`
@ -10,9 +10,13 @@ LL | is_send(m::foo());
| required by a bound introduced by this call
|
= help: within `Foo`, the trait `Send` is not implemented for `Rc<u32>`
= note: required because it appears within the type `Foo`
note: required because it appears within the type `Foo`
--> $DIR/auto-trait-leakage2.rs:7:16
|
LL | type Foo = impl std::fmt::Debug;
| ^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `is_send`
--> $DIR/auto-trait-leakage2.rs:14:15
--> $DIR/auto-trait-leakage2.rs:16:15
|
LL | fn is_send<T: Send>(_: T) {}
| ^^^^ required by this bound in `is_send`