Skip to content

Commit 9dd56f9

Browse files
committed
Move remaining logic in LookupResultEntry::getBaseDecl() to ASTScope::lookupUnqualified impl, add more extensive tests, fix failing tests
1 parent 03322bf commit 9dd56f9

File tree

5 files changed

+194
-123
lines changed

5 files changed

+194
-123
lines changed

include/swift/AST/NameLookup.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,8 @@ struct LookupResultEntry {
103103
/// extension (if it found something at that level).
104104
DeclContext *BaseDC;
105105

106-
/// The declaration that defines the base of the call to `Value`
106+
/// The declaration that defines the base of the call to `Value`.
107+
/// This is always available, as long as `BaseDC` is not null.
107108
ValueDecl *BaseDecl;
108109

109110
/// The declaration corresponds to the given name; i.e. the decl we are

lib/AST/NameLookup.cpp

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -56,28 +56,7 @@ ValueDecl *LookupResultEntry::getBaseDecl() const {
5656
if (BaseDC == nullptr)
5757
return nullptr;
5858

59-
if (BaseDecl)
60-
return BaseDecl;
61-
62-
if (auto *AFD = dyn_cast<AbstractFunctionDecl>(BaseDC))
63-
return AFD->getImplicitSelfDecl();
64-
65-
if (auto *PBI = dyn_cast<PatternBindingInitializer>(BaseDC)) {
66-
auto *selfDecl = PBI->getImplicitSelfDecl();
67-
assert(selfDecl);
68-
return selfDecl;
69-
}
70-
71-
if (auto *CE = dyn_cast<ClosureExpr>(BaseDC)) {
72-
auto *selfDecl = CE->getCapturedSelfDecl();
73-
assert(selfDecl);
74-
assert(selfDecl->isSelfParamCapture());
75-
return selfDecl;
76-
}
77-
78-
auto *nominalDecl = BaseDC->getSelfNominalTypeDecl();
79-
assert(nominalDecl);
80-
return nominalDecl;
59+
return BaseDecl;
8160
}
8261

8362
void LookupResult::filter(

lib/AST/UnqualifiedLookup.cpp

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "swift/AST/NameLookupRequests.h"
2525
#include "swift/AST/PropertyWrappers.h"
2626
#include "swift/AST/SourceFile.h"
27+
#include "swift/AST/Initializer.h"
2728
#include "swift/Basic/Debug.h"
2829
#include "swift/Basic/STLExtras.h"
2930
#include "swift/Basic/SourceManager.h"
@@ -345,20 +346,59 @@ void UnqualifiedLookupFactory::ResultFinderForTypeContext::findResults(
345346
for (auto Result : Lookup) {
346347
auto baseDC = const_cast<DeclContext *>(whereValueIsMember(Result));
347348

349+
// Retrieve the base decl for this lookup
350+
ValueDecl* baseDecl;
351+
348352
// Perform an unqualified lookup for the base decl of this result. This handles cases
349353
// where self was rebound (e.g. `guard let self = self`) earlier in the scope.
350-
// Only do this in closures, since implicit self isn't allowed to be rebound
351-
// in other contexts. Otherwise, we use the `ParamDecl` from `baseDC` if applicable.
354+
// - Only do this in closures that capture self weakly, since implicit self isn't
355+
// allowed to be rebound in other contexts. In other contexts, implicit self
356+
// _always_ refers to the context's self `ParamDecl`, even if there is another
357+
// local decl with the name `self` that would be found by `lookupSingleLocalDecl`.
352358
ValueDecl* localBaseDecl = nullptr;
353-
if (factory->DC->getContextKind() == DeclContextKind::AbstractClosureExpr && baseDC) {
354-
auto *localDecl = ASTScope::lookupSingleLocalDecl(factory->DC->getParentSourceFile(),
355-
DeclName(factory->Ctx.Id_self),
356-
factory->Loc);
357-
if (localDecl)
358-
localBaseDecl = localDecl;
359+
bool isInWeakSelfClosure = false;
360+
if (auto closureExpr = dyn_cast<ClosureExpr>(factory->DC)) {
361+
if (auto selfDecl = closureExpr->getCapturedSelfDecl()) {
362+
auto *attr = selfDecl->getAttrs().getAttribute<ReferenceOwnershipAttr>();
363+
isInWeakSelfClosure = attr->get() == ReferenceOwnership::Weak;
364+
}
365+
}
366+
367+
if (isInWeakSelfClosure) {
368+
localBaseDecl = ASTScope::lookupSingleLocalDecl(factory->DC->getParentSourceFile(),
369+
DeclName(factory->Ctx.Id_self),
370+
factory->Loc);
371+
}
372+
373+
if (baseDC == nullptr)
374+
baseDecl = nullptr;
375+
376+
else if (localBaseDecl)
377+
baseDecl = localBaseDecl;
378+
379+
else if (auto *AFD = dyn_cast<AbstractFunctionDecl>(baseDC))
380+
baseDecl = AFD->getImplicitSelfDecl();
381+
382+
else if (auto *PBI = dyn_cast<PatternBindingInitializer>(baseDC)) {
383+
auto *selfDecl = PBI->getImplicitSelfDecl();
384+
assert(selfDecl);
385+
baseDecl = selfDecl;
386+
}
387+
388+
else if (auto *CE = dyn_cast<ClosureExpr>(baseDC)) {
389+
auto *selfDecl = CE->getCapturedSelfDecl();
390+
assert(selfDecl);
391+
assert(selfDecl->isSelfParamCapture());
392+
baseDecl = selfDecl;
393+
}
394+
395+
else {
396+
auto *nominalDecl = baseDC->getSelfNominalTypeDecl();
397+
assert(nominalDecl);
398+
baseDecl = nominalDecl;
359399
}
360400

361-
results.emplace_back(baseDC, localBaseDecl, Result);
401+
results.emplace_back(baseDC, baseDecl, Result);
362402
#ifndef NDEBUG
363403
factory->addedResult(results.back());
364404
#endif

lib/Sema/MiscDiagnostics.cpp

Lines changed: 68 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1565,30 +1565,6 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
15651565

15661566
if (!DRE || !DRE->isImplicit())
15671567
return false;
1568-
1569-
// Defensive check for type. If the expression doesn't have type here, it
1570-
// should have been diagnosed somewhere else.
1571-
Type ty = DRE->getType();
1572-
assert(ty && "Implicit self parameter ref without type");
1573-
if (!ty)
1574-
return false;
1575-
1576-
// Metatype self captures don't extend the lifetime of an object.
1577-
if (ty->is<MetatypeType>())
1578-
return false;
1579-
1580-
// If self does not have reference semantics, it is very unlikely that
1581-
// capturing it will create a reference cycle.
1582-
if (!ty->hasReferenceSemantics())
1583-
return false;
1584-
1585-
// If this is an implicit self parameter to a `AbstractFunctionDecl`
1586-
// (`FuncDecl`, `ConstructorDecl`, or `DestructorDecl`,
1587-
// `@autoclosure @escaping () -> String = String()` as one example)
1588-
// then it isn't actually capturing the closure's 'self', and is fine.
1589-
if (isa<AbstractFunctionDecl>(DRE->getDecl())) {
1590-
return false;
1591-
}
15921568

15931569
// If this decl isn't named "self", then it isn't an implicit self capture
15941570
// and we have no reason to reject it.
@@ -1600,73 +1576,82 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
16001576
auto isExplicitWeakSelfCapture = false;
16011577
if (auto closureExpr = dyn_cast<ClosureExpr>(inClosure)) {
16021578
if (auto selfDecl = closureExpr->getCapturedSelfDecl()) {
1603-
// If `weak self` was captured explicitly, then implicit self
1604-
// is always allowed allowed once `self` is unwrapped.
1605-
// - If `self` is still an Optional, compilation would have failed already,
1606-
// so we don't need to check for that here.
16071579
if (selfDecl->getType()->is<WeakStorageType>()) {
16081580
isExplicitWeakSelfCapture = true;
16091581
}
1610-
1611-
// If this capture is using the name `self` actually referring
1612-
// to some other variable (e.g. with `[self = "hello"]`)
1613-
// then implicit self is not allowed.
1614-
else if (!selfDecl->isSelfParamCapture()) {
1615-
return true;
1616-
}
16171582
}
16181583
}
16191584

1620-
if (auto var = dyn_cast<VarDecl>(DRE->getDecl())) {
1621-
if (auto parentStmt = var->getParentPatternStmt()) {
1622-
if (isa<LabeledConditionalStmt>(parentStmt)) {
1623-
// If this `self` decl was not captured explicitly by this closure,
1624-
// but is actually from an outer `weak` capture's `if let self = self`
1625-
// or `guard let self = self` etc, then we don't allow implicit self.
1626-
if (!isExplicitWeakSelfCapture) {
1627-
return true;
1628-
}
1629-
1630-
// If this is an explicit `weak self` capture, then we need
1631-
// to validate that the unwrapped `self` decl is actually
1632-
// referring to `self`, and not something else like in
1633-
// `guard let self = .someOptionalVariable else { return }`
1634-
auto hasCorrectSelfBindingCondition = false;
1635-
for (auto cond : dyn_cast<LabeledConditionalStmt>(parentStmt)->getCond()) {
1636-
if (cond.getKind() == StmtConditionElement::CK_PatternBinding) {
1637-
if (auto optionalPattern = dyn_cast<OptionalSomePattern>(cond.getPattern())) {
1585+
// If this is an explicit `weak self` capture, then implicit self is allowed
1586+
// once the closure's self param is unwrapped. We need to validate that the
1587+
// unwrapped `self` decl specifically refers to an unwrapped copy of the
1588+
// closure's `self` param, and not something else like in
1589+
// `guard let self = .someOptionalVariable else { return }` or
1590+
// `let self = someUnrelatedVariable`. If self hasn't been unwrapped yet
1591+
// and is still an optional, we would have already hit an error elsewhere.
1592+
if (isExplicitWeakSelfCapture) {
1593+
bool hasCorrectSelfBindingCondition = false;
1594+
if (auto var = dyn_cast<VarDecl>(DRE->getDecl())) {
1595+
// if the `self` decls was defined in a `let`, `guard`, or `while` condition...
1596+
if (auto parentStmt = var->getParentPatternStmt())
1597+
if (auto parentConditionalStmt = dyn_cast<LabeledConditionalStmt>(parentStmt))
1598+
for (auto cond : parentConditionalStmt->getCond())
1599+
if (auto optionalPattern = dyn_cast_or_null<OptionalSomePattern>(cond.getPattern()))
16381600
// if the lhs of the optional binding is `self`...
1639-
if (optionalPattern->getSubPattern()->getBoundName() == Ctx.Id_self) {
1640-
if (auto loadExpr = dyn_cast<LoadExpr>(cond.getInitializer())) {
1641-
if (auto declRefExpr = dyn_cast<DeclRefExpr>(loadExpr->getSubExpr())) {
1601+
if (optionalPattern->getSubPattern()->getBoundName() == Ctx.Id_self)
1602+
if (auto loadExpr = dyn_cast<LoadExpr>(cond.getInitializer()))
1603+
if (auto declRefExpr = dyn_cast<DeclRefExpr>(loadExpr->getSubExpr()))
16421604
// and the rhs of the optional binding is `self`...
1643-
if (declRefExpr->getDecl()->getName().isSimpleName(Ctx.Id_self)) {
1644-
// then we can permit implicit self in this closure
1605+
if (declRefExpr->getDecl()->getName().isSimpleName(Ctx.Id_self))
1606+
// then we can permit implicit self in this case
16451607
hasCorrectSelfBindingCondition = true;
1646-
}
1647-
}
1648-
}
1649-
}
1650-
}
1651-
}
1652-
}
1653-
1654-
return !hasCorrectSelfBindingCondition;
1655-
}
16561608
}
16571609

1658-
if (!isEnclosingSelfReference(var, inClosure)) {
1659-
return false;
1660-
}
1610+
return !hasCorrectSelfBindingCondition;
16611611
}
16621612

1613+
// Defensive check for type. If the expression doesn't have type here, it
1614+
// should have been diagnosed somewhere else.
1615+
Type ty = DRE->getType();
1616+
assert(ty && "Implicit self parameter ref without type");
1617+
if (!ty)
1618+
return false;
1619+
1620+
// Metatype self captures don't extend the lifetime of an object.
1621+
if (ty->is<MetatypeType>())
1622+
return false;
1623+
1624+
// If self does not have reference semantics, it is very unlikely that
1625+
// capturing it will create a reference cycle.
1626+
if (!ty->hasReferenceSemantics())
1627+
return false;
1628+
1629+
if (auto closureExpr = dyn_cast<ClosureExpr>(inClosure))
1630+
if (auto selfDecl = closureExpr->getCapturedSelfDecl())
1631+
// If this capture is using the name `self` actually referring
1632+
// to some other variable (e.g. with `[self = "hello"]`)
1633+
// then implicit self is not allowed.
1634+
if (!selfDecl->isSelfParamCapture())
1635+
return true;
1636+
1637+
if (auto var = dyn_cast<VarDecl>(DRE->getDecl()))
1638+
if (!isEnclosingSelfReference(var, inClosure))
1639+
return false;
1640+
16631641
return true;
16641642
}
16651643

16661644
/// Return true if this is a closure expression that will require explicit
16671645
/// use or capture of "self." for qualification of member references.
16681646
static bool isClosureRequiringSelfQualification(
16691647
const AbstractClosureExpr *CE) {
1648+
// If this closure capture self weakly, then we have to validate each usage
1649+
// of implicit self individually, even in a nonescaping closure
1650+
if (auto closureExpr = dyn_cast<ClosureExpr>(CE))
1651+
if (auto selfDecl = closureExpr->getCapturedSelfDecl())
1652+
if (selfDecl->getType()->is<WeakStorageType>())
1653+
return true;
1654+
16701655
// If the closure's type was inferred to be noescape, then it doesn't
16711656
// need qualification.
16721657
if (AnyFunctionRef(const_cast<AbstractClosureExpr *>(CE))
@@ -1713,23 +1698,19 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
17131698
// Until Swift 6, only emit a warning when we get this with an
17141699
// explicit capture, since we used to not diagnose this at all.
17151700
auto shouldOnlyWarn = [&](Expr *selfRef) {
1716-
if (auto declRef = dyn_cast<DeclRefExpr>(selfRef)) {
1717-
if (auto decl = declRef->getDecl()) {
1718-
if (auto varDecl = dyn_cast<VarDecl>(decl)) {
1719-
// If the self decl was defined in an conditional binding in an `if`/`guard`/`while`,
1720-
// then we know this is an inner closure of some outer closure's `weak self` capture.
1721-
// Since this wasn't allowed in Swift 5.5, we should just always emit an error.
1722-
if (auto parentStmt = varDecl->getParentPatternStmt()) {
1723-
if (isa<LabeledConditionalStmt>(parentStmt)) {
1724-
return false;
1725-
}
1726-
}
1727-
1701+
// If this implicit self decl is from a closure that captured self weakly,
1702+
// then we should always emit an error, since implicit self was only
1703+
// allowed starting in Swift 5.8 and later.
1704+
if (auto closureExpr = dyn_cast<ClosureExpr>(ACE))
1705+
if (auto selfDecl = closureExpr->getCapturedSelfDecl())
1706+
if (selfDecl->getType()->is<WeakStorageType>())
1707+
return false;
1708+
1709+
if (auto declRef = dyn_cast<DeclRefExpr>(selfRef))
1710+
if (auto decl = declRef->getDecl())
1711+
if (auto varDecl = dyn_cast<VarDecl>(decl))
17281712
return !varDecl->isSelfParameter();
1729-
}
1730-
}
1731-
}
1732-
1713+
17331714
return false;
17341715
};
17351716

0 commit comments

Comments
 (0)