Skip to content

[Parse] Improve diagnostic for deprecated protocol<...> syntax #3631

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 21, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/swift/AST/DiagnosticsParse.def
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,8 @@ ERROR(disallowed_protocol_composition,PointsToFirstBadToken,

WARNING(deprecated_protocol_composition,none,
"'protocol<...>' composition syntax is deprecated; join the protocols using '&'", ())
WARNING(deprecated_protocol_composition_single,none,
"'protocol<...>' composition syntax is deprecated and not needed here", ())
WARNING(deprecated_any_composition,none,
"'protocol<>' syntax is deprecated; use 'Any' instead", ())

Expand Down
22 changes: 14 additions & 8 deletions lib/Parse/ParseType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -458,17 +458,23 @@ ParserResult<TypeRepr> Parser::parseTypeIdentifierOrTypeComposition() {
RAngleLoc = skipUntilGreaterInTypeList(/*protocolComposition=*/true);
}

// Replace 'protocol<T1, T2>' with 'T1 & T2'
auto Diag = diagnose(ProtocolLoc, diag::deprecated_protocol_composition);
auto composition = ProtocolCompositionTypeRepr::create(
Context, Protocols, ProtocolLoc, {LAngleLoc, RAngleLoc});

Diag.highlight({ProtocolLoc, RAngleLoc});
for (auto Comma : Commas) // remove commas and '<'
Diag.fixItReplace(Comma, " &");
Diag
.fixItRemove({ProtocolLoc, LAngleLoc}) // remove 'protocol<'
.fixItRemove(RAngleLoc); // remove '>'
if (Status.isSuccess()) {
// Only if we have complete protocol<...> construct, diagnose deprecated.
auto Diag = diagnose(ProtocolLoc,
Commas.size() > 0 ? diag::deprecated_protocol_composition
: diag::deprecated_protocol_composition_single);
Diag.highlight({ProtocolLoc, RAngleLoc});

// Replace 'protocol<T1, T2>' with 'T1 & T2'
for (auto Comma : Commas) // remove commas and '<'
Diag.fixItReplace(Comma, " &");
Diag
.fixItRemove({ProtocolLoc, LAngleLoc}) // remove 'protocol<'
.fixItRemove(RAngleLoc); // remove '>'
}

return makeParserResult(Status, composition);
}
Expand Down
15 changes: 6 additions & 9 deletions test/Parse/recovery.swift
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ struct ErrorTypeInVarDecl7 {
}

struct ErrorTypeInVarDecl8 {
var v1 : protocol<FooProtocol // expected-error {{expected '>' to complete protocol composition type}} expected-note {{to match this opening '<'}} expected-warning{{'protocol<...>' composition syntax is deprecated; join the protocols using '&'}}
var v1 : protocol<FooProtocol // expected-error {{expected '>' to complete protocol composition type}} expected-note {{to match this opening '<'}}
var v2 : Int
}

Expand All @@ -291,25 +291,22 @@ struct ErrorTypeInVarDecl9 {
}

struct ErrorTypeInVarDecl10 {
var v1 : protocol<FooProtocol // expected-error {{expected '>' to complete protocol composition type}} expected-note {{to match this opening '<'}} expected-warning {{'protocol<...>' composition syntax is deprecated; join the protocols using '&'}}
var v1 : protocol<FooProtocol // expected-error {{expected '>' to complete protocol composition type}} expected-note {{to match this opening '<'}}
var v2 : Int
}

struct ErrorTypeInVarDecl11 {
var v1 : protocol<FooProtocol, // expected-error {{expected identifier for type name}} expected-warning {{'protocol<...>' composition syntax is deprecated; join the protocols using '&'}}
var v1 : protocol<FooProtocol, // expected-error {{expected identifier for type name}}
var v2 : Int
}

