diff --git a/runtime/parser/type.go b/runtime/parser/type.go index 67b3fb2dff..74cd207ce8 100644 --- a/runtime/parser/type.go +++ b/runtime/parser/type.go @@ -80,6 +80,17 @@ func setTypeLeftDenotation(tokenType lexer.TokenType, leftDenotation typeLeftDen typeLeftDenotations[tokenType] = leftDenotation } +func setTypeMetaLeftDenotation(tokenType lexer.TokenType, metaLeftDenotation typeMetaLeftDenotationFunc) { + current := typeMetaLeftDenotations[tokenType] + if current != nil { + panic(errors.NewUnexpectedError( + "type meta left denotation for token %s already exists", + tokenType, + )) + } + typeMetaLeftDenotations[tokenType] = metaLeftDenotation +} + type prefixTypeFunc func(parser *parser, right ast.Type, tokenRange ast.Range) ast.Type type postfixTypeFunc func(parser *parser, left ast.Type, tokenRange ast.Range) ast.Type @@ -467,6 +478,34 @@ func defineIntersectionOrDictionaryType() { } }, ) + + // While restricted types have been removed from Cadence, during the first few months of the + // migration period, leave a special error in place to help developers + // TODO: remove this after Stable Cadence migration period is finished + setTypeMetaLeftDenotation( + lexer.TokenBraceOpen, + func(p *parser, rightBindingPower int, left ast.Type) (result ast.Type, err error, done bool) { + + // Perform a lookahead + + current := p.current + cursor := p.tokens.Cursor() + + // Skip the `{` token. + p.next() + + // In case there is a space, the type is *not* considered a restricted type. + // The buffered tokens are replayed to allow them to be re-parsed. + if p.current.Is(lexer.TokenSpace) { + p.current = current + p.tokens.Revert(cursor) + + return left, nil, true + } + + return nil, p.syntaxError("restricted types have been removed; replace with the concrete type or an equivalent intersection type"), true + }, + ) } func parseNominalType( diff --git a/runtime/parser/type_test.go b/runtime/parser/type_test.go index 8834c360ce..34e059e52f 100644 --- a/runtime/parser/type_test.go +++ b/runtime/parser/type_test.go @@ -516,8 +516,8 @@ func TestParseIntersectionType(t *testing.T) { utils.AssertEqualWithDiff(t, []error{ &SyntaxError{ - Message: "unexpected token: '{'", - Pos: ast.Position{Offset: 1, Line: 1, Column: 1}, + Message: "restricted types have been removed; replace with the concrete type or an equivalent intersection type", + Pos: ast.Position{Offset: 2, Line: 1, Column: 2}, }, }, errs, @@ -532,8 +532,8 @@ func TestParseIntersectionType(t *testing.T) { utils.AssertEqualWithDiff(t, []error{ &SyntaxError{ - Message: "unexpected token: '{'", - Pos: ast.Position{Offset: 1, Line: 1, Column: 1}, + Message: "restricted types have been removed; replace with the concrete type or an equivalent intersection type", + Pos: ast.Position{Offset: 2, Line: 1, Column: 2}, }, }, errs, @@ -548,8 +548,8 @@ func TestParseIntersectionType(t *testing.T) { utils.AssertEqualWithDiff(t, []error{ &SyntaxError{ - Message: "unexpected token: '{'", - Pos: ast.Position{Offset: 1, Line: 1, Column: 1}, + Message: "restricted types have been removed; replace with the concrete type or an equivalent intersection type", + Pos: ast.Position{Offset: 2, Line: 1, Column: 2}, }, }, errs,