Skip to content

Commit 5e34169

Browse files
committed
Separate computing interface types and underlying types
Computing the interface type of a typealias used to push validation forward and recompute the interface type on the fly. This was fragile and inconsistent with the way interface types are computed in the rest of the decls. Separate these two notions, and plumb through explicit interface type computations with the same "computeType" idiom. This will better allow us to identify the places where we have to force an interface type computation. Also remove access to the underlying type loc. It's now just a cache location the underlying type request will use. Push a type repr accessor to the places that need it, and push the underlying type accessor for everywhere else. Getting the structural type is still preferred for pre-validated computations. This required the resetting of a number of places where we were - in many cases tacitly - asking the question "does the interface type exist". This enables the removal of validateDeclForNameLookup
1 parent dceb357 commit 5e34169

23 files changed

+385
-142
lines changed

include/swift/AST/Decl.h

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2976,20 +2976,28 @@ class TypeAliasDecl : public GenericTypeDecl {
29762976

29772977
void setTypeEndLoc(SourceLoc e) { TypeEndLoc = e; }
29782978

2979-
TypeLoc &getUnderlyingTypeLoc() {
2980-
return UnderlyingTy;
2979+
/// Retrieve the TypeRepr corresponding to the parsed underlying type.
2980+
TypeRepr *getUnderlyingTypeRepr() const {
2981+
return UnderlyingTy.getTypeRepr();
29812982
}
2982-
const TypeLoc &getUnderlyingTypeLoc() const {
2983-
return UnderlyingTy;
2983+
void setUnderlyingTypeRepr(TypeRepr *repr) {
2984+
UnderlyingTy = repr;
29842985
}
2985-
2986+
2987+
/// Retrieve the interface type of the underlying type.
2988+
Type getUnderlyingType() const;
29862989
void setUnderlyingType(Type type);
29872990

29882991
/// For generic typealiases, return the unbound generic type.
29892992
UnboundGenericType *getUnboundGenericType() const;
29902993

2994+
/// Retrieve a sugared interface type containing the structure of the interface
2995+
/// type before any semantic validation has occured.
29912996
Type getStructuralType() const;
29922997

2998+
/// Set the interface type of this typealias declaration from the underlying type.
2999+
void computeType();
3000+
29933001
bool isCompatibilityAlias() const {
29943002
return Bits.TypeAliasDecl.IsCompatibilityAlias;
29953003
}

lib/AST/ASTPrinter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2276,7 +2276,7 @@ void PrintAST::visitTypeAliasDecl(TypeAliasDecl *decl) {
22762276
printGenericDeclGenericParams(decl);
22772277
});
22782278
bool ShouldPrint = true;
2279-
Type Ty = decl->getUnderlyingTypeLoc().getType();
2279+
Type Ty = decl->getUnderlyingType();
22802280

22812281
// If the underlying type is private, don't print it.
22822282
if (Options.SkipPrivateStdlibDecls && Ty && Ty.isPrivateStdlibType())
@@ -2294,7 +2294,7 @@ void PrintAST::visitTypeAliasDecl(TypeAliasDecl *decl) {
22942294
// preserving sugar.
22952295
llvm::SaveAndRestore<GenericEnvironment*> setGenericEnv(Options.GenericEnv,
22962296
decl->getGenericEnvironment());
2297-
printTypeLoc(decl->getUnderlyingTypeLoc());
2297+
printTypeLoc(TypeLoc::withoutLoc(Ty));
22982298
printGenericDeclGenericRequirements(decl);
22992299
}
23002300
}

lib/AST/ASTWalker.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,10 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
232232
return true;
233233
}
234234

235-
return doIt(TAD->getUnderlyingTypeLoc());
235+
if (auto typerepr = TAD->getUnderlyingTypeRepr())
236+
if (doIt(typerepr))
237+
return true;
238+
return false;
236239
}
237240

