From 739f8ea2c3b39f81f54bfea4b618770d7aa1a1c6 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 24 Aug 2015 13:12:02 +0200 Subject: Make it a syntactic criterion whether a literal is a legal type Introduce a new non-terminal "SimpleLiteral". Only SimpleLiterals can be types. --- docs/SyntaxSummary.txt | 5 +++-- src/dotty/tools/dotc/parsing/Parsers.scala | 3 ++- src/dotty/tools/dotc/parsing/Tokens.scala | 3 ++- src/dotty/tools/dotc/typer/Typer.scala | 5 +---- test/dotc/tests.scala | 2 +- tests/neg/singletons.scala | 2 ++ 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/docs/SyntaxSummary.txt b/docs/SyntaxSummary.txt index 52e880a34..764275f92 100644 --- a/docs/SyntaxSummary.txt +++ b/docs/SyntaxSummary.txt @@ -75,11 +75,12 @@ grammar. {\small \begin{lstlisting} - Literal ::= [`-'] integerLiteral + SimpleLiteral ::= [`-'] integerLiteral | [`-'] floatingPointLiteral | booleanLiteral | characterLiteral | stringLiteral + Literal ::= SimpleLiteral | processedStringLiteral | symbolLiteral | `null' @@ -108,7 +109,7 @@ grammar. | Path `.' `type' SingletonTypeTree(p) | `(' ArgTypes ')' Tuple(ts) | Refinement RefinedTypeTree(EmptyTree, refinement) - | Literal SingletonTypeTree(l) + | SimpleLiteral SingletonTypeTree(l) ArgType ::= Type | `_' TypeBounds ArgTypes ::= ArgType {`,' ArgType} diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala index 51ea09eac..69d7e5233 100644 --- a/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/src/dotty/tools/dotc/parsing/Parsers.scala @@ -117,6 +117,7 @@ object Parsers { def isIdent = in.token == IDENTIFIER || in.token == BACKQUOTED_IDENT def isIdent(name: Name) = in.token == IDENTIFIER && in.name == name + def isSimpleLiteral = simpleLiteralTokens contains in.token def isLiteral = literalTokens contains in.token def isNumericLit = numericLitTokens contains in.token def isModifier = modifierTokens contains in.token @@ -716,7 +717,7 @@ object Parsers { atPos(in.offset) { makeTupleOrParens(inParens(argTypes())) } else if (in.token == LBRACE) atPos(in.offset) { RefinedTypeTree(EmptyTree, refinement()) } - else if (isLiteral) { SingletonTypeTree(literal()) } + else if (isSimpleLiteral) { SingletonTypeTree(literal()) } else path(thisOK = false, handleSingletonType) match { case r @ SingletonTypeTree(_) => r case r => convertToTypeId(r) diff --git a/src/dotty/tools/dotc/parsing/Tokens.scala b/src/dotty/tools/dotc/parsing/Tokens.scala index 226a3710d..190226635 100644 --- a/src/dotty/tools/dotc/parsing/Tokens.scala +++ b/src/dotty/tools/dotc/parsing/Tokens.scala @@ -195,7 +195,8 @@ object Tokens extends TokensCommon { final val allTokens = tokenRange(minToken, maxToken) - final val literalTokens = tokenRange(CHARLIT, SYMBOLLIT) | BitSet(TRUE, FALSE, NULL) + final val simpleLiteralTokens = tokenRange(CHARLIT, STRINGLIT) | BitSet(TRUE, FALSE) + final val literalTokens = simpleLiteralTokens | BitSet(INTERPOLATIONID, SYMBOLLIT, NULL) final val atomicExprTokens = literalTokens | identifierTokens | BitSet( USCORE, NULL, THIS, SUPER, TRUE, FALSE, RETURN, XMLSTART) diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 4441adcfb..33ec156a1 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -782,10 +782,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit def typedSingletonTypeTree(tree: untpd.SingletonTypeTree)(implicit ctx: Context): SingletonTypeTree = track("typedSingletonTypeTree") { val ref1 = typedExpr(tree.ref) - val illegal = Set[Symbol](defn.NullClass, defn.SymbolClass) - val refSym = ref1.tpe.widen.typeSymbol - if (illegal contains refSym) ctx.error(i"$refSym is not a legal singleton constant type", tree.pos) - else checkStable(ref1.tpe, tree.pos) + checkStable(ref1.tpe, tree.pos) assignType(cpy.SingletonTypeTree(tree)(ref1), ref1) } diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala index 8f8b1d04a..b5af92d64 100644 --- a/test/dotc/tests.scala +++ b/test/dotc/tests.scala @@ -146,7 +146,7 @@ class tests extends CompilerTest { @Test def neg_instantiateAbstract = compileFile(negDir, "instantiateAbstract", xerrors = 8) @Test def neg_selfInheritance = compileFile(negDir, "selfInheritance", xerrors = 6) @Test def neg_selfreq = compileFile(negDir, "selfreq", xerrors = 4) - @Test def neg_singletons = compileFile(negDir, "singletons", xerrors = 4) + @Test def neg_singletons = compileFile(negDir, "singletons", xerrors = 5) @Test def neg_shadowedImplicits = compileFile(negDir, "arrayclone-new", xerrors = 2) @Test def neg_traitParamsTyper = compileFile(negDir, "traitParamsTyper", xerrors = 5) @Test def neg_traitParamsMixin = compileFile(negDir, "traitParamsMixin", xerrors = 2) diff --git a/tests/neg/singletons.scala b/tests/neg/singletons.scala index e4c6db060..5dff13096 100644 --- a/tests/neg/singletons.scala +++ b/tests/neg/singletons.scala @@ -6,4 +6,6 @@ object Test { val n: null = null // error: Null is not a legal singleton type val sym: 'sym = 'sym // error: Symbol is a legal singleton type + + val foo: s"abc" = "abc" // error: not a legal singleton type } -- cgit v1.2.3