diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/UnCurry.scala | 8 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Contexts.scala | 1 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Infer.scala | 101 | ||||
-rw-r--r-- | test/files/neg/bug126.check | 4 | ||||
-rw-r--r-- | test/files/neg/bug126.scala | 8 | ||||
-rw-r--r-- | test/files/neg/escapes.check | 5 | ||||
-rwxr-xr-x | test/files/neg/escapes.scala | 6 | ||||
-rw-r--r-- | test/files/neg/gadts1.check | 7 | ||||
-rw-r--r-- | test/files/neg/viewtest.check | 7 | ||||
-rwxr-xr-x | test/files/pos/escapes2.scala | 5 | ||||
-rw-r--r-- | test/files/pos/viewtest2.scala | 2 | ||||
-rw-r--r-- | test/files/run/lisp.scala | 2 |
12 files changed, 113 insertions, 43 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index c586253333..233b67aaf2 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -160,7 +160,7 @@ abstract class UnCurry extends InfoTransform with TypingTransformers { * try { * body * } catch { - * case ex: NonLocalReturnException => + * case ex: NonLocalReturnException[_] => * if (ex.key().eq(key)) ex.value() * else throw ex * } @@ -170,7 +170,11 @@ abstract class UnCurry extends InfoTransform with TypingTransformers { localTyper.typed { val extpe = nonLocalReturnExceptionType(meth) val ex = meth.newValue(body.pos, nme.ex) setInfo extpe - val pat = Bind(ex, Typed(Ident(nme.WILDCARD), TypeTree(extpe))) + val pat = Bind(ex, + Typed(Ident(nme.WILDCARD), + AppliedTypeTree(Ident(NonLocalReturnExceptionClass), + List(Bind(nme.WILDCARD.toTypeName, + EmptyTree))))) val rhs = If( Apply( diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index 6d2806c6ce..1f3743c310 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -336,7 +336,6 @@ trait Contexts requires Analyzer { if (settings.debug.value) log("resetting " + sym + " to " + info); sym.info match { case TypeBounds(lo, hi) if (hi <:< lo && lo <:< hi) => - Console.println("subst "+sym+" to "+lo) current = current.subst(List(sym), List(lo)) case _ => } diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index 793cceb256..95a0fd4028 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -234,7 +234,9 @@ trait Infer requires Analyzer { ) def foundReqMsg(found: Type, req: Type): String = - ";\n found : " + found.toLongString + "\n required: " + req + withDisambiguation(found, req) { + ";\n found : " + found.toLongString + "\n required: " + req + } def error(pos: PositionType, msg: String): unit = context.error(pos, msg) @@ -251,8 +253,7 @@ trait Infer requires Analyzer { (if (!(found.resultType eq found) && isWeaklyCompatible(found.resultType, req)) "\n possible cause: missing arguments for method or constructor" else "")) - if (settings.explaintypes.value) - explainTypes(found, req) + if (settings.explaintypes.value) explainTypes(found, req) } def typeErrorTree(tree: Tree, found: Type, req: Type): Tree = { @@ -260,6 +261,42 @@ trait Infer requires Analyzer { setError(tree) } + def explainTypes(tp1: Type, tp2: Type) = + withDisambiguation(tp1, tp2) { global.explainTypes(tp1, tp2) } + + /** If types `tp1' `tp2' contain different type variables with same name + * differentiate the names by including owner information + */ + private def withDisambiguation[T](tp1: Type, tp2: Type)(op: => T): T = { + + def explainName(sym: Symbol) = { sym.name = newTypeName("<"+sym+" in "+sym.owner+">") } + + val patches = { + val tparams1 = freeTypeParams.collect(tp1) + val tparams2 = freeTypeParams.collect(tp2) + for { + val tparam1 <- tparams1 + val tparam2 <- tparams2 + tparam1 != tparam2 && tparam1.name == tparam2.name + } yield { + val name = tparam1.name + explainName(tparam1) + explainName(tparam2) + if (tparam1.owner == tparam2.owner) tparam2.name = newTypeName("some other "+tparam2.name) + Triple(tparam1, tparam2, tparam1.name) + } + } + + val result = op + + for (val Triple(tparam1, tparam2, name) <- patches) { + tparam1.name = name + tparam2.name = name + } + + result + } + /* -- Tests & Checks---------------------------------------------------- */ /** Check that <code>sym</code> is defined and accessible as a member of @@ -297,9 +334,8 @@ trait Infer requires Analyzer { accessError("") } else { //System.out.println("check acc " + sym1 + ":" + sym1.tpe + " from " + pre);//DEBUG - var owntype = /* try{ */ + var owntype = try{ pre.memberType(sym1) -/* } catch { case ex: MalformedType => val sym2 = underlying(sym1) @@ -309,7 +345,6 @@ trait Infer requires Analyzer { else " contains a "+ex.msg)) ErrorType } -*/ if (pre.isInstanceOf[SuperType]) owntype = owntype.substSuper(pre, site.symbol.thisType) tree setSymbol sym1 setType owntype @@ -696,7 +731,7 @@ trait Infer requires Analyzer { computeArgs } else if (isFullyDefined(pt)) { if (settings.debug.value) log("infer constr " + tree + ":" + restpe + ", pt = " + pt) - var ptparams = freeTypeParams.collect(pt) + var ptparams = freeTypeParamsOfTerms.collect(pt) if (settings.debug.value) log("free type params = " + ptparams) val ptWithWildcards = pt.subst(ptparams, ptparams map (ptparam => WildcardType)) tvars = undetparams map freshVar @@ -777,17 +812,35 @@ trait Infer requires Analyzer { } } + /** Type intersection of simple type `tp1' with general type `tp2' + * The result eliminates some redundancies + */ + def intersect(tp1: Type, tp2: Type): Type = { + if (tp1 <:< tp2) tp1 + else if (tp2 <:< tp1) tp2 + else { + val reduced2 = tp2 match { + case rtp @ RefinedType(parents2, decls2) => + copyRefinedType(rtp, parents2 filter (p2 => !(tp1 <:< p2)), decls2) + case _ => + tp2 + } + intersectionType(List(tp1, reduced2)) + } + } + def inferTypedPattern(tpt: Tree, pt: Type): Type = { + //Console.println("infer typed pattern: "+tpt)//DEBUG checkCheckable(tpt.pos, tpt.tpe) if (!(tpt.tpe <:< pt)) { - val tpparams = freeTypeParams.collect(tpt.tpe) + val tpparams = freeTypeParamsOfTerms.collect(tpt.tpe) if (settings.debug.value) log("free type params (1) = " + tpparams) var tvars = tpparams map freshVar var tp = tpt.tpe.subst(tpparams, tvars) if (!(tp <:< pt)) { tvars = tpparams map freshVar tp = tpt.tpe.subst(tpparams, tvars) - val ptparams = freeTypeParams.collect(pt) + val ptparams = freeTypeParamsOfTerms.collect(pt) if (settings.debug.value) log("free type params (2) = " + ptparams) val ptvars = ptparams map freshVar val pt1 = pt.subst(ptparams, ptvars) @@ -799,7 +852,7 @@ trait Infer requires Analyzer { } tvars foreach instantiateTypeVar(true) } - intersectionType(List(tpt.tpe, pt)) + intersect(tpt.tpe, pt) } object toOrigin extends TypeMap { @@ -809,25 +862,24 @@ trait Infer requires Analyzer { } } - /** A traverser to collect type parameters referred to in a type - */ - object freeTypeParams extends TypeTraverser { + abstract class FreeSymCollector extends TypeTraverser { private var result: List[Symbol] = _ - private def includeIfTypeParam(sym: Symbol): unit = { - if (sym.isAbstractType && sym.owner.isTerm && !result.contains(sym)) - result = sym :: result - } + protected def includeCondition(sym: Symbol): boolean + private def include(sym: Symbol): unit = + if (includeCondition(sym) && !result.contains(sym)) result = sym :: result + override def traverse(tp: Type): TypeTraverser = { tp match { case TypeRef(NoPrefix, sym, _) => - includeIfTypeParam(sym) + include(sym) case TypeRef(ThisType(_), sym, _) => - includeIfTypeParam(sym) + include(sym) case _ => } mapOver(tp) this } + /** Collect all abstract type symbols referred to by type <code>tp</code>. * * @param tp ... @@ -840,6 +892,17 @@ trait Infer requires Analyzer { } } + /** A traverser to collect type parameters referred to in a type + */ + object freeTypeParamsOfTerms extends FreeSymCollector { + protected def includeCondition(sym: Symbol): boolean = sym.isAbstractType && sym.owner.isTerm + } + + object freeTypeParams extends FreeSymCollector { + protected def includeCondition(sym: Symbol): boolean = + sym.isAbstractType && (sym.owner.isTerm || (sym hasFlag PARAM)) + } + /* -- Overload Resolution ---------------------------------------------- */ /** Assign <code>tree</code> the symbol and type of the alternative which diff --git a/test/files/neg/bug126.check b/test/files/neg/bug126.check deleted file mode 100644 index 84a50aa821..0000000000 --- a/test/files/neg/bug126.check +++ /dev/null @@ -1,4 +0,0 @@ -bug126.scala:5 error: forward reference extends over definition of value foo2 - val Tuple1(foo2:(Any => Any)) = Tuple1((x:Any) => foo2(x)); - ^ -one error found diff --git a/test/files/neg/bug126.scala b/test/files/neg/bug126.scala deleted file mode 100644 index 75c10e608a..0000000000 --- a/test/files/neg/bug126.scala +++ /dev/null @@ -1,8 +0,0 @@ -class O { - val Bar:Any => Any = ((x:Any) => Bar(x)); - val Tuple2(foo:(Any => Any), bar) = Tuple2((x:Any) => foo(x), 1); - { - val Tuple1(foo2:(Any => Any)) = Tuple1((x:Any) => foo2(x)); - Console.println(foo2) - } -} diff --git a/test/files/neg/escapes.check b/test/files/neg/escapes.check new file mode 100644 index 0000000000..95299a4c75 --- /dev/null +++ b/test/files/neg/escapes.check @@ -0,0 +1,5 @@ +escapes.scala:2 error: type t escapes its defining scope as part of type t + def f(x: Any) = x match { case y: Cell[t] => y.elem }
+ ^ +subst type t to T +one error found diff --git a/test/files/neg/escapes.scala b/test/files/neg/escapes.scala new file mode 100755 index 0000000000..3a280e8d0a --- /dev/null +++ b/test/files/neg/escapes.scala @@ -0,0 +1,6 @@ +object Test { + def f(x: Any) = x match { case y: Cell[t] => y.elem } + class C3[T](val elem: T) + class D3[T](val elemD: T) extends C3[T](elemD) + def f[T](x: C3[T]) = x match { case d: D3[t] => d.elemD } +} diff --git a/test/files/neg/gadts1.check b/test/files/neg/gadts1.check index 8b3d6605ed..a761b79cb8 100644 --- a/test/files/neg/gadts1.check +++ b/test/files/neg/gadts1.check @@ -1,11 +1,6 @@ gadts1.scala:15 error: type mismatch; - found : Test.this.NumTerm - required: Test.this.Term[a] - case NumTerm(n) => c.x = Double(1.0) - ^ -gadts1.scala:15 error: type mismatch; found : Test.this.Double required: a case NumTerm(n) => c.x = Double(1.0) ^ -two errors found +one error found diff --git a/test/files/neg/viewtest.check b/test/files/neg/viewtest.check index b98b56bce5..044c3b7d91 100644 --- a/test/files/neg/viewtest.check +++ b/test/files/neg/viewtest.check @@ -1,7 +1,12 @@ +viewtest.scala:43 error: type mismatch; + found : scala.List[<type a in method compareTo>] + required: scala.List[<type a in method view3>] + case y1: List[a] => compareLists(x, y1) + ^ viewtest.scala:104 error: ambiguous implicit value: both method view4 in object O of type [a](a)a and method identity in object Predef of type [a](a)a match expected type (test.Str) => test.Ordered[test.Str] t = t insert Str(s) ^ -one error found +two errors found diff --git a/test/files/pos/escapes2.scala b/test/files/pos/escapes2.scala new file mode 100755 index 0000000000..b94066936a --- /dev/null +++ b/test/files/pos/escapes2.scala @@ -0,0 +1,5 @@ +object Test { + class C3[T](val elem: T) + class D3[T](val elemD: T) extends C3[T](elemD) + def f[T](x: C3[T]) = x match { case d: D3[t] => d.elemD } +} diff --git a/test/files/pos/viewtest2.scala b/test/files/pos/viewtest2.scala index 66cd1aa1bd..6a6ed96df7 100644 --- a/test/files/pos/viewtest2.scala +++ b/test/files/pos/viewtest2.scala @@ -40,7 +40,7 @@ object O { implicit def view3[a <% Ordered[a]](x: List[a]): Ordered[List[a]] = new Ordered[List[a]] { def compareTo [b >: List[a] <% Ordered[b]](y: b): int = y match { - case y1: List[a] => compareLists(x, y1) + case y1: List[a1] => compareLists(x, y1.asInstanceOf[List[a]]) case _ => -(y compareTo x) } private def compareLists(xs: List[a], ys: List[a]): int = { diff --git a/test/files/run/lisp.scala b/test/files/run/lisp.scala index f12196ca50..bf895f2349 100644 --- a/test/files/run/lisp.scala +++ b/test/files/run/lisp.scala @@ -287,7 +287,7 @@ object LispAny extends Lisp { } def asList(x: Data): List[Data] = x match { - case y: List[Data] => y + case y: List[_] => y case _ => lispError("malformed list: " + x) } |