diff options
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)) + } + } |