Skip to content

Commit 6670639

Browse files
committed
Clean up implementation, add more extensive tests
1 parent 9e55fb0 commit 6670639

File tree

2 files changed

+111
-15
lines changed

2 files changed

+111
-15
lines changed

lib/AST/UnqualifiedLookup.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -409,9 +409,7 @@ bool implicitSelfReferenceIsUnwrapped(const ValueDecl *selfDecl,
409409

410410
else if (auto OSP = dyn_cast<OptionalSomePattern>(pattern)) {
411411
if (auto subPattern = OSP->getSubPattern()) {
412-
if (subPattern->getBoundName() == Ctx.Id_self) {
413-
isSelfRebinding = true;
414-
}
412+
isSelfRebinding = subPattern->getBoundName() == Ctx.Id_self;
415413
}
416414
}
417415

@@ -445,12 +443,12 @@ bool implicitSelfReferenceIsUnwrapped(const ValueDecl *selfDecl,
445443
// permitted usage of implicit self. In closures this is most
446444
// often just `dc` itself, but in functions defined in the
447445
// closure body this would be some parent context.
448-
AbstractClosureExpr *closestParentClosure(DeclContext *dc) {
446+
ClosureExpr *closestParentClosure(DeclContext *dc) {
449447
if (!dc) {
450448
return nullptr;
451449
}
452450

453-
if (auto closure = dyn_cast<AbstractClosureExpr>(dc)) {
451+
if (auto closure = dyn_cast<ClosureExpr>(dc)) {
454452
return closure;
455453
}
456454

@@ -474,8 +472,7 @@ ValueDecl *UnqualifiedLookupFactory::ResultFinderForTypeContext::lookupBaseDecl(
474472
// self _always_ refers to the context's self `ParamDecl`, even if there
475473
// is another local decl with the name `self` that would be found by
476474
// `lookupSingleLocalDecl`.
477-
auto parentACE = closestParentClosure(factory->DC);
478-
auto closureExpr = dyn_cast_or_null<ClosureExpr>(parentACE);
475+
auto closureExpr = closestParentClosure(factory->DC);
479476
if (!closureExpr) {
480477
return nullptr;
481478
}

test/expr/closure/closures.swift

Lines changed: 107 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -841,6 +841,11 @@ public class TestImplicitSelfForWeakSelfCapture {
841841
method()
842842
self.method()
843843
}
844+
845+
subscript(index: Int) -> Int { // expected-error {{subscript' functions may only be declared within a type}}
846+
method()
847+
return index
848+
}
844849
}
845850

846851
doVoidStuffNonEscaping { [weak self] in
@@ -855,34 +860,128 @@ public class TestImplicitSelfForWeakSelfCapture {
855860
method()
856861
self.method()
857862
}
863+
864+
subscript(index: Int) -> Int { // expected-error {{subscript' functions may only be declared within a type}}
865+
method()
866+
return index
867+
}
868+
}
869+
870+
doVoidStuff { [weak self] in
871+
guard let self else { return }
872+
873+
func innerFunction1() {
874+
doVoidStuff { // expected-note {{capture 'self' explicitly to enable implicit 'self' in this closure}}
875+
method() // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note {{reference 'self.' explicitly}}
876+
}
877+
878+
// This example should probably compile without an error -- seems like a bug in the impl of SE-0269
879+
doVoidStuff { [self] in // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}}
880+
method() // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}}
881+
self.method()
882+
}
883+
884+
doVoidStuff { [weak self] in
885+
method() // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}}
886+
self?.method()
887+
}
888+
889+
doVoidStuff { [weak self] in
890+
guard let self else { return }
891+
method()
892+
893+
func innerMethod3() {
894+
method()
895+
self.method()
896+
}
897+
}
898+
}
858899
}
859900
}
860901
}
861902

862903
class NoImplicitSelfInInnerClass {
863904
func method() { }
864905

865-
private init() { // expected-note {{'self' declared here}} expected-note {{'self' declared here}}
906+
private init() { // expected-note {{'self' declared here}} expected-note {{'self' declared here}} expected-note {{'self' declared here}} expected-note {{'self' declared here}} expected-note {{'self' declared here}} expected-note {{'self' declared here}} expected-note {{'self' declared here}}
866907
doVoidStuff {
867-
class InnerType { // expected-note {{type declared here}}
868-
func functionInsideInnerType() {
869-
method() // expected-error {{class declaration cannot close over value 'self' defined in outer scope}}
870-
self.method() // expected-error {{value of type 'InnerType' has no member 'method'}}
871-
}
908+
class InnerType { // expected-note {{type declared here}} expected-note {{type declared here}} expected-note {{type declared here}}
909+
init() {
910+
method() // expected-error {{class declaration cannot close over value 'self' defined in outer scope}}
911+
self.method() // expected-error {{value of type 'InnerType' has no member 'method'}}
912+
}
913+
914+
func functionInsideInnerType() {
915+
method() // expected-error {{class declaration cannot close over value 'self' defined in outer scope}}
916+
self.method() // expected-error {{value of type 'InnerType' has no member 'method'}}
917+
}
918+
919+
subscript(index: Int) -> Int {
920+
method() // expected-error {{class declaration cannot close over value 'self' defined in outer scope}}
921+
self.method() // expected-error {{value of type 'InnerType' has no member 'method'}}
922+
return index
923+
}
872924
}
873925
}
874926

875927
doVoidStuff { [weak self] in
876928
guard let self else { return }
877929
method()
878930

879-
class InnerType { // expected-note {{type declared here}}
880-
func functionInsideInnerType() {
931+
class InnerType { // expected-note {{type declared here}} expected-note {{type declared here}} expected-note {{type declared here}}
932+
func methodOnInnerType() { }
933+
934+
init() {
935+
methodOnInnerType()
936+
method() // expected-error {{class declaration cannot close over value 'self' defined in outer scope}}
937+
self.method() // expected-error {{value of type 'InnerType' has no member 'method'}}
938+
}
939+
940+
func functionInsideInnerType() {
941+
methodOnInnerType()
942+
method() // expected-error {{class declaration cannot close over value 'self' defined in outer scope}}
943+
self.method() // expected-error {{value of type 'InnerType' has no member 'method'}}
944+
}
945+
946+
subscript(index: Int) -> Int {
947+
methodOnInnerType()
948+
method() // expected-error {{class declaration cannot close over value 'self' defined in outer scope}}
949+
self.method() // expected-error {{value of type 'InnerType' has no member 'method'}}
950+
return index
951+
}
952+
}
953+
}
954+
955+
doVoidStuff { [weak self] in
956+
guard let self else { return }
957+
958+
func innerMethod() {
959+
method()
960+
961+
class InnerType { // expected-note {{type declared here}}
962+
func methodOnInnerType() { }
963+
964+
init() {
965+
methodOnInnerType()
881966
method() // expected-error {{class declaration cannot close over value 'self' defined in outer scope}}
882967
self.method() // expected-error {{value of type 'InnerType' has no member 'method'}}
968+
969+
doVoidStuff { [weak self] in
970+
guard let self else { return }
971+
self.method() // expected-error {{value of type 'InnerType' has no member 'method'}}
972+
methodOnInnerType()
973+
}
974+
975+
doVoidStuff { [weak self] in
976+
guard let self else { return }
977+
method() // expected-error {{value of type 'InnerType' has no member 'method'}}
978+
methodOnInnerType()
979+
}
883980
}
981+
}
884982
}
885983
}
984+
886985
}
887986
}
888987

0 commit comments

Comments
 (0)