Skip to content

Commit d91d811

Browse files
committed
AST: Restore old behavior for name lookup inside 'lazy' in Swift 3 mode
Restore the old Swift 3 behavior for source compatibility reasons: - Unqualified lookup finds static properties (but not static methods) first, then global members. - Qualified lookup into 'self' is still supported. There's no change in Swift 4 mode, where the newer more correct behavior is enabled. Fixes <rdar://problem/32570766>.
1 parent 433b7f2 commit d91d811

File tree

5 files changed

+80
-5
lines changed

5 files changed

+80
-5
lines changed

lib/AST/NameLookup.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -642,9 +642,12 @@ UnqualifiedLookup::UnqualifiedLookup(DeclName Name, DeclContext *DC,
642642

643643
DC = DC->getParent();
644644

645-
BaseDecl = selfParam;
646645
ExtendedType = DC->getSelfTypeInContext();
647646
MetaBaseDecl = DC->getAsNominalTypeOrNominalTypeExtensionContext();
647+
if (Ctx.isSwiftVersion3())
648+
BaseDecl = MetaBaseDecl;
649+
else
650+
BaseDecl = selfParam;
648651

649652
isTypeLookup = PBD->isStatic();
650653
}
@@ -705,7 +708,7 @@ UnqualifiedLookup::UnqualifiedLookup(DeclName Name, DeclContext *DC,
705708
// might be type checking a default argument expression and
706709
// performing name lookup from there), the base declaration
707710
// is the nominal type, not 'self'.
708-
if (!AFD->isImplicit() &&
711+
if ((Ctx.isSwiftVersion3() || !AFD->isImplicit()) &&
709712
Loc.isValid() &&
710713
AFD->getBodySourceRange().isValid() &&
711714
!SM.rangeContainsTokenLoc(AFD->getBodySourceRange(), Loc)) {
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// RUN: %target-typecheck-verify-swift -parse-as-library -swift-version 3
2+
3+
class ReferenceSelfInLazyProperty {
4+
lazy var refs = (i, f())
5+
// expected-error@-1 {{cannot use instance member 'i' within property initializer; property initializers run before 'self' is available}}
6+
lazy var trefs: (Int, Int) = (i, f())
7+
// expected-error@-1 {{instance member 'i' cannot be used on type 'ReferenceSelfInLazyProperty'}}
8+
9+
lazy var qrefs = (self.i, self.f())
10+
lazy var qtrefs: (Int, Int) = (self.i, self.f())
11+
12+
lazy var crefs = { (i, f()) }()
13+
// expected-error@-1 {{instance member 'i' cannot be used on type 'ReferenceSelfInLazyProperty'}}
14+
15+
lazy var ctrefs: (Int, Int) = { (i, f()) }()
16+
// expected-error@-1 {{instance member 'i' cannot be used on type 'ReferenceSelfInLazyProperty'}}
17+
18+
lazy var cqrefs = { (self.i, self.f()) }()
19+
lazy var cqtrefs: (Int, Int) = { (self.i, self.f()) }()
20+
21+
lazy var mrefs = { () -> (Int, Int) in return (i, f()) }()
22+
// expected-error@-1 {{instance member 'i' cannot be used on type 'ReferenceSelfInLazyProperty'}}
23+
24+
lazy var mtrefs: (Int, Int) = { return (i, f()) }()
25+
// expected-error@-1 {{instance member 'i' cannot be used on type 'ReferenceSelfInLazyProperty'}}
26+
27+
lazy var mqrefs = { () -> (Int, Int) in (self.i, self.f()) }()
28+
lazy var mqtrefs: (Int, Int) = { return (self.i, self.f()) }()
29+
30+
lazy var lcqrefs = { [unowned self] in (self.i, self.f()) }()
31+
lazy var lcqtrefs: (Int, Int) = { [unowned self] in (self.i, self.f()) }()
32+
33+
lazy var lmrefs = { [unowned self] () -> (Int, Int) in return (i, f()) }()
34+
// expected-error@-1 {{instance member 'i' cannot be used on type 'ReferenceSelfInLazyProperty'}}
35+
lazy var lmtrefs: (Int, Int) = { [unowned self] in return (i, f()) }()
36+
// expected-error@-1 {{instance member 'i' cannot be used on type 'ReferenceSelfInLazyProperty'}}
37+
38+
lazy var lmqrefs = { [unowned self] () -> (Int, Int) in (self.i, self.f()) }()
39+
lazy var lmqtrefs: (Int, Int) = { [unowned self] in return (self.i, self.f()) }()
40+
41+
var i = 42
42+
func f() -> Int { return 0 }
43+
}
44+
45+
class ReferenceStaticInLazyProperty {
46+
lazy var refs1 = i
47+
lazy var refs2 = f()
48+
// expected-error@-1 {{use of unresolved identifier 'f'}}
49+
50+
lazy var trefs1: Int = i
51+
lazy var trefs2: Int = f()
52+
// expected-error@-1 {{use of unresolved identifier 'f'}}
53+
54+
static var i = 42
55+
static func f() -> Int { return 0 }
56+
// expected-note@-1 {{did you mean 'f'?}}
57+
}

test/NameBinding/name_lookup.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,7 @@ class r21677702 {
528528
// <rdar://problem/16954496> lazy properties must use "self." in their body, and can weirdly refer to class variables directly
529529
class r16954496 {
530530
func bar() {}
531-
lazy var x: Array<() -> Void> = [bar]
531+
lazy var x: Array<() -> Void> = [bar] // expected-error {{cannot convert value of type '(r16954496) -> () -> ()' to expected element type '() -> Void'}}
532532
}
533533

534534

test/SILGen/objc_properties.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ class HasLazyProperty : NSObject, HasProperty {
242242
return nil
243243
}
244244

245-
lazy var window = instanceMethod()
245+
lazy var window = self.instanceMethod()
246246
}
247247

248248
// CHECK-LABEL: sil hidden @_T015objc_properties15HasLazyPropertyC6windowSo8NSObjectCSgfg : $@convention(method) (@guaranteed HasLazyProperty) -> @owned Optional<NSObject> {

test/decl/var/lazy_properties.swift

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// RUN: %target-typecheck-verify-swift -parse-as-library -swift-version 3
21
// RUN: %target-typecheck-verify-swift -parse-as-library -swift-version 4
32

43
lazy func lazy_func() {} // expected-error {{'lazy' may only be used on 'var' declarations}} {{1-6=}}
@@ -162,3 +161,19 @@ class ReferenceSelfInLazyProperty : BaseClass {
162161

163162
lazy var refBaseClassProp = baseInstanceProp
164163
}
164+
165+
class ReferenceStaticInLazyProperty {
166+
lazy var refs1 = i
167+
// expected-error@-1 {{static member 'i' cannot be used on instance of type 'ReferenceStaticInLazyProperty'}}
168+
lazy var refs2 = f()
169+
// expected-error@-1 {{static member 'f' cannot be used on instance of type 'ReferenceStaticInLazyProperty'}}
170+
171+
lazy var trefs1: Int = i
172+
// expected-error@-1 {{static member 'i' cannot be used on instance of type 'ReferenceStaticInLazyProperty'}}
173+
174+
lazy var trefs2: Int = f()
175+
// expected-error@-1 {{static member 'f' cannot be used on instance of type 'ReferenceStaticInLazyProperty'}}
176+
177+
static var i = 42
178+
static func f() -> Int { return 0 }
179+
}

0 commit comments

Comments
 (0)