diff options
-rw-r--r-- | src/dotty/tools/dotc/typer/TypeAssigner.scala | 16 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 11 | ||||
-rw-r--r-- | test/dotc/tests.scala | 1 | ||||
-rw-r--r-- | tests/neg/t1569-failedAvoid.scala | 9 | ||||
-rw-r--r-- | tests/pos/avoid.scala | 10 | ||||
-rw-r--r-- | tests/pos/t1569.scala | 5 | ||||
-rw-r--r-- | tests/pos/t1569a.scala | 12 |
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") +} |