Skip to content

Commit dd2b51d

Browse files
committed
Add an OpaqueTypeArchetypeType subclass.
1 parent 71912bb commit dd2b51d

17 files changed

+474
-36
lines changed

include/swift/AST/GenericSignature.h

+4
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,10 @@ class alignas(1 << TypeAlignInBits) GenericSignature final
307307
/// <t_0_0, t_0_1, t_1_0>
308308
/// then this will return 0 for t_0_0, 1 for t_0_1, and 2 for t_1_0.
309309
unsigned getGenericParamOrdinal(GenericTypeParamType *param);
310+
311+
/// Get a substitution map that maps all of the generic signature's
312+
/// generic parameters to themselves.
313+
SubstitutionMap getIdentitySubstitutionMap() const;
310314

311315
static void Profile(llvm::FoldingSetNodeID &ID,
312316
TypeArrayView<GenericTypeParamType> genericParams,

include/swift/AST/TypeNodes.def

+1
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ TYPE(DynamicSelf, Type)
133133
ABSTRACT_TYPE(Substitutable, Type)
134134
ABSTRACT_TYPE(Archetype, SubstitutableType)
135135
ALWAYS_CANONICAL_TYPE(PrimaryArchetype, ArchetypeType)
136+
ALWAYS_CANONICAL_TYPE(OpaqueTypeArchetype, ArchetypeType)
136137
ALWAYS_CANONICAL_TYPE(OpenedArchetype, ArchetypeType)
137138
ALWAYS_CANONICAL_TYPE(NestedArchetype, ArchetypeType)
138139
TYPE_RANGE(Archetype, PrimaryArchetype, NestedArchetype)

include/swift/AST/Types.h

+64
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,10 @@ namespace swift {
5353
class GenericTypeParamType;
5454
class GenericParamList;
5555
class GenericSignature;
56+
class GenericSignatureBuilder;
5657
class Identifier;
5758
class InOutType;
59+
class OpaqueTypeDecl;
5860
class OpenedArchetypeType;
5961
enum class ReferenceCounting : uint8_t;
6062
enum class ResilienceExpansion : unsigned;
@@ -4728,6 +4730,65 @@ class PrimaryArchetypeType final : public ArchetypeType,
47284730
BEGIN_CAN_TYPE_WRAPPER(PrimaryArchetypeType, ArchetypeType)
47294731
END_CAN_TYPE_WRAPPER(PrimaryArchetypeType, ArchetypeType)
47304732

4733+
/// An archetype that represents an opaque type.
4734+
class OpaqueTypeArchetypeType final : public ArchetypeType,
4735+
public llvm::FoldingSetNode,
4736+
private ArchetypeTrailingObjects<OpaqueTypeArchetypeType>
4737+
{
4738+
friend TrailingObjects;
4739+
friend ArchetypeType;
4740+
friend GenericSignatureBuilder;
4741+
4742+
/// The declaration that defines the opaque type.
4743+
OpaqueTypeDecl *OpaqueDecl;
4744+
/// The substitutions into the interface signature of the opaque type.
4745+
SubstitutionMap Substitutions;
4746+
4747+
/// The generic signature used to build out this archetype, and its
4748+
/// nested archetypes.
4749+
GenericSignature *BoundSignature;
4750+
4751+
public:
4752+
/// Get an opaque archetype representing the underlying type of the given
4753+
/// opaque type decl.
4754+
static OpaqueTypeArchetypeType *
4755+
get(OpaqueTypeDecl *Decl,
4756+
SubstitutionMap Substitutions);
4757+
4758+
OpaqueTypeDecl *getOpaqueDecl() const {
4759+
return OpaqueDecl;
4760+
}
4761+
SubstitutionMap getSubstitutions() const {
4762+
return Substitutions;
4763+
}
4764+
4765+
/// Get the underlying type of the opaque type, if it's known.
4766+
Type getUnderlyingType() const;
4767+
4768+
static bool classof(const TypeBase *T) {
4769+
return T->getKind() == TypeKind::OpaqueTypeArchetype;
4770+
}
4771+
4772+
static void Profile(llvm::FoldingSetNodeID &ID,
4773+
OpaqueTypeDecl *OpaqueDecl,
4774+
SubstitutionMap Substitutions);
4775+
4776+
void Profile(llvm::FoldingSetNodeID &ID) {
4777+
Profile(ID, getOpaqueDecl(), getSubstitutions());
4778+
};
4779+
4780+
private:
4781+
OpaqueTypeArchetypeType(OpaqueTypeDecl *OpaqueDecl,
4782+
SubstitutionMap Substitutions,
4783+
RecursiveTypeProperties Props,
4784+
GenericSignature *BoundSignature,
4785+
Type InterfaceType,
4786+
ArrayRef<ProtocolDecl*> ConformsTo,
4787+
Type Superclass, LayoutConstraint Layout);
4788+
};
4789+
BEGIN_CAN_TYPE_WRAPPER(OpaqueTypeArchetypeType, ArchetypeType)
4790+
END_CAN_TYPE_WRAPPER(OpaqueTypeArchetypeType, ArchetypeType)
4791+
47314792
/// An archetype that represents the dynamic type of an opened existential.
47324793
class OpenedArchetypeType final : public ArchetypeType,
47334794
private ArchetypeTrailingObjects<OpenedArchetypeType>
@@ -4834,6 +4895,9 @@ const Type *ArchetypeType::getSubclassTrailingObjects() const {
48344895
if (auto contextTy = dyn_cast<PrimaryArchetypeType>(this)) {
48354896
return contextTy->getTrailingObjects<Type>();
48364897
}
4898+
if (auto opaqueTy = dyn_cast<OpaqueTypeArchetypeType>(this)) {
4899+
return opaqueTy->getTrailingObjects<Type>();
4900+
}
48374901
if (auto openedTy = dyn_cast<OpenedArchetypeType>(this)) {
48384902
return openedTy->getTrailingObjects<Type>();
48394903
}

lib/AST/ASTContext.cpp

+127
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ FOR_KNOWN_FOUNDATION_TYPES(CACHE_FOUNDATION_DECL)
323323
llvm::FoldingSet<BoundGenericType> BoundGenericTypes;
324324
llvm::FoldingSet<ProtocolCompositionType> ProtocolCompositionTypes;
325325
llvm::FoldingSet<LayoutConstraintInfo> LayoutConstraints;
326+
llvm::FoldingSet<OpaqueTypeArchetypeType> OpaqueArchetypes;
326327

327328
/// The set of function types.
328329
llvm::FoldingSet<FunctionType> FunctionTypes;
@@ -4177,6 +4178,132 @@ DependentMemberType *DependentMemberType::get(Type base,
41774178
return known;
41784179
}
41794180

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+
41804307
CanOpenedArchetypeType OpenedArchetypeType::get(Type existential,
41814308
Optional<UUID> knownID) {
41824309
auto &ctx = existential->getASTContext();

lib/AST/ASTDumper.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -3460,6 +3460,20 @@ namespace {
34603460
printArchetypeNestedTypes(T);
34613461
PrintWithColorRAII(OS, ParenthesisColor) << ')';
34623462
}
3463+
void visitOpaqueTypeArchetypeType(OpaqueTypeArchetypeType *T,
3464+
StringRef label) {
3465+
printArchetypeCommon(T, "opaque_type", label);
3466+
printField("decl", T->getOpaqueDecl()->getNamingDecl()->printRef());
3467+
if (!T->getSubstitutions().empty()) {
3468+
OS << '\n';
3469+
SmallPtrSet<const ProtocolConformance *, 4> Dumped;
3470+
dumpSubstitutionMapRec(T->getSubstitutions(), OS,
3471+
SubstitutionMap::DumpStyle::Full,
3472+
Indent + 2, Dumped);
3473+
}
3474+
printArchetypeNestedTypes(T);
3475+
PrintWithColorRAII(OS, ParenthesisColor) << ')';
3476+
}
34633477

34643478
void visitGenericTypeParamType(GenericTypeParamType *T, StringRef label) {
34653479
printCommon(label, "generic_type_param_type");

lib/AST/ASTMangler.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -955,6 +955,10 @@ void ASTMangler::appendType(Type type) {
955955
case TypeKind::NestedArchetype:
956956
llvm_unreachable("Cannot mangle free-standing archetypes");
957957

958+
case TypeKind::OpaqueTypeArchetype:
959+
#warning "todo"
960+
llvm_unreachable("TODO");
961+
958962
case TypeKind::DynamicSelf: {
959963
auto dynamicSelf = cast<DynamicSelfType>(tybase);
960964
if (dynamicSelf->getSelfType()->getAnyNominal()) {

lib/AST/ASTPrinter.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -4140,6 +4140,20 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
41404140
void visitPrimaryArchetypeType(PrimaryArchetypeType *T) {
41414141
printArchetypeCommon(T);
41424142
}
4143+
4144+
void visitOpaqueTypeArchetypeType(OpaqueTypeArchetypeType *T) {
4145+
#warning "todo"
4146+
Printer << "(__opaque " << T->getOpaqueDecl()->getNamingDecl()->printRef();
4147+
if (!T->getSubstitutions().empty()) {
4148+
Printer << '<';
4149+
auto replacements = T->getSubstitutions().getReplacementTypes();
4150+
interleave(replacements.begin(), replacements.end(),
4151+
[&](Type t) { visit(t); },
4152+
[&] { Printer << ", "; });
4153+
Printer << '>';
4154+
}
4155+
Printer << ')';
4156+
}
41434157

41444158
void visitGenericTypeParamType(GenericTypeParamType *T) {
41454159
if (T->getDecl() == nullptr) {

lib/AST/GenericSignature.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -1029,6 +1029,14 @@ unsigned GenericParamKey::findIndexIn(
10291029
return genericParams.size();
10301030
}
10311031

1032+
SubstitutionMap GenericSignature::getIdentitySubstitutionMap() const {
1033+
return SubstitutionMap::get(const_cast<GenericSignature*>(this),
1034+
[](SubstitutableType *t) -> Type {
1035+
return Type(cast<GenericTypeParamType>(t));
1036+
},
1037+
MakeAbstractConformanceForGenericType());
1038+
}
1039+
10321040
unsigned GenericSignature::getGenericParamOrdinal(GenericTypeParamType *param) {
10331041
return GenericParamKey(param->getDepth(), param->getIndex())
10341042
.findIndexIn(getGenericParams());

0 commit comments

Comments
 (0)