diff --git a/compiler/src/dotty/tools/dotc/core/Denotations.scala b/compiler/src/dotty/tools/dotc/core/Denotations.scala index e47def78fba1..57c678ad8cb1 100644 --- a/compiler/src/dotty/tools/dotc/core/Denotations.scala +++ b/compiler/src/dotty/tools/dotc/core/Denotations.scala @@ -459,7 +459,7 @@ object Denotations { /** Sym preference provided types also override */ def prefer(sym1: Symbol, sym2: Symbol, info1: Type, info2: Type) = preferSym(sym1, sym2) && - info1.overrides(info2, sym1.matchNullaryLoosely || sym2.matchNullaryLoosely) + info1.overrides(info2, sym1.matchNullaryLoosely || sym2.matchNullaryLoosely, checkClassInfo = false) def handleDoubleDef = if (preferSym(sym1, sym2)) denot1 @@ -600,13 +600,13 @@ object Denotations { case tp1: TypeBounds => tp2 match { case tp2: TypeBounds => if (safeIntersection) tp1 safe_& tp2 else tp1 & tp2 - case tp2: ClassInfo if tp1 contains tp2 => tp2 + case tp2: ClassInfo => tp2 case _ => mergeConflict(sym1, sym2, tp1, tp2) } case tp1: ClassInfo => tp2 match { case tp2: ClassInfo if tp1.cls eq tp2.cls => tp1.derivedClassInfo(tp1.prefix & tp2.prefix) - case tp2: TypeBounds if tp2 contains tp1 => tp1 + case tp2: TypeBounds => tp1 case _ => mergeConflict(sym1, sym2, tp1, tp2) } diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 7f1554c3dbec..ee004f9c89dd 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -910,21 +910,21 @@ object Types { /** Is this type a legal type for member `sym1` that overrides another * member `sym2` of type `that`? This is the same as `<:<`, except that - * if `matchLoosely` evaluates to true the types `=> T` and `()T` are seen - * as overriding each other. + * @param matchLoosely if true the types `=> T` and `()T` are seen as overriding each other. + * @param checkClassInfo if true we check that ClassInfos are within bounds of abstract types */ - final def overrides(that: Type, matchLoosely: => Boolean)(implicit ctx: Context): Boolean = { + final def overrides(that: Type, matchLoosely: => Boolean, checkClassInfo: Boolean = true)(implicit ctx: Context): Boolean = { def widenNullary(tp: Type) = tp match { case tp @ MethodType(Nil) => tp.resultType case _ => tp } - ((this.widenExpr frozen_<:< that.widenExpr) || - matchLoosely && { - val this1 = widenNullary(this) - val that1 = widenNullary(that) - ((this1 `ne` this) || (that1 `ne` that)) && this1.overrides(that1, matchLoosely = false) - } - ) + !checkClassInfo && this.isInstanceOf[ClassInfo] + || (this.widenExpr frozen_<:< that.widenExpr) + || matchLoosely && { + val this1 = widenNullary(this) + val that1 = widenNullary(that) + ((this1 `ne` this) || (that1 `ne` that)) && this1.overrides(that1, false, checkClassInfo) + } } /** Is this type close enough to that type so that members diff --git a/tests/neg/i7526.scala b/tests/neg/i7526.scala new file mode 100644 index 000000000000..146e8850995d --- /dev/null +++ b/tests/neg/i7526.scala @@ -0,0 +1,18 @@ +type Tr[-I, +O, +A] = I => (O, A) + +trait NetApi with + type Comp + +trait NetDB extends NetApi with + class Comp + +trait NetHelper extends NetApi + +def compQ(name: => String) + : (given n: NetApi) => Tr[Nothing, n.Comp, n.Comp] = ??? + +object net extends NetDB with NetHelper +import net._ +given n: NetApi = net + +val q: Tr[Nothing, Comp, Comp] = compQ("???") // error Found: Tr[Nothing, ?1.Comp, ?1.Comp] Required: Tr[Nothing, net.Comp, net.Comp] \ No newline at end of file diff --git a/tests/neg/override-inner-class.scala b/tests/neg/override-inner-class.scala new file mode 100644 index 000000000000..2ae9a5b3108c --- /dev/null +++ b/tests/neg/override-inner-class.scala @@ -0,0 +1,5 @@ +class C + type T >: String <: Any + +class D extends C + class T // error