diff options
author | Martin Odersky <odersky@gmail.com> | 2015-12-10 11:15:21 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2015-12-14 14:30:09 +0100 |
commit | f829cf8ba742b149a10250710c46b5a1c49aa7cc (patch) | |
tree | 65b55ddd4abeaf6e6e95b9b730d31be48ea23f25 | |
parent | 2a3f78673afe581fffec7f88039ba27a71ed2fe2 (diff) | |
download | dotty-f829cf8ba742b149a10250710c46b5a1c49aa7cc.tar.gz dotty-f829cf8ba742b149a10250710c46b5a1c49aa7cc.tar.bz2 dotty-f829cf8ba742b149a10250710c46b5a1c49aa7cc.zip |
Make some types of definitions symbolic
This is needed to ensure that the type of a definition node
(ValDef, TypeDef, or DefDef) always refers to the symbol of
that definition.
Caused a spurious error in selfReq to go away (so error count was
updated).
-rw-r--r-- | src/dotty/tools/dotc/typer/TypeAssigner.scala | 23 | ||||
-rw-r--r-- | test/dotc/tests.scala | 2 | ||||
-rw-r--r-- | tests/neg/overrides.scala | 22 |
3 files changed, 32 insertions, 15 deletions
diff --git a/src/dotty/tools/dotc/typer/TypeAssigner.scala b/src/dotty/tools/dotc/typer/TypeAssigner.scala index 30d6baf8a..69cea30dd 100644 --- a/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -392,13 +392,30 @@ trait TypeAssigner { tree.withType(proto) def assignType(tree: untpd.ValDef, sym: Symbol)(implicit ctx: Context) = - tree.withType(if (sym.exists) sym.valRef else NoType) + tree.withType(if (sym.exists) assertExists(symbolicIfNeeded(sym).orElse(sym.valRef)) else NoType) def assignType(tree: untpd.DefDef, sym: Symbol)(implicit ctx: Context) = - tree.withType(sym.termRefWithSig) + tree.withType(symbolicIfNeeded(sym).orElse(sym.termRefWithSig)) def assignType(tree: untpd.TypeDef, sym: Symbol)(implicit ctx: Context) = - tree.withType(sym.typeRef) + tree.withType(symbolicIfNeeded(sym).orElse(sym.typeRef)) + + private def symbolicIfNeeded(sym: Symbol)(implicit ctx: Context) = { + val owner = sym.owner + owner.infoOrCompleter match { + case info: ClassInfo if !owner.is(Package) && info.givenSelfType.exists => + // In that case a simple typeRef/termWithWithSig could return a member of + // the self type, not the symbol itself. To avoid this, we make the reference + // symbolic. In general it seems to be faster to keep the non-symblic + // reference, since there is less pressure on the uniqueness tables that way + // and less work to update all the different references. That's why symbolic references + // are only used if necessary. + NamedType.withFixedSym(owner.thisType, sym) + case _ => NoType + } + } + + def assertExists(tp: Type) = { assert(tp != NoType); tp } def assignType(tree: untpd.Import, sym: Symbol)(implicit ctx: Context) = tree.withType(sym.nonMemberTermRef) diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala index 9662d09d6..dc7f3179d 100644 --- a/test/dotc/tests.scala +++ b/test/dotc/tests.scala @@ -162,7 +162,7 @@ class tests extends CompilerTest { @Test def neg_instantiateAbstract = compileFile(negDir, "instantiateAbstract", xerrors = 8) @Test def neg_partialApplications = compileFile(negDir, "partialApplications", xerrors = 3) @Test def neg_selfInheritance = compileFile(negDir, "selfInheritance", xerrors = 6) - @Test def neg_selfreq = compileFile(negDir, "selfreq", xerrors = 3) + @Test def neg_selfreq = compileFile(negDir, "selfreq", xerrors = 2) @Test def neg_singletons = compileFile(negDir, "singletons", xerrors = 8) @Test def neg_shadowedImplicits = compileFile(negDir, "arrayclone-new", xerrors = 2) @Test def neg_traitParamsTyper = compileFile(negDir, "traitParamsTyper", xerrors = 5) diff --git a/tests/neg/overrides.scala b/tests/neg/overrides.scala index 9fe06d930..727759e3c 100644 --- a/tests/neg/overrides.scala +++ b/tests/neg/overrides.scala @@ -8,7 +8,7 @@ } trait FooB extends FooA { type A <: Ax; - trait Ax extends super.Ax { def xxx : Int; } + trait Ax extends super.Ax { def xxx : Int; } // error: classes cannot be overridden abstract class InnerB extends InnerA { // type B <: A; val a : A = doB; @@ -31,7 +31,7 @@ package p2 { // all being in the same package compiles fine } abstract class T3 extends T2 { - class A { + class A { // error: classes cannot be overridden bug() } } @@ -45,7 +45,7 @@ class A[T] { class B extends A[Int] { - def f(x: Int)(y: Int) = y + def f(x: Int)(y: Int) = y // error: needs `override' modifier f(2)() @@ -55,7 +55,7 @@ class X { def f: A[Int] = ??? } class Y extends X { - def f: A[Int] = ??? + def f: A[Int] = ??? // error: needs `override' modifier } @@ -66,18 +66,18 @@ class X1 { def f(): A1 = ??? } class Y1 extends X1 { - override def f(): B1 = ??? + override def f(): B1 = ??? // error: has incompatible type } class X2 { type T = A1 } class Y2 extends X2 { - type T = B1 + type T = B1 // error: needs `override' modifier } class X3 { - override type T = A1 + override type T = A1 // error: overrides nothing } package p3 { @@ -97,14 +97,14 @@ trait TOverrider { this: TCommon => override def f = "in TOverrider" // The overridden self-type member... } -class C2 extends C1 with TOverrider // ... fails to override, here. +class C2 extends C1 with TOverrider // ... fails to override, here. // error: accidental override } package p4 { abstract class C[T] { def head: T } - case class D[T](head: Int) extends C[T] + case class D[T](head: Int) extends C[T] // error: has incompatible type } @@ -114,10 +114,10 @@ class A { } class B extends A { - override val m: Int = 42 + override val m: Int = 42 // error: has incompatible type } class C extends A { - override def m: Int = 42 + override def m: Int = 42 // error: has incompatible type } } |