FIR: support more precise diagnostics about parameter names

#KT-52762 Fixed
This commit is contained in:
Mikhail Glukhikh
2022-06-17 18:27:04 +02:00
committed by Space
parent 9fbafc3eb9
commit 065e852199
18 changed files with 154 additions and 57 deletions
@@ -1482,6 +1482,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.NAME_FOR_AMBIGUOUS_PARAMETER) { firDiagnostic ->
NameForAmbiguousParameterImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirErrors.ASSIGNMENT_TYPE_MISMATCH) { firDiagnostic ->
AssignmentTypeMismatchImpl(
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
@@ -1063,6 +1063,10 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
abstract val name: String
}
abstract class NameForAmbiguousParameter : KtFirDiagnostic<KtValueArgument>() {
override val diagnosticClass get() = NameForAmbiguousParameter::class
}
abstract class AssignmentTypeMismatch : KtFirDiagnostic<KtExpression>() {
override val diagnosticClass get() = AssignmentTypeMismatch::class
abstract val expectedType: KtType
@@ -1274,6 +1274,11 @@ internal class NamedParameterNotFoundImpl(
override val token: KtLifetimeToken,
) : KtFirDiagnostic.NamedParameterNotFound(), KtAbstractFirDiagnostic<KtValueArgument>
internal class NameForAmbiguousParameterImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.NameForAmbiguousParameter(), KtAbstractFirDiagnostic<KtValueArgument>
internal class AssignmentTypeMismatchImpl(
override val expectedType: KtType,
override val actualType: KtType,
@@ -1,5 +1,5 @@
FILE: NamedParameterInConcurrentMap.kt
public final fun main(): R|kotlin/Unit| {
lval map: R|java/util/concurrent/ConcurrentHashMap<kotlin/String, kotlin/String>| = R|java/util/concurrent/ConcurrentHashMap.ConcurrentHashMap|<R|kotlin/String|, R|kotlin/String|>()
R|<local>/map|.<Inapplicable(INAPPLICABLE_ARGUMENTS_MAPPING_ERROR): java/util/concurrent/ConcurrentHashMap.put>#(key = String(key), value = String(value))
R|<local>/map|.R|SubstitutionOverride<java/util/concurrent/ConcurrentHashMap.put: R|kotlin/String?|>|(key = String(key), value = String(value))
}
@@ -5,7 +5,7 @@ import java.util.concurrent.ConcurrentHashMap
fun main() {
val map = ConcurrentHashMap<String, String>()
map.put(
<!NAMED_PARAMETER_NOT_FOUND!>key<!> = "key",
<!NAMED_PARAMETER_NOT_FOUND!>value<!> = "value"
<!NO_VALUE_FOR_PARAMETER, NO_VALUE_FOR_PARAMETER!>)<!>
key = "key",
value = "value"
)
}
@@ -482,6 +482,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val NAMED_PARAMETER_NOT_FOUND by error<KtValueArgument>(PositioningStrategy.NAME_OF_NAMED_ARGUMENT) {
parameter<String>("name")
}
val NAME_FOR_AMBIGUOUS_PARAMETER by error<KtValueArgument>(PositioningStrategy.NAME_OF_NAMED_ARGUMENT)
val ASSIGNMENT_TYPE_MISMATCH by error<KtExpression> {
parameter<ConeKotlinType>("expectedType")
@@ -338,6 +338,7 @@ object FirErrors {
val TOO_MANY_ARGUMENTS by error1<PsiElement, FirCallableSymbol<*>>()
val NO_VALUE_FOR_PARAMETER by error1<KtElement, FirValueParameterSymbol>(SourceElementPositioningStrategies.VALUE_ARGUMENTS)
val NAMED_PARAMETER_NOT_FOUND by error1<KtValueArgument, String>(SourceElementPositioningStrategies.NAME_OF_NAMED_ARGUMENT)
val NAME_FOR_AMBIGUOUS_PARAMETER by error0<KtValueArgument>(SourceElementPositioningStrategies.NAME_OF_NAMED_ARGUMENT)
val ASSIGNMENT_TYPE_MISMATCH by error3<KtExpression, ConeKotlinType, ConeKotlinType, Boolean>()
val RESULT_TYPE_MISMATCH by error2<KtExpression, ConeKotlinType, ConeKotlinType>()
val MANY_LAMBDA_EXPRESSION_ARGUMENTS by error0<KtValueArgument>()
@@ -297,13 +297,14 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MISPLACED_TYPE_PA
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MISSING_STDLIB_CLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MISSING_VAL_ON_ANNOTATION_PARAMETER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MODIFIER_FORM_FOR_NON_BUILT_IN_SUSPEND
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTIPLE_ARGUMENTS_APPLICABLE_FOR_CONTEXT_RECEIVER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MODIFIER_FORM_FOR_NON_BUILT_IN_SUSPEND_FUN
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTIPLE_ARGUMENTS_APPLICABLE_FOR_CONTEXT_RECEIVER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTIPLE_VARARG_PARAMETERS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MUST_BE_INITIALIZED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MUST_BE_INITIALIZED_OR_BE_ABSTRACT
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NAMED_ARGUMENTS_NOT_ALLOWED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NAMED_PARAMETER_NOT_FOUND
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NAME_FOR_AMBIGUOUS_PARAMETER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NAME_IN_CONSTRAINT_IS_NOT_A_TYPE_PARAMETER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NESTED_CLASS_NOT_ALLOWED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NEWER_VERSION_IN_SINCE_KOTLIN
@@ -578,6 +579,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_MODIFIER_TA
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_NUMBER_OF_TYPE_ARGUMENTS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_SETTER_PARAMETER_TYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_SETTER_RETURN_TYPE
import org.jetbrains.kotlin.psi.KtReferenceExpression
@Suppress("unused")
object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
@@ -937,6 +939,8 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
map.put(ARGUMENT_PASSED_TWICE, "An argument is already passed for this parameter")
map.put(NO_VALUE_FOR_PARAMETER, "No value passed for parameter ''{0}''", DECLARATION_NAME)
map.put(NAMED_PARAMETER_NOT_FOUND, "Cannot find a parameter with this name: {0}", TO_STRING)
map.put(NAME_FOR_AMBIGUOUS_PARAMETER, "Named argument is not allowed for a parameter with an ambiguous name")
map.put(MANY_LAMBDA_EXPRESSION_ARGUMENTS, "Only one lambda expression is allowed outside a parenthesized argument list")
map.put(NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER, "Not enough information to infer type variable {0}", STRING)
map.put(SPREAD_OF_NULLABLE, "The spread operator (*foo) may not be applied to an argument of nullable type")
@@ -235,6 +235,9 @@ private fun mapInapplicableCandidateError(
rootCause.argument.source ?: source,
rootCause.argument.name.asString()
)
is NameForAmbiguousParameter -> FirErrors.NAME_FOR_AMBIGUOUS_PARAMETER.createOn(
rootCause.argument.source ?: source
)
is UnsafeCall -> mapUnsafeCallError(diagnostic.candidate, rootCause, source, qualifiedAccessSource)
is ManyLambdaExpressionArguments -> FirErrors.MANY_LAMBDA_EXPRESSION_ARGUMENTS.createOn(rootCause.argument.source ?: source)
is InfixCallOfNonInfixFunction -> FirErrors.INFIX_MODIFIER_REQUIRED.createOn(source, rootCause.function)
@@ -34,8 +34,11 @@ import org.jetbrains.kotlin.fir.resolve.dfa.PropertyStability
import org.jetbrains.kotlin.fir.resolve.diagnostics.*
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.impl.delegatedWrapperData
import org.jetbrains.kotlin.fir.scopes.impl.importedFromObjectData
import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.ensureResolved
import org.jetbrains.kotlin.fir.symbols.impl.*
@@ -493,7 +496,12 @@ fun FirCallableDeclaration.getContainingClass(session: FirSession): FirRegularCl
session.symbolProvider.getSymbolByLookupTag(lookupTag)?.fir as? FirRegularClass
}
fun FirFunction.getAsForbiddenNamedArgumentsTarget(session: FirSession): ForbiddenNamedArgumentsTarget? {
fun FirFunction.getAsForbiddenNamedArgumentsTarget(
session: FirSession,
// NB: with originScope given this function will try to find overridden declaration with allowed parameter names
// for intersection/substitution overrides
originScope: FirTypeScope? = null
): ForbiddenNamedArgumentsTarget? {
if (this is FirConstructor && this.isPrimary) {
this.getContainingClass(session)?.let { containingClass ->
if (containingClass.classKind == ClassKind.ANNOTATION_CLASS) {
@@ -506,15 +514,21 @@ fun FirFunction.getAsForbiddenNamedArgumentsTarget(session: FirSession): Forbidd
FirDeclarationOrigin.Source, FirDeclarationOrigin.Precompiled, FirDeclarationOrigin.Library -> null
FirDeclarationOrigin.Delegated -> delegatedWrapperData?.wrapped?.getAsForbiddenNamedArgumentsTarget(session)
FirDeclarationOrigin.ImportedFromObject -> importedFromObjectData?.original?.getAsForbiddenNamedArgumentsTarget(session)
// For intersection overrides, the logic in
// org.jetbrains.kotlin.fir.scopes.impl.FirTypeIntersectionScope#selectMostSpecificMember picks the most specific one and store
// it in originalForIntersectionOverrideAttr. This follows from FE1.0 behavior which selects the most specific function
// (org.jetbrains.kotlin.resolve.OverridingUtil#selectMostSpecificMember), from which the `hasStableParameterNames` status is
// copied.
FirDeclarationOrigin.IntersectionOverride -> originalForIntersectionOverrideAttr?.getAsForbiddenNamedArgumentsTarget(session)
is FirDeclarationOrigin.Java, FirDeclarationOrigin.Enhancement -> ForbiddenNamedArgumentsTarget.NON_KOTLIN_FUNCTION
FirDeclarationOrigin.SamConstructor -> null
FirDeclarationOrigin.SubstitutionOverride -> originalForSubstitutionOverrideAttr?.getAsForbiddenNamedArgumentsTarget(session)
FirDeclarationOrigin.IntersectionOverride, FirDeclarationOrigin.SubstitutionOverride -> {
var result: ForbiddenNamedArgumentsTarget? =
originalIfFakeOverride()?.getAsForbiddenNamedArgumentsTarget(session) ?: return null
originScope?.processOverriddenFunctions(symbol as FirNamedFunctionSymbol) {
if (it.fir.getAsForbiddenNamedArgumentsTarget(session) == null) {
result = null
ProcessorAction.STOP
} else {
ProcessorAction.NEXT
}
}
result
}
// referenced function of a Kotlin function type
FirDeclarationOrigin.BuiltIns -> {
if (dispatchReceiverClassOrNull()?.isBuiltinFunctionalType() == true) {
@@ -13,10 +13,17 @@ import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.declarations.utils.isOperator
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.buildNamedArgumentExpression
import org.jetbrains.kotlin.fir.isIntersectionOverride
import org.jetbrains.kotlin.fir.isSubstitutionOrIntersectionOverride
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.defaultParameterResolver
import org.jetbrains.kotlin.fir.resolve.getAsForbiddenNamedArgumentsTarget
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget
import org.jetbrains.kotlin.util.OperatorNameConventions
@@ -128,7 +135,7 @@ private class FirCallArgumentsProcessor(
val result: LinkedHashMap<FirValueParameter, ResolvedCallArgument> = LinkedHashMap(function.valueParameters.size)
val forbiddenNamedArgumentsTarget: ForbiddenNamedArgumentsTarget? by lazy {
function.getAsForbiddenNamedArgumentsTarget(useSiteSession)
function.getAsForbiddenNamedArgumentsTarget(useSiteSession, originScope as? FirTypeScope)
}
private enum class State {
@@ -322,29 +329,75 @@ private class FirCallArgumentsProcessor(
}
private fun findParameterByName(argument: FirNamedArgumentExpression): FirValueParameter? {
val parameter = getParameterByName(argument.name)
var parameter = getParameterByName(argument.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))
val symbol = function.symbol as? FirNamedFunctionSymbol
var matchedIndex = -1
// Note: should be called when parameter != null && matchedIndex != -1
fun List<FirValueParameterSymbol>.findAndReportValueParameterWithDifferentName(): ProcessorAction {
val someParameter = getOrNull(matchedIndex)?.fir
val someName = someParameter?.name
if (someName != null && someName != argument.name) {
addDiagnostic(
NameForAmbiguousParameter(argument, matchedParameter = parameter!!, someParameter)
)
return ProcessorAction.STOP
}
return ProcessorAction.NEXT
}
if (parameter == null) {
if (symbol != null && function.isSubstitutionOrIntersectionOverride) {
var allowedParameters: List<FirValueParameterSymbol>? = null
(originScope as? FirTypeScope)?.processOverriddenFunctions(symbol) {
if (it.fir.getAsForbiddenNamedArgumentsTarget(useSiteSession) != null) {
return@processOverriddenFunctions ProcessorAction.NEXT
}
val someParameterSymbols = it.valueParameterSymbols
if (matchedIndex != -1) {
someParameterSymbols.findAndReportValueParameterWithDifferentName()
} else {
matchedIndex = someParameterSymbols.indexOfFirst { originalParameter ->
originalParameter.name == argument.name
}
if (matchedIndex != -1) {
parameter = parameters[matchedIndex]
val someParameter = allowedParameters?.getOrNull(matchedIndex)?.fir
if (someParameter != null) {
addDiagnostic(
NameForAmbiguousParameter(argument, matchedParameter = parameter!!, anotherParameter = someParameter)
)
ProcessorAction.STOP
} else {
ProcessorAction.NEXT
}
} else {
allowedParameters = someParameterSymbols
ProcessorAction.NEXT
}
}
}
}
if (parameter == null) {
addDiagnostic(NameNotFound(argument, function))
}
} else {
// TODO: should we check also substitution overrides? Performance!
if (symbol != null && function.isIntersectionOverride) {
matchedIndex = parameters.indexOfFirst { originalParameter ->
originalParameter.name == argument.name
}
if (matchedIndex != -1) {
(originScope as? FirTypeScope)?.processOverriddenFunctions(symbol) {
if (it.fir.getAsForbiddenNamedArgumentsTarget(useSiteSession) != null) {
return@processOverriddenFunctions ProcessorAction.NEXT
}
it.valueParameterSymbols.findAndReportValueParameterWithDifferentName()
}
}
}
}
return parameter
}
@@ -70,6 +70,12 @@ class NameNotFound(
val function: FirFunction
) : ResolutionDiagnostic(INAPPLICABLE_ARGUMENTS_MAPPING_ERROR)
class NameForAmbiguousParameter(
val argument: FirNamedArgumentExpression,
val matchedParameter: FirValueParameter,
val anotherParameter: FirValueParameter
) : ResolutionDiagnostic(INAPPLICABLE_ARGUMENTS_MAPPING_ERROR)
object InapplicableCandidate : ResolutionDiagnostic(INAPPLICABLE)
object HiddenCandidate : ResolutionDiagnostic(HIDDEN)
@@ -10,18 +10,18 @@ interface C : A, B
interface D : B, A
fun foo(x : C, y : D){
x.foo(x = 0)
x.foo(<!NAMED_PARAMETER_NOT_FOUND!>y<!> = 0<!NO_VALUE_FOR_PARAMETER!>)<!>
y.foo(<!NAMED_PARAMETER_NOT_FOUND!>x<!> = 0<!NO_VALUE_FOR_PARAMETER!>)<!>
y.foo(y = 0)
x.foo(<!NAME_FOR_AMBIGUOUS_PARAMETER!>x<!> = 0)
x.foo(<!NAME_FOR_AMBIGUOUS_PARAMETER!>y<!> = 0)
y.foo(<!NAME_FOR_AMBIGUOUS_PARAMETER!>x<!> = 0)
y.foo(<!NAME_FOR_AMBIGUOUS_PARAMETER!>y<!> = 0)
}
abstract class C1 : A, B
abstract class D1 : A, B
fun bar(x : C1, y : D1){
x.foo(x = 0)
x.foo(<!NAMED_PARAMETER_NOT_FOUND!>y<!> = 0<!NO_VALUE_FOR_PARAMETER!>)<!>
y.foo(x = 0)
y.foo(<!NAMED_PARAMETER_NOT_FOUND!>y<!> = 0<!NO_VALUE_FOR_PARAMETER!>)<!>
x.foo(<!NAME_FOR_AMBIGUOUS_PARAMETER!>x<!> = 0)
x.foo(<!NAME_FOR_AMBIGUOUS_PARAMETER!>y<!> = 0)
y.foo(<!NAME_FOR_AMBIGUOUS_PARAMETER!>x<!> = 0)
y.foo(<!NAME_FOR_AMBIGUOUS_PARAMETER!>y<!> = 0)
}
@@ -14,11 +14,11 @@ interface C : A, B { // Warning here, this is correct
}
fun test(c: C) {
c.foo(<!NAMED_PARAMETER_NOT_FOUND!>b1<!> = 1, <!NAMED_PARAMETER_NOT_FOUND!>b2<!> = 1.0<!NO_VALUE_FOR_PARAMETER, NO_VALUE_FOR_PARAMETER!>)<!>
c.foo(a1 = 1, <!NAMED_PARAMETER_NOT_FOUND!>b2<!> = 1.0<!NO_VALUE_FOR_PARAMETER!>)<!>
c.foo(a1 = 1, a2 = 1.0)
c.foo(a1 = 1, a2 = 1.0)
c.bar(a1 = 1, a2 = 1.0, <!NAMED_PARAMETER_NOT_FOUND!>b3<!>= ""<!NO_VALUE_FOR_PARAMETER!>)<!>
c.baz(a1 = 1, <!NAMED_PARAMETER_NOT_FOUND!>b2<!> = 1.0, a3 = "", <!NAMED_PARAMETER_NOT_FOUND!>b4<!> = 2, a5 = ""<!NO_VALUE_FOR_PARAMETER, NO_VALUE_FOR_PARAMETER!>)<!>
c.baz(a1 = 1, a2 = 1.0, a3 = "", <!NAMED_PARAMETER_NOT_FOUND!>b4<!> = 2, a5 = ""<!NO_VALUE_FOR_PARAMETER!>)<!>
c.foo(<!NAME_FOR_AMBIGUOUS_PARAMETER!>b1<!> = 1, <!NAME_FOR_AMBIGUOUS_PARAMETER!>b2<!> = 1.0)
c.foo(<!NAME_FOR_AMBIGUOUS_PARAMETER!>a1<!> = 1, <!NAME_FOR_AMBIGUOUS_PARAMETER!>b2<!> = 1.0)
c.foo(<!NAME_FOR_AMBIGUOUS_PARAMETER!>a1<!> = 1, <!NAME_FOR_AMBIGUOUS_PARAMETER!>a2<!> = 1.0)
c.foo(<!NAME_FOR_AMBIGUOUS_PARAMETER!>a1<!> = 1, <!NAME_FOR_AMBIGUOUS_PARAMETER!>a2<!> = 1.0)
c.bar(a1 = 1, a2 = 1.0, <!NAME_FOR_AMBIGUOUS_PARAMETER!>b3<!>= "")
c.baz(a1 = 1, <!NAME_FOR_AMBIGUOUS_PARAMETER!>b2<!> = 1.0, a3 = "", <!NAME_FOR_AMBIGUOUS_PARAMETER!>b4<!> = 2, a5 = "")
c.baz(a1 = 1, <!NAME_FOR_AMBIGUOUS_PARAMETER!>a2<!> = 1.0, a3 = "", <!NAME_FOR_AMBIGUOUS_PARAMETER!>b4<!> = 2, a5 = "")
}
@@ -10,6 +10,6 @@ interface C : A<Int>, B { // Warning here, this is correct
}
fun test(c: C) {
c.foo(a = 1)
c.foo(<!NAMED_PARAMETER_NOT_FOUND!>b<!> = 1<!NO_VALUE_FOR_PARAMETER!>)<!>
c.foo(<!NAME_FOR_AMBIGUOUS_PARAMETER!>a<!> = 1)
c.foo(<!NAME_FOR_AMBIGUOUS_PARAMETER!>b<!> = 1)
}
@@ -10,6 +10,6 @@ interface C : A, B { // Warning here, this is correct
}
fun test(c: C) {
c.foo(a = 1)
c.foo(<!NAMED_PARAMETER_NOT_FOUND!>b<!> = 1<!NO_VALUE_FOR_PARAMETER!>)<!>
c.foo(<!NAME_FOR_AMBIGUOUS_PARAMETER!>a<!> = 1)
c.foo(<!NAME_FOR_AMBIGUOUS_PARAMETER!>b<!> = 1)
}
@@ -11,5 +11,5 @@ interface C<U> : A<U>, B<U> { // Warning here, this is correct
fun test(c: C<Int>) {
c.foo(a = 1)
c.foo(<!NAMED_PARAMETER_NOT_FOUND!>b<!> = 1<!NO_VALUE_FOR_PARAMETER!>)<!>
c.foo(<!NAME_FOR_AMBIGUOUS_PARAMETER!>b<!> = 1)
}
@@ -18,5 +18,5 @@ fun test1(d: D) {
}
fun test2(c: C) {
c.foo(<!NAMED_PARAMETER_NOT_FOUND!>b1<!> = 1, <!NAMED_PARAMETER_NOT_FOUND!>b2<!> = 1.0<!NO_VALUE_FOR_PARAMETER, NO_VALUE_FOR_PARAMETER!>)<!>
c.foo(<!NAME_FOR_AMBIGUOUS_PARAMETER!>b1<!> = 1, <!NAME_FOR_AMBIGUOUS_PARAMETER!>b2<!> = 1.0)
}