summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/reflect/reify/codegen/GenSymbols.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala56
-rw-r--r--test/files/neg/t0764.check7
-rw-r--r--test/files/neg/t0764.scala45
-rw-r--r--test/files/neg/t0764b.check47
-rw-r--r--test/files/neg/t0764b.scala (renamed from test/files/pos/t0764b.scala)2
-rw-r--r--test/files/neg/t8104/Test_2.scala2
-rw-r--r--test/files/neg/t8177a.check6
-rw-r--r--test/files/neg/t8177a.scala6
-rw-r--r--test/files/pos/t0764.scala27
-rw-r--r--test/files/pos/t8177h.scala5
-rw-r--r--test/files/run/t6992.check1
-rw-r--r--test/files/run/t6992/Test_2.scala4
-rw-r--r--test/files/run/t8104.check3
-rw-r--r--test/files/run/t8104/Test_2.scala5
15 files changed, 168 insertions, 50 deletions
diff --git a/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala b/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala
index 3a97089d51..2965db17c6 100644
--- a/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala
+++ b/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala
@@ -93,7 +93,7 @@ trait GenSymbols {
// todo. make sure that free methods and free local defs work correctly
if (sym.isExistential) reifySymDef(sym)
else if (sym.isTerm) reifyFreeTerm(Ident(sym))
- else reifyFreeType(Ident(sym))
+ else reifyFreeType(Ident(sym)) // TODO: reify refinement classes
}
}
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index 6010d4eb12..b2e36a2732 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -1143,7 +1143,7 @@ trait Types
/** A class for this-types of the form <sym>.this.type
*/
abstract case class ThisType(sym: Symbol) extends SingletonType with ThisTypeApi {
- if (!sym.isClass) {
+ if (!sym.isClass && !sym.isFreeType) {
// SI-6640 allow StubSymbols to reveal what's missing from the classpath before we trip the assertion.
sym.failIfStub()
abort(s"ThisType($sym) for sym which is not a class")
@@ -4100,24 +4100,44 @@ trait Types
)
}
- /** Does member `sym1` of `tp1` have a stronger type
- * than member `sym2` of `tp2`?
+ /** Does member `symLo` of `tpLo` have a stronger type
+ * than member `symHi` of `tpHi`?
*/
- protected[internal] def specializesSym(tp1: Type, sym1: Symbol, tp2: Type, sym2: Symbol, depth: Depth): Boolean = {
- require((sym1 ne NoSymbol) && (sym2 ne NoSymbol), ((tp1, sym1, tp2, sym2, depth)))
- val info1 = tp1.memberInfo(sym1)
- val info2 = tp2.memberInfo(sym2).substThis(tp2.typeSymbol, tp1)
- //System.out.println("specializes "+tp1+"."+sym1+":"+info1+sym1.locationString+" AND "+tp2+"."+sym2+":"+info2)//DEBUG
- ( sym2.isTerm && isSubType(info1, info2, depth) && (!sym2.isStable || sym1.isStable) && (!sym1.hasVolatileType || sym2.hasVolatileType)
- || sym2.isAbstractType && {
- val memberTp1 = tp1.memberType(sym1)
- // println("kinds conform? "+(memberTp1, tp1, sym2, kindsConform(List(sym2), List(memberTp1), tp2, sym2.owner)))
- info2.bounds.containsType(memberTp1) &&
- kindsConform(List(sym2), List(memberTp1), tp1, sym1.owner)
- }
- || sym2.isAliasType && tp2.memberType(sym2).substThis(tp2.typeSymbol, tp1) =:= tp1.memberType(sym1) //@MAT ok
- )
- }
+ protected[internal] def specializesSym(preLo: Type, symLo: Symbol, preHi: Type, symHi: Symbol, depth: Depth): Boolean =
+ (symHi.isAliasType || symHi.isTerm || symHi.isAbstractType) && {
+ // only now that we know symHi is a viable candidate ^^^^^^^, do the expensive checks: ----V
+ require((symLo ne NoSymbol) && (symHi ne NoSymbol), ((preLo, symLo, preHi, symHi, depth)))
+
+ val tpHi = preHi.memberInfo(symHi).substThis(preHi.typeSymbol, preLo)
+
+ // Should we use memberType or memberInfo?
+ // memberType transforms (using `asSeenFrom`) `sym.tpe`,
+ // whereas memberInfo performs the same transform on `sym.info`.
+ // For term symbols, this ends up being the same thing (`sym.tpe == sym.info`).
+ // For type symbols, however, the `.info` of an abstract type member
+ // is defined by its bounds, whereas its `.tpe` is a `TypeRef` to that type symbol,
+ // so that `sym.tpe <:< sym.info`, but not the other way around.
+ //
+ // Thus, for the strongest (correct) result,
+ // we should use `memberType` on the low side.
+ //
+ // On the high side, we should use the result appropriate
+ // for the right side of the `<:<` above (`memberInfo`).
+ val tpLo = preLo.memberType(symLo)
+
+ debuglog(s"specializesSymHi: $preHi . $symHi : $tpHi")
+ debuglog(s"specializesSymLo: $preLo . $symLo : $tpLo")
+
+ if (symHi.isTerm)
+ (isSubType(tpLo, tpHi, depth) &&
+ (!symHi.isStable || symLo.isStable) && // sub-member must remain stable
+ (!symLo.hasVolatileType || symHi.hasVolatileType)) // sub-member must not introduce volatility
+ else if (symHi.isAbstractType)
+ ((tpHi.bounds containsType tpLo) &&
+ kindsConform(symHi :: Nil, tpLo :: Nil, preLo, symLo.owner))
+ else // we know `symHi.isAliasType` (see above)
+ tpLo =:= tpHi
+ }
/** A function implementing `tp1` matches `tp2`. */
final def matchesType(tp1: Type, tp2: Type, alwaysMatchSimple: Boolean): Boolean = {
diff --git a/test/files/neg/t0764.check b/test/files/neg/t0764.check
new file mode 100644
index 0000000000..0c7cff1e1e
--- /dev/null
+++ b/test/files/neg/t0764.check
@@ -0,0 +1,7 @@
+t0764.scala:13: error: type mismatch;
+ found : Node{type T = _1.type} where val _1: Node{type T = NextType}
+ required: Node{type T = Main.this.AType}
+ (which expands to) Node{type T = Node{type T = NextType}}
+ new Main[AType]( (value: AType).prepend )
+ ^
+one error found
diff --git a/test/files/neg/t0764.scala b/test/files/neg/t0764.scala
new file mode 100644
index 0000000000..9f77a59414
--- /dev/null
+++ b/test/files/neg/t0764.scala
@@ -0,0 +1,45 @@
+class Top[A] {
+ type AType = A
+}
+
+trait Node { outer =>
+ type T <: Node
+ def prepend = new Node { type T = outer.type }
+}
+
+class Main[NextType <: Node](value: Node { type T = NextType })
+ extends Top[Node { type T = NextType }] {
+
+ new Main[AType]( (value: AType).prepend )
+}
+
+/* we've been back-and-forth on this one -- see PRs on SI-8177 for the reasoning
+I think it should compile and that the following error is due to broken =:= on existentials
+ found : Node{type T = _1.type} where val _1: Node{type T = NextType}
+ required: Node{type T = Main.this.AType}
+ (which expands to) Node{type T = Node{type T = NextType}}
+
+I claim (omitting the forSome for brevity, even though the premature skolemization is probably the issue)
+_1.type =:= Main.this.AType
+because
+(1) _1.type <:< Main.this.AType and (2) Main.this.AType <:< _1.type
+(1), because:
+_1.type <:< Node{type T = NextType} (because skolemization and _1's upper bound)
+(2), because:
+Node{type T = NextType} <:< _1.type forSome val _1: Node{type T = NextType}
+because:
+Node{type T = NextType} <:< T forSome {type T <: Node{type T = NextType} with Singleton}
+because
+Node{type T = NextType} <:< Node{type T = NextType} with Singleton
+
+hmmm.. might the with Singleton be throwing a wrench in our existential house?
+
+Behold the equivalent program which type checks without the fix for SI-8177.
+(Expand type alias, convert type member to type param;
+note the covariance to encode subtyping on type members.)
+
+class Node[+T <: Node[_]] { def prepend = new Node[this.type] }
+class Main[NextType <: Node[_]](value: Node[NextType]) {
+ new Main(value.prepend)
+}
+*/ \ No newline at end of file
diff --git a/test/files/neg/t0764b.check b/test/files/neg/t0764b.check
new file mode 100644
index 0000000000..4040954e7c
--- /dev/null
+++ b/test/files/neg/t0764b.check
@@ -0,0 +1,47 @@
+t0764b.scala:27: error: type mismatch;
+ found : p1.t0764.Node{type T = p1.t0764.<refinement>.type}
+ required: p1.t0764.NodeAlias[p1.t0764.NodeAlias[A]]
+ (which expands to) p1.t0764.Node{type T = p1.t0764.Node{type T = A}}
+ private[this] def f2 = new Main1[NodeAlias[A]](v.prepend) // fail
+ ^
+t0764b.scala:28: error: type mismatch;
+ found : p1.t0764.Node{type T = p1.t0764.<refinement>.type}
+ required: p1.t0764.NodeAlias[p1.t0764.Node{type T = A}]
+ (which expands to) p1.t0764.Node{type T = p1.t0764.Node{type T = A}}
+ private[this] def f3 = new Main1[Node { type T = A }](v.prepend) // fail
+ ^
+t0764b.scala:34: error: type mismatch;
+ found : p1.t0764.Node{type T = p1.t0764.<refinement>.type}
+ required: p1.t0764.Node{type T = p1.t0764.NodeAlias[A]}
+ (which expands to) p1.t0764.Node{type T = p1.t0764.Node{type T = A}}
+ private[this] def f2 = new Main2[NodeAlias[A]](v.prepend) // fail
+ ^
+t0764b.scala:35: error: type mismatch;
+ found : p1.t0764.Node{type T = p1.t0764.<refinement>.type}
+ required: p1.t0764.Node{type T = p1.t0764.Node{type T = A}}
+ private[this] def f3 = new Main2[Node { type T = A }](v.prepend) // fail
+ ^
+t0764b.scala:51: error: type mismatch;
+ found : p2.t0764.Node{type T = p2.t0764.<refinement>.type}
+ required: p2.t0764.NodeAlias[p2.t0764.NodeAlias[A]]
+ (which expands to) p2.t0764.Node{type T = p2.t0764.Node{type T = A}}
+ private[this] def f2 = new Main1[NodeAlias[A]](v.prepend) // fail
+ ^
+t0764b.scala:52: error: type mismatch;
+ found : p2.t0764.Node{type T = p2.t0764.<refinement>.type}
+ required: p2.t0764.NodeAlias[p2.t0764.Node{type T = A}]
+ (which expands to) p2.t0764.Node{type T = p2.t0764.Node{type T = A}}
+ private[this] def f3 = new Main1[Node { type T = A }](v.prepend) // fail
+ ^
+t0764b.scala:58: error: type mismatch;
+ found : p2.t0764.Node{type T = p2.t0764.<refinement>.type}
+ required: p2.t0764.Node{type T = p2.t0764.NodeAlias[A]}
+ (which expands to) p2.t0764.Node{type T = p2.t0764.Node{type T = A}}
+ private[this] def f2 = new Main2[NodeAlias[A]](v.prepend) // fail
+ ^
+t0764b.scala:59: error: type mismatch;
+ found : p2.t0764.Node{type T = p2.t0764.<refinement>.type}
+ required: p2.t0764.Node{type T = p2.t0764.Node{type T = A}}
+ private[this] def f3 = new Main2[Node { type T = A }](v.prepend) // fail
+ ^
+8 errors found
diff --git a/test/files/pos/t0764b.scala b/test/files/neg/t0764b.scala
index 6ae3c105c9..14c623c67a 100644
--- a/test/files/pos/t0764b.scala
+++ b/test/files/neg/t0764b.scala
@@ -1,3 +1,5 @@
+// see neg/t0764 why this should probably be a pos/ test -- alas something's wrong with existential subtyping (?)
+
// In all cases when calling "prepend" the receiver 'v'
// has static type NodeAlias[A] or (equivalently) Node { type T = A }.
// Since prepend explicitly returns the singleton type of the receiver,
diff --git a/test/files/neg/t8104/Test_2.scala b/test/files/neg/t8104/Test_2.scala
index 585f76c00f..a3bd940188 100644
--- a/test/files/neg/t8104/Test_2.scala
+++ b/test/files/neg/t8104/Test_2.scala
@@ -9,7 +9,7 @@ object Test extends App {
case class C(x: Int, y: Int)
import scala.reflect.runtime.universe._
- def reprify[T, Repr](x: T)(implicit generic: Generic.Aux[T, Repr], tag: TypeTag[Repr]) = println(tag)
+ def reprify[T, Repr](x: T)(implicit generic: Generic.Aux[T, Repr], tag: WeakTypeTag[Repr]) = println(tag)
reprify(C(40, 2))
// this is a compilation error at the moment as explained in SI-8104
diff --git a/test/files/neg/t8177a.check b/test/files/neg/t8177a.check
new file mode 100644
index 0000000000..0d01206e0c
--- /dev/null
+++ b/test/files/neg/t8177a.check
@@ -0,0 +1,6 @@
+t8177a.scala:5: error: type mismatch;
+ found : A{type Result = Int}
+ required: A{type Result = String}
+ : A { type Result = String} = x
+ ^
+one error found
diff --git a/test/files/neg/t8177a.scala b/test/files/neg/t8177a.scala
new file mode 100644
index 0000000000..d1e47f8c1e
--- /dev/null
+++ b/test/files/neg/t8177a.scala
@@ -0,0 +1,6 @@
+trait A { type Result }
+
+class PolyTests {
+ def wrong(x: A { type Result = Int })
+ : A { type Result = String} = x
+} \ No newline at end of file
diff --git a/test/files/pos/t0764.scala b/test/files/pos/t0764.scala
deleted file mode 100644
index f1084f5ff8..0000000000
--- a/test/files/pos/t0764.scala
+++ /dev/null
@@ -1,27 +0,0 @@
-class Top[A] {
- type AType = A
-}
-
-trait Node { outer =>
- type T <: Node
- def prepend = new Node { type T = outer.type }
-}
-
-class Main[NextType <: Node](value: Node { type T = NextType })
- extends Top[Node { type T = NextType }] {
-
- new Main[AType]( (value: AType).prepend )
-}
-
-/* this used to be a neg test, even though it should've compiled
-SI-8177 fixed this.
-
-Behold the equivalent program which type checks without the fix for SI-8177.
-(Expand type alias, convert type member to type param;
-note the covariance to encode subtyping on type members.)
-
-class Node[+T <: Node[_]] { def prepend = new Node[this.type] }
-class Main[NextType <: Node[_]](value: Node[NextType]) {
- new Main(value.prepend)
-}
-*/ \ No newline at end of file
diff --git a/test/files/pos/t8177h.scala b/test/files/pos/t8177h.scala
new file mode 100644
index 0000000000..90b8a26ce7
--- /dev/null
+++ b/test/files/pos/t8177h.scala
@@ -0,0 +1,5 @@
+class Module { self =>
+ type settingsType <: Any
+ final type commonModuleType = Module {type settingsType = self.settingsType}
+ def foo(s: self.type): commonModuleType = s
+}
diff --git a/test/files/run/t6992.check b/test/files/run/t6992.check
index 1a0684c995..021f32ec95 100644
--- a/test/files/run/t6992.check
+++ b/test/files/run/t6992.check
@@ -1,3 +1,4 @@
+Test.foo.T
Int
42
42
diff --git a/test/files/run/t6992/Test_2.scala b/test/files/run/t6992/Test_2.scala
index 05282d6f5b..1ed8958d38 100644
--- a/test/files/run/t6992/Test_2.scala
+++ b/test/files/run/t6992/Test_2.scala
@@ -2,7 +2,9 @@ import scala.language.reflectiveCalls
object Test extends App {
val foo = Macros.foo("T")
- println(scala.reflect.runtime.universe.weakTypeOf[foo.T].typeSymbol.typeSignature)
+ val ttpe = scala.reflect.runtime.universe.weakTypeOf[foo.T]
+ println(ttpe)
+ println(ttpe.typeSymbol.typeSignature)
val bar = Macros.bar("test")
println(bar.test)
diff --git a/test/files/run/t8104.check b/test/files/run/t8104.check
index c2593eb199..40523a2868 100644
--- a/test/files/run/t8104.check
+++ b/test/files/run/t8104.check
@@ -1 +1,2 @@
-TypeTag[(Int, Int)]
+WeakTypeTag[<refinement>.this.Repr]
+(Int, Int)
diff --git a/test/files/run/t8104/Test_2.scala b/test/files/run/t8104/Test_2.scala
index 630176f175..55c080a563 100644
--- a/test/files/run/t8104/Test_2.scala
+++ b/test/files/run/t8104/Test_2.scala
@@ -9,7 +9,10 @@ object Test extends App {
case class C(x: Int, y: Int)
import scala.reflect.runtime.universe._
- def reprify[T, Repr](x: T)(implicit generic: Generic.Aux[T, Repr], tag: TypeTag[Repr]) = println(tag)
+ def reprify[T, Repr](x: T)(implicit generic: Generic.Aux[T, Repr], tag: WeakTypeTag[Repr]) = {
+ println(tag)
+ println(tag.tpe.typeSymbol.typeSignature)
+ }
reprify(C(40, 2))
implicitly[Generic.Aux[C, (Int, Int)]]