diff --git a/lib/Parse/ParseType.cpp b/lib/Parse/ParseType.cpp index f69ccf2cb7a8c..ee25cb2f8c7d0 100644 --- a/lib/Parse/ParseType.cpp +++ b/lib/Parse/ParseType.cpp @@ -881,13 +881,20 @@ Parser::parseTypeSimpleOrComposition(Diag<> MessageID, ParseTypeReason reason) { Tok.isContextualKeyword("any")) { auto keyword = Tok.getText(); auto badLoc = consumeToken(); + + // Suggest moving `some` or `any` in front of the first type unless + // the first type is an opaque or existential type. + if (opaqueLoc.isValid() || anyLoc.isValid()) { + diagnose(badLoc, diag::opaque_mid_composition, keyword) + .fixItRemove(badLoc); + } else { + diagnose(badLoc, diag::opaque_mid_composition, keyword) + .fixItRemove(badLoc) + .fixItInsert(FirstTypeLoc, keyword.str() + " "); + } const bool isAnyKeyword = keyword.equals("any"); - diagnose(badLoc, diag::opaque_mid_composition, keyword) - .fixItRemove(badLoc) - .fixItInsert(FirstTypeLoc, keyword.str() + " "); - if (isAnyKeyword) { if (anyLoc.isInvalid()) { anyLoc = badLoc; diff --git a/test/type/explicit_existential.swift b/test/type/explicit_existential.swift index 057e9a6b54cb3..c7d98d0fbcd2f 100644 --- a/test/type/explicit_existential.swift +++ b/test/type/explicit_existential.swift @@ -156,15 +156,17 @@ func anyAny() { protocol P1 {} protocol P2 {} +protocol P3 {} do { // Test that we don't accidentally misparse an 'any' type as a 'some' type // and vice versa. - let _: P1 & any P2 // expected-error {{'any' should appear at the beginning of a composition}} - let _: any P1 & any P2 // expected-error {{'any' should appear at the beginning of a composition}} - let _: any P1 & some P2 // expected-error {{'some' should appear at the beginning of a composition}} + let _: P1 & any P2 // expected-error {{'any' should appear at the beginning of a composition}} {{15-19=}} {{10-10=any }} + let _: any P1 & any P2 // expected-error {{'any' should appear at the beginning of a composition}} {{19-23=}} + let _: any P1 & P2 & any P3 // expected-error {{'any' should appear at the beginning of a composition}} {{24-28=}} + let _: any P1 & some P2 // expected-error {{'some' should appear at the beginning of a composition}} {{19-24=}} let _: some P1 & any P2 // expected-error@-1 {{'some' type can only be declared on a single property declaration}} - // expected-error@-2 {{'any' should appear at the beginning of a composition}} + // expected-error@-2 {{'any' should appear at the beginning of a composition}} {{20-24=}} } struct ConcreteComposition: P1, P2 {} diff --git a/test/type/opaque.swift b/test/type/opaque.swift index b07882b922bd0..dc4fe826214ab 100644 --- a/test/type/opaque.swift +++ b/test/type/opaque.swift @@ -488,8 +488,11 @@ func foo_repl(_ s: S) -> some Proto { protocol SomeProtocolA {} protocol SomeProtocolB {} -struct SomeStructC: SomeProtocolA, SomeProtocolB {} +protocol SomeProtocolC {} +struct SomeStructC: SomeProtocolA, SomeProtocolB, SomeProtocolC {} let someProperty: SomeProtocolA & some SomeProtocolB = SomeStructC() // expected-error {{'some' should appear at the beginning of a composition}}{{35-40=}}{{19-19=some }} +let someOtherProperty: some SomeProtocolA & some SomeProtocolB = SomeStructC() // expected-error {{'some' should appear at the beginning of a composition}}{{45-50=}} +let someThirdProperty: some SomeProtocolA & SomeProtocolB & some SomeProtocolC = SomeStructC() // expected-error {{'some' should appear at the beginning of a composition}}{{61-66=}} // An opaque result type on a protocol extension member effectively // contains an invariant reference to 'Self', and therefore cannot