Skip to content

Commit 9a56a93

Browse files
committed
Add new fixits for oldhat inout
Mirrors the fixits provided in ParsePattern for tuples. We now diagnose multiple extraneous uses of inout and uses of inout attached to the parameter name and not the type and offer to move them.
1 parent d03babd commit 9a56a93

File tree

2 files changed

+30
-6
lines changed

2 files changed

+30
-6
lines changed

lib/Parse/ParseType.cpp

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -467,10 +467,15 @@ ParserResult<TupleTypeRepr> Parser::parseTypeTupleBody() {
467467
/*AllowSepAfterLast=*/false,
468468
diag::expected_rparen_tuple_type_list,
469469
[&] () -> ParserStatus {
470-
// If this is an inout marker in an argument list, consume the inout.
470+
// If this is an deprecated use of the inout marker in an argument list,
471+
// consume the inout.
471472
SourceLoc InOutLoc;
472-
consumeIf(tok::kw_inout, InOutLoc);
473-
473+
bool hasAnyInOut = false;
474+
bool hasValidInOut = false;
475+
if (consumeIf(tok::kw_inout, InOutLoc)) {
476+
hasAnyInOut = true;
477+
hasValidInOut = false;
478+
}
474479
// If the tuple element starts with "ident :", then
475480
// the identifier is an element tag, and it is followed by a type
476481
// annotation.
@@ -483,6 +488,18 @@ ParserResult<TupleTypeRepr> Parser::parseTypeTupleBody() {
483488

484489
// Consume the ':'.
485490
consumeToken(tok::colon);
491+
SourceLoc postColonLoc = Tok.getLoc();
492+
493+
// Consume 'inout' if present.
494+
if (!hasAnyInOut && consumeIf(tok::kw_inout, InOutLoc)) {
495+
hasValidInOut = true;
496+
}
497+
498+
SourceLoc extraneousInOutLoc;
499+
while (consumeIf(tok::kw_inout, extraneousInOutLoc)) {
500+
diagnose(Tok.getLoc(), diag::parameter_inout_var_let_repeated)
501+
.fixItRemove(extraneousInOutLoc);
502+
}
486503

487504
// Parse the type annotation.
488505
ParserResult<TypeRepr> type = parseType(diag::expected_type);
@@ -491,13 +508,18 @@ ParserResult<TupleTypeRepr> Parser::parseTypeTupleBody() {
491508
if (type.isNull())
492509
return makeParserError();
493510

511+
if (!hasValidInOut && hasAnyInOut) {
512+
diagnose(Tok.getLoc(), diag::inout_as_attr_disallowed)
513+
.fixItRemove(InOutLoc)
514+
.fixItInsert(postColonLoc, "inout ");
515+
}
516+
494517
// If an 'inout' marker was specified, build the type. Note that we bury
495518
// the inout locator within the named locator. This is weird but required
496519
// by sema apparently.
497520
if (InOutLoc.isValid())
498521
type = makeParserResult(new (Context) InOutTypeRepr(type.get(),
499522
InOutLoc));
500-
501523

502524
ElementsR.push_back(
503525
new (Context) NamedTypeRepr(name, type.get(), nameLoc));

test/Parse/invalid.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ func test1(inout var x : Int) {} // expected-error {{parameter may not have mul
1212
// expected-error @-1 {{'inout' before a parameter name is not allowed, place it before the parameter type instead}} {{12-17=}} {{26-26=inout }}
1313
func test2(inout let x : Int) {} // expected-error {{parameter may not have multiple 'inout', 'var', or 'let' specifiers}} {{18-22=}}
1414
// expected-error @-1 {{'inout' before a parameter name is not allowed, place it before the parameter type instead}} {{12-17=}} {{26-26=inout }}
15+
func test3(f : (inout x : Int) -> Void) {} // expected-error {{'inout' before a parameter name is not allowed, place it before the parameter type instead}}
1516

1617
func test3() {
1718
undeclared_func( // expected-error {{use of unresolved identifier 'undeclared_func'}} expected-note {{to match this opening '('}} expected-error {{expected ',' separator}} {{19-19=,}}
@@ -69,8 +70,8 @@ SR698(1, b: 2,) // expected-error {{unexpected ',' separator}}
6970

7071
// SR-979 - Two inout crash compiler
7172
func SR979a(a : inout inout Int) {} // expected-error {{parameter may not have multiple 'inout', 'var', or 'let' specifiers}} {{17-23=}}
72-
func SR979b(inout inout b: Int) {} // expected-error {{parameter may not have multiple 'inout', 'var', or 'let' specifiers}} {{19-25=}}
73-
// expected-error @-1 {{'inout' before a parameter name is not allowed, place it before the parameter type instead}} {{13-18=}} {{28-28=inout }}
73+
func SR979b(inout inout b: Int) {} // expected-error {{inout' before a parameter name is not allowed, place it before the parameter type instead}} {{13-18=}} {{28-28=inout }}
74+
// expected-error@-1 {{parameter may not have multiple 'inout', 'var', or 'let' specifiers}} {{19-25=}}
7475
func SR979c(let a: inout Int) {} // expected-error {{parameter may not have multiple 'inout', 'var', or 'let' specifiers}} {{13-16=}}
7576
// expected-error @-1 {{'let' as a parameter attribute is not allowed}} {{13-16=}}
7677
func SR979d(let let a: Int) {} // expected-error {{'let' as a parameter attribute is not allowed}} {{13-16=}}
@@ -80,6 +81,7 @@ func SR979f(var inout x : Int) { // expected-error {{parameter may not have mult
8081
// expected-error @-1 {{parameters may not have the 'var' specifier}} {{13-16=}}{{3-3=var x = x\n }}
8182
x += 10
8283
}
84+
func SR979g(inout i: inout Int) {} // expected-error {{parameter may not have multiple 'inout', 'var', or 'let' specifiers}} {{13-18=}}
8385
func SR979h(let inout x : Int) {} // expected-error {{parameter may not have multiple 'inout', 'var', or 'let' specifiers}} {{17-23=}}
8486
// expected-error @-1 {{'let' as a parameter attribute is not allowed}}
8587
class VarTester {

0 commit comments

Comments
 (0)