Skip to content

Commit bf76471

Browse files
authored
Merge pull request #23923 from slavapestov/noescape-diagnostics-5.1
Redo diagnostics for escaping captures and non-escaping parameter call restriction [5.1]
2 parents 1842aaa + d848d12 commit bf76471

33 files changed

+826
-1018
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1379,21 +1379,6 @@ WARNING(attr_availability_nonspecific_platform_unexpected_version,none,
13791379
"unexpected version number in '%0' attribute for non-specific platform "
13801380
"'*'", (StringRef))
13811381

1382-
// autoclosure
1383-
ERROR(attr_autoclosure_expected_r_paren,PointsToFirstBadToken,
1384-
"expected ')' in @autoclosure", ())
1385-
ERROR(attr_noescape_conflicts_escaping_autoclosure,none,
1386-
"@noescape conflicts with @autoclosure(escaping)", ())
1387-
ERROR(attr_noescape_implied_by_autoclosure,none,
1388-
"@noescape is implied by @autoclosure and should not be "
1389-
"redundantly specified", ())
1390-
ERROR(attr_autoclosure_escaping_deprecated,none,
1391-
"@autoclosure(escaping) has been removed; use @autoclosure @escaping instead",
1392-
())
1393-
ERROR(attr_noescape_deprecated,none,
1394-
"@noescape is the default and has been removed",
1395-
())
1396-
13971382
// convention
13981383
ERROR(convention_attribute_expected_lparen,none,
13991384
"expected '(' after 'convention' attribute", ())

