aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorodersky <odersky@gmail.com>2015-01-31 19:32:17 +0100
committerodersky <odersky@gmail.com>2015-01-31 19:32:17 +0100
commit698935a661122ea2ba983cdab29805f15f8a153c (patch)
treeff13a07330ff5332eda3a1b9ff3118eb491c0d2c
parenta822fc15235d9cc91302bd82d180830eff357ae2 (diff)
parent57b616c1a7adc78dd46cb3ae5545e312c11e69be (diff)
downloaddotty-698935a661122ea2ba983cdab29805f15f8a153c.tar.gz
dotty-698935a661122ea2ba983cdab29805f15f8a153c.tar.bz2
dotty-698935a661122ea2ba983cdab29805f15f8a153c.zip
Merge pull request #338 from dotty-staging/fix/t3152-findMember
Fix/t3152 find member
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala46
-rw-r--r--src/dotty/tools/dotc/core/Types.scala12
-rw-r--r--src/dotty/tools/dotc/typer/ErrorReporting.scala2
-rw-r--r--tests/pos/t3020.scala (renamed from tests/pending/pos/t3020.scala)0
-rw-r--r--tests/pos/t3037.scala (renamed from tests/pending/pos/t3037.scala)0
-rw-r--r--tests/pos/t304.scala (renamed from tests/pending/pos/t304.scala)0
-rw-r--r--tests/pos/t3106.scala (renamed from tests/pending/pos/t3106.scala)0
-rw-r--r--tests/pos/t3137.scala (renamed from tests/pending/pos/t3137.scala)0
-rw-r--r--tests/pos/t3152.scala (renamed from tests/pending/pos/t3152.scala)0
-rwxr-xr-xtests/pos/t3174.scala (renamed from tests/pending/pos/t3174.scala)0
-rw-r--r--tests/pos/t3177.scala (renamed from tests/pending/pos/t3177.scala)0
-rw-r--r--tests/pos/t8023.scala9
-rw-r--r--tests/pos/t9004.scala29
13 files changed, 79 insertions, 19 deletions
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index 9826a23ea..fd4ef0bc7 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -140,21 +140,14 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi
private def firstTry(tp1: Type, tp2: Type): Boolean = tp2 match {
case tp2: NamedType =>
- def compareHKOrAlias(info1: Type) =
- tp2.name == tpnme.Apply && {
- val lambda2 = tp2.prefix.LambdaClass(forcing = true)
- lambda2.exists && !tp1.isLambda &&
- tp1.testLifted(lambda2.typeParams, isSubType(_, tp2.prefix))
- } || {
- tp2.info match {
- case info2: TypeAlias => isSubType(tp1, info2.alias)
- case _ => info1 match {
- case info1: TypeAlias => isSubType(info1.alias, tp2)
- case NoType => secondTry(tp1, tp2)
- case _ => thirdTryNamed(tp1, tp2)
- }
- }
+ def compareAlias(info1: Type) = tp2.info match {
+ case info2: TypeAlias => isSubType(tp1, info2.alias)
+ case _ => info1 match {
+ case info1: TypeAlias => isSubType(info1.alias, tp2)
+ case NoType => secondTry(tp1, tp2)
+ case _ => thirdTryNamed(tp1, tp2)
}
+ }
def compareNamed = {
implicit val ctx: Context = this.ctx // Dotty deviation: implicits need explicit type
tp1 match {
@@ -183,9 +176,12 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi
!tp1.isInstanceOf[WithFixedSym] &&
!tp2.isInstanceOf[WithFixedSym]
) ||
- compareHKOrAlias(tp1.info)
+ compareHK(tp1, tp2, inOrder = true) ||
+ compareHK(tp2, tp1, inOrder = false) ||
+ compareAlias(tp1.info)
case _ =>
- compareHKOrAlias(NoType)
+ compareHK(tp2, tp1, inOrder = false) ||
+ compareAlias(NoType)
}
}
compareNamed
@@ -243,7 +239,9 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi
case tp1: NamedType =>
tp1.info match {
case info1: TypeAlias => isSubType(info1.alias, tp2)
- case _ => thirdTry(tp1, tp2)
+ case _ => compareHK(tp1, tp2, inOrder = true) || thirdTry(tp1, tp2)
+ // Note: If we change the order here, doing compareHK first and following aliases second,
+ // we get a -Ycheck error when compiling dotc/transform. Need to investigate.
}
case tp1: PolyParam =>
def flagNothingBound = {
@@ -460,6 +458,18 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi
false
}
+ /** If `projection` is of the form T # Apply where `T` is an instance of a Lambda class,
+ * and `other` is not a type lambda projection, then convert `other` to a type lambda `U`, and
+ * continue with `T <:< U` if `inOrder` is true and `U <:< T` otherwise.
+ */
+ def compareHK(projection: NamedType, other: Type, inOrder: Boolean) =
+ projection.name == tpnme.Apply && {
+ val lambda = projection.prefix.LambdaClass(forcing = true)
+ lambda.exists && !other.isLambda &&
+ other.testLifted(lambda.typeParams,
+ if (inOrder) isSubType(projection.prefix, _) else isSubType(_, projection.prefix))
+ }
+
/** Returns true iff either `tp11 <:< tp21` or `tp12 <:< tp22`, trying at the same time
* to keep the constraint as wide as possible. Specifically, if
*
@@ -524,7 +534,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi
case mbr: SingleDenotation => qualifies(mbr)
case _ => mbr hasAltWith qualifies
}
- /*>|>*/ ctx.traceIndented(i"hasMatchingMember($tp1 . $name :? ${tp2.refinedInfo}) ${tp1.member(name).info.show} $rinfo2", subtyping) /*<|<*/ {
+ /*>|>*/ ctx.traceIndented(i"hasMatchingMember($base . $name :? ${tp2.refinedInfo}) ${base.member(name).info.show} $rinfo2", subtyping) /*<|<*/ {
memberMatches(base member name) ||
tp1.isInstanceOf[SingletonType] &&
{ // special case for situations like:
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index a36dda7e3..18f854f12 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -419,6 +419,8 @@ object Types {
if mt.paramTypes.isEmpty && (tp.symbol is Stable) => mt.resultType
case tp1 => tp1
})
+ case tp: PolyParam =>
+ goParam(tp)
case tp: TypeProxy =>
go(tp.underlying)
case tp: ClassInfo =>
@@ -460,6 +462,16 @@ object Types {
// loadClassWithPrivateInnerAndSubSelf in ShowClassTests
go(tp.cls.typeRef) orElse d
}
+ def goParam(tp: PolyParam) = {
+ val next = tp.underlying
+ ctx.typerState.constraint.entry(tp) match {
+ case bounds: TypeBounds if bounds ne next =>
+ ctx.typerState.ephemeral = true
+ go(bounds.hi)
+ case _ =>
+ go(next)
+ }
+ }
def goAnd(l: Type, r: Type) = go(l) & (go(r), pre)
def goOr(l: Type, r: Type) = go(l) | (go(r), pre)
go(this)
diff --git a/src/dotty/tools/dotc/typer/ErrorReporting.scala b/src/dotty/tools/dotc/typer/ErrorReporting.scala
index 8e8cf58f9..2ed720f83 100644
--- a/src/dotty/tools/dotc/typer/ErrorReporting.scala
+++ b/src/dotty/tools/dotc/typer/ErrorReporting.scala
@@ -96,7 +96,7 @@ object ErrorReporting {
def patternConstrStr(tree: Tree): String = ???
def typeMismatch(tree: Tree, pt: Type, implicitFailure: SearchFailure = NoImplicitMatches): Tree = {
- errorTree(tree, typeMismatchStr(tree.tpe, pt) + implicitFailure.postscript)
+ errorTree(tree, typeMismatchStr(normalize(tree.tpe, pt), pt) + implicitFailure.postscript)
}
/** A subtype log explaining why `found` does not conform to `expected` */
diff --git a/tests/pending/pos/t3020.scala b/tests/pos/t3020.scala
index 016563e27..016563e27 100644
--- a/tests/pending/pos/t3020.scala
+++ b/tests/pos/t3020.scala
diff --git a/tests/pending/pos/t3037.scala b/tests/pos/t3037.scala
index b71ffe041..b71ffe041 100644
--- a/tests/pending/pos/t3037.scala
+++ b/tests/pos/t3037.scala
diff --git a/tests/pending/pos/t304.scala b/tests/pos/t304.scala
index 76da44157..76da44157 100644
--- a/tests/pending/pos/t304.scala
+++ b/tests/pos/t304.scala
diff --git a/tests/pending/pos/t3106.scala b/tests/pos/t3106.scala
index a9591d0aa..a9591d0aa 100644
--- a/tests/pending/pos/t3106.scala
+++ b/tests/pos/t3106.scala
diff --git a/tests/pending/pos/t3137.scala b/tests/pos/t3137.scala
index cb7317af0..cb7317af0 100644
--- a/tests/pending/pos/t3137.scala
+++ b/tests/pos/t3137.scala
diff --git a/tests/pending/pos/t3152.scala b/tests/pos/t3152.scala
index 3d1dcbd6f..3d1dcbd6f 100644
--- a/tests/pending/pos/t3152.scala
+++ b/tests/pos/t3152.scala
diff --git a/tests/pending/pos/t3174.scala b/tests/pos/t3174.scala
index 8d9b2578d..8d9b2578d 100755
--- a/tests/pending/pos/t3174.scala
+++ b/tests/pos/t3174.scala
diff --git a/tests/pending/pos/t3177.scala b/tests/pos/t3177.scala
index 12dfce6ee..12dfce6ee 100644
--- a/tests/pending/pos/t3177.scala
+++ b/tests/pos/t3177.scala
diff --git a/tests/pos/t8023.scala b/tests/pos/t8023.scala
new file mode 100644
index 000000000..66d478abd
--- /dev/null
+++ b/tests/pos/t8023.scala
@@ -0,0 +1,9 @@
+class C[K]
+class D[K]
+
+object Test3 {
+ def foo = (null: Any) match {
+ case a: C[k] => new C[k]() // this one worked before as the info of `A` was complete
+ // ()
+ }
+}
diff --git a/tests/pos/t9004.scala b/tests/pos/t9004.scala
new file mode 100644
index 000000000..d591bc852
--- /dev/null
+++ b/tests/pos/t9004.scala
@@ -0,0 +1,29 @@
+object Main {
+ trait AA[RR] { type R = RR; def r: R }
+
+ def test1(a: AA[_]) = {
+ val f = () => a.r
+ // The tree a.r is given the type `a.R` which normalizes
+ // to B', where B' is a distinct symbol ("captured existential skolem")
+ // to substitute for the reference to an existential skolem of B.
+ //
+ // inference of the result type of the function computes the
+ // packed type of tree `a.r` to make sure that terms and types
+ // local to the body of the function don't leak into its result
+ // type. The captured existential skolem is considered to be local
+ // so it is abstracted to its upper bound, Any.
+ //
+ // However, the packedType transformation need not have even considered
+ // B', as it is clear that the type `a.R` is not local to the function
+ // body!
+ f: (() => a.R)
+
+ // The workaround is to annotate the function type, rather than
+ // relying in inference.
+ val g: (() => a.R) = () => a.r
+ val g2 = () => a.r
+
+ ()
+ }
+ // typer debug trace: http://rawgit.com/retronym/d5aeaf8e0a4a2e6eef4b/raw/out.html
+}