Skip to content

Commit b8af840

Browse files
[LF] introduce a basic patch mecanism for LF
1 parent 79499b7 commit b8af840

File tree

9 files changed

+100
-62
lines changed

9 files changed

+100
-62
lines changed

sdk/compiler/daml-lf-proto-encode/src/DA/Daml/LF/Proto3/Encode.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,4 @@ encodePayload :: Package -> ArchivePayload
1818
encodePayload package = case packageLfVersion package of
1919
(Version V2 minor) ->
2020
let payload = ArchivePayloadSumDamlLf2 $ BSL.toStrict $ Proto.toLazyByteString (EncodeV2.encodePackage package)
21-
in ArchivePayload (TL.pack $ renderMinorVersion minor) (Just payload)
21+
in ArchivePayload (TL.pack $ renderMinorVersion minor) 0 (Just payload)

sdk/daml-lf/archive/src/main/protobuf/com/digitalasset/daml/lf/archive/daml_lf.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ message ArchivePayload {
1313
// this is number 3 for historical reasons -- we had
1414
// Daml-LF v0 and v1 before we had minor versions.
1515
string minor = 3;
16+
int32 patch = 5; // must be empty
1617
reserved 9999; // for the removed "dev" major version
1718
reserved 1; // was daml_lf_0
1819

sdk/daml-lf/archive/src/main/scala/com/digitalasset/daml/lf/archive/Decode.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,14 @@ object Decode {
1515
onlySerializableDataDefs: Boolean = false,
1616
): Either[Error, (PackageId, Ast.Package)] =
1717
payload match {
18-
case ArchivePayload.Lf2(pkgId, protoPkg, minor)
18+
case ArchivePayload.Lf2(pkgId, protoPkg, minor, patch)
1919
if LanguageMajorVersion.V2.supportedMinorVersions.contains(minor) =>
2020
new DecodeV2(minor)
2121
.decodePackage(
2222
pkgId,
2323
protoPkg,
2424
onlySerializableDataDefs,
25+
patch,
2526
)
2627
.map(payload.pkgId -> _)
2728
case ArchivePayload.Lf1(pkgId, protoPkg, minor)

sdk/daml-lf/archive/src/main/scala/com/digitalasset/daml/lf/archive/DecodeV2.scala

Lines changed: 51 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -31,55 +31,63 @@ private[archive] class DecodeV2(minor: LV.Minor) {
3131
packageId: PackageId,
3232
lfPackage: PLF.Package,
3333
onlySerializableDataDefs: Boolean,
34-
): Either[Error, Package] = attempt(NameOf.qualifiedNameOfCurrentFunc) {
35-
36-
val internedStrings = lfPackage.getInternedStringsList.asScala.to(ImmArraySeq)
37-
38-
val internedDottedNames =
39-
decodeInternedDottedNames(
40-
lfPackage.getInternedDottedNamesList.asScala,
41-
internedStrings,
42-
)
43-
44-
val dependencyTracker = new PackageDependencyTracker(packageId)
45-
46-
val metadata: PackageMetadata = {
47-
if (!lfPackage.hasMetadata)
48-
throw Error.Parsing(s"Package.metadata is required in Daml-LF 2.$minor")
49-
decodePackageMetadata(lfPackage.getMetadata, internedStrings)
50-
}
34+
patchVersion: Int,
35+
): Either[Error, Package] =
36+
if (patchVersion != 0) {
37+
if (languageVersion < LV.Features.patchVersion)
38+
Left(Error.Parsing(s"Patch version not supported for LF $languageVersion"))
39+
else
40+
Left(Error.Parsing(s"Unknown patch version $patchVersion for LF $languageVersion"))
41+
} else
42+
attempt(NameOf.qualifiedNameOfCurrentFunc) {
43+
44+
val internedStrings = lfPackage.getInternedStringsList.asScala.to(ImmArraySeq)
45+
46+
val internedDottedNames =
47+
decodeInternedDottedNames(
48+
lfPackage.getInternedDottedNamesList.asScala,
49+
internedStrings,
50+
)
5151

52-
val imports = decodePackageImports(lfPackage)
52+
val dependencyTracker = new PackageDependencyTracker(packageId)
5353

54-
val env0 = Env(
55-
packageId = packageId,
56-
internedStrings = internedStrings,
57-
internedDottedNames = internedDottedNames,
58-
optDependencyTracker = Some(dependencyTracker),
59-
onlySerializableDataDefs = onlySerializableDataDefs,
60-
imports = imports,
61-
)
54+
val metadata: PackageMetadata = {
55+
if (!lfPackage.hasMetadata)
56+
throw Error.Parsing(s"Package.metadata is required in Daml-LF 2.$minor")
57+
decodePackageMetadata(lfPackage.getMetadata, internedStrings)
58+
}
6259

63-
val internedKinds = decodeKindsTable(env0, lfPackage)
64-
val env1 = env0.copy(internedKinds = internedKinds)
65-
val internedTypes = decodeTypesTable(env1, lfPackage)
66-
val env2 = env1.copy(internedTypes = internedTypes)
67-
val internedExprs = lfPackage.getInternedExprsList().asScala.toVector
68-
val env = env2.copy(internedExprs = internedExprs)
60+
val imports = decodePackageImports(lfPackage)
6961

70-
val importsSet =
71-
imports.map(xs => xs.map(s => eitherToParseError(PackageId.fromString(s))).toSet)
62+
val env0 = Env(
63+
packageId = packageId,
64+
internedStrings = internedStrings,
65+
internedDottedNames = internedDottedNames,
66+
optDependencyTracker = Some(dependencyTracker),
67+
onlySerializableDataDefs = onlySerializableDataDefs,
68+
imports = imports,
69+
)
7270

73-
val modules = lfPackage.getModulesList.asScala.map(env.decodeModule(_))
74-
Package.build(
75-
modules = modules,
76-
directDeps = dependencyTracker.getDependencies,
77-
languageVersion = languageVersion,
78-
metadata = metadata,
79-
imports = importsSet,
80-
)
71+
val internedKinds = decodeKindsTable(env0, lfPackage)
72+
val env1 = env0.copy(internedKinds = internedKinds)
73+
val internedTypes = decodeTypesTable(env1, lfPackage)
74+
val env2 = env1.copy(internedTypes = internedTypes)
75+
val internedExprs = lfPackage.getInternedExprsList().asScala.toVector
76+
val env = env2.copy(internedExprs = internedExprs)
77+
78+
val importsSet =
79+
imports.map(xs => xs.map(s => eitherToParseError(PackageId.fromString(s))).toSet)
80+
81+
val modules = lfPackage.getModulesList.asScala.map(env.decodeModule(_))
82+
Package.build(
83+
modules = modules,
84+
directDeps = dependencyTracker.getDependencies,
85+
languageVersion = languageVersion,
86+
metadata = metadata,
87+
imports = importsSet,
88+
)
8189

82-
}
90+
}
8391

8492
private[archive] def decodePackageMetadata(
8593
metadata: PLF.PackageMetadata,

sdk/daml-lf/archive/src/main/scala/com/digitalasset/daml/lf/archive/Reader.scala

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ object ArchivePayload {
2929
pkgId: PackageId,
3030
proto: DamlLf2.Package,
3131
minor: language.LanguageMinorVersion,
32+
patch: Int,
3233
) extends ArchivePayload {
3334
val version = LanguageVersion(LanguageMajorVersion.V2, minor)
3435
}
@@ -72,16 +73,19 @@ object Reader {
7273
): Either[Error, ArchivePayload] =
7374
lf.getSumCase match {
7475
case DamlLf.ArchivePayload.SumCase.DAML_LF_1 =>
75-
lf1PackageParser
76-
.fromByteString(lf.getDamlLf1)
77-
.map(
78-
ArchivePayload.Lf1(hash, _, LanguageMinorVersion(lf.getMinor))
79-
)
76+
if (lf.getPatch != 0)
77+
Left(Error.Parsing("Patch version is not supported for LF1"))
78+
else
79+
lf1PackageParser
80+
.fromByteString(lf.getDamlLf1)
81+
.map(
82+
ArchivePayload.Lf1(hash, _, LanguageMinorVersion(lf.getMinor))
83+
)
8084
case DamlLf.ArchivePayload.SumCase.DAML_LF_2 =>
8185
val minor = LanguageMinorVersion(lf.getMinor)
8286
lf2PackageParser(minor)
8387
.fromByteString(lf.getDamlLf2)
84-
.map(ArchivePayload.Lf2(hash, _, LanguageMinorVersion(lf.getMinor)))
88+
.map(ArchivePayload.Lf2(hash, _, LanguageMinorVersion(lf.getMinor), lf.getPatch))
8589
case DamlLf.ArchivePayload.SumCase.SUM_NOT_SET =>
8690
Left(Error.Parsing("Unrecognized or Unsupported LF version"))
8791
}

sdk/daml-lf/archive/src/test/scala/com/digitalasset/daml/lf/archive/DarReaderTest.scala

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ class DarReaderTest
4141
case ArchivePayload.Lf1(packageId, protoPkg, _) =>
4242
packageId shouldNot be(Symbol("empty"))
4343
protoPkg.getModulesCount should be > 0
44-
case ArchivePayload.Lf2(_, _, _) =>
45-
Assertions.fail("unexpected Lf1 payload")
44+
case ArchivePayload.Lf2(_, _, _, _) =>
45+
Assertions.fail("unexpected Lf2 payload")
4646
}
4747

4848
val mainPkg = dar.main.asInstanceOf[ArchivePayload.Lf1].proto
@@ -94,8 +94,8 @@ class DarReaderTest
9494
"LibraryModules",
9595
"GHC.Tuple.Check",
9696
)
97-
case ArchivePayload.Lf2(_, _, _) =>
98-
Assertions.fail("unexpected Lf2 payload")
97+
case ArchivePayload.Lf2(_, _, _, _) =>
98+
Assertions.fail("unexpected LF2 payload")
9999
}
100100

