Skip to content

Commit f15544d

Browse files
committed
Strike VarDecls in Pattern Binding Initializers From Overloads
We would previously consider the VarDecls bound by a particular pattern binding initializer context when performing overload resolution. This would lead to circular validation. Validation was tacitly breaking the cycle by returning an error type (but, crucially, not setting that interface type). Instead, pre-reject circular candidates. This greatly improves the diagnostic we emit here in truly circular cases since we can ride on `UR_InstanceMemberOnType` to yield struct PatternBindingWithTwoVars2 { var x = y, y = 3 } // cannot use instance member 'y' within property initializer; property initializers run before 'self' is available
1 parent 7032e65 commit f15544d

File tree

3 files changed

+35
-11
lines changed

3 files changed

+35
-11
lines changed

lib/Sema/CSSimplify.cpp

+14-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "swift/AST/ExistentialLayout.h"
2121
#include "swift/AST/GenericEnvironment.h"
2222
#include "swift/AST/GenericSignature.h"
23+
#include "swift/AST/Initializer.h"
2324
#include "swift/AST/ParameterList.h"
2425
#include "swift/AST/PropertyWrappers.h"
2526
#include "swift/AST/ProtocolConformance.h"
@@ -4864,7 +4865,19 @@ performMemberLookup(ConstraintKind constraintKind, DeclName memberName,
48644865
// reasonable choice.
48654866
auto addChoice = [&](OverloadChoice candidate) {
48664867
auto decl = candidate.getDecl();
4867-
4868+
4869+
// In a pattern binding initializer, immediately reject all of its bound
4870+
// variables. These would otherwise allow circular references.
4871+
if (auto *PBI = dyn_cast<PatternBindingInitializer>(DC)) {
4872+
if (auto *VD = dyn_cast<VarDecl>(decl)) {
4873+
if (PBI->getBinding() == VD->getParentPatternBinding()) {
4874+
result.addUnviable(candidate,
4875+
MemberLookupResult::UR_InstanceMemberOnType);
4876+
return;
4877+
}
4878+
}
4879+
}
4880+
48684881
// If the result is invalid, skip it.
48694882
// FIXME(InterfaceTypeRequest): isInvalid() should be based on the interface type.
48704883
(void)decl->getInterfaceType();

test/NameBinding/name_lookup.swift

+5-2
Original file line numberDiff line numberDiff line change
@@ -616,12 +616,15 @@ struct PatternBindingWithTwoVars1 { var x = 3, y = x }
616616
// expected-error@-1 {{cannot use instance member 'x' within property initializer; property initializers run before 'self' is available}}
617617

618618
struct PatternBindingWithTwoVars2 { var x = y, y = 3 }
619-
// expected-error@-1 {{type 'PatternBindingWithTwoVars2' has no member 'y'}}
619+
// expected-error@-1 {{property 'y' references itself}}
620+
// expected-error@-2 {{cannot use instance member 'y' within property initializer; property initializers run before 'self' is available}}
620621

621622
// This one should be accepted, but for now PatternBindingDecl validation
622623
// circularity detection is not fine grained enough.
623624
struct PatternBindingWithTwoVars3 { var x = y, y = x }
624-
// expected-error@-1 {{type 'PatternBindingWithTwoVars3' has no member 'y'}}
625+
// expected-error@-1 {{cannot use instance member 'x' within property initializer; property initializers run before 'self' is available}}
626+
// expected-error@-2 {{cannot use instance member 'y' within property initializer; property initializers run before 'self' is available}}
627+
// expected-error@-3 {{property 'y' references itself}}
625628

626629
// https://bugs.swift.org/browse/SR-9015
627630
func sr9015() {

test/decl/overload.swift

+16-8
Original file line numberDiff line numberDiff line change
@@ -571,23 +571,23 @@ enum SR_10084_E_8 {
571571
}
572572

573573
enum SR_10084_E_9 {
574-
case A // expected-note {{found this candidate}} // expected-note {{'A' previously declared here}}
575-
static let A: SR_10084_E_9 = .A // expected-note {{found this candidate}} // expected-error {{invalid redeclaration of 'A'}} // expected-error {{ambiguous use of 'A'}}
574+
case A // expected-note {{'A' previously declared here}}
575+
static let A: SR_10084_E_9 = .A // expected-error {{invalid redeclaration of 'A'}}
576576
}
577577

578578
enum SR_10084_E_10 {
579-
static let A: SR_10084_E_10 = .A // expected-note {{found this candidate}} // expected-note {{'A' previously declared here}} // expected-error {{ambiguous use of 'A'}}
580-
case A // expected-note {{found this candidate}} // expected-error {{invalid redeclaration of 'A'}}
579+
static let A: SR_10084_E_10 = .A // expected-note {{'A' previously declared here}}
580+
case A // expected-error {{invalid redeclaration of 'A'}}
581581
}
582582

583583
enum SR_10084_E_11 {
584-
case A // expected-note {{found this candidate}} // expected-note {{'A' previously declared here}}
585-
static var A: SR_10084_E_11 = .A // expected-note {{found this candidate}} // expected-error {{invalid redeclaration of 'A'}} // expected-error {{ambiguous use of 'A'}}
584+
case A // expected-note {{'A' previously declared here}}
585+
static var A: SR_10084_E_11 = .A // expected-error {{invalid redeclaration of 'A'}}
586586
}
587587

588588
enum SR_10084_E_12 {
589-
static var A: SR_10084_E_12 = .A // expected-note {{found this candidate}} // expected-note {{'A' previously declared here}} // expected-error {{ambiguous use of 'A'}}
590-
case A // expected-note {{found this candidate}} // expected-error {{invalid redeclaration of 'A'}}
589+
static var A: SR_10084_E_12 = .A // expected-note {{'A' previously declared here}}
590+
case A // expected-error {{invalid redeclaration of 'A'}}
591591
}
592592

593593
enum SR_10084_E_13 {
@@ -609,3 +609,11 @@ enum SR_10084_E_16 {
609609
typealias Z = Int // expected-note {{'Z' previously declared here}}
610610
case Z // expected-error {{invalid redeclaration of 'Z'}}
611611
}
612+
613+
// N.B. Validating the pattern binding initializer for `raw` used to cause
614+
// recursive validation of the VarDecl. Check that we don't regress now that
615+
// this isn't the case.
616+
public struct Cyclic {
617+
static func pickMe(please: Bool) -> Int { return 42 }
618+
public static let pickMe = Cyclic.pickMe(please: true)
619+
}

0 commit comments

Comments
 (0)