Generalize signature comparison: checking for conflicting overloads.
Also, vararg parameter no longer conflicts with Array<out T> (CONFLICTING_JVM_DECLARATIONS is reported, can be avoided using @JvmName).
This commit is contained in:
@@ -21,15 +21,14 @@ import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.INCOMPATIBLE
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.CallHandle
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilderImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.VALUE_PARAMETER_POSITION
|
||||
import org.jetbrains.kotlin.resolve.calls.results.FlatSignature
|
||||
import org.jetbrains.kotlin.resolve.calls.results.SpecificityComparisonCallbacks
|
||||
import org.jetbrains.kotlin.resolve.calls.results.isSignatureNotLessSpecific
|
||||
import org.jetbrains.kotlin.resolve.calls.results.varargParameterPosition
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasLowPriorityInOverloadResolution
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.utils.singletonOrEmptyList
|
||||
|
||||
object OverloadUtil {
|
||||
@@ -46,52 +45,29 @@ object OverloadUtil {
|
||||
return checkOverloadability(a, b)
|
||||
}
|
||||
|
||||
private object OverloadabilitySpecificityCallbacks : SpecificityComparisonCallbacks {
|
||||
override fun isNonSubtypeNotLessSpecific(specific: KotlinType, general: KotlinType): Boolean =
|
||||
false
|
||||
}
|
||||
|
||||
private fun checkOverloadability(a: CallableDescriptor, b: CallableDescriptor): Boolean {
|
||||
if (a.hasLowPriorityInOverloadResolution() != b.hasLowPriorityInOverloadResolution()) return true
|
||||
|
||||
// NB this makes generic and non-generic declarations with equivalent signatures non-conflicting
|
||||
// E.g., 'fun <T> foo()' and 'fun foo()'.
|
||||
// They can be disambiguated by providing explicit type parameters.
|
||||
if (a.typeParameters.isEmpty() != b.typeParameters.isEmpty()) return true
|
||||
|
||||
OverridingUtil.checkReceiverAndParameterCount(a, b)?.let { return it.result == INCOMPATIBLE }
|
||||
if (ErrorUtils.containsErrorType(a) || ErrorUtils.containsErrorType(b)) return true
|
||||
if (a.varargParameterPosition() != b.varargParameterPosition()) return true
|
||||
|
||||
val aValueParameters = OverridingUtil.compiledValueParameters(a)
|
||||
val bValueParameters = OverridingUtil.compiledValueParameters(b)
|
||||
val aSignature = FlatSignature.createFromCallableDescriptor(a)
|
||||
val bSignature = FlatSignature.createFromCallableDescriptor(b)
|
||||
|
||||
val aTypeParameters = a.typeParameters
|
||||
val bTypeParameters = b.typeParameters
|
||||
val aIsNotLessSpecificThanB = isSignatureNotLessSpecific(aSignature, bSignature, OverloadabilitySpecificityCallbacks)
|
||||
val bIsNotLessSpecificThanA = isSignatureNotLessSpecific(bSignature, aSignature, OverloadabilitySpecificityCallbacks)
|
||||
|
||||
val avsbConstraintsBuilder: ConstraintSystem.Builder = ConstraintSystemBuilderImpl()
|
||||
val avsbTypeSubstitutor = avsbConstraintsBuilder.registerTypeVariables(CallHandle.NONE, aTypeParameters)
|
||||
val bvsaConstraintsBuilder: ConstraintSystem.Builder = ConstraintSystemBuilderImpl()
|
||||
val bvsaTypeSubstitutor = bvsaConstraintsBuilder.registerTypeVariables(CallHandle.NONE, bTypeParameters)
|
||||
|
||||
var constraintIndex = 0
|
||||
|
||||
for ((aType, bType) in aValueParameters.zip(bValueParameters)) {
|
||||
if (aType.isError || bType.isError) return true
|
||||
|
||||
if (oneMoreSpecificThanAnother(bType, aType)) return true
|
||||
|
||||
if (!TypeUtils.dependsOnTypeParameters(aType, aTypeParameters)
|
||||
&& !TypeUtils.dependsOnTypeParameters(bType, bTypeParameters)
|
||||
&& !KotlinTypeChecker.DEFAULT.equalTypes(aType, bType)) {
|
||||
return true
|
||||
}
|
||||
|
||||
constraintIndex++
|
||||
val aTypeSubstituted = avsbTypeSubstitutor.safeSubstitute(aType, Variance.INVARIANT)
|
||||
val bTypeSubstituted = bvsaTypeSubstitutor.safeSubstitute(bType, Variance.INVARIANT)
|
||||
avsbConstraintsBuilder.addSubtypeConstraint(bType, aTypeSubstituted,
|
||||
VALUE_PARAMETER_POSITION.position(constraintIndex))
|
||||
bvsaConstraintsBuilder.addSubtypeConstraint(aType, bTypeSubstituted,
|
||||
VALUE_PARAMETER_POSITION.position(constraintIndex))
|
||||
}
|
||||
|
||||
if (constraintIndex == 0) return false
|
||||
|
||||
avsbConstraintsBuilder.fixVariables()
|
||||
bvsaConstraintsBuilder.fixVariables()
|
||||
|
||||
return avsbConstraintsBuilder.build().status.hasContradiction()
|
||||
|| bvsaConstraintsBuilder.build().status.hasContradiction()
|
||||
return !(aIsNotLessSpecificThanB && bIsNotLessSpecificThanA)
|
||||
}
|
||||
|
||||
private enum class DeclarationCategory {
|
||||
|
||||
@@ -30,49 +30,50 @@ class FlatSignature<out T>(
|
||||
val origin: T,
|
||||
val typeParameters: Collection<TypeParameterDescriptor>,
|
||||
val valueParameterTypes: List<KotlinType?>,
|
||||
val hasExtensionReceiver: Boolean,
|
||||
val hasVarargs: Boolean,
|
||||
val numDefaults: Int
|
||||
) {
|
||||
val isGeneric = typeParameters.isNotEmpty()
|
||||
|
||||
companion object {
|
||||
fun <D : CallableDescriptor, RC : ResolvedCall<D>> createFromResolvedCall(call: RC): FlatSignature<RC> {
|
||||
val originalDescriptor = call.candidateDescriptor.original
|
||||
fun <D : CallableDescriptor, RC : ResolvedCall<D>> createFromResolvedCall(resolvedCall: RC): FlatSignature<RC> {
|
||||
val originalDescriptor = resolvedCall.candidateDescriptor.original
|
||||
val originalValueParameters = originalDescriptor.valueParameters
|
||||
val originalTypeParameters = originalDescriptor.typeParameters
|
||||
|
||||
var numDefaults = 0
|
||||
val valueArgumentToParameterType = HashMap<ValueArgument, KotlinType>()
|
||||
for ((valueParameter, resolvedValueArgument) in call.valueArguments.entries) {
|
||||
for ((valueParameter, resolvedValueArgument) in resolvedCall.valueArguments.entries) {
|
||||
if (resolvedValueArgument is DefaultValueArgument) {
|
||||
numDefaults++
|
||||
}
|
||||
else {
|
||||
val originalValueParameter = originalValueParameters[valueParameter.index]
|
||||
val parameterType = originalValueParameter.flatType
|
||||
val parameterType = originalValueParameter.argumentValueType
|
||||
for (valueArgument in resolvedValueArgument.arguments) {
|
||||
if (valueArgument.getArgumentExpression() == null) continue
|
||||
valueArgumentToParameterType[valueArgument] = parameterType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val valueArgumentParameterTypes = call.call.valueArguments.map { valueArgumentToParameterType[it] }
|
||||
val valueParameterTypes = originalDescriptor.extensionReceiverTypeOrEmpty() + valueArgumentParameterTypes
|
||||
|
||||
val hasVarargs = originalDescriptor.valueParameters.any { it.varargElementType != null }
|
||||
|
||||
return FlatSignature(call, originalTypeParameters, valueParameterTypes, hasVarargs, numDefaults)
|
||||
return FlatSignature(resolvedCall,
|
||||
originalDescriptor.typeParameters,
|
||||
valueParameterTypes = originalDescriptor.extensionReceiverTypeOrEmpty() +
|
||||
resolvedCall.call.valueArguments.map { valueArgumentToParameterType[it] },
|
||||
hasExtensionReceiver = originalDescriptor.extensionReceiverParameter != null,
|
||||
hasVarargs = originalDescriptor.valueParameters.any { it.varargElementType != null },
|
||||
numDefaults = numDefaults)
|
||||
}
|
||||
|
||||
fun <D : CallableDescriptor> createFromCallableDescriptor(descriptor: D): FlatSignature<D> =
|
||||
FlatSignature(descriptor,
|
||||
descriptor.typeParameters,
|
||||
valueParameterTypes = descriptor.extensionReceiverTypeOrEmpty() + descriptor.valueParameters.map { it.flatType },
|
||||
valueParameterTypes = descriptor.extensionReceiverTypeOrEmpty() + descriptor.valueParameters.map { it.argumentValueType },
|
||||
hasExtensionReceiver = descriptor.extensionReceiverParameter != null,
|
||||
hasVarargs = descriptor.valueParameters.any { it.varargElementType != null },
|
||||
numDefaults = 0)
|
||||
|
||||
val ValueParameterDescriptor.flatType: KotlinType
|
||||
val ValueParameterDescriptor.argumentValueType: KotlinType
|
||||
get() = varargElementType ?: type
|
||||
|
||||
fun CallableDescriptor.extensionReceiverTypeOrEmpty() =
|
||||
|
||||
+23
-28
@@ -23,52 +23,47 @@ import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.valuePara
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
|
||||
interface SpecificityComparisonCallbacks<T> {
|
||||
fun isNotLessSpecificSignature(signature1: FlatSignature<T>, signature2: FlatSignature<T>): Boolean?
|
||||
fun isTypeNotLessSpecific(type1: KotlinType, type2: KotlinType): Boolean?
|
||||
interface SpecificityComparisonCallbacks {
|
||||
fun isNonSubtypeNotLessSpecific(specific: KotlinType, general: KotlinType): Boolean
|
||||
}
|
||||
|
||||
fun <T> isSignatureNotLessSpecific(
|
||||
signature1: FlatSignature<T>,
|
||||
signature2: FlatSignature<T>,
|
||||
callHandle: CallHandle,
|
||||
callbacks: SpecificityComparisonCallbacks<T>
|
||||
specific: FlatSignature<T>,
|
||||
general: FlatSignature<T>,
|
||||
callbacks: SpecificityComparisonCallbacks,
|
||||
callHandle: CallHandle = CallHandle.NONE
|
||||
): Boolean {
|
||||
callbacks.isNotLessSpecificSignature(signature1, signature2)?.let { return it }
|
||||
if (specific.hasExtensionReceiver != general.hasExtensionReceiver) return false
|
||||
if (specific.valueParameterTypes.size != general.valueParameterTypes.size) return false
|
||||
|
||||
val typeParameters = signature2.typeParameters
|
||||
val typeParameters = general.typeParameters
|
||||
val constraintSystemBuilder: ConstraintSystem.Builder = ConstraintSystemBuilderImpl()
|
||||
var numConstraints = 0
|
||||
val typeSubstitutor = constraintSystemBuilder.registerTypeVariables(callHandle, typeParameters)
|
||||
|
||||
for ((type1, type2) in signature1.valueParameterTypes.zip(signature2.valueParameterTypes)) {
|
||||
if (type1 == null || type2 == null) continue
|
||||
var numConstraints = 0
|
||||
for ((specificType, generalType) in specific.valueParameterTypes.zip(general.valueParameterTypes)) {
|
||||
if (specificType == null || generalType == null) continue
|
||||
|
||||
if (isDefinitelyLessSpecificByTypeSpecificity(type1, type2)) {
|
||||
if (isDefinitelyLessSpecificByTypeSpecificity(specificType, generalType)) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (typeParameters.isEmpty() || !TypeUtils.dependsOnTypeParameters(type2, typeParameters)) {
|
||||
if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(type1, type2)) {
|
||||
callbacks.isTypeNotLessSpecific(type1, type2)?.let { if (!it) return false }
|
||||
if (typeParameters.isEmpty() || !TypeUtils.dependsOnTypeParameters(generalType, typeParameters)) {
|
||||
if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(specificType, generalType)) {
|
||||
if (!callbacks.isNonSubtypeNotLessSpecific(specificType, generalType)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
val constraintPosition = valueParameterPosition(numConstraints++)
|
||||
val substitutedType2 = typeSubstitutor.safeSubstitute(type2, Variance.INVARIANT)
|
||||
constraintSystemBuilder.addSubtypeConstraint(type1, substitutedType2, constraintPosition)
|
||||
val substitutedGeneralType = typeSubstitutor.safeSubstitute(generalType, Variance.INVARIANT)
|
||||
constraintSystemBuilder.addSubtypeConstraint(specificType, substitutedGeneralType, valueParameterPosition(numConstraints++))
|
||||
}
|
||||
}
|
||||
|
||||
if (numConstraints > 0) {
|
||||
constraintSystemBuilder.fixVariables()
|
||||
val constraintSystem = constraintSystemBuilder.build()
|
||||
if (constraintSystem.status.hasContradiction()) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
constraintSystemBuilder.fixVariables()
|
||||
val constraintSystem = constraintSystemBuilder.build()
|
||||
return !constraintSystem.status.hasContradiction()
|
||||
}
|
||||
|
||||
private fun isDefinitelyLessSpecificByTypeSpecificity(specific: KotlinType, general: KotlinType): Boolean {
|
||||
|
||||
+25
-42
@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.descriptors.ScriptDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.CallHandle
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.toHandle
|
||||
import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
@@ -147,18 +146,22 @@ class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) {
|
||||
call1: FlatSignature<MutableResolvedCall<D>>,
|
||||
call2: FlatSignature<MutableResolvedCall<D>>,
|
||||
discriminateGenerics: Boolean
|
||||
): Boolean =
|
||||
isSignatureNotLessSpecific(call1, call2, call1.callHandle(),
|
||||
if (discriminateGenerics)
|
||||
SpecificityComparisonDiscriminatingGenerics
|
||||
else
|
||||
DefaultCallSpecificityComparison)
|
||||
): Boolean {
|
||||
if (discriminateGenerics) {
|
||||
val isGeneric1 = call1.isGeneric
|
||||
val isGeneric2 = call2.isGeneric
|
||||
// generic loses to non-generic
|
||||
if (isGeneric1 && !isGeneric2) return false
|
||||
if (!isGeneric1 && isGeneric2) return true
|
||||
// two generics are non-comparable
|
||||
if (isGeneric1 && isGeneric2) return false
|
||||
}
|
||||
|
||||
private abstract inner class SpecificityComparisonWithNumerics<T> : SpecificityComparisonCallbacks<T> {
|
||||
override fun isNotLessSpecificSignature(signature1: FlatSignature<T>, signature2: FlatSignature<T>): Boolean?
|
||||
= null
|
||||
return isSignatureNotLessSpecific(call1, call2, SpecificityComparisonWithNumerics, call1.callHandle())
|
||||
}
|
||||
|
||||
override fun isTypeNotLessSpecific(type1: KotlinType, type2: KotlinType): Boolean? {
|
||||
private val SpecificityComparisonWithNumerics = object : SpecificityComparisonCallbacks {
|
||||
override fun isNonSubtypeNotLessSpecific(specific: KotlinType, general: KotlinType): Boolean {
|
||||
val _double = builtIns.doubleType
|
||||
val _float = builtIns.floatType
|
||||
val _long = builtIns.longType
|
||||
@@ -167,41 +170,21 @@ class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) {
|
||||
val _short = builtIns.shortType
|
||||
|
||||
when {
|
||||
TypeUtils.equalTypes(type1, _double) && TypeUtils.equalTypes(type2, _float) -> return true
|
||||
TypeUtils.equalTypes(type1, _int) -> {
|
||||
TypeUtils.equalTypes(specific, _double) && TypeUtils.equalTypes(general, _float) -> return true
|
||||
TypeUtils.equalTypes(specific, _int) -> {
|
||||
when {
|
||||
TypeUtils.equalTypes(type2, _long) -> return true
|
||||
TypeUtils.equalTypes(type2, _byte) -> return true
|
||||
TypeUtils.equalTypes(type2, _short) -> return true
|
||||
TypeUtils.equalTypes(general, _long) -> return true
|
||||
TypeUtils.equalTypes(general, _byte) -> return true
|
||||
TypeUtils.equalTypes(general, _short) -> return true
|
||||
}
|
||||
}
|
||||
TypeUtils.equalTypes(type1, _short) && TypeUtils.equalTypes(type2, _byte) -> return true
|
||||
TypeUtils.equalTypes(specific, _short) && TypeUtils.equalTypes(general, _byte) -> return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
private val DefaultCallSpecificityComparison = object : SpecificityComparisonWithNumerics<MutableResolvedCall<*>>() {}
|
||||
private val DefaultDescriptorSpecificityComparison = object : SpecificityComparisonWithNumerics<CallableDescriptor>() {}
|
||||
|
||||
private val SpecificityComparisonDiscriminatingGenerics = object : SpecificityComparisonWithNumerics<MutableResolvedCall<*>>() {
|
||||
override fun isNotLessSpecificSignature(
|
||||
signature1: FlatSignature<MutableResolvedCall<*>>,
|
||||
signature2: FlatSignature<MutableResolvedCall<*>>
|
||||
): Boolean? {
|
||||
val isGeneric1 = signature1.isGeneric
|
||||
val isGeneric2 = signature2.isGeneric
|
||||
// generic loses to non-generic
|
||||
if (isGeneric1 && !isGeneric2) return false
|
||||
if (!isGeneric1 && isGeneric2) return true
|
||||
// two generics are non-comparable
|
||||
if (isGeneric1 && isGeneric2) return false
|
||||
// otherwise continue comparing signatures
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
private fun <D: CallableDescriptor> isOfNotLessSpecificShape(
|
||||
call1: FlatSignature<MutableResolvedCall<D>>,
|
||||
call2: FlatSignature<MutableResolvedCall<D>>
|
||||
@@ -250,23 +233,23 @@ class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if `d1` is definitely not less specific than `d2`,
|
||||
* `false` if `d1` is definitely less specific than `d2`,
|
||||
* Returns `true` if `f` is definitely not less specific than `g`,
|
||||
* `false` if `f` is definitely less specific than `g`,
|
||||
* `null` if undecided.
|
||||
*/
|
||||
private fun compareFunctionParameterTypes(f: CallableDescriptor, g: CallableDescriptor): Boolean {
|
||||
private fun isNotLessSpecificCallableReferenceDescriptor(f: CallableDescriptor, g: CallableDescriptor): Boolean {
|
||||
if (f.valueParameters.size != g.valueParameters.size) return false
|
||||
if (f.varargParameterPosition() != g.varargParameterPosition()) return false
|
||||
|
||||
val fSignature = FlatSignature.createFromCallableDescriptor(f)
|
||||
val gSignature = FlatSignature.createFromCallableDescriptor(g)
|
||||
return isSignatureNotLessSpecific(fSignature, gSignature, CallHandle.NONE, DefaultDescriptorSpecificityComparison)
|
||||
return isSignatureNotLessSpecific(fSignature, gSignature, SpecificityComparisonWithNumerics)
|
||||
}
|
||||
|
||||
private fun isNotLessSpecificCallableReference(f: CallableDescriptor, g: CallableDescriptor): Boolean =
|
||||
// TODO should we "discriminate generic descriptors" for callable references?
|
||||
tryCompareDescriptorsFromScripts(f, g) ?:
|
||||
compareFunctionParameterTypes(f, g)
|
||||
isNotLessSpecificCallableReferenceDescriptor(f, g)
|
||||
|
||||
companion object {
|
||||
// Different smartcasts may lead to the same candidate descriptor wrapped into different ResolvedCallImpl objects
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<!CONFLICTING_OVERLOADS!>fun foo(vararg <!UNUSED_PARAMETER!>x<!>: Int)<!> {}
|
||||
<!CONFLICTING_OVERLOADS!>fun foo(<!UNUSED_PARAMETER!>x<!>: IntArray)<!> {}
|
||||
<!CONFLICTING_JVM_DECLARATIONS!>fun foo(vararg <!UNUSED_PARAMETER!>x<!>: Int)<!> {}
|
||||
<!CONFLICTING_JVM_DECLARATIONS!>fun foo(<!UNUSED_PARAMETER!>x<!>: IntArray)<!> {}
|
||||
|
||||
<!CONFLICTING_JVM_DECLARATIONS!>fun foo(vararg <!UNUSED_PARAMETER!>x<!>: Int?)<!> {}
|
||||
<!CONFLICTING_JVM_DECLARATIONS!>fun foo(<!UNUSED_PARAMETER!>x<!>: Array<Int>)<!> {}
|
||||
<!CONFLICTING_JVM_DECLARATIONS!>fun foo(<!UNUSED_PARAMETER!>x<!>: Array<Int>)<!> {}
|
||||
|
||||
<!CONFLICTING_JVM_DECLARATIONS!>fun foo(vararg <!UNUSED_PARAMETER!>nn<!>: Number)<!> {}
|
||||
<!CONFLICTING_JVM_DECLARATIONS!>fun foo(<!UNUSED_PARAMETER!>nn<!>: Array<out Number>)<!> {}
|
||||
@@ -2,5 +2,7 @@ package
|
||||
|
||||
public fun foo(/*0*/ x: kotlin.Array<kotlin.Int>): kotlin.Unit
|
||||
public fun foo(/*0*/ vararg x: kotlin.Int? /*kotlin.Array<out kotlin.Int?>*/): kotlin.Unit
|
||||
public fun foo(/*0*/ nn: kotlin.Array<out kotlin.Number>): kotlin.Unit
|
||||
public fun foo(/*0*/ vararg nn: kotlin.Number /*kotlin.Array<out kotlin.Number>*/): kotlin.Unit
|
||||
public fun foo(/*0*/ vararg x: kotlin.Int /*kotlin.IntArray*/): kotlin.Unit
|
||||
public fun foo(/*0*/ x: kotlin.IntArray): kotlin.Unit
|
||||
|
||||
@@ -136,6 +136,15 @@ public class ErrorUtils {
|
||||
};
|
||||
}
|
||||
|
||||
public static boolean containsErrorType(@NotNull CallableDescriptor callableDescriptor) {
|
||||
if (callableDescriptor instanceof FunctionDescriptor) {
|
||||
return containsErrorType((FunctionDescriptor) callableDescriptor);
|
||||
}
|
||||
else {
|
||||
return containsErrorType(callableDescriptor.getReturnType());
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean containsErrorType(@NotNull FunctionDescriptor function) {
|
||||
if (containsErrorType(function.getReturnType())) {
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user