@@ -328,7 +328,8 @@ struct ASTContext::Implementation {
328
328
CanGenericSignature SingleGenericParameterSignature;
329
329
330
330
// / The existential signature <T : P> for each P.
331
- llvm::DenseMap<CanType, CanGenericSignature> ExistentialSignatures;
331
+ llvm::DenseMap<std::pair<CanType, const DeclContext *>, CanGenericSignature>
332
+ ExistentialSignatures;
332
333
333
334
// / Overridden declarations.
334
335
llvm::DenseMap<const ValueDecl *, ArrayRef<ValueDecl *>> Overrides;
@@ -4421,6 +4422,12 @@ CanTypeWrapper<OpenedArchetypeType> OpenedArchetypeType::getNew(
4421
4422
GenericEnvironment *environment, Type interfaceType,
4422
4423
ArrayRef<ProtocolDecl *> conformsTo, Type superclass,
4423
4424
LayoutConstraint layout) {
4425
+ // FIXME: It'd be great if all of our callers could submit interface types.
4426
+ // But the constraint solver submits archetypes when trying to issue checks
4427
+ // against members of existential types. For now, we'll work around them by
4428
+ // forcing an interface type.
4429
+ // assert((!superclass || !superclass->hasArchetype())
4430
+ // && "superclass must be interface type");
4424
4431
auto arena = AllocationArena::Permanent;
4425
4432
ASTContext &ctx = interfaceType->getASTContext ();
4426
4433
void *mem = ctx.Allocate (
@@ -4434,16 +4441,21 @@ CanTypeWrapper<OpenedArchetypeType> OpenedArchetypeType::getNew(
4434
4441
environment, interfaceType, conformsTo, superclass, layout));
4435
4442
}
4436
4443
4437
- CanTypeWrapper<OpenedArchetypeType> OpenedArchetypeType::get (
4438
- CanType existential, Optional<UUID> knownID) {
4444
+ CanTypeWrapper<OpenedArchetypeType>
4445
+ OpenedArchetypeType::get (CanType existential, const DeclContext *useDC,
4446
+ Optional<UUID> knownID) {
4439
4447
Type interfaceType = GenericTypeParamType::get (
4440
- /* isTypeSequence=*/ false , 0 , 0 , existential->getASTContext ());
4441
- return get (existential, interfaceType, knownID);
4448
+ /* isTypeSequence=*/ false ,
4449
+ /* depth*/ useDC->getGenericContextDepth () + 1 , /* index*/ 0 ,
4450
+ existential->getASTContext ());
4451
+ return get (existential, interfaceType, useDC, knownID);
4442
4452
}
4443
4453
4444
4454
CanOpenedArchetypeType OpenedArchetypeType::get (CanType existential,
4445
4455
Type interfaceType,
4456
+ const DeclContext *useDC,
4446
4457
Optional<UUID> knownID) {
4458
+ assert (!interfaceType->hasArchetype () && " must be interface type" );
4447
4459
// FIXME: Opened archetypes can't be transformed because the
4448
4460
// the identity of the archetype has to be preserved. This
4449
4461
// means that simplifying an opened archetype in the constraint
@@ -4475,8 +4487,8 @@ CanOpenedArchetypeType OpenedArchetypeType::get(CanType existential,
4475
4487
}
4476
4488
4477
4489
// / Create a generic environment for this opened archetype.
4478
- auto genericEnv = GenericEnvironment::forOpenedExistential (
4479
- existential, *knownID);
4490
+ auto genericEnv =
4491
+ GenericEnvironment::forOpenedExistential ( existential, useDC , *knownID);
4480
4492
openedExistentialEnvironments[*knownID] = genericEnv;
4481
4493
4482
4494
// Map the interface type into that environment.
@@ -4485,22 +4497,24 @@ CanOpenedArchetypeType OpenedArchetypeType::get(CanType existential,
4485
4497
return CanOpenedArchetypeType (result);
4486
4498
}
4487
4499
4488
-
4489
- CanType OpenedArchetypeType::getAny (CanType existential, Type interfaceType ) {
4500
+ CanType OpenedArchetypeType::getAny (CanType existential, Type interfaceType,
4501
+ const DeclContext *useDC ) {
4490
4502
if (auto metatypeTy = existential->getAs <ExistentialMetatypeType>()) {
4491
4503
auto instanceTy =
4492
4504
metatypeTy->getExistentialInstanceType ()->getCanonicalType ();
4493
4505
return CanMetatypeType::get (
4494
- OpenedArchetypeType::getAny (instanceTy, interfaceType));
4506
+ OpenedArchetypeType::getAny (instanceTy, interfaceType, useDC ));
4495
4507
}
4496
4508
assert (existential->isExistentialType ());
4497
- return OpenedArchetypeType::get (existential, interfaceType);
4509
+ return OpenedArchetypeType::get (existential, interfaceType, useDC );
4498
4510
}
4499
4511
4500
- CanType OpenedArchetypeType::getAny (CanType existential) {
4512
+ CanType OpenedArchetypeType::getAny (CanType existential,
4513
+ const DeclContext *useDC) {
4501
4514
Type interfaceType = GenericTypeParamType::get (
4502
- /* isTypeSequence=*/ false , 0 , 0 , existential->getASTContext ());
4503
- return getAny (existential, interfaceType);
4515
+ /* isTypeSequence=*/ false , useDC->getGenericContextDepth () + 1 , 0 ,
4516
+ existential->getASTContext ());
4517
+ return getAny (existential, interfaceType, useDC);
4504
4518
}
4505
4519
4506
4520
void SubstitutionMap::Storage::Profile (
@@ -4655,12 +4669,23 @@ GenericEnvironment *GenericEnvironment::getIncomplete(
4655
4669
}
4656
4670
4657
4671
// / Create a new generic environment for an opened archetype.
4658
- GenericEnvironment *GenericEnvironment::forOpenedExistential (
4659
- Type existential, UUID uuid) {
4672
+ GenericEnvironment *
4673
+ GenericEnvironment::forOpenedExistential (Type existential,
4674
+ const DeclContext *useDC, UUID uuid) {
4660
4675
auto &ctx = existential->getASTContext ();
4661
- auto signature = ctx.getOpenedArchetypeSignature (existential);
4676
+ auto signature = ctx.getOpenedArchetypeSignature (existential, useDC);
4677
+
4678
+ SubstitutionMap subs;
4679
+ if (auto *useEnvironment = useDC->getGenericEnvironmentOfContext ()) {
4680
+ subs = useEnvironment->getForwardingSubstitutionMap ();
4681
+ }
4682
+ return GenericEnvironment::forOpenedExistential (existential, signature, uuid);
4683
+ }
4662
4684
4685
+ GenericEnvironment *GenericEnvironment::forOpenedExistential (
4686
+ Type existential, GenericSignature signature, UUID uuid) {
4663
4687
// Allocate and construct the new environment.
4688
+ auto &ctx = existential->getASTContext ();
4664
4689
unsigned numGenericParams = signature.getGenericParams ().size ();
4665
4690
size_t bytes = totalSizeToAlloc<OpaqueTypeDecl *, SubstitutionMap,
4666
4691
OpenedGenericEnvironmentData, Type>(
@@ -5166,38 +5191,47 @@ CanGenericSignature ASTContext::getSingleGenericParameterSignature() const {
5166
5191
return canonicalSig;
5167
5192
}
5168
5193
5169
- CanGenericSignature ASTContext::getOpenedArchetypeSignature (Type type) {
5194
+ CanGenericSignature
5195
+ ASTContext::getOpenedArchetypeSignature (Type type, const DeclContext *useDC) {
5170
5196
assert (type->isExistentialType ());
5197
+ assert (useDC && " Must have a working declaration context!" );
5198
+
5171
5199
if (auto existential = type->getAs <ExistentialType>())
5172
5200
type = existential->getConstraintType ();
5173
5201
5174
5202
const CanType constraint = type->getCanonicalType ();
5175
5203
assert (!constraint->hasTypeParameter () && " This only works with archetypes" );
5176
5204
5177
5205
// The opened archetype signature for a protocol type is identical
5178
- // to the protocol's own canonical generic signature.
5179
- if (const auto protoTy = dyn_cast<ProtocolType>(constraint)) {
5180
- return protoTy->getDecl ()->getGenericSignature ().getCanonicalSignature ();
5206
+ // to the protocol's own canonical generic signature if there aren't any
5207
+ // outer generic parameters to worry about.
5208
+ if (!useDC->isGenericContext ()) {
5209
+ if (const auto protoTy = dyn_cast<ProtocolType>(constraint)) {
5210
+ return protoTy->getDecl ()->getGenericSignature ().getCanonicalSignature ();
5211
+ }
5181
5212
}
5182
5213
5183
- auto found = getImpl ().ExistentialSignatures .find (constraint);
5214
+ // Otherwise we need to build a generic signature that captures any outer
5215
+ // generic parameters. This ensures that we keep e.g. generic superclass
5216
+ // existentials contained in a well-formed generic context.
5217
+ auto found = getImpl ().ExistentialSignatures .find ({constraint, useDC});
5184
5218
if (found != getImpl ().ExistentialSignatures .end ())
5185
5219
return found->second ;
5186
5220
5221
+ auto depth = useDC->getGenericContextDepth () + 1 ;
5187
5222
auto genericParam =
5188
5223
GenericTypeParamType::get (/* type sequence*/ false ,
5189
- /* depth*/ 0 , /* index*/ 0 , *this );
5224
+ /* depth*/ depth , /* index*/ 0 , *this );
5190
5225
Requirement requirement (RequirementKind::Conformance, genericParam,
5191
5226
constraint);
5192
- auto genericSig = buildGenericSignature (*this ,
5193
- GenericSignature (),
5194
- {genericParam},
5195
- {requirement});
5227
+ auto genericSig = buildGenericSignature (
5228
+ *this , useDC->getGenericSignatureOfContext ().getCanonicalSignature (),
5229
+ {genericParam}, {requirement});
5196
5230
5197
5231
CanGenericSignature canGenericSig (genericSig);
5198
5232
5199
5233
auto result = getImpl ().ExistentialSignatures .insert (
5200
- std::make_pair (constraint, canGenericSig));
5234
+ std::make_pair (std::make_pair ( constraint, useDC) , canGenericSig));
5201
5235
assert (result.second );
5202
5236
(void ) result;
5203
5237
0 commit comments