Skip to content

Commit 3667ab8

Browse files
committed
Don't box arguments of any form of type cast or test
Previously, only asInstanceOf was excluded.
1 parent cc95088 commit 3667ab8

File tree

5 files changed

+33
-6
lines changed

5 files changed

+33
-6
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,7 @@ extension (sym: Symbol)
573573
&& sym != defn.Caps_unsafeBox
574574
&& sym != defn.Caps_unsafeUnbox
575575
&& !defn.isPolymorphicAfterErasure(sym)
576+
&& !defn.isTypeTestOrCast(sym)
576577

577578
def isRefiningParamAccessor(using Context): Boolean =
578579
sym.is(ParamAccessor)

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,17 @@ class CheckCaptures extends Recheck, SymTransformer:
563563
* The implementation picks `C` as `Cq` instead of `Cr`, if
564564
* 1. The argument(s) Ta are always pure
565565
* 2. `Cq` might subcapture `Cr`.
566+
* TODO: We could generalize this as follows:
567+
*
568+
* If the function `f` does not have an `@unboxed` parameter, then
569+
* any unboxing it does would be charged to the environment of the function
570+
* so they have to appear in Cq. So another approximation of the
571+
* result capability set is `Cq u Ca` where `Ca` is the capture set of the
572+
* argument.
573+
* If the function `f` does have an `@unboxed` parameter, then it could in addition
574+
* unbox reach capabilities over its formal parameter. Therefore, the approximation
575+
* would be `Cq u dcs(Ca)` instead.
576+
* If the approximation is known to subcapture the declared result Cr, we pick it.
566577
*/
567578
protected override
568579
def recheckApplication(tree: Apply, qualType: Type, funType: MethodType, argTypes: List[Type])(using Context): Type =

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

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -439,12 +439,9 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
439439

440440
case tree @ TypeApply(fn, args) =>
441441
traverse(fn)
442-
fn match
443-
case Select(qual, nme.asInstanceOf_) =>
444-
// No need to box type arguments of an asInstanceOf call. See #20224.
445-
case _ =>
446-
for case arg: TypeTree <- args do
447-
transformTT(arg, boxed = true, exact = false) // type arguments in type applications are boxed
442+
if !defn.isTypeTestOrCast(fn.symbol) then
443+
for case arg: TypeTree <- args do
444+
transformTT(arg, boxed = true, exact = false) // type arguments in type applications are boxed
448445

449446
case tree: TypeDef if tree.symbol.isClass =>
450447
val sym = tree.symbol

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1768,6 +1768,12 @@ class Definitions {
17681768
def isPolymorphicAfterErasure(sym: Symbol): Boolean =
17691769
(sym eq Any_isInstanceOf) || (sym eq Any_asInstanceOf) || (sym eq Object_synchronized)
17701770

1771+
def isTypeTestOrCast(sym: Symbol): Boolean =
1772+
(sym eq Any_isInstanceOf)
1773+
|| (sym eq Any_asInstanceOf)
1774+
|| (sym eq Any_typeTest)
1775+
|| (sym eq Any_typeCast)
1776+
17711777
/** Is this type a `TupleN` type?
17721778
*
17731779
* @return true if the dealiased type of `tp` is `TupleN[T1, T2, ..., Tn]`
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
trait Async extends caps.Capability:
2+
def group: Int
3+
4+
object Async:
5+
inline def current(using async: Async): async.type = async
6+
opaque type Spawn <: Async = Async
7+
def blocking[T](f: Spawn => T): T = ???
8+
9+
def main() =
10+
Async.blocking: spawn =>
11+
val c = Async.current(using spawn)
12+
val a = c.group

0 commit comments

Comments
 (0)