-
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
[WIP] Rework impl-trait-in-bindings feature #55807
Conversation
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 |
423ec56
to
98cec39
Compare
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 |
☔ The latest upstream changes (presumably #55859) made this pull request unmergeable. Please resolve the merge conflicts. |
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.
The NLL type-checker code looks "close but not quite right". The coercion may be being inserted in the wrong place, though, as I describe in my comment.
UnsafeFnPointer, | ||
|
||
// "Hide" -- convert a value to an opaque type, i.e. `impl Trait`, | ||
// thus hiding information about its conrete type. |
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.
Nit: s/conrete/concrete/
let predicates = match ty.sty { | ||
ty::Opaque(def_id, substs) => { | ||
let bounds = tcx.predicates_of(def_id); | ||
let result = bounds.instantiate(tcx, substs); |
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.
use this function instead
fn normalize_and_prove_instantiated_predicates(
&mut self,
instantiated_predicates: ty::InstantiatedPredicates<'tcx>,
locations: Locations,
) {
(it's elsewhere in the file)
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 looks good.
// as is done in coercion.rs? | ||
result | ||
} | ||
_ => bug!(), |
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.
Will the opaque type always be at the top level? I imagine there might be something like
let x: (impl Debug, impl Debug) = (22, 44);
I think what we want to do here instead is to use instantiate_opaque_types
to replace the ty::Opaque
with type variables. This will give us back a type that we can unify with the type of the value being casted. It will also give us back the predicates to prove that you can prove using prove_predicates
as below.
fn coerce_hidden(&self, source: Ty<'tcx>, target: Ty<'tcx>) -> CoerceResult<'tcx> { | ||
debug!("coerce_hidden(source={:?}, target={:?})", source, target); | ||
|
||
let target_predicates = if let ty::Opaque(def_id, substs) = target.sty { |
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, I'm not sure if this is where I think this code should go or not. It depends on whether we want to support e.g. (impl Foo, impl Bar)
etc.
One way to go about this would be to look to see whether the type includes any ty::Opaque
for which this location is a defining use. I don't remember off the top of my head what the code here looks like, @oli-obk may be able to point us at the right place, else I can dig harder.
But we may want to -- for now, at least -- move this out of the "main coercion" path and instead up to the code that handles a let x: T = ...
statement. We would in that case look to see whether T
contains any impl Trait
statements, much as we do for a function return: if so, we would use instantiate_opaque_types
to create a type with fresh variables, and then coerce from the source type into that type. Then we'd take the user's type annotation and return that as the type for the underlying pattern. Something like that.
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 feel like this is very analogous to normalization. Ultimately, we'll probably want to be handling it in a "lazy fashion" somehow. Have to think about what that means I guess.
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.
The think that makes me nervous here:
Can this coercion code trigger at times when it shouldn't?
In particular, opaque types play this "dual role", and I'm worried we'll confuse it here.
Example:
fn foo() -> impl Debug { }
fn main() {
let x = if true {
foo() // return type will be a TyOpaque
} else {
22 // I think this can "coerce" to the type from the `then` arm
};
}
Here, I imagine we should get an error, but we might wind up going down this path and trying to add a Hide
annotation or something?
Triage; @alexreg Hello, have you been able to get back to this PR? |
@Aaronepower Working on it slowly... it's a tricky one. |
Ping from triage @alexreg any updates on this? you have some conflicts to deal with. |
@Dylan-DPC Been distracted by other PRs lately; I'll be back on this soon. :-) |
And #57807? |
Thanks for the PR @alexreg. Since you're distracted with other PRs, I'll close this one out for now; feel free to reopen once you have time to work on it. :) |
@Centril Sure. Indeed I am busy with others right now, but I'll be getting back to it soon (especially when @nikomatsakis gets time to collate his notes and our discussions on this subject). |
Fixes #54600.
Not nearly ready for merge yet; just putting up here for feedback.
r? @nikomatsakis