@@ -950,6 +950,32 @@ getMagicIdentifierLiteralKind(tok Kind) {
950950 }
951951}
952952
953+ // / See if type(of: <expr>) can be parsed backtracking on failure.
954+ static bool canParseTypeOf (Parser &P) {
955+ if (!(P.Tok .getText () == " type" && P.peekToken ().is (tok::l_paren))) {
956+ return false ;
957+ }
958+ // Look ahead to parse the parenthesized expression.
959+ Parser::BacktrackingScope Backtrack (P);
960+ P.consumeToken (tok::identifier);
961+ P.consumeToken (tok::l_paren);
962+ // The first argument label must be 'of'.
963+ if (!(P.Tok .getText () == " of" && P.peekToken ().is (tok::colon))) {
964+ return false ;
965+ }
966+
967+ // Parse to the closing paren.
968+ while (!P.Tok .is (tok::r_paren) && !P.Tok .is (tok::eof)) {
969+ // Anything that looks like another argument label is bogus. It is
970+ // sufficient to parse for a single trailing comma. Backtracking will
971+ // fall back to an unresolved decl.
972+ if (P.Tok .is (tok::comma)) {
973+ return false ;
974+ }
975+ P.skipSingle ();
976+ }
977+ return true ;
978+ }
953979
954980// / parseExprPostfix
955981// /
@@ -1095,8 +1121,8 @@ ParserResult<Expr> Parser::parseExprPostfix(Diag<> ID, bool isExprBasic) {
10951121 }
10961122
10971123 case tok::identifier: // foo
1098- // If starts with 'type(', parse the 'type(of: ...)' metatype expression
1099- if (Tok. getText () == " type " && peekToken (). is (tok::l_paren )) {
1124+ // Attempt to parse for 'type(of: <expr>)'.
1125+ if (canParseTypeOf (* this )) {
11001126 Result = parseExprTypeOf ();
11011127 break ;
11021128 }
@@ -1418,35 +1444,25 @@ ParserResult<Expr> Parser::parseExprPostfix(Diag<> ID, bool isExprBasic) {
14181444 continue ;
14191445 }
14201446
1421- // Handle "x.dynamicType" - A metatype expr.
1422- // Deprecated in SE-0096: `x.dynamicType` becomes `type(of: x)`
1423- //
1424- // FIXME(SE-0096): This will go away along with the keyword soon.
1425- if (Tok.is (tok::kw_dynamicType)) {
1426- // Fix-it
1447+ // Handle "x.self" expr.
1448+ if (Tok.is (tok::kw_self)) {
1449+ Result = makeParserResult (
1450+ new (Context) DotSelfExpr (Result.get (), TokLoc, consumeToken ()));
1451+ continue ;
1452+ }
1453+
1454+ // Handle the deprecated 'x.dynamicType' and migrate it to `type(of: x)`
1455+ if (Tok.getText () == " dynamicType" ) {
1456+ BacktrackingScope backtrackScope (*this );
14271457 auto range = Result.get ()->getSourceRange ();
14281458 auto dynamicTypeExprRange = SourceRange (TokLoc, consumeToken ());
14291459 diagnose (TokLoc, diag::expr_dynamictype_deprecated)
14301460 .highlight (dynamicTypeExprRange)
14311461 .fixItReplace (dynamicTypeExprRange, " )" )
14321462 .fixItInsert (range.Start , " type(of: " );
14331463
1434- // HACK: Arbitrary.
1435- auto loc = range.Start ;
1436- auto dt = new (Context) DynamicTypeExpr (loc, loc, Result.get (), loc, Type ());
1437- dt->setImplicit ();
1438- Result = makeParserResult (dt);
1439- continue ;
1464+ // fallthrough to an UnresolvedDotExpr.
14401465 }
1441-
1442-
1443- // Handle "x.self" expr.
1444- if (Tok.is (tok::kw_self)) {
1445- Result = makeParserResult (
1446- new (Context) DotSelfExpr (Result.get (), TokLoc, consumeToken ()));
1447- continue ;
1448- }
1449-
14501466
14511467 // If we have '.<keyword><code_complete>', try to recover by creating
14521468 // an identifier with the same spelling as the keyword.
@@ -3030,26 +3046,14 @@ ParserResult<Expr> Parser::parseExprTypeOf() {
30303046 SourceLoc lParenLoc = consumeToken (tok::l_paren);
30313047
30323048 // Parse `of` label.
3033- auto ofRange = Tok.getRange ();
3034- if (Tok.canBeArgumentLabel () && peekToken ().is (tok::colon)) {
3035- bool hasOf = Tok.getText () == " of" ;
3036- if (!hasOf) {
3037- // User mis-spelled the 'of' label.
3038- diagnose (Tok, diag::expr_typeof_expected_label_of)
3039- .fixItReplace ({ ofRange.getStart (), ofRange.getEnd () }, " of" );
3040- }
3041-
3042- // Consume either 'of' or the misspelling.
3049+ if (Tok.getText () == " of" && peekToken ().is (tok::colon)) {
3050+ // Consume the label.
30433051 consumeToken ();
30443052 consumeToken (tok::colon);
3045-
3046- if (!hasOf) {
3047- return makeParserError ();
3048- }
30493053 } else {
3050- // No label at all; insert it.
3051- diagnose (Tok, diag::expr_typeof_expected_label_of)
3052- . fixItInsert (ofRange. getStart (), " of: " );
3054+ // There cannot be a richer diagnostic here because the user may have
3055+ // defined a function `type(...)` that conflicts with the magic expr.
3056+ diagnose (Tok, diag::expr_typeof_expected_label_of );
30533057 }
30543058
30553059 // Parse the subexpression.
0 commit comments