KT-948 Make type inference work with sure()/!!
!! part fixed
This commit is contained in:
+52
-21
@@ -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--<!>;
|
||||
|
||||
Reference in New Issue
Block a user