@@ -1568,17 +1568,81 @@ class CheckCaptures extends Recheck, SymTransformer:
15681568     *  to narrow to the read-only set, since that set can be propagated 
15691569     *  by the type variable instantiation. 
15701570     */  
1571-     private  def  improveReadOnly (actual : Type , expected : Type )(using  Context ):  Type  =  actual match 
1572-       case  actual @  CapturingType (parent, refs)
1573-       if  parent.derivesFrom(defn.Caps_Mutable )
1574-           &&  expected.isValueType
1575-           &&  ! expected.derivesFromMutable
1576-           &&  ! expected.isSingleton
1577-           &&  ! expected.isBoxedCapturing => 
1578-         actual.derivedCapturingType(parent, refs.readOnly)
1579-           .showing(i " improv ro  $actual vs  $expected =  $result" , capt)
1571+     private  def  improveReadOnly (actual : Type , expected : Type )(using  Context ):  Type  =  reporting.trace(i " improv ro  $actual vs  $expected" ): 
1572+       actual.dealiasKeepAnnots match 
1573+       case  actual @  CapturingType (parent, refs) => 
1574+         val  parent1  =  improveReadOnly(parent, expected)
1575+         val  refs1  = 
1576+           if  parent1.derivesFrom(defn.Caps_Mutable )
1577+               &&  expected.isValueType
1578+               &&  (! expected.derivesFromMutable ||  expected.captureSet.isAlwaysReadOnly)
1579+               &&  ! expected.isSingleton
1580+               &&  actual.isBoxedCapturing ==  expected.isBoxedCapturing
1581+           then  refs.readOnly
1582+           else  refs
1583+         actual.derivedCapturingType(parent1, refs1)
1584+       case  actual @  FunctionOrMethod (aargs, ares) => 
1585+         expected.dealias.stripCapturing match 
1586+           case  FunctionOrMethod (eargs, eres) => 
1587+             actual.derivedFunctionOrMethod(aargs, improveReadOnly(ares, eres))
1588+           case  _ => 
1589+             actual
1590+       case  actual @  AppliedType (atycon, aargs) => 
1591+         def  improveArgs (aargs : List [Type ], eargs : List [Type ], formals : List [ParamInfo ]):  List [Type ] = 
1592+           aargs match 
1593+             case  aargs @  (aarg ::  aargs1) => 
1594+               val  aarg1  = 
1595+                 if  formals.head.paramVariance.is(Covariant )
1596+                 then  improveReadOnly(aarg, eargs.head)
1597+                 else  aarg
1598+               aargs.derivedCons(aarg1, improveArgs(aargs1, eargs.tail, formals.tail))
1599+             case  Nil  => 
1600+               aargs
1601+         val  expected1  =  expected.dealias.stripCapturing
1602+         val  esym  =  expected1.typeSymbol
1603+         expected1 match 
1604+           case  AppliedType (etycon, eargs) => 
1605+             if  atycon.typeSymbol ==  esym then 
1606+               actual.derivedAppliedType(atycon,
1607+                 improveArgs(aargs, eargs, etycon.typeParams))
1608+             else  if  esym.isClass then 
1609+               //  This case is tricky: Try to lift actual to the base type with class `esym`,
1610+               //  improve the resulting arguments, and figure out if anything can be
1611+               //  deduced from that for the original arguments.
1612+               actual.baseType(esym) match 
1613+                 case  base @  AppliedType (_, bargs) => 
1614+                   //  If any of the base type arguments can be improved, check
1615+                   //  whether they are the same as an original argument, and in this
1616+                   //  case improve the original argument.
1617+                   val  iargs  =  improveArgs(bargs, eargs, etycon.typeParams)
1618+                   if  iargs ne bargs then 
1619+                     val  updates  = 
1620+                       for 
1621+                         (barg, iarg) <-  bargs.lazyZip(iargs)
1622+                         if  barg ne iarg
1623+                         aarg <-  aargs.find(_ eq barg)
1624+                       yield  (aarg, iarg)
1625+                     if  updates.nonEmpty then  AppliedType (atycon, aargs.map(updates.toMap))
1626+                     else  actual
1627+                   else  actual
1628+                 case  _ =>  actual
1629+             else  actual
1630+           case  _ => 
1631+             actual
1632+       case  actual @  RefinedType (aparent, aname, ainfo) => 
1633+         expected.dealias.stripCapturing match 
1634+           case  RefinedType (eparent, ename, einfo) if  aname ==  ename => 
1635+             actual.derivedRefinedType(
1636+               improveReadOnly(aparent, eparent),
1637+               aname,
1638+               improveReadOnly(ainfo, einfo))
1639+           case  _ => 
1640+             actual
1641+       case  actual @  AnnotatedType (parent, ann) => 
1642+         actual.derivedAnnotatedType(improveReadOnly(parent, expected), ann)
15801643      case  _ => 
15811644        actual
1645+     end  improveReadOnly 
15821646
15831647    /*  Currently not needed since it forms part of `adapt`
15841648    private def improve(actual: Type, prefix: Type)(using Context): Type = 
0 commit comments