Skip to content

Commit b664d2c

Browse files
Backport "Improve ConstraintHandling of SkolemTypes" to LTS (#21063)
Backports #20175 to the LTS branch. PR submitted by the release tooling. [skip ci]
2 parents d8efa12 + 3097d67 commit b664d2c

File tree

5 files changed

+84
-2
lines changed

5 files changed

+84
-2
lines changed

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

+15-2
Original file line numberDiff line numberDiff line change
@@ -5760,6 +5760,10 @@ object Types extends TypeUtils {
57605760
variance = saved
57615761
derivedLambdaType(tp)(ptypes1, this(restpe))
57625762

5763+
protected def mapOverTypeVar(tp: TypeVar) =
5764+
val inst = tp.instanceOpt
5765+
if (inst.exists) apply(inst) else tp
5766+
57635767
def isRange(tp: Type): Boolean = tp.isInstanceOf[Range]
57645768

57655769
protected def mapCapturingType(tp: Type, parent: Type, refs: CaptureSet, v: Int): Type =
@@ -5797,8 +5801,7 @@ object Types extends TypeUtils {
57975801
derivedTypeBounds(tp, lo1, this(tp.hi))
57985802

57995803
case tp: TypeVar =>
5800-
val inst = tp.instanceOpt
5801-
if (inst.exists) apply(inst) else tp
5804+
mapOverTypeVar(tp)
58025805

58035806
case tp: ExprType =>
58045807
derivedExprType(tp, this(tp.resultType))
@@ -6208,6 +6211,16 @@ object Types extends TypeUtils {
62086211
else
62096212
super.mapCapturingType(tp, parent, refs, v)
62106213

6214+
override protected def mapOverTypeVar(tp: TypeVar) =
6215+
val inst = tp.instanceOpt
6216+
if !inst.exists then tp
6217+
else
6218+
// We can keep the original type var if its instance is not transformed
6219+
// by the ApproximatingTypeMap. This allows for simpler bounds and for
6220+
// derivedSkolemType to retain more skolems, by keeping the info unchanged.
6221+
val res = apply(inst)
6222+
if res eq inst then tp else res
6223+
62116224
protected def reapply(tp: Type): Type = apply(tp)
62126225
}
62136226

compiler/test/dotc/pos-test-pickling.blacklist

+3
Original file line numberDiff line numberDiff line change
@@ -109,4 +109,7 @@ i7445b.scala
109109

110110
# more aggresive reduce projection makes a difference
111111
i15525.scala
112+
i19955a.scala
113+
i19955b.scala
114+
i20053b.scala
112115

tests/pos/i19955a.scala

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
2+
trait Summon[R, T <: R]:
3+
type Out
4+
object Summon:
5+
given [R, T <: R]: Summon[R, T] with
6+
type Out = R
7+
8+
trait DFTypeAny
9+
trait DFBits[W <: Int] extends DFTypeAny
10+
class DFVal[+T <: DFTypeAny]
11+
type DFValAny = DFVal[DFTypeAny]
12+
type DFValOf[+T <: DFTypeAny] = DFVal[T]
13+
trait Candidate[R]:
14+
type OutW <: Int
15+
object Candidate:
16+
type Aux[R, O <: Int] = Candidate[R] { type OutW = O }
17+
given [W <: Int, R <: DFValOf[DFBits[W]]]: Candidate[R] with
18+
type OutW = W
19+
20+
extension [L](lhs: L) def foo(using es: Summon[L, lhs.type]): Unit = ???
21+
extension [L <: DFValAny](lhs: L)(using icL: Candidate[L]) def baz: DFValOf[DFBits[icL.OutW]] = ???
22+
extension [L <: DFValAny, W <: Int](lhs: L)(using icL: Candidate.Aux[L, W])
23+
def bazAux: DFValOf[DFBits[W]] = ???
24+
25+
val x = new DFVal[DFBits[4]]
26+
val works = x.bazAux.foo
27+
val fails = x.baz.foo

tests/pos/i19955b.scala

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
2+
trait Wrap[W]
3+
4+
trait IsWrapOfInt[R]:
5+
type Out <: Int
6+
given [W <: Int, R <: Wrap[W]]: IsWrapOfInt[R] with
7+
type Out = Int
8+
9+
trait IsInt[U <: Int]
10+
given [U <: Int]: IsInt[U] = ???
11+
12+
extension [L](lhs: L) def get(using ev: IsWrapOfInt[L]): ev.Out = ???
13+
extension (lhs: Int) def isInt(using IsInt[lhs.type]): Unit = ???
14+
15+
val x: Wrap[Int] = ???
16+
val works = (x.get: Int).isInt
17+
val fails = x.get.isInt

tests/pos/i20053b.scala

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
trait Sub[R, T >: R]
3+
given [R, T >: R]: Sub[R, T] with {}
4+
5+
trait Candidate[-R]:
6+
type OutP
7+
given [P]: Candidate[Option[P]] with
8+
type OutP = P
9+
10+
extension [L](lhs: L)
11+
def ^^^[P](rhs: Option[P])
12+
(using es: Sub[lhs.type, Any])
13+
(using c: Candidate[L])
14+
(using check: c.type <:< Any): Option[c.OutP] = ???
15+
16+
val x: Option[Boolean] = ???
17+
18+
val z1 = x ^^^ x // Ok
19+
val z2 = z1 ^^^ x // Ok
20+
val zz = ^^^[Option[Boolean]](x ^^^ x)(x) // Ok
21+
22+
val zzz = x ^^^ x ^^^ x // Error before changes

0 commit comments

Comments
 (0)