Correct behavior:
open module currentModuleType4
import "pkl:test"
x: Int = 1
function fun(val: List<module>): Int = val.first.x
res1 = fun(List(this))
res4 = test.catch(() -> fun(List(new Dynamic { x = "nope" })))
Result:
x = 1
res1 = 1
res4 = "Expected value of type `currentModuleType4`, but got type `Dynamic`. Value: new Dynamic { x = ? }"
Incorrect behavior (List type annotation behind alias):
x = 1
res3 = 1
res6 = "Expected value of type `Int`, but got type `String`. Value: \"nope\""
This happens because the ListTypeNode's original elementTypeNode is a TypeVariableTypeNode, which unconditionally returns true for isNoopTypeCheck(). But when the alias is instantiated, this is replaced by the NonFinalModuleTypeNode (which is not a noop) without resetting skipElementTypeChecks.
This speaks to a need for better handling of internal cached (non-child) TypeNode state, which #1698 takes steps to try and address.
This affects all type nodes that attempts to optimize by detect noop checks at init time.
Correct behavior:
Result:
Incorrect behavior (
Listtype annotation behind alias):This happens because the
ListTypeNode's originalelementTypeNodeis aTypeVariableTypeNode, which unconditionally returnstrueforisNoopTypeCheck(). But when the alias is instantiated, this is replaced by theNonFinalModuleTypeNode(which is not a noop) without resettingskipElementTypeChecks.This speaks to a need for better handling of internal cached (non-child)
TypeNodestate, which #1698 takes steps to try and address.This affects all type nodes that attempts to optimize by detect noop checks at init time.