Skip to content

Commit c9b73da

Browse files
committed
[Sema] ban multi-arguments to tuple coercion
Implements part of SE-0110. Single argument in closures will not be accepted if there exists explicit type with a number of arguments that's not 1. ```swift let f: (Int, Int) -> Void = { x in } // this is now an error ``` Note there's a second part of SE-0110 which could be considered additive, which says one must add an extra pair of parens to specify a single arugment type that is a tuple: ```swift let g ((Int, Int)) -> Void = { y in } // y should have type (Int, Int) ``` This patch does not implement that part.
1 parent d3194ec commit c9b73da

36 files changed

+70
-77
lines changed

lib/Sema/CSApply.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6417,7 +6417,7 @@ namespace {
64176417
// Coerce the pattern, in case we resolved something.
64186418
auto fnType = closure->getType()->castTo<FunctionType>();
64196419
auto *params = closure->getParameters();
6420-
if (tc.coerceParameterListToType(params, closure, fnType->getInput()))
6420+
if (tc.coerceParameterListToType(params, closure, fnType))
64216421
return { false, nullptr };
64226422

64236423
// If this is a single-expression closure, convert the expression

lib/Sema/CSDiag.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5407,7 +5407,7 @@ bool FailureDiagnosis::visitClosureExpr(ClosureExpr *CE) {
54075407
return true;
54085408
}
54095409

5410-
if (CS->TC.coerceParameterListToType(params, CE, inferredArgType))
5410+
if (CS->TC.coerceParameterListToType(params, CE, fnType))
54115411
return true;
54125412

54135413
expectedResultType = fnType->getResult();

lib/Sema/TypeCheckPattern.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1683,8 +1683,9 @@ bool TypeChecker::coercePatternToType(Pattern *&P, DeclContext *dc, Type type,
16831683
/// TODO: These diagnostics should be a lot better now that we know this is
16841684
/// all specific to closures.
16851685
///
1686-
bool TypeChecker::coerceParameterListToType(ParameterList *P, DeclContext *DC,
1687-
Type paramListType) {
1686+
bool TypeChecker::coerceParameterListToType(ParameterList *P, ClosureExpr *CE,
1687+
AnyFunctionType *FN) {
1688+
Type paramListType = FN->getInput();
16881689
bool hadError = paramListType->is<ErrorType>();
16891690

16901691
// Sometimes a scalar type gets applied to a single-argument parameter list.
@@ -1693,7 +1694,7 @@ bool TypeChecker::coerceParameterListToType(ParameterList *P, DeclContext *DC,
16931694

16941695
// Check that the type, if explicitly spelled, is ok.
16951696
if (param->getTypeLoc().getTypeRepr()) {
1696-
hadError |= validateParameterType(param, DC, TypeResolutionOptions(),
1697+
hadError |= validateParameterType(param, CE, TypeResolutionOptions(),
16971698
nullptr, *this);
16981699

16991700
// Now that we've type checked the explicit argument type, see if it
@@ -1735,11 +1736,10 @@ bool TypeChecker::coerceParameterListToType(ParameterList *P, DeclContext *DC,
17351736
// The number of elements must match exactly.
17361737
// TODO: incomplete tuple patterns, with some syntax.
17371738
if (!hadError && tupleTy->getNumElements() != P->size()) {
1738-
if (P->size() == 1)
1739-
return handleParameter(P->get(0), paramListType);
1740-
1741-
diagnose(P->getStartLoc(), diag::tuple_pattern_length_mismatch,
1742-
paramListType);
1739+
auto fnType = FunctionType::get(paramListType->getDesugaredType(),
1740+
FN->getResult());
1741+
diagnose(P->getStartLoc(), diag::closure_argument_list_tuple,
1742+
fnType, tupleTy->getNumElements(), P->size());
17431743
hadError = true;
17441744
}
17451745

lib/Sema/TypeChecker.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1386,7 +1386,8 @@ class TypeChecker final : public LazyResolver {
13861386
/// contextual type.
13871387
///
13881388
/// \returns true if an error occurred, false otherwise.
1389-
bool coerceParameterListToType(ParameterList *P, DeclContext *dc, Type type);
1389+
bool coerceParameterListToType(ParameterList *P, ClosureExpr *CE,
1390+
AnyFunctionType *FN);
13901391

13911392

13921393
/// Type-check an initialized variable pattern declaration.

stdlib/private/StdlibCollectionUnittest/CheckSequenceType.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1807,7 +1807,7 @@ self.test("\(testNamePrefix)._preprocessingPass/semantics") {
18071807
let s = makeWrappedSequence(test.sequence.map(OpaqueValue.init))
18081808
var wasInvoked = false
18091809
let result = s._preprocessingPass {
1810-
(sequence) -> OpaqueValue<Int> in
1810+
() -> OpaqueValue<Int> in
18111811
wasInvoked = true
18121812

18131813
expectEqualSequence(
@@ -1830,7 +1830,7 @@ self.test("\(testNamePrefix)._preprocessingPass/semantics") {
18301830
var result: OpaqueValue<Int>? = nil
18311831
do {
18321832
result = try s._preprocessingPass {
1833-
(sequence) -> OpaqueValue<Int> in
1833+
() -> OpaqueValue<Int> in
18341834
wasInvoked = true
18351835
throw TestError.error2
18361836
}

stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2387,7 +2387,7 @@ public func expectEqualsUnordered<
23872387
let x: [(T, T)] =
23882388
expected.sorted(by: comparePairLess)
23892389
let y: [(T, T)] =
2390-
actual.map { ($0.0, $0.1) }
2390+
actual.map { ($0, $1) }
23912391
.sorted(by: comparePairLess)
23922392

23932393
func comparePairEquals(_ lhs: (T, T), rhs: (key: T, value: T)) -> Bool {

stdlib/private/StdlibUnittest/TypeIndexed.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ public func expectEqual<V: Comparable>(
105105
file: String = #file, line: UInt = #line
106106
) {
107107
expectEqualsUnordered(
108-
expected.map { (key: TypeIdentifier($0.0), value: $0.1) },
108+
expected.map { (key: TypeIdentifier($0), value: $1) },
109109
actual.byType,
110110
message(), stackTrace: stackTrace) { $0 <=> $1 }
111111
}

stdlib/public/SDK/AppKit/AppKit.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ extension NSView : _DefaultCustomPlaygroundQuickLookable {
5454
public extension NSGradient {
5555
convenience init?(colorsAndLocations objects: (NSColor, CGFloat)...) {
5656
self.init(
57-
colors: objects.map { $0.0 },
58-
atLocations: objects.map { $0.1 },
57+
colors: objects.map { c, _ in c },
58+
atLocations: objects.map { _, l in l },
5959
colorSpace: NSColorSpace.genericRGB())
6060
}
6161
}

stdlib/public/SDK/Foundation/Foundation.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -570,8 +570,8 @@ extension NSDictionary : ExpressibleByDictionaryLiteral {
570570
dictionaryLiteral elements: (NSCopying, AnyObject)...
571571
) {
572572
self.init(
573-
objects: elements.map { $0.1 },
574-
forKeys: elements.map { $0.0 },
573+
objects: elements.map { _, v in v },
574+
forKeys: elements.map { k, _ in k },
575575
count: elements.count)
576576
}
577577
}

stdlib/public/SDK/WatchKit/WatchKit.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ extension WKInterfaceController {
2929
withNamesAndContexts namesAndContexts: [(name: String, context: AnyObject)]
3030
) {
3131
WKInterfaceController.reloadRootControllers(
32-
withNames: namesAndContexts.map { $0.name },
33-
contexts: namesAndContexts.map { $0.context })
32+
withNames: namesAndContexts.map { name, _ in name },
33+
contexts: namesAndContexts.map { _, context in context })
3434
}
3535

3636
@available(*, deprecated,
@@ -47,8 +47,8 @@ extension WKInterfaceController {
4747
withNamesAndContexts namesAndContexts: [(name: String, context: AnyObject)]
4848
) {
4949
self.presentController(
50-
withNames: namesAndContexts.map { $0.name },
51-
contexts: namesAndContexts.map { $0.context })
50+
withNames: namesAndContexts.map { name, _ in name },
51+
contexts: namesAndContexts.map { _, context in context })
5252
}
5353
}
5454

0 commit comments

Comments
 (0)