aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/typer/TypeAssigner.scala16
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala11
-rw-r--r--test/dotc/tests.scala1
-rw-r--r--tests/neg/t1569-failedAvoid.scala9
-rw-r--r--tests/pos/avoid.scala10
-rw-r--r--tests/pos/t1569.scala5
-rw-r--r--tests/pos/t1569a.scala12
7 files changed, 48 insertions, 16 deletions
diff --git a/src/dotty/tools/dotc/typer/TypeAssigner.scala b/src/dotty/tools/dotc/typer/TypeAssigner.scala
index ccf67b55b..cb6fefab1 100644
--- a/src/dotty/tools/dotc/typer/TypeAssigner.scala
+++ b/src/dotty/tools/dotc/typer/TypeAssigner.scala
@@ -49,7 +49,21 @@ trait TypeAssigner {
case TypeAlias(ref) =>
apply(ref)
case info: ClassInfo =>
- mapOver(info.instantiatedParents.reduceLeft(ctx.typeComparer.andType(_, _)))
+ val parentType = info.instantiatedParents.reduceLeft(ctx.typeComparer.andType(_, _))
+ def addRefinement(parent: Type, decl: Symbol) = {
+ val inherited = parentType.findMember(decl.name, info.cls.thisType, Private)
+ val inheritedInfo = inherited.atSignature(decl.info .signature).info
+ if (inheritedInfo.exists && decl.info <:< inheritedInfo && !(inheritedInfo <:< decl.info))
+ typr.echo(
+ i"add ref $parent $decl --> ",
+ RefinedType(parent, decl.name, decl.info))
+ else
+ parent
+ }
+ val refinableDecls = info.decls.filterNot(
+ sym => sym.is(TypeParamAccessor | Private) || sym.isConstructor)
+ val fullType = (parentType /: refinableDecls)(addRefinement)
+ mapOver(fullType)
case _ =>
mapOver(tp)
}
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 80eb5965c..1cab2fa46 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -415,17 +415,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
def escapingRefs(block: Block)(implicit ctx: Context): collection.Set[NamedType] = {
var hoisted: Set[Symbol] = Set()
lazy val locals = localSyms(block.stats).toSet
- def isLocal(sym: Symbol): Boolean =
- (locals contains sym) && !isHoistableClass(sym)
- def isHoistableClass(sym: Symbol) =
- sym.isClass && {
- (hoisted contains sym) || {
- hoisted += sym
- !classLeaks(sym.asClass)
- }
- }
def leakingTypes(tp: Type): collection.Set[NamedType] =
- tp namedPartsWith (tp => isLocal(tp.symbol))
+ tp namedPartsWith (tp => locals.contains(tp.symbol))
def typeLeaks(tp: Type): Boolean = leakingTypes(tp).nonEmpty
def classLeaks(sym: ClassSymbol): Boolean =
(ctx.owner is Method) || // can't hoist classes out of method bodies
diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala
index 614dc9527..f93f36ced 100644
--- a/test/dotc/tests.scala
+++ b/test/dotc/tests.scala
@@ -99,6 +99,7 @@ class tests extends CompilerTest {
@Test def neg_variances = compileFile(negDir, "variances", xerrors = 2)
@Test def neg_badAuxConstr = compileFile(negDir, "badAuxConstr", xerrors = 2)
@Test def neg_typetest = compileFile(negDir, "typetest", xerrors = 1)
+ @Test def neg_t1569_failedAvoid = compileFile(negDir, "t1569-failedAvoid", xerrors = 1)
@Test def dotc = compileDir(dotcDir + "tools/dotc", twice)(allowDeepSubtypes)
@Test def dotc_ast = compileDir(dotcDir + "tools/dotc/ast", twice)
@Test def dotc_config = compileDir(dotcDir + "tools/dotc/config", twice)
diff --git a/tests/neg/t1569-failedAvoid.scala b/tests/neg/t1569-failedAvoid.scala
new file mode 100644
index 000000000..9d0fbb37a
--- /dev/null
+++ b/tests/neg/t1569-failedAvoid.scala
@@ -0,0 +1,9 @@
+// This was t1569.scala.
+// It fails in dotty because the expected type of the anonymous function in the last line
+// is fully determined (C). So that type is taken as the type of the anonymous function.
+// See pos/t1569a.scala for related examples that work.
+object Bug {
+ class C { type T }
+ def foo(x: Int)(y: C)(z: y.T): Unit = {}
+ foo(3)(new C { type T = String })("hello")
+}
diff --git a/tests/pos/avoid.scala b/tests/pos/avoid.scala
new file mode 100644
index 000000000..51471feaa
--- /dev/null
+++ b/tests/pos/avoid.scala
@@ -0,0 +1,10 @@
+abstract class C {
+ def y: Any
+}
+
+object test {
+ val x = new C{
+ def y: String = "abc"
+ }
+ val z: String = x.y
+}
diff --git a/tests/pos/t1569.scala b/tests/pos/t1569.scala
deleted file mode 100644
index a7200a6d1..000000000
--- a/tests/pos/t1569.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-object Bug {
- class C { type T }
- def foo(x: Int)(y: C)(z: y.T): Unit = {}
- foo(3)(new C { type T = String })("hello")
-}
diff --git a/tests/pos/t1569a.scala b/tests/pos/t1569a.scala
new file mode 100644
index 000000000..6cc3619a4
--- /dev/null
+++ b/tests/pos/t1569a.scala
@@ -0,0 +1,12 @@
+object Bug {
+ class C[T] { type TT = T }
+ def foo[U](x: Int)(y: C[U])(z: y.TT): Unit = {}
+ foo(3)(new C[String])("hello")
+}
+
+object Bug2 {
+ class C { type T }
+ class D extends C { type T = String }
+ def foo(x: Int)(y: C)(z: y.T): Unit = {}
+ foo(3)(new D)("hello")
+}