Skip to content

Commit 5d089cb

Browse files
committed
Fix overriding check in mergeSingleDenot
1 parent e54a934 commit 5d089cb

File tree

6 files changed

+48
-19
lines changed

6 files changed

+48
-19
lines changed

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -469,11 +469,12 @@ object Denotations {
469469
else if sym1.is(Method) && !sym2.is(Method) then 1
470470
else 0
471471

472+
val relaxedOverriding = ctx.explicitNulls && (sym1.is(JavaDefined) || sym2.is(JavaDefined))
472473
val matchLoosely = sym1.matchNullaryLoosely || sym2.matchNullaryLoosely
473474

474-
if symScore <= 0 && info2.overrides(info1, matchLoosely, checkClassInfo = false) then
475+
if symScore <= 0 && info2.overrides(info1, relaxedOverriding, matchLoosely, checkClassInfo = false) then
475476
denot2
476-
else if symScore >= 0 && info1.overrides(info2, matchLoosely, checkClassInfo = false) then
477+
else if symScore >= 0 && info1.overrides(info2, relaxedOverriding, matchLoosely, checkClassInfo = false) then
477478
denot1
478479
else
479480
val jointInfo = infoMeet(info1, info2, safeIntersection)

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

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,21 +1071,25 @@ object Types {
10711071

10721072
/** Is this type a legal type for member `sym1` that overrides another
10731073
* member `sym2` of type `that`? This is the same as `<:<`, except that
1074+
* @param relaxedCheck if true type `Null` becomes a subtype of non-primitive value types in TypeComparer.
10741075
* @param matchLoosely if true the types `=> T` and `()T` are seen as overriding each other.
10751076
* @param checkClassInfo if true we check that ClassInfos are within bounds of abstract types
10761077
*/
1077-
final def overrides(that: Type, matchLoosely: => Boolean, checkClassInfo: Boolean = true)(using Context): Boolean = {
1078+
final def overrides(that: Type, relaxedCheck: Boolean, matchLoosely: => Boolean, checkClassInfo: Boolean = true)(using Context): Boolean = {
10781079
def widenNullary(tp: Type) = tp match {
10791080
case tp @ MethodType(Nil) => tp.resultType
10801081
case _ => tp
10811082
}
1082-
!checkClassInfo && this.isInstanceOf[ClassInfo]
1083-
|| (this.widenExpr frozen_<:< that.widenExpr)
1084-
|| matchLoosely && {
1085-
val this1 = widenNullary(this)
1086-
val that1 = widenNullary(that)
1087-
((this1 `ne` this) || (that1 `ne` that)) && this1.overrides(that1, false, checkClassInfo)
1088-
}
1083+
val overrideCtx = if relaxedCheck && !ctx.mode.is(Mode.RelaxedOverriding) then ctx.relaxedOverrideContext else ctx
1084+
inContext(overrideCtx) {
1085+
!checkClassInfo && this.isInstanceOf[ClassInfo]
1086+
|| (this.widenExpr frozen_<:< that.widenExpr)
1087+
|| matchLoosely && {
1088+
val this1 = widenNullary(this)
1089+
val that1 = widenNullary(that)
1090+
((this1 `ne` this) || (that1 `ne` that)) && this1.overrides(that1, relaxedCheck, false, checkClassInfo)
1091+
}
1092+
}
10891093
}
10901094

10911095
/** Is this type close enough to that type so that members

compiler/src/dotty/tools/dotc/transform/OverridingPairs.scala

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -217,11 +217,9 @@ object OverridingPairs:
217217
else
218218
// releaxed override check for explicit nulls if one of the symbols is Java defined,
219219
// force `Null` to be a subtype of non-primitive value types during override checking.
220-
val overrideCtx = if ctx.explicitNulls && (member.is(JavaDefined) || other.is(JavaDefined))
221-
then ctx.relaxedOverrideContext else ctx
220+
val relaxedOverriding = ctx.explicitNulls && (member.is(JavaDefined) || other.is(JavaDefined))
222221
member.name.is(DefaultGetterName) // default getters are not checked for compatibility
223-
|| memberTp.overrides(otherTp,
224-
member.matchNullaryLoosely || other.matchNullaryLoosely || fallBack
225-
)(using overrideCtx)
222+
|| memberTp.overrides(otherTp, relaxedOverriding,
223+
member.matchNullaryLoosely || other.matchNullaryLoosely || fallBack)
226224

227225
end OverridingPairs

compiler/src/dotty/tools/dotc/transform/ResolveSuper.scala

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,8 @@ object ResolveSuper {
113113
// Since the super class can be Java defined,
114114
// we use relaxed overriding check for explicit nulls if one of the symbols is Java defined.
115115
// This forces `Null` to be a subtype of non-primitive value types during override checking.
116-
val overrideCtx = if ctx.explicitNulls && (sym.is(JavaDefined) || acc.is(JavaDefined))
117-
then ctx.relaxedOverrideContext else ctx
118-
if !otherTp.overrides(accTp, matchLoosely = true)(using overrideCtx) then
116+
val relaxedOverriding = ctx.explicitNulls && (sym.is(JavaDefined) || acc.is(JavaDefined))
117+
if !otherTp.overrides(accTp, relaxedOverriding, matchLoosely = true) then
119118
report.error(IllegalSuperAccessor(base, memberName, targetName, acc, accTp, other.symbol, otherTp), base.srcPos)
120119
bcs = bcs.tail
121120
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -767,7 +767,7 @@ object RefChecks {
767767
for (mbrd <- self.member(name).alternatives) {
768768
val mbr = mbrd.symbol
769769
val mbrType = mbr.info.asSeenFrom(self, mbr.owner)
770-
if (!mbrType.overrides(mbrd.info, matchLoosely = true))
770+
if (!mbrType.overrides(mbrd.info, false, matchLoosely = true))
771771
report.errorOrMigrationWarning(
772772
em"""${mbr.showLocated} is not a legal implementation of `$name` in $clazz
773773
| its type $mbrType
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
class C1:
2+
sealed abstract class Name {
3+
type ThisName <: Name
4+
def compareTo(that: ThisName): Int = ???
5+
}
6+
7+
class LocalName extends Name with Comparable[LocalName] {
8+
type ThisName = LocalName
9+
}
10+
11+
val localName = LocalName()
12+
println(localName)
13+
var count = 0
14+
15+
class C2:
16+
sealed abstract class Name {
17+
type ThisName <: Name
18+
def compareTo(that: ThisName | Null): Int = ???
19+
}
20+
21+
class LocalName extends Name with Comparable[LocalName] {
22+
type ThisName = LocalName
23+
}
24+
25+
val localName = LocalName()
26+
println(localName)
27+
var count = 0

0 commit comments

Comments
 (0)