include/swift/AST/DiagnosticsSIL.def

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,33 @@ ERROR(unsupported_c_function_pointer_conversion,none,
116116
ERROR(objc_selector_malformed,none,"the type ObjectiveC.Selector is malformed",
117117
())
118118

119+
// Invalid escaping capture diagnostics.
120+
ERROR(escaping_inout_capture,none,
121+
"escaping closure captures 'inout' parameter %0", (Identifier))
122+
NOTE(inout_param_defined_here,none,
123+
"parameter %0 is declared 'inout'", (Identifier))
124+
ERROR(escaping_mutable_self_capture,none,
125+
"escaping closure captures mutating 'self' parameter", ())
126+
127+
ERROR(escaping_noescape_param_capture,none,
128+
"escaping closure captures non-escaping parameter %0", (Identifier))
129+
NOTE(noescape_param_defined_here,none,
130+
"parameter %0 is implicitly non-escaping", (Identifier))
131+
132+
ERROR(escaping_noescape_var_capture,none,
133+
"escaping closure captures non-escaping value", ())
134+
135+
NOTE(value_captured_here,none,"captured here", ())
136+
137+
NOTE(value_captured_transitively,none,
138+
"captured indirectly by this call", ())
139+
140+
ERROR(err_noescape_param_call,none,
141+
"passing a %select{|closure which captures a }1non-escaping function "
142+
"parameter %0 to a call to a non-escaping function parameter can allow "
143+
"re-entrant modification of a variable",
144+
(DeclName, unsigned))
145+
119146
// Definite initialization diagnostics.
120147
NOTE(variable_defined_here,none,
121148
"%select{variable|constant}0 defined here", (bool))

include/swift/AST/DiagnosticsSema.def

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -293,11 +293,6 @@ ERROR(incorrect_explicit_closure_result,none,
293293
"declared closure result %0 is incompatible with contextual type %1",
294294
(Type, Type))
295295

296-
ERROR(err_noescape_param_call,none,
297-
"passing a %select{|closure which captures a }1non-escaping function "
298-
"parameter %0 to a call to a non-escaping function parameter can allow "
299-
"re-entrant modification of a variable",
300-
(DeclName, unsigned))
301296
ERROR(cannot_call_function_value,none,
302297
"cannot invoke value of function type with argument list '%0'",
303298
(StringRef))
@@ -2905,21 +2900,6 @@ NOTE(transitive_capture_through_here,none,
29052900
"%0, declared here, captures %1",
29062901
(Identifier, Identifier))
29072902

2908-
ERROR(closure_implicit_capture_without_noescape,none,
2909-
"escaping closures can only capture inout parameters explicitly by value",
2910-
())
2911-
ERROR(closure_implicit_capture_mutating_self,none,
2912-
"escaping closure cannot capture a mutating self parameter",
2913-
())
2914-
NOTE(create_mutating_copy_or_capture_self,none,
2915-
"create a mutating copy of self, or explicitly capture self for immutability",
2916-
())
2917-
ERROR(nested_function_with_implicit_capture_argument,none,
2918-
"nested function with %select{an |}0implicitly captured inout "
2919-
"parameter%select{|s}0 can only be used as a non-escaping argument", (bool))
2920-
ERROR(nested_function_escaping_inout_capture,none,
2921-
"nested function cannot capture inout parameter and escape", ())
2922-
29232903
WARNING(recursive_accessor_reference,none,
29242904
"attempting to %select{access|modify}1 %0 within its own "
29252905
"%select{getter|setter}1", (Identifier, bool))
@@ -3044,19 +3024,10 @@ WARNING(debug_description_in_string_interpolation_segment,none,
30443024
NOTE(silence_debug_description_in_interpolation_segment_call,none,
30453025
"use 'String(describing:)' to silence this warning", ())
30463026

3047-
ERROR(invalid_noescape_use,none,
3048-
"non-escaping %select{value|parameter}1 %0 may only be called",
3049-
(Identifier, bool))
30503027
NOTE(noescape_parameter,none,
30513028
"parameter %0 is implicitly non-escaping",
30523029
(Identifier))
30533030

3054-
ERROR(closure_noescape_use,none,
3055-
"closure use of non-escaping parameter %0 may allow it to escape",
3056-
(Identifier))
3057-
ERROR(decl_closure_noescape_use,none,
3058-
"declaration closing over non-escaping parameter %0 may allow it to escape",
3059-
(Identifier))
30603031
ERROR(passing_noescape_to_escaping,none,
30613032
"passing non-escaping parameter %0 to function expecting an @escaping closure",
30623033
(Identifier))
@@ -3529,8 +3500,6 @@ NOTE(overridden_required_initializer_here,none,
35293500
// Functions
35303501
ERROR(attribute_requires_function_type,none,
35313502
"@%0 attribute only applies to function types", (StringRef))
3532-
ERROR(attribute_not_supported,none,
3533-
"this attribute is not supported", ())
35343503
ERROR(unsupported_convention,none,
35353504
"convention '%0' not supported", (StringRef))
35363505
ERROR(unreferenced_generic_parameter,none,

include/swift/AST/Types.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -622,10 +622,14 @@ class alignas(1 << TypeAlignInBits) TypeBase {
622622
return getRecursiveProperties().isLValue();
623623
}
624624

625-
/// Is a type with these properties materializable: that is, is it a
626-
/// first-class value type?
625+
/// Is this a first-class value type, meaning it is not an InOutType or a
626+
/// tuple type containing an InOutType?
627627
bool isMaterializable();
628628

629+
/// Is this a non-escaping type, that is, a non-escaping function type or a
630+
/// tuple type containing a non-escaping type?
631+
bool isNoEscape() const;
632+
629633
/// Determine whether the type is dependent on DynamicSelf.
630634
bool hasDynamicSelfType() const {
631635
return getRecursiveProperties().hasDynamicSelf();

include/swift/Migrator/FixitFilter.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,6 @@ struct FixitFilter {
127127
Info.ID == diag::where_inside_brackets.ID ||
128128
Info.ID == diag::selector_construction_suggest.ID ||
129129
Info.ID == diag::selector_literal_deprecated_suggest.ID ||
130-
Info.ID == diag::attr_noescape_deprecated.ID ||
131-
Info.ID == diag::attr_autoclosure_escaping_deprecated.ID ||
132130
Info.ID == diag::attr_warn_unused_result_removed.ID ||
133131
Info.ID == diag::any_as_anyobject_fixit.ID ||
134132
Info.ID == diag::deprecated_protocol_composition.ID ||

include/swift/SILOptimizer/PassManager/Passes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ PASS(Devirtualizer, "devirtualizer",
134134
"Indirect Call Devirtualization")
135135
PASS(DiagnoseInfiniteRecursion, "diagnose-infinite-recursion",
136136
"Diagnose Infinitely-Recursive Code")
137+
PASS(DiagnoseInvalidEscapingCaptures, "diagnose-invalid-escaping-captures",
138+
"Diagnose Invalid Escaping Captures")
137139
PASS(DiagnoseStaticExclusivity, "diagnose-static-exclusivity",
138140
"Static Enforcement of Law of Exclusivity")
139141
PASS(DiagnoseUnreachable, "diagnose-unreachable",

lib/AST/Type.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3079,6 +3079,24 @@ const DependentMemberType *TypeBase::findUnresolvedDependentMemberType() {
30793079
return unresolvedDepMemTy;
30803080
}
30813081

3082+
bool TypeBase::isNoEscape() const {
3083+
auto type = getCanonicalType();
3084+
3085+
if (auto silFuncTy = dyn_cast<SILFunctionType>(type))
3086+
return silFuncTy->isNoEscape();
3087+
3088+
if (auto funcTy = dyn_cast<FunctionType>(type))
3089+
return funcTy->isNoEscape();
3090+
3091+
if (auto tupleTy = dyn_cast<TupleType>(type)) {
3092+
for (auto eltTy : tupleTy.getElementTypes())
3093+
if (eltTy->isNoEscape())
3094+
return true;
3095+
}
3096+
3097+
return false;
3098+
}
3099+
30823100
static Type getConcreteTypeForSuperclassTraversing(Type t) {
30833101
if (t->isExistentialType()) {
30843102
return t->getExistentialLayout().getSuperclass();

lib/Parse/ParseDecl.cpp

Lines changed: 3 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1940,31 +1940,10 @@ bool Parser::parseTypeAttribute(TypeAttributes &Attributes, bool justChecking) {
19401940
StringRef Text = Tok.getText();
19411941
SourceLoc Loc = consumeToken();
19421942

1943-
bool isAutoclosureEscaping = false;
1944-
SourceRange autoclosureEscapingParenRange;
19451943
StringRef conventionName;
19461944
StringRef witnessMethodProtocol;
19471945

1948-
// Handle @autoclosure(escaping)
1949-
if (attr == TAK_autoclosure) {
1950-
// We need to do a bit of lookahead here to make sure we parse a (weird)
1951-
// type like: "@autoclosure (escaping) -> Int" correctly (escaping is the
1952-
// name of a type here). We also want to support the case where the
1953-
// function type coming up is a typealias, e.g. "@autoclosure (escaping) T".
1954-
if (Tok.is(tok::l_paren) && peekToken().getText() == "escaping") {
1955-
Parser::BacktrackingScope Backtrack(*this);
1956-
consumeToken(tok::l_paren);
1957-
consumeToken(tok::identifier);
1958-
isAutoclosureEscaping =
1959-
Tok.is(tok::r_paren) && peekToken().isNot(tok::arrow);
1960-
}
1961-
1962-
if (isAutoclosureEscaping) {
1963-
autoclosureEscapingParenRange.Start = consumeToken(tok::l_paren);
1964-
consumeToken(tok::identifier);
1965-
autoclosureEscapingParenRange.End = consumeToken(tok::r_paren);
1966-
}
1967-
} else if (attr == TAK_convention) {
1946+
if (attr == TAK_convention) {
19681947
SourceLoc LPLoc;
19691948
if (!consumeIfNotAtStartOfLine(tok::l_paren)) {
19701949
if (!justChecking)
@@ -2027,48 +2006,10 @@ bool Parser::parseTypeAttribute(TypeAttributes &Attributes, bool justChecking) {
20272006
switch (attr) {
20282007
default: break;
20292008
case TAK_autoclosure:
2030-
// Handle @autoclosure(escaping)
2031-
if (isAutoclosureEscaping) {
2032-
// @noescape @autoclosure(escaping) makes no sense.
2033-
if (Attributes.has(TAK_noescape)) {
2034-
diagnose(Loc, diag::attr_noescape_conflicts_escaping_autoclosure);
2035-
} else {
2036-
diagnose(Loc, diag::attr_autoclosure_escaping_deprecated)
2037-
.fixItReplace(autoclosureEscapingParenRange, " @escaping ");
2038-
}
2039-
Attributes.setAttr(TAK_escaping, Loc);
2040-
} else if (Attributes.has(TAK_noescape) && !isInSILMode()) {
2041-
diagnose(Loc, diag::attr_noescape_implied_by_autoclosure);
2042-
}
2043-
break;
2044-
2045-
case TAK_noescape:
2046-
// You can't specify @noescape and @escaping together.
2047-
if (Attributes.has(TAK_escaping)) {
2048-
diagnose(Loc, diag::attr_escaping_conflicts_noescape);
2049-
return false;
2050-
}
2051-
2052-
// @noescape after @autoclosure is redundant.
2053-
if (Attributes.has(TAK_autoclosure) && !isInSILMode()) {
2054-
diagnose(Loc, diag::attr_noescape_implied_by_autoclosure);
2055-
}
2056-
2057-
// @noescape is deprecated and no longer used
2058-
// In SIL, the polarity of @escaping is reversed.
2059-
// @escaping is the default and @noescape is explicit.
2060-
if (!isInSILMode()) {
2061-
diagnose(Loc, diag::attr_noescape_deprecated)
2062-
.fixItRemove({Attributes.AtLoc, Loc});
2063-
}
2064-
break;
20652009
case TAK_escaping:
2066-
// You can't specify @noescape and @escaping together.
2067-
if (Attributes.has(TAK_noescape)) {
2068-
diagnose(Loc, diag::attr_escaping_conflicts_noescape);
2069-
return false;
2070-
}
2010+
case TAK_noescape:
20712011
break;
2012+
20722013
case TAK_out:
20732014
case TAK_in:
20742015
case TAK_owned:

lib/SILOptimizer/Mandatory/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ silopt_register_sources(
77
DIMemoryUseCollector.cpp
88
DataflowDiagnostics.cpp
99
DiagnoseInfiniteRecursion.cpp
10+
DiagnoseInvalidEscapingCaptures.cpp
1011
DiagnoseStaticExclusivity.cpp
1112
DiagnoseUnreachable.cpp
1213
GuaranteedARCOpts.cpp

0 commit comments

Comments
 (0)