Skip to content

Commit a0cbb87

Browse files
committed
Treat bounds of type variables as boxed
1 parent 84c1b24 commit a0cbb87

File tree

5 files changed

+32
-7
lines changed

5 files changed

+32
-7
lines changed

compiler/src/dotty/tools/dotc/cc/CaptureOps.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ extension (tp: Type)
6767
case _ =>
6868
tp
6969

70+
/** If `sym` is a type parameter, the boxed version of `tp`, otherwise `tp` */
71+
def boxedIfTypeParam(sym: Symbol)(using Context) =
72+
if sym.is(TypeParam) then tp.boxed else tp
73+
7074
/** The boxed version of `tp`, unless `tycon` is a function symbol */
7175
def boxedUnlessFun(tycon: Type)(using Context) =
7276
if ctx.phase != Phases.checkCapturesPhase || defn.isFunctionSymbol(tycon.typeSymbol)

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import typer.ProtoTypes.constrained
2323
import typer.Applications.productSelectorTypes
2424
import reporting.trace
2525
import annotation.constructorOnly
26-
import cc.{CapturingType, derivedCapturingType, CaptureSet, stripCapturing, isBoxedCapturing, boxedUnlessFun}
26+
import cc.{CapturingType, derivedCapturingType, CaptureSet, stripCapturing, isBoxedCapturing, boxed, boxedUnlessFun, boxedIfTypeParam}
2727

2828
/** Provides methods to compare types.
2929
*/
@@ -426,7 +426,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
426426
case tp2: TypeParamRef => constraint.isLess(tp1, tp2)
427427
case _ => false
428428
} ||
429-
isSubTypeWhenFrozen(bounds(tp1).hi, tp2) || {
429+
isSubTypeWhenFrozen(bounds(tp1).hi.boxed, tp2) || {
430430
if (canConstrain(tp1) && !approx.high)
431431
addConstraint(tp1, tp2, fromBelow = false) && flagNothingBound
432432
else thirdTry
@@ -547,7 +547,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
547547
|| narrowGADTBounds(tp2, tp1, approx, isUpper = false))
548548
&& (isBottom(tp1) || GADTusage(tp2.symbol))
549549

550-
isSubApproxHi(tp1, info2.lo) && (trustBounds || isSubApproxHi(tp1, info2.hi))
550+
isSubApproxHi(tp1, info2.lo.boxedIfTypeParam(tp2.symbol)) && (trustBounds || isSubApproxHi(tp1, info2.hi))
551551
|| compareGADT
552552
|| tryLiftedToThis2
553553
|| fourthTry
@@ -586,7 +586,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
586586
// So if the constraint is not yet frozen, we do the same comparison again
587587
// with a frozen constraint, which means that we get a chance to do the
588588
// widening in `fourthTry` before adding to the constraint.
589-
if (frozenConstraint) recur(tp1, bounds(tp2).lo)
589+
if (frozenConstraint) recur(tp1, bounds(tp2).lo.boxed)
590590
else isSubTypeWhenFrozen(tp1, tp2)
591591
alwaysTrue || {
592592
if (canConstrain(tp2) && !approx.low)
@@ -832,7 +832,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
832832
}
833833

834834
def tryBaseType(cls2: Symbol) = {
835-
val base = nonExprBaseType(tp1, cls2)
835+
val base = nonExprBaseType(tp1, cls2).boxedIfTypeParam(tp1.typeSymbol)
836836
if base.exists && (base ne tp1)
837837
&& (!caseLambda.exists || canWidenAbstract || tp1.widen.underlyingClassRef(refinementOK = true).exists)
838838
then
@@ -856,7 +856,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
856856
&& (tp2.isAny || GADTusage(tp1.symbol))
857857

858858
(!caseLambda.exists || canWidenAbstract)
859-
&& isSubType(hi1, tp2, approx.addLow) && (trustBounds || isSubType(lo1, tp2, approx.addLow))
859+
&& isSubType(hi1.boxedIfTypeParam(tp1.symbol), tp2, approx.addLow) && (trustBounds || isSubType(lo1, tp2, approx.addLow))
860860
|| compareGADT
861861
|| tryLiftedToThis1
862862
case _ =>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/eta.scala:4:9 --------------------------------------------
2+
4 | g // error
3+
| ^
4+
| Found: (g : () -> A)
5+
| Required: () -> {f} Proc
6+
|
7+
| longer explanation available when compiling with `-explain`
8+
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/eta.scala:6:14 -------------------------------------------
9+
6 | bar( () => f ) // error
10+
| ^^^^^^^
11+
| Found: {f} () -> box {f} () -> Unit
12+
| Required: () -> box ? () -> Unit
13+
|
14+
| longer explanation available when compiling with `-explain`
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
type Proc = (() -> Unit)
22
def foo(f: {*} Proc): {} Proc =
33
def bar[A <: {f} Proc](g: () -> A): () -> {f} Proc =
4-
g
4+
g // error
55
val stowaway: () -> {f} Proc =
66
bar( () => f ) // error
77
() => { stowaway.apply().apply() }
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
class A
2+
3+
def test(x: {*} Any) =
4+
abstract class Getter:
5+
def get(): {x} A
6+
class PolyGetter[T <: {x} A] extends Getter:
7+
override def get(): T = ??? // error

0 commit comments

Comments
 (0)