238241
bool visitOpaqueTypeDecl(OpaqueTypeDecl *OTD) {

lib/AST/Decl.cpp

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3527,34 +3527,35 @@ SourceRange TypeAliasDecl::getSourceRange() const {
35273527
return { TypeAliasLoc, getNameLoc() };
35283528
}
35293529

3530-
void TypeAliasDecl::setUnderlyingType(Type underlying) {
3531-
setValidationToChecked();
3532-
3533-
// lldb creates global typealiases containing archetypes
3534-
// sometimes...
3535-
if (underlying->hasArchetype() && isGenericContext())
3536-
underlying = underlying->mapTypeOutOfContext();
3537-
UnderlyingTy.setType(underlying);
3538-
3539-
// FIXME -- if we already have an interface type, we're changing the
3540-
// underlying type. See the comment in the ProtocolDecl case of
3541-
// validateDecl().
3542-
if (!hasInterfaceType()) {
3543-
// Set the interface type of this declaration.
3544-
ASTContext &ctx = getASTContext();
3530+
void TypeAliasDecl::computeType() {
3531+
assert(!hasInterfaceType());
3532+
3533+
// Set the interface type of this declaration.
3534+
ASTContext &ctx = getASTContext();
35453535

3546-
auto *genericSig = getGenericSignature();
3547-
SubstitutionMap subs;
3548-
if (genericSig)
3549-
subs = genericSig->getIdentitySubstitutionMap();
3536+
auto *genericSig = getGenericSignature();
3537+
SubstitutionMap subs;
3538+
if (genericSig)
3539+
subs = genericSig->getIdentitySubstitutionMap();
35503540

3551-
Type parent;
3552-
auto parentDC = getDeclContext();
3553-
if (parentDC->isTypeContext())
3554-
parent = parentDC->getDeclaredInterfaceType();
3555-
auto sugaredType = TypeAliasType::get(this, parent, subs, underlying);
3556-
setInterfaceType(MetatypeType::get(sugaredType, ctx));
3557-
}
3541+
Type parent;
3542+
auto parentDC = getDeclContext();
3543+
if (parentDC->isTypeContext())
3544+
parent = parentDC->getDeclaredInterfaceType();
3545+
auto sugaredType = TypeAliasType::get(this, parent, subs, getUnderlyingType());
3546+
setInterfaceType(MetatypeType::get(sugaredType, ctx));
3547+
}
3548+
3549+
Type TypeAliasDecl::getUnderlyingType() const {
3550+
return evaluateOrDefault(getASTContext().evaluator,
3551+
UnderlyingTypeRequest{const_cast<TypeAliasDecl *>(this)},
3552+
Type());
3553+
}
3554+
3555+
void TypeAliasDecl::setUnderlyingType(Type underlying) {
3556+
getASTContext().evaluator.cacheOutput(
3557+
UnderlyingTypeRequest{const_cast<TypeAliasDecl *>(this)},
3558+
std::move(underlying));
35583559
}
35593560

35603561
UnboundGenericType *TypeAliasDecl::getUnboundGenericType() const {
@@ -3571,12 +3572,10 @@ UnboundGenericType *TypeAliasDecl::getUnboundGenericType() const {
35713572
}
35723573

35733574
Type TypeAliasDecl::getStructuralType() const {
3574-
assert(!getGenericParams());
3575-
35763575
auto &context = getASTContext();
3577-
return evaluateOrDefault(context.evaluator,
3578-
StructuralTypeRequest { const_cast<TypeAliasDecl *>(this) },
3579-
Type());
3576+
return evaluateOrDefault(
3577+
context.evaluator,
3578+
StructuralTypeRequest{const_cast<TypeAliasDecl *>(this)}, Type());
35803579
}
35813580

35823581
Type AbstractTypeParamDecl::getSuperclass() const {

lib/AST/DiagnosticEngine.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ static bool isInterestingTypealias(Type type) {
379379
// Compatibility aliases are only interesting insofar as their underlying
380380
// types are interesting.
381381
if (aliasDecl->isCompatibilityAlias()) {
382-
auto underlyingTy = aliasDecl->getUnderlyingTypeLoc().getType();
382+
auto underlyingTy = aliasDecl->getUnderlyingType();
383383
return isInterestingTypealias(underlyingTy);
384384
}
385385

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3785,9 +3785,8 @@ PotentialArchetype *GenericSignatureBuilder::realizePotentialArchetype(
37853785

37863786
static Type getStructuralType(TypeDecl *typeDecl) {
37873787
if (auto typealias = dyn_cast<TypeAliasDecl>(typeDecl)) {
3788-
if (auto resolved = typealias->getUnderlyingTypeLoc().getType())
3789-
return resolved;
3790-
3788+
if (typealias->hasInterfaceType())
3789+
return typealias->getDeclaredInterfaceType();
37913790
return typealias->getStructuralType();
37923791
}
37933792

@@ -4196,11 +4195,10 @@ ConstraintResult GenericSignatureBuilder::expandConformanceRequirement(
41964195
out << start;
41974196
out << type->getFullName() << " == ";
41984197
if (auto typealias = dyn_cast<TypeAliasDecl>(type)) {
4199-
if (auto underlyingTypeRepr =
4200-
typealias->getUnderlyingTypeLoc().getTypeRepr())
4198+
if (auto underlyingTypeRepr = typealias->getUnderlyingTypeRepr())
42014199
underlyingTypeRepr->print(out);
42024200
else
4203-
typealias->getUnderlyingTypeLoc().getType().print(out);
4201+
typealias->getUnderlyingType().print(out);
42044202
} else {
42054203
type->print(out);
42064204
}

lib/AST/Module.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ void BuiltinUnit::LookupCache::lookupValue(
101101
const_cast<BuiltinUnit*>(&M));
102102
TAD->setUnderlyingType(Ty);
103103
TAD->setAccess(AccessLevel::Public);
104+
TAD->setValidationToChecked();
105+
TAD->computeType();
104106
Entry = TAD;
105107
}
106108
}

lib/AST/NameLookup.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1813,7 +1813,7 @@ resolveTypeDeclsToNominal(Evaluator &evaluator,
18131813
// Recognize Swift.AnyObject directly.
18141814
if (typealias->getName().is("AnyObject")) {
18151815
// TypeRepr version: Builtin.AnyObject
1816-
if (auto typeRepr = typealias->getUnderlyingTypeLoc().getTypeRepr()) {
1816+
if (auto typeRepr = typealias->getUnderlyingTypeRepr()) {
18171817
if (auto compound = dyn_cast<CompoundIdentTypeRepr>(typeRepr)) {
18181818
auto components = compound->getComponents();
18191819
if (components.size() == 2 &&
@@ -1825,9 +1825,10 @@ resolveTypeDeclsToNominal(Evaluator &evaluator,
18251825
}
18261826

18271827
// Type version: an empty class-bound existential.
1828-
if (auto type = typealias->getUnderlyingTypeLoc().getType()) {
1829-
if (type->isAnyObject())
1830-
anyObject = true;
1828+
if (typealias->hasInterfaceType()) {
1829+
if (auto type = typealias->getUnderlyingType())
1830+
if (type->isAnyObject())
1831+
anyObject = true;
18311832
}
18321833
}
18331834

@@ -2091,15 +2092,15 @@ DirectlyReferencedTypeDecls UnderlyingTypeDeclsReferencedRequest::evaluate(
20912092
Evaluator &evaluator,
20922093
TypeAliasDecl *typealias) const {
20932094
// Prefer syntactic information when we have it.
2094-
if (auto typeRepr = typealias->getUnderlyingTypeLoc().getTypeRepr()) {
2095+
if (auto typeRepr = typealias->getUnderlyingTypeRepr()) {
20952096
return directReferencesForTypeRepr(evaluator, typealias->getASTContext(),
20962097
typeRepr, typealias);
20972098
}
20982099

20992100
// Fall back to semantic types.
21002101
// FIXME: In the long run, we shouldn't need this. Non-syntactic results
21012102
// should be cached.
2102-
if (auto type = typealias->getUnderlyingTypeLoc().getType()) {
2103+
if (auto type = typealias->getUnderlyingType()) {
21032104
return directReferencesForType(type);
21042105
}
21052106

lib/ClangImporter/ClangImporter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2659,7 +2659,7 @@ void ClangModuleUnit::getTopLevelDecls(SmallVectorImpl<Decl*> &results) const {
26592659
auto alias = dyn_cast<TypeAliasDecl>(importedDecl);
26602660
if (!alias || !alias->isCompatibilityAlias()) continue;
26612661

2662-
auto aliasedTy = alias->getUnderlyingTypeLoc().getType();
2662+
auto aliasedTy = alias->getUnderlyingType();
26632663
ext = nullptr;
26642664
importedDecl = nullptr;
26652665

lib/ClangImporter/ImportDecl.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1493,6 +1493,7 @@ static void addSynthesizedTypealias(NominalTypeDecl *nominal, Identifier name,
14931493
typealias->setAccess(AccessLevel::Public);
14941494
typealias->setValidationToChecked();
14951495
typealias->setImplicit();
1496+
typealias->computeType();
14961497

14971498
nominal->addMember(typealias);
14981499
}
@@ -2563,6 +2564,8 @@ namespace {
25632564
/*genericparams*/nullptr, DC);
25642565
typealias->setUnderlyingType(
25652566
underlying->getDeclaredInterfaceType());
2567+
typealias->setValidationToChecked();
2568+
typealias->computeType();
25662569

25672570
Impl.SpecialTypedefNames[Decl->getCanonicalDecl()] =
25682571
MappedTypeNameKind::DefineAndUse;
@@ -2582,6 +2585,8 @@ namespace {
25822585
/*genericparams*/nullptr, DC);
25832586
typealias->setUnderlyingType(
25842587
Impl.SwiftContext.getAnyObjectType());
2588+
typealias->setValidationToChecked();
2589+
typealias->computeType();
25852590

25862591
Impl.SpecialTypedefNames[Decl->getCanonicalDecl()] =
25872592
MappedTypeNameKind::DefineAndUse;
@@ -2649,7 +2654,9 @@ namespace {
26492654
Loc,
26502655
/*genericparams*/nullptr, DC);
26512656
Result->setUnderlyingType(SwiftType);
2652-
2657+
Result->setValidationToChecked();
2658+
Result->computeType();
2659+
26532660
// Make Objective-C's 'id' unavailable.
26542661
if (Impl.SwiftContext.LangOpts.EnableObjCInterop && isObjCId(Decl)) {
26552662
auto attr = AvailableAttr::createPlatformAgnostic(
@@ -2943,6 +2950,8 @@ namespace {
29432950
C.Id_ErrorType, loc,
29442951
/*genericparams=*/nullptr, enumDecl);
29452952
alias->setUnderlyingType(errorWrapper->getDeclaredInterfaceType());
2953+
alias->setValidationToChecked();
2954+
alias->computeType();
29462955
enumDecl->addMember(alias);
29472956

29482957
// Add the 'Code' enum to the error wrapper.
@@ -4027,7 +4036,9 @@ namespace {
40274036
Loc,
40284037
/*genericparams*/nullptr, DC);
40294038
Result->setUnderlyingType(SwiftTypeDecl->getDeclaredInterfaceType());
4030-
4039+
Result->setValidationToChecked();
4040+
Result->computeType();
4041+
40314042
return Result;
40324043
}
40334044

@@ -5163,6 +5174,8 @@ namespace {
51635174
}
51645175

51655176
typealias->setUnderlyingType(typeDecl->getDeclaredInterfaceType());
5177+
typealias->setValidationToChecked();
5178+
typealias->computeType();
51665179
return typealias;
51675180
}
51685181

@@ -5398,7 +5411,9 @@ Decl *SwiftDeclConverter::importCompatibilityTypeAlias(
53985411
}
53995412

54005413
alias->setUnderlyingType(typeDecl->getDeclaredInterfaceType());
5401-
5414+
alias->setValidationToChecked();
5415+
alias->computeType();
5416+
54025417
// Record that this is the official version of this declaration.
54035418
Impl.ImportedDecls[{decl->getCanonicalDecl(), getVersion()}] = alias;
54045419
markAsVariant(alias, correctSwiftName);
@@ -8234,7 +8249,7 @@ ClangImporter::Implementation::createConstant(Identifier name, DeclContext *dc,
82348249

82358250
auto maxFloatTypeDecl = context.get_MaxBuiltinFloatTypeDecl();
82368251
floatExpr->setBuiltinType(
8237-
maxFloatTypeDecl->getUnderlyingTypeLoc().getType());
8252+
maxFloatTypeDecl->getUnderlyingType());
82388253

82398254
auto *floatDecl = literalType->getAnyNominal();
82408255
floatExpr->setBuiltinInitializer(

0 commit comments

Comments
 (0)