From 3b5f8a73e16d24c0c53ecf1c10efad47bd538d41 Mon Sep 17 00:00:00 2001 From: Moritz Kiefer Date: Thu, 18 Nov 2021 17:10:40 +0100 Subject: [PATCH] Remove precondition field from TemplateImplements (#11763) * Remove precondition field from TemplateImplements fixes #11635 changelog_begin changelog_end * Update daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Compiler.scala Co-authored-by: Remy Co-authored-by: Remy --- .../daml-lf-ast/src/DA/Daml/LF/Ast/Base.hs | 1 - .../daml-lf-ast/src/DA/Daml/LF/Ast/Optics.hs | 3 +- .../daml-lf-ast/src/DA/Daml/LF/Ast/Pretty.hs | 3 +- .../src/DA/Daml/LF/Proto3/DecodeV1.hs | 1 - .../src/DA/Daml/LF/Proto3/EncodeV1.hs | 1 - .../daml-lf-tools/src/DA/Daml/LF/Completer.hs | 5 +-- .../src/DA/Daml/LFConversion.hs | 3 +- .../InterfacePrecondition.daml | 6 +-- .../com/daml/daml_lf_dev/daml_lf_1.proto | 1 - .../daml/lf/archive/DecodeV1.scala | 1 - .../daml/lf/speedy/Compiler.scala | 42 +++++++++++++------ .../digitalasset/daml/lf/speedy/Profile.scala | 1 + .../digitalasset/daml/lf/speedy/SExpr.scala | 1 + .../digitalasset/daml/lf/language/Ast.scala | 11 ++--- .../digitalasset/daml/lf/language/Util.scala | 3 +- .../daml/lf/testing/parser/AstRewriter.scala | 2 - .../lf/validation/iterable/ExprIterable.scala | 3 +- .../lf/validation/iterable/TypeIterable.scala | 3 +- 18 files changed, 46 insertions(+), 45 deletions(-) diff --git a/compiler/daml-lf-ast/src/DA/Daml/LF/Ast/Base.hs b/compiler/daml-lf-ast/src/DA/Daml/LF/Ast/Base.hs index 4448a2aa6e94..b3115f3d247b 100644 --- a/compiler/daml-lf-ast/src/DA/Daml/LF/Ast/Base.hs +++ b/compiler/daml-lf-ast/src/DA/Daml/LF/Ast/Base.hs @@ -913,7 +913,6 @@ data TemplateImplements = TemplateImplements , tpiMethods :: !(NM.NameMap TemplateImplementsMethod) , tpiInheritedChoiceNames :: !(S.Set ChoiceName) -- ^ Set of inherited fixed choice names. - , tpiPrecond :: !Expr } deriving (Eq, Data, Generic, NFData, Show) diff --git a/compiler/daml-lf-ast/src/DA/Daml/LF/Ast/Optics.hs b/compiler/daml-lf-ast/src/DA/Daml/LF/Ast/Optics.hs index e8910ec1a2a3..c0480ac4a03c 100644 --- a/compiler/daml-lf-ast/src/DA/Daml/LF/Ast/Optics.hs +++ b/compiler/daml-lf-ast/src/DA/Daml/LF/Ast/Optics.hs @@ -80,11 +80,10 @@ templateExpr f (Template loc tpl param precond signatories observers agreement c <*> (NM.traverse . templateImplementsExpr) f implements templateImplementsExpr :: Traversal' TemplateImplements Expr -templateImplementsExpr f (TemplateImplements iface methods inheritedChoiceNames precond) = +templateImplementsExpr f (TemplateImplements iface methods inheritedChoiceNames) = TemplateImplements iface <$> (NM.traverse . templateImplementsMethodExpr) f methods <*> pure inheritedChoiceNames - <*> f precond templateImplementsMethodExpr :: Traversal' TemplateImplementsMethod Expr templateImplementsMethodExpr f (TemplateImplementsMethod name body) = diff --git a/compiler/daml-lf-ast/src/DA/Daml/LF/Ast/Pretty.hs b/compiler/daml-lf-ast/src/DA/Daml/LF/Ast/Pretty.hs index 3a0c2532a49f..5b5d98f466f5 100644 --- a/compiler/daml-lf-ast/src/DA/Daml/LF/Ast/Pretty.hs +++ b/compiler/daml-lf-ast/src/DA/Daml/LF/Ast/Pretty.hs @@ -635,11 +635,10 @@ pPrintTemplate lvl modName (Template mbLoc tpl param precond signatories observe implementsDoc = map (pPrintTemplateImplements lvl) (NM.toList implements) pPrintTemplateImplements :: PrettyLevel -> TemplateImplements -> Doc ann -pPrintTemplateImplements lvl (TemplateImplements name methods inheritedChoices precond) +pPrintTemplateImplements lvl (TemplateImplements name methods inheritedChoices) | NM.null methods = keyword_ "implements" <-> pPrintPrec lvl 0 name | otherwise = vcat $ [ keyword_ "implements" <-> pPrintPrec lvl 0 name <-> keyword_ "where" - , nest 2 (keyword_ "ensure" <-> pPrintPrec lvl 0 precond) , nest 2 (keyword_ "inherits" <-> pPrintPrec lvl 0 (S.toList inheritedChoices)) ] ++ map (nest 2 . pPrintTemplateImplementsMethod lvl) (NM.toList methods) diff --git a/compiler/daml-lf-proto/src/DA/Daml/LF/Proto3/DecodeV1.hs b/compiler/daml-lf-proto/src/DA/Daml/LF/Proto3/DecodeV1.hs index bf1917b566f5..6da7291f296a 100644 --- a/compiler/daml-lf-proto/src/DA/Daml/LF/Proto3/DecodeV1.hs +++ b/compiler/daml-lf-proto/src/DA/Daml/LF/Proto3/DecodeV1.hs @@ -329,7 +329,6 @@ decodeDefTemplateImplements LF1.DefTemplate_Implements{..} = TemplateImplements <$> mayDecode "defTemplate_ImplementsInterface" defTemplate_ImplementsInterface decodeTypeConName <*> decodeNM DuplicateMethod decodeDefTemplateImplementsMethod defTemplate_ImplementsMethods <*> decodeSet DuplicateChoice (decodeNameId ChoiceName) defTemplate_ImplementsInheritedChoiceInternedNames - <*> mayDecode "defTemplate_ImplementsPrecondition" defTemplate_ImplementsPrecond decodeExpr decodeDefTemplateImplementsMethod :: LF1.DefTemplate_ImplementsMethod -> Decode TemplateImplementsMethod decodeDefTemplateImplementsMethod LF1.DefTemplate_ImplementsMethod{..} = TemplateImplementsMethod diff --git a/compiler/daml-lf-proto/src/DA/Daml/LF/Proto3/EncodeV1.hs b/compiler/daml-lf-proto/src/DA/Daml/LF/Proto3/EncodeV1.hs index 2378f0b2c8f0..023ff66173e2 100644 --- a/compiler/daml-lf-proto/src/DA/Daml/LF/Proto3/EncodeV1.hs +++ b/compiler/daml-lf-proto/src/DA/Daml/LF/Proto3/EncodeV1.hs @@ -938,7 +938,6 @@ encodeTemplateImplements TemplateImplements{..} = do defTemplate_ImplementsInterface <- encodeQualTypeConName tpiInterface defTemplate_ImplementsMethods <- encodeNameMap encodeTemplateImplementsMethod tpiMethods defTemplate_ImplementsInheritedChoiceInternedNames <- encodeSet (encodeNameId unChoiceName) tpiInheritedChoiceNames - defTemplate_ImplementsPrecond <- encodeExpr tpiPrecond pure P.DefTemplate_Implements {..} encodeTemplateImplementsMethod :: TemplateImplementsMethod -> Encode P.DefTemplate_ImplementsMethod diff --git a/compiler/daml-lf-tools/src/DA/Daml/LF/Completer.hs b/compiler/daml-lf-tools/src/DA/Daml/LF/Completer.hs index 8b2fda0f50ae..e2dddc2a7543 100644 --- a/compiler/daml-lf-tools/src/DA/Daml/LF/Completer.hs +++ b/compiler/daml-lf-tools/src/DA/Daml/LF/Completer.hs @@ -32,6 +32,5 @@ completeTemplateImplements :: LF.World -> LF.TemplateImplements -> LF.TemplateIm completeTemplateImplements world tpi@TemplateImplements{..} = case lookupInterface tpiInterface world of Left _ -> error ("Could not find interface " <> T.unpack (T.intercalate "." (unTypeConName (qualObject tpiInterface)))) - Right DefInterface { intFixedChoices, intPrecondition } -> - tpi { tpiInheritedChoiceNames = S.fromList (NM.names intFixedChoices) - , tpiPrecond = intPrecondition} + Right DefInterface { intFixedChoices } -> + tpi { tpiInheritedChoiceNames = S.fromList (NM.names intFixedChoices) } diff --git a/compiler/damlc/daml-lf-conversion/src/DA/Daml/LFConversion.hs b/compiler/damlc/daml-lf-conversion/src/DA/Daml/LFConversion.hs index 17648ebb83eb..10488c7df1a1 100644 --- a/compiler/damlc/daml-lf-conversion/src/DA/Daml/LFConversion.hs +++ b/compiler/damlc/daml-lf-conversion/src/DA/Daml/LFConversion.hs @@ -975,8 +975,7 @@ convertImplements env tplTypeCon = NM.fromList <$> , Just methodName <- [T.stripPrefix "m_" fieldName] ] let inheritedChoiceNames = S.empty -- This is filled during LF post-processing (in the LF completer). - let precond = ETrue -- This is filled during LF post-processing (in the LF completer). - pure (TemplateImplements con methods inheritedChoiceNames precond) + pure (TemplateImplements con methods inheritedChoiceNames) convertChoices :: Env -> LF.TypeConName -> TemplateBinds -> ConvertM (NM.NameMap TemplateChoice) convertChoices env tplTypeCon tbinds = diff --git a/compiler/damlc/tests/daml-test-files/InterfacePrecondition.daml b/compiler/damlc/tests/daml-test-files/InterfacePrecondition.daml index d9de7a8affe9..33dfb35ed9a4 100644 --- a/compiler/damlc/tests/daml-test-files/InterfacePrecondition.daml +++ b/compiler/damlc/tests/daml-test-files/InterfacePrecondition.daml @@ -50,7 +50,7 @@ template Asset where signatory issuer, owner - ensure (amount >= 5 && amount <= 6) + ensure (amount >= 5 && amount <= 8) implements Token1 where let getOwner1 = owner @@ -95,13 +95,13 @@ main = scenario do create Asset with issuer = p owner = p - amount = 7 -- violates ensure of Asset + amount = 8 -- violates ensure of Asset & Token2 p `submitMustFail` do create Asset with issuer = p owner = p - amount = 8 -- violates ensure of Asset & Token2 + amount = 8 -- violates ensure of Token1 p `submit` do create Asset with diff --git a/daml-lf/archive/src/main/protobuf/com/daml/daml_lf_dev/daml_lf_1.proto b/daml-lf/archive/src/main/protobuf/com/daml/daml_lf_dev/daml_lf_1.proto index 6278147f9629..1a7ee45e13d0 100644 --- a/daml-lf/archive/src/main/protobuf/com/daml/daml_lf_dev/daml_lf_1.proto +++ b/daml-lf/archive/src/main/protobuf/com/daml/daml_lf_dev/daml_lf_1.proto @@ -1459,7 +1459,6 @@ message DefTemplate { repeated ImplementsMethod methods = 2; repeated int32 inherited_choice_interned_names = 3; // ^ inherited fixed choice names as interned strings - Expr precond = 4; } // The type constructor for the template, acting as both diff --git a/daml-lf/archive/src/main/scala/com/digitalasset/daml/lf/archive/DecodeV1.scala b/daml-lf/archive/src/main/scala/com/digitalasset/daml/lf/archive/DecodeV1.scala index 013384ba93c2..fd4a57f3ad28 100644 --- a/daml-lf/archive/src/main/scala/com/digitalasset/daml/lf/archive/DecodeV1.scala +++ b/daml-lf/archive/src/main/scala/com/digitalasset/daml/lf/archive/DecodeV1.scala @@ -610,7 +610,6 @@ private[archive] class DecodeV1(minor: LV.Minor) { inheritedChoices = lfImpl.getInheritedChoiceInternedNamesList.asScala .map(getInternedName(_, "TemplateImplements.inheritedChoices")) .toSet, - precond = decodeExpr(lfImpl.getPrecond, "TemplateImplements.precond"), ) private[this] def decodeTemplateImplementsMethod( diff --git a/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Compiler.scala b/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Compiler.scala index 3ef22156ea36..465818f0318c 100644 --- a/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Compiler.scala +++ b/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Compiler.scala @@ -397,6 +397,7 @@ private[lf] final class Compiler( val identifier = Identifier(pkgId, QualifiedName(module.name, ifaceName)) addDef(compileCreateInterface(identifier)) addDef(compileFetchInterface(identifier)) + addDef(compileInterfacePrecond(identifier, iface.param, iface.precond)) iface.fixedChoices.values.foreach( builder += compileFixedChoice(identifier, iface.param, _) ) @@ -1232,6 +1233,15 @@ private[lf] final class Compiler( } } + private[this] def compileInterfacePrecond( + iface: Identifier, + param: ExprVarName, + expr: Expr, + ) = + topLevelFunction1(t.InterfacePrecondDefRef(iface))((argPos, env) => + compile(env.bindExprVar(param, argPos), expr) + ) + private[this] def compileKey( tmplId: Identifier, tmpl: Template, @@ -1284,23 +1294,29 @@ private[lf] final class Compiler( tmplArgPos: Position, env: Env, ) = { - val precondsArray = - (Iterator(tmpl.precond) ++ (tmpl.implements.iterator.map(impl => impl._2.precond))) - .to(ImmArray) - val preconds = ECons(TBuiltin(BTBool), precondsArray, ENil(TBuiltin(BTBool))) val env2 = env.bindExprVar(tmpl.param, tmplArgPos) + val implementsPrecondsIterator = tmpl.implements.iterator.map[s.SExpr](impl => + // This relies on interfaces having the same representation as the underlying template + t.InterfacePrecondDefRef(impl._1)(env2.toSEVar(tmplArgPos)) + ) + // TODO Clean this up as part of changing how we evaluate these + // https://github.com/digital-asset/daml/issues/11762 + val precondsArray: ImmArray[s.SExpr] = + (Iterator(compile(env2, tmpl.precond)) ++ implementsPrecondsIterator ++ Iterator( + s.SEValue.EmptyList + )).to(ImmArray) + val preconds = s.SEApp(s.SEBuiltin(SBConsMany(precondsArray.length - 1)), precondsArray.toArray) // We check precondition in a separated builtin to prevent // further evaluation of agreement, signatories, observers and key // in case of failed precondition. - let(env2, SBCheckPrecond(tmplId)(env2.toSEVar(tmplArgPos), compile(env2, preconds))) { - (_, env) => - SBUCreate(tmplId, byInterface)( - env.toSEVar(tmplArgPos), - compile(env, tmpl.agreementText), - compile(env, tmpl.signatories), - compile(env, tmpl.observers), - compileKeyWithMaintainers(env, tmpl.key), - ) + let(env2, SBCheckPrecond(tmplId)(env2.toSEVar(tmplArgPos), preconds)) { (_, env) => + SBUCreate(tmplId, byInterface)( + env.toSEVar(tmplArgPos), + compile(env, tmpl.agreementText), + compile(env, tmpl.signatories), + compile(env, tmpl.observers), + compileKeyWithMaintainers(env, tmpl.key), + ) } } diff --git a/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Profile.scala b/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Profile.scala index ffe187c4259f..118fcf0241d7 100644 --- a/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Profile.scala +++ b/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Profile.scala @@ -251,6 +251,7 @@ object Profile { implicit val lookupByKeyDefRef: Allowed[LookupByKeyDefRef] = allowAll implicit val createAndExerciseLabel: Allowed[CreateAndExerciseLabel] = allowAll implicit val exceptionMessageDefRef: Allowed[ExceptionMessageDefRef] = allowAll + implicit val interfacePrecondDefRef: Allowed[InterfacePrecondDefRef] = allowAll implicit val scenarioLabel: Allowed[ScenarioLabel] = allowAll implicit val exprVarName: Allowed[Ast.ExprVarName] = allowAll diff --git a/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/SExpr.scala b/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/SExpr.scala index 74a0350b65f2..3dec5da1dd98 100644 --- a/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/SExpr.scala +++ b/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/SExpr.scala @@ -427,6 +427,7 @@ object SExpr { final case class KeyDefRef(ref: DefinitionRef) extends SDefinitionRef final case class SignatoriesDefRef(ref: DefinitionRef) extends SDefinitionRef final case class ObserversDefRef(ref: DefinitionRef) extends SDefinitionRef + final case class InterfacePrecondDefRef(ref: DefinitionRef) extends SDefinitionRef /** ImplementsDefRef(ref=templateId, ifaceId) points to a function that converts a * template value to an interface value. (This is currently an identity function.) diff --git a/daml-lf/language/src/main/scala/com/digitalasset/daml/lf/language/Ast.scala b/daml-lf/language/src/main/scala/com/digitalasset/daml/lf/language/Ast.scala index b54e94e29016..c7b629159ce2 100644 --- a/daml-lf/language/src/main/scala/com/digitalasset/daml/lf/language/Ast.scala +++ b/daml-lf/language/src/main/scala/com/digitalasset/daml/lf/language/Ast.scala @@ -848,7 +848,6 @@ object Ast { interface: TypeConName, methods: Map[MethodName, GenTemplateImplementsMethod[E]], inheritedChoices: Set[ChoiceName], - precond: E, ) final class GenTemplateImplementsCompanion[E] private[Ast] { @@ -856,28 +855,26 @@ object Ast { interface: TypeConName, methods: Iterable[(MethodName, GenTemplateImplementsMethod[E])], inheritedChoices: Iterable[ChoiceName], - precond: E, ): GenTemplateImplements[E] = { val methodMap = toMapWithoutDuplicate( methods, (methodName: MethodName) => throw PackageError(s"repeated method implementation $methodName"), ) - new GenTemplateImplements[E](interface, methodMap, inheritedChoices.toSet, precond) + new GenTemplateImplements[E](interface, methodMap, inheritedChoices.toSet) } def apply( interface: TypeConName, methods: Map[MethodName, GenTemplateImplementsMethod[E]], inheritedChoices: Set[ChoiceName], - precond: E, ): GenTemplateImplements[E] = - GenTemplateImplements[E](interface, methods, inheritedChoices, precond) + GenTemplateImplements[E](interface, methods, inheritedChoices) def unapply( arg: GenTemplateImplements[E] - ): Some[(TypeConName, Map[MethodName, GenTemplateImplementsMethod[E]], Set[ChoiceName], E)] = - Some((arg.interface, arg.methods, arg.inheritedChoices, arg.precond)) + ): Some[(TypeConName, Map[MethodName, GenTemplateImplementsMethod[E]], Set[ChoiceName])] = + Some((arg.interface, arg.methods, arg.inheritedChoices)) } type TemplateImplements = GenTemplateImplements[Expr] diff --git a/daml-lf/language/src/main/scala/com/digitalasset/daml/lf/language/Util.scala b/daml-lf/language/src/main/scala/com/digitalasset/daml/lf/language/Util.scala index e44746942457..65dd75870564 100644 --- a/daml-lf/language/src/main/scala/com/digitalasset/daml/lf/language/Util.scala +++ b/daml-lf/language/src/main/scala/com/digitalasset/daml/lf/language/Util.scala @@ -222,12 +222,11 @@ object Util { private[this] def toSignature(implements: TemplateImplements): TemplateImplementsSignature = implements match { - case TemplateImplements(name, methods, inheritedChoices, _) => + case TemplateImplements(name, methods, inheritedChoices) => TemplateImplementsSignature( name, methods.transform((_, v) => toSignature(v)), inheritedChoices, - (), ) } diff --git a/daml-lf/parser/src/main/scala/com/digitalasset/daml/lf/testing/parser/AstRewriter.scala b/daml-lf/parser/src/main/scala/com/digitalasset/daml/lf/testing/parser/AstRewriter.scala index b9d30599328e..5b0cc007d155 100644 --- a/daml-lf/parser/src/main/scala/com/digitalasset/daml/lf/testing/parser/AstRewriter.scala +++ b/daml-lf/parser/src/main/scala/com/digitalasset/daml/lf/testing/parser/AstRewriter.scala @@ -283,13 +283,11 @@ private[daml] class AstRewriter( interface, methods, inheritedChoices, - precond, ) => TemplateImplements( interface, methods.transform((_, x) => apply(x)), inheritedChoices, - apply(precond), ) } def apply(x: TemplateImplementsMethod): TemplateImplementsMethod = diff --git a/daml-lf/validation/src/main/scala/com/digitalasset/daml/lf/validation/iterable/ExprIterable.scala b/daml-lf/validation/src/main/scala/com/digitalasset/daml/lf/validation/iterable/ExprIterable.scala index 131b16cd1d08..bbf64063eb05 100644 --- a/daml-lf/validation/src/main/scala/com/digitalasset/daml/lf/validation/iterable/ExprIterable.scala +++ b/daml-lf/validation/src/main/scala/com/digitalasset/daml/lf/validation/iterable/ExprIterable.scala @@ -181,9 +181,8 @@ private[validation] object ExprIterable { interface @ _, methods, inheritedChoices @ _, - precond, ) => - Iterator(precond) ++ methods.values.iterator.flatMap(iterator(_)) + methods.values.iterator.flatMap(iterator(_)) } private[iterable] def iterator(x: TemplateImplementsMethod): Iterator[Expr] = diff --git a/daml-lf/validation/src/main/scala/com/digitalasset/daml/lf/validation/iterable/TypeIterable.scala b/daml-lf/validation/src/main/scala/com/digitalasset/daml/lf/validation/iterable/TypeIterable.scala index 1ae087ede9c7..5aceae097de4 100644 --- a/daml-lf/validation/src/main/scala/com/digitalasset/daml/lf/validation/iterable/TypeIterable.scala +++ b/daml-lf/validation/src/main/scala/com/digitalasset/daml/lf/validation/iterable/TypeIterable.scala @@ -228,9 +228,8 @@ private[validation] object TypeIterable { private[validation] def iterator(impl: TemplateImplements): Iterator[Type] = impl match { - case TemplateImplements(interface, methods, inheritedChoices @ _, precond) => + case TemplateImplements(interface, methods, inheritedChoices @ _) => Iterator(TTyCon(interface)) ++ - iterator(precond) ++ methods.values.flatMap(iterator(_)) }