Skip to content

Commit 56f0470

Browse files
authored
Merge pull request #3223 from CodaFi/it-will-be-an-inout-referendum
2 parents 6e95043 + 9a56a93 commit 56f0470

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)