diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt index b4930d5bdd9..939dc0040de 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt @@ -38,16 +38,20 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.context.TemporaryTraceAndCache import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsUtil +import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject import org.jetbrains.kotlin.types.ErrorUtils import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinTypeImpl import org.jetbrains.kotlin.types.TypeUtils +import org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE import org.jetbrains.kotlin.types.expressions.typeInfoFactory.createTypeInfo import javax.inject.Inject sealed class DoubleColonLHS(val type: KotlinType) { - class Expression(val typeInfo: KotlinTypeInfo) : DoubleColonLHS(typeInfo.type!!) + class Expression(typeInfo: KotlinTypeInfo) : DoubleColonLHS(typeInfo.type!!) { + val dataFlowInfo: DataFlowInfo = typeInfo.dataFlowInfo + } class Type(type: KotlinType, val possiblyBareType: PossiblyBareType) : DoubleColonLHS(type) } @@ -82,7 +86,9 @@ class DoubleColonExpressionResolver( val type = result?.type if (type != null && !type.isError) { checkClassLiteral(c, expression, result!!) - return dataFlowAnalyzer.createCheckedTypeInfo(reflectionTypes.getKClassType(Annotations.EMPTY, type), c, expression) + val kClassType = reflectionTypes.getKClassType(Annotations.EMPTY, type) + val dataFlowInfo = (result as? DoubleColonLHS.Expression)?.dataFlowInfo ?: c.dataFlowInfo + return dataFlowAnalyzer.checkType(createTypeInfo(kClassType, dataFlowInfo), expression, c) } } @@ -151,7 +157,7 @@ class DoubleColonExpressionResolver( if (shouldTryResolveLHSAsExpression(doubleColonExpression)) { val traceForExpr = TemporaryTraceAndCache.create(c, "resolve '::' LHS as expression", expression) - val contextForExpr = c.replaceTraceAndCache(traceForExpr) + val contextForExpr = c.replaceTraceAndCache(traceForExpr).replaceExpectedType(NO_EXPECTED_TYPE) val typeInfo = expressionTypingServices.getTypeInfo(expression, contextForExpr) val type = typeInfo.type @@ -255,7 +261,8 @@ class DoubleColonExpressionResolver( val (lhs, resolutionResults) = resolveCallableReference(expression, c, ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS) val result = getCallableReferenceType(expression, lhs, resolutionResults, c) - return dataFlowAnalyzer.createCheckedTypeInfo(result, c, expression) + val dataFlowInfo = (lhs as? DoubleColonLHS.Expression)?.dataFlowInfo ?: c.dataFlowInfo + return dataFlowAnalyzer.checkType(createTypeInfo(result, dataFlowInfo), expression, c) } private fun getCallableReferenceType( diff --git a/compiler/testData/diagnostics/tests/callableReference/bound/dataFlow.kt b/compiler/testData/diagnostics/tests/callableReference/bound/dataFlow.kt new file mode 100644 index 00000000000..ed27db76ec5 --- /dev/null +++ b/compiler/testData/diagnostics/tests/callableReference/bound/dataFlow.kt @@ -0,0 +1,13 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE + +import kotlin.reflect.KClass + +fun f1(x: String?): String { + x!!::hashCode + return x +} + +fun f2(y: String?): String { + val f: KClass<*> = (y ?: return "")::class + return y +} diff --git a/compiler/testData/diagnostics/tests/callableReference/bound/dataFlow.txt b/compiler/testData/diagnostics/tests/callableReference/bound/dataFlow.txt new file mode 100644 index 00000000000..9d30384d6ea --- /dev/null +++ b/compiler/testData/diagnostics/tests/callableReference/bound/dataFlow.txt @@ -0,0 +1,4 @@ +package + +public fun f1(/*0*/ x: kotlin.String?): kotlin.String +public fun f2(/*0*/ y: kotlin.String?): kotlin.String diff --git a/compiler/testData/diagnostics/tests/callableReference/bound/expectedType.kt b/compiler/testData/diagnostics/tests/callableReference/bound/expectedType.kt new file mode 100644 index 00000000000..689c3b8c4c0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/callableReference/bound/expectedType.kt @@ -0,0 +1,12 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE + +import kotlin.reflect.KClass + +fun test(s: String) { + val f: () -> Int = s::hashCode + val g: () -> String = s::toString + val h: (Any?) -> Boolean = s::equals + + val k: KClass = s::class + val l: KClass<*> = s::class +} diff --git a/compiler/testData/diagnostics/tests/callableReference/bound/expectedType.txt b/compiler/testData/diagnostics/tests/callableReference/bound/expectedType.txt new file mode 100644 index 00000000000..179719441aa --- /dev/null +++ b/compiler/testData/diagnostics/tests/callableReference/bound/expectedType.txt @@ -0,0 +1,3 @@ +package + +public fun test(/*0*/ s: kotlin.String): kotlin.Unit diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 0abcfe215c4..a25e896730c 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -1739,6 +1739,18 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("dataFlow.kt") + public void testDataFlow() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/bound/dataFlow.kt"); + doTest(fileName); + } + + @TestMetadata("expectedType.kt") + public void testExpectedType() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/bound/expectedType.kt"); + doTest(fileName); + } + @TestMetadata("functionCallWithoutArguments.kt") public void testFunctionCallWithoutArguments() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/bound/functionCallWithoutArguments.kt");