From 63146b4a60f89a4b3bdadcb241127a1671b0f949 Mon Sep 17 00:00:00 2001 From: odersky Date: Wed, 28 Feb 2024 22:20:47 +0100 Subject: [PATCH 1/2] Fix Function tree copier It did not copy correctly instances of the FunctionWithMods subclass. Fixes #19751 --- compiler/src/dotty/tools/dotc/ast/Trees.scala | 9 ++++---- compiler/src/dotty/tools/dotc/ast/untpd.scala | 6 ++++- tests/pos-custom-args/captures/i19751.scala | 22 +++++++++++++++++++ 3 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 tests/pos-custom-args/captures/i19751.scala diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 4ec41b95a90b..05adedabf43b 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -1254,11 +1254,12 @@ object Trees { case _ => finalize(tree, untpd.Ident(name)(sourceFile(tree))) } def Select(tree: Tree)(qualifier: Tree, name: Name)(using Context): Select = tree match { - case tree: SelectWithSig => - if ((qualifier eq tree.qualifier) && (name == tree.name)) tree - else finalize(tree, SelectWithSig(qualifier, name, tree.sig)(sourceFile(tree))) case tree: Select if (qualifier eq tree.qualifier) && (name == tree.name) => tree - case _ => finalize(tree, untpd.Select(qualifier, name)(sourceFile(tree))) + case _ => + val tree1 = tree match + case tree: SelectWithSig => untpd.SelectWithSig(qualifier, name, tree.sig)(using sourceFile(tree)) + case _ => untpd.Select(qualifier, name)(using sourceFile(tree)) + finalize(tree, tree1) } /** Copy Ident or Select trees */ def Ref(tree: RefTree)(name: Name)(using Context): RefTree = tree match { diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala index aabfdd97d7bd..8afcfd9c6ac3 100644 --- a/compiler/src/dotty/tools/dotc/ast/untpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala @@ -609,7 +609,11 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { } def Function(tree: Tree)(args: List[Tree], body: Tree)(using Context): Tree = tree match { case tree: Function if (args eq tree.args) && (body eq tree.body) => tree - case _ => finalize(tree, untpd.Function(args, body)(tree.source)) + case _ => + val tree1 = tree match + case tree: FunctionWithMods => untpd.FunctionWithMods(args, body, tree.mods, tree.erasedParams)(using tree.source) + case _ => untpd.Function(args, body)(using tree.source) + finalize(tree, tree1) } def PolyFunction(tree: Tree)(targs: List[Tree], body: Tree)(using Context): Tree = tree match { case tree: PolyFunction if (targs eq tree.targs) && (body eq tree.body) => tree diff --git a/tests/pos-custom-args/captures/i19751.scala b/tests/pos-custom-args/captures/i19751.scala new file mode 100644 index 000000000000..b6023cc0ff87 --- /dev/null +++ b/tests/pos-custom-args/captures/i19751.scala @@ -0,0 +1,22 @@ +import language.experimental.captureChecking +import annotation.capability +import caps.cap + +trait Ptr[A] +@capability trait Scope: + def allocate(size: Int): Ptr[Unit]^{this} + + +object Scope: + def confined[A](fn: Scope ?->{cap} A): A = + val scope = new Scope: + def allocate(size: Int) = new Ptr[Unit] {} + fn(using scope) + +def Test: Unit = + val s = Scope.confined: + val s2 = summon[Scope] + Scope.confined: + s2.allocate(5) + 5 + From cd68604247c56524631e841a93cfac89c2377cc6 Mon Sep 17 00:00:00 2001 From: odersky Date: Thu, 29 Feb 2024 11:13:19 +0100 Subject: [PATCH 2/2] Use fixed copying instead of writing code out --- compiler/src/dotty/tools/dotc/ast/Desugar.scala | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 9591bc5a93f0..53287465614a 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -1978,10 +1978,7 @@ object desugar { val applyVParams = args.zipWithIndex.map { case (p, n) => makeSyntheticParameter(n + 1, p) } - tree match - case tree: FunctionWithMods => - untpd.FunctionWithMods(applyVParams, result, tree.mods, tree.erasedParams) - case _ => untpd.Function(applyVParams, result) + cpy.Function(tree)(applyVParams, result).asInstanceOf[untpd.Function] } }