-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
typeck/type_of: let wfcheck handle generics in opaque types' substs. #70272
Conversation
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.
started reading but ran out of time. =) will return. initial comment.
for (idx, subst) in substs.iter().enumerate() { | ||
if let GenericArgKind::Type(ty) = subst.unpack() { | ||
|
||
let opaque_generics = self.tcx.generics_of(self.def_id); |
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.
Pre-existing, but this code is in dire need of some comments.
To start, can we add a comment explaining what is happening here -- I think it is this:
Examine the type parameters to the opaque type used in the defining use and make sure that (a) they are only generic parameters from the enclosing scope and (b) each generic parameter is used at most once. For example, given this function:
type Foo<A, B> = impl Debug;
fn f1<T, U>() -> Foo<T, U>
we would be iterating over the substs T, U
and checking that they are distinct. We would error for things like -> Foo<T, T>
or -> Foo<u32, U>
.
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.
wfcheck
is the primary checker and has a nice comment.
This is just a tombstone insurance policy. But I can try to document it if you want.
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'd still like a comment, even if only points over to the "primary comment"
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.
In fact, I think pointing out that this is "just" an insurance policy would be quite useful =)
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.
r=me with nits addressed (I think just a comment)
@@ -7,5 +7,23 @@ LL | | t | |||
LL | | } | |||
| |_^ | |||
|
|||
error: aborting due to previous error | |||
error: concrete type differs from previous defining opaque type use |
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 does seem like more confusing output than the old code...
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 difference is when the checks run and which "uses" (mentions, really) are considered "defining".
From the looks of the code, "defining" vs not is an unimplemented part of the feature.
At least now check::wfcheck
and type_of
are each more uniform and it should be easier to finish the feature, but I'd rather leave that to someone else.
@@ -4,13 +4,17 @@ error: at least one trait must be specified | |||
LL | type Cmp<T> = impl 'static; | |||
| ^^^^^^^^^^^^ | |||
|
|||
error: defining opaque type use does not fully define opaque type: generic parameter `T` is specified as concrete type `u32` | |||
--> $DIR/generic_nondefining_use.rs:10:1 | |||
error: non-defining opaque type use in defining scope |
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 error message seems pretty confusing to me. But I guess the old one was pretty bad too so I don't think it needs to block this PR...
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 used the error that used to be only emitted for lifetimes, also for types and consts.
I don't like either error but I didn't want to make a third variant of my own.
GenericArgKind::Lifetime(lt) => !matches!(lt, ty::ReStatic), | ||
GenericArgKind::Lifetime(lt) => { | ||
matches!(lt, ty::ReEarlyBound(_) | ty::ReFree(_)) | ||
} |
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 guess the other types just didn't happen in practice? Else it'd be nice to have a test.
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.
These are "exported" by the MIR borrowck (cc @matthewjasper) AFAICT, and that results in late-bound lifetimes (in the fn
signature, I presume) being ReFree
.
This list is minimal, as in I can't remove either ReEarlyBound
nor ReFree
without tests failing, and adding more would cause less errors (i.e. allowing buggy situations), not more.
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.
Actually, @matthewjasper, shouldn't ReFree
turn back into ReLateBound
? Although, I guess the actual concrete type is in terms of the type Foo<...> = impl Trait;
generics, so it's not affected by the substitutions back at the point Foo
is mentioned.
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 don't think that we currently ever go from a placeholder back to a bound region/type.
// HACK(eddyb) this check shouldn't be needed, as `wfcheck` | ||
// performs the same checks, in theory, but I've kept it here | ||
// using `delay_span_bug`, just in case `wfcheck` slips up. |
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.
@nikomatsakis Hang on, did you see this, or not? GitHub doesn't show it on your original comment, maybe I added it afterwards?
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 haven't pushed since, maybe you left the comment on a commit before I had added the comment?
e06d4c0
to
8ad149a
Compare
@bors r=nikomatsakis |
📌 Commit 8ad149a has been approved by |
☀️ Test successful - checks-azure |
I was working on #70164, and
type_of
's handling of opaque types seemed to be, by far, the trickiest use ofTy::walk
, but I believe it wasn't doing anything (see #57896 (comment) - I suspect, based on glancing at the PR discussion, that an early attempt was kept in, despite becoming just an overcomplicated way to do exactly the same as the previous simple type equality check).I would've loved to remove
ResolvedOpaqueTy
(keep theTy
and lose theSubsts
), but it looks like the MIR borrowck part of the process needs that now, so it would've been added anyway since #57896, even if that PR hadn't happened.In the process, I've moved the remaining substitution validation to
wfcheck
, which was already handling lifetimes, and kept onlydelay_span_bug
s intype_of
, as an insurance policy.I've added tests for lifetime and const cases, they seem to be checked correctly now.
(and more uniform than they were in #63063 (comment))
However, the quality of the errors is maybe a bit worse, and they don't trigger when there are other errors (not sure if this is due to compilation stop points or something more specific to one opaque type).
r? @nikomatsakis cc @matthewjasper @oli-obk @Aaron1011