Code change:
It took a colleague explaining to me that the return type of a function returning an impl Trait is unique across function definitions for me to understand the following error: This becomes more important for async/await because of the automatic translation of to : In the first case, can the error maybe call out that the opaque types are different due to how the compiler treats them? And for the second error, can this be called out in async-specific language. That error happens when you forget to call .
How about?: In the second case I think we should suggest that the s be moved into the branches tho this may be complicated to encode as a diagnostic. cc
Agreed, this is definitely a bit trickier. I'll defer to you on the best way to message this error.
In the first case, can the error maybe call out that the opaque types are different due to how the compiler treats them? Doesn't it already does so?
what is the correct nomenclature for a regular, non-opaque type that we could use here? With that we could say something like "consider materializing to an explicit type in both branches from the opaque type" and "for you can them on both branches to unify the types". This is rough wording, but gives an idea of what I'm thinking.
The antonym of opaque is transparent but I'm not sure that is situationally good to use here. ISTM you'd want to say something like "use an enum with variants for both cases" (at least that's the advice I'd give in person). I'd go for a non-actionable description as a first pass at this problem and consider an improvement later.
Are opaque types the same as anonymous types in C#/Java? If so I think 'anonymous' is clearer than opaque (pardon the pun!).
This is a real gotcha of rust and needs a great error message. We could show the definition sites of the opaque types so it's clear which type is expected in this position: Something like:
It doesn't matter where the resides in. Two uses will result in two distinct types from the POV of the type system. Only by naming an through a type alias can you refer to the same inferred type. Adding the qualification "in function signatures" does not enlighten. As for "anonymous", the closest equivalent Java's anonymous classes, which conjure new types, in Rust are closures. Also, with Java's anonymous classes you can recover the type identity at runtime using but you cannot name them. However, in Rust can be named (using a alias), they do not representationally create new types (although they do nominally), and they do not leak their type identities. Rather, is about hiding the underlying type (think of as a coercion that hides the type). The is most similar to Stanard ML's opaque matching (see section G.2 in the ) All in all, opacity is therefore the most appropriate description rather than anonymity.
I'll get used to :-) You're refering here to ? Most of the time when someone gets this error they're assuming they can do this but don't realise they need to make the two impl Traits be the same type. We could hint that there's an unstabilised feature that could help? But if they weren't trying to bind both impl Traits to be the same type, then given both types textually look the same it would be great if the error message could point out the difference between those two types. Currently the error says: As a nubie I need to see something different between the two types that I can get my teeth into. How about: Somehow it would be great to distinguish these two opaque types (or does the compiler at this point has no knowledge of where these two opaque types came from - only that they are not the same?).
Fwiw, we desire to keep jargon to minimum.
was removed from the language in in favor of just . We could hint towards that on nightly. Seems like a nice improvement.
Thanks Centril - hadn't seen that switch. If people are ok with adding line numbers to pinpoint the different impl Traits I'll have a go at rolling a PR?
With all the various improvements that we've done, is there more we could do? or shall we close this issue for now?

Related discussion:
text: if let Some((expected, found)) = expected_found { match (terr, is_simple_error, expected == found) { (&TypeError::Sorts(ref values), false, true) => { <ins> let sort_string = | a_type: Ty<'tcx> | if let ty::Opaque(def_id, _) = a_type.sty { format!(" (opaque type at {})", self.tcx.sess.source_map() .mk_substr_filename(self.tcx.def_span(def_id))) } else { format!(" ({})", a_type.sort_string(self.tcx)) }; </ins> diag.note_expected_found_extra( &"type", expected, found, <del> &format!(" ({})", values.expected.sort_string(self.tcx)), &format!(" ({})", values.found.sort_string(self.tcx)), </del> <ins> &sort_string(values.expected), &sort_string(values.found), </ins> ); } (_, false, _) => {