Skip to content

Commit 44d686f

Browse files
committed
[ConstraintSystem] Use new "specify label" fix/diagnostic to warn about backward scan
1 parent f292eb6 commit 44d686f

File tree

4 files changed

+50
-6
lines changed

4 files changed

+50
-6
lines changed

lib/Sema/CSDiagnostics.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2215,7 +2215,7 @@ class MissingOptionalUnwrapKeyPathFailure final : public ContextualFailure {
22152215
};
22162216

22172217
/// Diagnose situations when trailing closure has been matched to a specific
2218-
/// parameter via deprecated backward scan.
2218+
/// parameter via a deprecated backward scan.
22192219
///
22202220
/// \code
22212221
/// func multiple_trailing_with_defaults(

lib/Sema/CSFix.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1529,7 +1529,8 @@ UnwrapOptionalBaseKeyPathApplication::attempt(ConstraintSystem &cs, Type baseTy,
15291529

15301530
bool SpecifyLabelToAssociateTrailingClosure::diagnose(const Solution &solution,
15311531
bool asNote) const {
1532-
return false;
1532+
TrailingClosureRequiresExplicitLabel failure(solution, getLocator());
1533+
return failure.diagnose(asNote);
15331534
}
15341535

15351536
SpecifyLabelToAssociateTrailingClosure *

lib/Sema/CSSimplify.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1208,6 +1208,9 @@ ConstraintSystem::TypeMatchResult constraints::matchCallArguments(
12081208

12091209
// Match up the call arguments to the parameters.
12101210
SmallVector<ParamBinding, 4> parameterBindings;
1211+
TrailingClosureMatching selectedTrailingMatching =
1212+
TrailingClosureMatching::Forward;
1213+
12111214
{
12121215
ArgumentFailureTracker listener(cs, argsWithLabels, params, locator);
12131216
auto callArgumentMatch = constraints::matchCallArguments(
@@ -1224,10 +1227,10 @@ ConstraintSystem::TypeMatchResult constraints::matchCallArguments(
12241227
return cs.getTypeMatchAmbiguous();
12251228
}
12261229

1230+
selectedTrailingMatching = callArgumentMatch->trailingClosureMatching;
12271231
// Record the direction of matching used for this call.
1228-
cs.recordTrailingClosureMatch(
1229-
cs.getConstraintLocator(locator),
1230-
callArgumentMatch->trailingClosureMatching);
1232+
cs.recordTrailingClosureMatch(cs.getConstraintLocator(locator),
1233+
selectedTrailingMatching);
12311234

12321235
// If there was a disjunction because both forward and backward were
12331236
// possible, increase the score for forward matches to bias toward the
@@ -1316,6 +1319,15 @@ ConstraintSystem::TypeMatchResult constraints::matchCallArguments(
13161319
}
13171320
}
13181321

1322+
// In case solver matched trailing based on the backward scan,
1323+
// let's produce a warning which would suggest to add a label
1324+
// to disambiguate in the future.
1325+
if (selectedTrailingMatching == TrailingClosureMatching::Backward &&
1326+
argIdx == *argInfo->UnlabeledTrailingClosureIndex) {
1327+
cs.recordFix(SpecifyLabelToAssociateTrailingClosure::create(
1328+
cs, cs.getConstraintLocator(loc)));
1329+
}
1330+
13191331
// If argument comes for declaration it should loose
13201332
// `@autoclosure` flag, because in context it's used
13211333
// as a function type represented by autoclosure.
@@ -9963,7 +9975,8 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
99639975
case FixKind::AllowKeyPathRootTypeMismatch:
99649976
case FixKind::UnwrapOptionalBaseKeyPathApplication:
99659977
case FixKind::AllowCoercionToForceCast:
9966-
case FixKind::SpecifyKeyPathRootType: {
9978+
case FixKind::SpecifyKeyPathRootType:
9979+
case FixKind::SpecifyLabelToAssociateTrailingClosure: {
99679980
return recordFix(fix) ? SolutionKind::Error : SolutionKind::Solved;
99689981
}
99699982

test/expr/postfix/call/forward_trailing_closure_ambiguity.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,33 @@ func notAmbiguous3(
9292
func testNotAmbiguous3() {
9393
notAmbiguous3 { $0 }
9494
}
95+
96+
// Ambiguous subscript
97+
struct S {
98+
subscript( // expected-note {{'subscript(a:_:_:)' declared here}}
99+
a a: Int,
100+
fn1: (() -> Void)? = nil,
101+
fn2: (() -> Void)? = nil) -> Bool {
102+
get { return true }
103+
}
104+
105+
subscript( // expected-note {{'subscript(b:_:fn2:)' declared here}}
106+
b b: Int,
107+
fn1: (() -> Void)? = nil,
108+
fn2 fn2: (() -> Void)? = nil) -> Bool {
109+
get { return true }
110+
}
111+
112+
static func foo( // expected-note {{'foo(c:fn1:fn2:)' declared here}}
113+
c: Int,
114+
fn1: (() -> Void)? = nil,
115+
fn2: (() -> Void)? = nil) -> S {
116+
return S()
117+
}
118+
}
119+
120+
func test_ambiguous_subscript_unresolved_member(s: S) {
121+
_ = s[a: 42] {} // expected-warning {{backward matching of the unlabeled trailing closure is deprecated; label the argument with '_' to suppress this warning}} {{14-15=, }} {{18-18=]}}
122+
_ = s[b: 42] {} // expected-warning {{backward matching of the unlabeled trailing closure is deprecated; label the argument with 'fn2' to suppress this warning}} {{14-15=, fn2: }} {{18-18=]}}
123+
let _: S = .foo(c: 42) {} // expected-warning {{backward matching of the unlabeled trailing closure is deprecated; label the argument with 'fn2' to suppress this warning}} {{24-25=, fn2: }} {{28-28=)}}
124+
}

0 commit comments

Comments
 (0)