Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add choice collisions in scala name collision checker #11528

Merged
merged 3 commits into from
Nov 3, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This value gets reused a lot, so it's better for it to be a val instead of a def in this case, if I understand correctly.


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,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These NamedEntity types seem to replicate some parts of the AST, but these aren't used for anything, so I removed them. They're not needed in the name collision checker, which is the only thing these types are used for.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🙈

) 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)"
sofiafaro-da marked this conversation as resolved.
Show resolved Hide resolved

def pretty: String = s"template choice $modName:$tplName.$choiceName"
sofiafaro-da marked this conversation as resolved.
Show resolved Hide resolved
}

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)"
sofiafaro-da marked this conversation as resolved.
Show resolved Hide resolved

def pretty: String = s"template choice $modName:$tplName.$choiceName (via interface $iface)"
sofiafaro-da marked this conversation as resolved.
Show resolved Hide resolved
}
}