Skip to content

Commit 91966de

Browse files
Merge pull request #40705 from LucianoPAlmeida/SR-15657-diag-enum-cp
[Sema] Avoid misleading diagnostics for incomplete enum computed properties
2 parents 81f7124 + 29879ea commit 91966de

File tree

9 files changed

+60
-26
lines changed

9 files changed

+60
-26
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,11 @@ ERROR(enum_case_dot_prefix,none,
251251
ERROR(static_var_decl_global_scope,none,
252252
"%select{%error|static properties|class properties}0 may only be declared on a type",
253253
(StaticSpellingKind))
254-
ERROR(computed_property_no_accessors, none,
255-
"%select{computed property|subscript}0 must have accessors specified", (bool))
254+
ERROR(unexpected_curly_braces_in_decl, none,
255+
"unexpected '{' in declaration", ())
256+
ERROR(missing_accessor_return_decl,none,
257+
"missing return in %select{accessor|subscript}0 expected to return %1",
258+
(bool, TypeRepr*))
256259
ERROR(expected_getset_in_protocol,none,
257260
"expected get or set in a protocol property", ())
258261
ERROR(unexpected_getset_implementation_in_protocol,none,

include/swift/Parse/Parser.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,10 +1169,9 @@ class Parser {
11691169
struct ParsedAccessors;
11701170
ParserStatus parseGetSet(ParseDeclOptions Flags,
11711171
GenericParamList *GenericParams,
1172-
ParameterList *Indices,
1172+
ParameterList *Indices, TypeRepr *ResultType,
11731173
ParsedAccessors &accessors,
1174-
AbstractStorageDecl *storage,
1175-
SourceLoc StaticLoc);
1174+
AbstractStorageDecl *storage, SourceLoc StaticLoc);
11761175
ParserResult<VarDecl> parseDeclVarGetSet(PatternBindingEntry &entry,
11771176
ParseDeclOptions Flags,
11781177
SourceLoc StaticLoc,

lib/Parse/ParseDecl.cpp

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6226,7 +6226,7 @@ ParserStatus Parser::parseGetEffectSpecifier(ParsedAccessors &accessors,
62266226

62276227
ParserStatus Parser::parseGetSet(ParseDeclOptions Flags,
62286228
GenericParamList *GenericParams,
6229-
ParameterList *Indices,
6229+
ParameterList *Indices, TypeRepr *ResultType,
62306230
ParsedAccessors &accessors,
62316231
AbstractStorageDecl *storage,
62326232
SourceLoc StaticLoc) {
@@ -6258,8 +6258,22 @@ ParserStatus Parser::parseGetSet(ParseDeclOptions Flags,
62586258
if (parsingLimitedSyntax)
62596259
return makeParserSuccess();
62606260

6261-
diagnose(accessors.RBLoc, diag::computed_property_no_accessors,
6262-
/*subscript*/ Indices != nullptr);
6261+
if (ResultType != nullptr) {
6262+
// An error type at this point means we couldn't parse
6263+
// the result type for subscript correctly which will be
6264+
// already diagnosed as missing result type in declaration.
6265+
if (ResultType->getKind() == TypeReprKind::Error)
6266+
return makeParserError();
6267+
6268+
diagnose(accessors.RBLoc, diag::missing_accessor_return_decl,
6269+
/*subscript*/ Indices != nullptr, ResultType);
6270+
} else {
6271+
// This is supposed to be a computed property, but we don't
6272+
// have a result type representation which indicates this is probably not
6273+
// a well-formed computed property. So we can assume that empty braces
6274+
// are unexpected at this position for this declaration.
6275+
diagnose(accessors.LBLoc, diag::unexpected_curly_braces_in_decl);
6276+
}
62636277
return makeParserError();
62646278
}
62656279

@@ -6488,9 +6502,11 @@ Parser::parseDeclVarGetSet(PatternBindingEntry &entry, ParseDeclOptions Flags,
64886502

64896503
// Parse getter and setter.
64906504
ParsedAccessors accessors;
6505+
auto typedPattern = dyn_cast<TypedPattern>(pattern);
6506+
auto *resultTypeRepr = typedPattern ? typedPattern->getTypeRepr() : nullptr;
64916507
auto AccessorStatus = parseGetSet(Flags, /*GenericParams=*/nullptr,
6492-
/*Indices=*/nullptr, accessors,
6493-
storage, StaticLoc);
6508+
/*Indices=*/nullptr, resultTypeRepr,
6509+
accessors, storage, StaticLoc);
64946510
if (AccessorStatus.hasCodeCompletion())
64956511
return makeParserCodeCompletionStatus();
64966512
if (AccessorStatus.isErrorOrHasCompletion())
@@ -6500,7 +6516,7 @@ Parser::parseDeclVarGetSet(PatternBindingEntry &entry, ParseDeclOptions Flags,
65006516
if (!PrimaryVar)
65016517
return nullptr;
65026518

6503-
if (!isa<TypedPattern>(pattern)) {
6519+
if (!typedPattern) {
65046520
if (accessors.Get || accessors.Set || accessors.Address ||
65056521
accessors.MutableAddress) {
65066522
SourceLoc locAfterPattern = pattern->getLoc().getAdvancedLoc(
@@ -8029,7 +8045,7 @@ Parser::parseDeclSubscript(SourceLoc StaticLoc,
80298045
Status.setIsParseError();
80308046
}
80318047
} else if (!Status.hasCodeCompletion()) {
8032-
Status |= parseGetSet(Flags, GenericParams, Indices.get(),
8048+
Status |= parseGetSet(Flags, GenericParams, Indices.get(), ElementTy.get(),
80338049
accessors, Subscript, StaticLoc);
80348050
}
80358051

lib/Sema/TypeCheckStorage.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3326,6 +3326,7 @@ StorageImplInfoRequest::evaluate(Evaluator &evaluator,
33263326
bool hasModify = storage->getParsedAccessor(AccessorKind::Modify);
33273327
bool hasMutableAddress = storage->getParsedAccessor(AccessorKind::MutableAddress);
33283328

3329+
auto *DC = storage->getDeclContext();
33293330
// 'get', 'read', and a non-mutable addressor are all exclusive.
33303331
ReadImplKind readImpl;
33313332
if (storage->getParsedAccessor(AccessorKind::Get)) {
@@ -3354,10 +3355,10 @@ StorageImplInfoRequest::evaluate(Evaluator &evaluator,
33543355
readImpl = ReadImplKind::Stored;
33553356
}
33563357

3357-
// Extensions can't have stored properties. If there are braces, assume
3358-
// this is an incomplete computed property. This avoids an "extensions
3359-
// must not contain stored properties" error later on.
3360-
} else if (isa<ExtensionDecl>(storage->getDeclContext()) &&
3358+
// Extensions and enums can't have stored properties. If there are braces,
3359+
// assume this is an incomplete computed property. This avoids an
3360+
// "extensions|enums must not contain stored properties" error later on.
3361+
} else if ((isa<ExtensionDecl>(DC) || isa<EnumDecl>(DC)) &&
33613362
storage->getBracesRange().isValid()) {
33623363
readImpl = ReadImplKind::Get;
33633364

test/Constraints/closures.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,8 @@ func r21544303() {
9595
inSubcall = false
9696

9797
// This is a problem, but isn't clear what was intended.
98-
var somethingElse = true {
99-
} // expected-error {{computed property must have accessors specified}}
98+
var somethingElse = true { // expected-error {{unexpected '{' in declaration}}
99+
}
100100
inSubcall = false
101101

102102
var v2 : Bool = false

test/Parse/omit_return.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -545,10 +545,10 @@ func ff_implicitMemberAccessEnumCase() -> Unit {
545545

546546

547547
var fv_nop: () {
548-
} // expected-error {{computed property must have accessors specified}}
548+
} // expected-error {{missing return in accessor expected to return '()'}}
549549

550550
var fv_missing: String {
551-
} // expected-error {{computed property must have accessors specified}}
551+
} // expected-error {{missing return in accessor expected to return 'String'}}
552552

553553
var fv_implicit: String {
554554
"hello"
@@ -1054,12 +1054,12 @@ var fvs_optionalTryImplicit: String? {
10541054

10551055
enum S_nop {
10561056
subscript() -> () {
1057-
} // expected-error {{subscript must have accessors specified}}
1057+
} // expected-error {{missing return in subscript expected to return '()'}}
10581058
}
10591059

10601060
enum S_missing {
10611061
subscript() -> String {
1062-
} // expected-error {{subscript must have accessors specified}}
1062+
} // expected-error {{missing return in subscript expected to return 'String'}}
10631063
}
10641064

10651065
enum S_implicit {

test/decl/subscript/subscripting.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,14 +222,20 @@ struct RetOverloadedSubscript {
222222

223223
struct MissingGetterSubscript1 {
224224
subscript (i : Int) -> Int {
225-
} // expected-error {{subscript must have accessors specified}}
225+
} // expected-error {{missing return in subscript expected to return 'Int'}}
226226
}
227227
struct MissingGetterSubscript2 {
228228
subscript (i : Int, j : Int) -> Int {
229229
set {} // expected-error{{subscript with a setter must also have a getter}}
230230
}
231231
}
232232

233+
struct MissingReturnTypeAndEmptyBodySubscript {
234+
subscript(i: Int) { // expected-error{{expected '->' for subscript element type}}
235+
// expected-error@-1{{expected subscripting element type}}
236+
}
237+
}
238+
233239
func test_subscript(_ x2: inout X2, i: Int, j: Int, value: inout Int, no: NoSubscript,
234240
ovl: inout OverloadedSubscript, ret: inout RetOverloadedSubscript) {
235241
no[i] = value // expected-error{{value of type 'NoSubscript' has no subscripts}}

test/decl/var/properties.swift

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -378,12 +378,12 @@ var x12: X {
378378
}
379379
}
380380

381-
var x13: X {} // expected-error {{computed property must have accessors specified}}
381+
var x13: X {} // expected-error {{missing return in accessor expected to return 'X'}}
382382

383383
struct X14 {}
384384
extension X14 {
385385
var x14: X {
386-
} // expected-error {{computed property must have accessors specified}}
386+
} // expected-error {{missing return in accessor expected to return 'X'}}
387387
}
388388

389389
// Type checking problems
@@ -1340,3 +1340,12 @@ class LazyPropInClass {
13401340
lazy var foo: Int = { return 0 } // expected-error {{function produces expected type 'Int'; did you mean to call it with '()'?}}
13411341
// expected-note@-1 {{Remove '=' to make 'foo' a computed property}}{{21-23=}}{{3-8=}}
13421342
}
1343+
1344+
// SR-15657
1345+
enum SR15657 {
1346+
var foo: Int {} // expected-error{{missing return in accessor expected to return 'Int'}}
1347+
}
1348+
1349+
enum SR15657_G<T> {
1350+
var foo: T {} // expected-error{{missing return in accessor expected to return 'T'}}
1351+
}

test/decl/var/result_builders.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ var global: Int
2121
// FIXME: should this be allowed?
2222
@Maker
2323
var globalWithEmptyImplicitGetter: Int {}
24-
// expected-error@-1 {{computed property must have accessors specified}}
24+
// expected-error@-1 {{missing return in accessor expected to return 'Int'}}
2525
// expected-error@-3 {{result builder attribute 'Maker' can only be applied to a variable if it defines a getter}}
2626

2727
@Maker

0 commit comments

Comments
 (0)