Merge remote branch 'origin/master'
This commit is contained in:
@@ -37,7 +37,7 @@ public class ClassContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public StackValue getThisExpression() {
|
public StackValue getThisExpression() {
|
||||||
if (parentContext == null) return null;
|
if (parentContext == null) return StackValue.none();
|
||||||
|
|
||||||
thisWasUsed = true;
|
thisWasUsed = true;
|
||||||
if (thisExpression != null) return thisExpression;
|
if (thisExpression != null) return thisExpression;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,9 @@ package org.jetbrains.jet.codegen;
|
|||||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.JetDeclarationWithBody;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetNamedFunction;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.objectweb.asm.ClassVisitor;
|
import org.objectweb.asm.ClassVisitor;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
@@ -12,7 +14,6 @@ import org.objectweb.asm.Type;
|
|||||||
import org.objectweb.asm.commons.InstructionAdapter;
|
import org.objectweb.asm.commons.InstructionAdapter;
|
||||||
import org.objectweb.asm.commons.Method;
|
import org.objectweb.asm.commons.Method;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -40,11 +41,10 @@ public class FunctionCodegen {
|
|||||||
ClassContext funContext = owner.intoFunction(functionDescriptor);
|
ClassContext funContext = owner.intoFunction(functionDescriptor);
|
||||||
|
|
||||||
final JetExpression bodyExpression = f.getBodyExpression();
|
final JetExpression bodyExpression = f.getBodyExpression();
|
||||||
final List<JetElement> bodyExpressions = bodyExpression != null ? Collections.<JetElement>singletonList(bodyExpression) : null;
|
generatedMethod(bodyExpression, jvmMethod, funContext, functionDescriptor.getValueParameters(), functionDescriptor.getTypeParameters());
|
||||||
generatedMethod(bodyExpressions, jvmMethod, funContext, functionDescriptor.getValueParameters(), functionDescriptor.getTypeParameters());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generatedMethod(List<JetElement> bodyExpressions,
|
private void generatedMethod(JetExpression bodyExpressions,
|
||||||
Method jvmSignature,
|
Method jvmSignature,
|
||||||
ClassContext context,
|
ClassContext context,
|
||||||
List<ValueParameterDescriptor> paramDescrs,
|
List<ValueParameterDescriptor> paramDescrs,
|
||||||
@@ -95,35 +95,11 @@ public class FunctionCodegen {
|
|||||||
iv.areturn(jvmSignature.getReturnType());
|
iv.areturn(jvmSignature.getReturnType());
|
||||||
}
|
}
|
||||||
else if (!isAbstract) {
|
else if (!isAbstract) {
|
||||||
JetElement last = null;
|
codegen.returnExpression(bodyExpressions);
|
||||||
for (JetElement expression : bodyExpressions) {
|
|
||||||
expression.accept(codegen);
|
|
||||||
last = expression;
|
|
||||||
}
|
|
||||||
generateReturn(mv, last, codegen, jvmSignature);
|
|
||||||
}
|
}
|
||||||
mv.visitMaxs(0, 0);
|
mv.visitMaxs(0, 0);
|
||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateReturn(MethodVisitor mv, JetElement bodyExpression, ExpressionCodegen codegen, Method jvmSignature) {
|
|
||||||
if (!endsWithReturn(bodyExpression)) {
|
|
||||||
if (jvmSignature.getReturnType() == Type.VOID_TYPE) {
|
|
||||||
mv.visitInsn(Opcodes.RETURN);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
codegen.returnTopOfStack();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean endsWithReturn(JetElement bodyExpression) {
|
|
||||||
if (bodyExpression instanceof JetBlockExpression) {
|
|
||||||
final List<JetElement> statements = ((JetBlockExpression) bodyExpression).getStatements();
|
|
||||||
return statements.size() > 0 && statements.get(statements.size()-1) instanceof JetReturnExpression;
|
|
||||||
}
|
|
||||||
|
|
||||||
return bodyExpression instanceof JetReturnExpression;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,8 +48,7 @@ public abstract class StackValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static StackValue onStack(Type type) {
|
public static StackValue onStack(Type type) {
|
||||||
assert type != Type.VOID_TYPE;
|
return type == Type.VOID_TYPE ? none() : new OnStack(type);
|
||||||
return new OnStack(type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static StackValue constant(Object value, Type type) {
|
public static StackValue constant(Object value, Type type) {
|
||||||
@@ -190,6 +189,21 @@ public abstract class StackValue {
|
|||||||
v.mark(end);
|
v.mark(end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static StackValue none() {
|
||||||
|
return None.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class None extends StackValue {
|
||||||
|
public static None INSTANCE = new None();
|
||||||
|
private None() {
|
||||||
|
super(Type.VOID_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void put(Type type, InstructionAdapter v) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class Local extends StackValue {
|
public static class Local extends StackValue {
|
||||||
private final int index;
|
private final int index;
|
||||||
|
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class ArraySize implements IntrinsicMethod {
|
public class ArraySize implements IntrinsicMethod {
|
||||||
@Override
|
@Override
|
||||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver) {
|
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||||
codegen.ensureReceiverOnStack(element, null, JetTypeMapper.TYPE_OBJECT);
|
receiver.put(JetTypeMapper.TYPE_OBJECT, v);
|
||||||
v.arraylength();
|
v.arraylength();
|
||||||
return StackValue.onStack(Type.INT_TYPE);
|
return StackValue.onStack(Type.INT_TYPE);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package org.jetbrains.jet.codegen.intrinsics;
|
|||||||
|
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import org.jetbrains.jet.codegen.ExpressionCodegen;
|
import org.jetbrains.jet.codegen.ExpressionCodegen;
|
||||||
import org.jetbrains.jet.codegen.JetTypeMapper;
|
|
||||||
import org.jetbrains.jet.codegen.StackValue;
|
import org.jetbrains.jet.codegen.StackValue;
|
||||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||||
import org.objectweb.asm.Type;
|
import org.objectweb.asm.Type;
|
||||||
@@ -21,16 +20,16 @@ public class BinaryOp implements IntrinsicMethod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver) {
|
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||||
if (arguments.size() == 1) {
|
if (arguments.size() == 1) {
|
||||||
// intrinsic is called as an ordinary function
|
// intrinsic is called as an ordinary function
|
||||||
codegen.ensureReceiverOnStack(element, null, expectedType);
|
if (receiver != null) {
|
||||||
|
receiver.put(expectedType, v);
|
||||||
|
}
|
||||||
codegen.gen(arguments.get(0), expectedType);
|
codegen.gen(arguments.get(0), expectedType);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!haveReceiver) {
|
codegen.gen(arguments.get(0), expectedType);
|
||||||
codegen.gen(arguments.get(0), expectedType);
|
|
||||||
}
|
|
||||||
codegen.gen(arguments.get(1), expectedType);
|
codegen.gen(arguments.get(1), expectedType);
|
||||||
}
|
}
|
||||||
v.visitInsn(expectedType.getOpcode(opcode));
|
v.visitInsn(expectedType.getOpcode(opcode));
|
||||||
|
|||||||
@@ -14,16 +14,18 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class Concat implements IntrinsicMethod {
|
public class Concat implements IntrinsicMethod {
|
||||||
@Override
|
@Override
|
||||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver) {
|
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||||
codegen.generateStringBuilderConstructor();
|
codegen.generateStringBuilderConstructor();
|
||||||
if (haveReceiver) {
|
if (receiver == null) { // LHS.plus(RHS)
|
||||||
v.swap();
|
v.swap(); // StringBuilder LHS
|
||||||
codegen.invokeAppendMethod(codegen.expressionType(arguments.get(0)));
|
codegen.invokeAppendMethod(codegen.expressionType(arguments.get(0))); // StringBuilder(LHS)
|
||||||
}
|
|
||||||
else {
|
|
||||||
codegen.invokeAppend(arguments.get(0));
|
codegen.invokeAppend(arguments.get(0));
|
||||||
}
|
}
|
||||||
codegen.invokeAppend(arguments.get(1));
|
else { // LHS + RHS
|
||||||
|
codegen.invokeAppend(arguments.get(0)); // StringBuilder(LHS)
|
||||||
|
codegen.invokeAppend(arguments.get(1));
|
||||||
|
}
|
||||||
|
|
||||||
v.invokevirtual(ExpressionCodegen.CLASS_STRING_BUILDER, "toString", "()Ljava/lang/String;");
|
v.invokevirtual(ExpressionCodegen.CLASS_STRING_BUILDER, "toString", "()Ljava/lang/String;");
|
||||||
return StackValue.onStack(Type.getObjectType("java/lang/String"));
|
return StackValue.onStack(Type.getObjectType("java/lang/String"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ public class Increment implements IntrinsicMethod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver) {
|
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||||
final JetExpression operand = arguments.get(0);
|
final JetExpression operand = arguments.get(0);
|
||||||
if (operand instanceof JetReferenceExpression) {
|
if (operand instanceof JetReferenceExpression) {
|
||||||
final int index = codegen.indexOfLocal((JetReferenceExpression) operand);
|
final int index = codegen.indexOfLocal((JetReferenceExpression) operand);
|
||||||
@@ -31,7 +31,7 @@ public class Increment implements IntrinsicMethod {
|
|||||||
return StackValue.local(index, expectedType);
|
return StackValue.local(index, expectedType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StackValue value = codegen.generateIntermediateValue(operand);
|
StackValue value = codegen.genQualified(receiver, operand);
|
||||||
value.dupReceiver(v, 0);
|
value.dupReceiver(v, 0);
|
||||||
value.put(expectedType, v);
|
value.put(expectedType, v);
|
||||||
if (expectedType == Type.LONG_TYPE) {
|
if (expectedType == Type.LONG_TYPE) {
|
||||||
|
|||||||
@@ -14,5 +14,5 @@ import java.util.List;
|
|||||||
* @author yole
|
* @author yole
|
||||||
*/
|
*/
|
||||||
public interface IntrinsicMethod extends Callable {
|
public interface IntrinsicMethod extends Callable {
|
||||||
StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver);
|
StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class Inv implements IntrinsicMethod {
|
public class Inv implements IntrinsicMethod {
|
||||||
@Override
|
@Override
|
||||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver) {
|
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||||
codegen.putTopOfStack(expectedType);
|
receiver.put(expectedType, v);
|
||||||
v.aconst(-1);
|
v.aconst(-1);
|
||||||
v.xor(expectedType);
|
v.xor(expectedType);
|
||||||
return StackValue.onStack(expectedType);
|
return StackValue.onStack(expectedType);
|
||||||
|
|||||||
@@ -14,13 +14,13 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class Not implements IntrinsicMethod {
|
public class Not implements IntrinsicMethod {
|
||||||
@Override
|
@Override
|
||||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver) {
|
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||||
final StackValue stackValue;
|
final StackValue stackValue;
|
||||||
if (arguments.size() == 1) {
|
if (arguments.size() == 1) {
|
||||||
stackValue = codegen.generateIntermediateValue(arguments.get(0));
|
stackValue = codegen.gen(arguments.get(0));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
stackValue = codegen.getReceiverAsStackValue(element, null, expectedType);
|
stackValue = receiver;
|
||||||
}
|
}
|
||||||
return StackValue.not(stackValue);
|
return StackValue.not(stackValue);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class NumberCast implements IntrinsicMethod {
|
public class NumberCast implements IntrinsicMethod {
|
||||||
@Override
|
@Override
|
||||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver) {
|
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||||
codegen.putTopOfStack(expectedType);
|
receiver.put(expectedType, v);
|
||||||
return StackValue.onStack(expectedType);
|
return StackValue.onStack(expectedType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,9 +24,9 @@ public class PsiMethodCall implements IntrinsicMethod {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element,
|
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element,
|
||||||
List<JetExpression> arguments, boolean haveReceiver) {
|
List<JetExpression> arguments, StackValue receiver) {
|
||||||
final CallableMethod callableMethod = codegen.getTypeMapper().mapToCallableMethod(myMethod);
|
final CallableMethod callableMethod = codegen.getTypeMapper().mapToCallableMethod(myMethod);
|
||||||
codegen.invokeMethodWithArguments(callableMethod, (JetCallExpression) element, haveReceiver);
|
codegen.invokeMethodWithArguments(callableMethod, (JetCallExpression) element, receiver);
|
||||||
return StackValue.onStack(callableMethod.getSignature().getReturnType());
|
return StackValue.onStack(callableMethod.getSignature().getReturnType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public class RangeTo implements IntrinsicMethod {
|
|||||||
private static final String CLASS_INT_RANGE = "jet/IntRange";
|
private static final String CLASS_INT_RANGE = "jet/IntRange";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver) {
|
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||||
JetBinaryExpression expression = (JetBinaryExpression) element;
|
JetBinaryExpression expression = (JetBinaryExpression) element;
|
||||||
final Type leftType = codegen.expressionType(expression.getLeft());
|
final Type leftType = codegen.expressionType(expression.getLeft());
|
||||||
if (JetTypeMapper.isIntPrimitive(leftType)) {
|
if (JetTypeMapper.isIntPrimitive(leftType)) {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class TypeInfo implements IntrinsicMethod {
|
public class TypeInfo implements IntrinsicMethod {
|
||||||
@Override
|
@Override
|
||||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver) {
|
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||||
final List<JetTypeProjection> typeArguments = ((JetCallExpression) element).getTypeArguments();
|
final List<JetTypeProjection> typeArguments = ((JetCallExpression) element).getTypeArguments();
|
||||||
if (typeArguments.size() != 1) {
|
if (typeArguments.size() != 1) {
|
||||||
throw new UnsupportedOperationException("one type argument expected");
|
throw new UnsupportedOperationException("one type argument expected");
|
||||||
|
|||||||
@@ -14,12 +14,12 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class UnaryMinus implements IntrinsicMethod {
|
public class UnaryMinus implements IntrinsicMethod {
|
||||||
@Override
|
@Override
|
||||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver) {
|
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||||
if (arguments.size() == 1) {
|
if (arguments.size() == 1) {
|
||||||
codegen.gen(arguments.get(0), expectedType);
|
codegen.gen(arguments.get(0), expectedType);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
codegen.ensureReceiverOnStack(element, null, expectedType);
|
receiver.put(expectedType, v);
|
||||||
}
|
}
|
||||||
v.neg(expectedType);
|
v.neg(expectedType);
|
||||||
return StackValue.onStack(expectedType);
|
return StackValue.onStack(expectedType);
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class ValueTypeInfo implements IntrinsicMethod {
|
public class ValueTypeInfo implements IntrinsicMethod {
|
||||||
@Override
|
@Override
|
||||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver) {
|
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||||
codegen.gen(arguments.get(0), JetTypeMapper.TYPE_JET_OBJECT);
|
codegen.gen(arguments.get(0), JetTypeMapper.TYPE_JET_OBJECT);
|
||||||
v.invokeinterface("jet/JetObject", "getTypeInfo", "()Ljet/typeinfo/TypeInfo;");
|
v.invokeinterface("jet/JetObject", "getTypeInfo", "()Ljet/typeinfo/TypeInfo;");
|
||||||
return StackValue.onStack(JetTypeMapper.TYPE_TYPEINFO);
|
return StackValue.onStack(JetTypeMapper.TYPE_TYPEINFO);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import java.util.List;
|
|||||||
* @author abreslav
|
* @author abreslav
|
||||||
*/
|
*/
|
||||||
public class LocalVariableDescriptor extends VariableDescriptorImpl {
|
public class LocalVariableDescriptor extends VariableDescriptorImpl {
|
||||||
|
private boolean isVar;
|
||||||
public LocalVariableDescriptor(
|
public LocalVariableDescriptor(
|
||||||
@NotNull DeclarationDescriptor containingDeclaration,
|
@NotNull DeclarationDescriptor containingDeclaration,
|
||||||
@NotNull List<AnnotationDescriptor> annotations,
|
@NotNull List<AnnotationDescriptor> annotations,
|
||||||
@@ -19,6 +20,7 @@ public class LocalVariableDescriptor extends VariableDescriptorImpl {
|
|||||||
@Nullable JetType type,
|
@Nullable JetType type,
|
||||||
boolean mutable) {
|
boolean mutable) {
|
||||||
super(containingDeclaration, annotations, name, mutable ? type : null, type);
|
super(containingDeclaration, annotations, name, mutable ? type : null, type);
|
||||||
|
isVar = mutable;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -31,4 +33,9 @@ public class LocalVariableDescriptor extends VariableDescriptorImpl {
|
|||||||
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
|
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
|
||||||
return visitor.visitLocalVariableDescriptor(this, data);
|
return visitor.visitLocalVariableDescriptor(this, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isVar() {
|
||||||
|
return isVar;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,4 +94,9 @@ public class ValueParameterDescriptorImpl extends VariableDescriptorImpl impleme
|
|||||||
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
|
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
|
||||||
return visitor.visitValueParameterDescriptor(this, data);
|
return visitor.visitValueParameterDescriptor(this, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isVar() {
|
||||||
|
return isVar;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,4 +29,6 @@ public interface VariableDescriptor extends DeclarationDescriptor {
|
|||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
VariableDescriptor substitute(TypeSubstitutor substitutor);
|
VariableDescriptor substitute(TypeSubstitutor substitutor);
|
||||||
|
|
||||||
|
boolean isVar();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ public class DataFlowInfo {
|
|||||||
builder.put(variableDescriptor, thisFlags.or(otherFlags));
|
builder.put(variableDescriptor, thisFlags.or(otherFlags));
|
||||||
}
|
}
|
||||||
|
|
||||||
ListMultimap<VariableDescriptor, JetType> newTypeInfo = copyTypeInfo();
|
ListMultimap<VariableDescriptor, JetType> newTypeInfo = Multimaps.newListMultimap(Maps.<VariableDescriptor, Collection<JetType>>newHashMap(), ARRAY_LIST_SUPPLIER);
|
||||||
|
|
||||||
Set<VariableDescriptor> keys = newTypeInfo.keySet();
|
Set<VariableDescriptor> keys = newTypeInfo.keySet();
|
||||||
keys.retainAll(other.typeInfo.keySet());
|
keys.retainAll(other.typeInfo.keySet());
|
||||||
|
|||||||
@@ -1032,10 +1032,18 @@ public class JetTypeInferrer {
|
|||||||
if (!semanticServices.getTypeChecker().isSubtypeOf(enrichedType, context.expectedType)) {
|
if (!semanticServices.getTypeChecker().isSubtypeOf(enrichedType, context.expectedType)) {
|
||||||
context.trace.getErrorHandler().typeMismatch(expression, context.expectedType, expressionType);
|
context.trace.getErrorHandler().typeMismatch(expression, context.expectedType, expressionType);
|
||||||
} else {
|
} else {
|
||||||
context.trace.record(BindingContext.AUTOCAST, expression, context.expectedType);
|
checkAutoCast(expression, context.expectedType, variableDescriptor, context.trace);
|
||||||
}
|
}
|
||||||
return enrichedType;
|
return enrichedType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkAutoCast(JetExpression expression, JetType type, VariableDescriptor variableDescriptor, BindingTrace trace) {
|
||||||
|
if (variableDescriptor.isVar()) {
|
||||||
|
trace.getErrorHandler().genericError(expression.getNode(), "Automatic cast to " + type + " is impossible, because variable " + variableDescriptor.getName() + " is mutable");
|
||||||
|
} else {
|
||||||
|
trace.record(BindingContext.AUTOCAST, expression, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private List<JetType> checkArgumentTypes(@NotNull List<JetType> argumentTypes, @NotNull List<JetExpression> arguments, @NotNull List<TypeProjection> expectedArgumentTypes, @NotNull TypeInferenceContext context) {
|
private List<JetType> checkArgumentTypes(@NotNull List<JetType> argumentTypes, @NotNull List<JetExpression> arguments, @NotNull List<TypeProjection> expectedArgumentTypes, @NotNull TypeInferenceContext context) {
|
||||||
@@ -2381,7 +2389,7 @@ public class JetTypeInferrer {
|
|||||||
for (JetType possibleType : possibleTypes) {
|
for (JetType possibleType : possibleTypes) {
|
||||||
selectorReturnType = getSelectorReturnType(possibleType, selectorExpression, autocastResolutionContext);
|
selectorReturnType = getSelectorReturnType(possibleType, selectorExpression, autocastResolutionContext);
|
||||||
if (selectorReturnType != null) {
|
if (selectorReturnType != null) {
|
||||||
autocastResolutionTrace.record(BindingContext.AUTOCAST, receiverExpression, possibleType);
|
context.services.checkAutoCast(receiverExpression, possibleType, variableDescriptor, autocastResolutionTrace);
|
||||||
autocastResolutionTrace.addAllMyDataTo(context.trace);
|
autocastResolutionTrace.addAllMyDataTo(context.trace);
|
||||||
somethingFound = true;
|
somethingFound = true;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -215,4 +215,39 @@ fun returnFunctionLiteral(a: Any?): Function0<Int> =
|
|||||||
|
|
||||||
fun illegalTupleReturnType(a: Any): (Any, String) = (a, <error>a</error>)
|
fun illegalTupleReturnType(a: Any): (Any, String) = (a, <error>a</error>)
|
||||||
|
|
||||||
fun declarationInsidePattern(x: (Any, Any)): String = when(x) { is (val a is String, *) => <info descr="Automatically cast to String">a</info>; else => "something" }
|
fun declarationInsidePattern(x: (Any, Any)): String = when(x) { is (val a is String, *) => <info descr="Automatically cast to String">a</info>; else => "something" }
|
||||||
|
|
||||||
|
fun mergeAutocasts(a: Any?) {
|
||||||
|
if (a is String || a is Int) {
|
||||||
|
a.<error>compareTo</error>("")
|
||||||
|
a.toString()
|
||||||
|
}
|
||||||
|
if (a is Int || a is String) {
|
||||||
|
a.<error>compareTo</error>("")
|
||||||
|
}
|
||||||
|
when (a) {
|
||||||
|
is String, is Any => a.<error>compareTo</error>("")
|
||||||
|
}
|
||||||
|
if (a is String && a is Any) {
|
||||||
|
val i: Int = <info descr="Automatically cast to String">a</info>.compareTo("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//mutability
|
||||||
|
fun f(): String {
|
||||||
|
var a: Any = 11
|
||||||
|
if (a is String) {
|
||||||
|
val i: String = <error>a</error>
|
||||||
|
<error>a</error>.compareTo("f")
|
||||||
|
val f: Function0<String> = { <error>a</error> }
|
||||||
|
return <error>a</error>
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(var a: Any): Int {
|
||||||
|
if (a is Int) {
|
||||||
|
return <error>a</error>
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user