Skip to content

Commit 7fada0a

Browse files
authored
Merge pull request #35381 from xedin/rdar-73027153
[ConstraintSystem] Increase score only if members found on `Optional`…
2 parents 3c6cf85 + f663727 commit 7fada0a

File tree

4 files changed

+62
-13
lines changed

4 files changed

+62
-13
lines changed

include/swift/Sema/OverloadChoice.h

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,14 @@ class OverloadChoice {
7373
/// optional context type, turning a "Decl" kind into
7474
/// "DeclViaUnwrappedOptional".
7575
IsDeclViaUnwrappedOptional = 0x02,
76+
/// Indicates that there are viable members found on `Optional`
77+
/// type and its underlying type. And current overload choice
78+
/// is a backup one, which should be picked only if members
79+
/// found directly on `Optional` do not match.
80+
IsFallbackDeclViaUnwrappedOptional = 0x03,
7681
/// Indicates that this declaration was dynamic, turning a
7782
/// "Decl" kind into "DeclViaDynamic" kind.
78-
IsDeclViaDynamic = 0x03,
83+
IsDeclViaDynamic = 0x07,
7984
};
8085

8186
/// The base type to be used when referencing the declaration
@@ -175,17 +180,23 @@ class OverloadChoice {
175180

176181
/// Retrieve an overload choice for a declaration that was found
177182
/// by unwrapping an optional context type.
183+
///
184+
/// \param isFallback Indicates that this result should be used
185+
/// as a backup, if member found directly on `Optional` doesn't
186+
/// match.
178187
static OverloadChoice
179-
getDeclViaUnwrappedOptional(Type base, ValueDecl *value,
188+
getDeclViaUnwrappedOptional(Type base, ValueDecl *value, bool isFallback,
180189
FunctionRefKind functionRefKind) {
181190
OverloadChoice result;
182191
result.BaseAndDeclKind.setPointer(base);
183-
result.BaseAndDeclKind.setInt(IsDeclViaUnwrappedOptional);
192+
result.BaseAndDeclKind.setInt(isFallback
193+
? IsFallbackDeclViaUnwrappedOptional
194+
: IsDeclViaUnwrappedOptional);
184195
result.DeclOrKind = value;
185196
result.TheFunctionRefKind = functionRefKind;
186197
return result;
187198
}
188-
199+
189200
/// Retrieve an overload choice for a declaration that was found via
190201
/// dynamic member lookup. The `ValueDecl` is a `subscript(dynamicMember:)`
191202
/// method.
@@ -219,6 +230,7 @@ class OverloadChoice {
219230
case IsDeclViaBridge: return OverloadChoiceKind::DeclViaBridge;
220231
case IsDeclViaDynamic: return OverloadChoiceKind::DeclViaDynamic;
221232
case IsDeclViaUnwrappedOptional:
233+
case IsFallbackDeclViaUnwrappedOptional:
222234
return OverloadChoiceKind::DeclViaUnwrappedOptional;
223235
default: return OverloadChoiceKind::Decl;
224236
}
@@ -256,6 +268,12 @@ class OverloadChoice {
256268
return getKind() == OverloadChoiceKind::KeyPathDynamicMemberLookup;
257269
}
258270

271+
/// Determine whether this member is a backup in case
272+
/// members found directly on `Optional` didn't match.
273+
bool isFallbackMemberOnUnwrappedBase() const {
274+
return BaseAndDeclKind.getInt() == IsFallbackDeclViaUnwrappedOptional;
275+
}
276+
259277
/// Get the name of the overload choice.
260278
DeclName getName() const;
261279

lib/Sema/CSSimplify.cpp

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6672,8 +6672,9 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName,
66726672

66736673
// Local function that turns a ValueDecl into a properly configured
66746674
// OverloadChoice.
6675-
auto getOverloadChoice = [&](ValueDecl *cand, bool isBridged,
6676-
bool isUnwrappedOptional) -> OverloadChoice {
6675+
auto getOverloadChoice =
6676+
[&](ValueDecl *cand, bool isBridged, bool isUnwrappedOptional,
6677+
bool isFallbackUnwrap = false) -> OverloadChoice {
66776678
// If we're looking into an existential type, check whether this
66786679
// result was found via dynamic lookup.
66796680
if (instanceTy->isAnyObject()) {
@@ -6694,8 +6695,9 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName,
66946695
auto ovlBaseTy = MetatypeType::get(baseTy->castTo<MetatypeType>()
66956696
->getInstanceType()
66966697
->getOptionalObjectType());
6697-
return OverloadChoice::getDeclViaUnwrappedOptional(ovlBaseTy, cand,
6698-
functionRefKind);
6698+
return OverloadChoice::getDeclViaUnwrappedOptional(
6699+
ovlBaseTy, cand,
6700+
/*isFallback=*/isFallbackUnwrap, functionRefKind);
66996701
}
67006702

67016703
// While looking for subscript choices it's possible to find
@@ -6719,7 +6721,7 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName,
67196721

67206722
return OverloadChoice(baseTy, cand, functionRefKind);
67216723
};
6722-
6724+
67236725
// Add all results from this lookup.
67246726
for (auto result : lookup)
67256727
addChoice(getOverloadChoice(result.getValueDecl(),
@@ -6802,11 +6804,16 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName,
68026804
}
68036805

68046806
if (objectType->mayHaveMembers()) {
6807+
// If there are viable members directly on `Optional`, let's
6808+
// prioritize them and mark any results found on wrapped type
6809+
// as a fallback results.
6810+
bool isFallback = !result.ViableCandidates.empty();
68056811
LookupResult &optionalLookup = lookupMember(objectType, memberName);
68066812
for (auto result : optionalLookup)
68076813
addChoice(getOverloadChoice(result.getValueDecl(),
6808-
/*bridged*/false,
6809-
/*isUnwrappedOptional=*/true));
6814+
/*bridged*/ false,
6815+
/*isUnwrappedOptional=*/true,
6816+
/*isUnwrapFallback=*/isFallback));
68106817
}
68116818
}
68126819
}

lib/Sema/ConstraintSystem.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2799,8 +2799,7 @@ void ConstraintSystem::resolveOverload(ConstraintLocator *locator,
27992799
increaseScore(SK_DisfavoredOverload);
28002800
}
28012801

2802-
if (choice.getKind() == OverloadChoiceKind::DeclViaUnwrappedOptional &&
2803-
locator->isLastElement<LocatorPathElt::UnresolvedMember>()) {
2802+
if (choice.isFallbackMemberOnUnwrappedBase()) {
28042803
increaseScore(SK_UnresolvedMemberViaOptional);
28052804
}
28062805
}

test/Constraints/sr13815.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
// SR-13815
4+
5+
enum E {
6+
case foo(String)
7+
}
8+
9+
struct Test {
10+
var bar: E?
11+
}
12+
13+
struct S {
14+
func evaluate(_: Test) -> [Test] {
15+
return []
16+
}
17+
18+
func test(set: Set<String>) {
19+
let flattened = set.flatMap { element in
20+
evaluate(Test(bar: .foo(element)))
21+
}
22+
23+
let _: [Test] = flattened // Ok (find .`bar` after unwrap)
24+
}
25+
}

0 commit comments

Comments
 (0)