-
Notifications
You must be signed in to change notification settings - Fork 13.1k
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
Fix opaque types resulting from projections in function signature #66178
Conversation
r? @davidtwco (rust_highfive has picked a reviewer for you, use r? to override) |
This comment has been minimized.
This comment has been minimized.
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.
LGTM, might want to have someone else check over it though.
r? @varkor |
28d8354
to
a6094f4
Compare
This comment has been minimized.
This comment has been minimized.
This PR ended up fixing (!) the |
@@ -1,4 +1,4 @@ | |||
error: defining opaque type use does not fully define opaque type | |||
error: defining opaque type use does not fully define opaque type: generic parameter `V` is specified as concrete type `<T as TraitWithAssoc>::Assoc` |
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.
We could improve this error. (Also, I think define
should be determine
.) Maybe with a help message like:
uses of an opaque type must fully determine it, but here `Foo` is only determined for `V = <T as TraitWithAssoc>::Assoc`
It took me a couple of tries to work out what the error message was saying before.
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.
@varkor: Your proposed error message is backward - V
is the parameter that is not determined (because it's a concrete type instead of a generic parameter).
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.
While I think there's room to improve this error, this modification provides strictly more information. I think further improvements should go in another PR, since this PR is really about changing when error messages occur, not the actual contente.
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.
Okay, but let's open an issue for improving 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.
Opened #66723.
Just to clarify, normalisation is replacing generic parameters with inference variables, and then this pass is doing the opposite? Can we not just avoid replacing such generic parameters in the first place? |
@varkor: Not easily. These inference variables are created when we select the matching impl, which happens behind several layers of indrection (normalize -> project -> select). As far I as can tell, this is the only place where we don't want the usual behavior of creating new inference variables. I think it makes more sense to fix it up here, rather than adding another flag to |
Is there a possibility that there were previously some inference variables that did not come from replaced generic parameters, but we're now going to replace with new generic parameters? |
@varkor: This PR only replaces inference variables that occur directly in the substs of an opaque type, which by definition corresponds to a generic parameter. |
@Aaron1011 @rust-lang/compiler-contributors For future reference, when a PR implements a particular (or more) feature, I would love it if you could ensure if the appropriate |
Okay, this seems reasonable. Could you add some of the explanation you gave in your comments here to the comment in the code, just to give more context to someone coming across it without the background? Then I'm happy to go with this after the remaining comments have been addressed. |
66b4fe2
to
d6f372d
Compare
@varkor: I've added some of my explanation to the comments, and added a worked out example. This should now be ready to merge. |
📌 Commit df3f338 has been approved by |
⌛ Testing commit df3f338 with merge eef352e0f85460c42ae9bf53b0a9f4070c054634... |
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
💔 Test failed - checks-azure |
@varkor: This looks like a spurious failure |
@bors retry |
⌛ Testing commit df3f338 with merge 52ab26279852c6ee751cbdc0cd820a0ab2dc5b34... |
Your PR failed (pretty log, raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem. Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
💔 Test failed - checks-azure |
@varkor: Another spurious failure |
@bors retry |
Fix opaque types resulting from projections in function signature When we normalize the types in a function signature, we may end up resolving a projection to an opaque type (e.g. `Self::MyType` when we have `type MyType = impl SomeTrait`). When the projection is resolved, we will instantiate the generic parameters into fresh inference variables. While we do want to normalize projections to opaque types, we don't want to replace the explicit generic parameters (e.g. `T` in `impl MyTrait<T>`) with inference variables. We want the opaque type in the function signature to be eligible to be a defining use of that opaque type - adding inference variables prevents this, since the opaque type substs now appears to refer to some specific type, rather than a generic type. To resolve this issue, we inspect the opaque types in the function signature after normalization. Any inference variables in the substs are replaced with the corresponding generic parameter in the identity substs (e.g. `T` in `impl MyTrait<T>`). Note that normalization is the only way that we can end up with inference variables in opaque substs in a function signature - users have no way of getting inference variables into a function signature. Note that all of this refers to the opaque type (ty::Opaque) and its subst - *not* to the underlying type. Fixes #59342
☀️ Test successful - checks-azure |
When we normalize the types in a function signature, we may end up
resolving a projection to an opaque type (e.g.
Self::MyType
whenwe have
type MyType = impl SomeTrait
). When the projection isresolved, we will instantiate the generic parameters into fresh
inference variables.
While we do want to normalize projections to opaque types, we don't want
to replace the explicit generic parameters (e.g.
T
inimpl MyTrait<T>
) with inference variables. We want the opaque type in thefunction signature to be eligible to be a defining use of that opaque
type - adding inference variables prevents this, since the opaque type
substs now appears to refer to some specific type, rather than a generic
type.
To resolve this issue, we inspect the opaque types in the function
signature after normalization. Any inference variables in the substs are
replaced with the corresponding generic parameter in the identity substs
(e.g.
T
inimpl MyTrait<T>
). Note that normalization is the only waythat we can end up with inference variables in opaque substs in a
function signature - users have no way of getting inference variables
into a function signature.
Note that all of this refers to the opaque type (ty::Opaque) and its
subst - not to the underlying type.
Fixes #59342