bug with automatically casting mutable variables (KT-228) fixed

This commit is contained in:
svtk
2011-08-23 11:44:56 +04:00
parent 3f4f0c8737
commit 847c727ad0
9 changed files with 64 additions and 22 deletions
@@ -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<AnnotationDescriptor> 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, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D 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) {
return visitor.visitValueParameterDescriptor(this, data);
}
@Override
public boolean isVar() {
return isVar;
}
}
@@ -29,4 +29,6 @@ public interface VariableDescriptor extends DeclarationDescriptor {
@NotNull
@Override
VariableDescriptor substitute(TypeSubstitutor substitutor);
boolean isVar();
}
@@ -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();
@@ -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) {
@@ -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
@@ -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<JetType> 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<JetType> 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 {
+20 -1
View File
@@ -229,6 +229,25 @@ fun mergeAutocasts(a: Any?) {
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>.length
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
}
@@ -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) {
}