Skip to content

Commit 3524820

Browse files
authored
Merge pull request #13387 from rintaro/parse-typetupleelement
[Parse] Slightly refactor TypleTypeRepr element parsing
2 parents 251282a + 229f984 commit 3524820

File tree

3 files changed

+62
-61
lines changed

3 files changed

+62
-61
lines changed

include/swift/AST/TypeRepr.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,6 @@ struct TupleTypeReprElement {
594594
SourceLoc SecondNameLoc;
595595
SourceLoc UnderscoreLoc;
596596
SourceLoc ColonLoc;
597-
SourceLoc InOutLoc;
598597
TypeRepr *Type;
599598
SourceLoc TrailingCommaLoc;
600599

lib/Parse/ParseType.cpp

Lines changed: 58 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -843,17 +843,26 @@ ParserResult<TupleTypeRepr> Parser::parseTypeTupleBody() {
843843
[&] () -> ParserStatus {
844844
TupleTypeReprElement element;
845845

846-
// If this is a deprecated use of the inout marker in an argument list,
847-
// consume the inout.
848-
SourceLoc SpecifierLoc;
849-
consumeIf(tok::kw_inout, SpecifierLoc);
846+
// 'inout' here can be a obsoleted use of the marker in an argument list,
847+
// consume it in backtracking context so we can determine it's really a
848+
// deprecated use of it.
849+
llvm::Optional<BacktrackingScope> Backtracking;
850+
SourceLoc ObsoletedInOutLoc;
851+
if (Tok.is(tok::kw_inout)) {
852+
Backtracking.emplace(*this);
853+
ObsoletedInOutLoc = consumeToken(tok::kw_inout);
854+
}
850855

851856
// If the tuple element starts with a potential argument label followed by a
852857
// ':' or another potential argument label, then the identifier is an
853858
// element tag, and it is followed by a type annotation.
854859
if (Tok.canBeArgumentLabel() &&
855860
(peekToken().is(tok::colon) || peekToken().canBeArgumentLabel())) {
856-
// Consume the name
861+
if (Backtracking)
862+
// Found obsoleted 'inout' use.
863+
Backtracking->cancelBacktrack();
864+
865+
// Consume a name.
857866
if (!Tok.is(tok::kw__))
858867
element.Name = Context.getIdentifier(Tok.getText());
859868
element.NameLoc = consumeToken();
@@ -866,50 +875,52 @@ ParserResult<TupleTypeRepr> Parser::parseTypeTupleBody() {
866875
}
867876

868877
// Consume the ':'.
869-
SourceLoc colonLoc;
870-
if (Tok.is(tok::colon)) {
871-
colonLoc = consumeToken();
872-
} else {
878+
if (!consumeIf(tok::colon, element.ColonLoc))
873879
diagnose(Tok, diag::expected_parameter_colon);
874-
}
875-
876-
SourceLoc postColonLoc = Tok.getLoc();
877-
878-
// Parse the type annotation.
879-
auto type = parseType(diag::expected_type);
880-
if (type.hasCodeCompletion())
881-
return makeParserCodeCompletionStatus();
882-
if (type.isNull())
883-
return makeParserError();
884-
element.Type = type.get();
885-
886-
// Complain obsoleted 'inout' position; (inout name: Ty)
887-
if (SpecifierLoc.isValid() && !isa<InOutTypeRepr>(element.Type))
888-
diagnose(Tok.getLoc(), diag::inout_as_attr_disallowed, "'inout'")
889-
.fixItRemove(SpecifierLoc)
890-
.fixItInsert(postColonLoc, "inout ");
891-
} else {
892-
// Otherwise, this has to be a type.
893-
auto type = parseType();
894-
if (type.hasCodeCompletion())
895-
return makeParserCodeCompletionStatus();
896-
if (type.isNull())
897-
return makeParserError();
898-
element.Type = type.get();
880+
} else if (Backtracking) {
881+
// If we don't have labels, 'inout' is not a deprecated use.
882+
ObsoletedInOutLoc = SourceLoc();
899883
}
884+
Backtracking.reset();
885+
886+
// Parse the type annotation.
887+
auto type = parseType(diag::expected_type);
888+
if (type.hasCodeCompletion())
889+
return makeParserCodeCompletionStatus();
890+
if (type.isNull())
891+
return makeParserError();
892+
element.Type = type.get();
900893

901-
// If an 'inout' marker was specified, build inout type.
902-
// Note that we bury the inout locator within the named locator.
903-
// This is weird but required by Sema apparently.
904-
if (SpecifierLoc.isValid()) {
905-
if (isa<InOutTypeRepr>(element.Type) || isa<SharedTypeRepr>(element.Type))
894+
// Complain obsoleted 'inout' position; (inout name: Ty)
895+
if (ObsoletedInOutLoc.isValid()) {
896+
if (isa<InOutTypeRepr>(element.Type) ||
897+
isa<SharedTypeRepr>(element.Type)) {
898+
// If the parsed type is already a inout type et al, just remove it.
906899
diagnose(Tok, diag::parameter_specifier_repeated)
907-
.fixItRemove(SpecifierLoc);
908-
else
909-
element.Type = new (Context) InOutTypeRepr(element.Type, SpecifierLoc);
900+
.fixItRemove(ObsoletedInOutLoc);
901+
} else {
902+
diagnose(ObsoletedInOutLoc, diag::inout_as_attr_disallowed, "'inout'")
903+
.fixItRemove(ObsoletedInOutLoc)
904+
.fixItInsert(element.Type->getStartLoc(), "inout ");
905+
// Build inout type. Note that we bury the inout locator within the
906+
// named locator. This is weird but required by Sema apparently.
907+
element.Type =
908+
new (Context) InOutTypeRepr(element.Type, ObsoletedInOutLoc);
909+
}
910910
}
911911

912-
ElementsR.push_back(element);
912+
// Parse optional '...'.
913+
if (Tok.isEllipsis()) {
914+
auto ElementEllipsisLoc = consumeToken();
915+
if (EllipsisLoc.isInvalid()) {
916+
EllipsisLoc = ElementEllipsisLoc;
917+
EllipsisIdx = ElementsR.size();
918+
} else {
919+
diagnose(ElementEllipsisLoc, diag::multiple_ellipsis_in_tuple)
920+
.highlight(EllipsisLoc)
921+
.fixItRemove(ElementEllipsisLoc);
922+
}
923+
}
913924

914925
// Parse '= expr' here so we can complain about it directly, rather
915926
// than dying when we see it.
@@ -921,27 +932,14 @@ ParserResult<TupleTypeRepr> Parser::parseTypeTupleBody() {
921932
inFlight.fixItRemove(SourceRange(equalLoc, init.get()->getEndLoc()));
922933
}
923934

924-
if (Tok.isEllipsis()) {
925-
if (EllipsisLoc.isValid()) {
926-
diagnose(Tok, diag::multiple_ellipsis_in_tuple)
927-
.highlight(EllipsisLoc)
928-
.fixItRemove(Tok.getLoc());
929-
(void)consumeToken();
930-
} else {
931-
EllipsisLoc = consumeToken();
932-
EllipsisIdx = ElementsR.size() - 1;
933-
}
934-
}
935-
if (Tok.is(tok::comma)) {
935+
// Record the ',' location.
936+
if (Tok.is(tok::comma))
936937
element.TrailingCommaLoc = Tok.getLoc();
937-
}
938+
939+
ElementsR.push_back(element);
938940
return makeParserSuccess();
939941
});
940942

941-
if (EllipsisLoc.isValid() && ElementsR.empty()) {
942-
EllipsisLoc = SourceLoc();
943-
}
944-
945943
if (EllipsisLoc.isInvalid())
946944
EllipsisIdx = ElementsR.size();
947945

test/type/types.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,3 +188,7 @@ func sr5505(arg: Int) -> String {
188188
return "hello"
189189
}
190190
var _: sr5505 = sr5505 // expected-error {{use of undeclared type 'sr5505'}}
191+
192+
typealias A = (inout Int ..., Int ... = [42, 12]) -> Void // expected-error {{'inout' must not be used on variadic parameters}}
193+
// expected-error@-1 {{only a single element can be variadic}} {{35-39=}}
194+
// expected-error@-2 {{default argument not permitted in a tuple type}} {{39-49=}}

0 commit comments

Comments
 (0)