-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Plumb Through Parameterized Protocol Existentials #41743
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
Conversation
Add deep equality typing rules for P =~= Q, T == X, U == Y, V == Z, ... -------------------------------- P<T, U, V, ...> == Q<X, Y, Z, ...> Also add existential matching rules to discharge the constraints on parameterized protocols against concrete types. e.g. class C: P { typealias T = Int } func foo<T>(_ x: P<T>) {} foo(C()) Should cause T to unify against C.T = Int
Represent this in much the same way that collections do by creating an opaque value representing the source argument, and a conversion expression representing the destination argument.
The problem is that we currenly cannot represent the generic signature of values of type `any P<some P>`. This is because we wind up producing <Self where Self : P, Self.T == (some P)> What we'd like to do in the future is erase the errant (some P) with a fresh generic parameter and keep a substitution map on the side that records the opaque type constraint. Something like <Self, Opaque1 where Self : P, Opaque1 : P, Self.T == Opaque1> where Opaque1 == (some P)
054f47d
to
0aead28
Compare
@swift-ci smoke test |
@@ -635,6 +635,7 @@ Types | |||
type ::= protocol-list 'p' // existential type | |||
type ::= protocol-list superclass 'Xc' // existential type with superclass | |||
type ::= protocol-list 'Xl' // existential type with AnyObject | |||
type ::= protocol-list 'y' (type* '_')* type* retroactive-conformance* 'Xp' // parameterized protocol 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.
I would prefer a more general mangling that could accommodate arbitrary requirements in the future.
@@ -3253,6 +3259,22 @@ NodePointer Demangler::demangleSpecialType() { | |||
return createType(createWithChildren(Node::Kind::ExistentialMetatype, | |||
MTR, Type)); | |||
} | |||
case 'P': { | |||
NodePointer RetroactiveConformances; |
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.
What are the retroactive conformances here for? any P<some Q>
?
@@ -1445,7 +1445,7 @@ static const TypeInfo *createExistentialTypeInfo(IRGenModule &IGM, CanType T) { | |||
T = existential->getConstraintType()->getCanonicalType(); | |||
} | |||
llvm::StructType *type; | |||
if (isa<ProtocolType>(T)) | |||
if (isa<ProtocolType>(T) || isa<ParameterizedProtocolType>(T)) | |||
type = IGM.createNominalType(T); |
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.
Add a FIXME here or an assert, since this is wrong; the parametrized protocol type does not share metadata with the protocol type
@@ -1464,9 +1464,10 @@ class SubstFunctionTypePatternVisitor | |||
if (auto gp = handleTypeParameterInAbstractionPattern(pattern, t)) | |||
return gp; | |||
|
|||
assert(!pattern.getType()->hasTypeParameter() | |||
assert(pattern.getType()->isExistentialType() || |
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.
When is this violated?
|
||
// Use the requirements of any parameterized protocols to build out fake | ||
// argument conversions that can be used to infer opaque types. | ||
SmallVector<CollectionUpcastConversionExpr::ConversionPair, 4> argConversions; |
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.
Maybe CollectionUpcastConversionExpr::ConversionPair should be moved out?
Unblock most of the statics and the lowering for the static side of parameterized protocol existentials. Practically, this implements
any P<T>
forP
a parameterized protocol type (as in #41640). It also unblocksany P<some Q>
, though there's some representational issues that are not resolved in this PR - I will tackle them when opened existentials and their signatures are refactored to use a side substitution map.