Skip to content

Commit d079c02

Browse files
oderskyDarkDimius
authored andcommitted
Flag self names that conflict with parameters or members
A self name may no longer have the same name as a parameterless class member (or param accessor). The restriction makes sense because otherwise scoping is confusing. It's needed because otherwise we get TermRefs that have the same name and prefix but denote different things. Moved some code which exercises this from pos/typers to neg/typers
1 parent 09a4bc5 commit d079c02

File tree

4 files changed

+92
-67
lines changed

4 files changed

+92
-67
lines changed

src/dotty/tools/dotc/typer/Checking.scala

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,13 +102,14 @@ trait Checking {
102102
tp
103103
}
104104

105-
/** Check that class does not define */
105+
/** Check that class does not define same symbol twice */
106106
def checkNoDoubleDefs(cls: Symbol)(implicit ctx: Context): Unit = {
107107
val seen = new mutable.HashMap[Name, List[Symbol]] {
108108
override def default(key: Name) = Nil
109109
}
110110
typr.println(i"check no double defs $cls")
111-
for (decl <- cls.info.decls) {
111+
112+
def checkDecl(decl: Symbol): Unit = {
112113
for (other <- seen(decl.name)) {
113114
typr.println(i"conflict? $decl $other")
114115
if (decl.signature matches other.signature) {
@@ -129,6 +130,12 @@ trait Checking {
129130
}
130131
seen(decl.name) = decl :: seen(decl.name)
131132
}
133+
134+
cls.info.decls.foreach(checkDecl)
135+
cls.info match {
136+
case ClassInfo(_, _, _, _, selfSym: Symbol) => checkDecl(selfSym)
137+
case _ =>
138+
}
132139
}
133140

134141
def checkInstantiatable(cls: ClassSymbol, pos: Position): Unit = {

src/dotty/tools/dotc/typer/Namer.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ class Namer { typer: Typer =>
209209
ctx.error(s"${preExisting.showLocated} is compiled twice, runid = ${ctx.runId}", tree.pos)
210210
}
211211
else if ((!ctx.owner.isClass || name.isTypeName) && preExisting.exists) {
212-
ctx.error(d"$name is already defined as $preExisting")
212+
ctx.error(i"$name is already defined as $preExisting", tree.pos)
213213
}
214214
}
215215

tests/neg/typers.scala

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,56 @@
11
object typers {
2-
2+
3+
class A(x: Int) {
4+
val x: String = "a" // error: double def
5+
6+
{ val y: String = ""
7+
val y: Int = 0 // error: double def
8+
y
9+
}
10+
}
11+
12+
class B { self => // error: double def
13+
def self: Int = 0
14+
def self(x: Int): Int = x
15+
}
16+
317
class C {
418
val x: Int
5-
val x: String
19+
val x: String // error: double def
620
val y: Int
7-
def y: String
21+
def y: String // error: double def
822
val z: Int
9-
def z(): String
10-
11-
def f(x: Any) = ()
23+
def z(): String // error: double def
24+
25+
def f(x: Any) = () // error: double def
1226
def f(x: AnyRef): AnyRef
13-
27+
1428
def g(x: Object): Unit
15-
def g[T](x: T): T = x
29+
def g[T](x: T): T = x // error: double def
1630
}
17-
18-
31+
32+
33+
34+
1935
object returns {
20-
21-
def foo(x: Int) = {
36+
37+
def foo(x: Int) = { // error: has return; needs result type
2238
return 3
2339
}
24-
25-
return 4
40+
41+
return 4 // error: return outside method definition
2642
}
27-
43+
2844
object cyclic {
29-
def factorial(acc: Int, n: Int) =
45+
def factorial(acc: Int, n: Int) =
3046
if (n == 0) acc
31-
else factorial(acc * n, n - 1)
32-
33-
def foo(x: Int) = x
47+
else factorial(acc * n, n - 1) // error: cyclic reference
48+
49+
def foo(x: Int) = x // error: cyclic reference
3450
def foo() = foo(1)
35-
51+
3652
}
37-
53+
3854
object tries {
3955

4056
val x = try {
@@ -46,6 +62,6 @@ object typers {
4662
}
4763

4864
class Refinements {
49-
val y: C { val x: T; type T }
65+
val y: C { val x: T; type T } // error: illegal forward reference in refinement
5066
}
51-
}
67+
}

tests/pos/typers.scala

Lines changed: 43 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,61 @@
1-
package test
1+
package test
22

33
import annotation.{tailrec, switch}
44
import collection.mutable._
55

66
object typers {
7-
7+
88
val names = List("a", "b", "c")
99
val ints = List(1, 2, 3)
10-
10+
1111
object Inference {
1212

1313
for ((name, n) <- (names, ints).zipped)
1414
println(name.length + n)
15-
15+
1616
def double(x: Char): String = s"$x$x"
17-
17+
1818
"abc" flatMap double
19-
19+
2020
}
2121
object Eta {
22-
22+
2323
def fun(x: Int): Int = x + 1
2424
val foo = fun(_)
2525
}
26-
26+
2727
case class DefaultParams(init: String => String = identity)
2828
object DefaultParams {
2929
def foo(x: String => String = identity) = x("abc")
30-
30+
3131
foo()
3232
}
33-
33+
3434
class List[+T] {
3535
def :: (x: T) = new :: (x, this)
36-
36+
3737
def len: Int = this match {
3838
case x :: xs1 => 1 + xs1.len
3939
case Nil => 0
4040
}
4141
}
42-
42+
4343
object Nil extends List[Nothing]
44-
44+
4545
case class :: [+T] (hd: T, tl: List[T]) extends List[T]
46-
46+
4747
def len[U](xs: List[U]): Int = xs match {
4848
case x :: xs1 => 1 + len(xs1)
4949
case Nil => 0
5050
}
51-
51+
5252
object returns {
53-
53+
5454
def foo(x: Int): Int = {
5555
return 3
5656
}
5757
}
58-
58+
5959
object tries {
6060

6161
val x = try {
@@ -70,69 +70,71 @@ object typers {
7070
val y = try 2 catch Predef.identity
7171

7272
val z = try 3 finally "abc"
73-
73+
7474
println("abc".toString)
7575

7676
}
7777

7878
class C {
79-
79+
8080
@tailrec def factorial(acc: Int, n: Int): Int = (n: @switch) match {
8181
case 0 => acc
8282
case _ => factorial(acc * n, n - 1)
8383
}
84-
84+
8585
println(factorial(1, 10))
86-
87-
86+
87+
8888
}
89-
89+
9090
class Refinements {
9191
val y: C { type T; val key: T; def process(x: T): Int }
9292
}
93-
93+
9494
object Accessibility {
95-
95+
9696
class A {
9797
val x: String = "abc"
9898
}
99-
99+
100100
class B extends A {
101101
private def x: Int = 1
102102
}
103-
103+
104104
val b: B = new B
105105
val y = b.x
106106
val z: String = y
107-
107+
108108
}
109-
109+
110110
object Self {
111-
112-
class A(self: Int) { self =>
113-
111+
112+
class A(self1: Int) { self =>
113+
114+
def self1(x: Int) = x
115+
114116
class B {
115117
val b = self
116118
val c: A = b
117119
}
118-
120+
119121
val a = self
120122
val c: A = a
121123
}
122-
123-
124+
125+
124126
}
125-
127+
126128
object Arrays {
127-
129+
128130
val arr = List("a", "b", "c").toArray
129131
val i = 2
130132
arr(i).charAt(0)
131-
133+
132134
val x = new ArrayBuffer[String] // testing overloaded polymorphic constructors
133135

134136
val entries = Array("abc", "def")
135-
137+
136138
for ((x, i) <- entries.zipWithIndex)
137139
println(x)
138140
}
@@ -145,6 +147,6 @@ object typers {
145147
}
146148
val yy: String = y
147149
}
148-
149150

150-
}
151+
152+
}

0 commit comments

Comments
 (0)