diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java index efe4ab7e9b0..7662f478552 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java @@ -68,6 +68,7 @@ public interface BindingContext { WritableSlice> COMPILE_TIME_VALUE = Slices.createSimpleSlice(); WritableSlice TYPE = Slices.createSimpleSlice(); WritableSlice EXPRESSION_TYPE = new BasicWritableSlice(DO_NOTHING); + WritableSlice EXPRESSION_DATA_FLOW_INFO = new BasicWritableSlice(DO_NOTHING); WritableSlice REFERENCE_TARGET = new BasicWritableSlice(DO_NOTHING); WritableSlice> RESOLVED_CALL = new BasicWritableSlice>(DO_NOTHING); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java index 5df72656388..84bfdafac4e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java @@ -767,6 +767,7 @@ public class CallResolver { private ResolutionStatus checkValueArgumentTypes(CallResolutionContext context) { ResolutionStatus result = SUCCESS; + DataFlowInfo dataFlowInfo = context.dataFlowInfo; for (Map.Entry 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(); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolvedCallImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolvedCallImpl.java index 23c387d8ac7..f4eb4b6291c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolvedCallImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolvedCallImpl.java @@ -65,7 +65,7 @@ public class ResolvedCallImpl implements ResolvedC private final Map typeArguments = Maps.newLinkedHashMap(); private final Map autoCasts = Maps.newHashMap(); - private final Map valueArguments = Maps.newHashMap(); + private final Map valueArguments = Maps.newLinkedHashMap(); private boolean someArgumentHasNoType = false; private TemporaryBindingTrace trace; private ResolutionStatus status = UNKNOWN_STATUS; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java index 32f3698bc8a..b36d7ee6a10 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java @@ -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.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 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); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingInternals.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingInternals.java index 9348effa09c..dd2618b181a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingInternals.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingInternals.java @@ -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); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java index dc68014f924..84c0717f6c1 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java @@ -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) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorDispatcher.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorDispatcher.java index b101f9ccc02..b8a8e2370e4 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorDispatcher.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorDispatcher.java @@ -69,8 +69,8 @@ public class ExpressionTypingVisitorDispatcher extends JetVisitor 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 JetVisitorx) if (x != null) bar(x!!) if (x == null) bar(x!!) - if (x != null) else bar(x!!) + if (x != null) else bar(x!!) if (x == null) else bar(x!!) - if (x != null) bar(x!!) else bar(x!!) - if (x == null) bar(x!!) else bar(x!!) + if (x != null) bar(x!!) else bar(x!!) + if (x == null) bar(x!!) else bar(x!!) } diff --git a/compiler/testData/diagnostics/tests/nullabilityAndAutoCasts/AssertNotNull.jet b/compiler/testData/diagnostics/tests/nullabilityAndAutoCasts/AssertNotNull.jet index bf91b286d2b..6da7a053503 100644 --- a/compiler/testData/diagnostics/tests/nullabilityAndAutoCasts/AssertNotNull.jet +++ b/compiler/testData/diagnostics/tests/nullabilityAndAutoCasts/AssertNotNull.jet @@ -2,11 +2,11 @@ fun main(args : Array) { val a : Int? = null val b : Int? = null a!! : Int - a!! + 2 - a!!.plus(2) - a!!.plus(b!!) - 2.plus(b!!) - 2 + b!! + a!! + 2 + a!!.plus(2) + a!!.plus(b!!) + 2.plus(b!!) + 2 + b!! val c = 1 c!! @@ -30,6 +30,6 @@ fun main(args : Array) { } } - val f : String = a!! - a!! : String + val f : String = a!! + a!! : String } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/nullabilityAndAutoCasts/QualifiedExpressionNullability.jet b/compiler/testData/diagnostics/tests/nullabilityAndAutoCasts/QualifiedExpressionNullability.jet new file mode 100644 index 00000000000..a8d14c07da6 --- /dev/null +++ b/compiler/testData/diagnostics/tests/nullabilityAndAutoCasts/QualifiedExpressionNullability.jet @@ -0,0 +1,29 @@ +class Foo { + fun foo(a: Foo): Foo = a +} + +fun main(args : Array) { + val x: Foo? = null + val y: Foo? = null + + x.foo(y) + x!!.foo(y) + x.foo(y!!) + x!!.foo(y!!) + + val a: Foo? = null + val b: Foo? = null + val c: Foo? = null + + a.foo(b.foo(c)) + a!!.foo(b.foo(c)) + a.foo(b!!.foo(c)) + a!!.foo(b!!.foo(c)) + a.foo(b.foo(c!!)) + a!!.foo(b.foo(c!!)) + a.foo(b!!.foo(c!!)) + a!!.foo(b!!.foo(c!!)) + + val z: Foo? = null + z!!.foo(z!!) +} diff --git a/compiler/testData/diagnostics/tests/nullabilityAndAutoCasts/kt2164.jet b/compiler/testData/diagnostics/tests/nullabilityAndAutoCasts/kt2164.jet new file mode 100644 index 00000000000..79029f1165a --- /dev/null +++ b/compiler/testData/diagnostics/tests/nullabilityAndAutoCasts/kt2164.jet @@ -0,0 +1,38 @@ +//KT-2164 !! does not propagate nullability information +package kt2164 + +fun foo(x: Int): Int = x + 1 + +fun main(args : Array) { + val x: Int? = null + + foo(x) + + if (x != null) { + foo(x) + foo(x!!) + foo(x) + } + + foo(x) + + if (x != null) { + foo(x) + foo(x!!) + foo(x) + } else { + foo(x) + foo(x!!) + foo(x) + } + + foo(x) + foo(x!!) + foo(x) + + val y: Int? = null + y!! + y!! + foo(y) + foo(y!!) +} diff --git a/compiler/testData/diagnostics/tests/nullabilityAndAutoCasts/kt2216.jet b/compiler/testData/diagnostics/tests/nullabilityAndAutoCasts/kt2216.jet new file mode 100644 index 00000000000..4fccab1539d --- /dev/null +++ b/compiler/testData/diagnostics/tests/nullabilityAndAutoCasts/kt2216.jet @@ -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!!) + + val y: Int? = 0 + val z: Int? = 0 + bar(if (y != null) y else z, y) + y + 2 + baz(y, y, if (y == null) return else y, y) + baz(y, z!!, z, y) +}