diff options
author | Clemens Winter <clemenswinter1@gmail.com> | 2016-07-25 15:59:21 +0200 |
---|---|---|
committer | Clemens Winter <clemenswinter1@gmail.com> | 2016-08-01 10:42:05 +0200 |
commit | 835c92c9fe2f9eb7560b64a2557df56402c05332 (patch) | |
tree | 9fd450b0f74580e9b569d31b4354ce401927a8cc /src | |
parent | 6c386039fa5df125492bfdcffdc06cf90fb134f1 (diff) | |
download | dotty-835c92c9fe2f9eb7560b64a2557df56402c05332.tar.gz dotty-835c92c9fe2f9eb7560b64a2557df56402c05332.tar.bz2 dotty-835c92c9fe2f9eb7560b64a2557df56402c05332.zip |
Fix #1403: Reject unbound wildcard types
Diffstat (limited to 'src')
-rw-r--r-- | src/dotty/tools/dotc/parsing/Parsers.scala | 36 |
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 |