Skip to content

Commit 6afb888

Browse files
committed
Repeated params must correspond in override
Refchecks runs after elimRepeated and did not error on an attempt to override RepeatedParam with Seq. Also show RepeatedParam in error message.
1 parent 4f8be7d commit 6afb888

File tree

4 files changed

+52
-10
lines changed

4 files changed

+52
-10
lines changed

compiler/src/dotty/tools/dotc/core/Decorators.scala

+16
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,22 @@ object Decorators {
222222
def nestedExists(p: T => Boolean): Boolean = xss match
223223
case xs :: xss1 => xs.exists(p) || xss1.nestedExists(p)
224224
case nil => false
225+
def nestedZipExists(yss: List[List[U]])(f: (T, U) => Boolean): Boolean =
226+
@tailrec def zipExists(p1: List[T], p2: List[U]): Boolean =
227+
p1 match
228+
case h :: t =>
229+
p2 match
230+
case h2 :: t2 => f(h, h2) || zipExists(t, t2)
231+
case _ => false
232+
case _ => false
233+
@tailrec def loop(ps1: List[List[T]], ps2: List[List[U]]): Boolean =
234+
ps1 match
235+
case h :: t =>
236+
ps2 match
237+
case h2 :: t2 => zipExists(h, h2) || loop(t, t2)
238+
case _ => false
239+
case _ => false
240+
loop(xss, yss)
225241
end extension
226242

227243
extension (text: Text)

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

+14-8
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ object RefChecks {
253253
def infoString(sym: Symbol) = infoString0(sym, sym.owner != clazz)
254254
def infoStringWithLocation(sym: Symbol) = infoString0(sym, true)
255255

256-
def infoString0(sym: Symbol, showLocation: Boolean) = {
256+
def infoString0(sym: Symbol, showLocation: Boolean) = atPhase(typerPhase) {
257257
val sym1 = sym.underlyingSymbol
258258
def info = self.memberInfo(sym1)
259259
val infoStr =
@@ -265,6 +265,11 @@ object RefChecks {
265265
i"${if (showLocation) sym1.showLocated else sym1}$infoStr"
266266
}
267267

268+
def incompatibleRepeatedParam(member: Symbol, other: Symbol): Boolean =
269+
member.is(Method, butNot = JavaDefined) && other.is(Method, butNot = JavaDefined) && atPhase(typerPhase) {
270+
member.info.paramInfoss.nestedZipExists(other.info.paramInfoss)(_.isRepeatedParam != _.isRepeatedParam)
271+
}
272+
268273
/* Check that all conditions for overriding `other` by `member`
269274
* of class `clazz` are met.
270275
*/
@@ -350,10 +355,8 @@ object RefChecks {
350355
//Console.println(infoString(member) + " overrides " + infoString(other) + " in " + clazz);//DEBUG
351356

352357
/* Is the intersection between given two lists of overridden symbols empty? */
353-
def intersectionIsEmpty(syms1: Iterator[Symbol], syms2: Iterator[Symbol]) = {
354-
val set2 = syms2.toSet
355-
!(syms1 exists (set2 contains _))
356-
}
358+
def intersectionIsEmpty(syms1: Iterator[Symbol], syms2: Iterator[Symbol]) =
359+
!syms1.exists(syms2.toSet.contains)
357360

358361
// o: public | protected | package-protected (aka java's default access)
359362
// ^-may be overridden by member with access privileges-v
@@ -414,6 +417,8 @@ object RefChecks {
414417
+ "\n(Note: this can be resolved by declaring an override in " + clazz + ".)")
415418
else if member.is(Exported) then
416419
overrideError("cannot override since it comes from an export")
420+
else if incompatibleRepeatedParam(member, other) then
421+
overrideError("cannot override because erased signatures conflict in repeated parameter")
417422
else
418423
overrideError("needs `override` modifier")
419424
else if (other.is(AbsOverride) && other.isIncompleteIn(clazz) && !member.is(AbsOverride))
@@ -839,6 +844,7 @@ object RefChecks {
839844
def isSignatureMatch(sym: Symbol) = sym.isType || {
840845
val self = clazz.thisType
841846
sym.asSeenFrom(self).matches(member.asSeenFrom(self))
847+
&& !incompatibleRepeatedParam(sym, member)
842848
}
843849

844850
/* The rules for accessing members which have an access boundary are more
@@ -871,8 +877,8 @@ object RefChecks {
871877
}
872878

873879
// 4. Check that every defined member with an `override` modifier overrides some other member.
874-
for (member <- clazz.info.decls)
875-
if (member.isAnyOverride && !(clazz.thisType.baseClasses exists (hasMatchingSym(_, member)))) {
880+
for member <- clazz.info.decls do
881+
if member.isAnyOverride && !clazz.thisType.baseClasses.exists(hasMatchingSym(_, member)) then
876882
if (checks != noPrinter)
877883
for (bc <- clazz.info.baseClasses.tail) {
878884
val sym = bc.info.decl(member.name).symbol
@@ -896,7 +902,7 @@ object RefChecks {
896902
}
897903
member.resetFlag(Override)
898904
member.resetFlag(AbsOverride)
899-
}
905+
end if
900906
}
901907

902908
// Note: if a symbol has both @deprecated and @migration annotations and both

tests/neg/override-scala2-macro.check

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
-- [E164] Declaration Error: tests/neg/override-scala2-macro.scala:2:22 ------------------------------------------------
22
2 | override inline def f[A >: Any](args: A*): String = ??? // error
33
| ^
4-
|error overriding method f in class StringContext of type [A >: Any](args: Seq[A]): String;
5-
| method f of type [A >: Any](args: Seq[A]): String cannot be used here - only Scala-2 macros can override Scala-2 macros
4+
|error overriding method f in class StringContext of type [A >: Any](args: A*): String;
5+
| method f of type [A >: Any](args: A*): String cannot be used here - only Scala-2 macros can override Scala-2 macros

tests/neg/overrides.scala

+20
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,23 @@ class C extends A {
104104
}
105105
}
106106

107+
package p6 {
108+
class A { def apply(xs: Int*) = 42 }
109+
class B extends A { override def apply(xs: Seq[Int]) = 42 } // error
110+
}
111+
package p7 {
112+
class A { def apply(xs: Int*) = 42 }
113+
class B extends A { def apply(xs: Seq[Int]) = 42 } // error
114+
}
115+
package p8 {
116+
class A { def apply(xs: Seq[Int]) = 42 }
117+
class B extends A { override def apply(xs: Int*) = 42 } // error
118+
}
119+
package p9 {
120+
class A { def apply(xs: Seq[Int]) = 42 }
121+
class B extends A { def apply(xs: Int*) = 42 } // error
122+
}
123+
package p10 {
124+
class A { def apply(s: String)(xs: Int*) = 42 }
125+
class B extends A { def apply(s: String)(xs: Seq[Int]) = 42 } // error
126+
}

0 commit comments

Comments
 (0)