Skip to content

Commit 045bc16

Browse files
authored
Merge pull request #4031 from milseman/noescape_by_default
noescape by default: deprecate @NoEscape and @autoclosure(escaping)
2 parents a8e8fb4 + 8c3b582 commit 045bc16

File tree

90 files changed

+364
-298
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

90 files changed

+364
-298
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@ Note: This is in reverse chronological order, so newer entries are added to the
22

33
Swift 3.0
44
---------
5+
6+
* [SE-103](https://github.com/apple/swift-evolution/blob/master/proposals/0103-make-noescape-default.md)
7+
8+
Closure parameters are non-escaping by default, rather than explicitly being
9+
annotated `@noescape`. Use `@escaping` to say that a closure parameter may
10+
escape. `@autoclosure(escaping)` is now spelled `@autoclosure @escaping`.
11+
`@noescape` and `@autoclosure(escaping)` are deprecated.
12+
513
* [SE-0115](https://github.com/apple/swift-evolution/blob/master/proposals/0115-literal-syntax-protocols.md)
614

715
To clarify the role of `*LiteralConvertible` protocols, they have

include/swift/AST/DiagnosticsParse.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1215,6 +1215,12 @@ ERROR(attr_noescape_conflicts_escaping_autoclosure,none,
12151215
ERROR(attr_noescape_implied_by_autoclosure,none,
12161216
"@noescape is implied by @autoclosure and should not be "
12171217
"redundantly specified", ())
1218+
WARNING(attr_autoclosure_escaping_deprecated,none,
1219+
"@autoclosure(escaping) is deprecated; use @autoclosure @escaping instead",
1220+
())
1221+
WARNING(attr_noescape_deprecated,none,
1222+
"@noescape is the default and is deprecated",
1223+
())
12181224

12191225
// convention
12201226
ERROR(convention_attribute_expected_lparen,none,

include/swift/AST/DiagnosticsSema.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2239,7 +2239,7 @@ ERROR(closure_implicit_capture_mutating_self,none,
22392239
())
22402240
ERROR(nested_function_with_implicit_capture_argument,none,
22412241
"nested function with %select{an |}0implicitly captured inout "
2242-
"parameter%select{|s}0 can only be used as a @noescape argument", (bool))
2242+
"parameter%select{|s}0 can only be used as a non-escaping argument", (bool))
22432243
ERROR(nested_function_escaping_inout_capture,none,
22442244
"nested function cannot capture inout parameter and escape", ())
22452245

lib/AST/ASTDumper.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2917,7 +2917,6 @@ namespace {
29172917
printFlag(T->isAutoClosure(), "autoclosure");
29182918

29192919
// Dump out either @noescape or @escaping
2920-
printFlag(T->isNoEscape(), "@noescape");
29212920
printFlag(!T->isNoEscape(), "@escaping");
29222921

29232922
printFlag(T->throws(), "throws");

lib/AST/ASTPrinter.cpp

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3742,16 +3742,11 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
37423742
void printFunctionExtInfo(AnyFunctionType::ExtInfo info) {
37433743
if (Options.SkipAttributes)
37443744
return;
3745-
if (info.isAutoClosure()) {
3746-
if (info.isNoEscape())
3747-
Printer << "@autoclosure ";
3748-
else
3749-
Printer << "@autoclosure(escaping) ";
3750-
} else if (inParameterPrinting) {
3751-
if (!info.isNoEscape()) {
3752-
Printer << "@escaping ";
3753-
}
3754-
}
3745+
3746+
if (info.isAutoClosure())
3747+
Printer << "@autoclosure ";
3748+
if (inParameterPrinting && !info.isNoEscape())
3749+
Printer << "@escaping ";
37553750

37563751
if (Options.PrintFunctionRepresentationAttrs) {
37573752
// TODO: coalesce into a single convention attribute.

lib/AST/TypeRepr.cpp

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -276,13 +276,9 @@ void AttributedTypeRepr::printAttrs(llvm::raw_ostream &OS) const {
276276
void AttributedTypeRepr::printAttrs(ASTPrinter &Printer) const {
277277
const TypeAttributes &Attrs = getAttrs();
278278

279-
switch (Attrs.has(TAK_autoclosure)*2 + Attrs.has(TAK_noescape)) {
280-
case 0: break; // Nothing specified.
281-
case 1: Printer << "@noescape "; break;
282-
case 2: Printer << "@autoclosure(escaping) "; break;
283-
case 3: Printer << "@autoclosure "; break;
284-
}
285-
if (Attrs.has(TAK_escaping)) Printer << "@escaping ";
279+
if (Attrs.has(TAK_autoclosure)) Printer << "@autoclosure ";
280+
if (Attrs.has(TAK_escaping)) Printer << "@escaping ";
281+
286282
if (Attrs.has(TAK_thin)) Printer << "@thin ";
287283
if (Attrs.has(TAK_thick)) Printer << "@thick ";
288284
if (Attrs.convention.hasValue()) {

lib/FrontendTool/FrontendTool.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -629,8 +629,11 @@ class JSONFixitWriter : public DiagnosticConsumer {
629629
Info.ID == diag::noescape_autoclosure.ID ||
630630
Info.ID == diag::where_inside_brackets.ID ||
631631
Info.ID == diag::selector_construction_suggest.ID ||
632-
Info.ID == diag::selector_literal_deprecated_suggest.ID)
632+
Info.ID == diag::selector_literal_deprecated_suggest.ID ||
633+
Info.ID == diag::attr_noescape_deprecated.ID ||
634+
Info.ID == diag::attr_autoclosure_escaping_deprecated.ID)
633635
return true;
636+
634637
return false;
635638
}
636639

lib/Parse/ParseDecl.cpp

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1444,6 +1444,7 @@ bool Parser::parseTypeAttribute(TypeAttributes &Attributes, bool justChecking) {
14441444
SourceLoc Loc = consumeToken();
14451445

14461446
bool isAutoclosureEscaping = false;
1447+
SourceLoc autoclosureEscapingRightParenLoc;
14471448
StringRef conventionName;
14481449

14491450
// Handle @autoclosure(escaping)
@@ -1463,7 +1464,7 @@ bool Parser::parseTypeAttribute(TypeAttributes &Attributes, bool justChecking) {
14631464
if (isAutoclosureEscaping) {
14641465
consumeToken(tok::l_paren);
14651466
consumeToken(tok::identifier);
1466-
consumeToken(tok::r_paren);
1467+
autoclosureEscapingRightParenLoc = consumeToken(tok::r_paren);
14671468
}
14681469
} else if (attr == TAK_convention) {
14691470
SourceLoc LPLoc;
@@ -1512,27 +1513,35 @@ bool Parser::parseTypeAttribute(TypeAttributes &Attributes, bool justChecking) {
15121513
// Handle @autoclosure(escaping)
15131514
if (isAutoclosureEscaping) {
15141515
// @noescape @autoclosure(escaping) makes no sense.
1515-
if (Attributes.has(TAK_noescape))
1516+
if (Attributes.has(TAK_noescape)) {
15161517
diagnose(Loc, diag::attr_noescape_conflicts_escaping_autoclosure);
1517-
} else {
1518-
if (Attributes.has(TAK_noescape))
1519-
diagnose(Loc, diag::attr_noescape_implied_by_autoclosure);
1520-
Attributes.setAttr(TAK_noescape, Loc);
1518+
} else {
1519+
diagnose(Loc, diag::attr_autoclosure_escaping_deprecated)
1520+
.fixItReplace({Loc, autoclosureEscapingRightParenLoc},
1521+
"@autoclosure @escaping ");
1522+
}
1523+
Attributes.setAttr(TAK_escaping, Loc);
1524+
} else if (Attributes.has(TAK_noescape)) {
1525+
diagnose(Loc, diag::attr_noescape_implied_by_autoclosure);
15211526
}
15221527
break;
15231528

15241529
case TAK_noescape:
1525-
// You can't specify @noescape and @autoclosure(escaping) together, and
1526-
// @noescape after @autoclosure is redundant.
1527-
if (Attributes.has(TAK_autoclosure)) {
1528-
diagnose(Loc, diag::attr_noescape_conflicts_escaping_autoclosure);
1529-
return false;
1530-
}
15311530
// You can't specify @noescape and @escaping together.
15321531
if (Attributes.has(TAK_escaping)) {
15331532
diagnose(Loc, diag::attr_escaping_conflicts_noescape);
15341533
return false;
15351534
}
1535+
1536+
// @noescape after @autoclosure is redundant.
1537+
if (Attributes.has(TAK_autoclosure)) {
1538+
diagnose(Loc, diag::attr_noescape_implied_by_autoclosure);
1539+
}
1540+
1541+
// @noescape is deprecated and no longer used
1542+
diagnose(Loc, diag::attr_noescape_deprecated)
1543+
.fixItRemove({Attributes.AtLoc,Loc});
1544+
15361545
break;
15371546
case TAK_escaping:
15381547
// You can't specify @noescape and @escaping together.

lib/Sema/TypeCheckAttr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1609,7 +1609,7 @@ void TypeChecker::checkAutoClosureAttr(ParamDecl *PD, AutoClosureAttr *attr) {
16091609
return;
16101610

16111611
// This decl attribute has been moved to being a type attribute.
1612-
auto text = attr->isEscaping() ? "@autoclosure(escaping) " : "@autoclosure ";
1612+
auto text = attr->isEscaping() ? "@autoclosure @escaping " : "@autoclosure ";
16131613
diagnose(attr->getLocation(), diag::attr_decl_attr_now_on_type,
16141614
"@autoclosure")
16151615
.fixItRemove(attr->getRangeWithAt())

lib/Sema/TypeCheckType.cpp

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1915,15 +1915,13 @@ Type TypeResolver::resolveAttributedType(TypeAttributes &attrs,
19151915
}
19161916

19171917
bool defaultNoEscape = false;
1918-
// TODO: Get rid of the need for checking autoclosure, by refactoring
1919-
// special autoclosure knowledge to just as "isEscaping" or similar.
1920-
if (isFunctionParam && !attrs.has(TAK_autoclosure)) {
1921-
// Closure params default to non-escaping
1922-
if (attrs.has(TAK_noescape)) {
1923-
// FIXME: diagnostic to tell user this is redundant and drop it
1924-
} else if (!attrs.has(TAK_escaping)) {
1925-
defaultNoEscape = isDefaultNoEscapeContext(DC);
1926-
}
1918+
if (isFunctionParam && !attrs.has(TAK_escaping)) {
1919+
defaultNoEscape = isDefaultNoEscapeContext(DC);
1920+
}
1921+
1922+
if (isFunctionParam && attrs.has(TAK_noescape) &&
1923+
isDefaultNoEscapeContext(DC)) {
1924+
// FIXME: diagnostic to tell user this is redundant and drop it
19271925
}
19281926

19291927
// Resolve the function type directly with these attributes.

stdlib/private/StdlibCollectionUnittest/CheckMutableCollectionType.swift.gyb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public func withInvalidOrderings(_ body: (@escaping (Int, Int) -> Bool) -> Void)
6060

6161
internal func _mapInPlace<C : MutableCollection>(
6262
_ elements: inout C,
63-
_ transform: @noescape (C.Iterator.Element) -> C.Iterator.Element
63+
_ transform: (C.Iterator.Element) -> C.Iterator.Element
6464
) where C.Indices.Iterator.Element == C.Index {
6565
for i in elements.indices {
6666
elements[i] = transform(elements[i])

stdlib/private/StdlibCollectionUnittest/LoggingWrappers.swift.gyb

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -224,28 +224,28 @@ public struct ${Self}<
224224
}
225225

226226
public func map<T>(
227-
_ transform: @noescape (Base.Iterator.Element) throws -> T
227+
_ transform: (Base.Iterator.Element) throws -> T
228228
) rethrows -> [T] {
229229
Log.map[selfType] += 1
230230
return try base.map(transform)
231231
}
232232

233233
public func filter(
234-
_ isIncluded: @noescape (Base.Iterator.Element) throws -> Bool
234+
_ isIncluded: (Base.Iterator.Element) throws -> Bool
235235
) rethrows -> [Base.Iterator.Element] {
236236
Log.filter[selfType] += 1
237237
return try base.filter(isIncluded)
238238
}
239239

240240
public func forEach(
241-
_ body: @noescape (Base.Iterator.Element) throws -> Void
241+
_ body: (Base.Iterator.Element) throws -> Void
242242
) rethrows {
243243
Log.forEach[selfType] += 1
244244
try base.forEach(body)
245245
}
246246

247247
public func first(
248-
where predicate: @noescape (Base.Iterator.Element) throws -> Bool
248+
where predicate: (Base.Iterator.Element) throws -> Bool
249249
) rethrows -> Base.Iterator.Element? {
250250
Log.first[selfType] += 1
251251
return try base.first(where: predicate)
@@ -276,7 +276,7 @@ public struct ${Self}<
276276
public func split(
277277
maxSplits: Int = Int.max,
278278
omittingEmptySubsequences: Bool = true,
279-
whereSeparator isSeparator: @noescape (Base.Iterator.Element) throws -> Bool
279+
whereSeparator isSeparator: (Base.Iterator.Element) throws -> Bool
280280
) rethrows -> [SubSequence] {
281281
Log.split[selfType] += 1
282282
return try base.split(
@@ -296,7 +296,7 @@ public struct ${Self}<
296296
/// `preprocess` on `self` and return its result. Otherwise, return
297297
/// `nil`.
298298
public func _preprocessingPass<R>(
299-
_ preprocess: @noescape () throws -> R
299+
_ preprocess: () throws -> R
300300
) rethrows -> R? {
301301
Log._preprocessingPass[selfType] += 1
302302
return try base._preprocessingPass(preprocess)
@@ -443,14 +443,14 @@ public struct ${Self}<
443443

444444
% if Kind == 'MutableCollection':
445445
public mutating func partition(
446-
by belongsInSecondPartition: @noescape (Iterator.Element) throws -> Bool
446+
by belongsInSecondPartition: (Iterator.Element) throws -> Bool
447447
) rethrows -> Index {
448448
Log.partitionBy[selfType] += 1
449449
return try base.partition(by: belongsInSecondPartition)
450450
}
451451

452452
public mutating func _withUnsafeMutableBufferPointerIfSupported<R>(
453-
_ body: @noescape (UnsafeMutablePointer<Iterator.Element>, Int) throws -> R
453+
_ body: (UnsafeMutablePointer<Iterator.Element>, Int) throws -> R
454454
) rethrows -> R? {
455455
Log._withUnsafeMutableBufferPointerIfSupported[selfType] += 1
456456
let result = try base._withUnsafeMutableBufferPointerIfSupported(body)
@@ -650,7 +650,7 @@ public struct ${Self}<
650650
}
651651

652652
public mutating func _withUnsafeMutableBufferPointerIfSupported<R>(
653-
_ body: @noescape (UnsafeMutablePointer<Iterator.Element>, Int) throws -> R
653+
_ body: (UnsafeMutablePointer<Iterator.Element>, Int) throws -> R
654654
) rethrows -> R? {
655655
Log._withUnsafeMutableBufferPointerIfSupported[selfType] += 1
656656
let result = try base._withUnsafeMutableBufferPointerIfSupported(body)

stdlib/private/StdlibUnittest/RaceTest.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ import Glibc
4747
#if _runtime(_ObjC)
4848
import ObjectiveC
4949
#else
50-
func autoreleasepool(invoking code: @noescape () -> Void) {
50+
func autoreleasepool(invoking code: () -> Void) {
5151
// Native runtime does not have autorelease pools. Execute the code
5252
// directly.
5353
code()

stdlib/private/StdlibUnittestFoundationExtras/StdlibUnittestFoundationExtras.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ extension NSLocale {
2424

2525
public func withOverriddenLocaleCurrentLocale<Result>(
2626
_ temporaryLocale: NSLocale,
27-
_ body: @noescape () -> Result
27+
_ body: () -> Result
2828
) -> Result {
2929
let oldMethod = class_getClassMethod(
3030
NSLocale.self, #selector(getter: NSLocale.current))
@@ -48,7 +48,7 @@ public func withOverriddenLocaleCurrentLocale<Result>(
4848

4949
public func withOverriddenLocaleCurrentLocale<Result>(
5050
_ temporaryLocaleIdentifier: String,
51-
_ body: @noescape () -> Result
51+
_ body: () -> Result
5252
) -> Result {
5353
precondition(
5454
NSLocale.availableLocaleIdentifiers.contains(temporaryLocaleIdentifier),
@@ -65,7 +65,7 @@ public func withOverriddenLocaleCurrentLocale<Result>(
6565
/// return-autoreleased optimization.)
6666
@inline(never)
6767
public func autoreleasepoolIfUnoptimizedReturnAutoreleased(
68-
invoking body: @noescape () -> Void
68+
invoking body: () -> Void
6969
) {
7070
#if arch(i386) && (os(iOS) || os(watchOS))
7171
autoreleasepool(invoking: body)

stdlib/public/SDK/Dispatch/Block.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ public class DispatchWorkItem {
4343
qos.qosClass.rawValue.rawValue, Int32(qos.relativePriority), block)
4444
}
4545

46-
// Used by DispatchQueue.synchronously<T> to provide a @noescape path through
46+
// Used by DispatchQueue.synchronously<T> to provide a path through
4747
// dispatch_block_t, as we know the lifetime of the block in question.
48-
internal init(flags: DispatchWorkItemFlags = [], noescapeBlock: @noescape () -> ()) {
48+
internal init(flags: DispatchWorkItemFlags = [], noescapeBlock: () -> ()) {
4949
_block = _swift_dispatch_block_create_noescape(flags.rawValue, noescapeBlock)
5050
}
5151

stdlib/public/SDK/Dispatch/Data.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public struct DispatchData : RandomAccessCollection, _ObjectiveCBridgeable {
7070
}
7171

7272
public func withUnsafeBytes<Result, ContentType>(
73-
body: @noescape (UnsafePointer<ContentType>) throws -> Result) rethrows -> Result
73+
body: (UnsafePointer<ContentType>) throws -> Result) rethrows -> Result
7474
{
7575
var ptr: UnsafeRawPointer? = nil
7676
var size = 0
@@ -82,7 +82,7 @@ public struct DispatchData : RandomAccessCollection, _ObjectiveCBridgeable {
8282
}
8383

8484
public func enumerateBytes(
85-
block: @noescape (_ buffer: UnsafeBufferPointer<UInt8>, _ byteIndex: Int, _ stop: inout Bool) -> Void)
85+
block: (_ buffer: UnsafeBufferPointer<UInt8>, _ byteIndex: Int, _ stop: inout Bool) -> Void)
8686
{
8787
_swift_dispatch_data_apply(__wrapped) { (_, offset: Int, ptr: UnsafeRawPointer, size: Int) in
8888
let bytePtr = ptr.bindMemory(to: UInt8.self, capacity: size)

stdlib/public/SDK/Dispatch/Private.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ public func dispatch_io_set_interval(_ channel: DispatchIO, _ interval: UInt64,
139139
}
140140

141141
@available(*, unavailable, renamed:"DispatchQueue.apply(attributes:iterations:execute:)")
142-
public func dispatch_apply(_ iterations: Int, _ queue: DispatchQueue, _ block: @noescape (Int) -> Void)
142+
public func dispatch_apply(_ iterations: Int, _ queue: DispatchQueue, _ block: (Int) -> Void)
143143
{
144144
fatalError()
145145
}
@@ -205,7 +205,7 @@ public func dispatch_barrier_async(_ queue: DispatchQueue, _ block: () -> Void)
205205
}
206206

207207
@available(*, unavailable, renamed:"DispatchQueue.sync(self:flags:execute:)")
208-
public func dispatch_barrier_sync(_ queue: DispatchQueue, _ block: @noescape () -> Void)
208+
public func dispatch_barrier_sync(_ queue: DispatchQueue, _ block: () -> Void)
209209
{
210210
fatalError()
211211
}

0 commit comments

Comments
 (0)