[NI] Report unstable smart cast directly instead of using SmartCastManager

Fix compilation errors, revealed by this fix.

SmartCastManager is unnecessary for error reporting, intermediate diagnostics from the NI contain all required infromation.
When SmartCastManager is used it leads to missing unstable smart casts in case of expressions with captured types.
This happens, because data flow info is recorded for original expression without captured types, which is used as a key.
DataFlowValues created from receivers with captured types can't be used to retrieve that info.

^KT-39010 Fixed
This commit is contained in:
Pavel Kirpichenkov
2020-05-20 12:49:38 +03:00
parent b808d5f381
commit 0b33e9430b
15 changed files with 156 additions and 15 deletions
@@ -21545,6 +21545,16 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
runTest("compiler/testData/diagnostics/tests/smartCasts/inference/kt29767.kt");
}
@TestMetadata("kt39010.kt")
public void testKt39010() throws Exception {
runTest("compiler/testData/diagnostics/tests/smartCasts/inference/kt39010.kt");
}
@TestMetadata("kt39010_2.kt")
public void testKt39010_2() throws Exception {
runTest("compiler/testData/diagnostics/tests/smartCasts/inference/kt39010_2.kt");
}
@TestMetadata("kt4009.kt")
public void testKt4009() throws Exception {
runTest("compiler/testData/diagnostics/tests/smartCasts/inference/kt4009.kt");
@@ -415,19 +415,19 @@ private val nameToOperationConventionOrigin = mutableMapOf(
internal fun FirReference.statementOrigin(): IrStatementOrigin? {
return when (this) {
is FirPropertyFromParameterResolvedNamedReference -> IrStatementOrigin.INITIALIZE_PROPERTY_FROM_PARAMETER
is FirResolvedNamedReference -> when (resolvedSymbol) {
is FirResolvedNamedReference -> when (val symbol = resolvedSymbol) {
is AccessorSymbol, is SyntheticPropertySymbol -> IrStatementOrigin.GET_PROPERTY
is FirNamedFunctionSymbol -> when {
resolvedSymbol.callableId.isInvoke() ->
symbol.callableId.isInvoke() ->
IrStatementOrigin.INVOKE
source?.elementType == KtNodeTypes.FOR && resolvedSymbol.callableId.isIteratorNext() ->
source?.elementType == KtNodeTypes.FOR && symbol.callableId.isIteratorNext() ->
IrStatementOrigin.FOR_LOOP_NEXT
source?.elementType == KtNodeTypes.FOR && resolvedSymbol.callableId.isIteratorHasNext() ->
source?.elementType == KtNodeTypes.FOR && symbol.callableId.isIteratorHasNext() ->
IrStatementOrigin.FOR_LOOP_HAS_NEXT
source?.elementType == KtNodeTypes.FOR && resolvedSymbol.callableId.isIterator() ->
source?.elementType == KtNodeTypes.FOR && symbol.callableId.isIterator() ->
IrStatementOrigin.FOR_LOOP_ITERATOR
source?.elementType == KtNodeTypes.OPERATION_REFERENCE ->
nameToOperationConventionOrigin[resolvedSymbol.callableId.callableName]
nameToOperationConventionOrigin[symbol.callableId.callableName]
else ->
null
}
@@ -76,7 +76,7 @@ class IntegerLiteralTypeApproximationTransformer(
// check black box tests
// e.g. Byte doesn't have `and` in member scope. It's an extension
if (resultSymbol == null) return functionCall.compose()
functionCall.resultType = data?.let { functionCall.resultType.resolvedTypeFromPrototype(it) } ?: resultSymbol.fir.returnTypeRef
functionCall.resultType = data?.let { functionCall.resultType.resolvedTypeFromPrototype(it) } ?: resultSymbol!!.fir.returnTypeRef
// If the original call has argument mapping, values in that mapping refer to value parameters in that original symbol. We should
// map those original value parameters back to indices, and then renew the argument mapping with new value parameters in the result
// symbol. Otherwise, while putting the value argument to the converted IR call, it will encounter an unknown value parameter,
@@ -84,7 +84,7 @@ class IntegerLiteralTypeApproximationTransformer(
val newArgumentMapping =
functionCall.argumentMapping?.mapValues { (_, oldValueParameter) ->
val index = operator.valueParameters.indexOf(oldValueParameter)
if (index != -1) resultSymbol.fir.valueParameters[index] else oldValueParameter
if (index != -1) resultSymbol!!.fir.valueParameters[index] else oldValueParameter
}
return functionCall.transformCalleeReference(
StoreCalleeReference,
@@ -79,7 +79,7 @@ abstract class AbstractFirUseSiteMemberScope(
createFunctionCopy(firSimpleFunction, newSymbol).apply {
resolvePhase = firSimpleFunction.resolvePhase
typeParameters += firSimpleFunction.typeParameters
valueParameters += firSimpleFunction.valueParameters.zip(foundFir.valueParameters)
valueParameters += firSimpleFunction.valueParameters.zip(foundFir!!.valueParameters)
.map { (overrideParameter, overriddenParameter) ->
if (overriddenParameter.defaultValue != null)
createValueParameterCopy(overrideParameter, overriddenParameter.defaultValue).apply {
@@ -34,8 +34,9 @@ internal class FirWhenExpressionImpl(
typeRef.accept(visitor, data)
annotations.forEach { it.accept(visitor, data) }
calleeReference.accept(visitor, data)
if (subjectVariable != null) {
subjectVariable.accept(visitor, data)
val subjectVariable_ = subjectVariable
if (subjectVariable_ != null) {
subjectVariable_.accept(visitor, data)
} else {
subject?.accept(visitor, data)
}
@@ -150,8 +150,9 @@ fun SmartPrinter.printImplementation(implementation: Implementation) {
if (type == "FirWhenExpressionImpl" && field.name == "subject") {
println(
"""
|if (subjectVariable != null) {
| subjectVariable.accept(visitor, data)
|val subjectVariable_ = subjectVariable
| if (subjectVariable_ != null) {
| subjectVariable_.accept(visitor, data)
| } else {
| subject?.accept(visitor, data)
| }