mirror of
https://github.com/apple/pkl.git
synced 2026-07-02 19:21:41 +02:00
Fix type argument lost in constraint expressions within generic typealiases (#1709)
Co-authored-by: Daniel Chao <daniel.h.chao@gmail.com>
This commit is contained in:
@@ -31,7 +31,7 @@ public final class UnresolvedFunctionNode extends PklNode {
|
||||
private final int parameterCount;
|
||||
@Children private final @Nullable UnresolvedTypeNode[] unresolvedParameterTypeNodes;
|
||||
@Child private @Nullable UnresolvedTypeNode unresolvedReturnTypeNode;
|
||||
private final ExpressionNode bodyNode;
|
||||
@Child private ExpressionNode bodyNode;
|
||||
|
||||
public UnresolvedFunctionNode(
|
||||
VmLanguage language,
|
||||
|
||||
@@ -429,6 +429,10 @@ public abstract class UnresolvedTypeNode extends PklNode {
|
||||
this.typeParameter = typeParameter;
|
||||
}
|
||||
|
||||
public int getTypeParameterIndex() {
|
||||
return typeParameter.getIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeNode execute(VirtualFrame frame) {
|
||||
CompilerDirectives.transferToInterpreter();
|
||||
@@ -436,4 +440,23 @@ public abstract class UnresolvedTypeNode extends PklNode {
|
||||
return new TypeVariableNode(sourceSection, typeParameter);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An unresolved type node that is pre-resolved to a concrete type node. Used during type alias
|
||||
* instantiation to replace type variable references inside constraint expressions (e.g., {@code
|
||||
* every((it) -> it is T)}) with the corresponding concrete type argument.
|
||||
*/
|
||||
public static final class Resolved extends UnresolvedTypeNode {
|
||||
@Child private TypeNode typeNode;
|
||||
|
||||
public Resolved(SourceSection sourceSection, TypeNode typeNode) {
|
||||
super(sourceSection);
|
||||
this.typeNode = typeNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeNode execute(VirtualFrame frame) {
|
||||
return typeNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import org.pkl.core.ast.type.TypeNode;
|
||||
import org.pkl.core.ast.type.TypeNode.ConstrainedTypeNode;
|
||||
import org.pkl.core.ast.type.TypeNode.TypeVariableNode;
|
||||
import org.pkl.core.ast.type.TypeNode.UnknownTypeNode;
|
||||
import org.pkl.core.ast.type.UnresolvedTypeNode;
|
||||
|
||||
public final class VmTypeAlias extends VmValue {
|
||||
private final SourceSection sourceSection;
|
||||
@@ -204,6 +205,15 @@ public final class VmTypeAlias extends VmValue {
|
||||
typeArgumentNodes.length == 0
|
||||
? new UnknownTypeNode(sourceSection)
|
||||
: typeArgumentNodes[index]);
|
||||
} else if (node instanceof UnresolvedTypeNode.TypeVariable unresolvedTypeVar) {
|
||||
// Type variables inside constraint expressions (e.g. `every((it) -> it is T)`)
|
||||
// are still unresolved at instantiation time. Replace them with a resolved
|
||||
// unresolved type node that returns the concrete type argument.
|
||||
var index = unresolvedTypeVar.getTypeParameterIndex();
|
||||
node.replace(
|
||||
typeArgumentNodes.length == 0
|
||||
? new UnresolvedTypeNode.Unknown(sourceSection)
|
||||
: new UnresolvedTypeNode.Resolved(sourceSection, typeArgumentNodes[index]));
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
typealias MyList<T> = List(this[0] is T)
|
||||
|
||||
foo: MyList<Int> = List("uh oh")
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
–– Pkl Error ––
|
||||
Type constraint `this[0] is T` violated.
|
||||
Value: List("uh oh")
|
||||
|
||||
this[0] is T
|
||||
│ │ │
|
||||
│ │ false
|
||||
│ "uh oh"
|
||||
List("uh oh")
|
||||
|
||||
x | typealias MyList<T> = List(this[0] is T)
|
||||
^^^^^^^^^^^^
|
||||
at typeAliasConstraint3#foo (file:///$snippetsDir/input/types/typeAliasConstraint3.pkl)
|
||||
|
||||
x | foo: MyList<Int> = List("uh oh")
|
||||
^^^^^^^^^^^^^
|
||||
at typeAliasConstraint3#foo (file:///$snippetsDir/input/types/typeAliasConstraint3.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)
|
||||
Reference in New Issue
Block a user