From 962cff0a0b9cd0abb3411014d3e743be7b8a8f6c Mon Sep 17 00:00:00 2001 From: Steve Lawrence Date: Fri, 17 Apr 2026 12:34:58 -0400 Subject: [PATCH] Convert NodeInfo.Nothing from a lazy val to an object The NodeInfo.Nothing instance has a `children` Delay member that never actually gets evaluated. This is fine and not unexpected since Nothing doesn't really have children and so nothing ever attempts to access or need the member. However, in some cases it is possible for the Nothing val to be referenced in a serialized class (e.g. in a DPath expression object that stores argument types such as fn:round-half-to-even) when creating a saved parser. And because this Nothing has a Delay that is never evaluated, it leads to an "object not initialized" exception, preventing creating a saved parser. To fix this issue, this changes NodeInfo.Nothing from a lazy val to an object. Whether we use a lazy val or an object here really does not make a difference with how we use it, but in Scala lazy vals are serialized while objects are not--Scala only serializes object names which are used to look up and return the singleton instance during deserialization. This allows us to avoid all possible serialization issues, and also changes Nothing to match the same pattern as all the other TypeNodes. DAFFODIL-3079 --- .../daffodil/runtime1/dpath/NodeInfo.scala | 49 ++++++++++--------- .../outputValueCalc.tdml | 29 +++++++++++ .../TestOutputValueCalc.scala | 1 + 3 files changed, 57 insertions(+), 22 deletions(-) diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/dpath/NodeInfo.scala b/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/dpath/NodeInfo.scala index fef41e7a6c..d49e416cd3 100644 --- a/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/dpath/NodeInfo.scala +++ b/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/dpath/NodeInfo.scala @@ -297,29 +297,32 @@ object NodeInfo extends Enum { /** * Nothing is the bottom of the type lattice. * - * It is the return type of the dfdlx:error() function. It's a subtype of + * It is the return type of the fn:error() function. It's a subtype of * every type (except some special singletons like ArrayType). */ - lazy val Nothing = new TypeNode( - Seq( - Boolean, - Complex, - Array, - ArrayIndex, - Double, - Float, - Date, - Time, - DateTime, - UnsignedByte, - Byte, - HexBinary, - AnyURI, - String, - NonEmptyString - ), - Nil - ) with Boolean.Kind + protected sealed trait NothingKind extends NodeInfo.Kind + case object Nothing + extends TypeNode( + Seq( + Boolean, + Complex, + Array, + ArrayIndex, + Double, + Float, + Date, + Time, + DateTime, + UnsignedByte, + Byte, + HexBinary, + AnyURI, + String, + NonEmptyString + ), + Nil + ) + with Boolean.Kind with Complex.Kind with Array.Kind with ArrayIndex.Kind @@ -332,7 +335,9 @@ object NodeInfo extends Enum { with Byte.Kind with HexBinary.Kind with NonEmptyString.Kind - with AnyURI.Kind + with AnyURI.Kind { + sealed trait Kind extends NothingKind + } /** * All complex types are represented by this one type object. diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section17/calc_value_properties/outputValueCalc.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section17/calc_value_properties/outputValueCalc.tdml index a379d3a3ca..c15cb31188 100644 --- a/daffodil-test/src/test/resources/org/apache/daffodil/section17/calc_value_properties/outputValueCalc.tdml +++ b/daffodil-test/src/test/resources/org/apache/daffodil/section17/calc_value_properties/outputValueCalc.tdml @@ -315,6 +315,15 @@ + + + + + + + + @@ -766,6 +775,26 @@ + + + + + a + + + + + + + Unparse Error + This is the error string + + + + diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/section17/calc_value_properties/TestOutputValueCalc.scala b/daffodil-test/src/test/scala/org/apache/daffodil/section17/calc_value_properties/TestOutputValueCalc.scala index d6387d96be..a0ec423f76 100644 --- a/daffodil-test/src/test/scala/org/apache/daffodil/section17/calc_value_properties/TestOutputValueCalc.scala +++ b/daffodil-test/src/test/scala/org/apache/daffodil/section17/calc_value_properties/TestOutputValueCalc.scala @@ -58,6 +58,7 @@ class TestOutputValueCalc1 extends TdmlTests { @Test def errorOneArg = test @Test def errorTwoArg = test @Test def errorThreeArg = test + @Test def errorInRoundHalfToEven = test // DAFFODIL-1701 @Test def refSimpleTypeElemWithOvc = test