[FIR] Improve mapping arguments to parameters

This commit is contained in:
Dmitriy Novozhilov
2020-02-14 11:10:46 +03:00
parent 2e597a3a32
commit e696d1d06a
43 changed files with 498 additions and 241 deletions
@@ -324,16 +324,19 @@ private fun Candidate.getExpectedTypeWithSAMConversion(
internal fun FirExpression.getExpectedType(
session: FirSession,
parameter: FirValueParameter/*, languageVersionSettings: LanguageVersionSettings*/
) =
// if (this.isSpread || this.isArrayAssignedAsNamedArgumentInAnnotation(parameter, languageVersionSettings)) {
// parameter.type.unwrap()
// } else {
if (parameter.isVararg && (this !is FirWrappedArgumentExpression || !isSpread)) {
): ConeKotlinType {
val shouldUnwrapVarargType = when (this) {
is FirSpreadArgumentExpression -> !isSpread
is FirNamedArgumentExpression -> false
else -> true
}
return if (parameter.isVararg && shouldUnwrapVarargType) {
parameter.returnTypeRef.coneTypeUnsafe<ConeKotlinType>().varargElementType(session)
} else {
parameter.returnTypeRef.coneTypeUnsafe()
}//?.varargElementType?.unwrap() ?: parameter.type.unwrap()
// }
}
}
private fun ConeKotlinType.varargElementType(session: FirSession): ConeKotlinType {
@@ -354,4 +357,4 @@ fun FirTypeRef.isExtensionFunctionType(session: FirSession): Boolean {
if (typeAlias.expandedTypeRef.annotations.any(FirAnnotationCall::isExtensionFunctionAnnotationCall)) return true
return false
}
}
@@ -109,6 +109,8 @@ class Candidate(
var argumentMapping: Map<FirExpression, FirValueParameter>? = null
val postponedAtoms = mutableListOf<PostponedResolvedAtomMarker>()
val diagnostics: MutableList<ResolutionDiagnostic> = mutableListOf()
fun dispatchReceiverExpression(): FirExpression = when (explicitReceiverKind) {
ExplicitReceiverKind.DISPATCH_RECEIVER, ExplicitReceiverKind.BOTH_RECEIVERS -> callInfo.explicitReceiver!!
else -> dispatchReceiverValue?.receiverExpression ?: FirNoReceiverExpression
@@ -0,0 +1,257 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.fir.declarations.FirFunction
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirLambdaArgumentExpression
import org.jetbrains.kotlin.fir.expressions.FirNamedArgumentExpression
import org.jetbrains.kotlin.fir.expressions.FirSpreadArgumentExpression
import org.jetbrains.kotlin.name.Name
import java.util.*
import kotlin.collections.ArrayList
import kotlin.collections.component1
import kotlin.collections.component2
import kotlin.collections.set
data class ArgumentMapping(
// This map should be ordered by arguments as written, e.g.:
// fun foo(a: Int, b: Int) {}
// foo(b = bar(), a = qux())
// parameterToCallArgumentMap.values() should be [ 'bar()', 'foo()' ]
val parameterToCallArgumentMap: Map<FirValueParameter, ResolvedCallArgument>,
val diagnostics: List<ResolutionDiagnostic>
)
private val EmptyArgumentMapping = ArgumentMapping(emptyMap(), emptyList())
fun mapArguments(
arguments: List<FirExpression>,
function: FirFunction<*>
): ArgumentMapping {
if (arguments.isEmpty() && function.valueParameters.isEmpty()) {
return EmptyArgumentMapping
}
val externalArgument: FirExpression? = arguments.lastOrNull { it is FirLambdaArgumentExpression }
val argumentsInParenthesis: List<FirExpression> = if (externalArgument == null) {
arguments
} else {
arguments.subList(0, arguments.size - 1)
}
val processor = FirCallArgumentsProcessor(function)
processor.processArgumentsInParenthesis(argumentsInParenthesis)
if (externalArgument != null) {
processor.processExternalArgument(externalArgument)
}
processor.processDefaultsAndRunChecks()
return ArgumentMapping(processor.result, processor.diagnostics ?: emptyList())
}
private class FirCallArgumentsProcessor(private val function: FirFunction<*>) {
private var state = State.POSITION_ARGUMENTS
private var currentPositionedParameterIndex = 0
private var varargArguments: MutableList<FirExpression>? = null
private var nameToParameter: Map<Name, FirValueParameter>? = null
var diagnostics: MutableList<ResolutionDiagnostic>? = null
private set
val result: MutableMap<FirValueParameter, ResolvedCallArgument> = LinkedHashMap()
private enum class State {
POSITION_ARGUMENTS,
VARARG_POSITION,
NAMED_ONLY_ARGUMENTS
}
fun processArgumentsInParenthesis(arguments: List<FirExpression>) {
for (argument in arguments) {
val argumentName = argument.argumentName
// process position argument
if (argumentName == null) {
if (processPositionArgument(argument)) {
state = State.VARARG_POSITION
}
}
// process named argument
else {
if (state == State.VARARG_POSITION) {
completeVarargPositionArguments()
}
state = State.NAMED_ONLY_ARGUMENTS
processNamedArgument(argument, argumentName)
}
}
if (state == State.VARARG_POSITION) {
completeVarargPositionArguments()
}
}
// return true, if it was mapped to vararg parameter
private fun processPositionArgument(argument: FirExpression): Boolean {
if (state == State.NAMED_ONLY_ARGUMENTS) {
addDiagnostic(MixingNamedAndPositionArguments(argument))
return false
}
val parameter = parameters.getOrNull(currentPositionedParameterIndex)
if (parameter == null) {
addDiagnostic(TooManyArguments(argument, function))
return false
}
if (!parameter.isVararg) {
currentPositionedParameterIndex++
result[parameter] = ResolvedCallArgument.SimpleArgument(argument)
return false
}
// all position arguments will be mapped to current vararg parameter
else {
addVarargArgument(argument)
return true
}
}
private fun processNamedArgument(argument: FirExpression, name: Name) {
if (!function.hasStableParameterNames) {
addDiagnostic(NamedArgumentNotAllowed(argument, function))
}
val parameter = findParameterByName(argument, name) ?: return
result[parameter]?.let {
addDiagnostic(ArgumentPassedTwice(argument, parameter, it))
return
}
result[parameter] = ResolvedCallArgument.SimpleArgument(argument)
if (parameters.getOrNull(currentPositionedParameterIndex) == parameter) {
state = State.POSITION_ARGUMENTS
currentPositionedParameterIndex++
}
}
fun processExternalArgument(externalArgument: FirExpression) {
val lastParameter = parameters.lastOrNull()
if (lastParameter == null) {
addDiagnostic(TooManyArguments(externalArgument, function))
return
}
if (lastParameter.isVararg) {
addDiagnostic(VarargArgumentOutsideParentheses(externalArgument, lastParameter))
return
}
val previousOccurrence = result[lastParameter]
if (previousOccurrence != null) {
addDiagnostic(TooManyArguments(externalArgument, function))
return
}
result[lastParameter] = ResolvedCallArgument.SimpleArgument(externalArgument)
}
fun processDefaultsAndRunChecks() {
for ((parameter, resolvedArgument) in result) {
if (!parameter.isVararg) {
if (resolvedArgument !is ResolvedCallArgument.SimpleArgument) {
error("Incorrect resolved argument for parameter $parameter :$resolvedArgument")
} else if (resolvedArgument.callArgument.isSpread) {
addDiagnostic(NonVarargSpread(resolvedArgument.callArgument))
}
}
}
for (parameter in parameters) {
if (!result.containsKey(parameter)) {
if (parameter.defaultValue != null) {
result[parameter] = ResolvedCallArgument.DefaultArgument
} else if (parameter.isVararg) {
result[parameter] = ResolvedCallArgument.VarargArgument(emptyList())
} else {
addDiagnostic(NoValueForParameter(parameter, function))
}
}
}
}
private fun completeVarargPositionArguments() {
assert(state == State.VARARG_POSITION) { "Incorrect state: $state" }
val parameter = parameters[currentPositionedParameterIndex]
result.put(parameter, ResolvedCallArgument.VarargArgument(varargArguments!!))
}
private fun addVarargArgument(argument: FirExpression) {
if (varargArguments == null) {
varargArguments = ArrayList()
}
varargArguments!!.add(argument)
}
private fun getParameterByName(name: Name): FirValueParameter? {
if (nameToParameter == null) {
nameToParameter = parameters.associateBy { it.name }
}
return nameToParameter!![name]
}
private fun findParameterByName(argument: FirExpression, name: Name): FirValueParameter? {
val parameter = getParameterByName(name)
// TODO
// if (descriptor is CallableMemberDescriptor && descriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
// if (parameter == null) {
// for (valueParameter in descriptor.valueParameters) {
// val matchedParameter = valueParameter.overriddenDescriptors.firstOrNull {
// it.containingDeclaration.hasStableParameterNames() && it.name == name
// }
// if (matchedParameter != null) {
// addDiagnostic(NamedArgumentReference(argument, valueParameter))
// addDiagnostic(NameForAmbiguousParameter(argument, valueParameter, matchedParameter))
// return valueParameter
// }
// }
// } else {
// parameter.getOverriddenParameterWithOtherName()?.let {
// addDiagnostic(NameForAmbiguousParameter(argument, parameter, it))
// }
// }
// }
//
if (parameter == null) addDiagnostic(NameNotFound(argument, function))
return parameter
}
private fun addDiagnostic(diagnostic: ResolutionDiagnostic) {
if (diagnostics == null) {
diagnostics = mutableListOf()
}
diagnostics!!.add(diagnostic)
}
private val FirExpression.isSpread: Boolean
get() = this is FirSpreadArgumentExpression && isSpread
private val parameters: List<FirValueParameter>
get() = function.valueParameters
private val FirExpression.argumentName: Name?
get() = (this as? FirNamedArgumentExpression)?.name
// TODO: handle java functions
private val FirFunction<*>.hasStableParameterNames: Boolean
get() = true
}
@@ -1,119 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.fir.declarations.FirFunction
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirLambdaArgumentExpression
import org.jetbrains.kotlin.fir.expressions.FirNamedArgumentExpression
import org.jetbrains.kotlin.fir.expressions.FirWrappedArgumentExpression
import org.jetbrains.kotlin.fir.render
class FirCallArgumentsProcessor(
private val function: FirFunction<*>,
private val arguments: List<FirExpression>
) {
class Result(val argumentMapping: Map<FirExpression, FirValueParameter>, val isSuccess: Boolean)
fun process(): Result {
var currentState: State = State.PositionalOnly(function.valueParameters)
for (argument in arguments) {
if (argument is FirNamedArgumentExpression || argument is FirLambdaArgumentExpression) {
currentState = State.PositionalThenNamed(
function.valueParameters,
currentState.argumentMap,
currentState.usedParameters
)
}
val status = currentState.processArgument(argument)
if (status != MappingStatus.SUCCESS) {
// unmapped argument
return Result(currentState.argumentMap, isSuccess = false)
}
}
for (valueParameter in function.valueParameters) {
if (valueParameter !in currentState.usedParameters && !valueParameter.isVararg && valueParameter.defaultValue == null) {
// unmapped parameter
return Result(currentState.argumentMap, isSuccess = false)
}
}
return Result(currentState.argumentMap, isSuccess = currentState.argumentMap.size == arguments.size)
}
private enum class MappingStatus {
SUCCESS,
ERROR
}
private sealed class State(
val valueParameters: List<FirValueParameter>,
val argumentMap: MutableMap<FirExpression, FirValueParameter> = mutableMapOf(),
val usedParameters: MutableSet<FirValueParameter> = mutableSetOf()
) {
abstract fun processArgument(argument: FirExpression): MappingStatus
class PositionalOnly(valueParameters: List<FirValueParameter>) : State(valueParameters) {
var currentParameterIndex: Int = 0
val currentParameter get() = valueParameters.getOrNull(currentParameterIndex)
override fun processArgument(argument: FirExpression): MappingStatus {
require(argument !is FirNamedArgumentExpression) {
"Positional-only argument processor state should not receive ${argument.render()}"
}
val currentParameter = currentParameter ?: return MappingStatus.ERROR
argumentMap[argument] = currentParameter
val isSpread = argument is FirWrappedArgumentExpression && argument.isSpread
if (!currentParameter.isVararg || isSpread) {
usedParameters += currentParameter
currentParameterIndex++
}
if (!currentParameter.isVararg && isSpread) {
return MappingStatus.ERROR
}
return MappingStatus.SUCCESS
}
}
class PositionalThenNamed(
valueParameters: List<FirValueParameter>,
argumentMap: MutableMap<FirExpression, FirValueParameter>,
usedParameters: MutableSet<FirValueParameter>
) : State(valueParameters, argumentMap, usedParameters) {
val nameToParameter = valueParameters.associateBy { it.name }
private fun map(parameter: FirValueParameter, argument: FirExpression): MappingStatus {
if (parameter in usedParameters) return MappingStatus.ERROR
argumentMap[argument] = parameter
usedParameters += parameter
return MappingStatus.SUCCESS
}
override fun processArgument(argument: FirExpression): MappingStatus {
when (argument) {
is FirNamedArgumentExpression -> {
val name = argument.name
val parameter = nameToParameter[name] ?: return MappingStatus.ERROR
return map(parameter, argument)
}
is FirLambdaArgumentExpression -> {
val lastParameter = valueParameters.lastOrNull() ?: return MappingStatus.ERROR
return map(lastParameter, argument)
}
else -> {
return MappingStatus.ERROR
}
}
}
}
}
}
@@ -0,0 +1,51 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.fir.declarations.FirFunction
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability
abstract class ResolutionDiagnostic(val applicability: CandidateApplicability)
abstract class InapplicableArgumentDiagnostic : ResolutionDiagnostic(CandidateApplicability.INAPPLICABLE) {
abstract val argument: FirExpression
}
class MixingNamedAndPositionArguments(override val argument: FirExpression) : InapplicableArgumentDiagnostic()
class TooManyArguments(
val argument: FirExpression,
val function: FirFunction<*>
) : ResolutionDiagnostic(CandidateApplicability.PARAMETER_MAPPING_ERROR)
class NamedArgumentNotAllowed(
override val argument: FirExpression,
val function: FirFunction<*>
) : InapplicableArgumentDiagnostic()
class ArgumentPassedTwice(
override val argument: FirExpression,
val valueParameter: FirValueParameter,
val firstOccurrence: ResolvedCallArgument
) : InapplicableArgumentDiagnostic()
class VarargArgumentOutsideParentheses(
override val argument: FirExpression,
val valueParameter: FirValueParameter
) : InapplicableArgumentDiagnostic()
class NonVarargSpread(override val argument: FirExpression) : InapplicableArgumentDiagnostic()
class NoValueForParameter(
val valueParameter: FirValueParameter,
val function: FirFunction<*>
) : ResolutionDiagnostic(CandidateApplicability.PARAMETER_MAPPING_ERROR)
class NameNotFound(
override val argument: FirExpression,
val function: FirFunction<*>
) : InapplicableArgumentDiagnostic()
@@ -0,0 +1,26 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.fir.expressions.FirExpression
sealed class ResolvedCallArgument {
abstract val arguments: List<FirExpression>
object DefaultArgument : ResolvedCallArgument() {
override val arguments: List<FirExpression>
get() = emptyList()
}
class SimpleArgument(val callArgument: FirExpression) : ResolvedCallArgument() {
override val arguments: List<FirExpression>
get() = listOf(callArgument)
}
class VarargArgument(override val arguments: List<FirExpression>) : ResolvedCallArgument()
}
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation
import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.*
import org.jetbrains.kotlin.utils.addToStdlib.min
abstract class ResolutionStage {
@@ -154,11 +155,26 @@ internal object MapArguments : ResolutionStage() {
override suspend fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) {
val symbol = candidate.symbol as? FirFunctionSymbol<*> ?: return sink.reportApplicability(CandidateApplicability.HIDDEN)
val function = symbol.fir
val processor = FirCallArgumentsProcessor(function, callInfo.arguments)
val mappingResult = processor.process()
candidate.argumentMapping = mappingResult.argumentMapping
if (!mappingResult.isSuccess) {
return sink.yieldApplicability(CandidateApplicability.PARAMETER_MAPPING_ERROR)
val mapping = mapArguments(callInfo.arguments, function)
val argumentToParameterMapping = mutableMapOf<FirExpression, FirValueParameter>()
mapping.parameterToCallArgumentMap.forEach { (valueParameter, resolvedArgument) ->
when (resolvedArgument) {
is ResolvedCallArgument.SimpleArgument -> argumentToParameterMapping[resolvedArgument.callArgument] = valueParameter
is ResolvedCallArgument.VarargArgument -> resolvedArgument.arguments.forEach {
argumentToParameterMapping[it] = valueParameter
}
}
}
candidate.argumentMapping = argumentToParameterMapping
var applicability = CandidateApplicability.RESOLVED
mapping.diagnostics.forEach {
candidate.diagnostics += it
applicability = min(applicability, it.applicability)
}
if (applicability < CandidateApplicability.RESOLVED) {
return sink.yieldApplicability(applicability)
}
}
}
@@ -4,24 +4,30 @@ fun baz(f: () -> Unit, other: Boolean = true) {}
fun test() {
// OK
foo {}
foo() {}
foo({})
// Bad
<!INAPPLICABLE_CANDIDATE!>foo<!>(1) {}
<!INAPPLICABLE_CANDIDATE!>foo<!>(f = {}) {}
// OK
bar(1) {}
bar(x = 1) {}
bar(1, {})
bar(x = 1, f = {})
// Bad
<!INAPPLICABLE_CANDIDATE!>bar<!> {}
<!INAPPLICABLE_CANDIDATE!>bar<!>({})
// OK
baz(other = false, f = {})
baz({}, false)
// Bad
<!INAPPLICABLE_CANDIDATE!>baz<!> {}
<!INAPPLICABLE_CANDIDATE!>baz<!>() {}
<!INAPPLICABLE_CANDIDATE!>baz<!>(other = false) {}
+1 -1
View File
@@ -9,7 +9,7 @@ fun test() {
<!INAPPLICABLE_CANDIDATE!>foo<!>()
<!INAPPLICABLE_CANDIDATE!>foo<!>(0.0, false, 0, "")
<!INAPPLICABLE_CANDIDATE!>foo<!>(1, 2.0, third = true, "")
foo(1, 2.0, third = true, "")
<!INAPPLICABLE_CANDIDATE!>foo<!>(second = 0.0, first = 0, fourth = "")
<!INAPPLICABLE_CANDIDATE!>foo<!>(first = 0.0, second = 0, third = "", fourth = false)
<!INAPPLICABLE_CANDIDATE!>foo<!>(first = 0, second = 0.0, third = false, fourth = "", first = 1)
+2 -2
View File
@@ -9,9 +9,9 @@ FILE: simple.kt
R|/foo|(third = Boolean(false), second = Double(2.71), fourth = String(?!), first = Int(0))
<Inapplicable(PARAMETER_MAPPING_ERROR): [/foo]>#()
<Inapplicable(INAPPLICABLE): [/foo]>#(Double(0.0), Boolean(false), Int(0), String())
<Inapplicable(PARAMETER_MAPPING_ERROR): [/foo]>#(Int(1), Double(2.0), third = Boolean(true), String())
R|/foo|(Int(1), Double(2.0), third = Boolean(true), String())
<Inapplicable(PARAMETER_MAPPING_ERROR): [/foo]>#(second = Double(0.0), first = Int(0), fourth = String())
<Inapplicable(INAPPLICABLE): [/foo]>#(first = Double(0.0), second = Int(0), third = String(), fourth = Boolean(false))
<Inapplicable(PARAMETER_MAPPING_ERROR): [/foo]>#(first = Int(0), second = Double(0.0), third = Boolean(false), fourth = String(), first = Int(1))
<Inapplicable(INAPPLICABLE): [/foo]>#(first = Int(0), second = Double(0.0), third = Boolean(false), fourth = String(), first = Int(1))
<Inapplicable(PARAMETER_MAPPING_ERROR): [/foo]>#(Int(0), Double(0.0), Boolean(false), foth = String())
}
+1 -1
View File
@@ -11,6 +11,6 @@ FILE: vararg.kt
<Inapplicable(INAPPLICABLE): [/foo]>#(String())
<Inapplicable(INAPPLICABLE): [/foo]>#(Int(1), Int(2))
R|/bar|(Int(1), z = Boolean(true), vararg(y = *R|kotlin/arrayOf|<R|kotlin/String|>(vararg(String(my), String(yours)))))
<Inapplicable(PARAMETER_MAPPING_ERROR): [/bar]>#(Int(0), z = Boolean(false), y = String(), y = String(other))
<Inapplicable(INAPPLICABLE): [/bar]>#(Int(0), z = Boolean(false), y = String(), y = String(other))
<Inapplicable(PARAMETER_MAPPING_ERROR): [/bar]>#(Int(0), String(), Boolean(true))
}
@@ -1,5 +1,4 @@
// !LANGUAGE: +NewInference +MixedNamedArgumentsInTheirOwnPosition
// IGNORE_BACKEND_FIR: JVM_IR
fun foo(
p1: Int = 1,
@@ -1,5 +1,4 @@
// !LANGUAGE: +NewInference +MixedNamedArgumentsInTheirOwnPosition
// IGNORE_BACKEND_FIR: JVM_IR
fun foo(
p1: Int,
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun barB(vararg args: Byte) = args
fun barC(vararg args: Char) = args
fun barD(vararg args: Double) = args
@@ -1,4 +1,5 @@
// !LANGUAGE: -ProhibitAssigningSingleElementsToVarargsInNamedForm
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
if (test1(p = 1) != "1") return "fail 1"
+2 -2
View File
@@ -12,6 +12,6 @@ fun test() {
v1({}, {})
<!INAPPLICABLE_CANDIDATE!>v1<!>({}, 1, {})
v1({}, {}, {it})
v1({}) {}
v1 {}
<!INAPPLICABLE_CANDIDATE!>v1<!>({}) {}
<!INAPPLICABLE_CANDIDATE!>v1<!> {}
}
@@ -12,47 +12,47 @@ fun main() {
join(1, "2", "3")
<!INAPPLICABLE_CANDIDATE!>join<!>(*1, "2")
<!INAPPLICABLE_CANDIDATE!>join<!>(1, *"2")
join(x = 1, a = "2")
<!INAPPLICABLE_CANDIDATE!>join<!>(x = 1, a = "2")
<!INAPPLICABLE_CANDIDATE!>join<!>(x = *1, a = *"2")
<!INAPPLICABLE_CANDIDATE!>join<!>(x = 1, a = a)
join(x = 1, a = a)
<!INAPPLICABLE_CANDIDATE!>join<!>(x = 1, a = b)
join(1, *a)
<!INAPPLICABLE_CANDIDATE!>join<!>(1, *b)
<!INAPPLICABLE_CANDIDATE!>join<!>(1, *a, "3")
join(1, *a, "3")
<!INAPPLICABLE_CANDIDATE!>join<!>(1, *b, "3")
<!INAPPLICABLE_CANDIDATE!>join<!>(1, "4", *a, "3")
join(1, "4", *a, "3")
<!INAPPLICABLE_CANDIDATE!>join<!>(1, "4", *b, "3")
join(1, "4", *a)
<!INAPPLICABLE_CANDIDATE!>join<!>(1, "4", *a, *a, "3")
join(1, "4", *a, *a, "3")
<!INAPPLICABLE_CANDIDATE!>join<!>(1, "4", *a, *b, "3")
<!INAPPLICABLE_CANDIDATE!>join<!>(a = a, x = 1)
join(a = a, x = 1)
<!INAPPLICABLE_CANDIDATE!>join<!>(a = b, x = 1)
<!INAPPLICABLE_CANDIDATE!>join<!>(a = a, x = 1)
join(a = a, x = 1)
joinG<String>(1, "2")
<!INAPPLICABLE_CANDIDATE!>joinG<!><String>(*1, "2")
<!INAPPLICABLE_CANDIDATE!>joinG<!><String>(1, *"2")
<!INAPPLICABLE_CANDIDATE!>joinG<!><String>(x = 1, a = a)
joinG<String>(x = 1, a = "2")
joinG<String>(x = 1, a = a)
<!INAPPLICABLE_CANDIDATE!>joinG<!><String>(x = 1, a = "2")
<!INAPPLICABLE_CANDIDATE!>joinG<!><String>(x = *1, a = *"2")
joinG<String>(1, *a)
<!INAPPLICABLE_CANDIDATE!>joinG<!><String>(1, *a, "3")
<!INAPPLICABLE_CANDIDATE!>joinG<!><String>(1, "4", *a, "3")
joinG<String>(1, *a, "3")
joinG<String>(1, "4", *a, "3")
joinG<String>(1, "4", *a)
<!INAPPLICABLE_CANDIDATE!>joinG<!><String>(1, "4", *a, *a, "3")
<!INAPPLICABLE_CANDIDATE!>joinG<!><String>(a = a, x = 1)
joinG<String>(1, "4", *a, *a, "3")
joinG<String>(a = a, x = 1)
joinG(1, "2")
<!INAPPLICABLE_CANDIDATE!>joinG<!>(*1, "2")
<!INAPPLICABLE_CANDIDATE!>joinG<!>(1, *"2")
joinG(x = 1, a = a)
joinG(x = 1, a = "2")
<!INAPPLICABLE_CANDIDATE!>joinG<!>(x = 1, a = "2")
<!INAPPLICABLE_CANDIDATE!>joinG<!>(x = *1, a = *"2")
joinG(1, *a)
<!INAPPLICABLE_CANDIDATE!>joinG<!>(1, *a, "3")
<!INAPPLICABLE_CANDIDATE!>joinG<!>(1, "4", *a, "3")
joinG(1, *a, "3")
joinG(1, "4", *a, "3")
joinG(1, "4", *a)
<!INAPPLICABLE_CANDIDATE!>joinG<!>(1, "4", *a, *a, "3")
joinG(1, "4", *a, *a, "3")
joinG(a = a, x = 1)
val x1 = joinT(1, "2")
@@ -61,18 +61,18 @@ fun main() {
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><String?>(x2)
val x6 = joinT(1, *a)
checkSubtype<String?>(x6)
val x7 = <!INAPPLICABLE_CANDIDATE!>joinT<!>(1, *a, "3")
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><String?>(x7)
val x8 = <!INAPPLICABLE_CANDIDATE!>joinT<!>(1, "4", *a, "3")
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><String?>(x8)
val x7 = joinT(1, *a, "3")
checkSubtype<String?>(x7)
val x8 = joinT(1, "4", *a, "3")
checkSubtype<String?>(x8)
val x9 = joinT(1, "4", *a)
checkSubtype<String?>(x9)
val x10 = <!INAPPLICABLE_CANDIDATE!>joinT<!>(1, "4", *a, *a, "3")
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><String?>(x10)
val x10 = joinT(1, "4", *a, *a, "3")
checkSubtype<String?>(x10)
val x11 = joinT(a = a, x = 1)
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><String?>(x11)
checkSubtype<String?>(x11)
val x12 = joinT(x = 1, a = a)
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><String?>(x12)
checkSubtype<String?>(x12)
}
fun join(x : Int, vararg a : String) : String {
@@ -6,7 +6,7 @@ fun test(x: () -> Unit, y: () -> Unit) {
}
fun main() {
<!INAPPLICABLE_CANDIDATE!>test<!> {
test {
1
} {
2
@@ -5,7 +5,7 @@ import java.lang.invoke.MethodHandle
fun test(mh: MethodHandle) {
mh.invokeExact("1", "2")
mh.<!INAPPLICABLE_CANDIDATE!>invokeExact<!>(*emptyArray(), "X")
mh.<!INAPPLICABLE_CANDIDATE!>invokeExact<!>(*arrayOf("A", "B"), "C", *arrayOf("D", "E"))
mh.invokeExact(*emptyArray(), "X")
mh.invokeExact(*arrayOf("A", "B"), "C", *arrayOf("D", "E"))
mh.invoke(*arrayOf("A"))
}
@@ -5,7 +5,7 @@ import java.lang.invoke.MethodHandle
fun test(mh: MethodHandle) {
mh.invokeExact("1", "2")
mh.<!INAPPLICABLE_CANDIDATE!>invokeExact<!>(*emptyArray(), "X")
mh.<!INAPPLICABLE_CANDIDATE!>invokeExact<!>(*arrayOf("A", "B"), "C", *arrayOf("D", "E"))
mh.invokeExact(*emptyArray(), "X")
mh.invokeExact(*arrayOf("A", "B"), "C", *arrayOf("D", "E"))
mh.invoke(*arrayOf("A"))
}
@@ -10,14 +10,14 @@ fun foo(
) {}
fun main() {
<!INAPPLICABLE_CANDIDATE!>foo<!>(p1 = 1, "2", 3.0)
<!INAPPLICABLE_CANDIDATE!>foo<!>(1, p2 = "2", 3.0)
foo(p1 = 1, "2", 3.0)
foo(1, p2 = "2", 3.0)
foo(1, "2", p3 = 3.0)
foo(p1 = 1)
foo(1, p2 = "2")
<!INAPPLICABLE_CANDIDATE!>foo<!>(p1 = 1, p2 = "2", 3.0)
foo(p1 = 1, p2 = "2", 3.0)
foo()
foo(1, p2 = "")
@@ -9,11 +9,11 @@ fun foo(
) {}
fun main() {
<!INAPPLICABLE_CANDIDATE!>foo<!>(p1 = 1, "2", 3.0)
<!INAPPLICABLE_CANDIDATE!>foo<!>(1, p2 = "2", 3.0)
foo(p1 = 1, "2", 3.0)
foo(1, p2 = "2", 3.0)
foo(1, "2", p3 = 3.0)
<!INAPPLICABLE_CANDIDATE!>foo<!>(p1 = 1, p2 = "2", 3.0)
foo(p1 = 1, p2 = "2", 3.0)
<!INAPPLICABLE_CANDIDATE!>foo<!>(1, p3 = 2.0, "")
<!INAPPLICABLE_CANDIDATE!>foo<!>(1, p3 = 2.0, 3.0)
@@ -9,11 +9,11 @@ fun foo(
) {}
fun main() {
<!INAPPLICABLE_CANDIDATE!>foo<!>(p1 = 1, "2", 3.0)
<!INAPPLICABLE_CANDIDATE!>foo<!>(1, p2 = "2", 3.0)
foo(p1 = 1, "2", 3.0)
foo(1, p2 = "2", 3.0)
foo(1, "2", p3 = 3.0)
<!INAPPLICABLE_CANDIDATE!>foo<!>(p1 = 1, p2 = "2", 3.0)
foo(p1 = 1, p2 = "2", 3.0)
<!INAPPLICABLE_CANDIDATE!>foo<!>(1, p3 = 2.0, "")
<!INAPPLICABLE_CANDIDATE!>foo<!>(1, p3 = 2.0, 3.0)
@@ -9,11 +9,11 @@ fun foo(
) {}
fun main() {
<!INAPPLICABLE_CANDIDATE!>foo<!>(p1 = 1, "2", 3.0)
<!INAPPLICABLE_CANDIDATE!>foo<!>(1, p2 = "2", 3.0)
foo(p1 = 1, "2", 3.0)
foo(1, p2 = "2", 3.0)
foo(1, "2", p3 = 3.0)
<!INAPPLICABLE_CANDIDATE!>foo<!>(p1 = 1, p2 = "2", 3.0)
foo(p1 = 1, p2 = "2", 3.0)
<!INAPPLICABLE_CANDIDATE!>foo<!>(1, p3 = 2.0, "")
<!INAPPLICABLE_CANDIDATE!>foo<!>(1, p3 = 2.0, 3.0)
@@ -29,16 +29,16 @@ fun foo4(
fun main() {
<!INAPPLICABLE_CANDIDATE!>foo1<!>(1, 2, p2 = "3", 4.0)
<!INAPPLICABLE_CANDIDATE!>foo1<!>(p1 = intArrayOf(1, 2), "3", p3 = 4.0)
foo1(p1 = intArrayOf(1, 2), "3", p3 = 4.0)
<!INAPPLICABLE_CANDIDATE!>foo1<!>(p2 = "3", 4.0)
<!INAPPLICABLE_CANDIDATE!>foo2<!>(p1 = 1, "2", "3", p3 = 4.0)
<!INAPPLICABLE_CANDIDATE!>foo2<!>(1, p2 = arrayOf("2", "3"), 4.0)
foo2(p1 = 1, "2", "3", p3 = 4.0)
foo2(1, p2 = arrayOf("2", "3"), 4.0)
foo2(1, p3 = 3.0)
<!INAPPLICABLE_CANDIDATE!>foo3<!>(p1 = 1, "2", 3.0, 4.0)
<!INAPPLICABLE_CANDIDATE!>foo3<!>(p1 = 1, "2", p3 = doubleArrayOf(3.0, 4.0))
foo3(p1 = 1, "2", 3.0, 4.0)
foo3(p1 = 1, "2", p3 = doubleArrayOf(3.0, 4.0))
<!INAPPLICABLE_CANDIDATE!>foo4<!>(p1 = 1, "2", "3", p3 = 4.0, 5)
<!INAPPLICABLE_CANDIDATE!>foo4<!>(1, "2", "3", p3 = 4.0, 5)
@@ -50,8 +50,8 @@ fun main() {
<!INAPPLICABLE_CANDIDATE!>foo2<!>(1, p3 = 2.0, "4")
<!INAPPLICABLE_CANDIDATE!>foo2<!>(1, p3 = 2.0, *arrayOf("3", "4"))
<!INAPPLICABLE_CANDIDATE!>foo2<!>(1, p3 = 2.0, p2 = arrayOf("3", "4"))
foo2(1, p3 = 2.0, p2 = arrayOf("3", "4"))
<!INAPPLICABLE_CANDIDATE!>foo3<!>(1, p3 = doubleArrayOf(2.0, 3.0), "4")
<!INAPPLICABLE_CANDIDATE!>foo3<!>(1, p3 = doubleArrayOf(2.0, 3.0), p2 = "4")
foo3(1, p3 = doubleArrayOf(2.0, 3.0), p2 = "4")
}
@@ -96,7 +96,7 @@ fun testTwoLambdas() {
)
fun bar(): () -> Unit {
<!INAPPLICABLE_CANDIDATE!>twoLambdaArgs<!>()
twoLambdaArgs()
{}
{}
@@ -8,6 +8,6 @@ fun overloadedFun(arg: String, vararg args: String) = X1
fun overloadedFun(arg: String, vararg args: String, flag: Boolean = true) = X2
val test1a: X1 = overloadedFun("", "")
val test1b: X1 = overloadedFun("", args = "")
val test1b: X1 = <!INAPPLICABLE_CANDIDATE!>overloadedFun<!>("", args = "")
val test1c: X2 = overloadedFun("", "", "", flag = true)
@@ -9,5 +9,5 @@ fun overloadedFun5(s: String, vararg ss: String) = X2
val test1 = overloadedFun5("")
val test2 = overloadedFun5("", "")
val test3: X2 = overloadedFun5(s = "", ss = "")
val test4: X1 = overloadedFun5(ss = "")
val test3: X2 = <!INAPPLICABLE_CANDIDATE!>overloadedFun5<!>(s = "", ss = "")
val test4: X1 = <!INAPPLICABLE_CANDIDATE!>overloadedFun5<!>(ss = "")
@@ -2,7 +2,7 @@
fun <T> array(vararg x: T): Array<T> = null!!
open class B(vararg y: String) {
constructor(x: Int): <!INAPPLICABLE_CANDIDATE!>this<!>(x.toString(), *array("1"), "2")
constructor(x: Int): this(x.toString(), *array("1"), "2")
}
class A : B {
@@ -13,5 +13,5 @@ class A : B {
val b1 = B()
val b2 = B("1", "2", "3")
val b3 = <!INAPPLICABLE_CANDIDATE!>B<!>("1", *array("2", "3"), "4")
val b3 = B("1", *array("2", "3"), "4")
val b4 = B(1)
@@ -12,11 +12,11 @@ fun foo() {}
fun test_fun(s: String, arr: Array<String>) {
<!INAPPLICABLE_CANDIDATE!>withVararg<!>(arr) // Error
withVararg(*arr) // OK
<!INAPPLICABLE_CANDIDATE!>withVararg<!>(s = arr) // Error
withVararg(s = arr) // Error
withVararg(s = *arr) // OK
withVararg(s) // OK
withVararg(s = s) // Error
<!INAPPLICABLE_CANDIDATE!>withVararg<!>(s = s) // Error
}
fun test_ann(s: String, arr: Array<String>) {
@@ -12,11 +12,11 @@ fun foo() {}
fun test_fun(s: String, arr: Array<String>) {
<!INAPPLICABLE_CANDIDATE!>withVararg<!>(arr) // Error
withVararg(*arr) // OK
<!INAPPLICABLE_CANDIDATE!>withVararg<!>(s = arr) // OK
withVararg(s = arr) // OK
withVararg(s = *arr) // Warning
withVararg(s) // OK
withVararg(s = s) // Error
<!INAPPLICABLE_CANDIDATE!>withVararg<!>(s = s) // Error
}
fun test_ann(s: String, arr: Array<String>) {
@@ -7,27 +7,27 @@ fun foo(vararg s: Int) {}
open class Cls(vararg p: Long)
fun test(i: IntArray) {
foo(s = 1)
<!INAPPLICABLE_CANDIDATE!>foo<!>(s = i)
<!INAPPLICABLE_CANDIDATE!>foo<!>(s = 1)
foo(s = i)
foo(s = *i)
<!INAPPLICABLE_CANDIDATE!>foo<!>(s = intArrayOf(1))
foo(s = intArrayOf(1))
foo(s = *intArrayOf(1))
foo(1)
Cls(p = 1)
<!INAPPLICABLE_CANDIDATE!>Cls<!>(p = 1)
class Sub : Cls(p = 1)
class Sub : <!INAPPLICABLE_CANDIDATE!>Cls<!>(p = 1)
val c = object : Cls(p = 1) {}
val c = object : <!INAPPLICABLE_CANDIDATE!>Cls<!>(p = 1) {}
foo(s = *intArrayOf(elements = 1))
foo(s = *<!INAPPLICABLE_CANDIDATE!>intArrayOf<!>(elements = 1))
}
fun anyFoo(vararg a: Any) {}
fun testAny() {
anyFoo(a = "")
<!INAPPLICABLE_CANDIDATE!>anyFoo<!>(a = "")
anyFoo(a = arrayOf(""))
anyFoo(a = *arrayOf(""))
}
@@ -35,12 +35,12 @@ fun testAny() {
fun <T> genFoo(vararg t: T) {}
fun testGen() {
genFoo<Int>(t = 1)
genFoo<Int?>(t = null)
<!INAPPLICABLE_CANDIDATE!>genFoo<!><Int>(t = 1)
<!INAPPLICABLE_CANDIDATE!>genFoo<!><Int?>(t = null)
genFoo<Array<Int>>(t = arrayOf())
genFoo<Array<Int>>(t = *arrayOf(arrayOf()))
genFoo(t = "")
<!INAPPLICABLE_CANDIDATE!>genFoo<!>(t = "")
genFoo(t = arrayOf(""))
genFoo(t = *arrayOf(""))
}
@@ -49,12 +49,12 @@ fun manyFoo(vararg v: Int) {}
fun manyFoo(vararg s: String) {}
fun testMany(a: Any) {
manyFoo(v = 1)
manyFoo(s = "")
<!INAPPLICABLE_CANDIDATE!>manyFoo<!>(v = 1)
<!INAPPLICABLE_CANDIDATE!>manyFoo<!>(s = "")
<!INAPPLICABLE_CANDIDATE!>manyFoo<!>(a)
<!INAPPLICABLE_CANDIDATE!>manyFoo<!>(v = a)
<!INAPPLICABLE_CANDIDATE!>manyFoo<!>(s = a)
manyFoo(v = a as Int)
manyFoo(s = a as String)
<!INAPPLICABLE_CANDIDATE!>manyFoo<!>(v = a as Int)
<!INAPPLICABLE_CANDIDATE!>manyFoo<!>(s = a as String)
}
@@ -7,27 +7,27 @@ fun foo(vararg s: Int) {}
open class Cls(vararg p: Long)
fun test(i: IntArray) {
foo(s = 1)
<!INAPPLICABLE_CANDIDATE!>foo<!>(s = i)
<!INAPPLICABLE_CANDIDATE!>foo<!>(s = 1)
foo(s = i)
foo(s = *i)
<!INAPPLICABLE_CANDIDATE!>foo<!>(s = intArrayOf(1))
foo(s = intArrayOf(1))
foo(s = *intArrayOf(1))
foo(1)
Cls(p = 1)
<!INAPPLICABLE_CANDIDATE!>Cls<!>(p = 1)
class Sub : Cls(p = 1)
class Sub : <!INAPPLICABLE_CANDIDATE!>Cls<!>(p = 1)
val c = object : Cls(p = 1) {}
val c = object : <!INAPPLICABLE_CANDIDATE!>Cls<!>(p = 1) {}
foo(s = *intArrayOf(elements = 1))
foo(s = *<!INAPPLICABLE_CANDIDATE!>intArrayOf<!>(elements = 1))
}
fun anyFoo(vararg a: Any) {}
fun testAny() {
anyFoo(a = "")
<!INAPPLICABLE_CANDIDATE!>anyFoo<!>(a = "")
anyFoo(a = arrayOf(""))
anyFoo(a = *arrayOf(""))
}
@@ -35,12 +35,12 @@ fun testAny() {
fun <T> genFoo(vararg t: T) {}
fun testGen() {
genFoo<Int>(t = 1)
genFoo<Int?>(t = null)
<!INAPPLICABLE_CANDIDATE!>genFoo<!><Int>(t = 1)
<!INAPPLICABLE_CANDIDATE!>genFoo<!><Int?>(t = null)
genFoo<Array<Int>>(t = arrayOf())
genFoo<Array<Int>>(t = *arrayOf(arrayOf()))
genFoo(t = "")
<!INAPPLICABLE_CANDIDATE!>genFoo<!>(t = "")
genFoo(t = arrayOf(""))
genFoo(t = *arrayOf(""))
}
@@ -49,12 +49,12 @@ fun manyFoo(vararg v: Int) {}
fun manyFoo(vararg s: String) {}
fun testMany(a: Any) {
manyFoo(v = 1)
manyFoo(s = "")
<!INAPPLICABLE_CANDIDATE!>manyFoo<!>(v = 1)
<!INAPPLICABLE_CANDIDATE!>manyFoo<!>(s = "")
<!INAPPLICABLE_CANDIDATE!>manyFoo<!>(a)
<!INAPPLICABLE_CANDIDATE!>manyFoo<!>(v = a)
<!INAPPLICABLE_CANDIDATE!>manyFoo<!>(s = a)
manyFoo(v = a as Int)
manyFoo(s = a as String)
<!INAPPLICABLE_CANDIDATE!>manyFoo<!>(v = a as Int)
<!INAPPLICABLE_CANDIDATE!>manyFoo<!>(s = a as String)
}
@@ -45,5 +45,5 @@ fun foo(vararg i: Int) {}
@Ann(s = "value")
fun dep1() {
foo(i = 1)
<!INAPPLICABLE_CANDIDATE!>foo<!>(i = 1)
}
@@ -15,6 +15,6 @@ fun f2() {}
fun foo(vararg ints: Int) {}
fun test() {
foo(ints = 1)
<!INAPPLICABLE_CANDIDATE!>foo<!>(ints = 1)
foo(ints = *intArrayOf(1))
}
+13 -9
View File
@@ -24,15 +24,19 @@ FILE fqName:<root> fileName:/vararg.kt
RETURN type=kotlin.Nothing from='public final fun <get-test2> (): kotlin.Array<kotlin.String> declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test2 type:kotlin.Array<kotlin.String> visibility:private [final,static]' type=kotlin.Array<kotlin.String> origin=null
PROPERTY name:test3 visibility:public modality:FINAL [val]
FIELD PROPERTY_BACKING_FIELD name:test3 type:IrErrorType visibility:private [final,static]
FIELD PROPERTY_BACKING_FIELD name:test3 type:kotlin.Array<kotlin.String> visibility:private [final,static]
EXPRESSION_BODY
ERROR_CALL 'Unresolved reference: <Inapplicable(PARAMETER_MAPPING_ERROR): [kotlin/arrayOf]>#' type=IrErrorType
CONST String type=kotlin.String value="0"
CALL 'public final fun <get-test2> (): kotlin.Array<kotlin.String> declared in <root>' type=kotlin.Array<kotlin.String> origin=null
CALL 'public final fun <get-test1> (): kotlin.Array<kotlin.String> declared in <root>' type=kotlin.Array<kotlin.String> origin=null
CONST String type=kotlin.String value="4"
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test3> visibility:public modality:FINAL <> () returnType:IrErrorType
CALL 'public final fun arrayOf <T> (vararg elements: T of kotlin.arrayOf): kotlin.Array<T of kotlin.arrayOf> [inline] declared in kotlin' type=kotlin.Array<kotlin.String> origin=null
<T>: kotlin.String
elements: VARARG type=kotlin.Array<out kotlin.String> varargElementType=kotlin.String
CONST String type=kotlin.String value="0"
SPREAD_ELEMENT
CALL 'public final fun <get-test2> (): kotlin.Array<kotlin.String> declared in <root>' type=kotlin.Array<kotlin.String> origin=null
SPREAD_ELEMENT
CALL 'public final fun <get-test1> (): kotlin.Array<kotlin.String> declared in <root>' type=kotlin.Array<kotlin.String> origin=null
CONST String type=kotlin.String value="4"
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test3> visibility:public modality:FINAL <> () returnType:kotlin.Array<kotlin.String>
correspondingProperty: PROPERTY name:test3 visibility:public modality:FINAL [val]
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-test3> (): IrErrorType declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test3 type:IrErrorType visibility:private [final,static]' type=IrErrorType origin=null
RETURN type=kotlin.Nothing from='public final fun <get-test3> (): kotlin.Array<kotlin.String> declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test3 type:kotlin.Array<kotlin.String> visibility:private [final,static]' type=kotlin.Array<kotlin.String> origin=null
@@ -146,3 +146,6 @@ inline fun <T, R, C : MutableCollection<in R>> Iterable<T>.flatMapToNullable(des
}
return destination
}
fun <E : Enum<E>> min(a: E, b: E): E = if (a < b) a else b
fun <E : Comparable<E>> min(a: E, b: E): E = if (a < b) a else b
@@ -1,3 +1,5 @@
// IGNORE_FIR
class Foo {
fun invoke(vararg a: Any) {}
}
@@ -1,3 +1,5 @@
// IGNORE_FIR
class Foo {
fun invoke(vararg a: Any) {}
}
@@ -1,3 +1,5 @@
// IGNORE_FIR
class Foo {
fun invoke(vararg a: Any) {}
}
@@ -1,3 +1,5 @@
// IGNORE_FIR
class Foo {
fun invoke(vararg a: Any) {}
}
@@ -1,3 +1,5 @@
// IGNORE_FIR
class Foo {
fun invoke(vararg a: Any) {}
}