Skip to content

Repeated params must correspond in override #13248

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions compiler/src/dotty/tools/dotc/core/Decorators.scala
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,22 @@ object Decorators {
def nestedExists(p: T => Boolean): Boolean = xss match
case xs :: xss1 => xs.exists(p) || xss1.nestedExists(p)
case nil => false
def nestedZipExists(yss: List[List[U]])(f: (T, U) => Boolean): Boolean =
@tailrec def zipExists(p1: List[T], p2: List[U]): Boolean =
p1 match
case h :: t =>
p2 match
case h2 :: t2 => f(h, h2) || zipExists(t, t2)
case _ => false
case _ => false
@tailrec def loop(ps1: List[List[T]], ps2: List[List[U]]): Boolean =
ps1 match
case h :: t =>
ps2 match
case h2 :: t2 => zipExists(h, h2) || loop(t, t2)
case _ => false
case _ => false
loop(xss, yss)
end extension

extension (text: Text)
Expand Down
22 changes: 14 additions & 8 deletions compiler/src/dotty/tools/dotc/typer/RefChecks.scala
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ object RefChecks {
def infoString(sym: Symbol) = infoString0(sym, sym.owner != clazz)
def infoStringWithLocation(sym: Symbol) = infoString0(sym, true)

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

def incompatibleRepeatedParam(member: Symbol, other: Symbol): Boolean =
member.is(Method, butNot = JavaDefined) && other.is(Method, butNot = JavaDefined) && atPhase(typerPhase) {
member.info.paramInfoss.nestedZipExists(other.info.paramInfoss)(_.isRepeatedParam != _.isRepeatedParam)
}

/* Check that all conditions for overriding `other` by `member`
* of class `clazz` are met.
*/
Expand Down Expand Up @@ -350,10 +355,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
Expand Down Expand Up @@ -414,6 +417,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
overrideError("cannot override because erased signatures conflict in repeated parameter")
else
overrideError("needs `override` modifier")
else if (other.is(AbsOverride) && other.isIncompleteIn(clazz) && !member.is(AbsOverride))
Expand Down Expand Up @@ -839,6 +844,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
Expand Down Expand Up @@ -871,8 +877,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
Expand All @@ -896,7 +902,7 @@ object RefChecks {
}
member.resetFlag(Override)
member.resetFlag(AbsOverride)
}
end if
}

// Note: if a symbol has both @deprecated and @migration annotations and both
Expand Down
4 changes: 2 additions & 2 deletions tests/neg/override-scala2-macro.check
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
-- [E164] Declaration Error: tests/neg/override-scala2-macro.scala:2:22 ------------------------------------------------
2 | override inline def f[A >: Any](args: A*): String = ??? // error
| ^
|error overriding method f in class StringContext of type [A >: Any](args: Seq[A]): String;
| method f of type [A >: Any](args: Seq[A]): String cannot be used here - only Scala-2 macros can override Scala-2 macros
|error overriding method f in class StringContext of type [A >: Any](args: A*): String;
| method f of type [A >: Any](args: A*): String cannot be used here - only Scala-2 macros can override Scala-2 macros
20 changes: 20 additions & 0 deletions tests/neg/overrides.scala
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,23 @@ class C extends A {
}
}

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
}