From 82d43c23b67be7abed411dc990dd64aff57e687d Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Wed, 9 Aug 2017 11:13:00 +0300 Subject: [PATCH] [NI] Perform full type checking in NI if there is no contradiction In NI type checking actually performs in constraint system. To be conservative, now we still perform full type cheking but only if there is no contradiction in constraint system --- .../tower/KotlinToResolvedCallTransformer.kt | 7 ++--- .../calls/tower/ResolvedAtomCompleter.kt | 2 +- .../ControlStructureTypingUtils.java | 3 ++- .../types/expressions/DataFlowAnalyzer.java | 27 ++++++++++++++----- 4 files changed, 27 insertions(+), 12 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt index 2ce99e15d0c..bdef9894c2e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt @@ -199,14 +199,15 @@ class KotlinToResolvedCallTransformer( // todo external argument val argumentExpression = valueArgument.getArgumentExpression() ?: continue - updateRecordedType(argumentExpression, newContext) + updateRecordedType(argumentExpression, newContext, resolvedCall.isReallySuccess()) } } fun updateRecordedType( expression: KtExpression, - context: BasicCallResolutionContext + context: BasicCallResolutionContext, + reportErrorForTypeMismatch: Boolean ): KotlinType? { val deparenthesized = expression.let { KtPsiUtil.getLastElementDeparenthesized(it, context.statementFilter) @@ -225,7 +226,7 @@ class KotlinToResolvedCallTransformer( updatedType = updateRecordedTypeForArgument(updatedType, recordedType, expression, context) - dataFlowAnalyzer.checkType(updatedType, deparenthesized, context) + dataFlowAnalyzer.checkType(updatedType, deparenthesized, context, reportErrorForTypeMismatch) return updatedType } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt index 03f01ce589d..ca9214f81f5 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt @@ -102,7 +102,7 @@ class ResolvedAtomCompleter( .replaceBindingTrace(trace) val argumentExpression = resultValueArgument.valueArgument.getArgumentExpression() ?: continue - kotlinToResolvedCallTransformer.updateRecordedType(argumentExpression, newContext) + kotlinToResolvedCallTransformer.updateRecordedType(argumentExpression, newContext, true) } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingUtils.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingUtils.java index 16bd1e72e60..6789495140a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingUtils.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingUtils.java @@ -361,7 +361,8 @@ public class ControlStructureTypingUtils { .replaceExpectedType(c.expectedType) .replaceDataFlowInfo(typeInfo.getDataFlowInfo()) .replaceBindingTrace(c.trace), - hasError + hasError, + true ); return hasError.get(); } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DataFlowAnalyzer.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DataFlowAnalyzer.java index 0beb1962d63..c4f8947f841 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DataFlowAnalyzer.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DataFlowAnalyzer.java @@ -24,9 +24,9 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.config.LanguageFeature; import org.jetbrains.kotlin.config.LanguageVersionSettings; +import org.jetbrains.kotlin.contracts.EffectSystem; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.diagnostics.DiagnosticUtilsKt; -import org.jetbrains.kotlin.contracts.EffectSystem; import org.jetbrains.kotlin.incremental.KotlinLookupLocation; import org.jetbrains.kotlin.lexer.KtTokens; import org.jetbrains.kotlin.psi.*; @@ -252,7 +252,17 @@ public class DataFlowAnalyzer { @Nullable public KotlinType checkType(@Nullable KotlinType expressionType, @NotNull KtExpression expression, @NotNull ResolutionContext context) { - return checkType(expressionType, expression, context, null); + return checkType(expressionType, expression, context, null, true); + } + + @Nullable + public KotlinType checkType( + @Nullable KotlinType expressionType, + @NotNull KtExpression expression, + @NotNull ResolutionContext context, + boolean reportErrorForTypeMismatch + ) { + return checkType(expressionType, expression, context, null, reportErrorForTypeMismatch); } @NotNull @@ -265,14 +275,15 @@ public class DataFlowAnalyzer { @NotNull KotlinType expressionType, @NotNull KtExpression expression, @NotNull ResolutionContext c, - @NotNull Ref hasError + @NotNull Ref hasError, + boolean reportErrorForTypeMismatch ) { if (noExpectedType(c.expectedType) || !c.expectedType.getConstructor().isDenotable() || KotlinTypeChecker.DEFAULT.isSubtypeOf(expressionType, c.expectedType)) { return expressionType; } - if (expression instanceof KtConstantExpression) { + if (expression instanceof KtConstantExpression && reportErrorForTypeMismatch) { ConstantValue constantValue = constantExpressionEvaluator.evaluateToConstantValue(expression, c.trace, c.expectedType); boolean error = new CompileTimeConstantChecker(c, builtIns, true) .checkConstantExpressionType(constantValue, (KtConstantExpression) expression, c.expectedType); @@ -288,7 +299,8 @@ public class DataFlowAnalyzer { SmartCastResult castResult = checkPossibleCast(expressionType, expression, c); if (castResult != null) return castResult.getResultType(); - if (!DiagnosticUtilsKt.reportTypeMismatchDueToTypeProjection(c, expression, c.expectedType, expressionType) && + if (reportErrorForTypeMismatch && + !DiagnosticUtilsKt.reportTypeMismatchDueToTypeProjection(c, expression, c.expectedType, expressionType) && !DiagnosticUtilsKt.reportTypeMismatchDueToScalaLikeNamedFunctionSyntax(c, expression, c.expectedType, expressionType)) { c.trace.report(TYPE_MISMATCH.on(expression, c.expectedType, expressionType)); } @@ -301,7 +313,8 @@ public class DataFlowAnalyzer { @Nullable KotlinType expressionType, @NotNull KtExpression expressionToCheck, @NotNull ResolutionContext c, - @Nullable Ref hasError + @Nullable Ref hasError, + boolean reportErrorForTypeMismatch ) { if (hasError == null) { hasError = Ref.create(false); @@ -315,7 +328,7 @@ public class DataFlowAnalyzer { if (expressionType == null) return null; - KotlinType result = checkTypeInternal(expressionType, expression, c, hasError); + KotlinType result = checkTypeInternal(expressionType, expression, c, hasError, reportErrorForTypeMismatch); if (Boolean.FALSE.equals(hasError.get())) { for (AdditionalTypeChecker checker : additionalTypeCheckers) { checker.checkType(expression, expressionType, result, c);