mirror of
https://github.com/apple/pkl.git
synced 2026-07-09 06:25:16 +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;
|
private final int parameterCount;
|
||||||
@Children private final @Nullable UnresolvedTypeNode[] unresolvedParameterTypeNodes;
|
@Children private final @Nullable UnresolvedTypeNode[] unresolvedParameterTypeNodes;
|
||||||
@Child private @Nullable UnresolvedTypeNode unresolvedReturnTypeNode;
|
@Child private @Nullable UnresolvedTypeNode unresolvedReturnTypeNode;
|
||||||
private final ExpressionNode bodyNode;
|
@Child private ExpressionNode bodyNode;
|
||||||
|
|
||||||
public UnresolvedFunctionNode(
|
public UnresolvedFunctionNode(
|
||||||
VmLanguage language,
|
VmLanguage language,
|
||||||
|
|||||||
@@ -429,6 +429,10 @@ public abstract class UnresolvedTypeNode extends PklNode {
|
|||||||
this.typeParameter = typeParameter;
|
this.typeParameter = typeParameter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getTypeParameterIndex() {
|
||||||
|
return typeParameter.getIndex();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeNode execute(VirtualFrame frame) {
|
public TypeNode execute(VirtualFrame frame) {
|
||||||
CompilerDirectives.transferToInterpreter();
|
CompilerDirectives.transferToInterpreter();
|
||||||
@@ -436,4 +440,23 @@ public abstract class UnresolvedTypeNode extends PklNode {
|
|||||||
return new TypeVariableNode(sourceSection, typeParameter);
|
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.ConstrainedTypeNode;
|
||||||
import org.pkl.core.ast.type.TypeNode.TypeVariableNode;
|
import org.pkl.core.ast.type.TypeNode.TypeVariableNode;
|
||||||
import org.pkl.core.ast.type.TypeNode.UnknownTypeNode;
|
import org.pkl.core.ast.type.TypeNode.UnknownTypeNode;
|
||||||
|
import org.pkl.core.ast.type.UnresolvedTypeNode;
|
||||||
|
|
||||||
public final class VmTypeAlias extends VmValue {
|
public final class VmTypeAlias extends VmValue {
|
||||||
private final SourceSection sourceSection;
|
private final SourceSection sourceSection;
|
||||||
@@ -204,6 +205,15 @@ public final class VmTypeAlias extends VmValue {
|
|||||||
typeArgumentNodes.length == 0
|
typeArgumentNodes.length == 0
|
||||||
? new UnknownTypeNode(sourceSection)
|
? new UnknownTypeNode(sourceSection)
|
||||||
: typeArgumentNodes[index]);
|
: 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;
|
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