pass type arguments to generic functions
This commit is contained in:
@@ -123,7 +123,8 @@ public class ClosureCodegen {
|
||||
|
||||
private void generateBody(FunctionDescriptor funDescriptor, ClassVisitor cv, List<JetElement> body) {
|
||||
FunctionCodegen fc = new FunctionCodegen(null, cv, state);
|
||||
fc.generatedMethod(body, OwnerKind.IMPLEMENTATION, invokeSignature(funDescriptor), funDescriptor.getReceiverType(), funDescriptor.getValueParameters(), null);
|
||||
fc.generatedMethod(body, OwnerKind.IMPLEMENTATION, invokeSignature(funDescriptor), funDescriptor.getReceiverType(),
|
||||
funDescriptor.getValueParameters(), funDescriptor.getTypeParameters(), null);
|
||||
}
|
||||
|
||||
private void generateBridge(String className, FunctionDescriptor funDescriptor, ClassVisitor cv) {
|
||||
|
||||
@@ -29,6 +29,7 @@ import java.util.*;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
* @author yole
|
||||
*/
|
||||
public class ExpressionCodegen extends JetVisitor {
|
||||
private static final String CLASS_OBJECT = "java/lang/Object";
|
||||
@@ -83,6 +84,7 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
private final BindingContext bindingContext;
|
||||
private final StackValue thisExpression;
|
||||
private final Map<ClassDescriptor, StackValue> outerThisExpressions = new HashMap<ClassDescriptor, StackValue>();
|
||||
private final Map<TypeParameterDescriptor, StackValue> typeParameterExpressions = new HashMap<TypeParameterDescriptor, StackValue>();
|
||||
|
||||
public ExpressionCodegen(MethodVisitor v,
|
||||
FrameMap myMap,
|
||||
@@ -106,6 +108,10 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
outerThisExpressions.put(outer, expression);
|
||||
}
|
||||
|
||||
public void addTypeParameter(TypeParameterDescriptor typeParameter, StackValue expression) {
|
||||
typeParameterExpressions.put(typeParameter, expression);
|
||||
}
|
||||
|
||||
static void loadTypeInfo(JetTypeMapper typeMapper, ClassDescriptor descriptor, InstructionAdapter v) {
|
||||
String owner = typeMapper.jvmName(descriptor, OwnerKind.IMPLEMENTATION);
|
||||
if (descriptor.getTypeConstructor().getParameters().size() > 0) {
|
||||
@@ -785,6 +791,7 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
ensureReceiverOnStack(expression, null);
|
||||
}
|
||||
pushMethodArguments(expression, methodDescriptor);
|
||||
pushTypeArguments(expression);
|
||||
final String owner = NamespaceCodegen.getJVMClassName(DescriptorRenderer.getFQName(functionParent));
|
||||
v.invokestatic(owner, methodDescriptor.getName(), methodDescriptor.getDescriptor());
|
||||
}
|
||||
@@ -792,6 +799,7 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
ClassDescriptor containingClass = (ClassDescriptor) functionParent;
|
||||
ensureReceiverOnStack(expression, containingClass);
|
||||
pushMethodArguments(expression, methodDescriptor);
|
||||
pushTypeArguments(expression);
|
||||
final String owner = typeMapper.jvmName(containingClass, OwnerKind.INTERFACE);
|
||||
int opcode = typeMapper.isInterface(containingClass, OwnerKind.INTERFACE)
|
||||
? Opcodes.INVOKEINTERFACE
|
||||
@@ -1456,12 +1464,7 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
|
||||
Method method = typeMapper.mapConstructorSignature((ConstructorDescriptor) constructorDescriptor, OwnerKind.IMPLEMENTATION);
|
||||
pushMethodArguments(expression, method);
|
||||
|
||||
for (JetTypeProjection jetTypeArgument : expression.getTypeArguments()) {
|
||||
JetType typeArgument = bindingContext.resolveTypeReference(jetTypeArgument.getTypeReference());
|
||||
// TODO is the makeNullable() call correct here?
|
||||
ClassCodegen.newTypeInfo(v, typeArgument.isNullable(), typeMapper.mapType(TypeUtils.makeNullable(typeArgument)));
|
||||
}
|
||||
pushTypeArguments(expression);
|
||||
|
||||
v.invokespecial(JetTypeMapper.jvmNameForImplementation(classDecl), "<init>", method.getDescriptor());
|
||||
}
|
||||
@@ -1472,6 +1475,14 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
myStack.push(StackValue.onStack(type));
|
||||
}
|
||||
|
||||
private void pushTypeArguments(JetCall expression) {
|
||||
for (JetTypeProjection jetTypeArgument : expression.getTypeArguments()) {
|
||||
JetType typeArgument = bindingContext.resolveTypeReference(jetTypeArgument.getTypeReference());
|
||||
// TODO is the makeNullable() call correct here?
|
||||
ClassCodegen.newTypeInfo(v, typeArgument.isNullable(), typeMapper.mapType(TypeUtils.makeNullable(typeArgument)));
|
||||
}
|
||||
}
|
||||
|
||||
private void pushOuterClassArguments(ClassDescriptor classDecl) {
|
||||
if (classDecl.getContainingDeclaration() instanceof ClassDescriptor) {
|
||||
v.load(0, JetTypeMapper.jetImplementationType(classDecl));
|
||||
@@ -1709,7 +1720,7 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
private void generateTypeInfo(JetType jetType) {
|
||||
DeclarationDescriptor declarationDescriptor = jetType.getConstructor().getDeclarationDescriptor();
|
||||
if (declarationDescriptor instanceof TypeParameterDescriptor) {
|
||||
loadTypeParameterTypeInfo(declarationDescriptor);
|
||||
loadTypeParameterTypeInfo((TypeParameterDescriptor) declarationDescriptor);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1742,11 +1753,16 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
private void loadTypeParameterTypeInfo(DeclarationDescriptor declarationDescriptor) {
|
||||
DeclarationDescriptor containingDeclaration = declarationDescriptor.getContainingDeclaration();
|
||||
private void loadTypeParameterTypeInfo(TypeParameterDescriptor typeParameterDescriptor) {
|
||||
final StackValue value = typeParameterExpressions.get(typeParameterDescriptor);
|
||||
if (value != null) {
|
||||
value.put(JetTypeMapper.TYPE_TYPEINFO, v);
|
||||
return;
|
||||
}
|
||||
DeclarationDescriptor containingDeclaration = typeParameterDescriptor.getContainingDeclaration();
|
||||
if (containingDeclaration == contextType && contextType instanceof ClassDescriptor) {
|
||||
loadTypeInfo(typeMapper, (ClassDescriptor) contextType, v);
|
||||
v.iconst(((TypeParameterDescriptor) declarationDescriptor).getIndex());
|
||||
v.iconst(typeParameterDescriptor.getIndex());
|
||||
v.invokevirtual("jet/typeinfo/TypeInfo", "getTypeParameter", "(I)Ljet/typeinfo/TypeInfo;");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package org.jetbrains.jet.codegen;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
@@ -17,6 +19,7 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
* @author yole
|
||||
*/
|
||||
public class FunctionCodegen {
|
||||
private final JetDeclaration owner;
|
||||
@@ -33,21 +36,23 @@ public class FunctionCodegen {
|
||||
final JetTypeReference receiverTypeRef = f.getReceiverTypeRef();
|
||||
final JetType receiverType = receiverTypeRef == null ? null : state.getBindingContext().resolveTypeReference(receiverTypeRef);
|
||||
Method method = state.getTypeMapper().mapSignature(f);
|
||||
List<ValueParameterDescriptor> paramDescrs = state.getBindingContext().getFunctionDescriptor(f).getValueParameters();
|
||||
generateMethod(f, kind, method, receiverType, paramDescrs);
|
||||
final FunctionDescriptor functionDescriptor = state.getBindingContext().getFunctionDescriptor(f);
|
||||
generateMethod(f, kind, method, receiverType, functionDescriptor.getValueParameters(),
|
||||
functionDescriptor.getTypeParameters());
|
||||
}
|
||||
|
||||
public void generateMethod(JetDeclarationWithBody f,
|
||||
OwnerKind kind,
|
||||
Method jvmSignature,
|
||||
@Nullable JetType receiverType,
|
||||
List<ValueParameterDescriptor> paramDescrs) {
|
||||
List<ValueParameterDescriptor> paramDescrs,
|
||||
List<TypeParameterDescriptor> typeParameters) {
|
||||
final DeclarationDescriptor contextDesc = owner instanceof JetClassOrObject
|
||||
? state.getBindingContext().getClassDescriptor((JetClassOrObject) owner)
|
||||
: state.getBindingContext().getNamespaceDescriptor((JetNamespace) owner);
|
||||
final JetExpression bodyExpression = f.getBodyExpression();
|
||||
final List<JetElement> bodyExpressions = bodyExpression != null ? Collections.<JetElement>singletonList(bodyExpression) : null;
|
||||
generatedMethod(bodyExpressions, kind, jvmSignature, receiverType, paramDescrs, contextDesc);
|
||||
generatedMethod(bodyExpressions, kind, jvmSignature, receiverType, paramDescrs, typeParameters, contextDesc);
|
||||
}
|
||||
|
||||
public void generatedMethod(List<JetElement> bodyExpressions,
|
||||
@@ -55,6 +60,7 @@ public class FunctionCodegen {
|
||||
Method jvmSignature,
|
||||
JetType receiverType,
|
||||
List<ValueParameterDescriptor> paramDescrs,
|
||||
List<TypeParameterDescriptor> typeParameters,
|
||||
DeclarationDescriptor contextDesc)
|
||||
{
|
||||
int flags = Opcodes.ACC_PUBLIC; // TODO.
|
||||
@@ -85,14 +91,22 @@ public class FunctionCodegen {
|
||||
frameMap.enterTemp(); // Next slot for fake this
|
||||
}
|
||||
|
||||
StackValue thisExpression = receiverType == null ? null : StackValue.local(thisIdx, state.getTypeMapper().mapType(receiverType));
|
||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getReturnType(), contextDesc, kind, thisExpression, state);
|
||||
|
||||
int firstArg = thisIdx+1;
|
||||
Type[] argTypes = jvmSignature.getArgumentTypes();
|
||||
for (int i = 0; i < paramDescrs.size(); i++) {
|
||||
ValueParameterDescriptor parameter = paramDescrs.get(i);
|
||||
frameMap.enter(parameter, argTypes[i].getSize());
|
||||
}
|
||||
for (int i = 0; i < typeParameters.size(); i++) {
|
||||
final TypeParameterDescriptor typeParameterDescriptor = typeParameters.get(i);
|
||||
codegen.addTypeParameter(typeParameterDescriptor,
|
||||
StackValue.local(firstArg + paramDescrs.size() + i, JetTypeMapper.TYPE_TYPEINFO));
|
||||
frameMap.enterTemp();
|
||||
}
|
||||
|
||||
StackValue thisExpression = receiverType == null ? null : StackValue.local(thisIdx, state.getTypeMapper().mapType(receiverType));
|
||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getReturnType(), contextDesc, kind, thisExpression, state);
|
||||
if (kind instanceof OwnerKind.DelegateKind) {
|
||||
OwnerKind.DelegateKind dk = (OwnerKind.DelegateKind) kind;
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
|
||||
@@ -282,6 +282,9 @@ public class JetTypeMapper {
|
||||
for (JetParameter parameter : parameters) {
|
||||
parameterTypes.add(mapType(bindingContext.resolveTypeReference(parameter.getTypeReference())));
|
||||
}
|
||||
for (JetTypeParameter p: f.getTypeParameters()) {
|
||||
parameterTypes.add(TYPE_TYPEINFO);
|
||||
}
|
||||
final JetTypeReference returnTypeRef = f.getReturnTypeRef();
|
||||
Type returnType;
|
||||
if (returnTypeRef == null) {
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.PropertySetterDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
@@ -97,7 +94,9 @@ public class PropertyCodegen {
|
||||
if (getter != null) {
|
||||
if (getter.getBodyExpression() != null) {
|
||||
functionCodegen.generateMethod(getter, kind, mapper.mapGetterSignature(propertyDescriptor),
|
||||
null, Collections.<ValueParameterDescriptor>emptyList());
|
||||
null,
|
||||
Collections.<ValueParameterDescriptor>emptyList(),
|
||||
Collections.<TypeParameterDescriptor>emptyList());
|
||||
}
|
||||
else if (!getter.hasModifier(JetTokens.PRIVATE_KEYWORD)) {
|
||||
generateDefaultGetter(p, getter, kind);
|
||||
@@ -119,7 +118,9 @@ public class PropertyCodegen {
|
||||
final PropertySetterDescriptor setterDescriptor = propertyDescriptor.getSetter();
|
||||
assert setterDescriptor != null;
|
||||
functionCodegen.generateMethod(setter, kind, mapper.mapSetterSignature(propertyDescriptor),
|
||||
null, setterDescriptor.getValueParameters());
|
||||
null,
|
||||
setterDescriptor.getValueParameters(),
|
||||
Collections.<TypeParameterDescriptor>emptyList());
|
||||
}
|
||||
else if (!p.hasModifier(JetTokens.PRIVATE_KEYWORD)) {
|
||||
generateDefaultSetter(p, setter, kind);
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
class Foo() { }
|
||||
class Bar() { }
|
||||
|
||||
fun isInstance<T>(obj: Any?) = obj is T
|
||||
|
||||
fun box(): String {
|
||||
if (! isInstance<Foo>(Foo())) return "fail 1"
|
||||
if (isInstance<Bar>(Foo())) return "fail 2"
|
||||
return "OK"
|
||||
}
|
||||
@@ -96,6 +96,10 @@ public class TypeInfoTest extends CodegenTestCase {
|
||||
blackBoxFile("typeInfo/nullability.jet");
|
||||
}
|
||||
|
||||
public void testGenericFunction() throws Exception {
|
||||
blackBoxFile("typeInfo/genericFunction.jet");
|
||||
}
|
||||
|
||||
private Runnable newRunnable() {
|
||||
return new Runnable() {
|
||||
@Override
|
||||
|
||||
@@ -6,6 +6,7 @@ import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
* @author yole
|
||||
*/
|
||||
public class TypeInfo<T> implements JetObject {
|
||||
private TypeInfo<?> typeInfo;
|
||||
|
||||
Reference in New Issue
Block a user