Skip to content

Commit

Permalink
Make it a syntactic criterion whether a literal is a legal type
Browse files Browse the repository at this point in the history
Introduce a new non-terminal "SimpleLiteral". Only SimpleLiterals can be
types.
  • Loading branch information
odersky committed Aug 24, 2015
1 parent e850a99 commit 739f8ea
Show file tree
Hide file tree
Showing 6 changed files with 11 additions and 9 deletions.
5 changes: 3 additions & 2 deletions docs/SyntaxSummary.txt
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,12 @@ grammar.

{\small
\begin{lstlisting}
Literal ::= [`-'] integerLiteral
SimpleLiteral ::= [`-'] integerLiteral
| [`-'] floatingPointLiteral
| booleanLiteral
| characterLiteral
| stringLiteral
Literal ::= SimpleLiteral
| processedStringLiteral
| symbolLiteral
| `null'
Expand Down Expand Up @@ -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}
Expand Down
3 changes: 2 additions & 1 deletion src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
3 changes: 2 additions & 1 deletion src/dotty/tools/dotc/parsing/Tokens.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
5 changes: 1 addition & 4 deletions src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand Down
2 changes: 1 addition & 1 deletion test/dotc/tests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions tests/neg/singletons.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

0 comments on commit 739f8ea

Please sign in to comment.