Skip to content

Commit 199bf6e

Browse files
authored
Merge pull request #18425 from DougGregor/extended-nominal
[Name lookup] Introduce a request for "extended nominal type decl"
2 parents e0d1b5c + bc630b7 commit 199bf6e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+440
-325
lines changed

include/swift/AST/Decl.h

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1640,7 +1640,10 @@ class ExtensionDecl final : public GenericContext, public Decl,
16401640

16411641
/// The type being extended.
16421642
TypeLoc ExtendedType;
1643-
1643+
1644+
/// The nominal type being extended.
1645+
NominalTypeDecl *ExtendedNominal = nullptr;
1646+
16441647
MutableArrayRef<TypeLoc> Inherited;
16451648

16461649
/// \brief The next extension in the linked list of extensions.
@@ -1677,6 +1680,7 @@ class ExtensionDecl final : public GenericContext, public Decl,
16771680
/// Slow path for \c takeConformanceLoader().
16781681
std::pair<LazyMemberLoader *, uint64_t> takeConformanceLoaderSlow();
16791682

1683+
friend class ExtendedNominalRequest;
16801684
public:
16811685
using Decl::getASTContext;
16821686

@@ -1698,8 +1702,19 @@ class ExtensionDecl final : public GenericContext, public Decl,
16981702
void setBraces(SourceRange braces) { Braces = braces; }
16991703

17001704
/// Retrieve the type being extended.
1705+
///
1706+
/// Only use this entry point when the complete type, as spelled in the source,
1707+
/// is required. For most clients, \c getExtendedNominal(), which provides
1708+
/// only the \c NominalTypeDecl, will suffice.
17011709
Type getExtendedType() const { return ExtendedType.getType(); }
17021710

1711+
/// Retrieve the nominal type declaration that is being extended.
1712+
NominalTypeDecl *getExtendedNominal() const;
1713+
1714+
/// Determine whether this extension has already been bound to a nominal
1715+
/// type declaration.
1716+
bool alreadyBoundToNominal() const { return NextExtension.getInt(); }
1717+
17031718
/// Retrieve the extended type location.
17041719
TypeLoc &getExtendedTypeLoc() { return ExtendedType; }
17051720

