Skip to content
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

Merged
merged 6 commits into from
Apr 4, 2020

Conversation

eddyb
Copy link
Member

@eddyb eddyb commented Mar 22, 2020

I was working on #70164, and type_of's handling of opaque types seemed to be, by far, the trickiest use of Ty::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 the Ty and lose the Substs), 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 only delay_span_bugs in type_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

Copy link
Contributor

@nikomatsakis nikomatsakis left a 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);
Copy link
Contributor

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>.

Copy link
Member Author

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.

Copy link
Contributor

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"

Copy link
Contributor

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 =)

@bors

This comment has been minimized.

Copy link
Contributor

@nikomatsakis nikomatsakis left a 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
Copy link
Contributor

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...

Copy link
Member Author

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
Copy link
Contributor

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...

Copy link
Member Author

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(_))
}
Copy link
Contributor

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.

Copy link
Member Author

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.

Copy link
Member Author

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.

Copy link
Contributor

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.

@nikomatsakis nikomatsakis added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Apr 3, 2020
Comment on lines +398 to +408
// 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.
Copy link
Member Author

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?

Copy link
Member Author

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?

@eddyb
Copy link
Member Author

eddyb commented Apr 4, 2020

@bors r=nikomatsakis

@bors
Copy link
Contributor

bors commented Apr 4, 2020

📌 Commit 8ad149a has been approved by nikomatsakis

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Apr 4, 2020
@bors
Copy link
Contributor

bors commented Apr 4, 2020

⌛ Testing commit 8ad149a with merge 49dc2f9...

@bors
Copy link
Contributor

bors commented Apr 4, 2020

☀️ Test successful - checks-azure
Approved by: nikomatsakis
Pushing 49dc2f9 to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Apr 4, 2020
@bors bors merged commit 49dc2f9 into rust-lang:master Apr 4, 2020
@eddyb eddyb deleted the type-of-impl-trait branch April 4, 2020 14:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
F-type_alias_impl_trait `#[feature(type_alias_impl_trait)]` merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Development

Successfully merging this pull request may close these issues.

6 participants