summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala19
-rw-r--r--src/reflect/scala/reflect/internal/tpe/TypeMaps.scala3
-rw-r--r--test/files/pos/typevar-in-prefix.scala9
-rw-r--r--test/junit/scala/reflect/internal/TypesTest.scala11
4 files changed, 36 insertions, 6 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
index 99ef4ed373..e0b64a7600 100644
--- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
@@ -321,13 +321,20 @@ trait MethodSynthesis {
// starts compiling (instead of failing like it's supposed to) because the typer
// expects to be able to identify escaping locals in typedDefDef, and fails to
// spot that brand of them. In other words it's an artifact of the implementation.
+ //
+ // JZ: ... or we could go back to uniformly using explicit result types in all cases
+ // if we fix `dropExistential`. More details https://github.com/scala/scala-dev/issues/165
val getterTp = derivedSym.tpe_*.finalResultType
- val tpt = getterTp.widen match {
- // Range position errors ensue if we don't duplicate this in some
- // circumstances (at least: concrete vals with existential types.)
- case _: ExistentialType => TypeTree() setOriginal (tree.tpt.duplicate setPos tree.tpt.pos.focus)
- case _ if tree.mods.isDeferred => TypeTree() setOriginal tree.tpt // keep type tree of original abstract field
- case _ => TypeTree(getterTp)
+ // Range position errors ensue if we don't duplicate this in some
+ // circumstances (at least: concrete vals with existential types.)
+ def inferredTpt = TypeTree() setOriginal (tree.tpt.duplicate setPos tree.tpt.pos.focus)
+ val tpt = getterTp match {
+ case _: ExistentialType => inferredTpt
+ case _ => getterTp.widen match {
+ case _: ExistentialType => inferredTpt
+ case _ if tree.mods.isDeferred => TypeTree() setOriginal tree.tpt // keep type tree of original abstract field
+ case _ => TypeTree(getterTp)
+ }
}
tpt setPos tree.tpt.pos.focus
}
diff --git a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
index c3f92f1bce..24f83c0b99 100644
--- a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
+++ b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
@@ -1012,6 +1012,9 @@ private[internal] trait TypeMaps {
case _ =>
tp.normalize match {
case TypeRef(_, sym1, _) if (sym == sym1) => result = true
+ case refined: RefinedType =>
+ mapOver(tp.prefix)
+ mapOver(refined)
case SingleType(_, sym1) if (sym == sym1) => result = true
case _ => mapOver(tp)
}
diff --git a/test/files/pos/typevar-in-prefix.scala b/test/files/pos/typevar-in-prefix.scala
new file mode 100644
index 0000000000..929648b789
--- /dev/null
+++ b/test/files/pos/typevar-in-prefix.scala
@@ -0,0 +1,9 @@
+trait Test1 {
+ abstract class Setting
+ def Bool: Setting
+
+ class C[T <: Setting](val s: T)
+ val setting1 = null.asInstanceOf[_1.s.type forSome { val _1: C[Setting] }]
+ // the derived accessor for this val was not using an inferred type, as was
+ // the intention of the implementation in MethodSynthesis.
+}
diff --git a/test/junit/scala/reflect/internal/TypesTest.scala b/test/junit/scala/reflect/internal/TypesTest.scala
index 05a77cfb47..45a4369396 100644
--- a/test/junit/scala/reflect/internal/TypesTest.scala
+++ b/test/junit/scala/reflect/internal/TypesTest.scala
@@ -58,4 +58,15 @@ class TypesTest {
Assert.fail(xs.mkString("\n"))
}
}
+
+ @Test
+ def testRefinementContains(): Unit = {
+ val refinement = typeOf[{def foo: Int}]
+ assert(refinement.isInstanceOf[RefinedType])
+ assert(refinement.contains(IntClass))
+ val elem0 = refinement.baseTypeSeq(0)
+ assert(elem0.isInstanceOf[RefinementTypeRef])
+ assert(elem0.contains(IntClass))
+ }
+
}