diff --git a/pkl-core/src/main/java/org/pkl/core/runtime/VmUtils.java b/pkl-core/src/main/java/org/pkl/core/runtime/VmUtils.java index 71e06d88..b2f3ee2a 100644 --- a/pkl-core/src/main/java/org/pkl/core/runtime/VmUtils.java +++ b/pkl-core/src/main/java/org/pkl/core/runtime/VmUtils.java @@ -254,6 +254,18 @@ public final class VmUtils { IndirectCallNode callNode) { final var constantValue = member.getConstantValue(); + + // const members only need to be executed once on the prototype, and its cached value + // can be re-used for all children in the amends chain. + if (member.isConst() && owner != receiver) { + assert member.isProp(); + assert owner.isPrototype(); + var result = readMemberOrNull(owner, memberKey, checkType, callNode); + assert result != null; + receiver.setCachedValue(memberKey, result); + return result; + } + if (constantValue != null) { var result = constantValue; // for a property, Listing element, or Mapping value, do a type check diff --git a/pkl-core/src/test/files/LanguageSnippetTests/input/basic/constModifier5.pkl b/pkl-core/src/test/files/LanguageSnippetTests/input/basic/constModifier5.pkl new file mode 100644 index 00000000..a352c949 --- /dev/null +++ b/pkl-core/src/test/files/LanguageSnippetTests/input/basic/constModifier5.pkl @@ -0,0 +1,13 @@ +// should result in only one trace per property +class MyClass { + // property body only gets executed once + const prop = trace("hello") + + // typecheck only happens once + const prop2: Int(let (_ = trace("hello again")) true) = 1 + + res: Int +} + +a = new MyClass { res = 1 } +b = (a) { res = 2 } diff --git a/pkl-core/src/test/files/LanguageSnippetTests/output/basic/constModifier5.err b/pkl-core/src/test/files/LanguageSnippetTests/output/basic/constModifier5.err new file mode 100644 index 00000000..43c6808b --- /dev/null +++ b/pkl-core/src/test/files/LanguageSnippetTests/output/basic/constModifier5.err @@ -0,0 +1,12 @@ +a { + prop = "hello" + prop2 = 1 + res = 1 +} +b { + prop = "hello" + prop2 = 1 + res = 2 +} +pkl: TRACE: "hello" = "hello" (file:///$snippetsDir/input/basic/constModifier5.pkl) +pkl: TRACE: "hello again" = "hello again" (file:///$snippetsDir/input/basic/constModifier5.pkl)