-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
non-send futures error at point of use, but could cite point of definition in some cases #64130
Comments
I'm abusing the blocking tag here to try and keep this on the shortlist of "things we might try to do before beta". Assigning to myself to leave some mentoring notes. |
CC #42855 |
I laid out something thinking in this Zulip thread |
On obligation errors point at the unfulfilled binding when possible CC rust-lang#42855, rust-lang#64130, rust-lang#64135.
@rustbot claim |
OK let me try to leave a few notes here. First, we need to decide how this error should look. I created a gist that shows roughly what I'm going after, but it's not ideal: https://gist.github.com/nikomatsakis/ac95488236dec61976c92e523df622f9 First off, the messages like this:
are generated by the rust/src/librustc/traits/error_reporting.rs Lines 1559 to 1568 in dece573
What happens here is that we track some information about why we are forced to prove any particular trait relationship. For auto trait chains, we wind up with a chain of "obligation causes", specifically these two variants: rust/src/librustc/traits/error_reporting.rs Line 1688 in dece573
rust/src/librustc/traits/error_reporting.rs Line 1702 in dece573
So, to start, I think what we want to do is to look for the case where we have a chain of obligation causes that leads to generator types (we might want to include closures here, too, but I'm going to ignore them for now) and invoke a special path for such cases. To start, we could limit this to cases that involve only generators, generator interiors, and opaque type (apart from the top type), which seems to be the case in our example. This won't handle examples where futures are combined, e.g. async fn foo() {...}
async fn bar() {...}
fn is_send<T: Send>(_: T) { }
fn main() {
is_send((foo(), bar())); // introduces a tuple type into the chain
} but that seems ok to start. We can always think how to generalize it. I'm imagining we'll basically have a function like So then the idea would be that we can dump this "stack trace" as a series of notes. If the generator is local to the crate, we'll try to grab its span, but if it's foreign, we'll just print a path. Now, the nice thing is that each generator type is tagged with its def-id: Lines 163 to 165 in dece573
If this is a local def-id, we can go from that to get the HIR for the function and a span. If it's not local, we can't get the HIR, but we can print a path to it. One challenge is that the "generator interior" contains types that originate from expressions and variables, but it doesn't currently track where those types came from. It's just a list of types: Lines 167 to 169 in dece573
This value is computed by What we do is to visit patterns and expressions, looking for those that may overlook a type. For each one, we invoke the rust/src/librustc_typeck/check/generator_interior.rs Lines 24 to 28 in dece573
This function adds the type into the list of types if (a) it's not already present and (b) it may be live over a yield. The actual add happens here:
I think what I would like to do is to also remember the |
On obligation errors point at the unfulfilled binding when possible CC rust-lang#42855, rust-lang#64130, rust-lang#64135.
I talked about this with @yoshuawuyts today and we settled on something like this as a pretty decent error message (and, I think, achievable). One of the key changes is that it does not attempt to explain each step of how we got from the
|
In addition to what @nikomatsakis has said so far, I wanted to highlight something else in the example:
This line is intended to inform people that:
The goal is to inform people of these rules so they can start forming intuition about them. Because conditional |
FYI: When reading the error message for the first time I was looking for the 'where clause' in the error message. I guess the |
…efinition, r=nikomatsakis async/await: improve not-send errors cc rust-lang#64130. ``` note: future does not implement `std::marker::Send` because 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>` LL | baz().await; | ^^^^^^^^^^^ await occurs here, with `g` maybe used later LL | } | - `g` is later dropped here ``` r? @nikomatsakis
…provements, r=nikomatsakis async/await: improve not-send errors, part 2 Part of #64130. Fixes #65667. This PR improves the errors introduced in #64895 so that they have specialized messages for `Send` and `Sync`. r? @nikomatsakis
Consider this example (playground):
This program is in error because
bar()
is holding a mutex guard (which is notSend
) live across thebaz().await
call. The error however is rather opaque:When discussing this error, @cramertj suggested that we might look for patterns like this and try to offer a customized error. They sketched out
Something along these lines could be a big improvement!
The text was updated successfully, but these errors were encountered: