Skip to content

Commit a53b1e4

Browse files
committed
[Sema] Always look through optionals for unresolved member lookup
1 parent 040ac4b commit a53b1e4

File tree

5 files changed

+59
-3
lines changed

5 files changed

+59
-3
lines changed

include/swift/Sema/ConstraintSystem.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,8 @@ enum ScoreKind {
785785
SK_ForwardTrailingClosure,
786786
/// A use of a disfavored overload.
787787
SK_DisfavoredOverload,
788+
/// A member for an \c UnresolvedMemberExpr found via unwrapped optional base.
789+
SK_UnresolvedMemberViaOptional,
788790
/// An implicit force of an implicitly unwrapped optional value.
789791
SK_ForceUnchecked,
790792
/// A user-defined conversion.

lib/Sema/CSRanking.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ static StringRef getScoreKindName(ScoreKind kind) {
5252
case SK_DisfavoredOverload:
5353
return "disfavored overload";
5454

55+
case SK_UnresolvedMemberViaOptional:
56+
return "unwrapping optional at unresolved member base";
57+
5558
case SK_ForceUnchecked:
5659
return "force of an implicitly unwrapped optional";
5760

lib/Sema/CSSimplify.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6777,13 +6777,12 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName,
67776777
// through optional types.
67786778
//
67796779
// FIXME: Unify with the above code path.
6780-
if (result.ViableCandidates.empty() &&
6781-
baseObjTy->is<AnyMetatypeType>() &&
6780+
if (baseObjTy->is<AnyMetatypeType>() &&
67826781
constraintKind == ConstraintKind::UnresolvedValueMember) {
67836782
if (auto objectType = instanceTy->getOptionalObjectType()) {
67846783
// If we don't have a wrapped type yet, we can't look through the optional
67856784
// type.
6786-
if (objectType->getAs<TypeVariableType>()) {
6785+
if (objectType->getAs<TypeVariableType>() && result.ViableCandidates.empty()) {
67876786
MemberLookupResult result;
67886787
result.OverallResult = MemberLookupResult::Unsolved;
67896788
return result;

lib/Sema/ConstraintSystem.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2802,6 +2802,11 @@ void ConstraintSystem::resolveOverload(ConstraintLocator *locator,
28022802
choice.getDecl()->getAttrs().hasAttribute<DisfavoredOverloadAttr>()) {
28032803
increaseScore(SK_DisfavoredOverload);
28042804
}
2805+
2806+
if (choice.getKind() == OverloadChoiceKind::DeclViaUnwrappedOptional &&
2807+
locator->isLastElement<LocatorPathElt::UnresolvedMember>()) {
2808+
increaseScore(SK_UnresolvedMemberViaOptional);
2809+
}
28052810
}
28062811

28072812
Type ConstraintSystem::simplifyTypeImpl(Type type,
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// RUN: %target-typecheck-verify-swift -dump-ast > %t.dump
2+
// RUN: %FileCheck %s < %t.dump
3+
4+
// SR-13815
5+
extension Optional {
6+
func sr13815() -> SR13815? { SR13815() }
7+
static func sr13815_2() -> SR13815? { SR13815() }
8+
static func sr13815_3() -> SR13815? { SR13815() }
9+
static var sr13815_wrongType: Int { 0 }
10+
static var sr13815_overload: SR13815 { SR13815() }
11+
init(overloaded: Void) { self = nil }
12+
}
13+
14+
struct SR13815 {
15+
static var sr13815: SR13815? = SR13815()
16+
static var sr13815_2: SR13815? = SR13815()
17+
static var sr13815_wrongType: SR13815? { SR13815() }
18+
static var p_SR13815: SR13815? { SR13815() }
19+
static func sr13815_3() -> SR13815? { SR13815() }
20+
static var sr13815_overload: SR13815? { SR13815() }
21+
init(overloaded: Void) {}
22+
init?(failable: Void) {}
23+
init() {}
24+
}
25+
26+
protocol P_SR13815 {}
27+
extension Optional: P_SR13815 where Wrapped: Equatable {
28+
static func p_SR13815() {}
29+
}
30+
31+
let _: SR13815? = .sr13815
32+
let _: SR13815? = .sr13815_wrongType
33+
let _: SR13815? = .init()
34+
let _: SR13815? = .sr13815() // expected-error {{instance member 'sr13815' cannot be used on type 'SR13815?'}}
35+
let _: SR13815? = .sr13815_2()
36+
let _: SR13815? = .init(SR13815())
37+
let _: SR13815? = .init(overloaded: ())
38+
// If members exist on Optional and Wrapped, always choose the one on optional
39+
// CHECK: declref_expr {{.*}} location={{.*}}optional_overload.swift:37
40+
// CHECK-SAME: decl=optional_overload.(file).Optional extension.init(overloaded:)
41+
let _: SR13815? = .sr13815_overload
42+
// Should choose the overload from Optional even if the Wrapped overload would otherwise have a better score
43+
// CHECK: member_ref_expr {{.*}} location={{.*}}optional_overload.swift:41
44+
// CHECK-SAME: decl=optional_overload.(file).Optional extension.sr13815_overload
45+
let _: SR13815? = .init(failable: ())
46+
let _: SR13815? = .sr13815_3()
47+
let _: SR13815? = .p_SR13815

0 commit comments

Comments
 (0)