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();
|
JetSimpleNameExpression operationSign = expression.getOperationReference();
|
||||||
|
|
||||||
|
IElementType operationType = operationSign.getReferencedNameElementType();
|
||||||
// If it's a labeled expression
|
// If it's a labeled expression
|
||||||
if (JetTokens.LABELS.contains(operationSign.getReferencedNameElementType())) {
|
if (JetTokens.LABELS.contains(operationType)) {
|
||||||
String referencedName = operationSign.getReferencedName();
|
return visitLabeledExpression(expression, context, isStatement);
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IElementType operationType = operationSign.getReferencedNameElementType();
|
// Special case for expr!!
|
||||||
|
if (operationType == JetTokens.EXCLEXCL) {
|
||||||
|
return visitExclExclExpression(expression, context);
|
||||||
|
}
|
||||||
|
|
||||||
// Type check the base expression
|
// Type check the base expression
|
||||||
JetTypeInfo typeInfo = facade.getTypeInfo(baseExpression, context.replaceExpectedType(NO_EXPECTED_TYPE));
|
JetTypeInfo typeInfo = facade.getTypeInfo(baseExpression, context.replaceExpectedType(NO_EXPECTED_TYPE));
|
||||||
@@ -814,18 +812,6 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
DataFlowInfo dataFlowInfo = typeInfo.getDataFlowInfo();
|
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
|
// Conventions for unary operations
|
||||||
Name name = OperatorConventions.UNARY_OPERATION_NAMES.get(operationType);
|
Name name = OperatorConventions.UNARY_OPERATION_NAMES.get(operationType);
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
@@ -882,6 +868,51 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
return DataFlowUtils.checkType(result, expression, context, dataFlowInfo);
|
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) {
|
private boolean isKnownToBeNotNull(JetExpression expression, ExpressionTypingContext context) {
|
||||||
JetType type = context.trace.get(EXPRESSION_TYPE, expression);
|
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";
|
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
|
<!TYPE_MISMATCH!>a<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!><!> : String
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@ fun main(args : Array<String>) {
|
|||||||
val a : Int? = null;
|
val a : Int? = null;
|
||||||
var v = 1
|
var v = 1
|
||||||
val <!UNUSED_VARIABLE!>b<!> : String = <!TYPE_MISMATCH!>v<!>;
|
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!>g<!> : String = <!TYPE_MISMATCH!>v++<!>;
|
||||||
val <!UNUSED_VARIABLE!>g1<!> : String = <!TYPE_MISMATCH!>++v<!>;
|
val <!UNUSED_VARIABLE!>g1<!> : String = <!TYPE_MISMATCH!>++v<!>;
|
||||||
val <!UNUSED_VARIABLE!>h<!> : String = <!TYPE_MISMATCH!>v--<!>;
|
val <!UNUSED_VARIABLE!>h<!> : String = <!TYPE_MISMATCH!>v--<!>;
|
||||||
|
|||||||
Reference in New Issue
Block a user