Skip to content

Commit 08dfba5

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 08dfba5

File tree

3 files changed

+45
-10
lines changed

3 files changed

+45
-10
lines changed

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

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import scala.util.matching.Regex._
2626
import Constants.Constant
2727
import NullOpsDecorator._
2828
import dotty.tools.dotc.config.Feature
29+
import scala.PartialFunction.cond
2930

3031
object RefChecks {
3132
import tpd._
@@ -253,7 +254,7 @@ object RefChecks {
253254
def infoString(sym: Symbol) = infoString0(sym, sym.owner != clazz)
254255
def infoStringWithLocation(sym: Symbol) = infoString0(sym, true)
255256

256-
def infoString0(sym: Symbol, showLocation: Boolean) = {
257+
def infoString0(sym: Symbol, showLocation: Boolean) = atPhase(typerPhase) {
257258
val sym1 = sym.underlyingSymbol
258259
def info = self.memberInfo(sym1)
259260
val infoStr =
@@ -265,6 +266,19 @@ object RefChecks {
265266
i"${if (showLocation) sym1.showLocated else sym1}$infoStr"
266267
}
267268

269+
def incompatibleRepeatedParam(member: Symbol, other: Symbol): Boolean =
270+
def mismatched(p1: List[Type], p2: List[Type]): Boolean =
271+
p1 match
272+
case h :: t => cond(p2) { case h2 :: t2 => h.isRepeatedParam != h2.isRepeatedParam || mismatched(t, t2) }
273+
case _ => false
274+
def loop(ps1: List[List[Type]], ps2: List[List[Type]]): Boolean =
275+
ps1 match
276+
case h :: t => cond(ps2) { case h2 :: t2 => mismatched(h, h2) || loop(t, t2) }
277+
case _ => false
278+
member.is(Method, butNot = JavaDefined) && other.is(Method, butNot = JavaDefined) && atPhase(typerPhase) {
279+
loop(member.info.paramInfoss, other.info.paramInfoss)
280+
}
281+
268282
/* Check that all conditions for overriding `other` by `member`
269283
* of class `clazz` are met.
270284
*/
@@ -350,10 +364,8 @@ object RefChecks {
350364
//Console.println(infoString(member) + " overrides " + infoString(other) + " in " + clazz);//DEBUG
351365

352366
/* 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-
}
367+
def intersectionIsEmpty(syms1: Iterator[Symbol], syms2: Iterator[Symbol]) =
368+
!syms1.exists(syms2.toSet.contains)
357369

358370
// o: public | protected | package-protected (aka java's default access)
359371
// ^-may be overridden by member with access privileges-v
@@ -414,6 +426,8 @@ object RefChecks {
414426
+ "\n(Note: this can be resolved by declaring an override in " + clazz + ".)")
415427
else if member.is(Exported) then
416428
overrideError("cannot override since it comes from an export")
429+
else if incompatibleRepeatedParam(member, other) then
430+
overrideError("cannot override because erased signatures conflict in repeated parameter")
417431
else
418432
overrideError("needs `override` modifier")
419433
else if (other.is(AbsOverride) && other.isIncompleteIn(clazz) && !member.is(AbsOverride))
@@ -839,6 +853,7 @@ object RefChecks {
839853
def isSignatureMatch(sym: Symbol) = sym.isType || {
840854
val self = clazz.thisType
841855
sym.asSeenFrom(self).matches(member.asSeenFrom(self))
856+
&& !incompatibleRepeatedParam(sym, member)
842857
}
843858

844859
/* The rules for accessing members which have an access boundary are more
@@ -871,8 +886,8 @@ object RefChecks {
871886
}
872887

873888
// 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)))) {
889+
for member <- clazz.info.decls do
890+
if member.isAnyOverride && !clazz.thisType.baseClasses.exists(hasMatchingSym(_, member)) then
876891
if (checks != noPrinter)
877892
for (bc <- clazz.info.baseClasses.tail) {
878893
val sym = bc.info.decl(member.name).symbol
@@ -896,7 +911,7 @@ object RefChecks {
896911
}
897912
member.resetFlag(Override)
898913
member.resetFlag(AbsOverride)
899-
}
914+
end if
900915
}
901916

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

tests/neg/override-scala2-macro.check

Lines changed: 2 additions & 2 deletions
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

Lines changed: 20 additions & 0 deletions
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)