Skip to content

Commit 4b49b66

Browse files
authored
Merge pull request swiftlang#10140 from slavapestov/source-compatibility-the-lazy-way
Fix a crash and make 'lazy' changes Swift 3-compatible
2 parents f7b723a + d91d811 commit 4b49b66

File tree

8 files changed

+113
-6
lines changed

8 files changed

+113
-6
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)) {

lib/Sema/TypeCheckNameLookup.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
//
1717
//===----------------------------------------------------------------------===//
1818
#include "TypeChecker.h"
19+
#include "swift/AST/Initializer.h"
1920
#include "swift/AST/NameLookup.h"
2021
#include "swift/AST/ProtocolConformance.h"
2122
#include "swift/Basic/TopCollection.h"
@@ -192,7 +193,10 @@ LookupResult TypeChecker::lookupUnqualified(DeclContext *dc, DeclName name,
192193
auto baseDC = baseParam->getDeclContext();
193194
if (isa<AbstractFunctionDecl>(baseDC))
194195
baseDC = baseDC->getParent();
196+
if (isa<PatternBindingInitializer>(baseDC))
197+
baseDC = baseDC->getParent();
195198
foundInType = baseDC->getDeclaredTypeInContext();
199+
assert(foundInType && "bogus base declaration?");
196200
} else {
197201
auto baseNominal = cast<NominalTypeDecl>(found.getBaseDecl());
198202
for (auto currentDC = dc; currentDC; currentDC = currentDC->getParent()) {
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: 18 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=}}
@@ -159,4 +158,22 @@ class ReferenceSelfInLazyProperty : BaseClass {
159158

160159
var i = 42
161160
func f() -> Int { return 0 }
161+
162+
lazy var refBaseClassProp = baseInstanceProp
163+
}
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 }
162179
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// RUN: %target-swift-frontend %s -emit-ir
2+
3+
class Expression<A, R> {
4+
typealias Arg = A
5+
typealias Ret = R
6+
subscript(x: Arg) -> Ret! { return nil }
7+
}
8+
class Op<A, R> : Expression<A, R> {
9+
typealias OpType = (Arg) -> Ret
10+
let op: OpType
11+
init(op: @escaping OpType) {
12+
self.op = op
13+
super.init()
14+
}
15+
}
16+
17+
class BinaryOp<A1, A2, R> : Op<((A1, A2)), R> {
18+
override init(op: @escaping OpType) {
19+
super.init(op: op)
20+
}
21+
override subscript(x: Arg) -> Ret! {
22+
return op(x)
23+
}
24+
}
25+
let add = BinaryOp<Int, Int, Int> { return $0.0 + $0.1 }
26+
print(add[(1,1)])

validation-test/compiler_crashers/28763-swift-typebase-getcanonicaltype.swift renamed to validation-test/compiler_crashers_fixed/28763-swift-typebase-getcanonicaltype.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@
55
// See https://swift.org/LICENSE.txt for license information
66
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
77

8-
// RUN: not --crash %target-swift-frontend %s -emit-ir
8+
// RUN: not %target-swift-frontend %s -emit-ir
99
protocol P{func a}extension P{lazy var f=a

0 commit comments

Comments
 (0)