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