diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h index 055f86cd85ee6..40f6d91ab1403 100644 --- a/include/swift/Parse/Parser.h +++ b/include/swift/Parse/Parser.h @@ -1259,6 +1259,9 @@ class Parser { /// Whether the type is for a closure attribute. CustomAttribute, + + /// Whether the type is a destination of a cast. + CastDestination, }; ParserResult parseType(); @@ -1297,8 +1300,9 @@ class Parser { /// positioned at '.f'. /// - If there is no base type qualifier (e.g. when parsing just 'f'), returns /// an empty parser error. - ParserResult parseTypeIdentifier( - bool isParsingQualifiedDeclBaseType = false); + ParserResult + parseTypeIdentifier(bool isParsingQualifiedDeclBaseType = false, + ParseTypeReason reason = ParseTypeReason::Unspecified); ParserResult parseOldStyleProtocolComposition(); ParserResult parseAnyType(); ParserResult parseSILBoxType(GenericParamList *generics, diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 5de9eb323bb54..570d703970052 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -74,7 +74,8 @@ ParserResult Parser::parseExprImpl(Diag<> Message, ParserResult Parser::parseExprIs() { SourceLoc isLoc = consumeToken(tok::kw_is); - ParserResult type = parseType(diag::expected_type_after_is); + ParserResult type = + parseType(diag::expected_type_after_is, ParseTypeReason::CastDestination); if (type.hasCodeCompletion()) return makeParserCodeCompletionResult(); if (type.isNull()) @@ -101,7 +102,8 @@ ParserResult Parser::parseExprAs() { exclaimLoc = consumeToken(tok::exclaim_postfix); } - ParserResult type = parseType(diag::expected_type_after_as); + ParserResult type = + parseType(diag::expected_type_after_as, ParseTypeReason::CastDestination); if (type.hasCodeCompletion()) return makeParserCodeCompletionResult(); diff --git a/lib/Parse/ParseType.cpp b/lib/Parse/ParseType.cpp index 6d1692ce68178..096f22369e7f6 100644 --- a/lib/Parse/ParseType.cpp +++ b/lib/Parse/ParseType.cpp @@ -14,16 +14,16 @@ // //===----------------------------------------------------------------------===// -#include "swift/Parse/Parser.h" #include "swift/AST/ASTWalker.h" #include "swift/AST/Attr.h" #include "swift/AST/GenericParamList.h" #include "swift/AST/TypeRepr.h" -#include "swift/Parse/Lexer.h" #include "swift/Parse/CodeCompletionCallbacks.h" -#include "swift/Parse/SyntaxParsingContext.h" +#include "swift/Parse/Lexer.h" #include "swift/Parse/ParsedSyntaxBuilders.h" #include "swift/Parse/ParsedSyntaxRecorder.h" +#include "swift/Parse/Parser.h" +#include "swift/Parse/SyntaxParsingContext.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" @@ -180,7 +180,7 @@ ParserResult Parser::parseTypeSimple( case tok::kw_Self: case tok::kw_Any: case tok::identifier: { - ty = parseTypeIdentifier(); + ty = parseTypeIdentifier(/*isParsingQualifiedDeclBaseType=*/false, reason); break; } case tok::l_paren: @@ -679,7 +679,8 @@ ParserStatus Parser::parseGenericArguments(SmallVectorImpl &Args, /// identifier generic-args? ('.' identifier generic-args?)* /// ParserResult -Parser::parseTypeIdentifier(bool isParsingQualifiedDeclBaseType) { +Parser::parseTypeIdentifier(bool isParsingQualifiedDeclBaseType, + ParseTypeReason reason) { // If parsing a qualified declaration name, return error if base type cannot // be parsed. if (isParsingQualifiedDeclBaseType && !canParseBaseTypeForQualifiedDeclName()) @@ -722,9 +723,16 @@ Parser::parseTypeIdentifier(bool isParsingQualifiedDeclBaseType) { SourceLoc LAngle, RAngle; SmallVector GenericArgs; if (startsWithLess(Tok)) { - auto genericArgsStatus = parseGenericArguments(GenericArgs, LAngle, RAngle); - if (genericArgsStatus.isErrorOrHasCompletion()) - return genericArgsStatus; + // Only attempt to parse a generic argument list in a cast destination + // type if the token text is just "<", because it can be an operator, + // for example: "1 as Int16 << 7". + if (Tok.getText().equals("<") || + reason != ParseTypeReason::CastDestination) { + auto genericArgsStatus = + parseGenericArguments(GenericArgs, LAngle, RAngle); + if (genericArgsStatus.isErrorOrHasCompletion()) + return genericArgsStatus; + } } EndLoc = Loc.getEndLoc(); diff --git a/test/Parse/generic_disambiguation.swift b/test/Parse/generic_disambiguation.swift index ebb900e3e8c47..8124c02b1aa6d 100644 --- a/test/Parse/generic_disambiguation.swift +++ b/test/Parse/generic_disambiguation.swift @@ -76,3 +76,22 @@ A(x: 0) // parses as type // expected-warning{{unused}} _ = a < b ? c : d A<(B) throws -> D>(x: 0) // expected-warning{{unused}} + +// https://github.com/apple/swift/issues/43053 +do { + 1 as! A.F << 2 // expected-warning {{cast from 'Int' to unrelated type 'A.F' always fails}} + // expected-error@-1 {{referencing operator function '<<' on 'BinaryInteger' requires that 'A.F' conform to 'BinaryInteger'}} + 1 as! A << 2 // expected-warning {{cast from 'Int' to unrelated type 'A' always fails}} + // expected-error@-1 {{referencing operator function '<<' on 'BinaryInteger' requires that 'A' conform to 'BinaryInteger'}} + let _ = 1 as Int16 << 7 + let _ = 1 as? Int16 << 7 // expected-error {{value of optional type 'Int16?' must be unwrapped to a value of type 'Int16'}} + // expected-warning@-1 {{conditional downcast from literal to 'Int16' always fails; consider using 'as' coercion}} + // expected-note@-2 {{coalesce using '??' to provide a default when the optional value contains 'nil'}} + // expected-note@-3 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} + let _ = 1 is Int16 << 7 // expected-warning {{conditional downcast from literal to 'Int16' always fails; consider using 'as' coercion}} + // expected-error@-1 {{binary operator '<<' cannot be applied to operands of type 'Bool' and 'Int'}} + let _ = 1 as! Int16 << 7 // expected-warning {{conditional downcast from literal to 'Int16' always fails; consider using 'as' coercion}} + let _ = 1 as Int16 <= 7 + // FIXME: this should not produce any errors. + let _ = 1 as Int16 < 7 // expected-error {{expected type}} +}