Avoid resolving array-set method several times
While origin problem was in NI, it's also nice to have this change in OI in order to slightly improve performance #KT-33125 Fixed
This commit is contained in:
+18
-7
@@ -797,7 +797,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
context.trace.record(BindingContext.VARIABLE_REASSIGNMENT, expression);
|
context.trace.record(BindingContext.VARIABLE_REASSIGNMENT, expression);
|
||||||
KtExpression stubExpression = ExpressionTypingUtils.createFakeExpressionOfType(
|
KtExpression stubExpression = ExpressionTypingUtils.createFakeExpressionOfType(
|
||||||
baseExpression.getProject(), context.trace, "e", type);
|
baseExpression.getProject(), context.trace, "e", type);
|
||||||
checkLValue(context.trace, context, baseExpression, stubExpression, expression);
|
checkLValue(context.trace, context, baseExpression, stubExpression, expression, false);
|
||||||
}
|
}
|
||||||
// x++ type is x type, but ++x type is x.inc() type
|
// x++ type is x type, but ++x type is x.inc() type
|
||||||
DataFlowValue receiverValue = components.dataFlowValueFactory.createDataFlowValue(
|
DataFlowValue receiverValue = components.dataFlowValueFactory.createDataFlowValue(
|
||||||
@@ -930,7 +930,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
@NotNull ExpressionTypingContext context,
|
@NotNull ExpressionTypingContext context,
|
||||||
@NotNull KtExpression expressionWithParenthesis,
|
@NotNull KtExpression expressionWithParenthesis,
|
||||||
@Nullable KtExpression rightHandSide,
|
@Nullable KtExpression rightHandSide,
|
||||||
@NotNull KtOperationExpression operationExpression
|
@NotNull KtOperationExpression operationExpression,
|
||||||
|
boolean arraySetMethodAlreadyResolved
|
||||||
) {
|
) {
|
||||||
KtExpression expression = KtPsiUtil.deparenthesize(expressionWithParenthesis);
|
KtExpression expression = KtPsiUtil.deparenthesize(expressionWithParenthesis);
|
||||||
if (expression instanceof KtArrayAccessExpression) {
|
if (expression instanceof KtArrayAccessExpression) {
|
||||||
@@ -938,14 +939,24 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
KtExpression arrayExpression = arrayAccessExpression.getArrayExpression();
|
KtExpression arrayExpression = arrayAccessExpression.getArrayExpression();
|
||||||
if (arrayExpression == null || rightHandSide == null) return false;
|
if (arrayExpression == null || rightHandSide == null) return false;
|
||||||
|
|
||||||
TemporaryBindingTrace ignoreReportsTrace = TemporaryBindingTrace.create(trace, "Trace for checking set function");
|
BindingTrace traceWithIndexedLValue;
|
||||||
ExpressionTypingContext findSetterContext = context.replaceBindingTrace(ignoreReportsTrace);
|
boolean methodSetIsResolved;
|
||||||
KotlinTypeInfo info = resolveArrayAccessSetMethod(arrayAccessExpression, rightHandSide, findSetterContext, ignoreReportsTrace);
|
if (!arraySetMethodAlreadyResolved) {
|
||||||
|
TemporaryBindingTrace ignoreReportsTrace = TemporaryBindingTrace.create(trace, "Trace for checking set function");
|
||||||
|
ExpressionTypingContext findSetterContext = context.replaceBindingTrace(ignoreReportsTrace);
|
||||||
|
KotlinTypeInfo info = resolveArrayAccessSetMethod(arrayAccessExpression, rightHandSide, findSetterContext, ignoreReportsTrace);
|
||||||
|
|
||||||
|
traceWithIndexedLValue = ignoreReportsTrace;
|
||||||
|
methodSetIsResolved = info.getType() != null;
|
||||||
|
} else {
|
||||||
|
traceWithIndexedLValue = trace;
|
||||||
|
methodSetIsResolved = true;
|
||||||
|
}
|
||||||
|
|
||||||
IElementType operationType = operationExpression.getOperationReference().getReferencedNameElementType();
|
IElementType operationType = operationExpression.getOperationReference().getReferencedNameElementType();
|
||||||
if (KtTokens.AUGMENTED_ASSIGNMENTS.contains(operationType)
|
if (KtTokens.AUGMENTED_ASSIGNMENTS.contains(operationType)
|
||||||
|| operationType == KtTokens.PLUSPLUS || operationType == KtTokens.MINUSMINUS) {
|
|| operationType == KtTokens.PLUSPLUS || operationType == KtTokens.MINUSMINUS) {
|
||||||
ResolvedCall<?> resolvedCall = ignoreReportsTrace.get(INDEXED_LVALUE_SET, expression);
|
ResolvedCall<?> resolvedCall = traceWithIndexedLValue.get(INDEXED_LVALUE_SET, expression);
|
||||||
if (resolvedCall != null && trace.wantsDiagnostics()) {
|
if (resolvedCall != null && trace.wantsDiagnostics()) {
|
||||||
// Call must be validated with the actual, not temporary trace in order to report operator diagnostic
|
// Call must be validated with the actual, not temporary trace in order to report operator diagnostic
|
||||||
// Only unary assignment expressions (++, --) and +=/... must be checked, normal assignments have the proper trace
|
// Only unary assignment expressions (++, --) and +=/... must be checked, normal assignments have the proper trace
|
||||||
@@ -957,7 +968,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return info.getType() != null;
|
return methodSetIsResolved;
|
||||||
}
|
}
|
||||||
|
|
||||||
VariableDescriptor variable = BindingContextUtils.extractVariableDescriptorFromReference(trace.getBindingContext(), expression);
|
VariableDescriptor variable = BindingContextUtils.extractVariableDescriptorFromReference(trace.getBindingContext(), expression);
|
||||||
|
|||||||
+4
-4
@@ -233,7 +233,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
TemporaryTraceAndCache temporaryForBinaryOperation = TemporaryTraceAndCache.create(
|
TemporaryTraceAndCache temporaryForBinaryOperation = TemporaryTraceAndCache.create(
|
||||||
context, "trace to check binary operation like '+' for", expression);
|
context, "trace to check binary operation like '+' for", expression);
|
||||||
TemporaryBindingTrace ignoreReportsTrace = TemporaryBindingTrace.create(context.trace, "Trace for checking assignability");
|
TemporaryBindingTrace ignoreReportsTrace = TemporaryBindingTrace.create(context.trace, "Trace for checking assignability");
|
||||||
boolean lhsAssignable = basic.checkLValue(ignoreReportsTrace, context, left, right, expression);
|
boolean lhsAssignable = basic.checkLValue(ignoreReportsTrace, context, left, right, expression, false);
|
||||||
if (assignmentOperationType == null || lhsAssignable) {
|
if (assignmentOperationType == null || lhsAssignable) {
|
||||||
// Check for '+'
|
// Check for '+'
|
||||||
Name counterpartName = OperatorConventions.BINARY_OPERATION_NAMES.get(OperatorConventions.ASSIGNMENT_OPERATION_COUNTERPARTS.get(operationType));
|
Name counterpartName = OperatorConventions.BINARY_OPERATION_NAMES.get(OperatorConventions.ASSIGNMENT_OPERATION_COUNTERPARTS.get(operationType));
|
||||||
@@ -291,7 +291,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
|
|
||||||
components.dataFlowAnalyzer.checkType(binaryOperationType, expression, context.replaceExpectedType(expectedType)
|
components.dataFlowAnalyzer.checkType(binaryOperationType, expression, context.replaceExpectedType(expectedType)
|
||||||
.replaceDataFlowInfo(rightInfo.getDataFlowInfo()).replaceCallPosition(new CallPosition.PropertyAssignment(left)));
|
.replaceDataFlowInfo(rightInfo.getDataFlowInfo()).replaceCallPosition(new CallPosition.PropertyAssignment(left)));
|
||||||
basic.checkLValue(context.trace, context, leftOperand, right, expression);
|
basic.checkLValue(context.trace, context, leftOperand, right, expression, false);
|
||||||
}
|
}
|
||||||
temporary.commit();
|
temporary.commit();
|
||||||
return rightInfo.replaceType(checkAssignmentType(type, expression, contextWithExpectedType));
|
return rightInfo.replaceType(checkAssignmentType(type, expression, contextWithExpectedType));
|
||||||
@@ -337,7 +337,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
KtArrayAccessExpression arrayAccessExpression = (KtArrayAccessExpression) left;
|
KtArrayAccessExpression arrayAccessExpression = (KtArrayAccessExpression) left;
|
||||||
if (right == null) return TypeInfoFactoryKt.noTypeInfo(context);
|
if (right == null) return TypeInfoFactoryKt.noTypeInfo(context);
|
||||||
KotlinTypeInfo typeInfo = basic.resolveArrayAccessSetMethod(arrayAccessExpression, right, context, context.trace);
|
KotlinTypeInfo typeInfo = basic.resolveArrayAccessSetMethod(arrayAccessExpression, right, context, context.trace);
|
||||||
basic.checkLValue(context.trace, context, arrayAccessExpression, right, expression);
|
basic.checkLValue(context.trace, context, arrayAccessExpression, right, expression, true);
|
||||||
return typeInfo.replaceType(checkAssignmentType(typeInfo.getType(), expression, contextWithExpectedType));
|
return typeInfo.replaceType(checkAssignmentType(typeInfo.getType(), expression, contextWithExpectedType));
|
||||||
}
|
}
|
||||||
KotlinTypeInfo leftInfo = ExpressionTypingUtils.getTypeInfoOrNullType(left, context, facade);
|
KotlinTypeInfo leftInfo = ExpressionTypingUtils.getTypeInfoOrNullType(left, context, facade);
|
||||||
@@ -362,7 +362,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
resultInfo = leftInfo;
|
resultInfo = leftInfo;
|
||||||
}
|
}
|
||||||
if (expectedType != null && leftOperand != null) { //if expectedType == null, some other error has been generated
|
if (expectedType != null && leftOperand != null) { //if expectedType == null, some other error has been generated
|
||||||
basic.checkLValue(context.trace, context, leftOperand, right, expression);
|
basic.checkLValue(context.trace, context, leftOperand, right, expression, false);
|
||||||
}
|
}
|
||||||
return resultInfo.replaceType(components.dataFlowAnalyzer.checkStatementType(expression, contextWithExpectedType));
|
return resultInfo.replaceType(components.dataFlowAnalyzer.checkStatementType(expression, contextWithExpectedType));
|
||||||
}
|
}
|
||||||
|
|||||||
+40
@@ -0,0 +1,40 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// IGNORE_BACKEND: JS_IR
|
||||||
|
|
||||||
|
import kotlin.experimental.ExperimentalTypeInference
|
||||||
|
|
||||||
|
interface Foo<T>
|
||||||
|
|
||||||
|
class FooImpl<T> : Foo<T>
|
||||||
|
|
||||||
|
@UseExperimental(ExperimentalTypeInference::class)
|
||||||
|
fun <T> myflow(@BuilderInference block: Foo<T>.() -> Unit): Foo<T> {
|
||||||
|
val impl = FooImpl<T>()
|
||||||
|
impl.block()
|
||||||
|
return impl
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class MapWithPlusOperator<K, V>(val m: MutableMap<K, V>)
|
||||||
|
|
||||||
|
operator fun <K, V> MapWithPlusOperator<in K, in V>.plus(pair: Pair<K, V>): MapWithPlusOperator<K, V> {
|
||||||
|
m[pair.first] = pair.second
|
||||||
|
return this as MapWithPlusOperator<K, V>
|
||||||
|
}
|
||||||
|
|
||||||
|
var publicOk = "noOk"
|
||||||
|
|
||||||
|
fun test(map: MutableMap<Int, Any>): Foo<Any> {
|
||||||
|
var other: MapWithPlusOperator<Int, Any> = MapWithPlusOperator(mutableMapOf())
|
||||||
|
return myflow {
|
||||||
|
publicOk = "OK"
|
||||||
|
map += 1 to "s"
|
||||||
|
other += 1 to ("s" as Any)
|
||||||
|
map[0] = Any()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
test(mutableMapOf(1 to ""))
|
||||||
|
return publicOk
|
||||||
|
}
|
||||||
+5
@@ -5759,6 +5759,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/beginWithException.kt", "kotlin.coroutines");
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/beginWithException.kt", "kotlin.coroutines");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("builderInferenceAndGenericArrayAcessCall.kt")
|
||||||
|
public void testBuilderInferenceAndGenericArrayAcessCall() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/coroutines/builderInferenceAndGenericArrayAcessCall.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("capturedVarInSuspendLambda.kt")
|
@TestMetadata("capturedVarInSuspendLambda.kt")
|
||||||
public void testCapturedVarInSuspendLambda_1_2() throws Exception {
|
public void testCapturedVarInSuspendLambda_1_2() throws Exception {
|
||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/capturedVarInSuspendLambda.kt", "kotlin.coroutines.experimental");
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/capturedVarInSuspendLambda.kt", "kotlin.coroutines.experimental");
|
||||||
|
|||||||
+5
@@ -5759,6 +5759,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/beginWithException.kt", "kotlin.coroutines");
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/beginWithException.kt", "kotlin.coroutines");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("builderInferenceAndGenericArrayAcessCall.kt")
|
||||||
|
public void testBuilderInferenceAndGenericArrayAcessCall() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/coroutines/builderInferenceAndGenericArrayAcessCall.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("capturedVarInSuspendLambda.kt")
|
@TestMetadata("capturedVarInSuspendLambda.kt")
|
||||||
public void testCapturedVarInSuspendLambda_1_2() throws Exception {
|
public void testCapturedVarInSuspendLambda_1_2() throws Exception {
|
||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/capturedVarInSuspendLambda.kt", "kotlin.coroutines.experimental");
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/capturedVarInSuspendLambda.kt", "kotlin.coroutines.experimental");
|
||||||
|
|||||||
+5
@@ -5694,6 +5694,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/beginWithException.kt", "kotlin.coroutines");
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/beginWithException.kt", "kotlin.coroutines");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("builderInferenceAndGenericArrayAcessCall.kt")
|
||||||
|
public void testBuilderInferenceAndGenericArrayAcessCall() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/coroutines/builderInferenceAndGenericArrayAcessCall.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("capturedVarInSuspendLambda.kt")
|
@TestMetadata("capturedVarInSuspendLambda.kt")
|
||||||
public void testCapturedVarInSuspendLambda_1_3() throws Exception {
|
public void testCapturedVarInSuspendLambda_1_3() throws Exception {
|
||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/capturedVarInSuspendLambda.kt", "kotlin.coroutines");
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/capturedVarInSuspendLambda.kt", "kotlin.coroutines");
|
||||||
|
|||||||
Generated
+5
@@ -4799,6 +4799,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
|||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/beginWithException.kt", "kotlin.coroutines");
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/beginWithException.kt", "kotlin.coroutines");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("builderInferenceAndGenericArrayAcessCall.kt")
|
||||||
|
public void testBuilderInferenceAndGenericArrayAcessCall() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/coroutines/builderInferenceAndGenericArrayAcessCall.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("capturedVarInSuspendLambda.kt")
|
@TestMetadata("capturedVarInSuspendLambda.kt")
|
||||||
public void testCapturedVarInSuspendLambda_1_3() throws Exception {
|
public void testCapturedVarInSuspendLambda_1_3() throws Exception {
|
||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/capturedVarInSuspendLambda.kt", "kotlin.coroutines");
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/capturedVarInSuspendLambda.kt", "kotlin.coroutines");
|
||||||
|
|||||||
+5
@@ -4849,6 +4849,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/beginWithException.kt", "kotlin.coroutines");
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/beginWithException.kt", "kotlin.coroutines");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("builderInferenceAndGenericArrayAcessCall.kt")
|
||||||
|
public void testBuilderInferenceAndGenericArrayAcessCall() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/coroutines/builderInferenceAndGenericArrayAcessCall.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("capturedVarInSuspendLambda.kt")
|
@TestMetadata("capturedVarInSuspendLambda.kt")
|
||||||
public void testCapturedVarInSuspendLambda_1_2() throws Exception {
|
public void testCapturedVarInSuspendLambda_1_2() throws Exception {
|
||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/capturedVarInSuspendLambda.kt", "kotlin.coroutines.experimental");
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/capturedVarInSuspendLambda.kt", "kotlin.coroutines.experimental");
|
||||||
|
|||||||
Reference in New Issue
Block a user