From 70fc1d4ba3b74a9181ad3e7d6e1e807c430f4867 Mon Sep 17 00:00:00 2001 From: Jen Basch Date: Mon, 29 Jun 2026 23:49:21 -0700 Subject: [PATCH] Correctly handle type aliases with a type variable as the root (#1714) --- .../org/pkl/core/runtime/VmTypeAlias.java | 14 +++++++++++--- .../input/types/typeAlias3.pkl | 2 ++ .../input/types/typeAlias3a.pkl | 2 ++ .../output/types/typeAlias3.pcf | 1 + .../output/types/typeAlias3a.err | 19 +++++++++++++++++++ 5 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 pkl-core/src/test/files/LanguageSnippetTests/input/types/typeAlias3.pkl create mode 100644 pkl-core/src/test/files/LanguageSnippetTests/input/types/typeAlias3a.pkl create mode 100644 pkl-core/src/test/files/LanguageSnippetTests/output/types/typeAlias3.pcf create mode 100644 pkl-core/src/test/files/LanguageSnippetTests/output/types/typeAlias3a.err diff --git a/pkl-core/src/main/java/org/pkl/core/runtime/VmTypeAlias.java b/pkl-core/src/main/java/org/pkl/core/runtime/VmTypeAlias.java index 208b042bd..d5354d006 100644 --- a/pkl-core/src/main/java/org/pkl/core/runtime/VmTypeAlias.java +++ b/pkl-core/src/main/java/org/pkl/core/runtime/VmTypeAlias.java @@ -182,10 +182,18 @@ public final class VmTypeAlias extends VmValue { // which should be good for interpreted and compiled performance alike: // * Fewer root nodes to call // * ControlFlowException used to implement union types doesn't escape root node + + if (typeParameters.isEmpty()) return (TypeNode) typeNode.deepCopy(); + + // handle if alias root is itself a type variable (https://github.com/apple/pkl/issues/1711) + if (typeNode instanceof TypeVariableNode typeVarNode) { + // no need to run validation since the arg itself has already been checked + return typeArgumentNodes.length == 0 + ? new UnknownTypeNode(sourceSection) + : typeArgumentNodes[typeVarNode.getTypeParameterIndex()]; + } + var clone = (TypeNode) typeNode.deepCopy(); - - if (typeParameters.isEmpty()) return clone; - clone.accept( node -> { if (node instanceof TypeVariableNode typeVarNode) { diff --git a/pkl-core/src/test/files/LanguageSnippetTests/input/types/typeAlias3.pkl b/pkl-core/src/test/files/LanguageSnippetTests/input/types/typeAlias3.pkl new file mode 100644 index 000000000..4a2e41edc --- /dev/null +++ b/pkl-core/src/test/files/LanguageSnippetTests/input/types/typeAlias3.pkl @@ -0,0 +1,2 @@ +typealias Id = T +foo: Id = 1 diff --git a/pkl-core/src/test/files/LanguageSnippetTests/input/types/typeAlias3a.pkl b/pkl-core/src/test/files/LanguageSnippetTests/input/types/typeAlias3a.pkl new file mode 100644 index 000000000..7f9cb5eb4 --- /dev/null +++ b/pkl-core/src/test/files/LanguageSnippetTests/input/types/typeAlias3a.pkl @@ -0,0 +1,2 @@ +typealias Id = T +foo: Id = "oops" diff --git a/pkl-core/src/test/files/LanguageSnippetTests/output/types/typeAlias3.pcf b/pkl-core/src/test/files/LanguageSnippetTests/output/types/typeAlias3.pcf new file mode 100644 index 000000000..c4e5bcc80 --- /dev/null +++ b/pkl-core/src/test/files/LanguageSnippetTests/output/types/typeAlias3.pcf @@ -0,0 +1 @@ +foo = 1 diff --git a/pkl-core/src/test/files/LanguageSnippetTests/output/types/typeAlias3a.err b/pkl-core/src/test/files/LanguageSnippetTests/output/types/typeAlias3a.err new file mode 100644 index 000000000..e4374f1e8 --- /dev/null +++ b/pkl-core/src/test/files/LanguageSnippetTests/output/types/typeAlias3a.err @@ -0,0 +1,19 @@ +–– Pkl Error –– +Expected value of type `Int`, but got type `String`. +Value: "oops" + +x | foo: Id = "oops" + ^^^ +at typeAlias3a#foo (file:///$snippetsDir/input/types/typeAlias3a.pkl) + +x | foo: Id = "oops" + ^^^^^^ +at typeAlias3a#foo (file:///$snippetsDir/input/types/typeAlias3a.pkl) + +xxx | renderer.renderDocument(value) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +at pkl.base#Module.output.text (pkl:base) + +xxx | if (renderer is BytesRenderer) renderer.renderDocument(value) else text.encodeToBytes("UTF-8") + ^^^^ +at pkl.base#Module.output.bytes (pkl:base)