@@ -414,7 +414,8 @@ struct ASTContext::Implementation {
414
414
llvm::FoldingSet<BoundGenericType> BoundGenericTypes;
415
415
llvm::FoldingSet<ProtocolCompositionType> ProtocolCompositionTypes;
416
416
llvm::FoldingSet<LayoutConstraintInfo> LayoutConstraints;
417
- llvm::FoldingSet<OpaqueTypeArchetypeType> OpaqueArchetypes;
417
+ llvm::DenseMap<std::pair<OpaqueTypeDecl *, SubstitutionMap>,
418
+ GenericEnvironment *> OpaqueArchetypeEnvironments;
418
419
419
420
// / The set of function types.
420
421
llvm::FoldingSet<FunctionType> FunctionTypes;
@@ -4280,77 +4281,62 @@ DependentMemberType *DependentMemberType::get(Type base,
4280
4281
return known;
4281
4282
}
4282
4283
4283
- OpaqueTypeArchetypeType *
4284
- OpaqueTypeArchetypeType::get (OpaqueTypeDecl *Decl, unsigned ordinal,
4285
- SubstitutionMap Substitutions) {
4286
- auto opaqueParamType = Decl->getOpaqueGenericParams ()[ordinal];
4287
-
4288
- // TODO: We could attempt to preserve type sugar in the substitution map.
4289
- // Currently archetypes are assumed to be always canonical in many places,
4290
- // though, so doing so would require fixing those places.
4291
- Substitutions = Substitutions.getCanonical ();
4292
-
4293
- llvm::FoldingSetNodeID id;
4294
- Profile (id, Decl, ordinal, Substitutions);
4295
-
4296
- auto &ctx = Decl->getASTContext ();
4297
-
4284
+ // / Compute the recursive type properties of an opaque type archetype.
4285
+ static RecursiveTypeProperties getOpaqueTypeArchetypeProperties (
4286
+ SubstitutionMap subs) {
4298
4287
// An opaque type isn't contextually dependent like other archetypes, so
4299
4288
// by itself, it doesn't impose the "Has Archetype" recursive property,
4300
4289
// but the substituted types might. A disjoint "Has Opaque Archetype" tracks
4301
4290
// the presence of opaque archetypes.
4302
4291
RecursiveTypeProperties properties =
4303
4292
RecursiveTypeProperties::HasOpaqueArchetype;
4304
- for (auto type : Substitutions .getReplacementTypes ()) {
4293
+ for (auto type : subs .getReplacementTypes ()) {
4305
4294
properties |= type->getRecursiveProperties ();
4306
4295
}
4307
-
4296
+ return properties;
4297
+ }
4298
+
4299
+ OpaqueTypeArchetypeType *OpaqueTypeArchetypeType::getNew (
4300
+ GenericEnvironment *environment, Type interfaceType,
4301
+ ArrayRef<ProtocolDecl *> conformsTo, Type superclass,
4302
+ LayoutConstraint layout) {
4303
+ auto properties = getOpaqueTypeArchetypeProperties (
4304
+ environment->getOpaqueSubstitutions ());
4308
4305
auto arena = getArena (properties);
4309
-
4310
- llvm::FoldingSet<OpaqueTypeArchetypeType> &set
4311
- = ctx.getImpl ().getArena (arena).OpaqueArchetypes ;
4312
-
4313
- {
4314
- void *insertPos; // Discarded because the work below may invalidate the
4315
- // insertion point inside the folding set
4316
- if (auto existing = set.FindNodeOrInsertPos (id, insertPos)) {
4317
- return existing;
4318
- }
4319
- }
4320
-
4321
- auto reqs = Decl->getOpaqueInterfaceGenericSignature ()
4322
- ->getLocalRequirements (opaqueParamType);
4323
- auto superclass = reqs.superclass ;
4324
- #if !DO_IT_CORRECTLY
4325
- // Ad-hoc substitute the generic parameters of the superclass.
4326
- // If we correctly applied the substitutions to the generic signature
4327
- // constraints above, this would be unnecessary.
4328
- if (superclass && superclass->hasTypeParameter ()) {
4329
- superclass = superclass.subst (Substitutions);
4330
- }
4331
- #endif
4306
+ auto size = OpaqueTypeArchetypeType::totalSizeToAlloc<
4307
+ ProtocolDecl *, Type, LayoutConstraint>(
4308
+ conformsTo.size (), superclass ? 1 : 0 , layout ? 1 : 0 );
4309
+ ASTContext &ctx = interfaceType->getASTContext ();
4310
+ auto mem = ctx.Allocate (size, alignof (OpaqueTypeArchetypeType), arena);
4311
+ return ::new (mem)
4312
+ OpaqueTypeArchetypeType (environment, properties, interfaceType,
4313
+ conformsTo, superclass, layout);
4314
+ }
4315
+
4316
+ Type OpaqueTypeArchetypeType::get (
4317
+ OpaqueTypeDecl *Decl, unsigned ordinal, SubstitutionMap Substitutions) {
4318
+ // TODO: We could attempt to preserve type sugar in the substitution map.
4319
+ // Currently archetypes are assumed to be always canonical in many places,
4320
+ // though, so doing so would require fixing those places.
4321
+ Substitutions = Substitutions.getCanonical ();
4332
4322
4333
- auto mem = ctx.Allocate (
4334
- OpaqueTypeArchetypeType::totalSizeToAlloc<ProtocolDecl *, Type, LayoutConstraint>(
4335
- reqs.protos .size (), superclass ? 1 : 0 , reqs.layout ? 1 : 0 ),
4336
- alignof (OpaqueTypeArchetypeType),
4337
- arena);
4323
+ auto &ctx = Decl->getASTContext ();
4338
4324
4339
- auto newOpaque = ::new (mem)
4340
- OpaqueTypeArchetypeType (Decl, Substitutions, properties, opaqueParamType,
4341
- reqs.protos , superclass, reqs.layout );
4325
+ // Look for an opaque archetype environment in the appropriate arena.
4326
+ auto properties = getOpaqueTypeArchetypeProperties (Substitutions);
4327
+ auto arena = getArena (properties);
4328
+ auto &environments
4329
+ = ctx.getImpl ().getArena (arena).OpaqueArchetypeEnvironments ;
4330
+ GenericEnvironment *env = environments[{Decl, Substitutions}];
4342
4331
4343
- // Look up the insertion point in the folding set again in case something
4344
- // invalidated it above.
4345
- {
4346
- void *insertPos;
4347
- auto existing = set.FindNodeOrInsertPos (id, insertPos);
4348
- (void )existing;
4349
- assert (!existing && " race to create opaque archetype?!" );
4350
- set.InsertNode (newOpaque, insertPos);
4332
+ // Create the environment if it's missing.
4333
+ if (!env) {
4334
+ env = GenericEnvironment::forOpaqueType (Decl, Substitutions, arena);
4335
+ environments[{Decl, Substitutions}] = env;
4351
4336
}
4352
4337
4353
- return newOpaque;
4338
+ auto opaqueParamType = Decl->getOpaqueGenericParams ()[ordinal];
4339
+ return env->getOrCreateArchetypeFromInterfaceType (opaqueParamType);
4354
4340
}
4355
4341
4356
4342
CanOpenedArchetypeType OpenedArchetypeType::get (Type existential,
@@ -4411,15 +4397,11 @@ GenericEnvironment *OpenedArchetypeType::getGenericEnvironment() const {
4411
4397
if (Environment)
4412
4398
return Environment;
4413
4399
4414
- auto thisType = Type ( const_cast <OpenedArchetypeType*>(this ) );
4400
+ auto thisType = const_cast <OpenedArchetypeType*>(this );
4415
4401
auto &ctx = thisType->getASTContext ();
4416
4402
// Create a generic environment to represent the opened type.
4417
4403
auto signature = ctx.getOpenedArchetypeSignature (Opened);
4418
- auto *env = GenericEnvironment::getIncomplete (signature);
4419
- env->addMapping (signature.getGenericParams ().front ().getPointer (), thisType);
4420
- Environment = env;
4421
-
4422
- return env;
4404
+ return GenericEnvironment::forOpenedExistential (signature, thisType);
4423
4405
}
4424
4406
4425
4407
CanType OpenedArchetypeType::getAny (Type existential) {
@@ -4575,9 +4557,43 @@ GenericEnvironment *GenericEnvironment::getIncomplete(
4575
4557
4576
4558
// Allocate and construct the new environment.
4577
4559
unsigned numGenericParams = signature.getGenericParams ().size ();
4578
- size_t bytes = totalSizeToAlloc<Type>(numGenericParams);
4560
+ size_t bytes = totalSizeToAlloc<OpaqueTypeDecl *, SubstitutionMap, Type>(
4561
+ 0 , 0 , numGenericParams);
4562
+ void *mem = ctx.Allocate (bytes, alignof (GenericEnvironment));
4563
+ return new (mem) GenericEnvironment (signature, Kind::Normal);
4564
+ }
4565
+
4566
+ // / Create a new generic environment for an opened archetype.
4567
+ GenericEnvironment *GenericEnvironment::forOpenedExistential (
4568
+ GenericSignature signature, const OpenedArchetypeType *type) {
4569
+ auto &ctx = signature->getASTContext ();
4570
+
4571
+ // Allocate and construct the new environment.
4572
+ unsigned numGenericParams = signature.getGenericParams ().size ();
4573
+ size_t bytes = totalSizeToAlloc<OpaqueTypeDecl *, SubstitutionMap, Type>(
4574
+ 0 , 0 , numGenericParams);
4579
4575
void *mem = ctx.Allocate (bytes, alignof (GenericEnvironment));
4580
- return new (mem) GenericEnvironment (signature);
4576
+ auto env = new (mem) GenericEnvironment (signature, Kind::OpenedExistential);
4577
+ env->addMapping (
4578
+ signature.getGenericParams ().front (),
4579
+ Type (const_cast <OpenedArchetypeType *>(type)));
4580
+ return env;
4581
+ }
4582
+
4583
+ // / Create a new generic environment for an opaque type with the given set of
4584
+ // / outer substitutions.
4585
+ GenericEnvironment *GenericEnvironment::forOpaqueType (
4586
+ OpaqueTypeDecl *opaque, SubstitutionMap subs, AllocationArena arena) {
4587
+ auto &ctx = opaque->getASTContext ();
4588
+
4589
+ // Allocate and construct the new environment.
4590
+ auto signature = opaque->getOpaqueInterfaceGenericSignature ();
4591
+ unsigned numGenericParams = signature.getGenericParams ().size ();
4592
+ size_t bytes = totalSizeToAlloc<OpaqueTypeDecl *, SubstitutionMap, Type>(
4593
+ 1 , 1 , numGenericParams);
4594
+ void *mem = ctx.Allocate (bytes, alignof (GenericEnvironment), arena);
4595
+ auto env = new (mem) GenericEnvironment (GenericSignature (), opaque, subs);
4596
+ return env;
4581
4597
}
4582
4598
4583
4599
void DeclName::CompoundDeclName::Profile (llvm::FoldingSetNodeID &id,
0 commit comments