From 776790e38612922da715cd1e24e8a8b9575827bd Mon Sep 17 00:00:00 2001 From: Sofia Faro Date: Wed, 3 Nov 2021 17:01:34 +0000 Subject: [PATCH] Add choice collisions in scala name collision checker (#11528) * Add choice collisions in scala name collision chk This brings it in line with the LF spec. This PR also adds collisions for inherited (interface) choices. Closes #11137. changelog_begin changelog_end * scalafmt * Apply suggestions from code review Co-authored-by: Remy Co-authored-by: Remy --- .../daml/lf/validation/Collision.scala | 39 ++++++++++----- .../daml/lf/validation/NamedEntity.scala | 47 +++++++++++++++---- 2 files changed, 64 insertions(+), 22 deletions(-) diff --git a/daml-lf/validation/src/main/scala/com/digitalasset/daml/lf/validation/Collision.scala b/daml-lf/validation/src/main/scala/com/digitalasset/daml/lf/validation/Collision.scala index 60c3c709a31c..4dd4d27855b8 100644 --- a/daml-lf/validation/src/main/scala/com/digitalasset/daml/lf/validation/Collision.scala +++ b/daml-lf/validation/src/main/scala/com/digitalasset/daml/lf/validation/Collision.scala @@ -38,15 +38,20 @@ private[validation] object Collision { modules: Iterable[(ModuleName, Ast.Module)] ): Iterable[NamedEntity] = modules.flatMap { case (modName, module) => - val namedModule = NModDef(modName, module.definitions.toList) - namedModule :: namedEntitiesFromMod(namedModule, module.definitions.toList) + val namedModule = NModDef(modName) + namedModule :: namedEntitiesFromMod(namedModule, module) } private def namedEntitiesFromMod( module: NModDef, - defns: List[(DottedName, Ast.Definition)], + astModule: Ast.Module, ): List[NamedEntity] = - defns.flatMap { case (defName, defn) => namedEntitiesFromDef(module, defName, defn) } + (astModule.definitions.toList.flatMap { case (defName, defn) => + namedEntitiesFromDef(module, defName, defn) + } ++ + astModule.templates.toList.flatMap { case (tplName, tpl) => + namedEntitiesFromTemplate(module, tplName, tpl) + }) private def namedEntitiesFromDef( module: NModDef, @@ -54,17 +59,17 @@ private[validation] object Collision { defn: Ast.Definition, ): List[NamedEntity] = defn match { - case dDef @ Ast.DDataType(_, _, Ast.DataRecord(fields)) => - val recordDef = NRecDef(module, defName, dDef) + case Ast.DDataType(_, _, Ast.DataRecord(fields)) => + val recordDef = NRecDef(module, defName) recordDef :: fields.toList.map { case (name, _) => NField(recordDef, name) } - case dDef @ Ast.DDataType(_, _, Ast.DataVariant(variants)) => - val variantDef = NVarDef(module, defName, dDef) + case Ast.DDataType(_, _, Ast.DataVariant(variants)) => + val variantDef = NVarDef(module, defName) variantDef :: variants.toList.map { case (name, _) => NVarCon(variantDef, name) } - case dDef @ Ast.DDataType(_, _, Ast.DataEnum(values)) => - val enumDef = NEnumDef(module, defName, dDef) + case Ast.DDataType(_, _, Ast.DataEnum(values)) => + val enumDef = NEnumDef(module, defName) enumDef :: values.toList.map(NEnumCon(enumDef, _)) - case iDef @ Ast.DDataType(_, _, Ast.DataInterface) => - val interfaceDef = NInterface(module, defName, iDef) + case Ast.DDataType(_, _, Ast.DataInterface) => + val interfaceDef = NInterface(module, defName) interfaceDef :: List.empty case _: Ast.DValue => // ignore values @@ -72,7 +77,15 @@ private[validation] object Collision { case _: Ast.DTypeSyn => val synDef = NSynDef(module, defName) synDef :: List.empty - } + private def namedEntitiesFromTemplate( + module: NModDef, + tplName: DottedName, + tpl: Ast.Template, + ): List[NamedEntity] = + (tpl.choices.keys.map(NChoice(module, tplName, _)) ++ + tpl.implements.iterator.flatMap { case (iface, impl) => + impl.inheritedChoices.iterator.map(NChoiceViaInterface(module, tplName, _, iface)) + }).toList } diff --git a/daml-lf/validation/src/main/scala/com/digitalasset/daml/lf/validation/NamedEntity.scala b/daml-lf/validation/src/main/scala/com/digitalasset/daml/lf/validation/NamedEntity.scala index aeb7eaee00ea..666d19c519e0 100644 --- a/daml-lf/validation/src/main/scala/com/digitalasset/daml/lf/validation/NamedEntity.scala +++ b/daml-lf/validation/src/main/scala/com/digitalasset/daml/lf/validation/NamedEntity.scala @@ -4,8 +4,7 @@ package com.daml.lf.validation import com.daml.lf.data.Ref -import com.daml.lf.data.Ref.{DottedName, ModuleName, Name} -import com.daml.lf.language.Ast +import com.daml.lf.data.Ref.{DottedName, ModuleName, Name, ChoiceName, TypeConName} import com.daml.lf.validation.Util._ sealed trait NamedEntity extends Product with Serializable { @@ -17,13 +16,12 @@ sealed trait NamedEntity extends Product with Serializable { object NamedEntity { final case class NModDef( - name: ModuleName, - dfns: List[(DottedName, Ast.Definition)], + name: ModuleName ) extends NamedEntity { def modName: ModuleName = name - def fullyResolvedName: DottedName = name.toUpperCase + val fullyResolvedName: DottedName = name.toUpperCase override def toString = s"NModDef($name)" @@ -33,7 +31,6 @@ object NamedEntity { final case class NRecDef( module: NModDef, name: DottedName, - dfn: Ast.DDataType, ) extends NamedEntity { def modName: ModuleName = module.name @@ -49,7 +46,6 @@ object NamedEntity { final case class NVarDef( module: NModDef, name: DottedName, - dfn: Ast.DDataType, ) extends NamedEntity { def modName: ModuleName = module.name @@ -65,7 +61,6 @@ object NamedEntity { final case class NEnumDef( module: NModDef, name: DottedName, - dfn: Ast.DDataType, ) extends NamedEntity { def modName: ModuleName = module.name @@ -146,7 +141,6 @@ object NamedEntity { final case class NInterface( module: NModDef, name: DottedName, - dfn: Ast.DDataType, ) extends NamedEntity { def modName: ModuleName = module.name @@ -158,4 +152,39 @@ object NamedEntity { def pretty: String = s"interface $modName:$name" } + + final case class NChoice( + module: NModDef, + tplName: DottedName, + choiceName: ChoiceName, + ) extends NamedEntity { + def modName = module.modName + + val fullyResolvedName: DottedName = + module.fullyResolvedName ++ tplName.toUpperCase + Name.assertFromString( + choiceName.toUpperCase + ) + + override def toString: String = s"NChoice($modName:$tplName:$choiceName)" + + def pretty: String = s"template choice $modName:$tplName:$choiceName" + } + + final case class NChoiceViaInterface( + module: NModDef, + tplName: DottedName, + choiceName: ChoiceName, + iface: TypeConName, + ) extends NamedEntity { + def modName = module.modName + + val fullyResolvedName: DottedName = + module.fullyResolvedName ++ tplName.toUpperCase + Name.assertFromString( + choiceName.toUpperCase + ) + + override def toString: String = s"NChoiceViaInterface($modName:$tplName:$choiceName, $iface)" + + def pretty: String = s"template choice $modName:$tplName:$choiceName (via interface $iface)" + } }