From d7773131321ed92ad491e3e7a9b3044263d246c8 Mon Sep 17 00:00:00 2001 From: Sergey Lukjanov Date: Mon, 18 Jun 2012 15:25:06 +0400 Subject: [PATCH 01/15] Replace deprected 'rename' task with 'move' task --- update_dependencies.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/update_dependencies.xml b/update_dependencies.xml index ab180f44d8a..2ba2a3eeeba 100644 --- a/update_dependencies.xml +++ b/update_dependencies.xml @@ -58,7 +58,7 @@ - + From 845c3198bdebeb4f551c4342d4a852a67ca4d8b0 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Fri, 15 Jun 2012 22:03:00 +0400 Subject: [PATCH 02/15] KT-2164 !! does not propagate nullability information --- .../BasicExpressionTypingVisitor.java | 5 +++ .../tests/nullabilityAndAutoCasts/kt2164.jet | 38 +++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 compiler/testData/diagnostics/tests/nullabilityAndAutoCasts/kt2164.jet 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..93fbf8f10a3 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; @@ -784,6 +785,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/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!!) +} From ec7efdfee29fe63d43c570f7ff79459ab65f231c Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Mon, 18 Jun 2012 19:43:52 +0400 Subject: [PATCH 03/15] ExpressionTypingServices.getTypeInfo() --- .../types/expressions/ExpressionTypingServices.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) 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) { From 33f0ff3eebfb5fc0e046b6c30e66aaa2423adffc Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Mon, 18 Jun 2012 20:32:18 +0400 Subject: [PATCH 04/15] BindingContext.EXPRESSION_DATA_FLOW_INFO --- .../jetbrains/jet/lang/resolve/BindingContext.java | 1 + .../ExpressionTypingVisitorDispatcher.java | 12 +++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) 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/types/expressions/ExpressionTypingVisitorDispatcher.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorDispatcher.java index b101f9ccc02..92819b33366 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 @@ -115,8 +115,11 @@ 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 { @@ -144,7 +147,10 @@ public class ExpressionTypingVisitorDispatcher extends JetVisitor Date: Mon, 18 Jun 2012 20:39:33 +0400 Subject: [PATCH 05/15] getCallExpressionTypeInfo calculates common DataFlowInfo of all arguments in call expression --- .../BasicExpressionTypingVisitor.java | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) 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 93fbf8f10a3..935591a85a5 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 @@ -644,7 +644,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { public JetType getSelectorReturnType(@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).getType(); } else if (selectorExpression instanceof JetSimpleNameExpression) { @@ -693,8 +693,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { return null; } - @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]; @@ -710,7 +710,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(); @@ -722,11 +737,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, @@ -744,8 +759,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 From be65a9404a8c4d89c83a7cb3bf880d2af6fe4abc Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Mon, 18 Jun 2012 21:14:11 +0400 Subject: [PATCH 06/15] checkValueArgumentTypes processes arguments in the right order --- .../org/jetbrains/jet/lang/resolve/calls/ResolvedCallImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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; From 9db65d21b6a975e40816c6d5cb9ba7eb10418ca0 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Mon, 18 Jun 2012 21:27:47 +0400 Subject: [PATCH 07/15] checkValueArgumentTypes calculates DataFlowInfo during type checking --- .../org/jetbrains/jet/lang/resolve/calls/CallResolver.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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(); } From 85760405dc05ad9bd3f6aae9ccb0baa2a25fb60c Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Mon, 18 Jun 2012 21:43:25 +0400 Subject: [PATCH 08/15] fix tests --- .../tests/dataFlowInfoTraversal/ExclExcl.jet | 6 +++--- .../nullabilityAndAutoCasts/AssertNotNull.jet | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/ExclExcl.jet b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/ExclExcl.jet index 94d44069aec..9464d13025c 100644 --- a/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/ExclExcl.jet +++ b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/ExclExcl.jet @@ -6,8 +6,8 @@ fun foo() { bar(x) 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 From b43e17a7b0c0575c8a22e4b6d787c76f892a279f Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Mon, 18 Jun 2012 21:45:44 +0400 Subject: [PATCH 09/15] keep DataFlowInfo if resulting type of an expression is DeferredType --- .../types/expressions/ExpressionTypingVisitorDispatcher.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 92819b33366..cfbdb4d0042 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 @@ -131,7 +131,7 @@ public class ExpressionTypingVisitorDispatcher extends JetVisitor Date: Mon, 18 Jun 2012 21:49:44 +0400 Subject: [PATCH 10/15] test for KT-2216 --- .../tests/nullabilityAndAutoCasts/kt2216.jet | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 compiler/testData/diagnostics/tests/nullabilityAndAutoCasts/kt2216.jet 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) +} From 2b6927ad3bb1562fafb43f9c7567c0eb5051139f Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Mon, 18 Jun 2012 22:20:27 +0400 Subject: [PATCH 11/15] reorder logic in checkBinaryWithTypeRHS --- .../BasicExpressionTypingVisitor.java | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) 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 935591a85a5..8609e3c5047 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 @@ -196,18 +196,23 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { 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); + 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()); + } } IElementType operationType = expression.getOperationSign().getReferencedNameElementType(); @@ -219,11 +224,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { return DataFlowUtils.checkType(result, expression, context, 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) { From baf3ab2aa530f9dfe7958b6165924c84b0479c71 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Mon, 18 Jun 2012 22:23:35 +0400 Subject: [PATCH 12/15] pass DataFlowInfo in checkBinaryWithTypeRHSExpression --- .../types/expressions/BasicExpressionTypingVisitor.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) 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 8609e3c5047..4eea9a8c2c5 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 @@ -193,6 +193,7 @@ 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); @@ -203,6 +204,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { JetTypeInfo typeInfo = facade.getTypeInfo(expression.getLeft(), contextWithTemporaryTrace); if (typeInfo.getType() != null && checkBinaryWithTypeRHS(expression, contextWithTemporaryTrace, targetType, typeInfo.getType())) { temporaryTraceWithExpectedType.commit(); + dataFlowInfo = typeInfo.getDataFlowInfo(); tryWithNoExpectedType = false; } } @@ -212,6 +214,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { JetTypeInfo typeInfo = facade.getTypeInfo(expression.getLeft(), contextWithNoExpectedType); if (typeInfo.getType() != null) { checkBinaryWithTypeRHS(expression, contextWithNoExpectedType, targetType, typeInfo.getType()); + dataFlowInfo = typeInfo.getDataFlowInfo(); } } @@ -219,9 +222,9 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { 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) { From 651709bcc9243802e5d3d160d079ffe3d6a8a89e Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Tue, 19 Jun 2012 14:18:54 +0400 Subject: [PATCH 13/15] more methods return JetTypeInfo instead of JetType --- .../BasicExpressionTypingVisitor.java | 44 +++++++++---------- .../ExpressionTypingInternals.java | 7 ++- .../ExpressionTypingVisitorDispatcher.java | 4 +- .../PatternMatchingTypingVisitor.java | 2 +- 4 files changed, 28 insertions(+), 29 deletions(-) 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 4eea9a8c2c5..00dbe4ae03b 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 @@ -73,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 @@ -546,7 +547,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { 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) { @@ -557,12 +559,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, receiverTypeInfo.getDataFlowInfo()); } private void propagateConstantValues(JetQualifiedExpression expression, ExpressionTypingContext context, JetSimpleNameExpression selectorExpression) { @@ -644,34 +645,32 @@ 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 getCallExpressionTypeInfo((JetCallExpression) selectorExpression, receiver, callOperationNode, context).getType(); + 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(); 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); } } 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]; @@ -680,7 +679,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()); @@ -690,11 +689,12 @@ 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); } @NotNull 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/ExpressionTypingVisitorDispatcher.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorDispatcher.java index cfbdb4d0042..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 Date: Tue, 19 Jun 2012 14:33:04 +0400 Subject: [PATCH 14/15] test for qualified expression nullability --- .../QualifiedExpressionNullability.jet | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 compiler/testData/diagnostics/tests/nullabilityAndAutoCasts/QualifiedExpressionNullability.jet 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!!) +} From 1c599efbcd6c9a26f297b5a612dc880da0500100 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Tue, 19 Jun 2012 14:39:14 +0400 Subject: [PATCH 15/15] pass correct DataFlowInfo through qualified expressions #KT-2216 Fixed #KT-2164 Fixed --- .../types/expressions/BasicExpressionTypingVisitor.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) 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 00dbe4ae03b..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 @@ -543,6 +543,8 @@ 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); } @@ -563,7 +565,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { if (selectorReturnType != null) { context.trace.record(BindingContext.EXPRESSION_TYPE, selectorExpression, selectorReturnType); } - return DataFlowUtils.checkType(selectorReturnType, expression, context, receiverTypeInfo.getDataFlowInfo()); + return DataFlowUtils.checkType(selectorReturnType, expression, context, selectorReturnTypeInfo.getDataFlowInfo()); } private void propagateConstantValues(JetQualifiedExpression expression, ExpressionTypingContext context, JetSimpleNameExpression selectorExpression) { @@ -658,9 +660,10 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { JetExpression newReceiverExpression = qualifiedExpression.getReceiverExpression(); 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 getSelectorReturnTypeInfo(new ExpressionReceiver(newReceiverExpression, newReceiverType), qualifiedExpression.getOperationTokenNode(), newSelectorExpression, context); + return getSelectorReturnTypeInfo(new ExpressionReceiver(newReceiverExpression, newReceiverType), qualifiedExpression.getOperationTokenNode(), newSelectorExpression, context.replaceDataFlowInfo(newReceiverDataFlowInfo)); } } else {