diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt index 9836a3f0202..eb5fdeecb96 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt @@ -254,7 +254,14 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes val argumentExpression = valueArgument.getArgumentExpression() ?: return val effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor, valueArgument) - var expectedType = constraintSystem.build().currentSubstitutor.substitute(effectiveExpectedType, Variance.INVARIANT) + + val currentSubstitutor = constraintSystem.build().currentSubstitutor + val newSubstitution = object : DelegatedTypeSubstitution(currentSubstitutor.substitution) { + override fun approximateContravariantCapturedTypes() = true + } + + var expectedType = newSubstitution.buildSubstitutor().substitute(effectiveExpectedType, Variance.IN_VARIANCE) + if (expectedType == null || TypeUtils.isDontCarePlaceholder(expectedType)) { expectedType = argumentTypeResolver.getShapeTypeOfFunctionLiteral(functionLiteral, context.scope, context.trace, false) } diff --git a/compiler/testData/diagnostics/tests/resolve/capturedTypesInLambdaParameter.kt b/compiler/testData/diagnostics/tests/resolve/capturedTypesInLambdaParameter.kt new file mode 100644 index 00000000000..111b42f50bf --- /dev/null +++ b/compiler/testData/diagnostics/tests/resolve/capturedTypesInLambdaParameter.kt @@ -0,0 +1,37 @@ +// !CHECK_TYPE +// !DIAGNOSTICS: -UNUSED_PARAMETER +class B + +fun B.foo(f: (T) -> Unit) {} +fun B.bar(f: (T, T) -> Unit, g: (T, T) -> Unit) {} + +fun number(x: Number) {} +fun Number.foobar() {} + +fun test(b: B) { + b.foo { + it checkType { _() } + it.toInt() + } + + b.foo { x -> + x checkType { _() } + x.toInt() + } + + b.bar({ x, y -> + x checkType { _() } + y checkType { _() } + x.toInt() + y.toInt() + }) { u, w -> + u checkType { _() } + w checkType { _() } + + u.toInt() + w.toInt() + } + + b.foo(::number) + b.foo(Number::foobar) +} diff --git a/compiler/testData/diagnostics/tests/resolve/capturedTypesInLambdaParameter.txt b/compiler/testData/diagnostics/tests/resolve/capturedTypesInLambdaParameter.txt new file mode 100644 index 00000000000..583f8bb3905 --- /dev/null +++ b/compiler/testData/diagnostics/tests/resolve/capturedTypesInLambdaParameter.txt @@ -0,0 +1,14 @@ +package + +public fun number(/*0*/ x: kotlin.Number): kotlin.Unit +public fun test(/*0*/ b: B): kotlin.Unit +public fun B.bar(/*0*/ f: (T, T) -> kotlin.Unit, /*1*/ g: (T, T) -> kotlin.Unit): kotlin.Unit +public fun B.foo(/*0*/ f: (T) -> kotlin.Unit): kotlin.Unit +public fun kotlin.Number.foobar(): kotlin.Unit + +public final class B { + public 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 +} diff --git a/compiler/testData/diagnostics/testsWithJava8/samWithConsumer.kt b/compiler/testData/diagnostics/testsWithJava8/samWithConsumer.kt new file mode 100644 index 00000000000..cc5fa229e7b --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJava8/samWithConsumer.kt @@ -0,0 +1,22 @@ +// !CHECK_TYPE +// FILE: A.java +import java.util.function.Consumer; + +public class A { + void test(Consumer consumer) {} +} + +// FILE: 1.kt +import java.util.function.Consumer + +fun test(a: A) { + a.test (Consumer { + it checkType { _() } + it.toInt() + }) + + a.test { + it checkType { _() } + it.toInt() + } +} diff --git a/compiler/testData/diagnostics/testsWithJava8/samWithConsumer.txt b/compiler/testData/diagnostics/testsWithJava8/samWithConsumer.txt new file mode 100644 index 00000000000..a9a361bc462 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJava8/samWithConsumer.txt @@ -0,0 +1,11 @@ +package + +public fun test(/*0*/ a: A): kotlin.Unit + +public open class A { + public constructor 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/*package*/ open fun test(/*0*/ consumer: java.util.function.Consumer!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests-java8/tests/org/jetbrains/kotlin/checkers/DiagnosticsWithJava8TestGenerated.java b/compiler/tests-java8/tests/org/jetbrains/kotlin/checkers/DiagnosticsWithJava8TestGenerated.java index 8974117c2ee..6c824d6fed4 100644 --- a/compiler/tests-java8/tests/org/jetbrains/kotlin/checkers/DiagnosticsWithJava8TestGenerated.java +++ b/compiler/tests-java8/tests/org/jetbrains/kotlin/checkers/DiagnosticsWithJava8TestGenerated.java @@ -35,6 +35,12 @@ public class DiagnosticsWithJava8TestGenerated extends AbstractDiagnosticsWithFu KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithJava8"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("samWithConsumer.kt") + public void testSamWithConsumer() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJava8/samWithConsumer.kt"); + doTest(fileName); + } + @TestMetadata("compiler/testData/diagnostics/testsWithJava8/annotations") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 1ca930f1e4b..72b9348803f 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -15414,6 +15414,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("capturedTypesInLambdaParameter.kt") + public void testCapturedTypesInLambdaParameter() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/resolve/capturedTypesInLambdaParameter.kt"); + doTest(fileName); + } + @TestMetadata("constructorVsCompanion.kt") public void testConstructorVsCompanion() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/resolve/constructorVsCompanion.kt");