summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Suereth <Joshua.Suereth@gmail.com>2012-09-13 06:05:27 -0700
committerJosh Suereth <Joshua.Suereth@gmail.com>2012-09-13 06:05:27 -0700
commit20f701bf504530cb12e9d24e2dd66fa42244664d (patch)
tree2d5cd89f0fad0f9adb9b01cceb3ba535f40171cd
parentcfd874ac173ca8d6542921aeea60e1f5ace80b9d (diff)
parentf5e71796d5b964026f5723318d29be5b189b442e (diff)
downloadscala-20f701bf504530cb12e9d24e2dd66fa42244664d.tar.gz
scala-20f701bf504530cb12e9d24e2dd66fa42244664d.tar.bz2
scala-20f701bf504530cb12e9d24e2dd66fa42244664d.zip
Merge pull request #1296 from paulp/210-errors-and-trees
210 errors and trees
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala14
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala13
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala9
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala7
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala23
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala4
-rw-r--r--test/files/neg/names-defaults-neg.check2
-rw-r--r--test/files/neg/wrong-args-for-none.check4
-rw-r--r--test/files/neg/wrong-args-for-none.scala6
-rw-r--r--test/files/pos/z1720.scala16
-rw-r--r--test/pending/pos/t3943/Outer_1.java14
-rw-r--r--test/pending/pos/t3943/test_2.scala8
14 files changed, 100 insertions, 26 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index d101337087..9e3f47e8fb 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -13,7 +13,7 @@ import scala.collection.{ mutable, immutable }
import io.{ SourceReader, AbstractFile, Path }
import reporters.{ Reporter, ConsoleReporter }
import util.{ Exceptional, ClassPath, MergedClassPath, StatisticsInfo, ScalaClassLoader, returning }
-import scala.reflect.internal.util.{ NoPosition, SourceFile, NoSourceFile, BatchSourceFile, ScriptSourceFile }
+import scala.reflect.internal.util.{ NoPosition, OffsetPosition, SourceFile, NoSourceFile, BatchSourceFile, ScriptSourceFile }
import scala.reflect.internal.pickling.{ PickleBuffer, PickleFormat }
import settings.{ AestheticSettings }
import symtab.{ Flags, SymbolTable, SymbolLoaders, SymbolTrackers }
@@ -96,6 +96,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
/** Generate ASTs */
type TreeGen = scala.tools.nsc.ast.TreeGen
+ /** Tree generation, usually based on existing symbols. */
override object gen extends {
val global: Global.this.type = Global.this
} with TreeGen {
@@ -103,6 +104,17 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
typer.typed(mkCast(tree, pt))
}
+ /** Trees fresh from the oven, mostly for use by the parser. */
+ object treeBuilder extends {
+ val global: Global.this.type = Global.this
+ } with TreeBuilder {
+ def freshName(prefix: String): Name = freshTermName(prefix)
+ def freshTermName(prefix: String): TermName = currentUnit.freshTermName(prefix)
+ def freshTypeName(prefix: String): TypeName = currentUnit.freshTypeName(prefix)
+ def o2p(offset: Int): Position = new OffsetPosition(currentUnit.source, offset)
+ def r2p(start: Int, mid: Int, end: Int): Position = rangePos(currentUnit.source, start, mid, end)
+ }
+
/** Fold constants */
object constfold extends {
val global: Global.this.type = Global.this
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index e79c92e162..c925669444 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -280,14 +280,6 @@ self =>
/** whether a non-continuable syntax error has been seen */
private var lastErrorOffset : Int = -1
- object treeBuilder extends TreeBuilder {
- val global: self.global.type = self.global
- def freshName(prefix: String): Name = freshTermName(prefix)
- def freshTermName(prefix: String): TermName = Parser.this.freshTermName(prefix)
- def freshTypeName(prefix: String): TypeName = Parser.this.freshTypeName(prefix)
- def o2p(offset: Int) = Parser.this.o2p(offset)
- def r2p(start: Int, point: Int, end: Int) = Parser.this.r2p(start, point, end)
- }
import treeBuilder.{global => _, _}
/** The types of the context bounds of type parameters of the surrounding class
@@ -404,8 +396,7 @@ self =>
def mainParamType = AppliedTypeTree(Ident(tpnme.Array), List(Ident(tpnme.String)))
def mainParameter = List(ValDef(Modifiers(Flags.PARAM), nme.argv, mainParamType, EmptyTree))
def mainSetArgv = List(ValDef(NoMods, nme.args, TypeTree(), Ident(nme.argv)))
- def mainNew = makeNew(Nil, emptyValDef, stmts, ListOfNil, NoPosition, NoPosition)
- def mainDef = DefDef(NoMods, nme.main, Nil, List(mainParameter), scalaDot(tpnme.Unit), Block(mainSetArgv, mainNew))
+ def mainDef = DefDef(NoMods, nme.main, Nil, List(mainParameter), scalaDot(tpnme.Unit), Block(mainSetArgv, makeAnonymousNew(stmts)))
// object Main
def moduleName = newTermName(ScriptRunner scriptMain settings)
@@ -1302,7 +1293,7 @@ self =>
placeholderParams = placeholderParams ::: savedPlaceholderParams
res
}
-
+
def expr0(location: Int): Tree = (in.token: @scala.annotation.switch) match {
case IF =>
diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
index edf747486a..afafff4a64 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
@@ -199,6 +199,15 @@ abstract class TreeBuilder {
}
}
+ /** Creates a tree representing new Object { stats }.
+ * To make sure an anonymous subclass of Object is created,
+ * if there are no stats, a () is added.
+ */
+ def makeAnonymousNew(stats: List[Tree]): Tree = {
+ val stats1 = if (stats.isEmpty) List(Literal(Constant(()))) else stats
+ makeNew(Nil, emptyValDef, stats1, ListOfNil, NoPosition, NoPosition)
+ }
+
/** Create positioned tree representing an object creation <new parents { stats }
* @param npos the position of the new
* @param cpos the position of the anonymous class starting with parents
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index ae1a2c7e8e..37e452dc6a 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -959,7 +959,7 @@ abstract class Erasure extends AddInterfaces
case TypeApply(sel @ Select(qual, name), List(targ)) =>
if (qual.tpe != null && isPrimitiveValueClass(qual.tpe.typeSymbol) && targ.tpe != null && targ.tpe <:< AnyRefClass.tpe)
unit.error(sel.pos, "isInstanceOf cannot test if value types are references.")
-
+
def mkIsInstanceOf(q: () => Tree)(tp: Type): Tree =
Apply(
TypeApply(
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index 5097ecc3fe..86cdc59303 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -1474,13 +1474,13 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
case Select(qual, name) =>
def transformSelect = {
qual match {
- case _: Super if illegalSpecializedInheritance(currentClass) =>
+ case _: Super if illegalSpecializedInheritance(currentClass) =>
val pos = tree.pos
debuglog(pos.source.file.name+":"+pos.line+": not specializing call to super inside illegal specialized inheritance class.")
debuglog(pos.lineContent)
tree
case _ =>
-
+
debuglog("specializing Select %s [tree.tpe: %s]".format(symbol.defString, tree.tpe))
//log("!!! select " + tree + " -> " + symbol.info + " specTypeVars: " + specializedTypeVars(symbol.info))
diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
index b7195b0349..49ace019b9 100644
--- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
@@ -470,9 +470,6 @@ trait ContextErrors {
def NamedAndDefaultArgumentsNotSupportedForMacros(tree: Tree, fun: Tree) =
NormalTypeError(tree, "macros application do not support named and/or default arguments")
- def WrongNumberOfArgsError(tree: Tree, fun: Tree) =
- NormalTypeError(tree, "wrong number of arguments for "+ treeSymTypeMsg(fun))
-
def TooManyArgsNamesDefaultsError(tree: Tree, fun: Tree) =
NormalTypeError(tree, "too many arguments for "+treeSymTypeMsg(fun))
@@ -512,8 +509,8 @@ trait ContextErrors {
def TooManyArgsPatternError(fun: Tree) =
NormalTypeError(fun, "too many arguments for unapply pattern, maximum = "+definitions.MaxTupleArity)
- def WrongNumberArgsPatternError(tree: Tree, fun: Tree) =
- NormalTypeError(tree, "wrong number of arguments for "+treeSymTypeMsg(fun))
+ def WrongNumberOfArgsError(tree: Tree, fun: Tree) =
+ NormalTypeError(tree, "wrong number of arguments for "+ treeSymTypeMsg(fun))
def ApplyWithoutArgsError(tree: Tree, fun: Tree) =
NormalTypeError(tree, fun.tpe+" does not take parameters")
diff --git a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
index f8a5c401df..e5c0f5767c 100644
--- a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
@@ -59,6 +59,19 @@ trait TypeDiagnostics {
* the map, the addendum should also be printed.
*/
private var addendums = perRunCaches.newMap[Position, () => String]()
+ private var isTyperInPattern = false
+
+ /** Devising new ways of communicating error info out of
+ * desperation to work on error messages. This is used
+ * by typedPattern to wrap its business so we can generate
+ * a sensible error message when things go south.
+ */
+ def typingInPattern[T](body: => T): T = {
+ val saved = isTyperInPattern
+ isTyperInPattern = true
+ try body
+ finally isTyperInPattern = saved
+ }
def setAddendum(pos: Position, msg: () => String) =
if (pos != NoPosition)
@@ -138,13 +151,17 @@ trait TypeDiagnostics {
def hasParams = tree.tpe.paramSectionCount > 0
def preResultString = if (hasParams) ": " else " of type "
- def nullMessage = "expression of type " + tree.tpe
- def overloadedMessage = "overloaded method " + sym + " with alternatives:\n" + alternativesString(tree)
+ def patternMessage = "pattern " + tree.tpe.finalResultType + valueParamsString(tree.tpe)
+ def exprMessage = "expression of type " + tree.tpe
+ def overloadedMessage = s"overloaded method $sym with alternatives:\n" + alternativesString(tree)
def moduleMessage = "" + sym
def defaultMessage = moduleMessage + preResultString + tree.tpe
def applyMessage = defaultMessage + tree.symbol.locationString
- if (sym == null) nullMessage
+ if ((sym eq null) || (sym eq NoSymbol)) {
+ if (isTyperInPattern) patternMessage
+ else exprMessage
+ }
else if (sym.isOverloaded) overloadedMessage
else if (sym.isModule) moduleMessage
else if (sym.name == nme.apply) applyMessage
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index d90141b732..73ccdeec2c 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -3237,7 +3237,7 @@ trait Typers extends Modes with Adaptations with Tags {
val nbSubPats = args.length
val (formals, formalsExpanded) = extractorFormalTypes(resTp, nbSubPats, fun1.symbol)
- if (formals == null) duplErrorTree(WrongNumberArgsPatternError(tree, fun))
+ if (formals == null) duplErrorTree(WrongNumberOfArgsError(tree, fun))
else {
val args1 = typedArgs(args, mode, formals, formalsExpanded)
// This used to be the following (failing) assert:
@@ -5452,7 +5452,7 @@ trait Typers extends Modes with Adaptations with Tags {
// as a compromise, context.enrichmentEnabled tells adaptToMember to go ahead and enrich,
// but arbitrary conversions (in adapt) are disabled
// TODO: can we achieve the pattern matching bit of the string interpolation SIP without this?
- context.withImplicitsDisabledAllowEnrichment(typed(tree, PATTERNmode, pt))
+ typingInPattern(context.withImplicitsDisabledAllowEnrichment(typed(tree, PATTERNmode, pt)))
}
/** Types a (fully parameterized) type tree */
diff --git a/test/files/neg/names-defaults-neg.check b/test/files/neg/names-defaults-neg.check
index 2809350855..f3c45a6aa0 100644
--- a/test/files/neg/names-defaults-neg.check
+++ b/test/files/neg/names-defaults-neg.check
@@ -76,7 +76,7 @@ and method f in object t8 of type (a: Int, b: Object)String
match argument types (a: Int,b: String) and expected result type Any
println(t8.f(a = 0, b = "1")) // ambigous reference
^
-names-defaults-neg.scala:69: error: wrong number of arguments for <none>: (x: Int, y: String)A1
+names-defaults-neg.scala:69: error: wrong number of arguments for pattern A1(x: Int,y: String)
A1() match { case A1(_) => () }
^
names-defaults-neg.scala:76: error: no type parameters for method test4: (x: T[T[List[T[X forSome { type X }]]]])T[T[List[T[X forSome { type X }]]]] exist so that it can be applied to arguments (List[Int])
diff --git a/test/files/neg/wrong-args-for-none.check b/test/files/neg/wrong-args-for-none.check
new file mode 100644
index 0000000000..d3b2d572ab
--- /dev/null
+++ b/test/files/neg/wrong-args-for-none.check
@@ -0,0 +1,4 @@
+wrong-args-for-none.scala:5: error: wrong number of arguments for pattern Test.Foo(x: Int,y: Int)
+ def f(x: Any) = x match { case Bar(Foo(5)) => }
+ ^
+one error found
diff --git a/test/files/neg/wrong-args-for-none.scala b/test/files/neg/wrong-args-for-none.scala
new file mode 100644
index 0000000000..1caa4782a3
--- /dev/null
+++ b/test/files/neg/wrong-args-for-none.scala
@@ -0,0 +1,6 @@
+object Test {
+ case class Foo(x: Int, y: Int)
+ case class Bar(x: AnyRef)
+
+ def f(x: Any) = x match { case Bar(Foo(5)) => }
+}
diff --git a/test/files/pos/z1720.scala b/test/files/pos/z1720.scala
new file mode 100644
index 0000000000..7394d428c1
--- /dev/null
+++ b/test/files/pos/z1720.scala
@@ -0,0 +1,16 @@
+package test
+
+class Thing {
+ def info: Info[this.type] = InfoRepository.getInfo(this)
+ def info2: Info[this.type] = {
+ def self: this.type = this
+ InfoRepository.getInfo(self)
+ }
+}
+
+trait Info[T]
+case class InfoImpl[T](thing: T) extends Info[T]
+
+object InfoRepository {
+ def getInfo(t: Thing): Info[t.type] = InfoImpl(t)
+}
diff --git a/test/pending/pos/t3943/Outer_1.java b/test/pending/pos/t3943/Outer_1.java
new file mode 100644
index 0000000000..56c8cc7f85
--- /dev/null
+++ b/test/pending/pos/t3943/Outer_1.java
@@ -0,0 +1,14 @@
+public class Outer_1<E> {
+ abstract class Inner {
+ abstract public void foo(E e);
+ }
+}
+
+class Child extends Outer_1<String> {
+ // the implicit prefix for Inner is Outer<E> instead of Outer<String>
+ public Inner getInner() {
+ return new Inner() {
+ public void foo(String e) { System.out.println("meh "+e); }
+ };
+ }
+}
diff --git a/test/pending/pos/t3943/test_2.scala b/test/pending/pos/t3943/test_2.scala
new file mode 100644
index 0000000000..a19db8b226
--- /dev/null
+++ b/test/pending/pos/t3943/test_2.scala
@@ -0,0 +1,8 @@
+object Test extends App {
+ val x: Child = new Child
+ x.getInner.foo("meh")
+// ^
+// error: type mismatch;
+// found : java.lang.String("meh")
+// required: E
+}