Skip to content

Commit e3c1c42

Browse files
authored
Merge pull request swiftlang#35894 from CodaFi/semantic-members-only
Look Through Class-Bound Archetypes When Installing Semantic Members
2 parents 731d7e8 + 34ade3c commit e3c1c42

File tree

4 files changed

+57
-6
lines changed

4 files changed

+57
-6
lines changed

include/swift/AST/Decl.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3200,6 +3200,17 @@ class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext {
32003200
/// declaration, or \c nullptr if it doesn't have one.
32013201
ConstructorDecl *getDefaultInitializer() const;
32023202

3203+
/// Force the synthesis of all members named \c member requiring semantic
3204+
/// analysis and install them in the member list of this nominal type.
3205+
///
3206+
/// \Note The use of this method in the compiler signals an architectural
3207+
/// problem with the caller. Use \c TypeChecker::lookup* instead of
3208+
/// introducing new usages.
3209+
///
3210+
/// FIXME: This method presents a problem with respect to the consistency
3211+
/// and idempotency of lookups in the compiler. If we instead had a model
3212+
/// where lookup requests would explicitly return semantic members or parsed
3213+
/// members this function could disappear.
32033214
void synthesizeSemanticMembersIfNeeded(DeclName member);
32043215

32053216
/// Retrieves the static 'shared' property of a global actor type, which

lib/Sema/TypeCheckNameLookup.cpp

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,32 @@ LookupResult TypeChecker::lookupUnqualified(DeclContext *dc, DeclNameRef name,
273273
return result;
274274
}
275275

276+
// An unfortunate hack to kick the decl checker into adding semantic members to
277+
// the current type before we attempt a semantic lookup. The places this method
278+
// looks needs to be in sync with \c extractDirectlyReferencedNominalTypes.
279+
// See the note in \c synthesizeSemanticMembersIfNeeded about a better, more
280+
// just, and peaceful world.
281+
static void installSemanticMembersIfNeeded(Type type, DeclNameRef name) {
282+
// Look-through class-bound archetypes to ensure we synthesize e.g.
283+
// inherited constructors.
284+
if (auto archetypeTy = type->getAs<ArchetypeType>()) {
285+
if (auto super = archetypeTy->getSuperclass()) {
286+
type = super;
287+
}
288+
}
289+
290+
if (type->isExistentialType()) {
291+
auto layout = type->getExistentialLayout();
292+
if (auto super = layout.explicitSuperclass) {
293+
type = super;
294+
}
295+
}
296+
297+
if (auto *current = type->getAnyNominal()) {
298+
current->synthesizeSemanticMembersIfNeeded(name.getFullName());
299+
}
300+
}
301+
276302
LookupResult
277303
TypeChecker::lookupUnqualifiedType(DeclContext *dc, DeclNameRef name,
278304
SourceLoc loc,
@@ -320,9 +346,7 @@ LookupResult TypeChecker::lookupMember(DeclContext *dc,
320346
subOptions &= ~NL_RemoveNonVisible;
321347

322348
// Make sure we've resolved implicit members, if we need them.
323-
if (auto *current = type->getAnyNominal()) {
324-
current->synthesizeSemanticMembersIfNeeded(name.getFullName());
325-
}
349+
installSemanticMembersIfNeeded(type, name);
326350

327351
LookupResultBuilder builder(result, dc, options);
328352
SmallVector<ValueDecl *, 4> lookupResults;
@@ -392,9 +416,7 @@ LookupTypeResult TypeChecker::lookupMemberType(DeclContext *dc,
392416
subOptions |= NL_IncludeUsableFromInline;
393417

394418
// Make sure we've resolved implicit members, if we need them.
395-
if (auto *current = type->getAnyNominal()) {
396-
current->synthesizeSemanticMembersIfNeeded(name.getFullName());
397-
}
419+
installSemanticMembersIfNeeded(type, name);
398420

399421
if (!dc->lookupQualified(type, name, subOptions, decls))
400422
return result;
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
class A {
2+
required init(_ x: Int) {}
3+
}
4+
5+
class B : A {}
6+
class C : A {}
7+
8+
protocol P {}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %target-swift-frontend -typecheck -verify -primary-file %s %S/Inputs/inherited-init-multifile-other.swift
2+
// RUN: %target-swift-frontend -typecheck -verify %s -primary-file %S/Inputs/inherited-init-multifile-other.swift
3+
4+
func make<Result: B>(ofClass cls: Result.Type) -> Result {
5+
return cls.init(1)
6+
}
7+
8+
func make(ofClass cls: (C & P).Type) -> C {
9+
return cls.init(1)
10+
}

0 commit comments

Comments
 (0)