Skip to content

Commit 98bf4f8

Browse files
authored
Merge pull request #11192 from dotty-staging/fix-11078
Fix #11078: avoid widening F-bounds in type avoidance
2 parents c840d21 + f661681 commit 98bf4f8

File tree

4 files changed

+59
-2
lines changed

4 files changed

+59
-2
lines changed

Diff for: compiler/src/dotty/tools/dotc/core/TypeOps.scala

+3-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package dotc
33
package core
44

55
import Contexts._, Types._, Symbols._, Names._, Flags._
6-
import SymDenotations._
6+
import Denotations._, SymDenotations._
77
import util.Spans._
88
import util.Stats
99
import NameKinds.DepParamName
@@ -438,6 +438,8 @@ object TypeOps:
438438
tp.origin, fromBelow = variance > 0 || variance == 0 && tp.hasLowerBound)(using mapCtx)
439439
val lo1 = apply(lo)
440440
if (lo1 ne lo) lo1 else tp
441+
case tp: LazyRef if isExpandingBounds =>
442+
emptyRange
441443
case _ =>
442444
mapOver(tp)
443445
}

Diff for: compiler/src/dotty/tools/dotc/core/Types.scala

+16-1
Original file line numberDiff line numberDiff line change
@@ -5328,8 +5328,23 @@ object Types {
53285328
case _ => tp
53295329
}
53305330

5331+
private var expandingBounds: Boolean = false
5332+
5333+
/** Whether it is currently expanding bounds
5334+
*
5335+
* It is used to avoid following LazyRef in F-Bounds
5336+
*/
5337+
def isExpandingBounds: Boolean = expandingBounds
5338+
53315339
protected def expandBounds(tp: TypeBounds): Type =
5332-
range(atVariance(-variance)(reapply(tp.lo)), reapply(tp.hi))
5340+
if expandingBounds then tp
5341+
else {
5342+
val saved = expandingBounds
5343+
expandingBounds = true
5344+
val res = range(atVariance(-variance)(reapply(tp.lo)), reapply(tp.hi))
5345+
expandingBounds = saved
5346+
res
5347+
}
53335348

53345349
/** Try to widen a named type to its info relative to given prefix `pre`, where possible.
53355350
* The possible cases are listed inline in the code.

Diff for: tests/pos/i11078.scala

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
trait Foo[A <: Foo[A]]
2+
trait FooCreator[A <: Foo[A]] {
3+
def createFoo(): A
4+
}
5+
6+
trait FooWrapper {
7+
type A <: Foo[A]
8+
def foo: A
9+
}
10+
object FooWrapper {
11+
def apply[A0 <: Foo[A0]](toWrap: A0): FooWrapper { type A = A0 } = new FooWrapper {
12+
type A = A0
13+
def foo: A0 = toWrap
14+
}
15+
}
16+
17+
trait FooCreatorWrapper {
18+
type A <: Foo[A]
19+
def fooCreator: FooCreator[A]
20+
}
21+
22+
sealed trait Bar
23+
object Bar {
24+
case class Baz(wrapper: FooCreatorWrapper) extends Bar
25+
}
26+
27+
def process(bar: Bar): FooWrapper = bar match {
28+
case Bar.Baz(wrapper) => FooWrapper(wrapper.fooCreator.createFoo())
29+
}

Diff for: tests/pos/i11078b.scala

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
class Test {
2+
trait Foo[A <: Foo[A]]
3+
4+
trait FooWrapper with self =>
5+
type A <: Foo[A]
6+
def doThing(foo: FooWrapper): FooWrapper { type A = self.A } = ???
7+
end FooWrapper
8+
9+
val foos: scala.Seq[FooWrapper] = ???
10+
val newFoo = foos.foldLeft(??? : FooWrapper)((topFoo, foo) => topFoo.doThing(foo))
11+
}

0 commit comments

Comments
 (0)