Skip to content

Commit 2e275e3

Browse files
authored
Merge pull request #9583 from bitjammer/rdar-32143617-void-tuple-input-type
Migrator/QoI: Function input type: Don't fix Void to (Void), but fix …
2 parents df64cd7 + 0c48f71 commit 2e275e3

File tree

9 files changed

+97
-11
lines changed

9 files changed

+97
-11
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3183,6 +3183,8 @@ ERROR(objc_convention_invalid,none,
31833183
" with '@convention(%1)'", (Type, StringRef))
31843184
ERROR(function_type_no_parens,none,
31853185
"single argument function types require parentheses", ())
3186+
WARNING(paren_void_probably_void,none,
3187+
"when calling this function in Swift 4 or later, you must pass a '()' tuple; did you mean for the input type to be '()'?", ())
31863188
NOTE(not_objc_empty_protocol_composition,none,
31873189
"'Any' is not considered '@objc'; use 'AnyObject' instead", ())
31883190
NOTE(not_objc_protocol,none,

include/swift/Migrator/FixitFilter.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,12 @@ struct FixitFilter {
9090
return false;
9191
}
9292

93+
// Trying to add '_ in' to a closure signature can be counterproductive when
94+
// fixing function signatures like (Void) -> () to () -> ().
95+
if (Info.ID == diag::closure_argument_list_missing.ID) {
96+
return false;
97+
}
98+
9399
if (Kind == DiagnosticKind::Error)
94100
return true;
95101

@@ -120,7 +126,8 @@ struct FixitFilter {
120126
Info.ID == diag::override_swift3_objc_inference.ID ||
121127
Info.ID == diag::objc_inference_swift3_objc_derived.ID ||
122128
Info.ID == diag::missing_several_cases.ID ||
123-
Info.ID == diag::missing_particular_case.ID)
129+
Info.ID == diag::missing_particular_case.ID ||
130+
Info.ID == diag::paren_void_probably_void.ID)
124131
return true;
125132

126133
return false;

lib/Sema/CSDiag.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5143,9 +5143,20 @@ static bool diagnoseSingleCandidateFailures(CalleeCandidateInfo &CCI,
51435143
tuple->hasTrailingClosure())
51445144
TC.diagnose(loc, diag::extra_trailing_closure_in_call)
51455145
.highlight(arg->getSourceRange());
5146-
else if (Parameters.empty())
5147-
TC.diagnose(loc, diag::extra_argument_to_nullary_call)
5146+
else if (Parameters.empty()) {
5147+
auto Paren = dyn_cast<ParenExpr>(ArgExpr);
5148+
Expr *SubExpr = nullptr;
5149+
if (Paren) {
5150+
SubExpr = Paren->getSubExpr();
5151+
}
5152+
if (SubExpr && SubExpr->getType() && SubExpr->getType()->isVoid()) {
5153+
TC.diagnose(loc, diag::extra_argument_to_nullary_call)
5154+
.fixItRemove(SubExpr->getSourceRange());
5155+
} else {
5156+
TC.diagnose(loc, diag::extra_argument_to_nullary_call)
51485157
.highlight(ArgExpr->getSourceRange());
5158+
}
5159+
}
51495160
else if (name.empty())
51505161
TC.diagnose(loc, diag::extra_argument_positional)
51515162
.highlight(arg->getSourceRange());

