From 2a93dea0c4e8a0045c2d0e7c246c543f48ec37c7 Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Wed, 22 Mar 2017 17:52:51 +0300 Subject: [PATCH] Use concrete candidate to resolve collection literal This helps to avoid resolution errors when there is local array-like function with the same signature as in built-ins --- .../resolve/CollectionLiteralResolver.kt | 32 +++++++++++++------ .../kotlin/resolve/calls/CallResolver.java | 15 +++++++++ .../BasicExpressionTypingVisitor.java | 2 +- .../resolveToFunctionFromBuiltIns.kt | 18 +++++++++++ .../resolveToFunctionFromBuiltIns.txt | 15 +++++++++ .../checkers/DiagnosticsTestGenerated.java | 6 ++++ 6 files changed, 78 insertions(+), 10 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/collectionLiterals/resolveToFunctionFromBuiltIns.kt create mode 100644 compiler/testData/diagnostics/tests/collectionLiterals/resolveToFunctionFromBuiltIns.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/CollectionLiteralResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/CollectionLiteralResolver.kt index 03eee005077..3968599aafe 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/CollectionLiteralResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/CollectionLiteralResolver.kt @@ -21,8 +21,10 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.PrimitiveType import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersionSettings +import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor import org.jetbrains.kotlin.diagnostics.Errors.UNSUPPORTED import org.jetbrains.kotlin.diagnostics.Errors.UNSUPPORTED_FEATURE +import org.jetbrains.kotlin.incremental.KotlinLookupLocation import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtAnnotationEntry import org.jetbrains.kotlin.psi.KtClass @@ -54,6 +56,7 @@ object CollectionLiteralResolver { fun resolveCollectionLiteral(collectionLiteralExpression: KtCollectionLiteralExpression, context: ExpressionTypingContext, callResolver: CallResolver, + builtIns: KotlinBuiltIns, languageVersionSettings: LanguageVersionSettings ): KotlinTypeInfo { if (!isInsideAnnotationEntryOrClass(collectionLiteralExpression)) { @@ -62,28 +65,39 @@ object CollectionLiteralResolver { checkSupportsArrayLiterals(collectionLiteralExpression, context, languageVersionSettings) - return resolveCollectionLiteralSpecialMethod(collectionLiteralExpression, context, callResolver) + return resolveCollectionLiteralSpecialMethod(collectionLiteralExpression, context, callResolver, builtIns) } private fun resolveCollectionLiteralSpecialMethod( - collectionLiteralExpression: KtCollectionLiteralExpression, + expression: KtCollectionLiteralExpression, context: ExpressionTypingContext, - callResolver: CallResolver + callResolver: CallResolver, + builtIns: KotlinBuiltIns ): KotlinTypeInfo { - val collectionLiteralCallName = getArrayFunctionCallName(context.expectedType) - val call = CallMaker.makeCallForCollectionLiteral(collectionLiteralExpression) - val resolutionResults = callResolver.resolveCallWithGivenName(context, call, collectionLiteralExpression, collectionLiteralCallName) + val call = CallMaker.makeCallForCollectionLiteral(expression) + val functionDescriptor = getFunctionDescriptorForCollectionLiteral(expression, context, builtIns) - // TODO: check that resolved function is from package `kotlin`, otherwise report an error + val resolutionResults = callResolver.resolveCollectionLiteralCallWithGivenDescriptor(context, expression, call, functionDescriptor) + + // No single result after resolving one candidate? if (!resolutionResults.isSingleResult) { return noTypeInfo(context) } - context.trace.record(COLLECTION_LITERAL_CALL, collectionLiteralExpression, resolutionResults.resultingCall) + context.trace.record(COLLECTION_LITERAL_CALL, expression, resolutionResults.resultingCall) return createTypeInfo(resolutionResults.resultingDescriptor.returnType, context) } - fun checkSupportsArrayLiterals(expression: KtCollectionLiteralExpression, + private fun getFunctionDescriptorForCollectionLiteral( + expression: KtCollectionLiteralExpression, + context: ExpressionTypingContext, + builtIns: KotlinBuiltIns + ): SimpleFunctionDescriptor { + val callName = getArrayFunctionCallName(context.expectedType) + return builtIns.builtInsPackageScope.getContributedFunctions(callName, KotlinLookupLocation(expression)).single() + } + + private fun checkSupportsArrayLiterals(expression: KtCollectionLiteralExpression, context: ExpressionTypingContext, languageVersionSettings: LanguageVersionSettings ) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java index c6f4a6460e0..bc2741c624b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java @@ -234,6 +234,21 @@ public class CallResolver { ); } + @NotNull + public OverloadResolutionResults resolveCollectionLiteralCallWithGivenDescriptor( + @NotNull ExpressionTypingContext context, + @NotNull KtCollectionLiteralExpression expression, + @NotNull Call call, + @NotNull FunctionDescriptor functionDescriptor + ) { + BasicCallResolutionContext callResolutionContext = BasicCallResolutionContext.create(context, call, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS); + ResolutionCandidate candidate = ResolutionCandidate.create( + call, functionDescriptor, null, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, null); + + return computeTasksFromCandidatesAndResolvedCall( + callResolutionContext, Collections.singleton(candidate), TracingStrategyImpl.create(expression, call)); + } + @NotNull public OverloadResolutionResults resolveFunctionCall( @NotNull BindingTrace trace, diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java index f625b17c859..dbfe8fe292f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java @@ -1505,7 +1505,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { @NotNull KtCollectionLiteralExpression expression, ExpressionTypingContext context ) { return CollectionLiteralResolver.INSTANCE.resolveCollectionLiteral( - expression, context, components.callResolver, components.languageVersionSettings); + expression, context, components.callResolver, components.builtIns, components.languageVersionSettings); } @Override diff --git a/compiler/testData/diagnostics/tests/collectionLiterals/resolveToFunctionFromBuiltIns.kt b/compiler/testData/diagnostics/tests/collectionLiterals/resolveToFunctionFromBuiltIns.kt new file mode 100644 index 00000000000..68aef2e6c7b --- /dev/null +++ b/compiler/testData/diagnostics/tests/collectionLiterals/resolveToFunctionFromBuiltIns.kt @@ -0,0 +1,18 @@ +// !LANGUAGE: +ArrayLiteralsInAnnotations +// !DIAGNOSTICS: -UNUSED_VARIABLE, -UNSUPPORTED + +annotation class Anno(val a: Array = [""], val b: IntArray = []) + +@Anno([], []) +fun test() {} + +fun arrayOf(): Array = TODO() +fun intArrayOf(): Array = TODO() + +fun local() { + val a1: IntArray = [1, 2] + val a2: IntArray = [] + + val s1: Array = [""] + val s2: Array = [] +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/collectionLiterals/resolveToFunctionFromBuiltIns.txt b/compiler/testData/diagnostics/tests/collectionLiterals/resolveToFunctionFromBuiltIns.txt new file mode 100644 index 00000000000..7f89b5c6f98 --- /dev/null +++ b/compiler/testData/diagnostics/tests/collectionLiterals/resolveToFunctionFromBuiltIns.txt @@ -0,0 +1,15 @@ +package + +public fun arrayOf(): kotlin.Array +public fun intArrayOf(): kotlin.Array +public fun local(): kotlin.Unit +@Anno(a = {}, b = {}) public fun test(): kotlin.Unit + +public final annotation class Anno : kotlin.Annotation { + public constructor Anno(/*0*/ a: kotlin.Array = ..., /*1*/ b: kotlin.IntArray = ...) + public final val a: kotlin.Array + public final val b: kotlin.IntArray + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 202ab8e94fd..21bcb6cdd58 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -3387,6 +3387,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/collectionLiterals/noCollectionLiterals.kt"); doTest(fileName); } + + @TestMetadata("resolveToFunctionFromBuiltIns.kt") + public void testResolveToFunctionFromBuiltIns() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/collectionLiterals/resolveToFunctionFromBuiltIns.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/diagnostics/tests/constructorConsistency")