Support type inference for coroutines.

This commit is contained in:
Stanislav Erokhin
2016-12-08 13:49:30 +03:00
committed by Stanislav Erokhin
parent 509a504318
commit 55983a7808
29 changed files with 848 additions and 3 deletions
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.resolve.calls.callResolverUtil.CallResolverUtilKt;
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode;
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
import org.jetbrains.kotlin.resolve.calls.context.*;
import org.jetbrains.kotlin.resolve.calls.inference.CoroutineInferenceUtilKt;
import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments;
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl;
@@ -516,6 +517,13 @@ public class CallResolver {
BindingContextUtilsKt.recordDataFlowInfo(newContext, newContext.call.getCalleeExpression());
OverloadResolutionResultsImpl<D> results = doResolveCall(newContext, resolutionTask, tracing);
// this is necessary because we already run CallCompleter for such calls
if (CoroutineInferenceUtilKt.isResultWithCoroutineInference(results)) {
traceToResolveCall.commit();
return results;
}
DelegatingBindingTrace deltasTraceForTypeInference = ((OverloadResolutionResultsImpl) results).getTrace();
if (deltasTraceForTypeInference != null) {
deltasTraceForTypeInference.addOwnDataTo(traceToResolveCall);
@@ -52,7 +52,10 @@ import org.jetbrains.kotlin.types.TypeUtils.DONT_CARE
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeResolver) {
class GenericCandidateResolver(
private val argumentTypeResolver: ArgumentTypeResolver,
private val coroutineInferenceSupport: CoroutineInferenceSupport
) {
fun <D : CallableDescriptor> inferTypeArguments(context: CallCandidateResolutionContext<D>): ResolutionStatus {
val candidateCall = context.candidateCall
val candidate = candidateCall.candidateDescriptor
@@ -299,6 +302,10 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
val effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor, valueArgument)
if (isCoroutineCallWithAdditionalInference(valueParameterDescriptor, valueArgument)) {
coroutineInferenceSupport.analyzeCoroutine(functionLiteral, valueArgument, constraintSystem, context, effectiveExpectedType)
}
val currentSubstitutor = constraintSystem.build().currentSubstitutor
val newSubstitution = object : DelegatedTypeSubstitution(currentSubstitutor.substitution) {
override fun approximateContravariantCapturedTypes() = true
@@ -0,0 +1,284 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.resolve.calls.inference
import org.jetbrains.kotlin.builtins.*
import org.jetbrains.kotlin.coroutines.hasSuspendFunctionType
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.psi.KtLambdaExpression
import org.jetbrains.kotlin.psi.ValueArgument
import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.renderer.DescriptorRendererOptions
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver.getCallableReferenceExpressionIfAny
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver.getFunctionLiteralArgumentIfAny
import org.jetbrains.kotlin.resolve.calls.CallCompleter
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getEffectiveExpectedType
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.hasUnknownFunctionParameter
import org.jetbrains.kotlin.resolve.calls.context.*
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind
import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch
import org.jetbrains.kotlin.resolve.calls.model.isReallySuccess
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE
import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker
import org.jetbrains.kotlin.types.checker.TypeCheckerContext
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices
import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
import org.jetbrains.kotlin.types.typeUtil.builtIns
import org.jetbrains.kotlin.types.typeUtil.contains
import javax.inject.Inject
class TypeTemplate(
val typeVariable: TypeVariable,
val coroutineInferenceData: CoroutineInferenceData
) : FlexibleType(typeVariable.originalTypeParameter.builtIns.nothingType, typeVariable.originalTypeParameter.builtIns.nullableAnyType) {
override fun replaceAnnotations(newAnnotations: Annotations) = this
override fun makeNullableAsSpecified(newNullability: Boolean) = this
override val delegate: SimpleType
get() = upperBound
override fun render(renderer: DescriptorRenderer, options: DescriptorRendererOptions) =
"~${renderer.renderType(typeVariable.type)}"
}
class CoroutineInferenceData {
private val csBuilder = ConstraintSystemBuilderImpl()
private val typeTemplates = HashMap<TypeVariable, TypeTemplate>()
private var hereIsBadCall = false
fun getTypeTemplate(typeVariable: TypeVariable) =
typeTemplates.getOrPut(typeVariable) {
TypeTemplate(typeVariable, this)
}
fun initSystem() {
csBuilder.registerTypeVariables(CallHandle.NONE, typeTemplates.keys.map { it.freshTypeParameter })
}
fun toNewVariableType(type: KotlinType): KotlinType {
return (type.unwrap() as? TypeTemplate)?.typeVariable?.freshTypeParameter?.let { typeVariable ->
csBuilder.typeVariableSubstitutors[CallHandle.NONE]?.substitution?.get(typeVariable.defaultType)?.type
} ?: type
}
fun addConstraint(subType: KotlinType, superType: KotlinType) {
csBuilder.addSubtypeConstraint(toNewVariableType(subType), toNewVariableType(superType), ConstraintPositionKind.SPECIAL.position())
}
fun reportInferenceResult(externalCSBuilder: ConstraintSystem.Builder) {
if (hereIsBadCall) return
val resultingSubstitution = csBuilder.build().resultingSubstitutor.substitution
for ((originalTypeVariable) in typeTemplates) {
resultingSubstitution[originalTypeVariable.type]?.type.let {
externalCSBuilder.addSubtypeConstraint(originalTypeVariable.type, it, ConstraintPositionKind.FROM_COMPLETER.position())
externalCSBuilder.addSubtypeConstraint(it, originalTypeVariable.type, ConstraintPositionKind.FROM_COMPLETER.position())
}
}
}
fun badCallHappened() {
hereIsBadCall = true
}
}
class CoroutineInferenceSupport(
val argumentTypeResolver: ArgumentTypeResolver,
val expressionTypingServices: ExpressionTypingServices
) {
@set:Inject
lateinit var callCompleter: CallCompleter
fun analyzeCoroutine(
functionLiteral: KtFunction,
valueArgument: ValueArgument,
csBuilder: ConstraintSystem.Builder,
context: CallCandidateResolutionContext<*>,
lambdaExpectedType: KotlinType
) {
val argumentExpression = valueArgument.getArgumentExpression() ?: return
if (!lambdaExpectedType.isSuspendFunctionType) return
val lambdaReceiverType = lambdaExpectedType.getReceiverTypeFromFunctionType() ?: return
val inferenceData = CoroutineInferenceData()
val constraintSystem = csBuilder.build()
val newSubstitution = object : DelegatedTypeSubstitution(constraintSystem.currentSubstitutor.substitution) {
override fun get(key: KotlinType): TypeProjection? {
val substitutedType = super.get(key)
if (substitutedType?.type != TypeUtils.DONT_CARE) return substitutedType
// todo: what about nullable type?
val typeVariable = constraintSystem.typeVariables.firstOrNull {
it.originalTypeParameter.defaultType == key
} ?: return substitutedType
return inferenceData.getTypeTemplate(typeVariable).asTypeProjection()
}
override fun approximateContravariantCapturedTypes() = true
}
val newReceiverType = newSubstitution.buildSubstitutor().substitute(lambdaReceiverType, Variance.INVARIANT) ?: return
val approximationSubstitutor = object : DelegatedTypeSubstitution(constraintSystem.currentSubstitutor.substitution) {
override fun approximateContravariantCapturedTypes() = true
}
val approximatedLambdaType = approximationSubstitutor.buildSubstitutor().substitute(lambdaExpectedType, Variance.IN_VARIANCE) ?: return
val newExpectedType = createFunctionType(newReceiverType.builtIns, approximatedLambdaType.annotations, newReceiverType,
approximatedLambdaType.getValueParameterTypesFromFunctionType().map(TypeProjection::getType),
parameterNames = null, // TODO: parameterNames
returnType = approximatedLambdaType.getReturnTypeFromFunctionType(),
suspendFunction = true)
if (hasUnknownFunctionParameter(newExpectedType)) return
inferenceData.initSystem()
// this trace shouldn't be committed
val temporaryForCoroutine = TemporaryTraceAndCache.create(
context, "trace for type argument inference for coroutine", functionLiteral)
val newContext = context.replaceExpectedType(newExpectedType)
.replaceDataFlowInfo(context.candidateCall.dataFlowInfoForArguments.getInfo(valueArgument))
.replaceContextDependency(ContextDependency.INDEPENDENT).replaceTraceAndCache(temporaryForCoroutine)
argumentTypeResolver.getFunctionLiteralTypeInfo(argumentExpression, functionLiteral, newContext, RESOLVE_FUNCTION_ARGUMENTS).type
inferenceData.reportInferenceResult(csBuilder)
}
fun checkCoroutineCalls(
context: BasicCallResolutionContext,
tracingStrategy: TracingStrategy,
overloadResults: OverloadResolutionResultsImpl<*>
) {
val inferenceData = overloadResults.getCoroutineInferenceData() ?: return
val resultingCall = overloadResults.resultingCall
forceInferenceForArguments(context) { _: ValueArgument, _: KotlinType -> /* do nothing */ }
callCompleter.completeCall(context, overloadResults, tracingStrategy)
if (!resultingCall.isReallySuccess()) return
if (isBadCall(resultingCall.resultingDescriptor)) {
inferenceData.badCallHappened()
}
forceInferenceForArguments(context) {
valueArgument: ValueArgument, kotlinType: KotlinType ->
val argumentMatch = resultingCall.getArgumentMapping(valueArgument) as? ArgumentMatch
?: return@forceInferenceForArguments
with(NewKotlinTypeChecker) {
val parameterType = getEffectiveExpectedType(argumentMatch.valueParameter, valueArgument)
CoroutineTypeCheckerContext().isSubtypeOf(kotlinType.unwrap(), parameterType.unwrap())
}
}
val extensionReceiver = resultingCall.resultingDescriptor.extensionReceiverParameter ?: return
resultingCall.extensionReceiver?.let { actualReceiver ->
with(NewKotlinTypeChecker) {
CoroutineTypeCheckerContext().isSubtypeOf(actualReceiver.type.unwrap(), extensionReceiver.value.type.unwrap())
}
}
}
private fun isBadCall(resultingDescriptor: CallableDescriptor): Boolean {
fun KotlinType.containsTypeTemplate() = contains { it is TypeTemplate }
val returnType = resultingDescriptor.returnType ?: return true
if (returnType.containsTypeTemplate()) return true
if (resultingDescriptor !is FunctionDescriptor || resultingDescriptor.isSuspend) return false
for (valueParameter in resultingDescriptor.valueParameters) {
if (valueParameter.type.containsTypeTemplate()) return true
}
return false
}
private class CoroutineTypeCheckerContext : TypeCheckerContext(errorTypeEqualsToAnything = true) {
override fun addSubtypeConstraint(subType: UnwrappedType, superType: UnwrappedType): Boolean? {
(subType as? TypeTemplate ?: superType as? TypeTemplate)?.coroutineInferenceData?.addConstraint(subType, superType)
return null
}
}
private fun forceInferenceForArguments(context: CallResolutionContext<*>, callback: (argument: ValueArgument, argumentType: KotlinType) -> Unit) {
val infoForArguments = context.dataFlowInfoForArguments
val call = context.call
val baseContext = context.replaceContextDependency(ContextDependency.INDEPENDENT).replaceExpectedType(NO_EXPECTED_TYPE)
for (argument in call.valueArguments) {
val expression = argument.getArgumentExpression() ?: continue
val typeInfoForCall = getArgumentTypeInfo(expression, baseContext.replaceDataFlowInfo(infoForArguments.getInfo(argument)))
typeInfoForCall.type?.let { callback(argument, it) }
}
}
private fun getArgumentTypeInfo(
expression: KtExpression,
context: CallResolutionContext<*>
): KotlinTypeInfo {
getFunctionLiteralArgumentIfAny(expression, context)?.let {
return argumentTypeResolver.getFunctionLiteralTypeInfo(expression, it, context, RESOLVE_FUNCTION_ARGUMENTS)
}
getCallableReferenceExpressionIfAny(expression, context)?.let {
return argumentTypeResolver.getCallableReferenceTypeInfo(expression, it, context, RESOLVE_FUNCTION_ARGUMENTS)
}
return expressionTypingServices.getTypeInfo(expression, context)
}
}
fun isCoroutineCallWithAdditionalInference(parameterDescriptor: ValueParameterDescriptor, argument: ValueArgument) =
parameterDescriptor.hasSuspendFunctionType &&
argument.getArgumentExpression() is KtLambdaExpression &&
parameterDescriptor.type.let { it.isBuiltinFunctionalType && it.getReceiverTypeFromFunctionType() != null }
fun OverloadResolutionResultsImpl<*>.isResultWithCoroutineInference() = getCoroutineInferenceData() != null
private fun OverloadResolutionResultsImpl<*>.getCoroutineInferenceData(): CoroutineInferenceData? {
if (!isSingleResult) return null
fun getData(receiverValue: ReceiverValue?): CoroutineInferenceData? {
var coroutineInferenceData: CoroutineInferenceData? = null
receiverValue?.type?.contains {
(it as? TypeTemplate)?.coroutineInferenceData?.let { coroutineInferenceData = it }
false
}
return coroutineInferenceData
}
return getData(resultingCall.dispatchReceiver) ?: getData(resultingCall.extensionReceiver)
}
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isConventionCall
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isInfixCall
import org.jetbrains.kotlin.resolve.calls.callUtil.createLookupLocation
import org.jetbrains.kotlin.resolve.calls.context.*
import org.jetbrains.kotlin.resolve.calls.inference.CoroutineInferenceSupport
import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCallImpl
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCallImpl
@@ -67,7 +68,8 @@ class NewResolutionOldInference(
private val dynamicCallableDescriptors: DynamicCallableDescriptors,
private val syntheticScopes: SyntheticScopes,
private val syntheticConstructorsProvider: SyntheticConstructorsProvider,
private val languageVersionSettings: LanguageVersionSettings
private val languageVersionSettings: LanguageVersionSettings,
private val coroutineInferenceSupport: CoroutineInferenceSupport
) {
sealed class ResolutionKind<D : CallableDescriptor> {
abstract internal fun createTowerProcessor(
@@ -189,7 +191,9 @@ class NewResolutionOldInference(
}
}
return convertToOverloadResults(candidates, tracing, context)
val overloadResults = convertToOverloadResults(candidates, tracing, context)
coroutineInferenceSupport.checkCoroutineCalls(context, tracing, overloadResults)
return overloadResults
}
fun <D : CallableDescriptor> runResolutionForGivenCandidates(
@@ -0,0 +1,20 @@
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE
interface Controller<T> {
suspend fun yield(t: T) {}
fun justString(): String = ""
fun <Z> generidFun(t: Z) = t
}
fun <S> generate(g: suspend Controller<S>.() -> Unit): S = TODO()
val test1 = generate {
yield(justString())
}
val test2 = generate {
yield(generidFun(2))
}
@@ -0,0 +1,14 @@
package
public val test1: kotlin.String
public val test2: kotlin.Int
public fun </*0*/ S> generate(/*0*/ g: suspend Controller<S>.() -> kotlin.Unit): S
public interface Controller</*0*/ T> {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open fun </*0*/ Z> generidFun(/*0*/ t: Z): Z
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open fun justString(): kotlin.String
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public open suspend fun yield(/*0*/ t: T): kotlin.Unit
}
@@ -0,0 +1,21 @@
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE
class GenericController<T>
suspend fun <S> GenericController<S>.yieldAll(s: Collection<S>): String = ""
suspend fun <S> GenericController<S>.yieldAll(s: Set<S>): Int = 4
fun <T, R> generate(g: suspend GenericController<T>.() -> R): Pair<T, R> = TODO()
val test1 = generate {
yieldAll(setOf(4))
}
val test2 = generate {
yieldAll(listOf(4))
}
// Util function
fun <X> setOf(vararg x: X): Set<X> = TODO()
fun <X> listOf(vararg x: X): List<X> = TODO()
class Pair<T, S>
@@ -0,0 +1,23 @@
package
public val test1: Pair<kotlin.Int, kotlin.Int>
public val test2: Pair<kotlin.Int, kotlin.String>
public fun </*0*/ T, /*1*/ R> generate(/*0*/ g: suspend GenericController<T>.() -> R): Pair<T, R>
public fun </*0*/ X> listOf(/*0*/ vararg x: X /*kotlin.Array<out X>*/): kotlin.collections.List<X>
public fun </*0*/ X> setOf(/*0*/ vararg x: X /*kotlin.Array<out X>*/): kotlin.collections.Set<X>
public suspend fun </*0*/ S> GenericController<S>.yieldAll(/*0*/ s: kotlin.collections.Collection<S>): kotlin.String
public suspend fun </*0*/ S> GenericController<S>.yieldAll(/*0*/ s: kotlin.collections.Set<S>): kotlin.Int
public final class GenericController</*0*/ T> {
public constructor GenericController</*0*/ T>()
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
}
public final class Pair</*0*/ T, /*1*/ S> {
public constructor Pair</*0*/ T, /*1*/ S>()
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
}
@@ -0,0 +1,37 @@
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE
class GenericController<T> {
suspend fun yield(t: T) {}
}
suspend fun <S> GenericController<S>.yieldAll(s: Collection<S>) {}
fun <S> generate(g: suspend GenericController<S>.() -> Unit): S = TODO()
val test1 = generate {
yield(4)
yieldAll(setOf(4, 5))
}
val test2 = generate {
yieldAll(setOf(B))
}
val test3 = generate {
yieldAll(setOf(B, C))
}
val test4 = generate {
yieldAll(setOf(B))
yield(C)
}
// Utils
fun <X> setOf(vararg x: X): Set<X> = TODO()
interface A
object B : A
object C : A
@@ -0,0 +1,37 @@
package
public val test1: kotlin.Int
public val test2: B
public val test3: A
public val test4: A
public fun </*0*/ S> generate(/*0*/ g: suspend GenericController<S>.() -> kotlin.Unit): S
public fun </*0*/ X> setOf(/*0*/ vararg x: X /*kotlin.Array<out X>*/): kotlin.collections.Set<X>
public suspend fun </*0*/ S> GenericController<S>.yieldAll(/*0*/ s: kotlin.collections.Collection<S>): kotlin.Unit
public interface A {
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
}
public object B : A {
private constructor B()
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
}
public object C : A {
private constructor C()
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
}
public final class GenericController</*0*/ T> {
public constructor GenericController</*0*/ T>()
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
public final suspend fun yield(/*0*/ t: T): kotlin.Unit
}
@@ -0,0 +1,30 @@
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE
class GenericController<T> {
suspend fun yield(t: T) {}
fun notYield(t: T) {}
suspend fun yieldBarReturnType(t: T) = t
fun barReturnType(): T = TODO()
}
fun <S> generate(g: suspend GenericController<S>.() -> Unit): List<S> = TODO()
val test1 = generate {
yield(3)
}
val test2 = <!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>generate<!> {
yield(3)
notYield(3)
}
val test3 = <!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>generate<!> {
yield(3)
yieldBarReturnType(3)
}
val test4 = <!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>generate<!> {
yield(3)
barReturnType()
}
@@ -0,0 +1,27 @@
package
public val test1: kotlin.collections.List<kotlin.Int>
public val test2: [ERROR : Type for generate {
yield(3)
notYield(3)
}]
public val test3: [ERROR : Type for generate {
yield(3)
yieldBarReturnType(3)
}]
public val test4: [ERROR : Type for generate {
yield(3)
barReturnType()
}]
public fun </*0*/ S> generate(/*0*/ g: suspend GenericController<S>.() -> kotlin.Unit): kotlin.collections.List<S>
public final class GenericController</*0*/ T> {
public constructor GenericController</*0*/ T>()
public final fun barReturnType(): T
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 final fun notYield(/*0*/ t: T): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public final suspend fun yield(/*0*/ t: T): kotlin.Unit
public final suspend fun yieldBarReturnType(/*0*/ t: T): T
}
@@ -0,0 +1,17 @@
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE
class GenericController<T> {
suspend fun yield(t: T) {}
}
fun <S> generate(g: suspend GenericController<S>.() -> Unit): List<S> = TODO()
val test1 = generate {
yield(generate {
yield(generate {
yield(generate {
yield(3)
})
})
})
}
@@ -0,0 +1,12 @@
package
public val test1: kotlin.collections.List<kotlin.collections.List<kotlin.collections.List<kotlin.collections.List<kotlin.Int>>>>
public fun </*0*/ S> generate(/*0*/ g: suspend GenericController<S>.() -> kotlin.Unit): kotlin.collections.List<S>
public final class GenericController</*0*/ T> {
public constructor GenericController</*0*/ T>()
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
public final suspend fun yield(/*0*/ t: T): kotlin.Unit
}
@@ -0,0 +1,16 @@
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE
class GenericController<T> {
suspend fun yield(t: T) {}
}
fun <S> generate(g: suspend GenericController<S>.() -> Unit): List<S> = TODO()
suspend fun <S> GenericController<List<S>>.yieldGenerate(g: suspend GenericController<S>.() -> Unit): Unit = TODO()
val test1 = generate {
// TODO: KT-15185
<!TYPE_MISMATCH, TYPE_INFERENCE_PARAMETER_CONSTRAINT_ERROR!>yieldGenerate<!> {
yield(4)
}
}
@@ -0,0 +1,13 @@
package
public val test1: kotlin.collections.List<kotlin.Int>
public fun </*0*/ S> generate(/*0*/ g: suspend GenericController<S>.() -> kotlin.Unit): kotlin.collections.List<S>
public suspend fun </*0*/ S> GenericController<kotlin.collections.List<S>>.yieldGenerate(/*0*/ g: suspend GenericController<S>.() -> kotlin.Unit): kotlin.Unit
public final class GenericController</*0*/ T> {
public constructor GenericController</*0*/ T>()
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
public final suspend fun yield(/*0*/ t: T): kotlin.Unit
}
@@ -0,0 +1,9 @@
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE
class Controller
fun <R> generate(g: suspend Controller.() -> R): R = TODO()
val test1 = generate {
3
}
@@ -0,0 +1,11 @@
package
public val test1: kotlin.Int
public fun </*0*/ R> generate(/*0*/ g: suspend Controller.() -> R): R
public final class Controller {
public constructor Controller()
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
}
@@ -0,0 +1,14 @@
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE
class Controller<T> {
suspend fun yield(t: T) {}
}
fun <T, R> generate(g: suspend Controller<T>.() -> R): Pair<T, R> = TODO()
val test1 = generate {
yield("")
3
}
class Pair<T, R>
@@ -0,0 +1,19 @@
package
public val test1: Pair<kotlin.String, kotlin.Int>
public fun </*0*/ T, /*1*/ R> generate(/*0*/ g: suspend Controller<T>.() -> R): Pair<T, R>
public final class Controller</*0*/ T> {
public constructor Controller</*0*/ T>()
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
public final suspend fun yield(/*0*/ t: T): kotlin.Unit
}
public final class Pair</*0*/ T, /*1*/ R> {
public constructor Pair</*0*/ T, /*1*/ R>()
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
}
@@ -0,0 +1,29 @@
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE
class GenericController<T> {
suspend fun yield(t: T) {}
suspend fun yieldSet(t: Set<T>) {}
suspend fun yieldVararg(vararg t: T) {}
}
fun <S> generate(g: suspend GenericController<S>.() -> Unit): S = TODO()
val test1 = generate {
yield(4)
}
val test2 = generate {
yieldSet(setOf(1, 2, 3))
}
val test3 = generate {
yieldVararg(1, 2, 3)
}
val test4 = generate {
yieldVararg(1, 2, "")
}
// Util function
fun <X> setOf(vararg x: X): Set<X> = TODO()
@@ -0,0 +1,18 @@
package
public val test1: kotlin.Int
public val test2: kotlin.Int
public val test3: kotlin.Int
public val test4: kotlin.Any
public fun </*0*/ S> generate(/*0*/ g: suspend GenericController<S>.() -> kotlin.Unit): S
public fun </*0*/ X> setOf(/*0*/ vararg x: X /*kotlin.Array<out X>*/): kotlin.collections.Set<X>
public final class GenericController</*0*/ T> {
public constructor GenericController</*0*/ T>()
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
public final suspend fun yield(/*0*/ t: T): kotlin.Unit
public final suspend fun yieldSet(/*0*/ t: kotlin.collections.Set<T>): kotlin.Unit
public final suspend fun yieldVararg(/*0*/ vararg t: T /*kotlin.Array<out T>*/): kotlin.Unit
}
@@ -0,0 +1,11 @@
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE
class GenericController<T>
fun <S> generate(g: suspend GenericController<S>.() -> Unit): List<S> = TODO()
suspend fun GenericController<List<String>>.test() {}
val test1 = generate {
test()
}
@@ -0,0 +1,12 @@
package
public val test1: kotlin.collections.List<kotlin.collections.List<kotlin.String>>
public fun </*0*/ S> generate(/*0*/ g: suspend GenericController<S>.() -> kotlin.Unit): kotlin.collections.List<S>
public suspend fun GenericController<kotlin.collections.List<kotlin.String>>.test(): kotlin.Unit
public final class GenericController</*0*/ T> {
public constructor GenericController</*0*/ T>()
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
}
@@ -0,0 +1,16 @@
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE
class GenericController<T> {
suspend fun yield(t: T) {}
}
fun <S, P1, P2, R> generate(p1: P1, p2: List<P2>, g: suspend GenericController<S>.(P1, P2) -> R): Four<S, P1, P2, R> = TODO()
val test1 = generate(1, listOf("")) { p1, p2 ->
yield(p1)
p2
}
fun <X> listOf(vararg x: X): List<X> = TODO()
class Four<X, Y, Z, T>
@@ -0,0 +1,20 @@
package
public val test1: Four<kotlin.Int, kotlin.Int, kotlin.String, kotlin.String>
public fun </*0*/ S, /*1*/ P1, /*2*/ P2, /*3*/ R> generate(/*0*/ p1: P1, /*1*/ p2: kotlin.collections.List<P2>, /*2*/ g: suspend GenericController<S>.(P1, P2) -> R): Four<S, P1, P2, R>
public fun </*0*/ X> listOf(/*0*/ vararg x: X /*kotlin.Array<out X>*/): kotlin.collections.List<X>
public final class Four</*0*/ X, /*1*/ Y, /*2*/ Z, /*3*/ T> {
public constructor Four</*0*/ X, /*1*/ Y, /*2*/ Z, /*3*/ T>()
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
}
public final class GenericController</*0*/ T> {
public constructor GenericController</*0*/ T>()
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
public final suspend fun yield(/*0*/ t: T): kotlin.Unit
}
@@ -0,0 +1,19 @@
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE
class GenericController<T> {
suspend fun yield(t: T) {}
}
fun <S> generate(g: suspend GenericController<S>.(S) -> Unit): S = TODO()
val test1 = <!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>generate<!> {
yield(4)
}
val test2 = generate<Int> {
yield(4)
}
val test3 = generate { bar: Int ->
yield(4)
}
@@ -0,0 +1,16 @@
package
public val test1: [ERROR : Type for generate {
yield(4)
}]
public val test2: kotlin.Int
public val test3: kotlin.Int
public fun </*0*/ S> generate(/*0*/ g: suspend GenericController<S>.(S) -> kotlin.Unit): S
public final class GenericController</*0*/ T> {
public constructor GenericController</*0*/ T>()
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
public final suspend fun yield(/*0*/ t: T): kotlin.Unit
}
@@ -4324,6 +4324,87 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("compiler/testData/diagnostics/tests/coroutines/inference")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Inference extends AbstractDiagnosticsTest {
public void testAllFilesPresentInInference() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/coroutines/inference"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("correctMember.kt")
public void testCorrectMember() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/coroutines/inference/correctMember.kt");
doTest(fileName);
}
@TestMetadata("extensionPriority.kt")
public void testExtensionPriority() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/coroutines/inference/extensionPriority.kt");
doTest(fileName);
}
@TestMetadata("extensionSuspend.kt")
public void testExtensionSuspend() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/coroutines/inference/extensionSuspend.kt");
doTest(fileName);
}
@TestMetadata("incorrectCalls.kt")
public void testIncorrectCalls() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/coroutines/inference/incorrectCalls.kt");
doTest(fileName);
}
@TestMetadata("recursiveGenerators.kt")
public void testRecursiveGenerators() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/coroutines/inference/recursiveGenerators.kt");
doTest(fileName);
}
@TestMetadata("recursiveGenerators2.kt")
public void testRecursiveGenerators2() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/coroutines/inference/recursiveGenerators2.kt");
doTest(fileName);
}
@TestMetadata("returnTypeInference.kt")
public void testReturnTypeInference() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/coroutines/inference/returnTypeInference.kt");
doTest(fileName);
}
@TestMetadata("returnTypeInference2.kt")
public void testReturnTypeInference2() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/coroutines/inference/returnTypeInference2.kt");
doTest(fileName);
}
@TestMetadata("simpleGenerator.kt")
public void testSimpleGenerator() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/coroutines/inference/simpleGenerator.kt");
doTest(fileName);
}
@TestMetadata("typeFromReceiver.kt")
public void testTypeFromReceiver() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/coroutines/inference/typeFromReceiver.kt");
doTest(fileName);
}
@TestMetadata("withParameter.kt")
public void testWithParameter() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/coroutines/inference/withParameter.kt");
doTest(fileName);
}
@TestMetadata("withUninferredParameter.kt")
public void testWithUninferredParameter() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/coroutines/inference/withUninferredParameter.kt");
doTest(fileName);
}
}
@TestMetadata("compiler/testData/diagnostics/tests/coroutines/suspendFunctionType")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)