func ErrorTypeInPattern1(_: protocol<) { } // expected-error {{expected identifier for type name}}
// expected-warning @-1 {{'protocol<...>' composition syntax is deprecated; join the protocols using '&'}}
func ErrorTypeInPattern2(_: protocol<F) { } // expected-warning {{'protocol<...>' composition syntax is deprecated; join the protocols using '&'}}
// expected-error@-1 {{expected '>' to complete protocol composition type}}
// expected-note@-2 {{to match this opening '<'}}
// expected-error@-3 {{use of undeclared type 'F'}}
func ErrorTypeInPattern2(_: protocol<F) { } // expected-error {{expected '>' to complete protocol composition type}}
// expected-note@-1 {{to match this opening '<'}}
// expected-error@-2 {{use of undeclared type 'F'}}

func ErrorTypeInPattern3(_: protocol<F,) { } // expected-error {{expected identifier for type name}}
// expected-error@-1 {{use of undeclared type 'F'}}
// expected-warning@-2 {{'protocol<...>' composition syntax is deprecated; join the protocols using '&'}}

struct ErrorTypeInVarDecl12 {
var v1 : FooProtocol & // expected-error{{expected identifier for type name}}
Expand Down
2 changes: 1 addition & 1 deletion test/expr/expressions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ func test_lambda() {

func test_lambda2() {
{ () -> protocol<Int> in
// expected-warning @-1 {{'protocol<...>' composition syntax is deprecated; join the protocols using '&'}}
// expected-warning @-1 {{'protocol<...>' composition syntax is deprecated and not needed here}} {{11-20=}} {{23-24=}}
// expected-error @-2 {{non-protocol type 'Int' cannot be used within a protocol composition}}
// expected-warning @-3 {{result of call is unused}}
return 1
Expand Down
9 changes: 4 additions & 5 deletions test/type/protocol_composition.swift
Original file line number Diff line number Diff line change
Expand Up @@ -111,22 +111,21 @@ func testConversion() {
accept_manyPrintable(sp)

// Conversions among existential types.
var x2 : protocol<SuperREPLPrintable, FooProtocol> // expected-warning {{'protocol<...>' composition syntax is deprecated; join the protocols using '&'}}
var x2 : protocol<SuperREPLPrintable, FooProtocol> // expected-warning {{'protocol<...>' composition syntax is deprecated; join the protocols using '&'}} {{12-21=}} {{39-40= &}} {{52-53=}}
x2 = x // expected-error{{value of type 'FooProtocol & REPLPrintable' does not conform to 'FooProtocol & SuperREPLPrintable' in assignment}}
x = x2

// Subtyping
var _ : () -> FooProtocol & SuperREPLPrintable = return_superPrintable

// FIXME: closures make ABI conversions explicit. rdar://problem/19517003
var _ : () -> protocol<FooProtocol, REPLPrintable> = { return_superPrintable() } // expected-warning {{'protocol<...>' composition syntax is deprecated; join the protocols using '&'}}
var _ : () -> protocol<FooProtocol, REPLPrintable> = { return_superPrintable() } // expected-warning {{'protocol<...>' composition syntax is deprecated; join the protocols using '&'}} {{17-26=}} {{37-38= &}} {{52-53=}}
}

// Test the parser's splitting of >= into > and =.
var x : protocol<P5>= 17 // expected-warning {{'protocol<...>' composition syntax is deprecated; join the protocols using '&'}}
var x : protocol<P5>= 17 // expected-warning {{'protocol<...>' composition syntax is deprecated and not needed here}} {{9-18=}} {{20-22=}}

typealias A = protocol<> // expected-warning {{'protocol<>' syntax is deprecated; use 'Any' instead}} {{15-25=Any}}
typealias B = protocol<P1, P2> // expected-warning {{'protocol<...>' composition syntax is deprecated; join the protocols using '&'}} {{15-24=}} {{26-27= &}} {{30-31=}}



typealias C = protocol<P1> // expected-warning {{'protocol<...>' composition syntax is deprecated and not needed here}} {{15-24=}} {{26-27=}}