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
This commit is contained in:
Mikhail Zarechenskiy
2017-03-22 17:52:51 +03:00
parent 222f101d10
commit 2a93dea0c4
6 changed files with 78 additions and 10 deletions
@@ -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
) {
@@ -234,6 +234,21 @@ public class CallResolver {
);
}
@NotNull
public OverloadResolutionResults<FunctionDescriptor> resolveCollectionLiteralCallWithGivenDescriptor(
@NotNull ExpressionTypingContext context,
@NotNull KtCollectionLiteralExpression expression,
@NotNull Call call,
@NotNull FunctionDescriptor functionDescriptor
) {
BasicCallResolutionContext callResolutionContext = BasicCallResolutionContext.create(context, call, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS);
ResolutionCandidate<FunctionDescriptor> candidate = ResolutionCandidate.create(
call, functionDescriptor, null, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, null);
return computeTasksFromCandidatesAndResolvedCall(
callResolutionContext, Collections.singleton(candidate), TracingStrategyImpl.create(expression, call));
}
@NotNull
public OverloadResolutionResults<FunctionDescriptor> resolveFunctionCall(
@NotNull BindingTrace trace,
@@ -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
@@ -0,0 +1,18 @@
// !LANGUAGE: +ArrayLiteralsInAnnotations
// !DIAGNOSTICS: -UNUSED_VARIABLE, -UNSUPPORTED
annotation class Anno(val a: Array<String> = [""], val b: IntArray = [])
@Anno([], [])
fun test() {}
fun arrayOf(): Array<Int> = TODO()
fun intArrayOf(): Array<Int> = TODO()
fun local() {
val a1: IntArray = [1, 2]
val a2: IntArray = []
val s1: Array<String> = [""]
val s2: Array<String> = []
}
@@ -0,0 +1,15 @@
package
public fun arrayOf(): kotlin.Array<kotlin.Int>
public fun intArrayOf(): kotlin.Array<kotlin.Int>
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<kotlin.String> = ..., /*1*/ b: kotlin.IntArray = ...)
public final val a: kotlin.Array<kotlin.String>
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
}
@@ -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")