KT-948 Make type inference work with sure()/!!

!! part fixed
This commit is contained in:
Svetlana Isakova
2012-08-01 17:02:31 +04:00
parent 4e0a9f2af6
commit 6d9529e826
4 changed files with 72 additions and 23 deletions
@@ -793,18 +793,16 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
JetSimpleNameExpression operationSign = expression.getOperationReference();
IElementType operationType = operationSign.getReferencedNameElementType();
// If it's a labeled expression
if (JetTokens.LABELS.contains(operationSign.getReferencedNameElementType())) {
String referencedName = operationSign.getReferencedName();
referencedName = referencedName == null ? " <?>" : referencedName;
context.labelResolver.enterLabeledElement(new LabelName(referencedName.substring(1)), baseExpression);
// TODO : Some processing for the label?
JetTypeInfo typeInfo = facade.getTypeInfo(baseExpression, context, isStatement);
context.labelResolver.exitLabeledElement(baseExpression);
return DataFlowUtils.checkType(typeInfo.getType(), expression, context, typeInfo.getDataFlowInfo());
if (JetTokens.LABELS.contains(operationType)) {
return visitLabeledExpression(expression, context, isStatement);
}
IElementType operationType = operationSign.getReferencedNameElementType();
// Special case for expr!!
if (operationType == JetTokens.EXCLEXCL) {
return visitExclExclExpression(expression, context);
}
// Type check the base expression
JetTypeInfo typeInfo = facade.getTypeInfo(baseExpression, context.replaceExpectedType(NO_EXPECTED_TYPE));
@@ -814,18 +812,6 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
}
DataFlowInfo dataFlowInfo = typeInfo.getDataFlowInfo();
// Special case for expr!!
if (operationType == JetTokens.EXCLEXCL) {
if (isKnownToBeNotNull(baseExpression, context)) {
context.trace.report(UNNECESSARY_NOT_NULL_ASSERTION.on(operationSign, type));
}
else {
DataFlowValue value = DataFlowValueFactory.INSTANCE.createDataFlowValue(baseExpression, type, context.trace.getBindingContext());
dataFlowInfo = dataFlowInfo.disequate(value, DataFlowValue.NULL);
}
return DataFlowUtils.checkType(TypeUtils.makeNotNullable(type), expression, context, dataFlowInfo);
}
// Conventions for unary operations
Name name = OperatorConventions.UNARY_OPERATION_NAMES.get(operationType);
if (name == null) {
@@ -882,6 +868,51 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
return DataFlowUtils.checkType(result, expression, context, dataFlowInfo);
}
private JetTypeInfo visitExclExclExpression(@NotNull JetUnaryExpression expression, @NotNull ExpressionTypingContext context) {
JetExpression baseExpression = expression.getBaseExpression();
assert baseExpression != null;
JetSimpleNameExpression operationSign = expression.getOperationReference();
assert operationSign.getReferencedNameElementType() == JetTokens.EXCLEXCL;
JetType expectedType;
if (context.expectedType != NO_EXPECTED_TYPE) {
expectedType = TypeUtils.makeNullable(context.expectedType);
}
else {
expectedType = NO_EXPECTED_TYPE;
}
JetTypeInfo typeInfo = facade.getTypeInfo(baseExpression, context.replaceExpectedType(expectedType));
JetType type = typeInfo.getType();
if (type == null) {
return typeInfo;
}
DataFlowInfo dataFlowInfo = typeInfo.getDataFlowInfo();
if (isKnownToBeNotNull(baseExpression, context)) {
context.trace.report(UNNECESSARY_NOT_NULL_ASSERTION.on(operationSign, type));
}
else {
DataFlowValue value = DataFlowValueFactory.INSTANCE.createDataFlowValue(baseExpression, type, context.trace.getBindingContext());
dataFlowInfo = dataFlowInfo.disequate(value, DataFlowValue.NULL);
}
return JetTypeInfo.create(TypeUtils.makeNotNullable(type), dataFlowInfo);
}
private JetTypeInfo visitLabeledExpression(@NotNull JetUnaryExpression expression, @NotNull ExpressionTypingContext context,
boolean isStatement) {
JetExpression baseExpression = expression.getBaseExpression();
assert baseExpression != null;
JetSimpleNameExpression operationSign = expression.getOperationReference();
assert JetTokens.LABELS.contains(operationSign.getReferencedNameElementType());
String referencedName = operationSign.getReferencedName();
referencedName = referencedName == null ? " <?>" : referencedName;
context.labelResolver.enterLabeledElement(new LabelName(referencedName.substring(1)), baseExpression);
// TODO : Some processing for the label?
JetTypeInfo typeInfo = facade.getTypeInfo(baseExpression, context, isStatement);
context.labelResolver.exitLabeledElement(baseExpression);
return DataFlowUtils.checkType(typeInfo.getType(), expression, context, typeInfo.getDataFlowInfo());
}
private boolean isKnownToBeNotNull(JetExpression expression, ExpressionTypingContext context) {
JetType type = context.trace.get(EXPRESSION_TYPE, expression);
assert type != null : "This method is only supposed to be called when the type is not null";
@@ -0,0 +1,18 @@
package a
import java.util.*
fun <T> emptyList() : List<T>? = ArrayList<T>()
fun foo() {
// type arguments shouldn't be required
val <!UNUSED_VARIABLE!>l<!> : List<Int> = emptyList()!!
val <!UNUSED_VARIABLE!>l1<!> = <!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>emptyList<!>()!!
emptyList()!! : List<Int>
emptyList() : List<Int>?
doWithList(emptyList()!!)
}
fun doWithList(list: List<Int>) = list
@@ -30,6 +30,6 @@ fun main(args : Array<String>) {
}
}
val <!UNUSED_VARIABLE!>f<!> : String = <!TYPE_MISMATCH!>a<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!><!>
val <!UNUSED_VARIABLE!>f<!> : String = <!TYPE_MISMATCH!>a<!><!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
<!TYPE_MISMATCH!>a<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!><!> : String
}
@@ -2,7 +2,7 @@ fun main(args : Array<String>) {
val a : Int? = null;
var v = 1
val <!UNUSED_VARIABLE!>b<!> : String = <!TYPE_MISMATCH!>v<!>;
val <!UNUSED_VARIABLE!>f<!> : String = <!TYPE_MISMATCH!>a!!<!>;
val <!UNUSED_VARIABLE!>f<!> : String = <!TYPE_MISMATCH!>a<!>!!;
val <!UNUSED_VARIABLE!>g<!> : String = <!TYPE_MISMATCH!>v++<!>;
val <!UNUSED_VARIABLE!>g1<!> : String = <!TYPE_MISMATCH!>++v<!>;
val <!UNUSED_VARIABLE!>h<!> : String = <!TYPE_MISMATCH!>v--<!>;