Skip to content

Commit 9898fca

Browse files
committed
Parser: Parse 'simple' types, not just identifiers, in obsoleted protocol composition syntax
1 parent bb5fb2e commit 9898fca

File tree

3 files changed

+38
-22
lines changed

3 files changed

+38
-22
lines changed

lib/Parse/ParseType.cpp

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,16 +1049,17 @@ ParserResult<TypeRepr> Parser::parseOldStyleProtocolComposition() {
10491049

10501050
// Parse the type-composition-list.
10511051
ParserStatus Status;
1052-
SmallVector<TypeRepr *, 4> Protocols;
1052+
SmallVector<TypeRepr *, 4> Components;
10531053
bool IsEmpty = startsWithGreater(Tok);
10541054
if (!IsEmpty) {
10551055
do {
1056-
// Parse the type-identifier.
1057-
ParserResult<TypeRepr> Protocol = parseTypeIdentifier();
1058-
Status |= Protocol;
1059-
if (auto *DeclRefTR =
1060-
dyn_cast_or_null<DeclRefTypeRepr>(Protocol.getPtrOrNull()))
1061-
Protocols.push_back(DeclRefTR);
1056+
// Parse the type.
1057+
ParserResult<TypeRepr> TR =
1058+
parseTypeSimple(diag::expected_type, ParseTypeReason::Unspecified);
1059+
Status |= TR;
1060+
1061+
if (TR.isNonNull())
1062+
Components.push_back(TR.get());
10621063
} while (consumeIf(tok::comma));
10631064
}
10641065

@@ -1078,28 +1079,28 @@ ParserResult<TypeRepr> Parser::parseOldStyleProtocolComposition() {
10781079
}
10791080

10801081
auto composition = CompositionTypeRepr::create(
1081-
Context, Protocols, ProtocolLoc, {LAngleLoc, RAngleLoc});
1082+
Context, Components, ProtocolLoc, {LAngleLoc, RAngleLoc});
10821083

