Skip to content

Commit 8c2cff8

Browse files
authored
Merge pull request #29937 from CodaFi/semantic-gymnastics
[Sema] Always install property wrappers during qualified lookup
2 parents 850aba5 + 92b8d63 commit 8c2cff8

File tree

4 files changed

+67
-40
lines changed

4 files changed

+67
-40
lines changed

lib/AST/NameLookup.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1534,6 +1534,34 @@ bool DeclContext::lookupQualified(Type type,
15341534
return lookupQualified(nominalTypesToLookInto, member, options, decls);
15351535
}
15361536

1537+
static void installPropertyWrapperMembersIfNeeded(NominalTypeDecl *target,
1538+
DeclNameRef member) {
1539+
auto &Context = target->getASTContext();
1540+
auto baseName = member.getBaseName();
1541+
if (!member.isSimpleName() || baseName.isSpecial())
1542+
return;
1543+
1544+
if ((!baseName.getIdentifier().str().startswith("$") &&
1545+
!baseName.getIdentifier().str().startswith("_")) ||
1546+
baseName.getIdentifier().str().size() <= 1) {
1547+
return;
1548+
}
1549+
1550+
// $- and _-prefixed variables can be generated by properties that have
1551+
// attached property wrappers.
1552+
auto originalPropertyName =
1553+
Context.getIdentifier(baseName.getIdentifier().str().substr(1));
1554+
for (auto member : target->lookupDirect(originalPropertyName)) {
1555+
if (auto var = dyn_cast<VarDecl>(member)) {
1556+
if (var->hasAttachedPropertyWrapper()) {
1557+
auto sourceFile = var->getDeclContext()->getParentSourceFile();
1558+
if (sourceFile && sourceFile->Kind != SourceFileKind::Interface)
1559+
(void)var->getPropertyWrapperBackingProperty();
1560+
}
1561+
}
1562+
}
1563+
}
1564+
15371565
bool DeclContext::lookupQualified(ArrayRef<NominalTypeDecl *> typeDecls,
15381566
DeclNameRef member,
15391567
NLOptions options,
@@ -1584,6 +1612,7 @@ QualifiedLookupRequest::evaluate(Evaluator &eval, const DeclContext *DC,
15841612

15851613
// Visit all of the nominal types we know about, discovering any others
15861614
// we need along the way.
1615+
auto &ctx = DC->getASTContext();
15871616
bool wantProtocolMembers = (options & NL_ProtocolMembers);
15881617
while (!stack.empty()) {
15891618
auto current = stack.back();
@@ -1592,6 +1621,11 @@ QualifiedLookupRequest::evaluate(Evaluator &eval, const DeclContext *DC,
15921621
if (tracker)
15931622
tracker->addUsedMember({current, member.getBaseName()},isLookupCascading);
15941623

1624+
// Make sure we've resolved property wrappers, if we need them.
1625+
if (ctx.areSemanticQueriesEnabled()) {
1626+
installPropertyWrapperMembersIfNeeded(current, member);
1627+
}
1628+
15951629
// Look for results within the current nominal type and its extensions.
15961630
bool currentIsProtocol = isa<ProtocolDecl>(current);
15971631
auto flags = OptionSet<NominalTypeDecl::LookupDirectFlags>();

lib/Sema/TypeCheckNameLookup.cpp

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
#include "swift/AST/NameLookup.h"
2323
#include "swift/AST/NameLookupRequests.h"
2424
#include "swift/AST/ProtocolConformance.h"
25-
#include "swift/AST/SourceFile.h"
2625
#include "swift/Basic/TopCollection.h"
2726
#include <algorithm>
2827

@@ -230,47 +229,10 @@ convertToUnqualifiedLookupOptions(NameLookupOptions options) {
230229
return newOptions;
231230
}
232231

233-
static void installPropertyWrapperMembersIfNeeded(NominalTypeDecl *target,
234-
DeclName member) {
235-
if (!target) return;
236-
237-
auto &Context = target->getASTContext();
238-
auto baseName = member.getBaseName();
239-
if (!member.isSimpleName() || baseName.isSpecial())
240-
return;
241-
242-
if ((!baseName.getIdentifier().str().startswith("$") &&
243-
!baseName.getIdentifier().str().startswith("_")) ||
244-
baseName.getIdentifier().str().size() <= 1) {
245-
return;
246-
}
247-
248-
// $- and _-prefixed variables can be generated by properties that have
249-
// attached property wrappers.
250-
auto originalPropertyName =
251-
Context.getIdentifier(baseName.getIdentifier().str().substr(1));
252-
for (auto member : target->lookupDirect(originalPropertyName)) {
253-
if (auto var = dyn_cast<VarDecl>(member)) {
254-
if (var->hasAttachedPropertyWrapper()) {
255-
auto sourceFile = var->getDeclContext()->getParentSourceFile();
256-
if (sourceFile && sourceFile->Kind != SourceFileKind::Interface)
257-
(void)var->getPropertyWrapperBackingProperty();
258-
}
259-
}
260-
}
261-
}
262-
263232
LookupResult TypeChecker::lookupUnqualified(DeclContext *dc, DeclNameRef name,
264233
SourceLoc loc,
265234
NameLookupOptions options) {
266235
auto ulOptions = convertToUnqualifiedLookupOptions(options);
267-
268-
// Make sure we've resolved implicit members, if we need them.
269-
if (auto *current = dc->getInnermostTypeContext()) {
270-
installPropertyWrapperMembersIfNeeded(current->getSelfNominalTypeDecl(),
271-
name.getFullName());
272-
}
273-
274236
auto &ctx = dc->getASTContext();
275237
auto descriptor = UnqualifiedLookupDescriptor(name, dc, loc, ulOptions);
276238
auto lookup = evaluateOrDefault(ctx.evaluator,
@@ -365,7 +327,6 @@ LookupResult TypeChecker::lookupMember(DeclContext *dc,
365327
// Make sure we've resolved implicit members, if we need them.
366328
if (auto *current = type->getAnyNominal()) {
367329
current->synthesizeSemanticMembersIfNeeded(name.getFullName());
368-
installPropertyWrapperMembersIfNeeded(current, name.getFullName());
369330
}
370331

371332
LookupResultBuilder builder(result, dc, options);
@@ -445,7 +406,6 @@ LookupTypeResult TypeChecker::lookupMemberType(DeclContext *dc,
445406
// Make sure we've resolved implicit members, if we need them.
446407
if (auto *current = type->getAnyNominal()) {
447408
current->synthesizeSemanticMembersIfNeeded(name.getFullName());
448-
installPropertyWrapperMembersIfNeeded(current, name.getFullName());
449409
}
450410

451411
if (!dc->lookupQualified(type, name, subOptions, decls))
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
@propertyWrapper
2+
public struct WrapGod<T> {
3+
private var value: T
4+
5+
public init(wrappedValue: T) {
6+
value = wrappedValue
7+
}
8+
9+
public var wrappedValue: T {
10+
get { value }
11+
set { value = newValue }
12+
}
13+
14+
public var projectedValue: T {
15+
get { value }
16+
set { value = newValue }
17+
}
18+
}
19+
20+
class BaseClass {
21+
@WrapGod final var value: Int = 42
22+
init() {}
23+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend %s -verify -O -primary-file %s %S/Inputs/property_wrappers_multi_file_2.swift -c -o %t/use.o
3+
// RUN: %target-swift-frontend %s -verify -O -primary-file %S/Inputs/property_wrappers_multi_file_2.swift %s -c -o %t/def.o
4+
5+
final class Subclass: BaseClass {
6+
override init() {
7+
super.init()
8+
$value = 42
9+
}
10+
}

0 commit comments

Comments
 (0)