bug with automatically casting mutable variables (KT-228) fixed
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user