From 65e7141c84c4a5de742a2bd235e0c83cadb45ddc Mon Sep 17 00:00:00 2001 From: Jen Basch Date: Wed, 1 Jul 2026 13:32:37 -0700 Subject: [PATCH] Do not treat replaceable `TypeVariableNode` instances as noops --- .../java/org/pkl/core/ast/type/TypeNode.java | 27 ++++++++++++++++--- .../pkl/core/ast/type/UnresolvedTypeNode.java | 6 ++++- .../input/types/typeAlias4.pkl | 24 +++++++++++++++++ .../output/types/typeAlias4.pcf | 9 +++++++ 4 files changed, 62 insertions(+), 4 deletions(-) create mode 100644 pkl-core/src/test/files/LanguageSnippetTests/input/types/typeAlias4.pkl create mode 100644 pkl-core/src/test/files/LanguageSnippetTests/output/types/typeAlias4.pcf diff --git a/pkl-core/src/main/java/org/pkl/core/ast/type/TypeNode.java b/pkl-core/src/main/java/org/pkl/core/ast/type/TypeNode.java index edf41628c..2ca808b95 100644 --- a/pkl-core/src/main/java/org/pkl/core/ast/type/TypeNode.java +++ b/pkl-core/src/main/java/org/pkl/core/ast/type/TypeNode.java @@ -2395,11 +2395,13 @@ protected boolean isParametric() { public static final class TypeVariableNode extends WriteFrameSlotTypeNode { private final TypeParameter typeParameter; + private final boolean isInTypeAlias; - public TypeVariableNode(SourceSection sourceSection, TypeParameter typeParameter) { - + public TypeVariableNode( + SourceSection sourceSection, TypeParameter typeParameter, boolean isInTypeAlias) { super(sourceSection); this.typeParameter = typeParameter; + this.isInTypeAlias = isInTypeAlias; } public int getTypeParameterIndex() { @@ -2408,7 +2410,10 @@ public int getTypeParameterIndex() { @Override public boolean isNoopTypeCheck() { - return true; + // if in a type alias, this node will be replaced by another TypeNode that may not be a noop + // so we return false so that containing TypeNodes don't skip checks erroneously + // this is slightly less efficient if the replacement _is_ a noop, but only inside typealiases + return !isInTypeAlias; } @Override @@ -2789,6 +2794,22 @@ public Object executeAndSet(VirtualFrame frame, Object value) { } } + /** See docstring on {@link TypeAliasTypeNode#executeLazily}. */ + @Override + public Object executeEagerly(VirtualFrame frame, Object value) { + var prevOwner = VmUtils.getOwner(frame); + var prevReceiver = VmUtils.getReceiver(frame); + setOwner(frame, VmUtils.getOwner(typeAlias.getEnclosingFrame())); + setReceiver(frame, VmUtils.getReceiver(typeAlias.getEnclosingFrame())); + + try { + return aliasedTypeNode.executeEagerly(frame, value); + } finally { + setOwner(frame, prevOwner); + setReceiver(frame, prevReceiver); + } + } + @TruffleBoundary private VmFunction newMixin(VmLanguage language, String qualifiedName) { //noinspection ConstantConditions diff --git a/pkl-core/src/main/java/org/pkl/core/ast/type/UnresolvedTypeNode.java b/pkl-core/src/main/java/org/pkl/core/ast/type/UnresolvedTypeNode.java index e5cbd35d2..cf60f7770 100644 --- a/pkl-core/src/main/java/org/pkl/core/ast/type/UnresolvedTypeNode.java +++ b/pkl-core/src/main/java/org/pkl/core/ast/type/UnresolvedTypeNode.java @@ -18,12 +18,14 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.ExplodeLoop; +import com.oracle.truffle.api.nodes.NodeUtil; import com.oracle.truffle.api.source.SourceSection; import java.util.Set; import org.pkl.core.TypeParameter; import org.pkl.core.ast.ExpressionNode; import org.pkl.core.ast.PklNode; import org.pkl.core.ast.expression.primary.GetModuleNode; +import org.pkl.core.ast.member.TypeAliasNode; import org.pkl.core.ast.type.TypeNode.*; import org.pkl.core.ast.type.TypeNodeFactory.*; import org.pkl.core.runtime.*; @@ -437,7 +439,9 @@ public int getTypeParameterIndex() { public TypeNode execute(VirtualFrame frame) { CompilerDirectives.transferToInterpreter(); - return new TypeVariableNode(sourceSection, typeParameter); + //noinspection ConstantValue + return new TypeVariableNode( + sourceSection, typeParameter, NodeUtil.findParent(this, TypeAliasNode.class) != null); } } diff --git a/pkl-core/src/test/files/LanguageSnippetTests/input/types/typeAlias4.pkl b/pkl-core/src/test/files/LanguageSnippetTests/input/types/typeAlias4.pkl new file mode 100644 index 000000000..c7cedd442 --- /dev/null +++ b/pkl-core/src/test/files/LanguageSnippetTests/input/types/typeAlias4.pkl @@ -0,0 +1,24 @@ +typealias MyList = List +res1 = List(new Dynamic {}) is MyList + +typealias MyList2 = List(any((it) -> it is T)) +res1a = List(new Dynamic {}) is MyList +res1b = List(this) is MyList + +typealias MySet = Set +res2 = Set(new Dynamic {}) is MySet + +typealias MyMap = Map +res3 = Map("foo", new Dynamic {}) is MyMap + +typealias MyListing = Listing +res4 = new Listing { new Dynamic {} } is MyListing + +typealias MyMapping = Mapping +res5 = new Mapping { ["foo"] = new Dynamic {} } is MyMapping + +typealias MyUnion = A | B +res6 = new Dynamic {} is MyUnion + +typealias NestedUnion = (A | A) | (B | B) +res7 = new Dynamic {} is NestedUnion diff --git a/pkl-core/src/test/files/LanguageSnippetTests/output/types/typeAlias4.pcf b/pkl-core/src/test/files/LanguageSnippetTests/output/types/typeAlias4.pcf new file mode 100644 index 000000000..f4d265122 --- /dev/null +++ b/pkl-core/src/test/files/LanguageSnippetTests/output/types/typeAlias4.pcf @@ -0,0 +1,9 @@ +res1 = false +res1a = false +res1b = true +res2 = false +res3 = false +res4 = false +res5 = false +res6 = false +res7 = false