Skip to content

Commit d032a9a

Browse files
authored
Merge pull request #22758 from jckarter/opened-archetype-generic-environment
Generic environments for opened archetypes
2 parents af43ae7 + 64488b1 commit d032a9a

19 files changed

+180
-75
lines changed

include/swift/AST/Types.h

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4695,8 +4695,11 @@ class ArchetypeType : public SubstitutableType,
46954695
/// Register a nested type with the given name.
46964696
void registerNestedType(Identifier name, Type nested);
46974697

4698-
/// getPrimary - Return the primary archetype parent of this archetype.
4699-
PrimaryArchetypeType *getPrimary() const;
4698+
/// Return the root archetype parent of this archetype.
4699+
ArchetypeType *getRoot() const;
4700+
4701+
/// Get the generic environment this archetype lives in.
4702+
GenericEnvironment *getGenericEnvironment() const;
47004703

47014704
// Implement isa/cast/dyncast/etc.
47024705
static bool classof(const TypeBase *T) {
@@ -4760,7 +4763,8 @@ class OpenedArchetypeType final : public ArchetypeType,
47604763
{
47614764
friend TrailingObjects;
47624765
friend ArchetypeType;
4763-
4766+
4767+
mutable GenericEnvironment *Environment = nullptr;
47644768
TypeBase *Opened;
47654769
UUID ID;
47664770
public:
@@ -4789,12 +4793,17 @@ class OpenedArchetypeType final : public ArchetypeType,
47894793
return Opened;
47904794
}
47914795

4796+
/// Get a generic environment with this opened type bound to its generic
4797+
/// parameter.
4798+
GenericEnvironment *getGenericEnvironment() const;
4799+
47924800
static bool classof(const TypeBase *T) {
47934801
return T->getKind() == TypeKind::OpenedArchetype;
47944802
}
47954803

47964804
private:
4797-
OpenedArchetypeType(const ASTContext &Ctx, Type Existential,
4805+
OpenedArchetypeType(const ASTContext &Ctx,
4806+
Type Existential,
47984807
ArrayRef<ProtocolDecl *> ConformsTo, Type Superclass,
47994808
LayoutConstraint Layout, UUID uuid);
48004809
};
@@ -4831,6 +4840,10 @@ class NestedArchetypeType final : public ArchetypeType,
48314840
static bool classof(const TypeBase *T) {
48324841
return T->getKind() == TypeKind::NestedArchetype;
48334842
}
4843+
4844+
DependentMemberType *getInterfaceType() const {
4845+
return cast<DependentMemberType>(InterfaceType.getPointer());
4846+
}
48344847

48354848
private:
48364849
NestedArchetypeType(const ASTContext &Ctx,

include/swift/Serialization/DeclTypeRecordNodes.def

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,9 @@ TRAILING_INFO(TUPLE_TYPE_ELT)
8888
TYPE(FUNCTION)
8989
TRAILING_INFO(FUNCTION_PARAM)
9090
TYPE(METATYPE)
91-
TYPE(ARCHETYPE)
91+
TYPE(PRIMARY_ARCHETYPE)
92+
TYPE(OPENED_ARCHETYPE)
93+
TYPE(NESTED_ARCHETYPE)
9294
TYPE(PROTOCOL_COMPOSITION)
9395
TYPE(BOUND_GENERIC)
9496

include/swift/Serialization/ModuleFormat.h

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5252
/// describe what change you made. The content of this comment isn't important;
5353
/// it just ensures a conflict if two people change the module format.
5454
/// Don't worry about adhering to the 80-column limit for this line.
55-
const uint16_t SWIFTMODULE_VERSION_MINOR = 474; // Last change: @_alwaysEmitIntoClient
55+
const uint16_t SWIFTMODULE_VERSION_MINOR = 475; // Last change: Generalize nested archetype serialization
5656

5757
using DeclIDField = BCFixed<31>;
5858

@@ -766,17 +766,24 @@ namespace decls_block {
766766
MetatypeRepresentationField // representation
767767
>;
768768

769-
using ArchetypeTypeLayout = BCRecordLayout<
770-
ARCHETYPE_TYPE,
769+
using PrimaryArchetypeTypeLayout = BCRecordLayout<
770+
PRIMARY_ARCHETYPE_TYPE,
771771
GenericEnvironmentIDField, // generic environment
772-
TypeIDField // interface type
772+
BCVBR<4>, // generic type parameter depth
773+
BCVBR<4> // index + 1, or zero if we have a generic type parameter decl
773774
>;
774775

775-
using OpenedExistentialTypeLayout = BCRecordLayout<
776-
OPENED_EXISTENTIAL_TYPE,
776+
using OpenedArchetypeTypeLayout = BCRecordLayout<
777+
OPENED_ARCHETYPE_TYPE,
777778
TypeIDField // the existential type
778779
>;
779-
780+
781+
using NestedArchetypeTypeLayout = BCRecordLayout<
782+
NESTED_ARCHETYPE_TYPE,
783+
TypeIDField, // root archetype
784+
TypeIDField // interface type relative to root
785+
>;
786+
780787
using DynamicSelfTypeLayout = BCRecordLayout<
781788
DYNAMIC_SELF_TYPE,
782789
TypeIDField // self type
@@ -1058,7 +1065,7 @@ namespace decls_block {
10581065
// - the foreign error convention, if any
10591066
// - inlinable body text, if any
10601067
>;
1061-
1068+
10621069
// TODO: remove the unnecessary FuncDecl components here
10631070
using AccessorLayout = BCRecordLayout<
10641071
ACCESSOR_DECL,

lib/AST/ASTContext.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4316,11 +4316,28 @@ CanOpenedArchetypeType OpenedArchetypeType::get(Type existential,
43164316
::new (mem) OpenedArchetypeType(ctx, existential,
43174317
protos, layoutSuperclass,
43184318
layoutConstraint, *knownID);
4319+
result->InterfaceType = GenericTypeParamType::get(0, 0, ctx);
4320+
43194321
openedExistentialArchetypes[*knownID] = result;
4320-
43214322
return CanOpenedArchetypeType(result);
43224323
}
43234324

4325+
GenericEnvironment *OpenedArchetypeType::getGenericEnvironment() const {
4326+
if (Environment)
4327+
return Environment;
4328+
4329+
auto thisType = Type(const_cast<OpenedArchetypeType*>(this));
4330+
auto &ctx = thisType->getASTContext();
4331+
// Create a generic environment to represent the opened type.
4332+
auto signature = ctx.getExistentialSignature(Opened->getCanonicalType(),
4333+
nullptr);
4334+
auto env = signature->createGenericEnvironment();
4335+
env->addMapping(signature->getGenericParams()[0], thisType);
4336+
Environment = env;
4337+
4338+
return env;
4339+
}
4340+
43244341
CanType OpenedArchetypeType::getAny(Type existential) {
43254342
if (auto metatypeTy = existential->getAs<ExistentialMetatypeType>()) {
43264343
auto instanceTy = metatypeTy->getInstanceType();

lib/AST/ASTVerifier.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -632,13 +632,15 @@ class Verifier : public ASTWalker {
632632
// Only visit each archetype once.
633633
if (!visitedArchetypes.insert(archetype).second)
634634
return false;
635+
636+
auto root = archetype->getRoot();
635637

636638
// We should know about archetypes corresponding to opened
637639
// existential archetypes.
638-
if (auto opened = dyn_cast<OpenedArchetypeType>(archetype)) {
640+
if (auto opened = dyn_cast<OpenedArchetypeType>(root)) {
639641
if (OpenedExistentialArchetypes.count(opened) == 0) {
640642
Out << "Found opened existential archetype "
641-
<< archetype->getString()
643+
<< root->getString()
642644
<< " outside enclosing OpenExistentialExpr\n";
643645
return true;
644646
}
@@ -649,18 +651,18 @@ class Verifier : public ASTWalker {
649651
// Otherwise, the archetype needs to be from this scope.
650652
if (GenericEnv.empty() || !GenericEnv.back()) {
651653
Out << "AST verification error: archetype outside of generic "
652-
"context: " << archetype->getString() << "\n";
654+
"context: " << root->getString() << "\n";
653655
return true;
654656
}
655657

656658
// Get the primary archetype.
657-
auto *parent = archetype->getPrimary();
659+
auto rootPrimary = cast<PrimaryArchetypeType>(root);
658660

659-
if (!GenericEnv.back().containsPrimaryArchetype(parent)) {
661+
if (!GenericEnv.back().containsPrimaryArchetype(rootPrimary)) {
660662
Out << "AST verification error: archetype "
661-
<< archetype->getString() << " not allowed in this context\n";
663+
<< root->getString() << " not allowed in this context\n";
662664

663-
if (auto env = parent->getGenericEnvironment()) {
665+
if (auto env = rootPrimary->getGenericEnvironment()) {
664666
if (auto owningDC = env->getOwningDeclContext()) {
665667
llvm::errs() << "archetype came from:\n";
666668
owningDC->dumpContext();

lib/AST/GenericEnvironment.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,9 @@ Type GenericEnvironment::mapTypeIntoContext(GenericEnvironment *env,
122122
}
123123

124124
Type MapTypeOutOfContext::operator()(SubstitutableType *type) const {
125-
return cast<ArchetypeType>(type)->getInterfaceType();
125+
auto archetype = cast<ArchetypeType>(type);
126+
127+
return archetype->getInterfaceType();
126128
}
127129

128130
Type TypeBase::mapTypeOutOfContext() {

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2811,6 +2811,8 @@ static void concretizeNestedTypeFromConcreteParent(
28112811
->getTypeWitness(assocType, builder.getLazyResolver());
28122812
if (!witnessType || witnessType->hasError())
28132813
return; // FIXME: should we delay here?
2814+
} else if (auto archetype = concreteParent->getAs<ArchetypeType>()) {
2815+
witnessType = archetype->getNestedType(assocType->getName());
28142816
} else {
28152817
witnessType = DependentMemberType::get(concreteParent, assocType);
28162818
}
@@ -2902,7 +2904,7 @@ PotentialArchetype *PotentialArchetype::updateNestedTypeForConformance(
29022904

29032905
void ArchetypeType::resolveNestedType(
29042906
std::pair<Identifier, Type> &nested) const {
2905-
auto genericEnv = getPrimary()->getGenericEnvironment();
2907+
auto genericEnv = getGenericEnvironment();
29062908
auto &builder = *genericEnv->getGenericSignatureBuilder();
29072909

29082910
Type interfaceType = getInterfaceType();
@@ -3886,14 +3888,17 @@ ResolvedType GenericSignatureBuilder::maybeResolveEquivalenceClass(
38863888
}
38873889

38883890
// The equivalence class of a dependent member type is determined by its
3889-
// base equivalence class.
3891+
// base equivalence class, if there is one.
38903892
if (auto depMemTy = type->getAs<DependentMemberType>()) {
38913893
// Find the equivalence class of the base.
38923894
auto resolvedBase =
38933895
maybeResolveEquivalenceClass(depMemTy->getBase(),
38943896
resolutionKind,
38953897
wantExactPotentialArchetype);
38963898
if (!resolvedBase) return resolvedBase;
3899+
// If the base is concrete, so is this member.
3900+
if (resolvedBase.getAsConcreteType())
3901+
return ResolvedType::forConcrete(type);
38973902

38983903
// Find the nested type declaration for this.
38993904
auto baseEquivClass = resolvedBase.getEquivalenceClass(*this);

lib/AST/Type.cpp

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2368,12 +2368,23 @@ ArchetypeType::ArchetypeType(TypeKind Kind,
23682368
getSubclassTrailingObjects<ProtocolDecl *>());
23692369
}
23702370

2371-
PrimaryArchetypeType *ArchetypeType::getPrimary() const {
2372-
ArchetypeType *archetype = const_cast<ArchetypeType*>(this);
2373-
while (auto child = dyn_cast<NestedArchetypeType>(archetype)) {
2374-
archetype = child->getParent();
2371+
GenericEnvironment *ArchetypeType::getGenericEnvironment() const {
2372+
auto root = getRoot();
2373+
if (auto primary = dyn_cast<PrimaryArchetypeType>(root)) {
2374+
return primary->getGenericEnvironment();
23752375
}
2376-
return dyn_cast<PrimaryArchetypeType>(archetype);
2376+
if (auto opened = dyn_cast<OpenedArchetypeType>(root)) {
2377+
return opened->getGenericEnvironment();
2378+
}
2379+
llvm_unreachable("unhandled root archetype kind?!");
2380+
}
2381+
2382+
ArchetypeType *ArchetypeType::getRoot() const {
2383+
auto parent = this;
2384+
while (auto nested = dyn_cast<NestedArchetypeType>(parent)) {
2385+
parent = nested->getParent();
2386+
}
2387+
return const_cast<ArchetypeType*>(parent);
23772388
}
23782389

23792390
PrimaryArchetypeType::PrimaryArchetypeType(const ASTContext &Ctx,
@@ -3368,10 +3379,10 @@ Type Type::transformRec(
33683379
if (Optional<Type> transformed = fn(getPointer()))
33693380
return *transformed;
33703381

3371-
// Recurse.
3382+
// Recur.
33723383
}
33733384

3374-
// Recursive into children of this type.
3385+
// Recur into children of this type.
33753386
TypeBase *base = getPointer();
33763387
switch (base->getKind()) {
33773388
#define ALWAYS_CANONICAL_TYPE(Id, Parent) \

lib/IRGen/GenArchetype.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ llvm::Value *irgen::emitArchetypeWitnessTableRef(IRGenFunction &IGF,
172172
auto wtable = IGF.tryGetLocalTypeData(archetype, localDataKind);
173173
if (wtable) return wtable;
174174

175-
// If we don't have an environment, this must be an implied witness table
175+
// If we have an opened type, this must be an implied witness table
176176
// reference.
177177
// FIXME: eliminate this path when opened types have generic environments.
178178
if (auto opened = dyn_cast<OpenedArchetypeType>(archetype)) {
@@ -195,7 +195,9 @@ llvm::Value *irgen::emitArchetypeWitnessTableRef(IRGenFunction &IGF,
195195
});
196196
}
197197

198-
auto environment = archetype->getPrimary()->getGenericEnvironment();
198+
assert(isa<PrimaryArchetypeType>(archetype->getRoot())
199+
&& "might not work yet for opened/opaque archetypes!");
200+
auto environment = archetype->getGenericEnvironment();
199201

200202
// Otherwise, ask the generic signature for the environment for the best
201203
// path to the conformance.

lib/IRGen/GenType.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1508,7 +1508,7 @@ const TypeInfo &TypeConverter::getCompleteTypeInfo(CanType T) {
15081508

15091509
ArchetypeType *TypeConverter::getExemplarArchetype(ArchetypeType *t) {
15101510
// Get the primary archetype.
1511-
auto primary = t->getPrimary();
1511+
auto primary = dyn_cast<PrimaryArchetypeType>(t->getRoot());
15121512

15131513
// If there is no primary (IOW, it's an opened archetype), the archetype is
15141514
// an exemplar.
@@ -2219,7 +2219,7 @@ void IRGenFunction::setLocalSelfMetadata(llvm::Value *value,
22192219

22202220
#ifndef NDEBUG
22212221
bool TypeConverter::isExemplarArchetype(ArchetypeType *arch) const {
2222-
auto primary = arch->getPrimary();
2222+
auto primary = dyn_cast<PrimaryArchetypeType>(arch->getRoot());
22232223
if (!primary) return true;
22242224
auto genericEnv = primary->getGenericEnvironment();
22252225

lib/IRGen/Outlining.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,10 @@ irgen::getTypeAndGenericSignatureForManglingOutlineFunction(SILType type) {
110110
GenericEnvironment *env = nullptr;
111111
loweredType.findIf([&env](Type t) -> bool {
112112
if (auto arch = t->getAs<ArchetypeType>()) {
113-
env = arch->getPrimary()->getGenericEnvironment();
113+
auto root = arch->getRoot();
114+
if (!isa<PrimaryArchetypeType>(root))
115+
return false;
116+
env = root->getGenericEnvironment();
114117
return true;
115118
}
116119
return false;

lib/SIL/SILVerifier.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,16 +77,14 @@ static llvm::cl::opt<bool> SkipConvertEscapeToNoescapeAttributes(
7777
/// Returns true if A is an opened existential type or is equal to an
7878
/// archetype from F's generic context.
7979
static bool isArchetypeValidInFunction(ArchetypeType *A, const SILFunction *F) {
80-
if (isa<OpenedArchetypeType>(A))
80+
auto root = dyn_cast<PrimaryArchetypeType>(A->getRoot());
81+
if (!root)
8182
return true;
8283

83-
// Find the primary archetype.
84-
auto P = A->getPrimary();
85-
8684
// Ok, we have a primary archetype, make sure it is in the nested generic
8785
// environment of our caller.
8886
if (auto *genericEnv = F->getGenericEnvironment())
89-
if (P->getGenericEnvironment() == genericEnv)
87+
if (root->getGenericEnvironment() == genericEnv)
9088
return true;
9189

9290
return false;

lib/SILOptimizer/Utils/Generics.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,7 +1036,9 @@ shouldBePartiallySpecialized(Type Replacement,
10361036
llvm::SmallSetVector<ArchetypeType *, 2> UsedArchetypes;
10371037
Replacement.visit([&](Type Ty) {
10381038
if (auto Archetype = Ty->getAs<ArchetypeType>()) {
1039-
UsedArchetypes.insert(Archetype->getPrimary());
1039+
if (auto Primary = dyn_cast<PrimaryArchetypeType>(Archetype->getRoot())) {
1040+
UsedArchetypes.insert(Primary);
1041+
}
10401042
}
10411043
});
10421044

@@ -1264,7 +1266,9 @@ void FunctionSignaturePartialSpecializer::collectUsedCallerArchetypes(
12641266
// Add used generic parameters/archetypes.
12651267
Replacement.visit([&](Type Ty) {
12661268
if (auto Archetype = Ty->getAs<ArchetypeType>()) {
1267-
UsedCallerArchetypes.insert(Archetype->getPrimary());
1269+
if (auto Primary = dyn_cast<PrimaryArchetypeType>(Archetype->getRoot())) {
1270+
UsedCallerArchetypes.insert(Primary);
1271+
}
12681272
}
12691273
});
12701274
}

lib/Sema/CSSimplify.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#include "CSFix.h"
1919
#include "ConstraintSystem.h"
2020
#include "swift/AST/ExistentialLayout.h"
21+
#include "swift/AST/GenericEnvironment.h"
22+
#include "swift/AST/GenericSignature.h"
2123
#include "swift/AST/ParameterList.h"
2224
#include "swift/AST/ProtocolConformance.h"
2325
#include "swift/Basic/StringExtras.h"

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2950,9 +2950,13 @@ static Type replaceArchetypesWithTypeVariables(ConstraintSystem &cs,
29502950
if (found != types.end())
29512951
return found->second;
29522952

2953-
if (isa<NestedArchetypeType>(origType))
2954-
return Type();
2955-
else if (auto archetypeType = dyn_cast<ArchetypeType>(origType)) {
2953+
if (auto archetypeType = dyn_cast<ArchetypeType>(origType)) {
2954+
auto root = archetypeType->getRoot();
2955+
// For other nested types, fail here so the default logic in subst()
2956+
// for nested types applies.
2957+
if (root != archetypeType)
2958+
return Type();
2959+
29562960
auto locator = cs.getConstraintLocator(nullptr);
29572961
auto replacement = cs.createTypeVariable(locator);
29582962

0 commit comments

Comments
 (0)