Skip to content

Commit 4b5ae85

Browse files
committed
emit a warning + fixit to move @autoclosure/@NoEscape to the type position
instead of from the parameter position. This should be upgraded to an error later in Swift 3, but we'll give the community some time to react.
1 parent 8746676 commit 4b5ae85

File tree

4 files changed

+31
-6
lines changed

4 files changed

+31
-6
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,10 @@ ERROR(missing_initializer_def,PointsToFirstBadToken,
766766
"initializer requires a body", ())
767767

768768
// Attributes
769+
WARNING(attr_decl_attr_now_on_type,none,
770+
"%0 is now an attribute on a parameter type, "
771+
"instead of on the parameter itself", (StringRef))
772+
769773
ERROR(operator_not_func,none,
770774
"operators must be declared with 'func'", ())
771775
ERROR(redefining_builtin_operator,none,

lib/Sema/TypeCheckAttr.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1559,6 +1559,13 @@ void TypeChecker::checkAutoClosureAttr(ParamDecl *PD, AutoClosureAttr *attr) {
15591559
if (FTy->isAutoClosure())
15601560
return;
15611561

1562+
// This decl attribute has been moved to being a type attribute.
1563+
auto text = attr->isEscaping() ? "@autoclosure(escaping)" : "@autoclosure";
1564+
diagnose(attr->getLocation(), diag::attr_decl_attr_now_on_type,
1565+
"@autoclosure")
1566+
.fixItRemove(attr->getRangeWithAt())
1567+
.fixItInsert(PD->getTypeLoc().getSourceRange().Start, text);
1568+
15621569
auto *FuncTyInput = FTy->getInput()->getAs<TupleType>();
15631570
if (!FuncTyInput || FuncTyInput->getNumElements() != 0) {
15641571
diagnose(attr->getLocation(), diag::autoclosure_function_input_nonunit);
@@ -1601,6 +1608,11 @@ void TypeChecker::checkNoEscapeAttr(ParamDecl *PD, NoEscapeAttr *attr) {
16011608
if (FTy->isNoEscape())
16021609
return;
16031610

1611+
// This decl attribute has been moved to being a type attribute.
1612+
diagnose(attr->getLocation(), diag::attr_decl_attr_now_on_type, "@noescape")
1613+
.fixItRemove(attr->getRangeWithAt())
1614+
.fixItInsert(PD->getTypeLoc().getSourceRange().Start, "@noescape");
1615+
16041616
// Change the type to include the noescape bit.
16051617
PD->overwriteType(FunctionType::get(FTy->getInput(), FTy->getResult(),
16061618
FTy->getExtInfo().withNoEscape(true)));

test/attr/attr_autoclosure.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ struct AutoclosureEscapeTest {
6868
}
6969

7070
// @autoclosure(escaping)
71+
// expected-warning @+1 {{@autoclosure is now an attribute on a parameter type, instead of on the parameter itself}} {{13-34=}} {{38-38=@autoclosure(escaping)}}
7172
func func10(@autoclosure(escaping _: () -> ()) { } // expected-error{{expected ')' in @autoclosure}}
7273
// expected-note@-1{{to match this opening '('}}
7374
@@ -120,3 +121,11 @@ let _ : (@autoclosure(escaping) () -> ()) -> ()
120121
// escaping is the name of param type
121122
let _ : (@autoclosure(escaping) -> ()) -> () // expected-error {{use of undeclared type 'escaping'}}
122123

124+
125+
// Migration
126+
// expected-warning @+1 {{@autoclosure is now an attribute on a parameter type, instead of on the parameter itself}} {{16-28=}} {{32-32=@autoclosure}}
127+
func migrateAC(@autoclosure _: () -> ()) { }
128+
129+
// expected-warning @+1 {{@autoclosure is now an attribute on a parameter type, instead of on the parameter itself}} {{17-39=}} {{43-43=@autoclosure(escaping)}}
130+
func migrateACE(@autoclosure(escaping) _: () -> ()) { }
131+

test/attr/attr_noescape.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -223,9 +223,9 @@ class NoEscapeImmediatelyApplied {
223223

224224

225225
// Reduced example from XCTest overlay, involves a TupleShuffleExpr
226-
public func XCTAssertTrue(@autoclosure _ expression: () -> Boolean, _ message: String = "", file: StaticString = #file, line: UInt = #line) -> Void {
226+
public func XCTAssertTrue(_ expression: @autoclosure () -> Boolean, _ message: String = "", file: StaticString = #file, line: UInt = #line) -> Void {
227227
}
228-
public func XCTAssert( @autoclosure _ expression: () -> Boolean, _ message: String = "", file: StaticString = #file, line: UInt = #line) -> Void {
228+
public func XCTAssert(_ expression: @autoclosure () -> Boolean, _ message: String = "", file: StaticString = #file, line: UInt = #line) -> Void {
229229
XCTAssertTrue(expression, message, file: file, line: line);
230230
}
231231

@@ -293,10 +293,10 @@ enum r19997577Type {
293293
}
294294

295295
// type attribute and decl attribute
296-
func noescapeD(@noescape f: () -> Bool) {} // ok
296+
func noescapeD(@noescape f: () -> Bool) {} // expected-warning {{@noescape is now an attribute on a parameter type, instead of on the parameter itself}} {{16-25=}} {{29-29=@noescape}}
297297
func noescapeT(f: @noescape () -> Bool) {} // ok
298-
func autoclosureD(@autoclosure f: () -> Bool) {} // ok
298+
func autoclosureD(@autoclosure f: () -> Bool) {} // expected-warning {{@autoclosure is now an attribute on a parameter type, instead of on the parameter itself}} {{19-31=}} {{35-35=@autoclosure}}
299299
func autoclosureT(f: @autoclosure () -> Bool) {} // ok
300300

301-
func noescapeD_noescapeT(@noescape f: @noescape () -> Bool) {} // ok
302-
func autoclosureD_noescapeT(@autoclosure f: @noescape () -> Bool) {} // ok
301+
func noescapeD_noescapeT(@noescape f: @noescape () -> Bool) {}
302+
func autoclosureD_noescapeT(@autoclosure f: @noescape () -> Bool) {} // expected-warning {{@autoclosure is now an attribute on a parameter type, instead of on the parameter itself}} {{29-41=}} {{45-45=@autoclosure}}

0 commit comments

Comments
 (0)