diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index 73331046b41f..5ccd77b6e94a 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -336,6 +336,22 @@ object RefChecks { next == other || isInheritedAccessor(next, other) } + /** Detect any param section where params in last position do not agree isRepeatedParam. + */ + def incompatibleRepeatedParam(member: Symbol, other: Symbol): Boolean = + def loop(mParamInfoss: List[List[Type]], oParamInfoss: List[List[Type]]): Boolean = + mParamInfoss match + case Nil => false + case h :: t => + oParamInfoss match + case Nil => false + case h2 :: t2 => h.nonEmpty && h2.nonEmpty && h.last.isRepeatedParam != h2.last.isRepeatedParam + || loop(t, t2) + member.is(Method, butNot = JavaDefined) + && other.is(Method, butNot = JavaDefined) + && atPhase(typerPhase): + loop(member.info.paramInfoss, other.info.paramInfoss) + /* Check that all conditions for overriding `other` by `member` * of class `clazz` are met. */ @@ -425,10 +441,8 @@ object RefChecks { //Console.println(infoString(member) + " overrides " + infoString(other) + " in " + clazz);//DEBUG /* Is the intersection between given two lists of overridden symbols empty? */ - def intersectionIsEmpty(syms1: Iterator[Symbol], syms2: Iterator[Symbol]) = { - val set2 = syms2.toSet - !(syms1 exists (set2 contains _)) - } + def intersectionIsEmpty(syms1: Iterator[Symbol], syms2: Iterator[Symbol]) = + !syms1.exists(syms2.toSet.contains) // o: public | protected | package-protected (aka java's default access) // ^-may be overridden by member with access privileges-v @@ -498,6 +512,8 @@ object RefChecks { + "\n(Note: this can be resolved by declaring an override in " + clazz + ".)") else if member.is(Exported) then overrideError("cannot override since it comes from an export") + else if incompatibleRepeatedParam(member, other) then + report.error(DoubleDefinition(member, other, clazz), member.srcPos) else overrideError("needs `override` modifier") else if (other.is(AbsOverride) && other.isIncompleteIn(clazz) && !member.is(AbsOverride)) @@ -878,6 +894,7 @@ object RefChecks { def isSignatureMatch(sym: Symbol) = sym.isType || { val self = clazz.thisType sym.asSeenFrom(self).matches(member.asSeenFrom(self)) + && !incompatibleRepeatedParam(sym, member) } /* The rules for accessing members which have an access boundary are more @@ -910,8 +927,8 @@ object RefChecks { } // 4. Check that every defined member with an `override` modifier overrides some other member. - for (member <- clazz.info.decls) - if (member.isAnyOverride && !(clazz.thisType.baseClasses exists (hasMatchingSym(_, member)))) { + for member <- clazz.info.decls do + if member.isAnyOverride && !clazz.thisType.baseClasses.exists(hasMatchingSym(_, member)) then if (checks != noPrinter) for (bc <- clazz.info.baseClasses.tail) { val sym = bc.info.decl(member.name).symbol @@ -935,7 +952,7 @@ object RefChecks { } member.resetFlag(Override) member.resetFlag(AbsOverride) - } + end if } /** Check that we do not "override" anything with a private method diff --git a/tests/neg/overrides.scala b/tests/neg/overrides.scala index c8fc8de97f7c..ff83b91d26be 100644 --- a/tests/neg/overrides.scala +++ b/tests/neg/overrides.scala @@ -120,3 +120,24 @@ class C extends A { override def m: Int = 42 // error: has incompatible type } } + +package p6 { + class A { def apply(xs: Int*) = 42 } + class B extends A { override def apply(xs: Seq[Int]) = 42 } // error +} +package p7 { + class A { def apply(xs: Int*) = 42 } + class B extends A { def apply(xs: Seq[Int]) = 42 } // error +} +package p8 { + class A { def apply(xs: Seq[Int]) = 42 } + class B extends A { override def apply(xs: Int*) = 42 } // error +} +package p9 { + class A { def apply(xs: Seq[Int]) = 42 } + class B extends A { def apply(xs: Int*) = 42 } // error +} +package p10 { + class A { def apply(s: String)(xs: Int*) = 42 } + class B extends A { def apply(s: String)(xs: Seq[Int]) = 42 } // error +}