-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[Variadic Generics] require pack ident type within a pack expansion t… #63208
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
[Variadic Generics] require pack ident type within a pack expansion t… #63208
Conversation
Woohoo, thank you! One minor piece of initial feedback - there are quite a few formatting changes, which make it difficult to spot the functional changes. Could you please either apply the formatting changes in a separate commit or drop them from this PR? |
I suspect that clang-format has been ran for the whole file, you can use |
Yeah that was definitely not intentional, and I will figure out why it happened so I can stop it in the future, and revert that all here. Definitely none of that showed up locally when I did a confirming |
d7f41c8
to
8cd02bf
Compare
I figured out the over-eager clang-formatting and fixed it, though what caused the cause remains mysterious. |
bc6c647
to
9ab5def
Compare
lib/Sema/TypeCheckType.h
Outdated
@@ -76,6 +76,12 @@ enum class TypeResolutionFlags : uint16_t { | |||
/// Pack references are only allowed inside pack expansions | |||
/// and in generic requirements. | |||
AllowPackReferences = 1 << 11, | |||
|
|||
/// Whether this is a resolution based on a pack expansion. | |||
FromPackExpansion = 1 << 12, |
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 mentioned this offline, but I wonder if FromPackExpansion
and AllowPackReferences
can be one flag, as their uses seem to be very similar
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.
Almost same... maybeResolvePackExpansionType
(where the AllowPackReferences
flag is added) can be called from resolvePackExpansionType
(where the FromPackExpansion
flag is added) but also from resolveASTFunctionTypeParams
. AllowPackReferences
is also added in a few other places outside of TypeCheckType.cpp
So running the tests in pack-expansion-expressions.swift, I see cases where resolvePackReference
is reached and AllowPackReferences
is set but FromPackExpansion
is not. However in none of these cases is the new failure case logic in resolveDeclRefTypeRepr
any different, because in every case of the flag mismatch, either isParameterPack
and FromPackReference
are both true or both false (the failure case is only when isParameterPack
is true but FromPackReference
is false).
That all said, I don't at this point have the insight into the several other places where the AllowPackReferences
flag is added to know how they are reached and whether there could be a scenario where this new diagnostic could give a false negative?
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.
Hmmm I wonder if that code in resolveASTFunctionTypeParams
is now unnecessary / a remnant from when parameter packs used the same syntax as varargs parameters. I commented that code out and am running the tests now locally to see...
The other places where AllowPackReferences
is set are all during constraint generation when we see an each T
type repr inside an expression. All of those call-sites look like this:
// Add a PackElementOf constraint for 'each T' type reprs.
PackExpansionExpr *elementEnv = nullptr;
if (!PackElementEnvironments.empty()) {
options |= TypeResolutionFlags::AllowPackReferences;
elementEnv = PackElementEnvironments.back();
}
and !PackElementEnvironments.empty()
is a guarantee that the each
type repr appears inside of a PackExpansionExpr
, so I don't think these places can cause any false negatives.
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.
Oh! There's one other place AllowPackReferences
is set in RequirementRequest
because you can write each T
in a generic requirement without repeat
, e.g.
protocol P {}
func generic<each T>() where each T: P {}
...and I think we do want to diagnose something like where T: P
!
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.
Thank you @hborla for the further insights. I have examined and tested more and concluded that it will indeed be best to get rid of my new FromPackExpansion
flag and just rely on AllowPackReferences
.
I also found a couple of more tests that needed syntax fixing.
9ab5def
to
8f4216e
Compare
…o form a pack reference
1460fba
to
89e5648
Compare
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.
Looks great!
… tests, but also disable them due to triggering a constraints checker assertion
39579e2
to
e8361dd
Compare
@swift-ci Please smoke test |
@@ -77,3 +77,19 @@ func sameShapeDiagnostics<T..., U...>(t: repeat each T, u: repeat each U) { | |||
_ = repeat Array<(each T, each U)>() // expected-error {{pack expansion requires that 'U' and 'T' have the same shape}} | |||
_ = repeat (Array<each T>(), each u) // expected-error {{pack expansion requires that 'U' and 'T' have the same shape}} | |||
} | |||
|
|||
func returnPackExpansionType<T...>(_ t: repeat each T) -> repeat each T { // expected-error {{variadic expansion 'T' cannot appear outside of a function parameter list, function result, tuple element or generic argument list}} |
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 inaccurate. Is says an expansion cannot appear outside a function result, but syntactically the expansion is the function result.
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 "function result" should just be removed from the message. A previous experimental implementation of variadic generics that modeled packs as tuples (where this message was added) allowed returning a pack type T
, but the current design does not allow for that. I also think we should eliminate the phrase "variadic expansion". I can update this message in a separate PR.
…o form a pack reference