Skip to content

Commit

Permalink
Add choice collisions in scala name collision checker (#11528)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>

Co-authored-by: Remy <[email protected]>
  • Loading branch information
sofiafaro-da and remyhaemmerle-da authored Nov 3, 2021
1 parent 2efcb21 commit 776790e
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,41 +38,54 @@ 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,
defName: DottedName,
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
List.empty
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
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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)"

Expand All @@ -33,7 +31,6 @@ object NamedEntity {
final case class NRecDef(
module: NModDef,
name: DottedName,
dfn: Ast.DDataType,
) extends NamedEntity {

def modName: ModuleName = module.name
Expand All @@ -49,7 +46,6 @@ object NamedEntity {
final case class NVarDef(
module: NModDef,
name: DottedName,
dfn: Ast.DDataType,
) extends NamedEntity {

def modName: ModuleName = module.name
Expand All @@ -65,7 +61,6 @@ object NamedEntity {
final case class NEnumDef(
module: NModDef,
name: DottedName,
dfn: Ast.DDataType,
) extends NamedEntity {

def modName: ModuleName = module.name
Expand Down Expand Up @@ -146,7 +141,6 @@ object NamedEntity {
final case class NInterface(
module: NModDef,
name: DottedName,
dfn: Ast.DDataType,
) extends NamedEntity {

def modName: ModuleName = module.name
Expand All @@ -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)"
}
}

0 comments on commit 776790e

Please sign in to comment.