diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Types.scala | 3 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Contexts.scala | 14 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 15 | ||||
-rw-r--r-- | test/files/neg/bug412.check | 6 | ||||
-rw-r--r-- | test/files/neg/bug412.scala (renamed from test/pending/neg/bug412.scala) | 0 | ||||
-rw-r--r-- | test/pending/pos/bug563.scala | 7 | ||||
-rw-r--r-- | test/pending/run/bug412.scala | 33 |
7 files changed, 68 insertions, 10 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala index 2e805dd5e3..5ec350c35f 100644 --- a/src/compiler/scala/tools/nsc/symtab/Types.scala +++ b/src/compiler/scala/tools/nsc/symtab/Types.scala @@ -1586,7 +1586,8 @@ trait Types requires SymbolTable { if (constr1.inst != NoType) constr1.inst <:< tp2 else { constr1.hibounds = tp2 :: constr1.hibounds; true } case Pair(_, RefinedType(parents2, ref2)) => - (parents2 forall tp1.<:<) && (ref2.toList forall tp1.specializes) + (parents2 forall tp1.<:<) && (ref2.toList forall tp1.specializes) && + (!parents2.exists(.symbol.isAbstractType) || tp1.symbol != AllRefClass) case Pair(RefinedType(parents1, ref1), _) => parents1 exists (.<:<(tp2)) /* todo: replace following with diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index 11d2aa2a3e..f24d2a21a4 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -263,7 +263,7 @@ trait Contexts requires Analyzer { private def collectImplicits(syms: List[Symbol], pre: Type): List[ImplicitInfo] = for (val sym <- syms; sym.hasFlag(IMPLICIT) && isAccessible(sym, pre, false)) - yield ImplicitInfo(sym.name, pre.memberType(sym), sym); + yield new ImplicitInfo(sym.name, pre, sym); private def collectImplicitImports(imp: ImportInfo): List[ImplicitInfo] = { val pre = imp.qual.tpe; @@ -274,7 +274,7 @@ trait Contexts requires Analyzer { var impls = collect(sels1) filter (info => info.name != from); if (to != nme.WILDCARD) { val sym = imp.importedSymbol(to); - if (sym.hasFlag(IMPLICIT)) impls = ImplicitInfo(to, pre.memberType(sym), sym) :: impls; + if (sym.hasFlag(IMPLICIT)) impls = new ImplicitInfo(to, pre, sym) :: impls; } impls } @@ -338,9 +338,15 @@ trait Contexts requires Analyzer { override def toString() = tree.toString(); } - case class ImplicitInfo(val name: Name, val tpe: Type, val sym: Symbol); + class ImplicitInfo(val name: Name, pre: Type, val sym: Symbol) { + private var tpeCache: Type = null; + def tpe: Type = { + if (tpeCache == null) tpeCache = pre.memberType(sym) + tpeCache + } + } - val NoImplicitInfo = ImplicitInfo(null, null, null) + val NoImplicitInfo = new ImplicitInfo(null, null, null) case class ImportType(expr: Tree) extends Type; } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 8637ff3a60..05dd710154 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -485,14 +485,17 @@ trait Typers requires Analyzer { // adapt(tree, mode, pt) // } - def adaptToMember(qual: Tree, name: Name, tp: Type): Tree = + def adaptToMember(qual: Tree, name: Name, tp: Type): Tree = { + val qtpe = qual.tpe.widen; if (qual.isTerm && (qual.symbol == null || qual.symbol.isValue) && - !phase.erasedTypes && !qual.tpe.widen.isError && !tp.isError) { - val coercion = inferView(qual.pos, qual.tpe.widen, name, tp, true) + !phase.erasedTypes && !qtpe.isError && !tp.isError && + qtpe.symbol != AllRefClass && qtpe.symbol != AllClass && qtpe != WildcardType) { + val coercion = inferView(qual.pos, qtpe, name, tp, true) if (coercion != EmptyTree) typedQualifier(atPos(qual.pos)(Apply(coercion, List(qual)))) else qual } else qual + } def adaptToName(qual: Tree, name: Name) = if (qual.tpe.nonLocalMember(name) != NoSymbol) qual @@ -911,7 +914,9 @@ trait Typers requires Analyzer { val vparamSyms = List.map2(fun.vparams, argpts) { (vparam, argpt) => if (vparam.tpt.isEmpty) vparam.tpt.tpe = - if (argpt == NoType) { error(vparam.pos, "missing parameter type"); ErrorType } + if (argpt == NoType || argpt == WildcardType) { + error(vparam.pos, "missing parameter type"); ErrorType + } else argpt namer.enterSym(vparam) vparam.symbol @@ -1782,7 +1787,7 @@ trait Typers requires Analyzer { def implicitsOfClass(clazz: Symbol): List[ImplicitInfo] = ( clazz.initialize.linkedModule.moduleClass.info.members.toList.filter(.hasFlag(IMPLICIT)) map - (sym => ImplicitInfo(sym.name, clazz.linkedModule.tpe.memberType(sym), sym)) + (sym => new ImplicitInfo(sym.name, clazz.linkedModule.tpe, sym)) ) var tree = searchImplicit(context.implicitss, true) diff --git a/test/files/neg/bug412.check b/test/files/neg/bug412.check new file mode 100644 index 0000000000..6caf74fb3d --- /dev/null +++ b/test/files/neg/bug412.check @@ -0,0 +1,6 @@ +bug412.scala:9 error: type mismatch; + found : scala.AllRef(null) + required: A.this.CX with A.this.C2 + val c: CX with C2 = null; + ^ +one error found diff --git a/test/pending/neg/bug412.scala b/test/files/neg/bug412.scala index 66de4761fb..66de4761fb 100644 --- a/test/pending/neg/bug412.scala +++ b/test/files/neg/bug412.scala diff --git a/test/pending/pos/bug563.scala b/test/pending/pos/bug563.scala new file mode 100644 index 0000000000..d559226bdb --- /dev/null +++ b/test/pending/pos/bug563.scala @@ -0,0 +1,7 @@ +object Test { + def map[A,R](a : List[A], f : A => R) : List[R] = a.map(f); + + def split(sn : Iterable[List[Cell[int]]]) : unit = + for (val n <- sn) + map(n,ptr => new Cell(ptr.elem)); +} diff --git a/test/pending/run/bug412.scala b/test/pending/run/bug412.scala new file mode 100644 index 0000000000..4610235427 --- /dev/null +++ b/test/pending/run/bug412.scala @@ -0,0 +1,33 @@ +object Magic { + + abstract class A[T1,T2]() { + trait C { type T; } + trait C1 extends C { type T = T1; } + trait C2 extends C { type T <: T2; } + + type CX; + + var cv: CX with C2 = _; + val c: CX with C2 = cv; + + def castA(x: c.T): T2 = x; + } + + class B[T1,T2] extends A[T1,T2]() { + type CX = C1; + + def castB(x: T1): T2 = castA(x); + } + + def cast[T1,T2](v: T1): T2 = + new B[T1,T2]().castB(v) + +} + +object Test { + + def main(args: Array[String]): Unit = { + Magic.cast[String,Exception]("xyz").printStackTrace(); + } + +} |