1
Fork 0

Rollup merge of #98259 - jyn514:improve-obligation-errors, r=estebank

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.

Helps with https://github.com/rust-lang/rust/issues/97332.

r? ``@estebank`` cc ``@eholk`` ``@compiler-errors``
This commit is contained in:
Michael Goulet 2022-06-23 14:39:06 -07:00 committed by GitHub
commit 413e350f87
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 389 additions and 72 deletions

View file

@ -8,6 +8,7 @@ use crate::infer::InferCtxt;
use crate::traits::normalize_to; use crate::traits::normalize_to;
use hir::HirId; use hir::HirId;
use rustc_ast::Movability;
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::{ use rustc_errors::{
@ -2386,24 +2387,104 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
{ {
let parent_trait_ref = let parent_trait_ref =
self.resolve_vars_if_possible(data.parent_trait_pred); self.resolve_vars_if_possible(data.parent_trait_pred);
let ty = parent_trait_ref.skip_binder().self_ty(); let nested_ty = parent_trait_ref.skip_binder().self_ty();
matches!(ty.kind(), ty::Generator(..)) matches!(nested_ty.kind(), ty::Generator(..))
|| matches!(ty.kind(), ty::Closure(..)) || matches!(nested_ty.kind(), ty::Closure(..))
} else { } else {
false 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 // Don't print the tuple of capture types
if !is_upvar_tys_infer_tuple { 'print: {
let msg = format!("required because it appears within the type `{}`", ty); if !is_upvar_tys_infer_tuple {
match ty.kind() { let msg = format!("required because it appears within the type `{}`", ty);
ty::Adt(def, _) => match self.tcx.opt_item_ident(def.did()) { match ty.kind() {
Some(ident) => err.span_note(ident.span, &msg), ty::Adt(def, _) => {
None => err.note(&msg), // `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()) {
_ => err.note(&msg), 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); 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>` = 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 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's used within this async block
= note: required because it appears within the type `std::future::from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:47:31: 47:36]>` --> $DIR/issue-68112.rs:47:31
= 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>>>` LL | async fn ready2<T>(t: T) -> T { t }
= 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 `impl Future<Output = Arc<RefCell<i32>>>`
= note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:55:26: 59:6]` --> $DIR/issue-68112.rs:48:31
= 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 = ()>` 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` note: required by a bound in `require_send`
--> $DIR/issue-68112.rs:11:25 --> $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 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 { 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`
| |
= help: the trait `Sync` is not implemented for `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:15:11 --> $DIR/issue-70935-complex-spans.rs:27:11
| |
LL | baz(|| async{ LL | baz(|| async{
| _____________- | _____________-
@ -14,9 +14,9 @@ LL | | foo(tx.clone());
LL | | }).await; LL | | }).await;
| | - ^^^^^^ await occurs here, with the value maybe used later | | - ^^^^^^ 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 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; LL | }).await;
| ^ | ^

View file

@ -1,16 +1,28 @@
// edition:2018 // edition:2018
// revisions: normal drop_tracking
// [drop_tracking]compile-flags:-Zdrop-tracking
// #70935: Check if we do not emit snippet // #70935: Check if we do not emit snippet
// with newlines which lead complex diagnostics. // with newlines which lead complex diagnostics.
use std::future::Future; use std::future::Future;
async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> { 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 { 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 { async move {
baz(|| async{ //[drop_tracking]~^ within this async block
baz(|| async{ //[drop_tracking]~ NOTE: used within this closure
foo(tx.clone()); foo(tx.clone());
}).await; }).await;
} }

View file

@ -5,9 +5,15 @@
fn main() { fn main() {
gimme_send(foo()); gimme_send(foo());
//~^ ERROR cannot be sent between threads safely //~^ 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) { fn gimme_send<T: Send>(t: T) {
//~^ NOTE required by this bound
//~| NOTE required by a bound
drop(t); drop(t);
} }
@ -20,6 +26,8 @@ impl Drop for NotSend {
impl !Send for NotSend {} impl !Send for NotSend {}
async fn foo() { async fn foo() {
//~^ NOTE used within this async block
//~| NOTE within this `impl Future
let mut x = (NotSend {},); let mut x = (NotSend {},);
drop(x.0); drop(x.0);
x.0 = NotSend {}; 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` = 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 `(NotSend,)`
= note: required because it appears within the type `{ResumeTy, (NotSend,), impl Future<Output = ()>, ()}` = note: required because it captures the following types: `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's used within this async block
= 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]>` --> $DIR/partial-drop-partial-reinit.rs:28:16
= note: required because it appears within the type `impl Future<Output = ()>` |
= note: required because it appears within the type `impl Future<Output = ()>` LL | async fn foo() {
| ________________^
LL | |
LL | |
LL | | let mut x = (NotSend {},);
... |
LL | | bar().await;
LL | | }
| |_^
note: required by a bound in `gimme_send` 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) { LL | fn gimme_send<T: Send>(t: T) {
| ^^^^ required by this bound in `gimme_send` | ^^^^ 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<()>` = 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 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` note: required by a bound in `spawn`
--> $SRC_DIR/std/src/thread/mod.rs:LL:COL --> $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<()>` = 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 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` note: required by a bound in `spawn`
--> $SRC_DIR/std/src/thread/mod.rs:LL:COL --> $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) {} 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>>> { fn make_non_send_generator() -> impl Generator<Return = Arc<RefCell<i32>>> {
make_gen1(Arc::new(RefCell::new(0))) make_gen1(Arc::new(RefCell::new(0)))
@ -28,29 +32,39 @@ fn make_non_send_generator() -> impl Generator<Return = Arc<RefCell<i32>>> {
fn test1() { fn test1() {
let send_gen = || { let send_gen = || {
let _non_send_gen = make_non_send_generator(); let _non_send_gen = make_non_send_generator();
//~^ NOTE not `Send`
yield; yield;
}; //~^ NOTE yield occurs here
//~| NOTE value is used across a yield
}; //~ NOTE later dropped here
require_send(send_gen); require_send(send_gen);
//~^ ERROR generator cannot be sent between threads //~^ ERROR generator cannot be sent between threads
//~| NOTE not `Send`
} }
pub fn make_gen2<T>(t: T) -> impl Generator<Return = T> { 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; yield;
t 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))) make_gen2(Arc::new(RefCell::new(0)))
} }
fn test2() { fn test2() {
let send_gen = || { let send_gen = || { //~ NOTE used within this generator
let _non_send_gen = make_non_send_generator2(); let _non_send_gen = make_non_send_generator2();
yield; yield;
}; };
require_send(send_gen); require_send(send_gen);
//~^ ERROR `RefCell<i32>` cannot be shared between threads safely //~^ 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() {} fn main() {}

View file

@ -1,17 +1,19 @@
error: generator cannot be sent between threads safely 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); LL | require_send(send_gen);
| ^^^^^^^^^^^^ generator is not `Send` | ^^^^^^^^^^^^ generator is not `Send`
| |
= help: the trait `Sync` is not implemented for `RefCell<i32>` = help: the trait `Sync` is not implemented for `RefCell<i32>`
note: generator is not `Send` as this value is used across a yield 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(); LL | let _non_send_gen = make_non_send_generator();
| ------------- has type `impl Generator<Return = Arc<RefCell<i32>>>` which is not `Send` | ------------- has type `impl Generator<Return = Arc<RefCell<i32>>>` which is not `Send`
LL |
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 | };
| - `_non_send_gen` is later dropped here | - `_non_send_gen` is later dropped here
note: required by a bound in `require_send` 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` | ^^^^ required by this bound in `require_send`
error[E0277]: `RefCell<i32>` cannot be shared between threads safely 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); LL | require_send(send_gen);
| ^^^^^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely | ^^^^^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
| |
= help: the trait `Sync` is not implemented for `RefCell<i32>` = 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 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's used within this generator
= note: required because it appears within the type `impl Generator<Return = Arc<RefCell<i32>>>` --> $DIR/issue-68112.rs:48:5
= 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>>>, ()}` LL | / || {
= note: required because it appears within the type `[generator@$DIR/issue-68112.rs:48:20: 51:6]` 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` note: required by a bound in `require_send`
--> $DIR/issue-68112.rs:22:25 --> $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>` = 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 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` note: required by a bound in `assert_send`
--> $DIR/not-send-sync.rs:7:23 --> $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>` = 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 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's used within this generator
= 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:42:5
= 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}), []), ()}` LL | / || {
= 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}), []), ()}]` 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` note: required by a bound in `require_send`
--> $DIR/generator-print-verbose-1.rs:26:25 --> $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>` = 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 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` note: required by a bound in `assert_send`
--> $DIR/generator-print-verbose-2.rs:10:23 --> $DIR/generator-print-verbose-2.rs:10:23
| |