@@ -3615,6 +3630,23 @@ class ClassDecl final : public NominalTypeDecl {
36153630
/// might have implicitly @objc members, but will never itself be @objc.
36163631
ObjCClassKind checkObjCAncestry() const;
36173632

3633+
/// \brief Whether this class or its superclasses has some form of generic
3634+
/// context.
3635+
///
3636+
/// For example, given
3637+
///
3638+
/// class A<X> {}
3639+
/// class B : A<Int> {}
3640+
/// struct C<T> {
3641+
/// struct Inner {}
3642+
/// }
3643+
/// class D {}
3644+
/// class E: D {}
3645+
///
3646+
/// Calling hasGenericAncestry() on `B` returns `A<Int>`, on `C<T>.Inner`
3647+
/// returns `C<T>.Inner`, but on `E` it returns null.
3648+
ClassDecl *getGenericAncestor() const;
3649+
36183650
/// The type of metaclass to use for a class.
36193651
enum class MetaclassKind : uint8_t {
36203652
ObjC,
@@ -3679,7 +3711,7 @@ class ClassDecl final : public NominalTypeDecl {
36793711
///
36803712
/// This is true of imported Objective-C classes.
36813713
bool usesObjCGenericsModel() const {
3682-
return isObjC() && hasClangNode() && isGenericContext();
3714+
return hasClangNode() && isGenericContext() && isObjC();
36833715
}
36843716

36853717
/// True if the class is known to be implemented in Swift.

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1490,7 +1490,8 @@ ERROR(extension_specialization,none,
14901490
ERROR(extension_stored_property,none,
14911491
"extensions must not contain stored properties", ())
14921492
ERROR(extension_nongeneric_trailing_where,none,
1493-
"trailing 'where' clause for extension of non-generic type %0", (Type))
1493+
"trailing 'where' clause for extension of non-generic type %0",
1494+
(DeclName))
14941495
ERROR(extension_protocol_inheritance,none,
14951496
"extension of protocol %0 cannot have an inheritance clause", (Type))
14961497
ERROR(objc_generic_extension_using_type_parameter,none,

include/swift/AST/NameLookupRequests.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,33 @@ class SuperclassDeclRequest :
157157
void noteCycleStep(DiagnosticEngine &diags) const;
158158
};
159159

160+
/// Request the nominal declaration extended by a given extension declaration.
161+
class ExtendedNominalRequest :
162+
public SimpleRequest<ExtendedNominalRequest,
163+
CacheKind::SeparatelyCached,
164+
NominalTypeDecl *,
165+
ExtensionDecl *> {
166+
public:
167+
using SimpleRequest::SimpleRequest;
168+
169+
private:
170+
friend class SimpleRequest;
171+
172+
// Evaluation.
173+
NominalTypeDecl *evaluate(Evaluator &evaluator, ExtensionDecl *ext) const;
174+
175+
public:
176+
// Separate caching.
177+
bool isCached() const { return true; }
178+
Optional<NominalTypeDecl *> getCachedResult() const;
179+
void cacheResult(NominalTypeDecl *value) const;
180+
181+
// Cycle handling
182+
NominalTypeDecl *breakCycle() const { return nullptr; }
183+
void diagnoseCycle(DiagnosticEngine &diags) const;
184+
void noteCycleStep(DiagnosticEngine &diags) const;
185+
};
186+
160187
/// The zone number for name-lookup requests.
161188
#define SWIFT_NAME_LOOKUP_REQUESTS_TYPEID_ZONE 9
162189

include/swift/AST/NameLookupTypeIDZone.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@
1717
SWIFT_TYPEID(InheritedDeclsReferencedRequest)
1818
SWIFT_TYPEID(UnderlyingTypeDeclsReferencedRequest)
1919
SWIFT_TYPEID(SuperclassDeclRequest)
20+
SWIFT_TYPEID(ExtendedNominalRequest)

include/swift/AST/Types.h

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -806,23 +806,6 @@ class alignas(1 << TypeAlignInBits) TypeBase {
806806
Type getSuperclassForDecl(const ClassDecl *classDecl,
807807
bool useArchetypes = true);
808808

809-
/// \brief Whether this type or its superclasses has some form of generic
810-
/// context.
811-
///
812-
/// For example, given
813-
///
814-
/// class A<X> {}
815-
/// class B : A<Int> {}
816-
/// struct C<T> {
817-
/// struct Inner {}
818-
/// }
819-
/// class D {}
820-
/// class E: D {}
821-
///
822-
/// Calling hasGenericAncestry() on `B` returns `A<Int>`, on `C<T>.Inner`
823-
/// returns `C<T>.Inner`, but on `E` it returns null.
824-
Type getGenericAncestor();
825-
826809
/// \brief True if this type is the superclass of another type, or a generic
827810
/// type that could be bound to the superclass.
828811
///

lib/AST/ASTDumper.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1295,11 +1295,8 @@ void swift::printContext(raw_ostream &os, DeclContext *dc) {
12951295
break;
12961296

12971297
case DeclContextKind::ExtensionDecl:
1298-
if (auto extendedTy = cast<ExtensionDecl>(dc)->getExtendedType()) {
1299-
if (auto nominal = extendedTy->getAnyNominal()) {
1300-
printName(os, nominal->getName());
1301-
break;
1302-
}
1298+
if (auto extendedNominal = cast<ExtensionDecl>(dc)->getExtendedNominal()) {
1299+
printName(os, extendedNominal->getName());
13031300
}
13041301
os << " extension";
13051302
break;

lib/AST/ASTMangler.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1402,13 +1402,11 @@ void ASTMangler::appendContext(const DeclContext *ctx) {
14021402

14031403
case DeclContextKind::ExtensionDecl: {
14041404
auto ExtD = cast<ExtensionDecl>(ctx);
1405-
auto ExtTy = ExtD->getExtendedType();
1405+
auto decl = ExtD->getExtendedNominal();
14061406
// Recover from erroneous extension.
1407-
if (ExtTy.isNull() || ExtTy->hasError())
1407+
if (!decl)
14081408
return appendContext(ExtD->getDeclContext());
14091409

1410-
auto decl = ExtTy->getAnyNominal();
1411-
assert(decl && "extension of non-nominal type?");
14121410
if (!ExtD->isEquivalentToExtendedContext()) {
14131411
// Mangle the extension if:
14141412
// - the extension is defined in a different module from the original

lib/AST/ASTPrinter.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1817,8 +1817,7 @@ void PrintAST::printExtension(ExtensionDecl *decl) {
18171817
recordDeclLoc(decl, [&]{
18181818
// We cannot extend sugared types.
18191819
Type extendedType = decl->getExtendedType();
1820-
NominalTypeDecl *nominal = extendedType ? extendedType->getAnyNominal() : nullptr;
1821-
if (!nominal) {
1820+
if (!extendedType || !extendedType->getAnyNominal()) {
18221821
// Fallback to TypeRepr.
18231822
printTypeLoc(decl->getExtendedTypeLoc());
18241823
return;

lib/AST/ASTScope.cpp

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1760,11 +1760,6 @@ SmallVector<ValueDecl *, 4> ASTScope::getLocalBindings() const {
17601760
if (range.Start == range.End)
17611761
break;
17621762

1763-
// Bind this extension, if we haven't done so already.
1764-
if (!extension->getExtendedType())
1765-
if (auto resolver = extension->getASTContext().getLazyResolver())
1766-
resolver->bindExtension(extension);
1767-
17681763
// If there are generic parameters, add them.
17691764
for (auto genericParams = extension->getGenericParams();
17701765
genericParams;
@@ -1915,8 +1910,8 @@ void ASTScope::print(llvm::raw_ostream &out, unsigned level,
19151910
out << " extension of '";
19161911
if (auto typeRepr = extension->getExtendedTypeLoc().getTypeRepr())
19171912
typeRepr->print(out);
1918-
else
1919-
extension->getExtendedType()->print(out);
1913+
else if (auto nominal = extension->getExtendedNominal())
1914+
out << nominal->getName();
19201915
out << "'";
19211916
printRange();
19221917
break;

lib/AST/ASTVerifier.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2471,7 +2471,7 @@ class Verifier : public ASTWalker {
24712471
} else {
24722472
auto ext = cast<ExtensionDecl>(decl);
24732473
conformingDC = ext;
2474-
nominal = ext->getExtendedType()->getAnyNominal();
2474+
nominal = ext->getExtendedNominal();
24752475
}
24762476

24772477
auto proto = conformance->getProtocol();
@@ -2619,8 +2619,14 @@ class Verifier : public ASTWalker {
26192619
verifyProtocolList(nominal, nominal->getLocalProtocols());
26202620

26212621
// Make sure that the protocol conformances are complete.
2622-
for (auto conformance : nominal->getLocalConformances()) {
2623-
verifyConformance(nominal, conformance);
2622+
// Only do so within the source file of the nominal type,
2623+
// because anywhere else this can trigger new type-check requests.
2624+
if (auto sf = M.dyn_cast<SourceFile *>()) {
2625+
if (nominal->getParentSourceFile() == sf) {
2626+
for (auto conformance : nominal->getLocalConformances()) {
2627+
verifyConformance(nominal, conformance);
2628+
}
2629+
}
26242630
}
26252631

26262632
verifyCheckedBase(nominal);
@@ -3491,7 +3497,7 @@ void swift::verify(SourceFile &SF) {
34913497
bool swift::shouldVerify(const Decl *D, const ASTContext &Context) {
34923498
#if !(defined(NDEBUG) || defined(SWIFT_DISABLE_AST_VERIFIER))
34933499
if (const auto *ED = dyn_cast<ExtensionDecl>(D)) {
3494-
return shouldVerify(ED->getExtendedType()->getAnyNominal(), Context);
3500+
return shouldVerify(ED->getExtendedNominal(), Context);
34953501
}
34963502

34973503
const auto *VD = dyn_cast<ValueDecl>(D);

lib/AST/AccessRequests.cpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -206,12 +206,9 @@ DefaultAndMaxAccessLevelRequest::evaluate(Evaluator &evaluator,
206206

207207
AccessLevel maxAccess = AccessLevel::Public;
208208

209-
if (!ED->getExtendedType().isNull() &&
210-
!ED->getExtendedType()->hasError()) {
211-
if (NominalTypeDecl *nominal = ED->getExtendedType()->getAnyNominal()) {
212-
maxAccess = std::max(nominal->getFormalAccess(),
213-
AccessLevel::FilePrivate);
214-
}
209+
if (NominalTypeDecl *nominal = ED->getExtendedNominal()) {
210+
maxAccess = std::max(nominal->getFormalAccess(),
211+
AccessLevel::FilePrivate);
215212
}
216213

217214
if (const GenericParamList *genericParams = ED->getGenericParams()) {

lib/AST/ConformanceLookupTable.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -865,6 +865,11 @@ ConformanceLookupTable::getConformance(NominalTypeDecl *nominal,
865865
ctx.getInheritedConformance(type, inheritedConformance->getConcrete());
866866
} else {
867867
// Create or find the normal conformance.
868+
if (auto ext = dyn_cast<ExtensionDecl>(conformingDC)) {
869+
if (auto resolver = ctx.getLazyResolver())
870+
resolver->bindExtension(ext);
871+
}
872+
868873
Type conformingType = conformingDC->getDeclaredInterfaceType();
869874
SourceLoc conformanceLoc
870875
= conformingNominal == conformingDC

lib/AST/Decl.cpp

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -981,6 +981,12 @@ ExtensionDecl::takeConformanceLoaderSlow() {
981981
return { contextInfo->loader, contextInfo->allConformancesData };
982982
}
983983

984+
NominalTypeDecl *ExtensionDecl::getExtendedNominal() const {
985+
ASTContext &ctx = getASTContext();
986+
return ctx.evaluator(
987+
ExtendedNominalRequest{const_cast<ExtensionDecl *>(this)});;
988+
}
989+
984990
Type ExtensionDecl::getInheritedType(unsigned index) const {
985991
ASTContext &ctx = getASTContext();
986992
return ctx.evaluator(InheritedTypeRequest{const_cast<ExtensionDecl *>(this),
@@ -992,7 +998,7 @@ bool ExtensionDecl::isConstrainedExtension() const {
992998
if (!getGenericSignature())
993999
return false;
9941000

995-
auto nominal = getExtendedType()->getAnyNominal();
1001+
auto nominal = getExtendedNominal();
9961002
assert(nominal);
9971003

9981004
// If the generic signature differs from that of the nominal type, it's a
@@ -1002,7 +1008,7 @@ bool ExtensionDecl::isConstrainedExtension() const {
10021008
}
10031009

10041010
bool ExtensionDecl::isEquivalentToExtendedContext() const {
1005-
auto decl = getExtendedType()->getAnyNominal();
1011+
auto decl = getExtendedNominal();
10061012
return getParentModule() == decl->getParentModule()
10071013
&& !isConstrainedExtension()
10081014
&& !getDeclaredInterfaceType()->isExistentialType();
@@ -2373,11 +2379,9 @@ AccessLevel ValueDecl::getEffectiveAccess() const {
23732379
} else if (auto enclosingExt = dyn_cast<ExtensionDecl>(getDeclContext())) {
23742380
// Just check the base type. If it's a constrained extension, Sema should
23752381
// have already enforced access more strictly.
2376-
if (auto extendedTy = enclosingExt->getExtendedType()) {
2377-
if (auto nominal = extendedTy->getAnyNominal()) {
2378-
effectiveAccess =
2379-
restrictToEnclosing(effectiveAccess, nominal->getEffectiveAccess());
2380-
}
2382+
if (auto nominal = enclosingExt->getExtendedNominal()) {
2383+
effectiveAccess =
2384+
restrictToEnclosing(effectiveAccess, nominal->getEffectiveAccess());
23812385
}
23822386

23832387
} else if (getDeclContext()->isLocalContext()) {
@@ -2430,13 +2434,11 @@ getAccessScopeForFormalAccess(const ValueDecl *VD,
24302434
} else if (auto enclosingExt = dyn_cast<ExtensionDecl>(resultDC)) {
24312435
// Just check the base type. If it's a constrained extension, Sema should
24322436
// have already enforced access more strictly.
2433-
if (auto extendedTy = enclosingExt->getExtendedType()) {
2434-
if (auto nominal = extendedTy->getAnyNominal()) {
2435-
auto nominalAccess =
2436-
getAdjustedFormalAccess(nominal, useDC,
2437-
treatUsableFromInlineAsPublic);
2438-
access = std::min(access, nominalAccess);
2439-
}
2437+
if (auto nominal = enclosingExt->getExtendedNominal()) {
2438+
auto nominalAccess =
2439+
getAdjustedFormalAccess(nominal, useDC,
2440+
treatUsableFromInlineAsPublic);
2441+
access = std::min(access, nominalAccess);
24402442
}
24412443

24422444
} else {
@@ -2881,7 +2883,7 @@ ExtensionRange NominalTypeDecl::getExtensions() {
28812883
}
28822884

28832885
void NominalTypeDecl::addExtension(ExtensionDecl *extension) {
2884-
assert(!extension->NextExtension.getInt() && "Already added extension");
2886+
assert(!extension->alreadyBoundToNominal() && "Already added extension");
28852887
extension->NextExtension.setInt(true);
28862888

28872889
// First extension; set both first and last.
@@ -3374,6 +3376,18 @@ ClassDecl::findImplementingMethod(const AbstractFunctionDecl *Method) const {
33743376
return nullptr;
33753377
}
33763378

3379+
ClassDecl *ClassDecl::getGenericAncestor() const {
3380+
ClassDecl *current = const_cast<ClassDecl *>(this);
3381+
3382+
while (current) {
3383+
if (current->isGenericContext())
3384+
return current;
3385+
3386+
current = current->getSuperclassDecl();
3387+
}
3388+
3389+
return nullptr;
3390+
}
33773391

33783392
EnumCaseDecl *EnumCaseDecl::create(SourceLoc CaseLoc,
33793393
ArrayRef<EnumElementDecl *> Elements,

0 commit comments

Comments
 (0)