Skip to content

Commit 9009f16

Browse files
authored
Repeated params must correspond in override (#16836)
Refchecks runs after elimRepeated and did not error on an attempt to override RepeatedParam with Seq. Also show RepeatedParam in error message for double definition. Fixes #12662 Resubmits #13248 which was opened against old master.
2 parents bbb70cc + d6fd2c4 commit 9009f16

File tree

2 files changed

+45
-7
lines changed

2 files changed

+45
-7
lines changed

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

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

339+
/** Detect any param section where params in last position do not agree isRepeatedParam.
340+
*/
341+
def incompatibleRepeatedParam(member: Symbol, other: Symbol): Boolean =
342+
def loop(mParamInfoss: List[List[Type]], oParamInfoss: List[List[Type]]): Boolean =
343+
mParamInfoss match
344+
case Nil => false
345+
case h :: t =>
346+
oParamInfoss match
347+
case Nil => false
348+
case h2 :: t2 => h.nonEmpty && h2.nonEmpty && h.last.isRepeatedParam != h2.last.isRepeatedParam
349+
|| loop(t, t2)
350+
member.is(Method, butNot = JavaDefined)
351+
&& other.is(Method, butNot = JavaDefined)
352+
&& atPhase(typerPhase):
353+
loop(member.info.paramInfoss, other.info.paramInfoss)
354+
339355
/* Check that all conditions for overriding `other` by `member`
340356
* of class `clazz` are met.
341357
*/
@@ -425,10 +441,8 @@ object RefChecks {
425441
//Console.println(infoString(member) + " overrides " + infoString(other) + " in " + clazz);//DEBUG
426442

427443
/* 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-
}
444+
def intersectionIsEmpty(syms1: Iterator[Symbol], syms2: Iterator[Symbol]) =
445+
!syms1.exists(syms2.toSet.contains)
432446

433447
// o: public | protected | package-protected (aka java's default access)
434448
// ^-may be overridden by member with access privileges-v
@@ -498,6 +512,8 @@ object RefChecks {
498512
+ "\n(Note: this can be resolved by declaring an override in " + clazz + ".)")
499513
else if member.is(Exported) then
500514
overrideError("cannot override since it comes from an export")
515+
else if incompatibleRepeatedParam(member, other) then
516+
report.error(DoubleDefinition(member, other, clazz), member.srcPos)
501517
else
502518
overrideError("needs `override` modifier")
503519
else if (other.is(AbsOverride) && other.isIncompleteIn(clazz) && !member.is(AbsOverride))
@@ -878,6 +894,7 @@ object RefChecks {
878894
def isSignatureMatch(sym: Symbol) = sym.isType || {
879895
val self = clazz.thisType
880896
sym.asSeenFrom(self).matches(member.asSeenFrom(self))
897+
&& !incompatibleRepeatedParam(sym, member)
881898
}
882899

883900
/* The rules for accessing members which have an access boundary are more
@@ -910,8 +927,8 @@ object RefChecks {
910927
}
911928

912929
// 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)))) {
930+
for member <- clazz.info.decls do
931+
if member.isAnyOverride && !clazz.thisType.baseClasses.exists(hasMatchingSym(_, member)) then
915932
if (checks != noPrinter)
916933
for (bc <- clazz.info.baseClasses.tail) {
917934
val sym = bc.info.decl(member.name).symbol
@@ -935,7 +952,7 @@ object RefChecks {
935952
}
936953
member.resetFlag(Override)
937954
member.resetFlag(AbsOverride)
938-
}
955+
end if
939956
}
940957

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

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)