diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index 7f5779bb6127..0cdfc8791c00 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -785,9 +785,6 @@ object Contexts { def withNotNullInfos(infos: List[NotNullInfo]): Context = if !c.explicitNulls || (c.notNullInfos eq infos) then c else c.fresh.setNotNullInfos(infos) - def relaxedOverrideContext: Context = - c.withModeBits(c.mode &~ Mode.SafeNulls | Mode.RelaxedOverriding) - // TODO: Fix issue when converting ModeChanges and FreshModeChanges to extension givens extension (c: Context) { final def withModeBits(mode: Mode): Context = diff --git a/compiler/src/dotty/tools/dotc/core/Denotations.scala b/compiler/src/dotty/tools/dotc/core/Denotations.scala index 85ff51bc19de..c5047cb5d806 100644 --- a/compiler/src/dotty/tools/dotc/core/Denotations.scala +++ b/compiler/src/dotty/tools/dotc/core/Denotations.scala @@ -478,12 +478,11 @@ object Denotations { else if sym1.is(Method) && !sym2.is(Method) then 1 else 0 - val relaxedOverriding = ctx.explicitNulls && (sym1.is(JavaDefined) || sym2.is(JavaDefined)) val matchLoosely = sym1.matchNullaryLoosely || sym2.matchNullaryLoosely - if symScore <= 0 && info2.overrides(info1, relaxedOverriding, matchLoosely, checkClassInfo = false) then + if symScore <= 0 && info2.overrides(info1, matchLoosely, checkClassInfo = false) then denot2 - else if symScore >= 0 && info1.overrides(info2, relaxedOverriding, matchLoosely, checkClassInfo = false) then + else if symScore >= 0 && info1.overrides(info2, matchLoosely, checkClassInfo = false) then denot1 else val jointInfo = infoMeet(info1, info2, safeIntersection) diff --git a/compiler/src/dotty/tools/dotc/core/Mode.scala b/compiler/src/dotty/tools/dotc/core/Mode.scala index 14d7827974c0..55e88eae4f6e 100644 --- a/compiler/src/dotty/tools/dotc/core/Mode.scala +++ b/compiler/src/dotty/tools/dotc/core/Mode.scala @@ -105,7 +105,7 @@ object Mode { /** Use previous Scheme for implicit resolution. Currently significant * in 3.0-migration where we use Scala-2's scheme instead and in 3.5 and 3.6-migration - * where we use the previous scheme up to 3.4 for comparison with the new scheme. + * where we use the previous scheme up to 3.4 for comparison with the new scheme. */ val OldImplicitResolution: Mode = newMode(15, "OldImplicitResolution") @@ -163,11 +163,6 @@ object Mode { */ val ForceInline: Mode = newMode(29, "ForceInline") - /** This mode is enabled when we check Java overriding in explicit nulls. - * Type `Null` becomes a subtype of non-primitive value types in TypeComparer. - */ - val RelaxedOverriding: Mode = newMode(30, "RelaxedOverriding") - /** Skip inlining of methods. */ val NoInline: Mode = newMode(31, "NoInline") } diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index 8414c3795f49..ca2df327851e 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -967,17 +967,10 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling || compareGADT || tryLiftedToThis1 case _ => - // `Mode.RelaxedOverriding` is only enabled when checking Java overriding - // in explicit nulls, and `Null` becomes a bottom type, which allows - // `T | Null` being a subtype of `T`. - // A type variable `T` from Java is translated to `T >: Nothing <: Any`. - // However, `null` can always be a value of `T` for Java side. - // So the best solution here is to let `Null` be a subtype of non-primitive - // value types temporarily. def isNullable(tp: Type): Boolean = tp.dealias match case tp: TypeRef => val tpSym = tp.symbol - ctx.mode.is(Mode.RelaxedOverriding) && !tpSym.isPrimitiveValueClass || + !tpSym.isPrimitiveValueClass || tpSym.isNullableClass case tp: TermRef => // https://scala-lang.org/files/archive/spec/2.13/03-types.html#singleton-types diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index c5937074f4bc..ab3b44847e18 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -1160,17 +1160,14 @@ object Types extends TypeUtils { * * @param isSubType a function used for checking subtype relationships. */ - final def overrides(that: Type, relaxedCheck: Boolean, matchLoosely: => Boolean, checkClassInfo: Boolean = true, + final def overrides(that: Type, matchLoosely: => Boolean, checkClassInfo: Boolean = true, isSubType: (Type, Type) => Context ?=> Boolean = (tp1, tp2) => tp1 frozen_<:< tp2)(using Context): Boolean = { - val overrideCtx = if relaxedCheck then ctx.relaxedOverrideContext else ctx - inContext(overrideCtx) { - !checkClassInfo && this.isInstanceOf[ClassInfo] - || isSubType(this.widenExpr, that.widenExpr) - || matchLoosely && { - val this1 = this.widenNullaryMethod - val that1 = that.widenNullaryMethod - ((this1 `ne` this) || (that1 `ne` that)) && this1.overrides(that1, relaxedCheck, false, checkClassInfo) - } + !checkClassInfo && this.isInstanceOf[ClassInfo] + || isSubType(this.widenExpr, that.widenExpr) + || matchLoosely && { + val this1 = this.widenNullaryMethod + val that1 = that.widenNullaryMethod + ((this1 `ne` this) || (that1 `ne` that)) && this1.overrides(that1, false, checkClassInfo) } } @@ -1196,8 +1193,7 @@ object Types extends TypeUtils { */ def matches(that: Type)(using Context): Boolean = { record("matches") - val overrideCtx = if ctx.explicitNulls then ctx.relaxedOverrideContext else ctx - TypeComparer.matchesType(this, that, relaxed = !ctx.phase.erasedTypes)(using overrideCtx) + TypeComparer.matchesType(this, that, relaxed = !ctx.phase.erasedTypes) } /** This is the same as `matches` except that it also matches => T with T and diff --git a/compiler/src/dotty/tools/dotc/transform/OverridingPairs.scala b/compiler/src/dotty/tools/dotc/transform/OverridingPairs.scala index 6529eed77fa0..a9a17f6db464 100644 --- a/compiler/src/dotty/tools/dotc/transform/OverridingPairs.scala +++ b/compiler/src/dotty/tools/dotc/transform/OverridingPairs.scala @@ -225,11 +225,7 @@ object OverridingPairs: } ) else - // releaxed override check for explicit nulls if one of the symbols is Java defined, - // force `Null` to be a subtype of non-primitive value types during override checking. - val relaxedOverriding = ctx.explicitNulls && (member.is(JavaDefined) || other.is(JavaDefined)) member.name.is(DefaultGetterName) // default getters are not checked for compatibility - || memberTp.overrides(otherTp, relaxedOverriding, - member.matchNullaryLoosely || other.matchNullaryLoosely || fallBack, isSubType = isSubType) + || memberTp.overrides(otherTp, member.matchNullaryLoosely || other.matchNullaryLoosely || fallBack, isSubType = isSubType) end OverridingPairs diff --git a/compiler/src/dotty/tools/dotc/transform/ResolveSuper.scala b/compiler/src/dotty/tools/dotc/transform/ResolveSuper.scala index dd3f41be5a8e..7b236f0e2b0e 100644 --- a/compiler/src/dotty/tools/dotc/transform/ResolveSuper.scala +++ b/compiler/src/dotty/tools/dotc/transform/ResolveSuper.scala @@ -111,11 +111,8 @@ object ResolveSuper { // of the superaccessor's type, see i5433.scala for an example where this matters val otherTp = other.asSeenFrom(base.typeRef).info val accTp = acc.asSeenFrom(base.typeRef).info - // Since the super class can be Java defined, - // we use relaxed overriding check for explicit nulls if one of the symbols is Java defined. - // This forces `Null` to be a subtype of non-primitive value types during override checking. - val relaxedOverriding = ctx.explicitNulls && (sym.is(JavaDefined) || acc.is(JavaDefined)) - if !otherTp.overrides(accTp, relaxedOverriding, matchLoosely = true) then + + if !otherTp.overrides(accTp, matchLoosely = true) then report.error(IllegalSuperAccessor(base, memberName, targetName, acc, accTp, other.symbol, otherTp), base.srcPos) bcs = bcs.tail } diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index 7e53b38b5f98..00a6a0a8e060 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -906,7 +906,7 @@ object RefChecks { for (mbrd <- self.member(name).alternatives) { val mbr = mbrd.symbol val mbrType = mbr.info.asSeenFrom(self, mbr.owner) - if (!mbrType.overrides(mbrd.info, relaxedCheck = false, matchLoosely = true)) + if (!mbrType.overrides(mbrd.info, matchLoosely = true)) report.errorOrMigrationWarning( em"""${mbr.showLocated} is not a legal implementation of `$name` in $clazz | its type $mbrType