-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Print associated types on opaque impl Trait
types
#91096
Print associated types on opaque impl Trait
types
#91096
Conversation
Can we move that to a separate PR? I can approve and merge that quickly.
You can use
Some of the output is getting quite verbose :( The one that stands out to me in particular is for closures: multiple |
// Append to trait_ref's projection list if it exists, otherwise | ||
// insert a new one. | ||
if let Some((_, assoc_items)) = | ||
traits.iter_mut().find(|(t, _)| t == &trait_ref) | ||
{ | ||
is_future = true; | ||
continue; | ||
assoc_items.push(proj_ty); | ||
} else { | ||
traits.push((trait_ref, vec![proj_ty])); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of this can be replaced by using the .entry()
API instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that's what I was using before I hit issues with iter() ordering being unstable and messing up the ui tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To make myself a bit more clear, I was using an HashMap here before and when I iterated over the entries during the printing phase, the test outputs were randomized across runs. I tried to fix this by then collecting back into a Vec only after iteration, but I didn't know what to sort_by
since all of my keys aren't Ord
.
Sort by what though? PolyTraitRef (or TraitRef) which I would want to use as the key to this mapping is not Ord. Should I sort by the ref's DefId and its substs? |
Can do. |
@@ -1,4 +1,4 @@ | |||
error: `extern` block uses type `impl Fn<()>`, which is not FFI-safe | |||
error: `extern` block uses type `impl Fn<()> + FnOnce<(), Output = ()>`, which is not FFI-safe |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is what I was mentioning. I think that we can look at the traits to see that one implies the other to show only one at a time, without special casing closures.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah so this is printing because we have two predicates here Fn<()>
and <Self as FnOnce<()>>::Output == ()
. The first one makes us print Fn<()>
and the second makes us print FnOnce<(), Output = ()>
.
I actually would be interested in special casing just Fn
/FnMut
/FnOnce
and fixing it up further so it prints impl Fn() -> ()
instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can keep track of the traits for the predicates you've seen already and see if the new predicate's trait is part of the existing ones' super-traits. Special casing sounds reasonable-ish, but I would prefer it if we could just make it work for the general case :)
Regardless, dealing with the <_ as async {}>::Return
types in a nicer way (even if it is showing them as _
) has priority over this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can keep track of the traits for the predicates you've seen already
Is there any ordering enforced for the list of predicates that we're iterating over here, though?
I would prefer it if we could just make it work for the general case :)
So I'm pretty sure this only prints supertraits if you're bounding an associated type on that supertrait, so in practice we really only see this with Fn*
family of traits I think. (Because impl Fn() -> Foo
desugars to impl Fn<()> + FnOnce<(), Output=Foo>
, or similar, right?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Closures is gonna be the most common thing people will see, but a crate can write their own API structure that does the same thing. If closures are special cased, any user of those (potential, as none come to mind) crates could get confused.
@@ -15,7 +15,7 @@ LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return> | |||
| ------------------------------- the found opaque type | |||
| | |||
= note: expected opaque type `impl Future<Output = u8>` | |||
found opaque type `impl Future` | |||
found opaque type `impl Future<Output = <[static generator@$DIR/issue-78722.rs:12:26: 12:31] as Generator<ResumeTy>>::Return>` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think though that we should special case Generator
and call it something like [async@$DIR/issue-78722.rs:12:20: 12:31]
so it looks like:
found opaque type `impl Future<Output = <[async@$DIR/issue-78722.rs:12:26: 12:31]>`
What do you think?
It is tricky, because I'd want to refer to the whole Future as that, but that would also be confusing :-/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm.. Yeah, I could see us special-casing it. I wouldn't mind printing [async@...]
for the whole impl Future
type. Having impl Future<Output = [async@...]>
seems to me confusing because the output type isn't the async block's type itself.
... unless there's a way of normalizing that <_ as Generator>::Return
type in the code here. That would be the best.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you make Generator::Return
a lang_item
and query it here to unconditionally replace it with _
or [async result]
, what is the diff in the tests? We might want to go that route instead, depending on how much real code is affected. I suspect that this type isn't being shown much today because it most commonly appears only as part of Future::Output
, so it wouldn't be a regression to hide it.
☔ The latest upstream changes (presumably #91104) made this pull request unmergeable. Please resolve the merge conflicts. |
e24de3e
to
22f9b9b
Compare
I updated the code to address a few issues with my original PR:
And a few smaller things to support these changes:
What do you think @estebank ? |
22f9b9b
to
703d751
Compare
@@ -7,7 +7,7 @@ LL | | |||
LL | static STATIC_FN: FunType = some_fn; | |||
| ^^^^^^^ expected opaque type, found fn item | |||
| | |||
= note: expected opaque type `impl Fn<()>` | |||
= note: expected opaque type `impl Fn<()> + FnOnce<()>` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Noticed this, a bit odd because it seems you were detecting this case already
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the reason this one doesn't rewrite itself into impl Fn() -> T
is because the opaque type has no return type constraint. I'll fix it to just go back to impl Fn<()>
(very easy to do) or we could print -> _
if you think that would look better!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Either approach would be fine. Do whichever works best for you.
703d751
to
4c6194f
Compare
This comment has been minimized.
This comment has been minimized.
4c6194f
to
9cc1179
Compare
= note: expected opaque type `impl Fn()` | ||
found fn item `fn() {bar}` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(not for this PR): These cases should have an additional note
explaining the difference between fn
and Fn
, and what you can do to deal with that.
@bors r+ |
📌 Commit 9cc1179 has been approved by |
⌛ Testing commit 9cc1179 with merge 26389d998e6ee0492f2c7f3eec661d37e9d6d841... |
The job Click to see the possible cause of the failure (guessed by this bot)
|
💔 Test failed - checks-actions |
@bors retry |
…ait, r=estebank Print associated types on opaque `impl Trait` types This PR generalizes rust-lang#91021, printing associated types for all opaque `impl Trait` types instead of just special-casing for future. before: ``` error[E0271]: type mismatch resolving `<impl Iterator as Iterator>::Item == u32` ``` after: ``` error[E0271]: type mismatch resolving `<impl Iterator<Item = usize> as Iterator>::Item == u32` ``` --- Questions: 1. I'm kinda lost in binders hell with this one. Is all of the `rebind`ing necessary? 2. Is there a map collection type that will give me a stable iteration order? Doesn't seem like TraitRef is Ord, so I can't just sort later.. 3. I removed the logic that suppresses printing generator projection types. It creates outputs like this [gist](https://gist.github.com/compiler-errors/d6f12fb30079feb1ad1d5f1ab39a3a8d). Should I put that back? 4. I also added spaces between traits, `impl A+B` -> `impl A + B`. I quite like this change, but is there a good reason to keep it like that? r? `@estebank`
…ait, r=estebank Print associated types on opaque `impl Trait` types This PR generalizes rust-lang#91021, printing associated types for all opaque `impl Trait` types instead of just special-casing for future. before: ``` error[E0271]: type mismatch resolving `<impl Iterator as Iterator>::Item == u32` ``` after: ``` error[E0271]: type mismatch resolving `<impl Iterator<Item = usize> as Iterator>::Item == u32` ``` --- Questions: 1. I'm kinda lost in binders hell with this one. Is all of the `rebind`ing necessary? 2. Is there a map collection type that will give me a stable iteration order? Doesn't seem like TraitRef is Ord, so I can't just sort later.. 3. I removed the logic that suppresses printing generator projection types. It creates outputs like this [gist](https://gist.github.com/compiler-errors/d6f12fb30079feb1ad1d5f1ab39a3a8d). Should I put that back? 4. I also added spaces between traits, `impl A+B` -> `impl A + B`. I quite like this change, but is there a good reason to keep it like that? r? ``@estebank``
…ait, r=estebank Print associated types on opaque `impl Trait` types This PR generalizes rust-lang#91021, printing associated types for all opaque `impl Trait` types instead of just special-casing for future. before: ``` error[E0271]: type mismatch resolving `<impl Iterator as Iterator>::Item == u32` ``` after: ``` error[E0271]: type mismatch resolving `<impl Iterator<Item = usize> as Iterator>::Item == u32` ``` --- Questions: 1. I'm kinda lost in binders hell with this one. Is all of the `rebind`ing necessary? 2. Is there a map collection type that will give me a stable iteration order? Doesn't seem like TraitRef is Ord, so I can't just sort later.. 3. I removed the logic that suppresses printing generator projection types. It creates outputs like this [gist](https://gist.github.com/compiler-errors/d6f12fb30079feb1ad1d5f1ab39a3a8d). Should I put that back? 4. I also added spaces between traits, `impl A+B` -> `impl A + B`. I quite like this change, but is there a good reason to keep it like that? r? ```@estebank```
…askrgr Rollup of 6 pull requests Successful merges: - rust-lang#89359 (Various fixes for const_trait_impl) - rust-lang#90499 (Link with default MACOSX_DEPLOYMENT_TARGET if not otherwise specified.) - rust-lang#91096 (Print associated types on opaque `impl Trait` types) - rust-lang#91111 (Do not visit attributes in `ItemLowerer`.) - rust-lang#91162 (explain why CTFE/Miri perform truncation on shift offset) - rust-lang#91185 (Remove `-Z force-overflow-checks`) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
… r=jackh726 Restore `impl Future<Output = Type>` to async blocks I was sad when I undid some of the code I wrote in rust-lang#91096 in the PR rust-lang#95225, so I fixed it here to not print `[async output]`. This PR "manually" normalizes the associated type `<[generator] as Generator>::Return` type which appears very frequently in `impl Future` types that result from async block desugaring.
This PR generalizes #91021, printing associated types for all opaque
impl Trait
types instead of just special-casing for future.before:
after:
Questions:
rebind
ing necessary?impl A+B
->impl A + B
. I quite like this change, but is there a good reason to keep it like that?r? @estebank