@@ -1095,6 +1095,12 @@ ParserResult<Expr> Parser::parseExprPostfix(Diag<> ID, bool isExprBasic) {
10951095 }
10961096
10971097 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)) {
1100+ Result = parseExprTypeOf ();
1101+ break ;
1102+ }
1103+
10981104 // If we are parsing a refutable pattern and are inside a let/var pattern,
10991105 // the identifiers change to be value bindings instead of decl references.
11001106 // Parse and return this as an UnresolvedPatternExpr around a binding. This
@@ -1413,12 +1419,27 @@ ParserResult<Expr> Parser::parseExprPostfix(Diag<> ID, bool isExprBasic) {
14131419 }
14141420
14151421 // 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.
14161425 if (Tok.is (tok::kw_dynamicType)) {
1417- Result = makeParserResult (
1418- new (Context) DynamicTypeExpr (Result.get (), consumeToken (), Type ()));
1426+ // Fix-it
1427+ auto range = Result.get ()->getSourceRange ();
1428+ auto dynamicTypeExprRange = SourceRange (TokLoc, consumeToken ());
1429+ diagnose (TokLoc, diag::expr_dynamictype_deprecated)
1430+ .highlight (dynamicTypeExprRange)
1431+ .fixItReplace (dynamicTypeExprRange, " )" )
1432+ .fixItInsert (range.Start , " type(of: " );
1433+
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);
14191439 continue ;
14201440 }
14211441
1442+
14221443 // Handle "x.self" expr.
14231444 if (Tok.is (tok::kw_self)) {
14241445 Result = makeParserResult (
@@ -2995,3 +3016,76 @@ Parser::parseVersionConstraintSpec() {
29953016 return makeParserResult (new (Context) VersionConstraintAvailabilitySpec (
29963017 Platform.getValue (), PlatformLoc, Version, VersionRange));
29973018}
3019+
3020+ // / parseExprTypeOf
3021+ // /
3022+ // / expr-dynamictype:
3023+ // / 'type' '(' 'of:' expr ')'
3024+ // /
3025+ ParserResult<Expr> Parser::parseExprTypeOf () {
3026+ // Consume 'type'
3027+ SourceLoc keywordLoc = consumeToken ();
3028+
3029+ // Parse the leading '('.
3030+ SourceLoc lParenLoc = consumeToken (tok::l_paren);
3031+
3032+ // 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.
3043+ consumeToken ();
3044+ consumeToken (tok::colon);
3045+
3046+ if (!hasOf) {
3047+ return makeParserError ();
3048+ }
3049+ } else {
3050+ // No label at all; insert it.
3051+ diagnose (Tok, diag::expr_typeof_expected_label_of)
3052+ .fixItInsert (ofRange.getStart (), " of: " );
3053+ }
3054+
3055+ // Parse the subexpression.
3056+ ParserResult<Expr> subExpr = parseExpr (diag::expr_typeof_expected_expr);
3057+ if (subExpr.hasCodeCompletion ())
3058+ return makeParserCodeCompletionResult<Expr>();
3059+
3060+ // Parse the closing ')'
3061+ SourceLoc rParenLoc;
3062+ if (subExpr.isParseError ()) {
3063+ skipUntilDeclStmtRBrace (tok::r_paren);
3064+ if (Tok.is (tok::r_paren))
3065+ rParenLoc = consumeToken ();
3066+ else
3067+ rParenLoc = Tok.getLoc ();
3068+ } else {
3069+ parseMatchingToken (tok::r_paren, rParenLoc,
3070+ diag::expr_typeof_expected_rparen, lParenLoc);
3071+ }
3072+
3073+ // If the subexpression was in error, just propagate the error.
3074+ if (subExpr.isParseError ()) {
3075+ if (subExpr.hasCodeCompletion ()) {
3076+ auto res = makeParserResult (
3077+ new (Context) DynamicTypeExpr (keywordLoc, lParenLoc,
3078+ subExpr.get (), rParenLoc,
3079+ Type ()));
3080+ res.setHasCodeCompletion ();
3081+ return res;
3082+ } else {
3083+ return makeParserResult<Expr>(
3084+ new (Context) ErrorExpr (SourceRange (keywordLoc, rParenLoc)));
3085+ }
3086+ }
3087+
3088+ return makeParserResult (
3089+ new (Context) DynamicTypeExpr (keywordLoc, lParenLoc,
3090+ subExpr.get (), rParenLoc, Type ()));
3091+ }
0 commit comments