Skip to content

Commit 547ba1c

Browse files
committed
Intro a request to lazily compute default definition types
The new request, DefaultDefinitionTypeRequest, is triggered by calling AssociatedTypeDecl::getDefaultDefinitionType.
1 parent 6cca050 commit 547ba1c

File tree

9 files changed

+101
-51
lines changed

9 files changed

+101
-51
lines changed

include/swift/AST/Decl.h

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3045,17 +3045,19 @@ class AssociatedTypeDecl : public AbstractTypeParamDecl {
30453045
SourceLoc KeywordLoc;
30463046

30473047
/// The default definition.
3048-
TypeLoc DefaultDefinition;
3048+
TypeRepr *DefaultDefinition;
30493049

30503050
/// The where clause attached to the associated type.
30513051
TrailingWhereClause *TrailingWhere;
30523052

30533053
LazyMemberLoader *Resolver = nullptr;
30543054
uint64_t ResolverContextData;
30553055

3056+
friend class DefaultDefinitionTypeRequest;
3057+
30563058
public:
30573059
AssociatedTypeDecl(DeclContext *dc, SourceLoc keywordLoc, Identifier name,
3058-
SourceLoc nameLoc, TypeLoc defaultDefinition,
3060+
SourceLoc nameLoc, TypeRepr *defaultDefinition,
30593061
TrailingWhereClause *trailingWhere);
30603062
AssociatedTypeDecl(DeclContext *dc, SourceLoc keywordLoc, Identifier name,
30613063
SourceLoc nameLoc, TrailingWhereClause *trailingWhere,
@@ -3071,17 +3073,14 @@ class AssociatedTypeDecl : public AbstractTypeParamDecl {
30713073
bool hasDefaultDefinitionType() const {
30723074
// If we have a TypeRepr, return true immediately without kicking off
30733075
// a request.
3074-
return !DefaultDefinition.isNull() || getDefaultDefinitionType();
3076+
return DefaultDefinition || getDefaultDefinitionType();
30753077
}
30763078

30773079
/// Retrieve the default definition type.
30783080
Type getDefaultDefinitionType() const;
30793081

3080-
TypeLoc &getDefaultDefinitionLoc() {
3081-
return DefaultDefinition;
3082-
}
3083-
3084-
const TypeLoc &getDefaultDefinitionLoc() const {
3082+
/// Retrieve the default definition as written in the source.
3083+
TypeRepr *getDefaultDefinitionTypeRepr() const {
30853084
return DefaultDefinition;
30863085
}
30873086

include/swift/AST/TypeCheckRequests.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,30 @@ class RequirementSignatureRequest :
269269
void cacheResult(ArrayRef<Requirement> value) const;
270270
};
271271

272+
/// Compute the default definition type of an associated type.
273+
class DefaultDefinitionTypeRequest :
274+
public SimpleRequest<DefaultDefinitionTypeRequest,
275+
CacheKind::Cached,
276+
Type,
277+
AssociatedTypeDecl *> {
278+
public:
279+
using SimpleRequest::SimpleRequest;
280+
281+
private:
282+
friend SimpleRequest;
283+
284+
// Evaluation.
285+
llvm::Expected<Type> evaluate(Evaluator &evaluator, AssociatedTypeDecl *decl) const;
286+
287+
public:
288+
// Cycle handling
289+
void diagnoseCycle(DiagnosticEngine &diags) const;
290+
void noteCycleStep(DiagnosticEngine &diags) const;
291+
292+
// Caching.
293+
bool isCached() const { return true; }
294+
};
295+
272296
/// Describes the owner of a where clause, from which we can extract
273297
/// requirements.
274298
struct WhereClauseOwner {

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ SWIFT_TYPEID(IsFinalRequest)
2323
SWIFT_TYPEID(IsDynamicRequest)
2424
SWIFT_TYPEID(RequirementRequest)
2525
SWIFT_TYPEID(RequirementSignatureRequest)
26+
SWIFT_TYPEID(DefaultDefinitionTypeRequest)
2627
SWIFT_TYPEID(USRGenerationRequest)
2728
SWIFT_TYPEID(StructuralTypeRequest)
2829
SWIFT_TYPEID(DefaultTypeRequest)

lib/AST/Decl.cpp

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3531,7 +3531,7 @@ SourceRange GenericTypeParamDecl::getSourceRange() const {
35313531

35323532
AssociatedTypeDecl::AssociatedTypeDecl(DeclContext *dc, SourceLoc keywordLoc,
35333533
Identifier name, SourceLoc nameLoc,
3534-
TypeLoc defaultDefinition,
3534+
TypeRepr *defaultDefinition,
35353535
TrailingWhereClause *trailingWhere)
35363536
: AbstractTypeParamDecl(DeclKind::AssociatedType, dc, name, nameLoc),
35373537
KeywordLoc(keywordLoc), DefaultDefinition(defaultDefinition),
@@ -3544,8 +3544,9 @@ AssociatedTypeDecl::AssociatedTypeDecl(DeclContext *dc, SourceLoc keywordLoc,
35443544
LazyMemberLoader *definitionResolver,
35453545
uint64_t resolverData)
35463546
: AbstractTypeParamDecl(DeclKind::AssociatedType, dc, name, nameLoc),
3547-
KeywordLoc(keywordLoc), TrailingWhere(trailingWhere),
3548-
Resolver(definitionResolver), ResolverContextData(resolverData) {
3547+
KeywordLoc(keywordLoc), DefaultDefinition(nullptr),
3548+
TrailingWhere(trailingWhere), Resolver(definitionResolver),
3549+
ResolverContextData(resolverData) {
35493550
assert(Resolver && "missing resolver");
35503551
}
35513552

@@ -3558,21 +3559,17 @@ void AssociatedTypeDecl::computeType() {
35583559
}
35593560

35603561
Type AssociatedTypeDecl::getDefaultDefinitionType() const {
3561-
if (Resolver) {
3562-
const_cast<AssociatedTypeDecl *>(this)->DefaultDefinition
3563-
= TypeLoc::withoutLoc(
3564-
Resolver->loadAssociatedTypeDefault(this, ResolverContextData));
3565-
const_cast<AssociatedTypeDecl *>(this)->Resolver = nullptr;
3566-
}
3567-
return DefaultDefinition.getType();
3562+
return evaluateOrDefault(getASTContext().evaluator,
3563+
DefaultDefinitionTypeRequest{const_cast<AssociatedTypeDecl *>(this)},
3564+
Type());
35683565
}
35693566

35703567
SourceRange AssociatedTypeDecl::getSourceRange() const {
35713568
SourceLoc endLoc;
35723569
if (auto TWC = getTrailingWhereClause()) {
35733570
endLoc = TWC->getSourceRange().End;
3574-
} else if (getDefaultDefinitionLoc().hasLocation()) {
3575-
endLoc = getDefaultDefinitionLoc().getSourceRange().End;
3571+
} else if (auto defaultDefinition = getDefaultDefinitionTypeRepr()) {
3572+
endLoc = defaultDefinition->getEndLoc();
35763573
} else if (!getInherited().empty()) {
35773574
endLoc = getInherited().back().getSourceRange().End;
35783575
} else {

lib/AST/TypeCheckRequests.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,20 @@ void RequirementSignatureRequest::cacheResult(ArrayRef<Requirement> value) const
311311
proto->setRequirementSignature(value);
312312
}
313313

314+
//----------------------------------------------------------------------------//
315+
// DefaultDefinitionTypeRequest computation.
316+
//----------------------------------------------------------------------------//
317+
318+
void DefaultDefinitionTypeRequest::diagnoseCycle(DiagnosticEngine &diags) const {
319+
auto decl = std::get<0>(getStorage());
320+
diags.diagnose(decl, diag::circular_reference);
321+
}
322+
323+
void DefaultDefinitionTypeRequest::noteCycleStep(DiagnosticEngine &diags) const {
324+
auto decl = std::get<0>(getStorage());
325+
diags.diagnose(decl, diag::circular_reference_through);
326+
}
327+
314328
//----------------------------------------------------------------------------//
315329
// Requirement computation.
316330
//----------------------------------------------------------------------------//

lib/Sema/TypeCheckAccess.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,8 @@ class AccessControlChecker : public AccessControlCheckerBase,
626626
}
627627
});
628628
});
629-
checkTypeAccess(assocType->getDefaultDefinitionLoc(), assocType,
629+
checkTypeAccess(assocType->getDefaultDefinitionType(),
630+
assocType->getDefaultDefinitionTypeRepr(), assocType,
630631
/*mayBeInferred*/false,
631632
[&](AccessScope typeAccessScope,
632633
const TypeRepr *thisComplainRepr,
@@ -1215,7 +1216,8 @@ class UsableFromInlineChecker : public AccessControlCheckerBase,
12151216
highlightOffendingType(TC, diag, complainRepr);
12161217
});
12171218
});
1218-
checkTypeAccess(assocType->getDefaultDefinitionLoc(), assocType,
1219+
checkTypeAccess(assocType->getDefaultDefinitionType(),
1220+
assocType->getDefaultDefinitionTypeRepr(), assocType,
12191221
/*mayBeInferred*/false,
12201222
[&](AccessScope typeAccessScope,
12211223
const TypeRepr *complainRepr,
@@ -1775,7 +1777,8 @@ class ExportabilityChecker : public DeclVisitor<ExportabilityChecker> {
17751777
checkType(requirement, assocType, getDiagnoseCallback(assocType),
17761778
getDiagnoseCallback(assocType));
17771779
});
1778-
checkType(assocType->getDefaultDefinitionLoc(), assocType,
1780+
checkType(assocType->getDefaultDefinitionType(),
1781+
assocType->getDefaultDefinitionTypeRepr(), assocType,
17791782
getDiagnoseCallback(assocType), getDiagnoseCallback(assocType));
17801783

17811784
if (assocType->getTrailingWhereClause()) {

lib/Sema/TypeCheckDecl.cpp

Lines changed: 38 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,6 +1413,25 @@ RequirementSignatureRequest::evaluate(Evaluator &evaluator, ProtocolDecl *proto)
14131413
return reqSignature->getRequirements();
14141414
}
14151415

1416+
llvm::Expected<Type>
1417+
DefaultDefinitionTypeRequest::evaluate(Evaluator &evaluator,
1418+
AssociatedTypeDecl *assocType) const {
1419+
if (assocType->Resolver) {
1420+
auto defaultType = assocType->Resolver->loadAssociatedTypeDefault(
1421+
assocType, assocType->ResolverContextData);
1422+
assocType->Resolver = nullptr;
1423+
return defaultType;
1424+
}
1425+
1426+
TypeRepr *defaultDefinition = assocType->getDefaultDefinitionTypeRepr();
1427+
if (defaultDefinition) {
1428+
auto resolution = TypeResolution::forInterface(assocType->getDeclContext());
1429+
return resolution.resolveType(defaultDefinition, None);
1430+
}
1431+
1432+
return Type();
1433+
}
1434+
14161435
namespace {
14171436
/// How to generate the raw value for each element of an enum that doesn't
14181437
/// have one explicitly specified.
@@ -2652,6 +2671,25 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
26522671

26532672
// Trigger the checking for overridden declarations.
26542673
(void)AT->getOverriddenDecls();
2674+
2675+
auto defaultType = AT->getDefaultDefinitionType();
2676+
if (defaultType && !defaultType->hasError()) {
2677+
// associatedtype X = X is invalid
2678+
auto mentionsItself =
2679+
defaultType.findIf([&](Type defaultType) {
2680+
if (auto DMT = defaultType->getAs<DependentMemberType>()) {
2681+
return DMT->getAssocType() == AT;
2682+
}
2683+
return false;
2684+
});
2685+
2686+
if (mentionsItself) {
2687+
TC.diagnose(AT->getDefaultDefinitionTypeRepr()->getLoc(),
2688+
diag::recursive_decl_reference,
2689+
AT->getDescriptiveKind(), AT->getName());
2690+
AT->diagnose(diag::kind_declared_here, DescriptiveDeclKind::Type);
2691+
}
2692+
}
26552693
}
26562694

26572695
void checkUnsupportedNestedType(NominalTypeDecl *NTD) {
@@ -3754,32 +3792,6 @@ void TypeChecker::validateDecl(ValueDecl *D) {
37543792

37553793
DeclValidationRAII IBV(assocType);
37563794

3757-
// Check the default definition, if there is one.
3758-
TypeLoc &defaultDefinition = assocType->getDefaultDefinitionLoc();
3759-
if (!defaultDefinition.isNull()) {
3760-
if (validateType(
3761-
defaultDefinition,
3762-
TypeResolution::forInterface(
3763-
assocType->getDeclContext()),
3764-
None)) {
3765-
defaultDefinition.setInvalidType(Context);
3766-
} else {
3767-
// associatedtype X = X is invalid
3768-
auto mentionsItself =
3769-
defaultDefinition.getType().findIf([&](Type type) {
3770-
if (auto DMT = type->getAs<DependentMemberType>()) {
3771-
return DMT->getAssocType() == assocType;
3772-
}
3773-
return false;
3774-
});
3775-
3776-
if (mentionsItself) {
3777-
diagnose(defaultDefinition.getLoc(), diag::recursive_decl_reference,
3778-
assocType->getDescriptiveKind(), assocType->getName());
3779-
diagnose(assocType, diag::kind_declared_here, DescriptiveDeclKind::Type);
3780-
}
3781-
}
3782-
}
37833795
// Finally, set the interface type.
37843796
if (!assocType->hasInterfaceType())
37853797
assocType->computeType();

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5648,7 +5648,7 @@ void TypeChecker::inferDefaultWitnesses(ProtocolDecl *proto) {
56485648
diagnose(defaultedAssocType, diag::assoc_type_default_here,
56495649
assocType->getFullName(), defaultAssocType)
56505650
.highlight(
5651-
defaultedAssocType->getDefaultDefinitionLoc().getSourceRange());
5651+
defaultedAssocType->getDefaultDefinitionTypeRepr()->getSourceRange());
56525652

56535653
continue;
56545654
}

lib/Sema/TypeCheckProtocolInference.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1866,7 +1866,7 @@ bool AssociatedTypeInference::diagnoseAmbiguousSolutions(
18661866
// Otherwise, we have a default.
18671867
diags.diagnose(assocType, diag::associated_type_deduction_default,
18681868
type)
1869-
.highlight(assocType->getDefaultDefinitionLoc().getSourceRange());
1869+
.highlight(assocType->getDefaultDefinitionTypeRepr()->getSourceRange());
18701870
};
18711871

18721872
diagnoseWitness(firstMatch, firstType);

0 commit comments

Comments
 (0)