[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
This commit is contained in:
Mikhail Zarechenskiy
2017-08-09 11:13:00 +03:00
parent f51f7a0fe4
commit 82d43c23b6
4 changed files with 27 additions and 12 deletions
@@ -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
}
@@ -102,7 +102,7 @@ class ResolvedAtomCompleter(
.replaceBindingTrace(trace)
val argumentExpression = resultValueArgument.valueArgument.getArgumentExpression() ?: continue
kotlinToResolvedCallTransformer.updateRecordedType(argumentExpression, newContext)
kotlinToResolvedCallTransformer.updateRecordedType(argumentExpression, newContext, true)
}
}
@@ -361,7 +361,8 @@ public class ControlStructureTypingUtils {
.replaceExpectedType(c.expectedType)
.replaceDataFlowInfo(typeInfo.getDataFlowInfo())
.replaceBindingTrace(c.trace),
hasError
hasError,
true
);
return hasError.get();
}
@@ -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<Boolean> hasError
@NotNull Ref<Boolean> 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<Boolean> hasError
@Nullable Ref<Boolean> 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);