FIR: Fix capturing of flexible types

This commit is contained in:
Denis Zharkov
2020-01-29 15:30:17 +03:00
parent ac2b5beb4e
commit d28e1f156a
7 changed files with 29 additions and 9 deletions
@@ -207,7 +207,7 @@ fun Candidate.resolvePlainArgumentType(
val position = SimpleConstraintSystemConstraintPosition //TODO val position = SimpleConstraintSystemConstraintPosition //TODO
val session = sink.components.session val session = sink.components.session
val capturedType = prepareCapturedType(argumentType, session) val capturedType = prepareCapturedType(argumentType)
val nullableExpectedType = expectedType.withNullability(ConeNullability.NULLABLE, session.inferenceContext) val nullableExpectedType = expectedType.withNullability(ConeNullability.NULLABLE, session.inferenceContext)
if (isReceiver && isSafeCall) { if (isReceiver && isSafeCall) {
@@ -220,12 +220,20 @@ fun Candidate.resolvePlainArgumentType(
checkApplicabilityForArgumentType(csBuilder, capturedType, expectedType, position, isReceiver, isDispatch, nullableExpectedType, sink) checkApplicabilityForArgumentType(csBuilder, capturedType, expectedType, position, isReceiver, isDispatch, nullableExpectedType, sink)
} }
fun Candidate.prepareCapturedType(argumentType: ConeKotlinType, session: FirSession): ConeKotlinType { fun Candidate.prepareCapturedType(argumentType: ConeKotlinType): ConeKotlinType {
if (argumentType.typeArguments.isEmpty() || argumentType !is ConeClassLikeType) return argumentType return captureTypeFromExpressionOrNull(argumentType) ?: argumentType
}
private fun Candidate.captureTypeFromExpressionOrNull(argumentType: ConeKotlinType): ConeKotlinType? {
if (argumentType is ConeFlexibleType) {
return captureTypeFromExpressionOrNull(argumentType.lowerBound)
}
if (argumentType.typeArguments.isEmpty() || argumentType !is ConeClassLikeType) return null
return bodyResolveComponents.inferenceComponents.ctx.captureFromArguments( return bodyResolveComponents.inferenceComponents.ctx.captureFromArguments(
argumentType, CaptureStatus.FROM_EXPRESSION argumentType, CaptureStatus.FROM_EXPRESSION
) as? ConeKotlinType ?: argumentType ) as? ConeKotlinType
} }
private fun checkApplicabilityForArgumentType( private fun checkApplicabilityForArgumentType(
@@ -0,0 +1,3 @@
fun foo(z: java.util.zip.ZipFile) {
z.entries().asSequence()
}
@@ -0,0 +1,4 @@
FILE: capturedFlexible.kt
public final fun foo(z: R|java/util/zip/ZipFile|): R|kotlin/Unit| {
R|<local>/z|.R|java/util/zip/ZipFile.entries|().R|kotlin/sequences/asSequence|<R|captured type: lowerType = null|>()
}
@@ -464,6 +464,11 @@ public class FirDiagnosticsWithStdlibTestGenerated extends AbstractFirDiagnostic
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/resolve/testData/resolve/stdlib/j+k"), Pattern.compile("^([^.]+)\\.kt$"), null, true); KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/resolve/testData/resolve/stdlib/j+k"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
} }
@TestMetadata("capturedFlexible.kt")
public void testCapturedFlexible() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/stdlib/j+k/capturedFlexible.kt");
}
@TestMetadata("complexFlexibleInference.kt") @TestMetadata("complexFlexibleInference.kt")
public void testComplexFlexibleInference() throws Exception { public void testComplexFlexibleInference() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/stdlib/j+k/complexFlexibleInference.kt"); runTest("compiler/fir/resolve/testData/resolve/stdlib/j+k/complexFlexibleInference.kt");
+1 -1
View File
@@ -6,6 +6,6 @@ import java.util.stream.IntStream
fun main() { fun main() {
val xs = IntStream.range(0, 10).mapToObj { it.toString() } val xs = IntStream.range(0, 10).mapToObj { it.toString() }
.<!INAPPLICABLE_CANDIDATE!>collect<!>(Collectors.toList()) .collect(Collectors.toList())
<!UNRESOLVED_REFERENCE!>xs[0]<!> <!UNRESOLVED_REFERENCE!>xs[0]<!>
} }
@@ -7,8 +7,8 @@ import java.util.stream.Collectors
import java.util.stream.Stream import java.util.stream.Stream
fun test(a: Stream<String>) { fun test(a: Stream<String>) {
a.<!INAPPLICABLE_CANDIDATE!>collect<!>(Collectors.toList()) <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><MutableList<String>>() } a.collect(Collectors.toList()) checkType { <!UNRESOLVED_REFERENCE!>_<!><MutableList<String>>() }
// actually the inferred type is platform // actually the inferred type is platform
a.<!INAPPLICABLE_CANDIDATE!>collect<!>(Collectors.toList()) <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><List<String?>>() } a.collect(Collectors.toList()) checkType { <!UNRESOLVED_REFERENCE!>_<!><List<String?>>() }
} }
@@ -8,6 +8,6 @@ interface A : Collection<String> {
} }
fun foo(x: List<String>, y: A) { fun foo(x: List<String>, y: A) {
x.stream().filter { it.length > 0 }.<!INAPPLICABLE_CANDIDATE!>collect<!>(Collectors.toList()) x.stream().filter { it.length > 0 }.collect(Collectors.toList())
y.stream().filter { it.length > 0 } y.stream().filter { it.length > 0 }
} }