Skip to content

Commit 7aced27

Browse files
authored
Merge pull request #3045 from slavapestov/open-type-cleanup
Sema: Open type cleanup
2 parents 85d2167 + bc968c6 commit 7aced27

27 files changed

+318
-269
lines changed

include/swift/AST/Decl.h

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2771,18 +2771,12 @@ class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext {
27712771
Type DeclaredTy;
27722772
Type DeclaredTyInContext;
27732773

2774-
void setDeclaredType(Type declaredTy) {
2775-
assert(DeclaredTy.isNull() && "Already set declared type");
2776-
DeclaredTy = declaredTy;
2777-
}
2778-
27792774
NominalTypeDecl(DeclKind K, DeclContext *DC, Identifier name,
27802775
SourceLoc NameLoc,
27812776
MutableArrayRef<TypeLoc> inherited,
27822777
GenericParamList *GenericParams) :
27832778
GenericTypeDecl(K, DC, name, NameLoc, inherited, GenericParams),
2784-
IterableDeclContext(IterableDeclContextKind::NominalTypeDecl),
2785-
DeclaredTy(nullptr)
2779+
IterableDeclContext(IterableDeclContextKind::NominalTypeDecl)
27862780
{
27872781
setGenericParams(GenericParams);
27882782
NominalTypeDeclBits.HasDelayedMembers = false;

include/swift/AST/DeclContext.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -368,11 +368,6 @@ class alignas(1 << DeclContextAlignInBits) DeclContext {
368368
/// Determine whether the innermost context is generic.
369369
bool isInnermostContextGeneric() const;
370370

371-
/// Determine the maximum depth of the current generic type context's generic
372-
/// parameters. If the current context is not a generic type context, returns
373-
/// the maximum depth of any generic parameter in this context.
374-
unsigned getGenericTypeContextDepth() const;
375-
376371
/// Get the most optimal resilience expansion for code in this context.
377372
/// If the body is able to be inlined into functions in other resilience
378373
/// domains, this ensures that only sufficiently-conservative access patterns

include/swift/AST/Requirement.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,12 @@ class Requirement {
5555
public:
5656
/// Create a conformance or same-type requirement.
5757
Requirement(RequirementKind kind, Type first, Type second)
58-
: FirstTypeAndKind(first, kind), SecondType(second) { }
58+
: FirstTypeAndKind(first, kind), SecondType(second) {
59+
if (kind != RequirementKind::WitnessMarker) {
60+
assert(first);
61+
assert(second);
62+
}
63+
}
5964

6065
/// \brief Determine the kind of requirement.
6166
RequirementKind getKind() const { return FirstTypeAndKind.getInt(); }

include/swift/AST/Types.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3403,7 +3403,7 @@ class DictionaryType : public TypeBase {
34033403

34043404
/// ProtocolType - A protocol type describes an abstract interface implemented
34053405
/// by another type.
3406-
class ProtocolType : public NominalType {
3406+
class ProtocolType : public NominalType, public llvm::FoldingSetNode {
34073407
public:
34083408
/// \brief Retrieve the type when we're referencing the given protocol.
34093409
/// declaration.
@@ -3435,6 +3435,11 @@ class ProtocolType : public NominalType {
34353435
static int compareProtocols(ProtocolDecl * const* PP1,
34363436
ProtocolDecl * const* PP2);
34373437

3438+
void Profile(llvm::FoldingSetNodeID &ID) {
3439+
Profile(ID, getDecl(), getParent());
3440+
}
3441+
static void Profile(llvm::FoldingSetNodeID &ID, ProtocolDecl *D, Type Parent);
3442+
34383443
private:
34393444
friend class NominalTypeDecl;
34403445
ProtocolType(ProtocolDecl *TheDecl, const ASTContext &Ctx);

lib/AST/ASTContext.cpp

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ struct ASTContext::Implementation {
276276
llvm::FoldingSet<ClassType> ClassTypes;
277277
llvm::FoldingSet<UnboundGenericType> UnboundGenericTypes;
278278
llvm::FoldingSet<BoundGenericType> BoundGenericTypes;
279+
llvm::FoldingSet<ProtocolType> ProtocolTypes;
279280

280281
llvm::DenseMap<std::pair<TypeBase *, DeclContext *>,
281282
ArrayRef<Substitution>>
@@ -2621,6 +2622,8 @@ BoundGenericType *BoundGenericType::get(NominalTypeDecl *TheDecl,
26212622
ASTContext &C = TheDecl->getDeclContext()->getASTContext();
26222623
llvm::FoldingSetNodeID ID;
26232624
RecursiveTypeProperties properties;
2625+
if (Parent)
2626+
properties |= Parent->getRecursiveProperties();
26242627
BoundGenericType::Profile(ID, TheDecl, Parent, GenericArgs, properties);
26252628

26262629
auto arena = getArena(properties);
@@ -3173,21 +3176,17 @@ SILFunctionType::SILFunctionType(GenericSignature *genericSig,
31733176

31743177
for (auto param : getParameters()) {
31753178
(void)param;
3176-
assert(!param.getType().findIf([](Type t) {
3177-
return t->is<ArchetypeType>()
3178-
&& !t->castTo<ArchetypeType>()->getSelfProtocol();
3179-
}) && "interface type of generic type should not contain context archetypes");
3179+
assert(!param.getType()->hasArchetype()
3180+
&& "interface type of generic type should not contain context archetypes");
31803181
}
31813182
for (auto result : getAllResults()) {
31823183
(void)result;
3183-
assert(!result.getType().findIf([](Type t) {
3184-
return t->is<ArchetypeType>();
3185-
}) && "interface type of generic type should not contain context archetypes");
3184+
assert(!result.getType()->hasArchetype()
3185+
&& "interface type of generic type should not contain context archetypes");
31863186
}
31873187
if (hasErrorResult()) {
3188-
assert(!getErrorResult().getType().findIf([](Type t) {
3189-
return t->is<ArchetypeType>();
3190-
}) && "interface type of generic type should not contain context archetypes");
3188+
assert(!getErrorResult().getType()->hasArchetype()
3189+
&& "interface type of generic type should not contain context archetypes");
31913190
}
31923191
}
31933192

@@ -3360,18 +3359,39 @@ ImplicitlyUnwrappedOptionalType *ImplicitlyUnwrappedOptionalType::get(Type base)
33603359
}
33613360

33623361
ProtocolType *ProtocolType::get(ProtocolDecl *D, const ASTContext &C) {
3363-
if (auto declaredTy = D->getDeclaredType())
3364-
return declaredTy->castTo<ProtocolType>();
3362+
// Protocol types can never be nested inside other types, but we should
3363+
// model this anyway to fix some compiler crashes when computing
3364+
// substitutions on invalid code.
3365+
Type Parent;
3366+
3367+
llvm::FoldingSetNodeID id;
3368+
ProtocolType::Profile(id, D, Parent);
3369+
3370+
RecursiveTypeProperties properties;
3371+
if (Parent) properties |= Parent->getRecursiveProperties();
3372+
auto arena = getArena(properties);
3373+
3374+
void *insertPos = 0;
3375+
if (auto protoTy
3376+
= C.Impl.getArena(arena).ProtocolTypes.FindNodeOrInsertPos(id, insertPos))
3377+
return protoTy;
3378+
3379+
auto protoTy = new (C, arena) ProtocolType(D, C);
3380+
C.Impl.getArena(arena).ProtocolTypes.InsertNode(protoTy, insertPos);
33653381

3366-
auto protoTy = new (C, AllocationArena::Permanent) ProtocolType(D, C);
3367-
D->setDeclaredType(protoTy);
33683382
return protoTy;
33693383
}
33703384

33713385
ProtocolType::ProtocolType(ProtocolDecl *TheDecl, const ASTContext &Ctx)
33723386
: NominalType(TypeKind::Protocol, &Ctx, TheDecl, /*Parent=*/Type(),
33733387
RecursiveTypeProperties()) { }
33743388

3389+
void ProtocolType::Profile(llvm::FoldingSetNodeID &ID, ProtocolDecl *D,
3390+
Type Parent) {
3391+
ID.AddPointer(D);
3392+
ID.AddPointer(Parent.getPointer());
3393+
}
3394+
33753395
LValueType *LValueType::get(Type objectTy) {
33763396
assert(!objectTy->is<ErrorType>() &&
33773397
"cannot have ErrorType wrapped inside LValueType");

lib/AST/ArchetypeBuilder.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2157,6 +2157,9 @@ addRequirements(
21572157
ArchetypeBuilder::PotentialArchetype *pa,
21582158
llvm::SmallPtrSet<ArchetypeBuilder::PotentialArchetype *, 16> &knownPAs,
21592159
SmallVectorImpl<Requirement> &requirements) {
2160+
2161+
auto &ctx = builder.getASTContext();
2162+
21602163
// If the potential archetype has been bound away to a concrete type,
21612164
// it needs no requirements.
21622165
if (pa->isConcreteType())
@@ -2181,8 +2184,8 @@ addRequirements(
21812184

21822185
ProtocolType::canonicalizeProtocols(protocols);
21832186
for (auto proto : protocols) {
2184-
requirements.push_back(Requirement(RequirementKind::Conformance,
2185-
type, proto->getDeclaredType()));
2187+
requirements.push_back(Requirement(RequirementKind::Conformance, type,
2188+
ProtocolType::get(proto, ctx)));
21862189
}
21872190
}
21882191

lib/AST/Decl.cpp

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1684,11 +1684,9 @@ Type ValueDecl::getInterfaceType() const {
16841684

16851685
if (auto assocType = dyn_cast<AssociatedTypeDecl>(this)) {
16861686
auto proto = cast<ProtocolDecl>(getDeclContext());
1687-
(void)proto->getType(); // make sure we've computed the type.
1688-
// FIXME: the generic parameter types list should never be empty.
1689-
auto selfTy = proto->getInnermostGenericParamTypes().empty()
1690-
? proto->getProtocolSelf()->getType()
1691-
: proto->getInnermostGenericParamTypes().back();
1687+
if (!proto->hasType())
1688+
proto->computeType(); // make sure we've computed the type.
1689+
auto selfTy = proto->getProtocolSelf()->getDeclaredType();
16921690
auto &ctx = getASTContext();
16931691
InterfaceTy = DependentMemberType::get(
16941692
selfTy,
@@ -1909,14 +1907,11 @@ void NominalTypeDecl::computeType() {
19091907
Type parentTy = getDeclContext()->getDeclaredTypeInContext();
19101908
ASTContext &ctx = getASTContext();
19111909
if (auto proto = dyn_cast<ProtocolDecl>(this)) {
1912-
if (!getDeclaredType()) {
1913-
ProtocolType::get(proto, ctx);
1914-
assert(getDeclaredType());
1915-
}
1910+
DeclaredTy = ProtocolType::get(proto, ctx);
19161911
} else if (getGenericParams()) {
1917-
setDeclaredType(UnboundGenericType::get(this, parentTy, ctx));
1912+
DeclaredTy = UnboundGenericType::get(this, parentTy, ctx);
19181913
} else {
1919-
setDeclaredType(NominalType::get(this, parentTy, ctx));
1914+
DeclaredTy = NominalType::get(this, parentTy, ctx);
19201915
}
19211916

19221917
// Set the type.

lib/AST/DeclContext.cpp

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -431,25 +431,6 @@ bool DeclContext::isGenericContext() const {
431431
llvm_unreachable("illegal declcontext hierarchy");
432432
}
433433

434-
/// Determine the maximum depth of the current generic type context's generic
435-
/// parameters. If the current context is not a generic type context, returns
436-
/// the maximum depth of any generic parameter in this context.
437-
unsigned DeclContext::getGenericTypeContextDepth() const {
438-
unsigned depth = 0;
439-
bool inTypeContext = true;
440-
for (const auto *dc = this; dc; dc = dc->getParent()) {
441-
// Starting from the innermost context that is not a type context, count
442-
// all parent contexts that have generic parameters.
443-
if (!dc->isTypeContext())
444-
inTypeContext = false;
445-
446-
if (!inTypeContext && dc->isInnermostContextGeneric())
447-
depth++;
448-
}
449-
450-
return depth;
451-
}
452-
453434
/// Get the most optimal resilience expansion for the body of this function.
454435
/// If the body is able to be inlined into functions in other resilience
455436
/// domains, this ensures that only sufficiently-conservative access patterns

lib/Sema/CSApply.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,6 +1123,8 @@ namespace {
11231123
ConstraintLocatorBuilder locator,
11241124
Optional<Pattern*> typeFromPattern = None);
11251125

1126+
using LevelTy = llvm::PointerEmbeddedInt<unsigned, 2>;
1127+
11261128
/// \brief Coerce the given expression (which is the argument to a call) to
11271129
/// the given parameter type.
11281130
///
@@ -1136,8 +1138,6 @@ namespace {
11361138
/// \param locator Locator used to describe where in this expression we are.
11371139
///
11381140
/// \returns the coerced expression, which will have type \c ToType.
1139-
using LevelTy = llvm::PointerEmbeddedInt<unsigned, 2>;
1140-
11411141
Expr *
11421142
coerceCallArguments(Expr *arg, Type paramType,
11431143
llvm::PointerUnion<ApplyExpr *, LevelTy> applyOrLevel,

lib/Sema/CSRanking.cpp

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,8 @@ static bool isProtocolExtensionAsSpecializedAs(TypeChecker &tc,
450450
// the second protocol extension.
451451
ConstraintSystem cs(tc, dc1, None);
452452
llvm::DenseMap<CanType, TypeVariableType *> replacements;
453-
cs.openGeneric(dc2, sig2, false, dc2->getGenericTypeContextDepth(),
453+
cs.openGeneric(dc2, dc2, sig2,
454+
/*skipProtocolSelfConstraint=*/false,
454455
ConstraintLocatorBuilder(nullptr),
455456
replacements);
456457

@@ -571,14 +572,35 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, DeclContext *dc,
571572
auto locator = cs.getConstraintLocator(nullptr);
572573
// FIXME: Locator when anchored on a declaration.
573574
// Get the type of a reference to the second declaration.
574-
Type openedType2 = cs.openType(type2, locator,
575-
decl2->getInnermostDeclContext());
575+
llvm::DenseMap<CanType, TypeVariableType *> unused;
576+
Type openedType2;
577+
if (auto *funcType = type2->getAs<AnyFunctionType>()) {
578+
openedType2 = cs.openFunctionType(
579+
funcType, locator,
580+
/*replacements=*/unused,
581+
decl2->getInnermostDeclContext(),
582+
decl2->getDeclContext(),
583+
/*skipProtocolSelfConstraint=*/false);
584+
} else {
585+
openedType2 = cs.openType(type2, locator, unused);
586+
}
576587

577588
// Get the type of a reference to the first declaration, swapping in
578589
// archetypes for the dependent types.
579590
llvm::DenseMap<CanType, TypeVariableType *> replacements;
580591
auto dc1 = decl1->getInnermostDeclContext();
581-
Type openedType1 = cs.openType(type1, locator, replacements, dc1);
592+
Type openedType1;
593+
if (auto *funcType = type1->getAs<AnyFunctionType>()) {
594+
openedType1 = cs.openFunctionType(
595+
funcType, locator,
596+
replacements,
597+
dc1,
598+
decl1->getDeclContext(),
599+
/*skipProtocolSelfConstraint=*/false);
600+
} else {
601+
openedType1 = cs.openType(type1, locator, replacements);
602+
}
603+
582604
for (const auto &replacement : replacements) {
583605
if (auto mapped =
584606
ArchetypeBuilder::mapTypeIntoContext(dc1,

0 commit comments

Comments
 (0)