@@ -1310,12 +1310,14 @@ class CheckCaptures extends Recheck, SymTransformer:
13101310 testAdapted(actual, expected, tree, addenda)(err.typeMismatch)
13111311
13121312 @ annotation.tailrec
1313- private def widenNamed (tp : Type )(using Context ): Type = tp match
1314- case stp : SingletonType => widenNamed(stp.widen)
1315- case ntp : NamedType => ntp.info match
1316- case info : TypeBounds => widenNamed(info.hi)
1317- case _ => tp
1318- case _ => tp
1313+ private def findImpureUpperBound (tp : Type )(using Context ): Type = tp match
1314+ case _ : SingletonType => findImpureUpperBound(tp.widen)
1315+ case tp : TypeRef if tp.symbol.isAbstractOrParamType =>
1316+ tp.info match
1317+ case TypeBounds (_, hi) if hi.isBoxedCapturing => hi
1318+ case TypeBounds (_, hi) => findImpureUpperBound(hi)
1319+ case _ => NoType
1320+ case _ => NoType
13191321
13201322 inline def testAdapted (actual : Type , expected : Type , tree : Tree , addenda : Addenda )
13211323 (fail : (Tree , Type , Addenda ) => Unit )(using Context ): Type =
@@ -1332,7 +1334,8 @@ class CheckCaptures extends Recheck, SymTransformer:
13321334 //
13331335 // Therefore, when the expected type is a selection proto, we conservatively widen
13341336 // the actual type to strip type parameters.
1335- widenNamed(actual)
1337+ val hi = findImpureUpperBound(actual)
1338+ if ! hi.exists then actual else hi
13361339 else actual
13371340 val actualBoxed = adapt(actual1, expected1, tree)
13381341 // println(i"check conforms $actualBoxed <<< $expected1")
@@ -1357,8 +1360,8 @@ class CheckCaptures extends Recheck, SymTransformer:
13571360 * In those cases, we widen such types and try box adaptation another time.
13581361 */
13591362 def tryWidenNamed : Boolean =
1360- val actual1 = widenNamed (actual)
1361- ( actual1 ne actual) && {
1363+ val actual1 = findImpureUpperBound (actual)
1364+ actual1.exists && {
13621365 val actualBoxed1 = adapt(actual1, expected1, tree)
13631366 isCompatible(actualBoxed1, expected1)
13641367 }
0 commit comments