diff --git a/compiler/damlc/tests/daml-test-files/ExceptionSemantics.daml b/compiler/damlc/tests/daml-test-files/ExceptionSemantics.daml index 10106db6f7bd..db7433ce166f 100644 --- a/compiler/damlc/tests/daml-test-files/ExceptionSemantics.daml +++ b/compiler/damlc/tests/daml-test-files/ExceptionSemantics.daml @@ -2,6 +2,7 @@ -- SPDX-License-Identifier: Apache-2.0 -- @SINCE-LF-FEATURE DAML_EXCEPTIONS +-- @ERROR range=145:1-145:11; Attempt to exercise a consumed contract module ExceptionSemantics where import DA.Exception (throw) @@ -33,6 +34,14 @@ template T catch E -> pure () + nonconsuming choice UncatchableTry : () + with + cid : ContractId K + controller p + do try (() <$ fetch cid) + catch + E -> pure() + nonconsuming choice TransientDuplicate : () with i : Int @@ -132,3 +141,12 @@ divulgence = scenario do submit p1 $ exercise divulger (RollbackFetch cid) submit p2 $ exercise fetcher (Fetch cid) pure () + +tryContext = scenario do + p <- getParty "p" + kCid <- submit p $ create (K p 0) + submit p $ archive kCid + c <- submit p $ create (T p) + -- This will result in a partial transaction with ptx.context.info + -- pointing to a TryContextInfo. + submit p $ exercise c (UncatchableTry kCid) diff --git a/compiler/scenario-service/server/src/main/scala/com/digitalasset/daml/lf/scenario/Conversions.scala b/compiler/scenario-service/server/src/main/scala/com/digitalasset/daml/lf/scenario/Conversions.scala index c453d10657c2..1ac88bbd7d95 100644 --- a/compiler/scenario-service/server/src/main/scala/com/digitalasset/daml/lf/scenario/Conversions.scala +++ b/compiler/scenario-service/server/src/main/scala/com/digitalasset/daml/lf/scenario/Conversions.scala @@ -11,6 +11,7 @@ import com.daml.lf.transaction.{GlobalKey, Node => N, NodeId} import com.daml.lf.ledger._ import com.daml.lf.value.{Value => V} +import scala.annotation.tailrec import scala.jdk.CollectionConverters._ final class Conversions( @@ -416,19 +417,23 @@ final class Conversions( ptx.context.children.toImmArray.toSeq.sortBy(_.index).map(convertTxNodeId).asJava ) - ptx.context.info match { - case ctx: SPartialTransaction.ExercisesContextInfo => - val ecBuilder = proto.ExerciseContext.newBuilder - .setTargetId(mkContractRef(ctx.targetId, ctx.templateId)) - .setChoiceId(ctx.choiceId) - .setChosenValue(convertValue(ctx.chosenValue)) - ctx.optLocation.map(loc => ecBuilder.setExerciseLocation(convertLocation(loc))) - builder.setExerciseContext(ecBuilder.build) - case _: SPartialTransaction.TryContextInfo => - // TODO: https://github.com/digital-asset/daml/issues/8020 - // handle catch context - sys.error("exception not supported") - case _: SPartialTransaction.RootContextInfo => + @tailrec + def unwindToExercise( + contextInfo: SPartialTransaction.ContextInfo + ): Option[SPartialTransaction.ExercisesContextInfo] = contextInfo match { + case ctx: SPartialTransaction.ExercisesContextInfo => Some(ctx) + case ctx: SPartialTransaction.TryContextInfo => + unwindToExercise(ctx.parent.info) + case _: SPartialTransaction.RootContextInfo => None + } + + unwindToExercise(ptx.context.info).foreach { ctx => + val ecBuilder = proto.ExerciseContext.newBuilder + .setTargetId(mkContractRef(ctx.targetId, ctx.templateId)) + .setChoiceId(ctx.choiceId) + .setChosenValue(convertValue(ctx.chosenValue)) + ctx.optLocation.map(loc => ecBuilder.setExerciseLocation(convertLocation(loc))) + builder.setExerciseContext(ecBuilder.build) } builder.build }