Skip to content

Commit f675ad9

Browse files
committed
Domain checking for named type parameters
Now verifies that the named type parameters of an overriding type or class are the same as the named type parameters of an overridden type.
1 parent d897678 commit f675ad9

File tree

3 files changed

+18
-10
lines changed

3 files changed

+18
-10
lines changed

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,8 @@ object RefChecks {
246246
isDefaultGetter(member.name) || // default getters are not checked for compatibility
247247
memberTp.overrides(otherTp)
248248

249+
def domain(sym: Symbol): Set[Name] = sym.info.namedTypeParams.map(_.name)
250+
249251
//Console.println(infoString(member) + " overrides " + infoString(other) + " in " + clazz);//DEBUG
250252

251253
// return if we already checked this combination elsewhere
@@ -342,6 +344,9 @@ object RefChecks {
342344
overrideError("cannot be used here - only term macros can override term macros")
343345
} else if (!compatibleTypes) {
344346
overrideError("has incompatible type" + err.whyNoMatchStr(memberTp, otherTp))
347+
} else if (member.isType && domain(member) != domain(other)) {
348+
overrideError("has different named type parameters: "+
349+
i"[${domain(member).toList}%, %] instead of [${domain(other).toList}%, %]")
345350
} else {
346351
checkOverrideDeprecated()
347352
}

tests/neg/named-params.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,6 @@ object Test {
3232
val z5 = d2[Elem = Int][Value = String](1) //error // error
3333

3434
}
35+
36+
37+

tests/pos/CollectionStrawMan3.scala

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -114,13 +114,13 @@ object CollectionStrawMan1 {
114114
/* --------- Concrete collection types ------------------------------- */
115115

116116
/** Concrete collection type: List */
117-
sealed trait List[+A] extends Seq[A] with FromIterator[List] {
117+
sealed trait List[type +Elem] extends Seq[Elem] with FromIterator[List] {
118118
def isEmpty: Boolean
119-
def head: A
120-
def tail: List[A]
121-
def iterator = new ListIterator[A](this)
119+
def head: Elem
120+
def tail: List[Elem]
121+
def iterator = new ListIterator[Elem](this)
122122
def fromIterator[B](it: Iterator[B]): List[B] = List.fromIterator(it)
123-
def apply(i: Int): A = {
123+
def apply(i: Int): Elem = {
124124
require(!isEmpty)
125125
if (i == 0) head else tail.apply(i - 1)
126126
}
@@ -155,17 +155,17 @@ object CollectionStrawMan1 {
155155
}
156156

157157
/** Concrete collection type: ArrayBuffer */
158-
class ArrayBuffer[A] private (initElems: Array[AnyRef], initLength: Int) extends Seq[A] with FromIterator[ArrayBuffer] {
158+
class ArrayBuffer[type Elem] private (initElems: Array[AnyRef], initLength: Int) extends Seq[Elem] with FromIterator[ArrayBuffer] {
159159
def this() = this(new Array[AnyRef](16), 0)
160160
private var elems: Array[AnyRef] = initElems
161161
private var start = 0
162162
private var limit = initLength
163-
def apply(i: Int) = elems(start + i).asInstanceOf[A]
163+
def apply(i: Int) = elems(start + i).asInstanceOf[Elem]
164164
def length = limit - start
165-
def iterator = new ArrayBufferIterator[A](elems, start, length)
165+
def iterator = new ArrayBufferIterator[Elem](elems, start, length)
166166
def fromIterator[B](it: Iterator[B]): ArrayBuffer[B] =
167167
ArrayBuffer.fromIterator(it)
168-
def +=(elem: A): this.type = {
168+
def +=(elem: Elem): this.type = {
169169
if (limit == elems.length) {
170170
if (start > 0) {
171171
Array.copy(elems, start, elems, 0, length)
@@ -213,7 +213,7 @@ object CollectionStrawMan1 {
213213
}
214214

215215
/** Concrete collection type: View */
216-
class View[+A](it: => Iterator[A]) extends CanIterate[A] {
216+
class View[type +Elem](it: => Iterator[Elem]) extends CanIterate[Elem] {
217217
def iterator = it
218218
}
219219

0 commit comments

Comments
 (0)