Skip to content

Commit 3dacbed

Browse files
committed
Add new error diagnostic for escaping optional closures
1 parent 026c3c9 commit 3dacbed

File tree

3 files changed

+17
-15
lines changed

3 files changed

+17
-15
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4047,6 +4047,8 @@ NOTE(overridden_required_initializer_here,none,
40474047
// Functions
40484048
ERROR(attribute_requires_function_type,none,
40494049
"@%0 attribute only applies to function types", (StringRef))
4050+
ERROR(optional_closures_are_already_escaping,none,
4051+
"Optional closures are already @escaping", ())
40504052
ERROR(unsupported_convention,none,
40514053
"convention '%0' not supported", (StringRef))
40524054
ERROR(unreferenced_generic_parameter,none,

lib/Sema/TypeCheckType.cpp

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2414,20 +2414,21 @@ Type TypeResolver::resolveAttributedType(TypeAttributes &attrs,
24142414
if (!attrs.has(i))
24152415
continue;
24162416

2417-
auto diag = diagnoseInvalid(repr, attrs.getLoc(i),
2418-
diag::attribute_requires_function_type,
2419-
TypeAttributes::getAttrName(i));
2420-
2421-
// If we see @escaping among the attributes on this type, because it isn't
2422-
// a function type, we'll remove it.
2423-
if (i == TAK_escaping) {
2417+
if (i == TAK_escaping && ty->getOptionalObjectType()) {
2418+
auto diag = diagnoseInvalid(repr, attrs.getLoc(i),
2419+
diag::optional_closures_are_already_escaping);
24242420
diag.fixItRemove(getTypeAttrRangeWithAt(Context,
2425-
attrs.getLoc(TAK_escaping)));
2426-
// Specialize the diagnostic for Optionals.
2427-
if (ty->getOptionalObjectType()) {
2428-
diag.flush();
2429-
diagnoseInvalid(repr, repr->getLoc(),
2430-
diag::escaping_optional_type_argument);
2421+
attrs.getLoc(TAK_escaping)));
2422+
} else {
2423+
auto diag = diagnoseInvalid(repr, attrs.getLoc(i),
2424+
diag::attribute_requires_function_type,
2425+
TypeAttributes::getAttrName(i));
2426+
2427+
// If we see @escaping among the attributes on this type, because it isn't
2428+
// a function type, we'll remove it.
2429+
if (i == TAK_escaping) {
2430+
diag.fixItRemove(getTypeAttrRangeWithAt(Context,
2431+
attrs.getLoc(TAK_escaping)));
24312432
}
24322433
}
24332434
attrs.clearAttribute(i);

test/attr/attr_escaping.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,7 @@ struct GenericStruct<T> {}
7272

7373
func misuseEscaping(_ a: @escaping Int) {} // expected-error{{@escaping attribute only applies to function types}} {{26-36=}}
7474
func misuseEscaping(_ a: (@escaping Int)?) {} // expected-error{{@escaping attribute only applies to function types}} {{27-36=}}
75-
func misuseEscaping(opt a: @escaping ((Int) -> Int)?) {} // expected-error{{@escaping attribute only applies to function types}} {{28-38=}}
76-
// expected-note@-1{{closure is already escaping in optional type argument}}
75+
func misuseEscaping(opt a: @escaping ((Int) -> Int)?) {} // expected-error{{Optional closures are already @escaping}} {{28-38=}}
7776

7877
func misuseEscaping(_ a: (@escaping (Int) -> Int)?) {} // expected-error{{@escaping attribute may only be used in function parameter position}} {{27-36=}}
7978
// expected-note@-1{{closure is already escaping in optional type argument}}

0 commit comments

Comments
 (0)