From 3e20bebd192444d8c1b079489292011e8030b532 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Wed, 2 May 2012 10:42:48 +0200 Subject: SI-5729: TypeVar experimentals iff -Xexperimental it used to also be enabled by -Yvirtpatmat, which is now on by default, but this type hackery is no longer necessary to bootstrap under the new pattern matching scheme, so let's only turn it on when people are feeling -Xexperimental --- test/files/pos/t5729.scala | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 test/files/pos/t5729.scala (limited to 'test/files/pos') diff --git a/test/files/pos/t5729.scala b/test/files/pos/t5729.scala new file mode 100644 index 0000000000..9fd9c9ffbb --- /dev/null +++ b/test/files/pos/t5729.scala @@ -0,0 +1,6 @@ +trait T[X] +object Test { + def join(in: Seq[T[_]]): Int = ??? + def join[S](in: Seq[T[S]]): String = ??? + join(null: Seq[T[_]]) +} \ No newline at end of file -- cgit v1.2.3 From e9ed9d4280246fece2268e69cca0fe316ba19b98 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Wed, 2 May 2012 16:11:34 +0200 Subject: SI-5542 closed by test case --- test/files/pos/t5542.flags | 1 + test/files/pos/t5542.scala | 3 +++ 2 files changed, 4 insertions(+) create mode 100644 test/files/pos/t5542.flags create mode 100644 test/files/pos/t5542.scala (limited to 'test/files/pos') diff --git a/test/files/pos/t5542.flags b/test/files/pos/t5542.flags new file mode 100644 index 0000000000..464cc20ea6 --- /dev/null +++ b/test/files/pos/t5542.flags @@ -0,0 +1 @@ +-Xfatal-warnings -unchecked \ No newline at end of file diff --git a/test/files/pos/t5542.scala b/test/files/pos/t5542.scala new file mode 100644 index 0000000000..80b8cef030 --- /dev/null +++ b/test/files/pos/t5542.scala @@ -0,0 +1,3 @@ +class Test { + Option(3) match { case Some(n) => n; case None => 0 } +} \ No newline at end of file -- cgit v1.2.3 From 40f0340628c376dbc8e327de2adc58c203e16d68 Mon Sep 17 00:00:00 2001 From: Aleksandar Prokopec Date: Wed, 2 May 2012 19:12:09 +0200 Subject: Test case for si-5198. --- test/files/pos/t5198.scala | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 test/files/pos/t5198.scala (limited to 'test/files/pos') diff --git a/test/files/pos/t5198.scala b/test/files/pos/t5198.scala new file mode 100644 index 0000000000..f403f77f7d --- /dev/null +++ b/test/files/pos/t5198.scala @@ -0,0 +1,15 @@ +package gaga + + + + + +trait Sys[Self <: Sys[Self]] { + type Tx +} + + +sealed trait AssocEntry[S <: Sys[S], @specialized(Int) A] { + def value: A + def value(implicit tx: S#Tx): A +} -- cgit v1.2.3 From aabe71f989f023d64b6c52680485e4cacb4e88b9 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Wed, 2 May 2012 10:19:05 -0700 Subject: SI-5720: Qual block doesn't update sym owner A one-line change to blockWithQualifier. The symptom is undefined tmp var symbols in the backend; lamba lift thinks the tmp var is free and adds it to anonfun ctors. --- .../tools/nsc/typechecker/NamesDefaults.scala | 2 + test/files/pos/t5720-ownerous.scala | 56 ++++++++++++++++++++++ test/files/pos/t5727.scala | 31 ++++++++++++ 3 files changed, 89 insertions(+) create mode 100644 test/files/pos/t5720-ownerous.scala create mode 100644 test/files/pos/t5727.scala (limited to 'test/files/pos') diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala index 898a9fee9f..90e388c30a 100644 --- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala +++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala @@ -155,6 +155,8 @@ trait NamesDefaults { self: Analyzer => val sym = blockTyper.context.owner.newValue(unit.freshTermName("qual$"), qual.pos) setInfo qual.tpe blockTyper.context.scope enter sym val vd = atPos(sym.pos)(ValDef(sym, qual) setType NoType) + // it stays in Vegas: SI-5720, SI-5727 + qual changeOwner (blockTyper.context.owner -> sym) var baseFunTransformed = atPos(baseFun.pos.makeTransparent) { // don't use treeCopy: it would assign opaque position. diff --git a/test/files/pos/t5720-ownerous.scala b/test/files/pos/t5720-ownerous.scala new file mode 100644 index 0000000000..3a12499612 --- /dev/null +++ b/test/files/pos/t5720-ownerous.scala @@ -0,0 +1,56 @@ + +/* + * The block under qual$1 must be owned by it. + * In the sample bug, the first default arg generates x$4, + * the second default arg generates qual$1, hence the maximal + * minimization. + * + def model: C.this.M = { + val qual$1: C.this.M = scala.Option.apply[C.this.M]({ + val x$1: lang.this.String("foo") = "foo"; + val x$2: String = C.this.M.apply$default$2("foo"); + C.this.M.apply("foo")(x$2) +}).getOrElse[C.this.M]({ + val x$3: lang.this.String("bar") = "bar"; + val x$4: String = C.this.M.apply$default$2("bar"); + C.this.M.apply("bar")(x$4) + }); + val x$5: lang.this.String("baz") = "baz"; + val x$6: String = qual$1.copy$default$2("baz"); + qual$1.copy("baz")(x$6) + } + */ +class C { + case class M(currentUser: String = "anon")(val message: String = "empty") + val m = M("foo")() + + // reported + //def model = Option(M("foo")()).getOrElse(M("bar")()).copy(currentUser = "")() + + // the bug + def model = Option(m).getOrElse(M("bar")()).copy("baz")() + + // style points for this version + def modish = ((null: Option[M]) getOrElse new M()()).copy()() + + // various simplifications are too simple + case class N(currentUser: String = "anon") + val n = N("fun") + def nudel = Option(n).getOrElse(N()).copy() +} + +object Test { + def main(args: Array[String]) { + val c = new C + println(c.model.currentUser) + println(c.model.message) + } +} +/* +symbol value x$4$1 does not exist in badcopy.C.model +at scala.reflect.internal.SymbolTable.abort(SymbolTable.scala:45) +at scala.tools.nsc.Global.abort(Global.scala:202) +at scala.tools.nsc.backend.icode.GenICode$ICodePhase.liftedTree2$1(GenICode.scala:998) +at scala.tools.nsc.backend.icode.GenICode$ICodePhase.scala$tools$nsc$backend$icode$GenICode$ICodePhase$$genLoad(GenICode.scala:992) +*/ + diff --git a/test/files/pos/t5727.scala b/test/files/pos/t5727.scala new file mode 100644 index 0000000000..e091d827b4 --- /dev/null +++ b/test/files/pos/t5727.scala @@ -0,0 +1,31 @@ + +/* + * We like operators, bar none. + */ +object Test { + + trait SomeInfo + case object NoInfo extends SomeInfo + + sealed abstract class Res[+T] + case object NotRes extends Res[Nothing] + + + abstract class Base[+T] { + def apply(f: String): Res[T] + // 'i' crashes the compiler, similarly if we use currying + //def |[U >: T](a: => Base[U], i: SomeInfo = NoInfo): Base[U] = null + def bar[U >: T](a: => Base[U], i: SomeInfo = NoInfo): Base[U] = null + } + + implicit def fromStringToBase(a: String): Base[String] = new Base[String] { def apply(in: String) = NotRes } + + // bug + //def Sample: Base[Any] = ( rep("foo" | "bar") | "sth") + def Sample: Base[Any] = ( rep("foo" bar "bar") bar "sth") + + def rep[T](p: => Base[T]): Base[T] = null // whatever + + def main(args: Array[String]) { + } +} -- cgit v1.2.3 From 7a5aaa9e23a98d60343cc0c4411b3fc395faa3ab Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Thu, 3 May 2012 11:09:13 +0200 Subject: SI-5703: normalize refined types more to improve Array[T] java-interop with T[], normalize Object with Object{} to Object fix #SI-5688 by flattening refined types in parents updated check files to reflect flattening of refined types and updated position for refined types --- src/compiler/scala/reflect/internal/Types.scala | 31 ++++++++++----- .../nsc/symtab/classfile/ClassfileParser.scala | 6 ++- .../scala/tools/nsc/typechecker/Namers.scala | 5 +++ .../tools/nsc/typechecker/PatternMatching.scala | 2 +- test/files/neg/override.check | 2 +- test/files/pos/t5703/Base.java | 3 ++ test/files/pos/t5703/Impl.scala | 3 ++ test/files/run/existentials3-old.check | 44 +++++++++++----------- test/files/run/t5688.check | 1 + test/files/run/t5688.scala | 23 +++++++++++ 10 files changed, 86 insertions(+), 34 deletions(-) create mode 100644 test/files/pos/t5703/Base.java create mode 100644 test/files/pos/t5703/Impl.scala create mode 100644 test/files/run/t5688.check create mode 100644 test/files/run/t5688.scala (limited to 'test/files/pos') diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala index 165f8119ce..799671f9e3 100644 --- a/src/compiler/scala/reflect/internal/Types.scala +++ b/src/compiler/scala/reflect/internal/Types.scala @@ -1610,12 +1610,26 @@ trait Types extends api.Types { self: SymbolTable => override def typeConstructor = copyRefinedType(this, parents map (_.typeConstructor), decls) - /* MO to AM: This is probably not correct - * If they are several higher-kinded parents with different bounds we need - * to take the intersection of their bounds - */ - override def normalize = { - if (isHigherKinded) { + final override def normalize: Type = + if (phase.erasedTypes) normalizeImpl + else { + if (normalized eq null) normalized = normalizeImpl + normalized + } + + private var normalized: Type = _ + private def normalizeImpl = { + // TODO see comments around def intersectionType and def merge + def flatten(tps: List[Type]): List[Type] = tps flatMap { case RefinedType(parents, ds) if ds.isEmpty => flatten(parents) case tp => List(tp) } + val flattened = flatten(parents).distinct + if (decls.isEmpty && flattened.tail.isEmpty) { + flattened.head + } else if (flattened != parents) { + refinedType(flattened, if (typeSymbol eq NoSymbol) NoSymbol else typeSymbol.owner, decls, NoPosition) + } else if (isHigherKinded) { + // MO to AM: This is probably not correct + // If they are several higher-kinded parents with different bounds we need + // to take the intersection of their bounds typeFun( typeParams, RefinedType( @@ -1625,8 +1639,7 @@ trait Types extends api.Types { self: SymbolTable => }, decls, typeSymbol)) - } - else super.normalize + } else super.normalize } /** A refined type P1 with ... with Pn { decls } is volatile if @@ -3322,7 +3335,7 @@ trait Types extends api.Types { self: SymbolTable => if (phase.erasedTypes) if (parents.isEmpty) ObjectClass.tpe else parents.head else { - val clazz = owner.newRefinementClass(NoPosition) + val clazz = owner.newRefinementClass(pos) // TODO: why were we passing in NoPosition instead of pos? val result = RefinedType(parents, decls, clazz) clazz.setInfo(result) result diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index b51c8baa31..739060d02e 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -774,8 +774,12 @@ abstract class ClassfileParser { // make unbounded Array[T] where T is a type variable into Array[T with Object] // (this is necessary because such arrays have a representation which is incompatible // with arrays of primitive types. - if (elemtp.typeSymbol.isAbstractType && !(elemtp <:< definitions.ObjectClass.tpe)) + // NOTE that the comparison to Object only works for abstract types bounded by classes that are strict subclasses of Object + // if the bound is exactly Object, it will have been converted to Any, and the comparison will fail + // see also RestrictJavaArraysMap (when compiling java sources directly) + if (elemtp.typeSymbol.isAbstractType && !(elemtp <:< definitions.ObjectClass.tpe)) { elemtp = intersectionType(List(elemtp, definitions.ObjectClass.tpe)) + } definitions.arrayType(elemtp) case '(' => diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 45f7d7e618..4e7dac890b 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -1347,6 +1347,11 @@ trait Namers extends MethodSynthesis { /** Convert Java generic array type T[] to (T with Object)[] * (this is necessary because such arrays have a representation which is incompatible * with arrays of primitive types.) + * + * @note the comparison to Object only works for abstract types bounded by classes that are strict subclasses of Object + * if the bound is exactly Object, it will have been converted to Any, and the comparison will fail + * + * see also sigToType */ private object RestrictJavaArraysMap extends TypeMap { def apply(tp: Type): Type = tp match { diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala index c3a7f2bbc5..61e02edaff 100644 --- a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala +++ b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala @@ -931,7 +931,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL // implements the run-time aspects of (ยง8.2) (typedPattern has already done the necessary type transformations) // TODO: normalize construction, which yields a combination of a EqualityTestTreeMaker (when necessary) and a TypeTestTreeMaker case class TypeAndEqualityTestTreeMaker(prevBinder: Symbol, patBinder: Symbol, pt: Type, pos: Position) extends CondTreeMaker { - val nextBinderTp = glb(List(patBinder.info.widen, pt)) + val nextBinderTp = glb(List(patBinder.info.widen, pt)).normalize /** Type patterns consist of types, type variables, and wildcards. A type pattern T is of one of the following forms: - A reference to a class C, p.C, or T#C. diff --git a/test/files/neg/override.check b/test/files/neg/override.check index 0336fb2b11..fc152cb3b1 100644 --- a/test/files/neg/override.check +++ b/test/files/neg/override.check @@ -1,5 +1,5 @@ override.scala:9: error: overriding type T in trait A with bounds >: Int <: Int; type T in trait B with bounds >: String <: String has incompatible type lazy val x : A with B = x - ^ + ^ one error found diff --git a/test/files/pos/t5703/Base.java b/test/files/pos/t5703/Base.java new file mode 100644 index 0000000000..fa75cc3bdd --- /dev/null +++ b/test/files/pos/t5703/Base.java @@ -0,0 +1,3 @@ +public abstract class Base { + public abstract void func(Params[] params); +} \ No newline at end of file diff --git a/test/files/pos/t5703/Impl.scala b/test/files/pos/t5703/Impl.scala new file mode 100644 index 0000000000..ee22d8fb4b --- /dev/null +++ b/test/files/pos/t5703/Impl.scala @@ -0,0 +1,3 @@ +class Implementation extends Base[Object] { + def func(params: Array[Object]): Unit = {} +} \ No newline at end of file diff --git a/test/files/run/existentials3-old.check b/test/files/run/existentials3-old.check index e166e53ba8..72abfac637 100644 --- a/test/files/run/existentials3-old.check +++ b/test/files/run/existentials3-old.check @@ -1,22 +1,22 @@ -_ <: scala.runtime.AbstractFunction0[_ <: Object with Test$ToS with scala.Product with scala.Serializable] with scala.Serializable with java.lang.Object -_ <: Object with Test$ToS with scala.Product with scala.Serializable -Object with Test$ToS -Object with Test$ToS -Object with Test$ToS -scala.Function0[Object with Test$ToS] -scala.Function0[Object with Test$ToS] -_ <: Object with _ <: Object with Object with Test$ToS -_ <: Object with _ <: Object with _ <: Object with Test$ToS -scala.collection.immutable.List[Object with scala.collection.Seq[Int]] -scala.collection.immutable.List[Object with scala.collection.Seq[_ <: Int]] -_ <: scala.runtime.AbstractFunction0[_ <: Object with Test$ToS with scala.Product with scala.Serializable] with scala.Serializable with java.lang.Object -_ <: Object with Test$ToS with scala.Product with scala.Serializable -Object with Test$ToS -Object with Test$ToS -Object with Test$ToS -scala.Function0[Object with Test$ToS] -scala.Function0[Object with Test$ToS] -_ <: Object with _ <: Object with Object with Test$ToS -_ <: Object with _ <: Object with _ <: Object with Test$ToS -scala.collection.immutable.List[Object with scala.collection.Seq[Int]] -scala.collection.immutable.List[Object with scala.collection.Seq[_ <: Int]] +_ <: scala.runtime.AbstractFunction0[_ <: Object with Test$ToS with scala.Product with scala.Serializable] with scala.Serializable with java.lang.Object +_ <: Object with Test$ToS with scala.Product with scala.Serializable +Object with Test$ToS +Object with Test$ToS +Object with Test$ToS +scala.Function0[Object with Test$ToS] +scala.Function0[Object with Test$ToS] +_ <: Object with _ <: Object with Test$ToS +_ <: Object with _ <: Object with _ <: Object with Test$ToS +scala.collection.immutable.List[Object with scala.collection.Seq[Int]] +scala.collection.immutable.List[Object with scala.collection.Seq[_ <: Int]] +_ <: scala.runtime.AbstractFunction0[_ <: Object with Test$ToS with scala.Product with scala.Serializable] with scala.Serializable with java.lang.Object +_ <: Object with Test$ToS with scala.Product with scala.Serializable +Object with Test$ToS +Object with Test$ToS +Object with Test$ToS +scala.Function0[Object with Test$ToS] +scala.Function0[Object with Test$ToS] +_ <: Object with _ <: Object with Test$ToS +_ <: Object with _ <: Object with _ <: Object with Test$ToS +scala.collection.immutable.List[Object with scala.collection.Seq[Int]] +scala.collection.immutable.List[Object with scala.collection.Seq[_ <: Int]] diff --git a/test/files/run/t5688.check b/test/files/run/t5688.check new file mode 100644 index 0000000000..2c84f9e2ef --- /dev/null +++ b/test/files/run/t5688.check @@ -0,0 +1 @@ +Vector(ta, tb, tab) diff --git a/test/files/run/t5688.scala b/test/files/run/t5688.scala new file mode 100644 index 0000000000..f99bfb47d3 --- /dev/null +++ b/test/files/run/t5688.scala @@ -0,0 +1,23 @@ +object Test extends App { + trait T + + trait TA + trait TB + + class A extends T with TA + class B extends T with TB + class AB extends T with TA with TB + // Matching on _: TA with TB + + val li: Vector[T] = Vector(new A, new B, new AB) + + val matched = (for (l <- li) yield { + l match { + case _: TA with TB => "tab" + case _: TA => "ta" + case _: TB => "tb" + } + }) + + println(matched) +} \ No newline at end of file -- cgit v1.2.3