aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/parsing/Parsers.scala
diff options
context:
space:
mode:
authorClemens Winter <clemenswinter1@gmail.com>2016-07-25 15:59:21 +0200
committerClemens Winter <clemenswinter1@gmail.com>2016-08-01 10:42:05 +0200
commit835c92c9fe2f9eb7560b64a2557df56402c05332 (patch)
tree9fd450b0f74580e9b569d31b4354ce401927a8cc /src/dotty/tools/dotc/parsing/Parsers.scala
parent6c386039fa5df125492bfdcffdc06cf90fb134f1 (diff)
downloaddotty-835c92c9fe2f9eb7560b64a2557df56402c05332.tar.gz
dotty-835c92c9fe2f9eb7560b64a2557df56402c05332.tar.bz2
dotty-835c92c9fe2f9eb7560b64a2557df56402c05332.zip
Fix #1403: Reject unbound wildcard types
Diffstat (limited to 'src/dotty/tools/dotc/parsing/Parsers.scala')
-rw-r--r--src/dotty/tools/dotc/parsing/Parsers.scala36
1 files changed, 27 insertions, 9 deletions
diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala
index 572db975c..12f629c57 100644
--- a/src/dotty/tools/dotc/parsing/Parsers.scala
+++ b/src/dotty/tools/dotc/parsing/Parsers.scala
@@ -19,7 +19,7 @@ import StdNames._
import util.Positions._
import Constants._
import ScriptParsers._
-import annotation.switch
+import scala.annotation.{tailrec, switch}
import util.DotClass
import rewrite.Rewrites.patch
@@ -648,12 +648,19 @@ object Parsers {
}
/* ------------- TYPES ------------------------------------------------------ */
+ /** Same as [[typ]], but emits a syntax error if it returns a wildcard.
+ */
+ def toplevelTyp(): Tree = {
+ val t = typ()
+ for (wildcardPos <- findWildcardType(t)) syntaxError("unbound wildcard type", wildcardPos)
+ t
+ }
- /** Type ::= FunArgTypes `=>' Type
+ /** Type ::= FunArgTypes `=>' Type
* | HkTypeParamClause `->' Type
- * | InfixType
+ * | InfixType
* FunArgTypes ::= InfixType
- * | `(' [ FunArgType {`,' FunArgType } ] `)'
+ * | `(' [ FunArgType {`,' FunArgType } ] `)'
*/
def typ(): Tree = {
val start = in.offset
@@ -823,7 +830,7 @@ object Parsers {
/** ParamValueType ::= Type [`*']
*/
def paramValueType(): Tree = {
- val t = typ()
+ val t = toplevelTyp()
if (isIdent(nme.raw.STAR)) {
in.nextToken()
atPos(t.pos.start) { PostfixOp(t, nme.raw.STAR) }
@@ -845,7 +852,7 @@ object Parsers {
atPos(in.offset) { TypeBoundsTree(bound(SUPERTYPE), bound(SUBTYPE)) }
private def bound(tok: Int): Tree =
- if (in.token == tok) { in.nextToken(); typ() }
+ if (in.token == tok) { in.nextToken(); toplevelTyp() }
else EmptyTree
/** TypeParamBounds ::= TypeBounds {`<%' Type} {`:' Type}
@@ -859,19 +866,19 @@ object Parsers {
def contextBounds(pname: TypeName): List[Tree] = in.token match {
case COLON =>
atPos(in.skipToken) {
- AppliedTypeTree(typ(), Ident(pname))
+ AppliedTypeTree(toplevelTyp(), Ident(pname))
} :: contextBounds(pname)
case VIEWBOUND =>
deprecationWarning("view bounds `<%' are deprecated, use a context bound `:' instead")
atPos(in.skipToken) {
- Function(Ident(pname) :: Nil, typ())
+ Function(Ident(pname) :: Nil, toplevelTyp())
} :: contextBounds(pname)
case _ =>
Nil
}
def typedOpt(): Tree =
- if (in.token == COLON) { in.nextToken(); typ() }
+ if (in.token == COLON) { in.nextToken(); toplevelTyp() }
else TypeTree()
def typeDependingOn(location: Location.Value): Tree =
@@ -879,6 +886,17 @@ object Parsers {
else if (location == Location.InPattern) refinedType()
else infixType()
+ /** Checks whether `t` is a wildcard type.
+ * If it is, returns the [[Position]] where the wildcard occurs.
+ */
+ @tailrec
+ private final def findWildcardType(t: Tree): Option[Position] = t match {
+ case TypeBoundsTree(_, _) => Some(t.pos)
+ case Parens(t1) => findWildcardType(t1)
+ case Annotated(_, t1) => findWildcardType(t1)
+ case _ => None
+ }
+
/* ----------- EXPRESSIONS ------------------------------------------------ */
/** EqualsExpr ::= `=' Expr