lib/Sema/TypeCheckType.cpp

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2324,13 +2324,43 @@ Type TypeResolver::resolveASTFunctionType(FunctionTypeRepr *repr,
23242324
if (!isa<TupleTypeRepr>(repr->getArgsTypeRepr()) &&
23252325
!repr->isWarnedAbout()) {
23262326
auto args = repr->getArgsTypeRepr();
2327-
TC.diagnose(args->getStartLoc(), diag::function_type_no_parens)
2328-
.highlight(args->getSourceRange())
2329-
.fixItInsert(args->getStartLoc(), "(")
2330-
.fixItInsertAfter(args->getEndLoc(), ")");
2327+
2328+
bool isVoid = false;
2329+
if (const auto Void = dyn_cast<SimpleIdentTypeRepr>(args)) {
2330+
if (Void->getIdentifier().str() == "Void") {
2331+
isVoid = true;
2332+
}
2333+
}
2334+
if (isVoid) {
2335+
TC.diagnose(args->getStartLoc(), diag::function_type_no_parens)
2336+
.fixItReplace(args->getStartLoc(), "()");
2337+
} else {
2338+
TC.diagnose(args->getStartLoc(), diag::function_type_no_parens)
2339+
.highlight(args->getSourceRange())
2340+
.fixItInsert(args->getStartLoc(), "(")
2341+
.fixItInsertAfter(args->getEndLoc(), ")");
2342+
}
23312343

23322344
// Don't emit this warning three times when in generics.
23332345
repr->setWarned();
2346+
} else if (isa<TupleTypeRepr>(repr->getArgsTypeRepr()) &&
2347+
!repr->isWarnedAbout()) {
2348+
// If someone wrote (Void) -> () in Swift 3, they probably meant
2349+
// () -> (), but (Void) -> () is (()) -> () so emit a warning
2350+
// asking if they meant () -> ().
2351+
auto args = repr->getArgsTypeRepr();
2352+
if (const auto Tuple = dyn_cast<TupleTypeRepr>(args)) {
2353+
if (Tuple->getNumElements() == 1) {
2354+
if (const auto Void =
2355+
dyn_cast<SimpleIdentTypeRepr>(Tuple->getElement(0))) {
2356+
if (Void->getIdentifier().str() == "Void") {
2357+
TC.diagnose(args->getStartLoc(), diag::paren_void_probably_void)
2358+
.fixItReplace(args->getSourceRange(), "()");
2359+
repr->setWarned();
2360+
}
2361+
}
2362+
}
2363+
}
23342364
}
23352365

23362366
// SIL uses polymorphic function types to resolve overloaded member functions.

test/Constraints/diagnostics.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,12 @@ for j in i.wibble(a, a) { // expected-error {{type 'A' does not conform to proto
8484
}
8585

8686
// Generic as part of function/tuple types
87-
func f6<T:P2>(_ g: (Void) -> T) -> (c: Int, i: T) {
87+
func f6<T:P2>(_ g: (Void) -> T) -> (c: Int, i: T) { // expected-warning {{when calling this function in Swift 4 or later, you must pass a '()' tuple; did you mean for the input type to be '()'?}} {{20-26=()}}
8888
return (c: 0, i: g())
8989
}
9090

9191
func f7() -> (c: Int, v: A) {
92-
let g: (Void) -> A = { return A() }
92+
let g: (Void) -> A = { return A() } // expected-warning {{when calling this function in Swift 4 or later, you must pass a '()' tuple; did you mean for the input type to be '()'?}} {{10-16=()}}
9393
return f6(g) // expected-error {{cannot convert return expression of type '(c: Int, i: A)' to return type '(c: Int, v: A)'}}
9494
}
9595

@@ -966,4 +966,4 @@ class SR_4692_b {
966966

967967
private func f(x: Int, y: Bool) {
968968
}
969-
}
969+
}

test/Migrator/fixit_void.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %target-swift-frontend -typecheck %s -swift-version 3
2+
// RUN: %target-swift-frontend -typecheck -update-code -primary-file %s -emit-migrated-file-path %t.result -swift-version 3
3+
// RUN: diff -u %s.expected %t.result
4+
// RUN: %target-swift-frontend -typecheck %s.expected -swift-version 4
5+
6+
func takesNothing(_ f: () -> ()) {
7+
f()
8+
f(())
9+
}
10+
11+
func takesVoidFunction(_ f: (Void) -> ()) {
12+
f()
13+
f(())
14+
}
15+
16+
takesNothing { print("Hello") }
17+
takesVoidFunction { print("Hello") }
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %target-swift-frontend -typecheck %s -swift-version 3
2+
// RUN: %target-swift-frontend -typecheck -update-code -primary-file %s -emit-migrated-file-path %t.result -swift-version 3
3+
// RUN: diff -u %s.expected %t.result
4+
// RUN: %target-swift-frontend -typecheck %s.expected -swift-version 4
5+
6+
func takesNothing(_ f: () -> ()) {
7+
f()
8+
f()
9+
}
10+
11+
func takesVoidFunction(_ f: () -> ()) {
12+
f()
13+
f()
14+
}
15+
16+
takesNothing { print("Hello") }
17+
takesVoidFunction { print("Hello") }

test/Parse/type_expr.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,3 +298,5 @@ func complexSequence() {
298298
// expected-error @-3 {{expected member name or constructor call after type name}}
299299
// expected-note @-4 {{use '.self' to reference the type object}} {{11-11=(}} {{36-36=).self}}
300300
}
301+
302+
func takesVoid(f: Void -> ()) {} // expected-error {{single argument function types require parentheses}} {{19-23=()}}

test/expr/closure/single_expr.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func testMap(_ array: [Int]) {
2323
// Nested single-expression closures -- <rdar://problem/20931915>
2424
class NestedSingleExpr {
2525
private var b: Bool = false
26-
private func callClosure(_ callback: (Void) -> Void) {}
26+
private func callClosure(_ callback: () -> Void) {}
2727

2828
func call() {
2929
callClosure { [weak self] in

0 commit comments

Comments
 (0)