Skip to content

Commit cc92f76

Browse files
committed
Revert changes for handling SE-0365 in Swift 5
Revert "Remove properties from AST nodes" This reverts commit e4b8a82. Revert "Suppress more false-positive 'self is unused' warnings" This reverts commit 35e028e. Revert "fix warning annotation in test" This reverts commit dfa1fda. Revert "Permit implicit self for weak self captures in nonescaping closures in Swift 5 (this is an error in Swift 6)" This reverts commit 94ef6c4.
1 parent 21e94de commit cc92f76

File tree

4 files changed

+38
-206
lines changed

4 files changed

+38
-206
lines changed

lib/AST/UnqualifiedLookup.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -408,13 +408,6 @@ ValueDecl *UnqualifiedLookupFactory::ResultFinderForTypeContext::lookupBaseDecl(
408408
}
409409
}
410410

411-
// We can only change the behavior of lookup in Swift 6 and later,
412-
// due to a bug in Swift 5 where implicit self is always allowed
413-
// for weak self captures in non-escaping closures.
414-
if (!factory->Ctx.LangOpts.isSwiftVersionAtLeast(6)) {
415-
return nullptr;
416-
}
417-
418411
if (isInWeakSelfClosure) {
419412
return ASTScope::lookupSingleLocalDecl(factory->DC->getParentSourceFile(),
420413
DeclName(factory->Ctx.Id_self),

lib/Sema/MiscDiagnostics.cpp

Lines changed: 21 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1526,15 +1526,6 @@ static void diagRecursivePropertyAccess(const Expr *E, const DeclContext *DC) {
15261526
const_cast<Expr *>(E)->walk(walker);
15271527
}
15281528

1529-
namespace DiagnosticsContext {
1530-
/// A mapping of replacement `ValueDecl`s to use in `VarDeclUsageAnalysis`
1531-
/// instead of the actual `ValueDecl` of the associated `DeclRefExpr`.
1532-
/// This lets `VarDeclUsageAnalysis` avoid emitting false-positive warnings
1533-
/// in certain circumstances.
1534-
static llvm::SmallDenseMap<DeclRefExpr *, ValueDecl *>
1535-
DeclMappingForUsageAnalysis;
1536-
}
1537-
15381529
/// Look for any property references in closures that lack a 'self.' qualifier.
15391530
/// Within a closure, we require that the source code contain 'self.' explicitly
15401531
/// (or that the closure explicitly capture 'self' in the capture list) because
@@ -1589,15 +1580,8 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
15891580
// let self = .someOptionalVariable else { return }` or `let self =
15901581
// someUnrelatedVariable`. If self hasn't been unwrapped yet and is still
15911582
// an optional, we would have already hit an error elsewhere.
1592-
//
1593-
// Always run the `implicitWeakSelfReferenceIsValid` check, since it
1594-
// annotates applicable decls / stmts with state used in
1595-
// `VarDeclUsageChecker`, and we need that state even in closures that
1596-
// don't directly capture self weakly (but are inner closures of a closure
1597-
// that does capture self weakly).
1598-
auto isValid = implicitWeakSelfReferenceIsValid(DRE, inClosure);
15991583
if (closureHasWeakSelfCapture(inClosure)) {
1600-
return !isValid;
1584+
return !implicitWeakSelfReferenceIsValid(DRE);
16011585
}
16021586

16031587
// Defensive check for type. If the expression doesn't have type here, it
@@ -1636,37 +1620,12 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
16361620
return true;
16371621
}
16381622

1639-
static bool
1640-
implicitWeakSelfReferenceIsValid(DeclRefExpr *DRE,
1641-
const AbstractClosureExpr *inClosure) {
1623+
static bool implicitWeakSelfReferenceIsValid(const DeclRefExpr *DRE) {
16421624
ASTContext &Ctx = DRE->getDecl()->getASTContext();
1643-
auto selfDecl = DRE->getDecl();
1644-
1645-
if (!Ctx.LangOpts.isSwiftVersionAtLeast(6)) {
1646-
// In Swift 5 language modes, the decl of this implicit `DeclRefExpr`
1647-
// incorrectly refers to the `self` `ParamDecl` of the closure
1648-
// (which is always non-optional), instead of the actual decl that
1649-
// an explicit `self` call would refer to. As a workaround, we can
1650-
// manually lookup what self "should" refer to, and then validate
1651-
// that decl instead.
1652-
auto lookupResult = ASTScope::lookupSingleLocalDecl(
1653-
inClosure->getParentSourceFile(), DeclName(Ctx.Id_self),
1654-
DRE->getLoc());
1655-
if (!lookupResult) {
1656-
return false;
1657-
}
1658-
1659-
// When `VarDeclUsageChecker` checks this DRE, we need to use
1660-
// the base we looked up here instead, since otherwise
1661-
// we'll emit confusing false-positive warnings.
1662-
DiagnosticsContext::DeclMappingForUsageAnalysis[DRE] = lookupResult;
1663-
1664-
selfDecl = lookupResult;
1665-
}
16661625

16671626
// Check if the implicit self decl refers to a var in a conditional stmt
16681627
LabeledConditionalStmt *conditionalStmt = nullptr;
1669-
if (auto var = dyn_cast<VarDecl>(selfDecl)) {
1628+
if (auto var = dyn_cast<VarDecl>(DRE->getDecl())) {
16701629
if (auto parentStmt = var->getParentPatternStmt()) {
16711630
conditionalStmt = dyn_cast<LabeledConditionalStmt>(parentStmt);
16721631
}
@@ -1686,7 +1645,7 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
16861645

16871646
if (auto LE = dyn_cast<LoadExpr>(cond.getInitializer())) {
16881647
if (auto selfDRE = dyn_cast<DeclRefExpr>(LE->getSubExpr())) {
1689-
return selfDRE->getDecl()->getName().isSimpleName(Ctx.Id_self);
1648+
return (selfDRE->getDecl()->getName().isSimpleName(Ctx.Id_self));
16901649
}
16911650
}
16921651
}
@@ -1707,8 +1666,14 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
17071666

17081667
/// Return true if this is a closure expression that will require explicit
17091668
/// use or capture of "self." for qualification of member references.
1710-
static bool
1711-
isClosureRequiringSelfQualification(const AbstractClosureExpr *CE) {
1669+
static bool isClosureRequiringSelfQualification(
1670+
const AbstractClosureExpr *CE) {
1671+
// If this closure capture self weakly, then we have to validate each
1672+
// usage of implicit self individually, even in a nonescaping closure
1673+
if (closureHasWeakSelfCapture(CE)) {
1674+
return true;
1675+
}
1676+
17121677
// If the closure's type was inferred to be noescape, then it doesn't
17131678
// need qualification.
17141679
if (AnyFunctionRef(const_cast<AbstractClosureExpr *>(CE))
@@ -1737,11 +1702,8 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
17371702
std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
17381703
if (auto *CE = dyn_cast<AbstractClosureExpr>(E)) {
17391704
// If this is a potentially-escaping closure expression, start looking
1740-
// for references to self if we aren't already. But if this closure
1741-
// captures self weakly, then we have to validate each usage of implicit
1742-
// self individually, even in a nonescaping closure
1743-
if (isClosureRequiringSelfQualification(CE) ||
1744-
closureHasWeakSelfCapture(CE))
1705+
// for references to self if we aren't already.
1706+
if (isClosureRequiringSelfQualification(CE))
17451707
Closures.push_back(CE);
17461708
}
17471709

@@ -1762,10 +1724,7 @@ static void diagnoseImplicitSelfUseInClosure(const Expr *E,
17621724
// weakly, then we should always emit an error, since implicit self was
17631725
// only allowed starting in Swift 5.8 and later.
17641726
if (closureHasWeakSelfCapture(ACE)) {
1765-
// Implicit self was incorrectly permitted for weak self captures
1766-
// in non-escaping closures in Swift 5.7, so in that case we can
1767-
// only warn until Swift 6.
1768-
return !isClosureRequiringSelfQualification(ACE);
1727+
return false;
17691728
}
17701729

17711730
// We know that isImplicitSelfParamUseLikelyToCauseCycle is true,
@@ -2635,15 +2594,7 @@ class VarDeclUsageChecker : public ASTWalker {
26352594

26362595
VarDecls[vd] |= Flag;
26372596
}
2638-
2639-
ValueDecl *getDecl(DeclRefExpr *DRE) {
2640-
if (auto decl = DiagnosticsContext::DeclMappingForUsageAnalysis[DRE]) {
2641-
return decl;
2642-
}
2643-
2644-
return DRE->getDecl();
2645-
}
2646-
2597+
26472598
void markBaseOfStorageUse(Expr *E, ConcreteDeclRef decl, unsigned flags);
26482599
void markBaseOfStorageUse(Expr *E, bool isMutating);
26492600

@@ -3324,7 +3275,7 @@ VarDeclUsageChecker::~VarDeclUsageChecker() {
33243275
auto initExpr = SC->getCond()[0].getInitializer();
33253276
if (initExpr->getStartLoc().isValid()) {
33263277
unsigned noParens = initExpr->canAppendPostfixExpression();
3327-
3278+
33283279
// If the subexpr is an "as?" cast, we can rewrite it to
33293280
// be an "is" test.
33303281
ConditionalCheckedCastExpr *CCE = nullptr;
@@ -3543,7 +3494,7 @@ void VarDeclUsageChecker::markStoredOrInOutExpr(Expr *E, unsigned Flags) {
35433494

35443495
// If we found a decl that is being assigned to, then mark it.
35453496
if (auto *DRE = dyn_cast<DeclRefExpr>(E)) {
3546-
addMark(getDecl(DRE), Flags);
3497+
addMark(DRE->getDecl(), Flags);
35473498
return;
35483499
}
35493500

@@ -3628,10 +3579,10 @@ std::pair<bool, Expr *> VarDeclUsageChecker::walkToExprPre(Expr *E) {
36283579
// If this is a DeclRefExpr found in a random place, it is a load of the
36293580
// vardecl.
36303581
if (auto *DRE = dyn_cast<DeclRefExpr>(E)) {
3631-
addMark(getDecl(DRE), RK_Read);
3582+
addMark(DRE->getDecl(), RK_Read);
36323583

36333584
// If the Expression is a read of a getter, track for diagnostics
3634-
if (auto VD = dyn_cast<VarDecl>(getDecl(DRE))) {
3585+
if (auto VD = dyn_cast<VarDecl>(DRE->getDecl())) {
36353586
AssociatedGetterRefExpr.insert(std::make_pair(VD, DRE));
36363587
}
36373588
}
@@ -3705,7 +3656,7 @@ void VarDeclUsageChecker::handleIfConfig(IfConfigDecl *ICD) {
37053656
// conservatively mark it read and written. This will silence "variable
37063657
// unused" and "could be marked let" warnings for it.
37073658
if (auto *DRE = dyn_cast<DeclRefExpr>(E))
3708-
VDUC.addMark(VDUC.getDecl(DRE), RK_Read | RK_Written);
3659+
VDUC.addMark(DRE->getDecl(), RK_Read|RK_Written);
37093660
else if (auto *declRef = dyn_cast<UnresolvedDeclRefExpr>(E)) {
37103661
auto name = declRef->getName();
37113662
auto loc = declRef->getLoc();

test/expr/closure/closures.swift

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,8 @@ class ExplicitSelfRequiredTest {
176176
doVoidStuff({ _ = "\(x)"}) // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{18-18= [self] in}} expected-note{{reference 'self.' explicitly}} {{26-26=self.}}
177177
doVoidStuff({ [y = self] in x += 1 }) // expected-warning {{capture 'y' was never used}} expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{20-20=self, }} expected-note{{reference 'self.' explicitly}} {{33-33=self.}}
178178
doStuff({ [y = self] in x+1 }) // expected-warning {{capture 'y' was never used}} expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{16-16=self, }} expected-note{{reference 'self.' explicitly}} {{29-29=self.}}
179-
doVoidStuff({ [self = ExplicitSelfRequiredTest()] in x += 1 }) // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}}
180-
doStuff({ [self = ExplicitSelfRequiredTest()] in x+1 }) // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}}
179+
doVoidStuff({ [self = ExplicitSelfRequiredTest()] in x += 1 }) // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-warning {{capture 'self' was never used}}
180+
doStuff({ [self = ExplicitSelfRequiredTest()] in x+1 }) // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-warning {{capture 'self' was never used}}
181181

182182
// Methods follow the same rules as properties, uses of 'self' without capturing must be marked with "self."
183183
doStuff { method() } // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{14-14= [self] in}} expected-note{{reference 'self.' explicitly}} {{15-15=self.}}
@@ -186,8 +186,8 @@ class ExplicitSelfRequiredTest {
186186
doVoidStuff { () -> () in _ = method() } // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{18-18= [self]}} expected-note{{reference 'self.' explicitly}} {{35-35=self.}}
187187
doVoidStuff { [y = self] in _ = method() } // expected-warning {{capture 'y' was never used}} expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{20-20=self, }} expected-note{{reference 'self.' explicitly}} {{37-37=self.}}
188188
doStuff({ [y = self] in method() }) // expected-warning {{capture 'y' was never used}} expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{16-16=self, }} expected-note{{reference 'self.' explicitly}} {{29-29=self.}}
189-
doVoidStuff({ [self = ExplicitSelfRequiredTest()] in _ = method() }) // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}}
190-
doStuff({ [self = ExplicitSelfRequiredTest()] in method() }) // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}}
189+
doVoidStuff({ [self = ExplicitSelfRequiredTest()] in _ = method() }) // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-warning {{capture 'self' was never used}}
190+
doStuff({ [self = ExplicitSelfRequiredTest()] in method() }) // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-warning {{capture 'self' was never used}}
191191
doVoidStuff { _ = self.method() }
192192
doVoidStuff { [self] in _ = method() }
193193
doVoidStuff { [self = self] in _ = method() }
@@ -261,12 +261,12 @@ class ExplicitSelfRequiredTest {
261261
// because its `sawError` flag is set to true. To preserve the "capture 'y' was never used" warnings
262262
// above, we put these cases in their own method.
263263
func weakSelfError() {
264-
doVoidStuff({ [weak self] in x += 1 }) // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}}
265-
doVoidStuffNonEscaping({ [weak self] in x += 1 }) // expected-warning {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}}
266-
doStuff({ [weak self] in x+1 }) // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}}
267-
doVoidStuff({ [weak self] in _ = method() }) // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}}
268-
doVoidStuffNonEscaping({ [weak self] in _ = method() }) // expected-warning {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}}
269-
doStuff({ [weak self] in method() }) // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}}
264+
doVoidStuff({ [weak self] in x += 1 }) // expected-error {{explicit use of 'self' is required when 'self' is optional, to make control flow explicit}} expected-note {{reference 'self?.' explicitly}}
265+
doVoidStuffNonEscaping({ [weak self] in x += 1 }) // expected-error {{explicit use of 'self' is required when 'self' is optional, to make control flow explicit}} expected-note {{reference 'self?.' explicitly}}
266+
doStuff({ [weak self] in x+1 }) // expected-error {{explicit use of 'self' is required when 'self' is optional, to make control flow explicit}} expected-note {{reference 'self?.' explicitly}}
267+
doVoidStuff({ [weak self] in _ = method() }) // expected-error {{explicit use of 'self' is required when 'self' is optional, to make control flow explicit}} expected-note{{reference 'self?.' explicitly}}
268+
doVoidStuffNonEscaping({ [weak self] in _ = method() }) // expected-error {{explicit use of 'self' is required when 'self' is optional, to make control flow explicit}} expected-note{{reference 'self?.' explicitly}}
269+
doStuff({ [weak self] in method() }) // expected-error {{explicit use of 'self' is required when 'self' is optional, to make control flow explicit}} expected-note{{reference 'self?.' explicitly}}
270270
}
271271
}
272272

@@ -742,12 +742,12 @@ public class TestImplicitCaptureOfExplicitCaptureOfSelfInEscapingClosure {
742742
}
743743

744744
public class TestImplicitSelfForWeakSelfCapture {
745-
static let staticOptional: TestImplicitSelfForWeakSelfCapture? = .init()
745+
static var staticOptional: TestImplicitSelfForWeakSelfCapture? = .init()
746746
func method() { }
747747

748748
private init() {
749749
doVoidStuff { [weak self] in
750-
method() // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}}
750+
method() // expected-error {{explicit use of 'self' is required when 'self' is optional, to make control flow explicit}} expected-note {{reference 'self?.' explicitly}}
751751
guard let self = self else { return }
752752
method()
753753
}
@@ -771,7 +771,7 @@ public class TestImplicitSelfForWeakSelfCapture {
771771
}
772772

773773
doVoidStuffNonEscaping { [weak self] in
774-
method() // expected-warning {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}}
774+
method() // expected-error {{explicit use of 'self' is required when 'self' is optional, to make control flow explicit}} expected-note {{reference 'self?.' explicitly}}
775775
guard let self = self else { return }
776776
method()
777777
}
@@ -791,7 +791,7 @@ public class TestImplicitSelfForWeakSelfCapture {
791791
doVoidStuffNonEscaping { [weak self] in
792792
let `self`: TestImplicitSelfForWeakSelfCapture? = self ?? TestImplicitSelfForWeakSelfCapture.staticOptional
793793
guard let self = self else { return }
794-
method() // expected-warning {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}}
794+
method() // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}}
795795
}
796796

797797
doVoidStuffNonEscaping { [weak self] in
@@ -803,7 +803,7 @@ public class TestImplicitSelfForWeakSelfCapture {
803803

804804
doVoidStuffNonEscaping { [weak self] in
805805
guard let self = self ?? TestImplicitSelfForWeakSelfCapture.staticOptional else { return }
806-
method() // expected-warning {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}}
806+
method() // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}}
807807
}
808808
}
809809
}
@@ -824,12 +824,12 @@ public class TestRebindingSelfIsDisallowed {
824824

825825
doVoidStuff { [weak self] in
826826
let `self` = "self shouldn't become a string"
827-
let _: Int = count // expected-error{{cannot convert value of type 'Void' to specified type 'Int'}}
827+
let _: Int = count // expected-error{{reference to property 'count' in closure requires explicit use of 'self' to make capture semantics explicit}}
828828
}
829829

830830
doVoidStuffNonEscaping { [weak self] in
831831
let `self` = "self shouldn't become a string"
832-
let _: Int = count // expected-error{{cannot convert value of type 'Void' to specified type 'Int'}}
832+
let _: Int = count // expected-error{{reference to property 'count' in closure requires explicit use of 'self' to make capture semantics explicit}}
833833
}
834834
}
835835

0 commit comments

Comments
 (0)