10831084
if (Status.isSuccess() && !Status.hasCodeCompletion()) {
10841085
// Only if we have complete protocol<...> construct, diagnose deprecated.
10851086
SmallString<32> replacement;
1086-
if (Protocols.empty()) {
1087+
if (Components.empty()) {
10871088
replacement = "Any";
10881089
} else {
10891090
auto extractText = [&](TypeRepr *Ty) -> StringRef {
10901091
auto SourceRange = Ty->getSourceRange();
10911092
return SourceMgr.extractText(
10921093
Lexer::getCharSourceRangeFromSourceRange(SourceMgr, SourceRange));
10931094
};
1094-
auto Begin = Protocols.begin();
1095+
auto Begin = Components.begin();
10951096
replacement += extractText(*Begin);
1096-
while (++Begin != Protocols.end()) {
1097+
while (++Begin != Components.end()) {
10971098
replacement += " & ";
10981099
replacement += extractText(*Begin);
10991100
}
11001101
}
11011102

1102-
if (Protocols.size() > 1) {
1103+
if (Components.size() > 1) {
11031104
// Need parenthesis if the next token looks like postfix TypeRepr.
11041105
// i.e. '?', '!', '.Type', '.Protocol'
11051106
bool needParen = false;
@@ -1122,9 +1123,9 @@ ParserResult<TypeRepr> Parser::parseOldStyleProtocolComposition() {
11221123

11231124
// Replace 'protocol<T1, T2>' with 'T1 & T2'
11241125
diagnose(ProtocolLoc,
1125-
IsEmpty ? diag::deprecated_any_composition :
1126-
Protocols.size() > 1 ? diag::deprecated_protocol_composition :
1127-
diag::deprecated_protocol_composition_single)
1126+
IsEmpty ? diag::deprecated_any_composition :
1127+
Components.size() > 1 ? diag::deprecated_protocol_composition :
1128+
diag::deprecated_protocol_composition_single)
11281129
.highlight(composition->getSourceRange())
11291130
.fixItReplace(composition->getSourceRange(), replacement);
11301131
}
@@ -1714,7 +1715,7 @@ bool Parser::canParseOldStyleProtocolComposition() {
17141715

17151716
// Parse the type-composition-list.
17161717
do {
1717-
if (!canParseTypeIdentifier()) {
1718+
if (!canParseType()) {
17181719
return false;
17191720
}
17201721
} while (consumeIf(tok::comma));

test/Parse/recovery.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -381,16 +381,16 @@ struct ErrorTypeInVarDecl10 {
381381
}
382382

383383
struct ErrorTypeInVarDecl11 {
384-
var v1 : protocol<FooProtocol, // expected-error {{expected identifier for type name}}
384+
var v1 : protocol<FooProtocol, // expected-error {{expected type}}
385385
var v2 : Int
386386
}
387387

388-
func ErrorTypeInPattern1(_: protocol<) { } // expected-error {{expected identifier for type name}}
388+
func ErrorTypeInPattern1(_: protocol<) { } // expected-error {{expected type}}
389389
func ErrorTypeInPattern2(_: protocol<F) { } // expected-error {{expected '>' to complete protocol-constrained type}}
390390
// expected-note@-1 {{to match this opening '<'}}
391391
// expected-error@-2 {{cannot find type 'F' in scope}}
392392

393-
func ErrorTypeInPattern3(_: protocol<F,) { } // expected-error {{expected identifier for type name}}
393+
func ErrorTypeInPattern3(_: protocol<F,) { } // expected-error {{expected type}}
394394
// expected-error@-1 {{cannot find type 'F' in scope}}
395395

396396
struct ErrorTypeInVarDecl12 {

test/type/protocol_composition.swift

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,16 +132,31 @@ typealias B1 = protocol<P1,P2> // expected-error {{'protocol<...>' composition s
132132
typealias B2 = protocol<P1, P2> // expected-error {{'protocol<...>' composition syntax has been removed; join the protocols using '&'}} {{16-32=P1 & P2}}
133133
typealias B3 = protocol<P1 ,P2> // expected-error {{'protocol<...>' composition syntax has been removed; join the protocols using '&'}} {{16-32=P1 & P2}}
134134
typealias B4 = protocol<P1 , P2> // expected-error {{'protocol<...>' composition syntax has been removed; join the protocols using '&'}} {{16-33=P1 & P2}}
135-
typealias C1 = protocol<Any, P1> // expected-error {{'protocol<...>' composition syntax has been removed and is not needed here}} {{16-33=P1}}
136-
typealias C2 = protocol<P1, Any> // expected-error {{'protocol<...>' composition syntax has been removed and is not needed here}} {{16-33=P1}}
135+
typealias C1 = protocol<Any, P1> // expected-error {{'protocol<...>' composition syntax has been removed; join the protocols using '&'}} {{16-33=Any & P1}}
136+
typealias C2 = protocol<P1, Any> // expected-error {{'protocol<...>' composition syntax has been removed; join the protocols using '&'}} {{16-33=P1 & Any}}
137137
typealias D = protocol<P1> // expected-error {{'protocol<...>' composition syntax has been removed and is not needed here}} {{15-27=P1}}
138138
typealias E = protocol<Any> // expected-error {{'protocol<...>' composition syntax has been removed and is not needed here}} {{15-28=Any}}
139-
typealias F = protocol<Any, Any> // expected-error {{'protocol<...>' composition syntax has been removed and is not needed here}} {{15-33=Any}}
139+
typealias F = protocol<Any, Any> // expected-error {{'protocol<...>' composition syntax has been removed; join the protocols using '&'}} {{15-33=Any & Any}}
140140
typealias G = protocol<P1>.Type // expected-error {{'protocol<...>' composition syntax has been removed and is not needed here}} {{15-27=P1}}
141141
typealias H = protocol<P1>! // expected-error {{'protocol<...>' composition syntax has been removed and is not needed here}} {{15-28=P1!}}
142142
// expected-warning@-1 {{using '!' is not allowed here; treating this as '?' instead}}
143143
typealias J = protocol<P1, P2>.Protocol // expected-error {{'protocol<...>' composition syntax has been removed; join the protocols using '&'}} {{15-31=(P1 & P2)}}
144144
typealias K = protocol<P1, P2>? // expected-error {{'protocol<...>' composition syntax has been removed; join the protocols using '&'}} {{15-32=(P1 & P2)?}}
145+
typealias L = protocol<(P1), P2> // expected-error {{'protocol<...>' composition syntax has been removed; join the protocols using '&'}} {{15-33=(P1) & P2}}
146+
147+
// Deprecated protocol composition syntax in expression context.
148+
do {
149+
func typesAreEqual<T>(_: T.Type, _: T.Type) {}
150+
151+
typesAreEqual(Optional<P1 & P2>.self,
152+
Optional<protocol<P1, P2>>.self)
153+
// expected-error@-1 {{'protocol<...>' composition syntax has been removed; join the protocols using '&'}} {{26-43=P1 & P2>}}
154+
155+
// Test that we parse non-identifier components.
156+
typesAreEqual(Optional<P1 & P2>.self,
157+
Optional<protocol<P1, (P2)>>.self)
158+
// expected-error@-1 {{'protocol<...>' composition syntax has been removed; join the protocols using '&'}} {{26-45=P1 & (P2)>}}
159+
}
145160

146161
typealias T01 = P1.Protocol & P2 // expected-error {{non-protocol, non-class type '(any P1).Type' cannot be used within a protocol-constrained type}}
147162
typealias T02 = P1.Type & P2 // expected-error {{non-protocol, non-class type 'any P1.Type' cannot be used within a protocol-constrained type}}

0 commit comments

Comments
 (0)