From 3eb0fdd72cd4b46db5ddfd2fcd288b4823d8c0cd Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 14 Jun 2017 11:29:50 +0200 Subject: [PATCH 1/4] Fix #2514; Survive non-sensical trees in Typer Two problems here, because of previous parsing errors - We encounter a TypeTree() without expected type - We encounter a ValDef as an argument of an AppliedTypeTree --- compiler/src/dotty/tools/dotc/typer/Typer.scala | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 974c9786799a..378cd97cf7cd 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1056,8 +1056,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit throw ex } case _ => - assert(isFullyDefined(pt, ForceDegree.none)) - tree.withType(pt) + tree.withType( + if (isFullyDefined(pt, ForceDegree.none)) pt else UnspecifiedErrorType) } } @@ -1124,7 +1124,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit tparam.ensureCompleted() case _ => } - typed(desugaredArg, argPt) + if (desugaredArg.isType) typed(desugaredArg, argPt) + else desugaredArg.withType(UnspecifiedErrorType) } args.zipWithConserve(tparams)(typedArg(_, _)).asInstanceOf[List[Tree]] } From dc713147266965372bd1ca14a3932c3a6a822074 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 14 Jun 2017 11:32:18 +0200 Subject: [PATCH 2/4] Add test --- tests/neg/i2514.scala | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tests/neg/i2514.scala diff --git a/tests/neg/i2514.scala b/tests/neg/i2514.scala new file mode 100644 index 000000000000..35bc840ccb3f --- /dev/null +++ b/tests/neg/i2514.scala @@ -0,0 +1,10 @@ +object Foo { + def foo(): Int = { + val f: implicit Int => Int = (implicit x: Int) => 2 * x // error // error + f(2) + } + + val f = (implicit x: Int) => x // error // error + + ((implicit x: Int) => x): (implicit Int => Int) // error // error // error +} From d0c255cdb5f43dbc115d5d2ac4145cb9271da3b6 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 14 Jun 2017 13:08:19 +0200 Subject: [PATCH 3/4] Make T* a type tree That "varargs" syntax T* was classified as a term tree, but it should be a type tree. --- compiler/src/dotty/tools/dotc/ast/Desugar.scala | 4 ++-- compiler/src/dotty/tools/dotc/ast/untpd.scala | 2 +- compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala | 2 +- compiler/src/dotty/tools/dotc/parsing/Parsers.scala | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index af0f81441362..855196c600bf 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -380,7 +380,7 @@ object desugar { def enumTagMeths = if (isEnumCase) enumTagMeth(CaseKind.Class)._1 :: Nil else Nil def copyMeths = { def isRepeated(tree: Tree): Boolean = tree match { - case PostfixOp(_, Ident(nme.raw.STAR)) => true + case PostfixOp(_, Ident(tpnme.raw.STAR)) => true case ByNameTypeTree(tree1) => isRepeated(tree1) case _ => false } @@ -1051,7 +1051,7 @@ object desugar { else // l.op(r), or val x = r; l.op(x), plus handle named args specially makeBinop(l, op, r) case PostfixOp(t, op) => - if ((ctx.mode is Mode.Type) && !op.isBackquoted && op.name == nme.raw.STAR) { + if ((ctx.mode is Mode.Type) && !op.isBackquoted && op.name == tpnme.raw.STAR) { val seqType = if (ctx.compilationUnit.isJava) defn.ArrayType else defn.SeqType Annotated( AppliedTypeTree(ref(seqType), t), diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala index 9ebf35972a91..52a49de47f88 100644 --- a/compiler/src/dotty/tools/dotc/ast/untpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala @@ -367,7 +367,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { * parameter, the reference will be a repeated argument. */ def refOfDef(tree: MemberDef)(implicit ctx: Context) = tree match { - case ValDef(_, PostfixOp(_, Ident(nme.raw.STAR)), _) => repeated(Ident(tree.name)) + case ValDef(_, PostfixOp(_, Ident(tpnme.raw.STAR)), _) => repeated(Ident(tree.name)) case _ => Ident(tree.name) } diff --git a/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala b/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala index 323308caa955..d79580e86e2e 100644 --- a/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala @@ -447,7 +447,7 @@ object JavaParsers { if (in.token == DOTDOTDOT) { in.nextToken() t = atPos(t.pos.start) { - PostfixOp(t, Ident(nme.raw.STAR)) + PostfixOp(t, Ident(tpnme.raw.STAR)) } } atPos(start, in.offset) { diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 87fbe0c7e278..2ce78f366f39 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -916,7 +916,7 @@ object Parsers { val t = toplevelTyp() if (isIdent(nme.raw.STAR)) { in.nextToken() - atPos(startOffset(t)) { PostfixOp(t, Ident(nme.raw.STAR)) } + atPos(startOffset(t)) { PostfixOp(t, Ident(tpnme.raw.STAR)) } } else t } @@ -1322,7 +1322,7 @@ object Parsers { * | `(' [ExprsInParens `,'] PostfixExpr `:' `_' `*' ')' * * Special treatment for arguments of primary class constructor - * annotations. All empty argument lists `(` `)` following the first + * annotations. All empty argument lists `(` `)` following the first * get represented as `List(ParamNotArg)` instead of `Nil`, indicating that * the token sequence should be interpreted as an empty parameter clause * instead. `ParamNotArg` can also be produced when parsing the first @@ -2047,7 +2047,7 @@ object Parsers { private def checkVarArgsRules(vparamss: List[List[untpd.ValDef]]): List[untpd.ValDef] = { def isVarArgs(tpt: Trees.Tree[Untyped]): Boolean = tpt match { - case PostfixOp(_, op) if op.name == nme.raw.STAR => true + case PostfixOp(_, op) if op.name == tpnme.raw.STAR => true case _ => false } From 696bb4bde0096ea9bce48b1d628bbaa14dfb2cfc Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 14 Jun 2017 13:10:49 +0200 Subject: [PATCH 4/4] Unrelated test Play with Result and Try types. Piggybacked here. --- tests/pos/Result.scala | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 tests/pos/Result.scala diff --git a/tests/pos/Result.scala b/tests/pos/Result.scala new file mode 100644 index 000000000000..1e7193ebb5af --- /dev/null +++ b/tests/pos/Result.scala @@ -0,0 +1,17 @@ +import scala.util.control.NonFatal +object p { + + enum Result[+T, +E] { + case OK [T](x: T) extends Result[T, Nothing] + case Err[E](e: E) extends Result[Nothing, E] + } + + type Try[T] = Result[T, Throwable] + object Try { + def apply[T](x: => T): Try[T] = + try Result.OK(x) + catch { + case NonFatal(ex) => Result.Err(ex) + } + } +}