@@ -323,6 +323,7 @@ FOR_KNOWN_FOUNDATION_TYPES(CACHE_FOUNDATION_DECL)
323
323
llvm::FoldingSet<BoundGenericType> BoundGenericTypes;
324
324
llvm::FoldingSet<ProtocolCompositionType> ProtocolCompositionTypes;
325
325
llvm::FoldingSet<LayoutConstraintInfo> LayoutConstraints;
326
+ llvm::FoldingSet<OpaqueTypeArchetypeType> OpaqueArchetypes;
326
327
327
328
// / The set of function types.
328
329
llvm::FoldingSet<FunctionType> FunctionTypes;
@@ -4177,6 +4178,132 @@ DependentMemberType *DependentMemberType::get(Type base,
4177
4178
return known;
4178
4179
}
4179
4180
4181
+ OpaqueTypeArchetypeType *
4182
+ OpaqueTypeArchetypeType::get (OpaqueTypeDecl *Decl,
4183
+ SubstitutionMap Substitutions) {
4184
+ // TODO: We could attempt to preserve type sugar in the substitution map.
4185
+ Substitutions = Substitutions.getCanonical ();
4186
+
4187
+ // TODO: Eventually an opaque archetype ought to be arbitrarily substitutable
4188
+ // into any generic environment. However, there isn't currently a good way to
4189
+ // do this with GenericSignatureBuilder; in a situation like this:
4190
+ //
4191
+ // __opaque_type Foo<t_0_0: P>: Q // internal signature <t_0_0: P, t_1_0: Q>
4192
+ //
4193
+ // func bar<t_0_0, t_0_1, t_0_2: P>() -> Foo<t_0_2>
4194
+ //
4195
+ // we'd want to feed the GSB constraints to form:
4196
+ //
4197
+ // <t_0_0: P, t_1_0: Q where t_0_0 == t_0_2>
4198
+ //
4199
+ // even though t_0_2 isn't *in* this generic signature; it represents a type
4200
+ // bound elsewhere from some other generic context. If we knew the generic
4201
+ // environment `t_0_2` came from, then maybe we could map it into that context,
4202
+ // but currently we have no way to know that with certainty.
4203
+ //
4204
+ // For now, opaque types cannot propagate across decls; every declaration
4205
+ // with an opaque type has a unique opaque decl. Therefore, the only
4206
+ // expressions involving opaque types ought to be contextualized inside
4207
+ // function bodies, and the only time we need an opaque interface type should
4208
+ // be for the opaque decl itself and the originating decl with the opaque
4209
+ // result type, in which case the interface type mapping is identity and
4210
+ // this problem can be temporarily avoided.
4211
+ #ifndef NDEBUG
4212
+ for (unsigned i : indices (Substitutions.getReplacementTypes ())) {
4213
+ auto replacement = Substitutions.getReplacementTypes ()[i];
4214
+
4215
+ if (!replacement->hasTypeParameter ())
4216
+ continue ;
4217
+
4218
+ auto replacementParam = replacement->getAs <GenericTypeParamType>();
4219
+ if (!replacementParam)
4220
+ llvm_unreachable (" opaque types cannot currently be parameterized by non-identity type parameter mappings" );
4221
+
4222
+ assert (i == Decl->getGenericSignature ()->getGenericParamOrdinal (replacementParam)
4223
+ && " opaque types cannot currently be parameterized by non-identity type parameter mappings" );
4224
+ }
4225
+ #endif
4226
+
4227
+ llvm::FoldingSetNodeID id;
4228
+ Profile (id, Decl, Substitutions);
4229
+
4230
+ auto &ctx = Decl->getASTContext ();
4231
+
4232
+ // An opaque type isn't contextually dependent like other archetypes, so
4233
+ // by itself, it doesn't impose the "Has Archetype" recursive property,
4234
+ // but the substituted types might.
4235
+ RecursiveTypeProperties properties = {};
4236
+ for (auto type : Substitutions.getReplacementTypes ()) {
4237
+ properties |= type->getRecursiveProperties ();
4238
+ }
4239
+
4240
+ auto arena = getArena (properties);
4241
+
4242
+ llvm::FoldingSet<OpaqueTypeArchetypeType> &set
4243
+ = ctx.getImpl ().getArena (arena).OpaqueArchetypes ;
4244
+
4245
+ {
4246
+ void *insertPos; // Discarded because the work below may invalidate the
4247
+ // insertion point inside the folding set
4248
+ if (auto existing = set.FindNodeOrInsertPos (id, insertPos)) {
4249
+ return existing;
4250
+ }
4251
+ }
4252
+
4253
+ // Create a new opaque archetype.
4254
+ // It lives in an environment in which the interface generic arguments of the
4255
+ // decl have all been same-type-bound to the arguments from our substitution
4256
+ // map.
4257
+ GenericSignatureBuilder builder (ctx);
4258
+ builder.addGenericSignature (Decl->getOpaqueInterfaceGenericSignature ());
4259
+ // Same-type-constrain the arguments in the outer signature to their
4260
+ // replacements in the substitution map.
4261
+ if (auto outerSig = Decl->getGenericSignature ()) {
4262
+ for (auto outerParam : outerSig->getGenericParams ()) {
4263
+ auto boundType = Type (outerParam).subst (Substitutions);
4264
+ builder.addSameTypeRequirement (Type (outerParam), boundType,
4265
+ GenericSignatureBuilder::FloatingRequirementSource::forAbstract (),
4266
+ GenericSignatureBuilder::UnresolvedHandlingKind::GenerateConstraints,
4267
+ [](Type, Type) { llvm_unreachable (" error?" ); });
4268
+ }
4269
+ }
4270
+
4271
+ auto signature = std::move (builder)
4272
+ .computeGenericSignature (SourceLoc ());
4273
+
4274
+ auto opaqueInterfaceTy = Decl->getUnderlyingInterfaceType ();
4275
+ auto layout = signature->getLayoutConstraint (opaqueInterfaceTy);
4276
+ auto superclass = signature->getSuperclassBound (opaqueInterfaceTy);
4277
+ SmallVector<ProtocolDecl*, 4 > protos;
4278
+ for (auto proto : signature->getConformsTo (opaqueInterfaceTy)) {
4279
+ protos.push_back (proto);
4280
+ }
4281
+
4282
+ auto mem = ctx.Allocate (
4283
+ OpaqueTypeArchetypeType::totalSizeToAlloc<ProtocolDecl *, Type, LayoutConstraint>(
4284
+ protos.size (), superclass ? 1 : 0 , layout ? 1 : 0 ),
4285
+ alignof (OpaqueTypeArchetypeType),
4286
+ arena);
4287
+
4288
+ auto newOpaque = ::new (mem) OpaqueTypeArchetypeType (Decl, Substitutions,
4289
+ properties,
4290
+ signature,
4291
+ opaqueInterfaceTy,
4292
+ protos, superclass, layout);
4293
+
4294
+ // Look up the insertion point in the folding set again in case something
4295
+ // invalidated it above.
4296
+ {
4297
+ void *insertPos;
4298
+ auto existing = set.FindNodeOrInsertPos (id, insertPos);
4299
+ (void )existing;
4300
+ assert (!existing && " race to create opaque archetype?!" );
4301
+ set.InsertNode (newOpaque, insertPos);
4302
+ }
4303
+
4304
+ return newOpaque;
4305
+ }
4306
+
4180
4307
CanOpenedArchetypeType OpenedArchetypeType::get (Type existential,
4181
4308
Optional<UUID> knownID) {
4182
4309
auto &ctx = existential->getASTContext ();
0 commit comments