From 847c727ad06da9b435fe4c7379ec3f8ad15de72f Mon Sep 17 00:00:00 2001 From: svtk Date: Tue, 23 Aug 2011 11:44:56 +0400 Subject: [PATCH] bug with automatically casting mutable variables (KT-228) fixed --- .../descriptors/LocalVariableDescriptor.java | 7 ++++ .../ValueParameterDescriptorImpl.java | 5 +++ .../lang/descriptors/VariableDescriptor.java | 2 ++ .../jet/lang/resolve/BindingTrace.java | 3 +- .../jet/lang/resolve/BindingTraceAdapter.java | 5 +-- .../jet/lang/resolve/BindingTraceContext.java | 9 ++++-- .../jet/lang/types/JetTypeInferrer.java | 32 ++++++++++--------- idea/testData/checker/infos/Autocasts.jet | 21 +++++++++++- .../tests/org/jetbrains/jet/JetTestUtils.java | 2 +- 9 files changed, 64 insertions(+), 22 deletions(-) diff --git a/idea/src/org/jetbrains/jet/lang/descriptors/LocalVariableDescriptor.java b/idea/src/org/jetbrains/jet/lang/descriptors/LocalVariableDescriptor.java index 9cc0de63485..171bb870095 100644 --- a/idea/src/org/jetbrains/jet/lang/descriptors/LocalVariableDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/descriptors/LocalVariableDescriptor.java @@ -12,6 +12,7 @@ import java.util.List; * @author abreslav */ public class LocalVariableDescriptor extends VariableDescriptorImpl { + private boolean isVar; public LocalVariableDescriptor( @NotNull DeclarationDescriptor containingDeclaration, @NotNull List annotations, @@ -19,6 +20,7 @@ public class LocalVariableDescriptor extends VariableDescriptorImpl { @Nullable JetType type, boolean mutable) { super(containingDeclaration, annotations, name, mutable ? type : null, type); + isVar = mutable; } @NotNull @@ -31,4 +33,9 @@ public class LocalVariableDescriptor extends VariableDescriptorImpl { public R accept(DeclarationDescriptorVisitor visitor, D data) { return visitor.visitLocalVariableDescriptor(this, data); } + + @Override + public boolean isVar() { + return isVar; + } } diff --git a/idea/src/org/jetbrains/jet/lang/descriptors/ValueParameterDescriptorImpl.java b/idea/src/org/jetbrains/jet/lang/descriptors/ValueParameterDescriptorImpl.java index 1cb7663d839..d4021b21a3f 100644 --- a/idea/src/org/jetbrains/jet/lang/descriptors/ValueParameterDescriptorImpl.java +++ b/idea/src/org/jetbrains/jet/lang/descriptors/ValueParameterDescriptorImpl.java @@ -94,4 +94,9 @@ public class ValueParameterDescriptorImpl extends VariableDescriptorImpl impleme public R accept(DeclarationDescriptorVisitor visitor, D data) { return visitor.visitValueParameterDescriptor(this, data); } + + @Override + public boolean isVar() { + return isVar; + } } diff --git a/idea/src/org/jetbrains/jet/lang/descriptors/VariableDescriptor.java b/idea/src/org/jetbrains/jet/lang/descriptors/VariableDescriptor.java index c79eabb9fe8..1d942a63393 100644 --- a/idea/src/org/jetbrains/jet/lang/descriptors/VariableDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/descriptors/VariableDescriptor.java @@ -29,4 +29,6 @@ public interface VariableDescriptor extends DeclarationDescriptor { @NotNull @Override VariableDescriptor substitute(TypeSubstitutor substitutor); + + boolean isVar(); } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/BindingTrace.java b/idea/src/org/jetbrains/jet/lang/resolve/BindingTrace.java index b718ba1006d..6404919e50c 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/BindingTrace.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/BindingTrace.java @@ -5,6 +5,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.ErrorHandlerWithRegions; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; +import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; @@ -43,7 +44,7 @@ public interface BindingTrace { void requireBackingField(@NotNull PropertyDescriptor propertyDescriptor); - void recordAutoCast(@NotNull JetExpression expression, @NotNull JetType type); + void recordAutoCast(@NotNull JetExpression expression, @NotNull JetType type, @NotNull VariableDescriptor variableDescriptor); @NotNull ErrorHandlerWithRegions getErrorHandler(); diff --git a/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceAdapter.java b/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceAdapter.java index 4df6456f756..cd2aa8fcb61 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceAdapter.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceAdapter.java @@ -5,6 +5,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.ErrorHandlerWithRegions; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; +import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; @@ -17,8 +18,8 @@ public class BindingTraceAdapter implements BindingTrace { private final BindingTrace originalTrace; @Override - public void recordAutoCast(@NotNull JetExpression expression, @NotNull JetType type) { - originalTrace.recordAutoCast(expression, type); + public void recordAutoCast(@NotNull JetExpression expression, @NotNull JetType type, @NotNull VariableDescriptor variableDescriptor) { + originalTrace.recordAutoCast(expression, type, variableDescriptor); } public BindingTraceAdapter(BindingTrace originalTrace) { diff --git a/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java b/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java index b629e475a75..075ba9098ed 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java @@ -167,8 +167,13 @@ public class BindingTraceContext implements BindingContext, BindingTrace { } @Override - public void recordAutoCast(@NotNull JetExpression expression, @NotNull JetType type) { - safePut(autoCasts, expression, type); + public void recordAutoCast(@NotNull JetExpression expression, @NotNull JetType type, @NotNull VariableDescriptor variableDescriptor) { + if (variableDescriptor.isVar()) { + getErrorHandler().genericError(expression.getNode(), "Automatic cast to " + type + " is impossible, because variable " + variableDescriptor.getName() + " is mutable"); + } + else { + safePut(autoCasts, expression, type); + } } @Override diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java index 4c201d48c4c..2fe80bf87a8 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java @@ -763,29 +763,31 @@ public class JetTypeInferrer { semanticServices.getTypeChecker().isSubtypeOf(expressionType, context.expectedType)) { return expressionType; } - VariableDescriptor variableDescriptor = getVariableDescriptorFromSimpleName(expression, context); - if (variableDescriptor == null) return expressionType; - JetType enrichedType = null; - List possibleTypes = Lists.newArrayList(context.dataFlowInfo.getPossibleTypes(variableDescriptor)); - Collections.reverse(possibleTypes); - for (JetType possibleType: possibleTypes) { - if (semanticServices.getTypeChecker().isSubtypeOf(possibleType, context.expectedType)) { - enrichedType = possibleType; - break; + + VariableDescriptor variableDescriptor = getVariableDescriptorFromSimpleName(expression, context); + if (variableDescriptor != null) { + + List possibleTypes = Lists.newArrayList(context.dataFlowInfo.getPossibleTypes(variableDescriptor)); + Collections.reverse(possibleTypes); + for (JetType possibleType : possibleTypes) { + if (semanticServices.getTypeChecker().isSubtypeOf(possibleType, context.expectedType)) { + enrichedType = possibleType; + break; + } + } + if (enrichedType == null) { + enrichedType = context.dataFlowInfo.getOutType(variableDescriptor); } - } - if (enrichedType == null) { - enrichedType = context.dataFlowInfo.getOutType(variableDescriptor); } if (enrichedType == null) { enrichedType = expressionType; } - if (!semanticServices.getTypeChecker().isSubtypeOf(enrichedType, context.expectedType)) { + if (variableDescriptor == null || !semanticServices.getTypeChecker().isSubtypeOf(enrichedType, context.expectedType)) { context.trace.getErrorHandler().typeMismatch(expression, context.expectedType, expressionType); } else { - context.trace.recordAutoCast(expression, context.expectedType); + context.trace.recordAutoCast(expression, context.expectedType, variableDescriptor); } return enrichedType; } @@ -2120,7 +2122,7 @@ public class JetTypeInferrer { selectorReturnType = getSelectorReturnType(possibleType, selectorExpression, context); if (selectorReturnType != null) { regionToCommit = errorHandler.closeAndReturnCurrentRegion(); - context.trace.recordAutoCast(receiverExpression, possibleType); + context.trace.recordAutoCast(receiverExpression, possibleType, variableDescriptor); break; } else { diff --git a/idea/testData/checker/infos/Autocasts.jet b/idea/testData/checker/infos/Autocasts.jet index caf2ce8bcbf..a984f13d017 100644 --- a/idea/testData/checker/infos/Autocasts.jet +++ b/idea/testData/checker/infos/Autocasts.jet @@ -229,6 +229,25 @@ fun mergeAutocasts(a: Any?) { is String, is Any => a.compareTo("") } if (a is String && a is Any) { - val i: Int = a.length + val i: Int = a.compareTo("") } +} + +//mutability +fun f(): String { + var a: Any = 11 + if (a is String) { + val i: String = a + a.compareTo("f") + val f: Function0 = { a } + return a + } + return "" +} + +fun foo(var a: Any): Int { + if (a is Int) { + return a + } + return 1 } \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/JetTestUtils.java b/idea/tests/org/jetbrains/jet/JetTestUtils.java index 96e8bf142e6..ac1c2d5da50 100644 --- a/idea/tests/org/jetbrains/jet/JetTestUtils.java +++ b/idea/tests/org/jetbrains/jet/JetTestUtils.java @@ -83,7 +83,7 @@ public class JetTestUtils { } @Override - public void recordAutoCast(@NotNull JetExpression expression, @NotNull JetType type) { + public void recordAutoCast(@NotNull JetExpression expression, @NotNull JetType type, @NotNull VariableDescriptor variableDescriptor) { }