Skip to content

Commit 6121aef

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 a356581 commit 6121aef

File tree

5 files changed

+54
-10
lines changed

5 files changed

+54
-10
lines changed

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

+16
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,22 @@ object Decorators {
234234
def nestedExists(p: T => Boolean): Boolean = xss match
235235
case xs :: xss1 => xs.exists(p) || xss1.nestedExists(p)
236236
case nil => false
237+
def nestedZipExists(yss: List[List[U]])(f: (T, U) => Boolean): Boolean =
238+
@tailrec def zipExists(p1: List[T], p2: List[U]): Boolean =
239+
p1 match
240+
case h :: t =>
241+
p2 match
242+
case h2 :: t2 => f(h, h2) || zipExists(t, t2)
243+
case _ => false
244+
case _ => false
245+
@tailrec def loop(ps1: List[List[T]], ps2: List[List[U]]): Boolean =
246+
ps1 match
247+
case h :: t =>
248+
ps2 match
249+
case h2 :: t2 => zipExists(h, h2) || loop(t, t2)
250+
case _ => false
251+
case _ => false
252+
loop(xss, yss)
237253
end extension
238254

239255
extension (text: Text)

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ object ErrorReporting {
125125
/** Explain info of symbol `sym` as a member of class `base`.
126126
* @param showLocation if true also show sym's location.
127127
*/
128-
def infoString(sym: Symbol, base: Type, showLocation: Boolean): String =
128+
def infoString(sym: Symbol, base: Type, showLocation: Boolean): String = atPhase(Phases.typerPhase) {
129129
val sym1 = sym.underlyingSymbol
130130
def info = base.memberInfo(sym1)
131131
val infoStr =
@@ -135,6 +135,7 @@ object ErrorReporting {
135135
else if sym1.isTerm then i" of type $info"
136136
else ""
137137
i"${if showLocation then sym1.showLocated else sym1}$infoStr"
138+
}
138139

139140
def infoStringWithLocation(sym: Symbol, base: Type) =
140141
infoString(sym, base, showLocation = true)

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

+13-7
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,11 @@ object RefChecks {
336336
next == other || isInheritedAccessor(next, other)
337337
}
338338

339+
def incompatibleRepeatedParam(member: Symbol, other: Symbol): Boolean =
340+
member.is(Method, butNot = JavaDefined) && other.is(Method, butNot = JavaDefined) && atPhase(typerPhase) {
341+
member.info.paramInfoss.nestedZipExists(other.info.paramInfoss)(_.isRepeatedParam != _.isRepeatedParam)
342+
}
343+
339344
/* Check that all conditions for overriding `other` by `member`
340345
* of class `clazz` are met.
341346
*/
@@ -425,10 +430,8 @@ object RefChecks {
425430
//Console.println(infoString(member) + " overrides " + infoString(other) + " in " + clazz);//DEBUG
426431

427432
/* Is the intersection between given two lists of overridden symbols empty? */
428-
def intersectionIsEmpty(syms1: Iterator[Symbol], syms2: Iterator[Symbol]) = {
429-
val set2 = syms2.toSet
430-
!(syms1 exists (set2 contains _))
431-
}
433+
def intersectionIsEmpty(syms1: Iterator[Symbol], syms2: Iterator[Symbol]) =
434+
!syms1.exists(syms2.toSet.contains)
432435

433436
// o: public | protected | package-protected (aka java's default access)
434437
// ^-may be overridden by member with access privileges-v
@@ -498,6 +501,8 @@ object RefChecks {
498501
+ "\n(Note: this can be resolved by declaring an override in " + clazz + ".)")
499502
else if member.is(Exported) then
500503
overrideError("cannot override since it comes from an export")
504+
else if incompatibleRepeatedParam(member, other) then
505+
overrideError("cannot override because erased signatures conflict in repeated parameter")
501506
else
502507
overrideError("needs `override` modifier")
503508
else if (other.is(AbsOverride) && other.isIncompleteIn(clazz) && !member.is(AbsOverride))
@@ -878,6 +883,7 @@ object RefChecks {
878883
def isSignatureMatch(sym: Symbol) = sym.isType || {
879884
val self = clazz.thisType
880885
sym.asSeenFrom(self).matches(member.asSeenFrom(self))
886+
&& !incompatibleRepeatedParam(sym, member)
881887
}
882888

883889
/* The rules for accessing members which have an access boundary are more
@@ -910,8 +916,8 @@ object RefChecks {
910916
}
911917

912918
// 4. Check that every defined member with an `override` modifier overrides some other member.
913-
for (member <- clazz.info.decls)
914-
if (member.isAnyOverride && !(clazz.thisType.baseClasses exists (hasMatchingSym(_, member)))) {
919+
for member <- clazz.info.decls do
920+
if member.isAnyOverride && !clazz.thisType.baseClasses.exists(hasMatchingSym(_, member)) then
915921
if (checks != noPrinter)
916922
for (bc <- clazz.info.baseClasses.tail) {
917923
val sym = bc.info.decl(member.name).symbol
@@ -935,7 +941,7 @@ object RefChecks {
935941
}
936942
member.resetFlag(Override)
937943
member.resetFlag(AbsOverride)
938-
}
944+
end if
939945
}
940946

941947
/** Check that we do not "override" anything with a private method

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

+21
Original file line numberDiff line numberDiff line change
@@ -120,3 +120,24 @@ class C extends A {
120120
override def m: Int = 42 // error: has incompatible type
121121
}
122122
}
123+
124+
package p6 {
125+
class A { def apply(xs: Int*) = 42 }
126+
class B extends A { override def apply(xs: Seq[Int]) = 42 } // error
127+
}
128+
package p7 {
129+
class A { def apply(xs: Int*) = 42 }
130+
class B extends A { def apply(xs: Seq[Int]) = 42 } // error
131+
}
132+
package p8 {
133+
class A { def apply(xs: Seq[Int]) = 42 }
134+
class B extends A { override def apply(xs: Int*) = 42 } // error
135+
}
136+
package p9 {
137+
class A { def apply(xs: Seq[Int]) = 42 }
138+
class B extends A { def apply(xs: Int*) = 42 } // error
139+
}
140+
package p10 {
141+
class A { def apply(s: String)(xs: Int*) = 42 }
142+
class B extends A { def apply(s: String)(xs: Seq[Int]) = 42 } // error
143+
}

0 commit comments

Comments
 (0)