Merge pull request #81 from udalov/kt2164

KT-2164 & KT-2216
This commit is contained in:
Svetlana Isakova
2012-06-19 06:02:21 -07:00
13 changed files with 197 additions and 69 deletions
@@ -68,6 +68,7 @@ public interface BindingContext {
WritableSlice<JetExpression, CompileTimeConstant<?>> COMPILE_TIME_VALUE = Slices.createSimpleSlice();
WritableSlice<JetTypeReference, JetType> TYPE = Slices.createSimpleSlice();
WritableSlice<JetExpression, JetType> EXPRESSION_TYPE = new BasicWritableSlice<JetExpression, JetType>(DO_NOTHING);
WritableSlice<JetExpression, DataFlowInfo> EXPRESSION_DATA_FLOW_INFO = new BasicWritableSlice<JetExpression, DataFlowInfo>(DO_NOTHING);
WritableSlice<JetReferenceExpression, DeclarationDescriptor> REFERENCE_TARGET = new BasicWritableSlice<JetReferenceExpression, DeclarationDescriptor>(DO_NOTHING);
WritableSlice<JetElement, ResolvedCall<? extends CallableDescriptor>> RESOLVED_CALL = new BasicWritableSlice<JetElement, ResolvedCall<? extends CallableDescriptor>>(DO_NOTHING);
@@ -767,6 +767,7 @@ public class CallResolver {
private <D extends CallableDescriptor, F extends D> ResolutionStatus checkValueArgumentTypes(CallResolutionContext<D, F> context) {
ResolutionStatus result = SUCCESS;
DataFlowInfo dataFlowInfo = context.dataFlowInfo;
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : context.candidateCall.getValueArguments().entrySet()) {
ValueParameterDescriptor parameterDescriptor = entry.getKey();
ResolvedValueArgument resolvedArgument = entry.getValue();
@@ -777,7 +778,9 @@ public class CallResolver {
if (expression == null) continue;
JetType expectedType = getEffectiveExpectedType(parameterDescriptor, argument);
JetType type = expressionTypingServices.getType(context.scope, expression, expectedType, context.dataFlowInfo, context.candidateCall.getTrace());
JetTypeInfo typeInfo = expressionTypingServices.getTypeInfo(context.scope, expression, expectedType, dataFlowInfo, context.candidateCall.getTrace());
JetType type = typeInfo.getType();
dataFlowInfo = dataFlowInfo.and(typeInfo.getDataFlowInfo());
if (type == null || ErrorUtils.isErrorType(type)) {
context.candidateCall.argumentHasNoType();
}
@@ -65,7 +65,7 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements ResolvedC
private final Map<TypeParameterDescriptor, JetType> typeArguments = Maps.newLinkedHashMap();
private final Map<ValueParameterDescriptor, JetType> autoCasts = Maps.newHashMap();
private final Map<ValueParameterDescriptor, ResolvedValueArgument> valueArguments = Maps.newHashMap();
private final Map<ValueParameterDescriptor, ResolvedValueArgument> valueArguments = Maps.newLinkedHashMap();
private boolean someArgumentHasNoType = false;
private TemporaryBindingTrace trace;
private ResolutionStatus status = UNKNOWN_STATUS;
@@ -33,6 +33,7 @@ import org.jetbrains.jet.lang.resolve.calls.CallMaker;
import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults;
import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResultsUtil;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValue;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValueFactory;
import org.jetbrains.jet.lang.resolve.constants.*;
import org.jetbrains.jet.lang.resolve.constants.StringValue;
@@ -72,9 +73,10 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
public JetTypeInfo visitSimpleNameExpression(JetSimpleNameExpression expression, ExpressionTypingContext context) {
// TODO : other members
// TODO : type substitutions???
JetType type = DataFlowUtils.checkType(getSelectorReturnType(NO_RECEIVER, null, expression, context), expression, context);
JetTypeInfo typeInfo = getSelectorReturnTypeInfo(NO_RECEIVER, null, expression, context);
JetType type = DataFlowUtils.checkType(typeInfo.getType(), expression, context);
ExpressionTypingUtils.checkWrappingInRef(expression, context);
return JetTypeInfo.create(type, context.dataFlowInfo); // TODO : Extensions to this
return JetTypeInfo.create(type, typeInfo.getDataFlowInfo()); // TODO : Extensions to this
}
@Nullable
@@ -192,37 +194,41 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
public JetTypeInfo visitBinaryWithTypeRHSExpression(JetBinaryExpressionWithTypeRHS expression, ExpressionTypingContext context) {
JetTypeReference right = expression.getRight();
JetType result = null;
DataFlowInfo dataFlowInfo = context.dataFlowInfo;
if (right != null) {
JetType targetType = context.expressionTypingServices.getTypeResolver().resolveType(context.scope, right, context.trace, true);
boolean tryWithNoExpectedType = true;
if (isTypeFlexible(expression.getLeft()) || expression.getOperationSign().getReferencedNameElementType() == JetTokens.COLON) {
TemporaryBindingTrace temporaryTraceWithExpectedType = TemporaryBindingTrace.create(context.trace);
boolean success = checkBinaryWithTypeRHS(expression, context.replaceBindingTrace(temporaryTraceWithExpectedType).replaceExpectedType(targetType), targetType);
if (success) {
ExpressionTypingContext contextWithTemporaryTrace = context.replaceBindingTrace(temporaryTraceWithExpectedType).replaceExpectedType(targetType);
JetTypeInfo typeInfo = facade.getTypeInfo(expression.getLeft(), contextWithTemporaryTrace);
if (typeInfo.getType() != null && checkBinaryWithTypeRHS(expression, contextWithTemporaryTrace, targetType, typeInfo.getType())) {
temporaryTraceWithExpectedType.commit();
}
else {
checkBinaryWithTypeRHS(expression, context.replaceExpectedType(NO_EXPECTED_TYPE), targetType);
dataFlowInfo = typeInfo.getDataFlowInfo();
tryWithNoExpectedType = false;
}
}
else {
checkBinaryWithTypeRHS(expression, context.replaceExpectedType(NO_EXPECTED_TYPE), targetType);
if (tryWithNoExpectedType) {
ExpressionTypingContext contextWithNoExpectedType = context.replaceExpectedType(NO_EXPECTED_TYPE);
JetTypeInfo typeInfo = facade.getTypeInfo(expression.getLeft(), contextWithNoExpectedType);
if (typeInfo.getType() != null) {
checkBinaryWithTypeRHS(expression, contextWithNoExpectedType, targetType, typeInfo.getType());
dataFlowInfo = typeInfo.getDataFlowInfo();
}
}
IElementType operationType = expression.getOperationSign().getReferencedNameElementType();
result = operationType == JetTokens.AS_SAFE ? TypeUtils.makeNullable(targetType) : targetType;
}
else {
facade.getTypeInfo(expression.getLeft(), context.replaceExpectedType(NO_EXPECTED_TYPE));
dataFlowInfo = facade.getTypeInfo(expression.getLeft(), context.replaceExpectedType(NO_EXPECTED_TYPE)).getDataFlowInfo();
}
return DataFlowUtils.checkType(result, expression, context, context.dataFlowInfo);
return DataFlowUtils.checkType(result, expression, context, dataFlowInfo);
}
private boolean checkBinaryWithTypeRHS(JetBinaryExpressionWithTypeRHS expression, ExpressionTypingContext context, @NotNull JetType targetType) {
JetType actualType = facade.getTypeInfo(expression.getLeft(), context).getType();
if (actualType == null) return false;
private boolean checkBinaryWithTypeRHS(JetBinaryExpressionWithTypeRHS expression, ExpressionTypingContext context, @NotNull JetType targetType, JetType actualType) {
JetSimpleNameExpression operationSign = expression.getOperationSign();
IElementType operationType = operationSign.getReferencedNameElementType();
if (operationType == JetTokens.COLON) {
@@ -537,11 +543,14 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
if (selectorExpression == null) return JetTypeInfo.create(null, context.dataFlowInfo);
if (receiverType == null) receiverType = ErrorUtils.createErrorType("Type for " + expression.getText());
context = context.replaceDataFlowInfo(receiverTypeInfo.getDataFlowInfo());
if (selectorExpression instanceof JetSimpleNameExpression) {
propagateConstantValues(expression, context, (JetSimpleNameExpression) selectorExpression);
}
JetType selectorReturnType = getSelectorReturnType(new ExpressionReceiver(receiverExpression, receiverType), expression.getOperationTokenNode(), selectorExpression, context);
JetTypeInfo selectorReturnTypeInfo = getSelectorReturnTypeInfo(new ExpressionReceiver(receiverExpression, receiverType), expression.getOperationTokenNode(), selectorExpression, context);
JetType selectorReturnType = selectorReturnTypeInfo.getType();
//TODO move further
if (expression.getOperationSign() == JetTokens.SAFE_ACCESS) {
@@ -552,12 +561,11 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
}
}
JetType result = selectorReturnType;
// TODO : this is suspicious: remove this code?
if (result != null) {
context.trace.record(BindingContext.EXPRESSION_TYPE, selectorExpression, result);
if (selectorReturnType != null) {
context.trace.record(BindingContext.EXPRESSION_TYPE, selectorExpression, selectorReturnType);
}
return DataFlowUtils.checkType(result, expression, context, receiverTypeInfo.getDataFlowInfo());
return DataFlowUtils.checkType(selectorReturnType, expression, context, selectorReturnTypeInfo.getDataFlowInfo());
}
private void propagateConstantValues(JetQualifiedExpression expression, ExpressionTypingContext context, JetSimpleNameExpression selectorExpression) {
@@ -639,34 +647,33 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
return null;
}
@Nullable
public JetType getSelectorReturnType(@NotNull ReceiverDescriptor receiver, @Nullable ASTNode callOperationNode, @NotNull JetExpression selectorExpression, @NotNull ExpressionTypingContext context) {
@NotNull
public JetTypeInfo getSelectorReturnTypeInfo(@NotNull ReceiverDescriptor receiver, @Nullable ASTNode callOperationNode, @NotNull JetExpression selectorExpression, @NotNull ExpressionTypingContext context) {
if (selectorExpression instanceof JetCallExpression) {
return getCallExpressionType((JetCallExpression) selectorExpression, receiver, callOperationNode, context);
return getCallExpressionTypeInfo((JetCallExpression) selectorExpression, receiver, callOperationNode, context);
}
else if (selectorExpression instanceof JetSimpleNameExpression) {
return getSimpleNameExpressionType((JetSimpleNameExpression) selectorExpression, receiver, callOperationNode, context);
return getSimpleNameExpressionTypeInfo((JetSimpleNameExpression) selectorExpression, receiver, callOperationNode, context);
}
else if (selectorExpression instanceof JetQualifiedExpression) {
JetQualifiedExpression qualifiedExpression = (JetQualifiedExpression) selectorExpression;
JetExpression newReceiverExpression = qualifiedExpression.getReceiverExpression();
JetType newReceiverType = getSelectorReturnType(receiver, callOperationNode, newReceiverExpression, context.replaceExpectedType(NO_EXPECTED_TYPE));
JetTypeInfo newReceiverTypeInfo = getSelectorReturnTypeInfo(receiver, callOperationNode, newReceiverExpression, context.replaceExpectedType(NO_EXPECTED_TYPE));
JetType newReceiverType = newReceiverTypeInfo.getType();
DataFlowInfo newReceiverDataFlowInfo = newReceiverTypeInfo.getDataFlowInfo();
JetExpression newSelectorExpression = qualifiedExpression.getSelectorExpression();
if (newReceiverType != null && newSelectorExpression != null) {
return getSelectorReturnType(new ExpressionReceiver(newReceiverExpression, newReceiverType), qualifiedExpression.getOperationTokenNode(), newSelectorExpression, context);
return getSelectorReturnTypeInfo(new ExpressionReceiver(newReceiverExpression, newReceiverType), qualifiedExpression.getOperationTokenNode(), newSelectorExpression, context.replaceDataFlowInfo(newReceiverDataFlowInfo));
}
}
else {
context.trace.report(ILLEGAL_SELECTOR.on(selectorExpression, selectorExpression.getText()));
}
return null;
return JetTypeInfo.create(null, context.dataFlowInfo);
}
@Nullable
private JetType getSimpleNameExpressionType(@NotNull JetSimpleNameExpression nameExpression, @NotNull ReceiverDescriptor receiver,
@NotNull
private JetTypeInfo getSimpleNameExpressionTypeInfo(@NotNull JetSimpleNameExpression nameExpression, @NotNull ReceiverDescriptor receiver,
@Nullable ASTNode callOperationNode, @NotNull ExpressionTypingContext context) {
boolean[] result = new boolean[1];
@@ -675,7 +682,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
JetType type = getVariableType(nameExpression, receiver, callOperationNode, context.replaceBindingTrace(traceForVariable), result);
if (result[0]) {
traceForVariable.commit();
return type;
return JetTypeInfo.create(type, context.dataFlowInfo);
}
Call call = CallMaker.makeCall(nameExpression, receiver, callOperationNode, nameExpression, Collections.<ValueArgument>emptyList());
@@ -685,15 +692,16 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
traceForFunction.commit();
boolean hasValueParameters = functionDescriptor == null || functionDescriptor.getValueParameters().size() > 0;
context.trace.report(FUNCTION_CALL_EXPECTED.on(nameExpression, nameExpression, hasValueParameters));
return functionDescriptor != null ? functionDescriptor.getReturnType() : null;
type = functionDescriptor != null ? functionDescriptor.getReturnType() : null;
return JetTypeInfo.create(type, context.dataFlowInfo);
}
traceForVariable.commit();
return null;
return JetTypeInfo.create(null, context.dataFlowInfo);
}
@Nullable
private JetType getCallExpressionType(@NotNull JetCallExpression callExpression, @NotNull ReceiverDescriptor receiver,
@NotNull
private JetTypeInfo getCallExpressionTypeInfo(@NotNull JetCallExpression callExpression, @NotNull ReceiverDescriptor receiver,
@Nullable ASTNode callOperationNode, @NotNull ExpressionTypingContext context) {
boolean[] result = new boolean[1];
@@ -709,7 +717,22 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
boolean hasValueParameters = functionDescriptor == null || functionDescriptor.getValueParameters().size() > 0;
context.trace.report(FUNCTION_CALL_EXPECTED.on(callExpression, callExpression, hasValueParameters));
}
return functionDescriptor != null ? functionDescriptor.getReturnType() : null;
if (functionDescriptor == null) {
return JetTypeInfo.create(null, context.dataFlowInfo);
}
JetType type = functionDescriptor.getReturnType();
DataFlowInfo dataFlowInfo = context.dataFlowInfo;
JetValueArgumentList argumentList = callExpression.getValueArgumentList();
if (argumentList != null) {
for (JetValueArgument argument : argumentList.getArguments()) {
JetExpression expression = argument.getArgumentExpression();
if (expression != null) {
dataFlowInfo = dataFlowInfo.and(facade.getTypeInfo(expression, context.replaceDataFlowInfo(dataFlowInfo)).getDataFlowInfo());
}
}
}
return JetTypeInfo.create(type, dataFlowInfo);
}
JetExpression calleeExpression = callExpression.getCalleeExpression();
@@ -721,11 +744,11 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
traceForVariable.commit();
context.trace.report(FUNCTION_EXPECTED.on((JetReferenceExpression) calleeExpression, calleeExpression,
type != null ? type : ErrorUtils.createErrorType("")));
return null;
return JetTypeInfo.create(null, context.dataFlowInfo);
}
}
traceForFunction.commit();
return null;
return JetTypeInfo.create(null, context.dataFlowInfo);
}
private static void checkSuper(@NotNull ReceiverDescriptor receiverDescriptor, @NotNull OverloadResolutionResults<? extends CallableDescriptor> results,
@@ -743,8 +766,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
@Override
public JetTypeInfo visitCallExpression(JetCallExpression expression, ExpressionTypingContext context) {
JetType expressionType = getCallExpressionType(expression, NO_RECEIVER, null, context);
return DataFlowUtils.checkType(expressionType, expression, context, context.dataFlowInfo);
JetTypeInfo expressionTypeInfo = getCallExpressionTypeInfo(expression, NO_RECEIVER, null, context);
return DataFlowUtils.checkType(expressionTypeInfo.getType(), expression, context, expressionTypeInfo.getDataFlowInfo());
}
@Override
@@ -784,6 +807,10 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
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);
}
@@ -22,17 +22,16 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.JetTypeInfo;
/**
* @author abreslav
*/
/*package*/ interface ExpressionTypingInternals extends ExpressionTypingFacade {
@Nullable
JetType getSelectorReturnType(@NotNull ReceiverDescriptor receiver, @Nullable ASTNode callOperationNode, @NotNull JetExpression selectorExpression, @NotNull ExpressionTypingContext context);
@NotNull
JetTypeInfo getSelectorReturnTypeInfo(@NotNull ReceiverDescriptor receiver, @Nullable ASTNode callOperationNode, @NotNull JetExpression selectorExpression, @NotNull ExpressionTypingContext context);
boolean checkInExpression(JetElement callElement, @NotNull JetSimpleNameExpression operationSign, @Nullable JetExpression left, @NotNull JetExpression right, ExpressionTypingContext context);
@@ -115,12 +115,17 @@ public class ExpressionTypingServices {
return ErrorUtils.createErrorType("Type for " + expression.getText());
}
@Nullable
public JetType getType(@NotNull final JetScope scope, @NotNull JetExpression expression, @NotNull JetType expectedType, @NotNull DataFlowInfo dataFlowInfo, @NotNull BindingTrace trace) {
@NotNull
public JetTypeInfo getTypeInfo(@NotNull final JetScope scope, @NotNull JetExpression expression, @NotNull JetType expectedType, @NotNull DataFlowInfo dataFlowInfo, @NotNull BindingTrace trace) {
ExpressionTypingContext context = ExpressionTypingContext.newContext(
this, trace, scope, dataFlowInfo, expectedType, false
);
return expressionTypingFacade.getTypeInfo(expression, context).getType();
return expressionTypingFacade.getTypeInfo(expression, context);
}
@Nullable
public JetType getType(@NotNull final JetScope scope, @NotNull JetExpression expression, @NotNull JetType expectedType, @NotNull DataFlowInfo dataFlowInfo, @NotNull BindingTrace trace) {
return getTypeInfo(scope, expression, expectedType, dataFlowInfo, trace).getType();
}
public JetType getTypeWithNamespaces(@NotNull final JetScope scope, @NotNull JetExpression expression, @NotNull BindingTrace trace) {
@@ -69,8 +69,8 @@ public class ExpressionTypingVisitorDispatcher extends JetVisitor<JetTypeInfo, E
}
@Override
public JetType getSelectorReturnType(@NotNull ReceiverDescriptor receiver, @Nullable ASTNode callOperationNode, @NotNull JetExpression selectorExpression, @NotNull ExpressionTypingContext context) {
return basic.getSelectorReturnType(receiver, callOperationNode, selectorExpression, context);
public JetTypeInfo getSelectorReturnTypeInfo(@NotNull ReceiverDescriptor receiver, @Nullable ASTNode callOperationNode, @NotNull JetExpression selectorExpression, @NotNull ExpressionTypingContext context) {
return basic.getSelectorReturnTypeInfo(receiver, callOperationNode, selectorExpression, context);
}
@Override
@@ -115,8 +115,11 @@ public class ExpressionTypingVisitorDispatcher extends JetVisitor<JetTypeInfo, E
@NotNull
private JetTypeInfo getTypeInfo(@NotNull JetExpression expression, ExpressionTypingContext context, JetVisitor<JetTypeInfo, ExpressionTypingContext> visitor) {
if (context.trace.get(BindingContext.PROCESSED, expression)) {
return JetTypeInfo.create(context.trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, expression),
context.dataFlowInfo);
DataFlowInfo dataFlowInfo = context.trace.get(BindingContext.EXPRESSION_DATA_FLOW_INFO, expression);
if (dataFlowInfo == null) {
dataFlowInfo = context.dataFlowInfo;
}
return JetTypeInfo.create(context.trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, expression), dataFlowInfo);
}
JetTypeInfo result;
try {
@@ -128,7 +131,7 @@ public class ExpressionTypingVisitorDispatcher extends JetVisitor<JetTypeInfo, E
}
if (result.getType() instanceof DeferredType) {
result = JetTypeInfo.create(((DeferredType) result.getType()).getActualType(), context.dataFlowInfo);
result = JetTypeInfo.create(((DeferredType) result.getType()).getActualType(), result.getDataFlowInfo());
}
if (result.getType() != null) {
context.trace.record(BindingContext.EXPRESSION_TYPE, expression, result.getType());
@@ -144,7 +147,10 @@ public class ExpressionTypingVisitorDispatcher extends JetVisitor<JetTypeInfo, E
context.trace.record(BindingContext.RESOLUTION_SCOPE, expression, context.scope);
}
context.trace.record(BindingContext.PROCESSED, expression);
return result;
if (result.getDataFlowInfo() != context.dataFlowInfo) {
context.trace.record(BindingContext.EXPRESSION_DATA_FLOW_INFO, expression, result.getDataFlowInfo());
}
return result;
}
//////////////////////////////////////////////////////////////////////////////////////////////
@@ -239,7 +239,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
JetExpression decomposerExpression = pattern.getDecomposerExpression();
if (decomposerExpression != null) {
ReceiverDescriptor receiver = new TransientReceiver(subjectType);
JetType selectorReturnType = facade.getSelectorReturnType(receiver, null, decomposerExpression, context);
JetType selectorReturnType = facade.getSelectorReturnTypeInfo(receiver, null, decomposerExpression, context).getType();
if (pattern.getArgumentList() != null) {
result.set(checkPatternType(pattern.getArgumentList(), selectorReturnType == null
@@ -6,8 +6,8 @@ fun foo() {
bar(<!TYPE_MISMATCH!>x<!>)
if (x != null) bar(x<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>)
if (x == null) bar(x!!)
if (x != null) else bar(x!!)
if (x != null) else bar(x<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>)
if (x == null) else bar(x<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>)
if (x != null) bar(x<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>) else bar(x!!)
if (x == null) bar(x!!) else bar(x<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>)
if (x != null) bar(x<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>) else bar(x<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>)
if (x == null) bar(x<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>) else bar(x<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>)
}
@@ -2,11 +2,11 @@ fun main(args : Array<String>) {
val a : Int? = null
val b : Int? = null
a!! : Int
a!! + 2
a!!.plus(2)
a!!.plus(b!!)
2.plus(b!!)
2 + b!!
a<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!> + 2
a<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.plus(2)
a<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.plus(b!!)
2.plus(b<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>)
2 + b<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
val c = 1
c<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
@@ -30,6 +30,6 @@ fun main(args : Array<String>) {
}
}
val <!UNUSED_VARIABLE!>f<!> : String = <!TYPE_MISMATCH!>a!!<!>
<!TYPE_MISMATCH!>a!!<!> : String
val <!UNUSED_VARIABLE!>f<!> : String = <!TYPE_MISMATCH!>a<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!><!>
<!TYPE_MISMATCH!>a<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!><!> : String
}
@@ -0,0 +1,29 @@
class Foo {
fun foo(a: Foo): Foo = a
}
fun main(args : Array<String>) {
val x: Foo? = null
val y: Foo? = null
x<!UNSAFE_CALL!>.<!>foo(<!TYPE_MISMATCH!>y<!>)
x!!.foo(<!TYPE_MISMATCH!>y<!>)
x.foo(y!!)
x<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.foo(y<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>)
val a: Foo? = null
val b: Foo? = null
val c: Foo? = null
a<!UNSAFE_CALL!>.<!>foo(b<!UNSAFE_CALL!>.<!>foo(<!TYPE_MISMATCH!>c<!>))
a!!.foo(b<!UNSAFE_CALL!>.<!>foo(<!TYPE_MISMATCH!>c<!>))
a.foo(b!!.foo(<!TYPE_MISMATCH!>c<!>))
a<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.foo(b<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.foo(<!TYPE_MISMATCH!>c<!>))
a.foo(b.foo(c!!))
a<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.foo(b.foo(c<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>))
a.foo(b<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.foo(c<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>))
a<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.foo(b<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.foo(c<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>))
val z: Foo? = null
z!!.foo(z<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>)
}
@@ -0,0 +1,38 @@
//KT-2164 !! does not propagate nullability information
package kt2164
fun foo(x: Int): Int = x + 1
fun main(args : Array<String>) {
val x: Int? = null
foo(<!TYPE_MISMATCH!>x<!>)
if (x != null) {
foo(x)
foo(x<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>)
foo(x)
}
foo(<!TYPE_MISMATCH!>x<!>)
if (x != null) {
foo(x)
foo(x<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>)
foo(x)
} else {
foo(<!TYPE_MISMATCH!>x<!>)
foo(x!!)
foo(x)
}
foo(x)
foo(x<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>)
foo(x)
val y: Int? = null
y!!
y<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
foo(y)
foo(y<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>)
}
@@ -0,0 +1,20 @@
//KT-2216 Nullability of a value determined in function parameter computation doesn't pass to code following
package kt2216
fun bar(y: Int, z: Int) = y + z
fun baz(a: Int, b: Int, c: Int, d: Int) = a + b + c + d
fun foo() {
val x: Int? = 0
bar(if (x != null) x else return, x)
x + 2
bar(x, x<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>)
val y: Int? = 0
val z: Int? = 0
bar(if (y != null) y else <!TYPE_MISMATCH!>z<!>, <!TYPE_MISMATCH!>y<!>)
y <!UNSAFE_INFIX_CALL!>+<!> 2
baz(<!TYPE_MISMATCH!>y<!>, <!TYPE_MISMATCH!>y<!>, if (y == null) return else y, y)
baz(y, z!!, z, y)
}