Skip to content

Commit f468f17

Browse files
committed
Fix #7526: Don't check class info within bounds when computing denotations
When computing a denotation, always assume that ClassInfos override TypeBounds and other ClassInfos. RefChecks will verify later that the overrides are legal. This is needed to prevent infinite recursion involving interleaved subtype checks and denotation computations prompted by findMember.
1 parent ca6b1c6 commit f468f17

File tree

4 files changed

+36
-13
lines changed

4 files changed

+36
-13
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ object Denotations {
459459
/** Sym preference provided types also override */
460460
def prefer(sym1: Symbol, sym2: Symbol, info1: Type, info2: Type) =
461461
preferSym(sym1, sym2) &&
462-
info1.overrides(info2, sym1.matchNullaryLoosely || sym2.matchNullaryLoosely)
462+
info1.overrides(info2, sym1.matchNullaryLoosely || sym2.matchNullaryLoosely, checkClassInfo = false)
463463

464464
def handleDoubleDef =
465465
if (preferSym(sym1, sym2)) denot1
@@ -600,13 +600,13 @@ object Denotations {
600600
case tp1: TypeBounds =>
601601
tp2 match {
602602
case tp2: TypeBounds => if (safeIntersection) tp1 safe_& tp2 else tp1 & tp2
603-
case tp2: ClassInfo if tp1 contains tp2 => tp2
603+
case tp2: ClassInfo => tp2
604604
case _ => mergeConflict(sym1, sym2, tp1, tp2)
605605
}
606606
case tp1: ClassInfo =>
607607
tp2 match {
608608
case tp2: ClassInfo if tp1.cls eq tp2.cls => tp1.derivedClassInfo(tp1.prefix & tp2.prefix)
609-
case tp2: TypeBounds if tp2 contains tp1 => tp1
609+
case tp2: TypeBounds => tp1
610610
case _ => mergeConflict(sym1, sym2, tp1, tp2)
611611
}
612612

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

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -910,21 +910,21 @@ object Types {
910910

911911
/** Is this type a legal type for member `sym1` that overrides another
912912
* member `sym2` of type `that`? This is the same as `<:<`, except that
913-
* if `matchLoosely` evaluates to true the types `=> T` and `()T` are seen
914-
* as overriding each other.
913+
* @param matchLoosely if true the types `=> T` and `()T` are seen as overriding each other.
914+
* @param checkClassInfo if true we check that ClassInfos are within bounds of abstract types
915915
*/
916-
final def overrides(that: Type, matchLoosely: => Boolean)(implicit ctx: Context): Boolean = {
916+
final def overrides(that: Type, matchLoosely: => Boolean, checkClassInfo: Boolean = true)(implicit ctx: Context): Boolean = {
917917
def widenNullary(tp: Type) = tp match {
918918
case tp @ MethodType(Nil) => tp.resultType
919919
case _ => tp
920920
}
921-
((this.widenExpr frozen_<:< that.widenExpr) ||
922-
matchLoosely && {
923-
val this1 = widenNullary(this)
924-
val that1 = widenNullary(that)
925-
((this1 `ne` this) || (that1 `ne` that)) && this1.overrides(that1, matchLoosely = false)
926-
}
927-
)
921+
this.isInstanceOf[ClassInfo] && !checkClassInfo
922+
|| (this.widenExpr frozen_<:< that.widenExpr)
923+
|| matchLoosely && {
924+
val this1 = widenNullary(this)
925+
val that1 = widenNullary(that)
926+
((this1 `ne` this) || (that1 `ne` that)) && this1.overrides(that1, false, checkClassInfo)
927+
}
928928
}
929929

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

tests/neg/i7526.scala

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
type Tr[-I, +O, +A] = I => (O, A)
2+
3+
trait NetApi with
4+
type Comp
5+
6+
trait NetDB extends NetApi with
7+
class Comp
8+
9+
trait NetHelper extends NetApi
10+
11+
def compQ(name: => String)
12+
: (given n: NetApi) => Tr[Nothing, n.Comp, n.Comp] = ???
13+
14+
object net extends NetDB with NetHelper
15+
import net._
16+
given n: NetApi = net
17+
18+
val q: Tr[Nothing, Comp, Comp] = compQ("???") // error Found: Tr[Nothing, ?1.Comp, ?1.Comp] Required: Tr[Nothing, net.Comp, net.Comp]

tests/neg/override-inner-class.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class C
2+
type T >: String <: Any
3+
4+
class D extends C
5+
class T // error

0 commit comments

Comments
 (0)