aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2015-12-10 11:15:21 +0100
committerMartin Odersky <odersky@gmail.com>2015-12-14 14:30:09 +0100
commitf829cf8ba742b149a10250710c46b5a1c49aa7cc (patch)
tree65b55ddd4abeaf6e6e95b9b730d31be48ea23f25
parent2a3f78673afe581fffec7f88039ba27a71ed2fe2 (diff)
downloaddotty-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.scala23
-rw-r--r--test/dotc/tests.scala2
-rw-r--r--tests/neg/overrides.scala22
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
}
}