View file

@ -3,23 +3,37 @@ use std::rc::Rc;
// Fast path, main can see the concrete type returned. // Fast path, main can see the concrete type returned.
fn before() -> impl Fn(i32) { 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)); 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) {} 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() { fn main() {
send(before()); send(before());
//~^ ERROR `Rc<Cell<i32>>` cannot be sent between threads safely //~^ 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()); send(after());
//~^ ERROR `Rc<Cell<i32>>` cannot be sent between threads safely //~^ 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, // Deferred path, main has to wait until typeck finishes,
// to check if the return type of after is Send. // to check if the return type of after is Send.
fn after() -> impl Fn(i32) { 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)); 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 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) { LL | fn before() -> impl Fn(i32) {
| ------------ within this `impl Fn(i32)` | ------------ within this `impl Fn(i32)`
@ -10,16 +10,24 @@ LL | send(before());
| required by a bound introduced by this call | required by a bound introduced by this call
| |
= help: within `impl Fn(i32)`, the trait `Send` is not implemented for `Rc<Cell<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:7:5: 7:22]` note: required because it's used within this closure
= note: required because it appears within the type `impl Fn(i32)` --> $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` 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) {} LL | fn send<T: Send>(_: T) {}
| ^^^^ required by this bound in `send` | ^^^^ required by this bound in `send`
error[E0277]: `Rc<Cell<i32>>` cannot be sent between threads safely 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()); LL | send(after());
| ---- ^^^^^^^ `Rc<Cell<i32>>` cannot be sent between threads safely | ---- ^^^^^^^ `Rc<Cell<i32>>` cannot be sent between threads safely
@ -30,10 +38,18 @@ LL | fn after() -> impl Fn(i32) {
| ------------ within this `impl Fn(i32)` | ------------ within this `impl Fn(i32)`
| |
= help: within `impl Fn(i32)`, the trait `Send` is not implemented for `Rc<Cell<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's used within this closure
= note: required because it appears within the type `impl Fn(i32)` --> $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` 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) {} LL | fn send<T: Send>(_: T) {}
| ^^^^ required by this bound in `send` | ^^^^ 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>` = 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 it appears within the type `Cell<i32>`
= note: required because of the requirements on the impl of `UnwindSafe` for `&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` note: required by a bound in `catch_unwind`
--> $SRC_DIR/std/src/panic.rs:LL:COL --> $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 | `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>` = 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` note: required by a bound in `bar`
--> $DIR/kindck-nonsendable-1.rs:5:21 --> $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 { 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` note: required by a bound in `spawn`
--> $SRC_DIR/std/src/thread/mod.rs:LL:COL --> $SRC_DIR/std/src/thread/mod.rs:LL:COL
| |

View file

@ -10,7 +10,14 @@ LL |
LL | let hello = hello.clone(); LL | let hello = hello.clone();
| ^^^^^ within `[closure@$DIR/not-clone-closure.rs:7:17: 9:6]`, the trait `Clone` is not implemented for `S` | ^^^^^ 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)]` help: consider annotating `S` with `#[derive(Clone)]`
| |
LL | #[derive(Clone)] LL | #[derive(Clone)]

View file

@ -4,7 +4,9 @@
mod m { mod m {
use std::rc::Rc; 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 { pub fn foo() -> Foo {
Rc::new(22_u32) Rc::new(22_u32)
@ -12,8 +14,12 @@ mod m {
} }
fn is_send<T: Send>(_: T) {} fn is_send<T: Send>(_: T) {}
//~^ required by this bound
//~| required by a bound
fn main() { fn main() {
is_send(m::foo()); is_send(m::foo());
//~^ ERROR: `Rc<u32>` cannot be sent between threads safely [E0277] //~^ 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 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; LL | type Foo = impl std::fmt::Debug;
| -------------------- within this `Foo` | -------------------- within this `Foo`
@ -10,9 +10,13 @@ LL | is_send(m::foo());
| required by a bound introduced by this call | required by a bound introduced by this call
| |
= help: within `Foo`, the trait `Send` is not implemented for `Rc<u32>` = 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` 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) {} LL | fn is_send<T: Send>(_: T) {}
| ^^^^ required by this bound in `is_send` | ^^^^ required by this bound in `is_send`