101101
def internedName(
@@ -116,7 +116,7 @@ class DarReaderTest
116116
forAll(dar.all) {
117117
case ArchivePayload.Lf1(_, _, _) =>
118118
Assertions.fail("unexpected Lf1 payload")
119-
case ArchivePayload.Lf2(packageId, protoPkg, _) =>
119+
case ArchivePayload.Lf2(packageId, protoPkg, _, _) =>
120120
packageId shouldNot be(Symbol("empty"))
121121
protoPkg.getModulesCount should be > 0
122122
}
@@ -150,7 +150,7 @@ class DarReaderTest
150150
forExactly(1, dar.dependencies) {
151151
case ArchivePayload.Lf1(_, _, _) =>
152152
Assertions.fail("unexpected Lf1 payload")
153-
case ArchivePayload.Lf2(_, protoPkg, _) =>
153+
case ArchivePayload.Lf2(_, protoPkg, _, _) =>
154154
val archiveModules = protoPkg.getModulesList.asScala
155155
val archiveInternedDotted = protoPkg.getInternedDottedNamesList.asScala
156156
val archiveInternedStrings = protoPkg.getInternedStringsList.asScala

sdk/daml-lf/archive/src/test/scala/com/digitalasset/daml/lf/archive/DecodeV2Spec.scala

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package com.digitalasset.daml.lf.archive
55

66
import com.daml.SafeProto
7+
78
import java.math.BigDecimal
89
import java.nio.file.Paths
910
import com.daml.bazeltools.BazelRunfiles._
@@ -1501,7 +1502,7 @@ class DecodeV2Spec
15011502

15021503
"decodeModuleRef" should {
15031504

1504-
lazy val Right(ArchivePayload.Lf2(pkgId, pkgProto, minorVersion)) =
1505+
lazy val Right(ArchivePayload.Lf2(pkgId, pkgProto, minorVersion, _)) =
15051506
ArchiveReader.fromFile(Paths.get(rlocation("daml-lf/archive/DarReaderTest.dalf")))
15061507

15071508
lazy val extId = {
@@ -1536,7 +1537,7 @@ class DecodeV2Spec
15361537

15371538
"decode resolving the interned package ID" in {
15381539
val decoder = new DecodeV2(minorVersion)
1539-
inside(decoder.decodePackage(pkgId, pkgProto, false)) { case Right(pkg) =>
1540+
inside(decoder.decodePackage(pkgId, pkgProto, false, 0)) { case Right(pkg) =>
15401541
inside(
15411542
pkg
15421543
.modules(Ref.DottedName.assertFromString("DarReaderTest"))
@@ -1657,7 +1658,7 @@ class DecodeV2Spec
16571658
val pkgId = Ref.PackageId.assertFromString(
16581659
"0000000000000000000000000000000000000000000000000000000000000000"
16591660
)
1660-
inside(decoder.decodePackage(pkgId, DamlLf2.Package.newBuilder().build(), false)) {
1661+
inside(decoder.decodePackage(pkgId, DamlLf2.Package.newBuilder().build(), false, 0)) {
16611662
case Left(err) => err shouldBe an[Error.Parsing]
16621663
}
16631664
}
@@ -1680,7 +1681,7 @@ class DecodeV2Spec
16801681
.addInternedStrings("0.0.0")
16811682
.setMetadata(metadata)
16821683
.build()
1683-
inside(decoder.decodePackage(pkgId, pkg, false)) { case Right(pkg) =>
1684+
inside(decoder.decodePackage(pkgId, pkg, false, 0)) { case Right(pkg) =>
16841685
pkg.metadata shouldBe
16851686
Ast.PackageMetadata(
16861687
Ref.PackageName.assertFromString("foobar"),
@@ -1812,6 +1813,28 @@ class DecodeV2Spec
18121813
Decode.decodeArchive(exprToArch(buildLet(498), "1")) shouldBe a[Right[_, _]]
18131814
}
18141815
}
1816+
1817+
"fail for unknown patch versions" in {
1818+
val pkgId = Ref.PackageId.assertFromString("-pkgId-")
1819+
1820+
forEveryVersion { version =>
1821+
inside(
1822+
Decode.decodeArchivePayload(
1823+
ArchivePayload.Lf2(
1824+
pkgId = pkgId,
1825+
proto = DamlLf2.Package.getDefaultInstance,
1826+
minor = version.minor,
1827+
patch = 1,
1828+
)
1829+
)
1830+
) { case Left(err) =>
1831+
if (version < LV.Features.patchVersion)
1832+
err.msg should include(s"Patch version not supported for LF $version")
1833+
else
1834+
err.msg should include(s"Unknown patch version 1 for LF $version")
1835+
}
1836+
}
1837+
}
18151838
}
18161839

18171840
"decodeChoice" should {

sdk/daml-lf/encoder/src/test/scala/com/digitalasset/daml/lf/testing/archive/DamlLfEncoderTest.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ class DamlLfEncoderTest
9494
for {
9595
payload <- dar.all
9696
name <- payload match {
97-
case ArchivePayload.Lf2(_, pkg, _) => getNonEmptyModules(pkg)
97+
case ArchivePayload.Lf2(_, pkg, _, _) => getNonEmptyModules(pkg)
9898
case _ => throw new RuntimeException(s"Unsupported language version: ${payload.version}")
9999
}
100100
} yield name

sdk/daml-lf/language/src/main/scala/com/digitalasset/daml/lf/language/LanguageVersion.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ object LanguageVersion {
8585
val default = v2_1
8686
val exceptions = v2_1
8787
val packageUpgrades = v2_1
88+
val patchVersion = v2_dev
8889
val persistedPackageVersion = v2_dev
8990

9091
val choiceFuncs = v2_dev

0 commit comments

Comments
 (0)