Skip to content

Commit 7863e29

Browse files
garricnCodaFi
authored andcommitted
Add fix-it to error and add note - SR-4637 (#8947)
Specialize the diagnostic emitted to remove the @escaping attribute from type refs to mention that arrows in optionals are implicitly escaping anyway.
1 parent 8fea2f7 commit 7863e29

File tree

2 files changed

+32
-15
lines changed

2 files changed

+32
-15
lines changed

lib/Sema/TypeCheckType.cpp

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2035,6 +2035,14 @@ Type TypeResolver::resolveAttributedType(AttributedTypeRepr *repr,
20352035
Type TypeResolver::resolveAttributedType(TypeAttributes &attrs,
20362036
TypeRepr *repr,
20372037
TypeResolutionOptions options) {
2038+
// Convenience to grab the source range of a type attribute.
2039+
auto getTypeAttrRangeWithAt = [](TypeChecker &TC, SourceLoc attrLoc) {
2040+
return SourceRange(attrLoc.getAdvancedLoc(-1),
2041+
Lexer::getLocForEndOfToken(TC.Context.SourceMgr,
2042+
attrLoc));
2043+
2044+
};
2045+
20382046
// Remember whether this is a function parameter.
20392047
bool isFunctionParam =
20402048
options.contains(TR_FunctionInput) ||
@@ -2230,12 +2238,8 @@ Type TypeResolver::resolveAttributedType(TypeAttributes &attrs,
22302238

22312239
// @noreturn has been replaced with a 'Never' return type.
22322240
if (fnRepr && attrs.has(TAK_noreturn)) {
2233-
auto &SM = TC.Context.SourceMgr;
22342241
auto loc = attrs.getLoc(TAK_noreturn);
2235-
auto attrRange = SourceRange(
2236-
loc.getAdvancedLoc(-1),
2237-
Lexer::getLocForEndOfToken(SM, loc));
2238-
2242+
auto attrRange = getTypeAttrRangeWithAt(TC, loc);
22392243
auto resultRange = fnRepr->getResultTypeRepr()->getSourceRange();
22402244

22412245
TC.diagnose(loc, diag::noreturn_not_supported)
@@ -2276,11 +2280,8 @@ Type TypeResolver::resolveAttributedType(TypeAttributes &attrs,
22762280
// The attribute is meaningless except on parameter types.
22772281
bool shouldDiagnose = !isFunctionParam && !skipDiagnostic;
22782282
if (shouldDiagnose) {
2279-
auto &SM = TC.Context.SourceMgr;
22802283
auto loc = attrs.getLoc(TAK_escaping);
2281-
auto attrRange = SourceRange(
2282-
loc.getAdvancedLoc(-1),
2283-
Lexer::getLocForEndOfToken(SM, loc));
2284+
auto attrRange = getTypeAttrRangeWithAt(TC, loc);
22842285

22852286
TC.diagnose(loc, diag::escaping_non_function_parameter)
22862287
.fixItRemove(attrRange);
@@ -2305,11 +2306,25 @@ Type TypeResolver::resolveAttributedType(TypeAttributes &attrs,
23052306
attrs.clearAttribute(TAK_noescape);
23062307

23072308
for (auto i : FunctionAttrs) {
2308-
if (attrs.has(i)) {
2309-
TC.diagnose(attrs.getLoc(i), diag::attribute_requires_function_type,
2310-
TypeAttributes::getAttrName(i));
2311-
attrs.clearAttribute(i);
2309+
if (!attrs.has(i))
2310+
continue;
2311+
2312+
auto diag = TC.diagnose(attrs.getLoc(i),
2313+
diag::attribute_requires_function_type,
2314+
TypeAttributes::getAttrName(i));
2315+
2316+
// If we see @escaping among the attributes on this type, because it isn't
2317+
// a function type, we'll remove it.
2318+
if (i == TAK_escaping) {
2319+
diag.fixItRemove(getTypeAttrRangeWithAt(TC,
2320+
attrs.getLoc(TAK_escaping)));
2321+
// Specialize the diagnostic for Optionals.
2322+
if (ty->getOptionalObjectType()) {
2323+
diag.flush();
2324+
TC.diagnose(repr->getLoc(), diag::escaping_optional_type_argument);
2325+
}
23122326
}
2327+
attrs.clearAttribute(i);
23132328
}
23142329
} else if (hasFunctionAttr && fnRepr) {
23152330
// Remove the function attributes from the set so that we don't diagnose.

test/attr/attr_escaping.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,10 @@ let foo: @escaping (Int) -> Int // expected-error{{@escaping attribute may only
7575

7676
struct GenericStruct<T> {}
7777

78-
func misuseEscaping(_ a: @escaping Int) {} // expected-error{{@escaping attribute only applies to function types}}
79-
func misuseEscaping(_ a: (@escaping Int)?) {} // expected-error{{@escaping attribute only applies to function types}}
78+
func misuseEscaping(_ a: @escaping Int) {} // expected-error{{@escaping attribute only applies to function types}} {{26-38=}}
79+
func misuseEscaping(_ a: (@escaping Int)?) {} // expected-error{{@escaping attribute only applies to function types}} {{27-39=}}
80+
func misuseEscaping(opt a: @escaping ((Int) -> Int)?) {} // expected-error{{@escaping attribute only applies to function types}} {{28-38=}}
81+
// expected-note@-1{{closure is already escaping in optional type argument}}
8082

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

0 commit comments

Comments
 (0)