-
Notifications
You must be signed in to change notification settings - Fork 13.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Suggest move closures when a Sync bound is not satisfied through a closure #33307
Comments
Why isn't the impl<'a, T: Sync> Send for &'a T impl on the stack? |
Not sure, really. |
My patch so far diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index d7ddfc9..b70a813 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -861,10 +861,26 @@ fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
}
ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
let parent_trait_ref = infcx.resolve_type_vars_if_possible(&data.parent_trait_ref);
+ let ty = parent_trait_ref.0.self_ty();
err.fileline_note(
cause_span,
&format!("required because it appears within the type `{}`",
- parent_trait_ref.0.self_ty()));
+ ty));
+
+ // In case the requirement is that a closure be Send,
+ if Some(parent_trait_ref.0.def_id) == infcx.tcx.lang_items.send_trait() {
+ if let ty::TyClosure(did, _) = ty.sty {
+ if let Some(span) = infcx.tcx.map.span_if_local(did) {
+ let suggestion = match infcx.tcx.sess.codemap().span_to_snippet(span) {
+ Ok(string) => format!("move {}", string),
+ Err(_) => format!("move |<args>| <body>")
+ };
+ err.span_suggestion(span,
+ "Perhaps try marking this closure as a `move` closure?",
+ suggestion);
+ }
+ }
+ }
let parent_predicate = parent_trait_ref.to_predicate();
note_obligation_cause_code(infcx,
err, Still needs to check if the closure is move already or if move-ifying it will have any effect. |
After not dropping impls:
|
@Manishearth: I'd love to see it also spell out which variable is of the non- |
Yeah, that's a good idea. It shouldn't be too hard to do either. |
@arielb1 You were assigned to this issue, but I don't believe it's been implemented. Should we unassign you? |
So, to spell this out:
I think we have to be careful to not go advising fn want_send<T: Send>(t: T) { }
fn want_sync<T: Sync>(t: T) { }
// move will not help because `x` is itself a reference:
fn foo(x: &Cell<T>) {
want_send(|| x.set(1));
}
// move will not help because `Cell<T>` is not sync:
fn foo(x: Cell<T>) {
want_sync(|| x.set(1));
} |
Triage: no change. Current output:
|
playpen
This currently gives the error
If a closure needs to be Sync, we should perhaps suggest that it be made a move closure.
Perhaps we should verify that the closure can be made move (i.e. it is
: 'static
when made move), but I'm not sure how easy that is to do.We already suggest move closures when you do the same thing with a
Vec
, because the error reaches borrowck. Typeck sync issues don't suggest move.cc @nikomatsakis
The text was updated successfully, but these errors were encountered: