From a9391c8dfb9c059771395bc90ae05429f6fba4ac Mon Sep 17 00:00:00 2001 From: Pavel Kirpichenkov Date: Mon, 23 Dec 2019 12:28:39 +0300 Subject: [PATCH] [NI] Remove Nothing result type restriction in most cases Make Nothing as result type not suitable only for if, when, try and ?: special functions. --- .../kotlin/fir/resolve/calls/InferenceUtil.kt | 3 +- ...irOldFrontendDiagnosticsTestGenerated.java | 10 ++++ .../resolve/calls/GenericCandidateResolver.kt | 2 +- ...plicitNothingAsTypeParameterCallChecker.kt | 3 +- .../tower/KotlinResolutionCallbacksImpl.kt | 1 + .../KotlinResolutionStatelessCallbacksImpl.kt | 10 ++++ .../calls/components/ExternalComponents.kt | 6 +- .../KotlinConstraintSystemCompleter.kt | 4 +- .../components/ResultTypeResolver.kt | 60 +++++++++++-------- .../TrivialConstraintTypeInferenceOracle.kt | 9 +++ .../controlFlowAnalysis/throwInLambda.fir.kt | 1 - .../controlFlowAnalysis/throwInLambda.kt | 3 +- .../lambdaNothingAndExpectedType.fir.kt | 2 +- .../inference/regressions/kt32106.fir.kt | 22 +++++++ .../tests/inference/regressions/kt32106.kt | 22 +++++++ .../tests/inference/regressions/kt32106.txt | 31 ++++++++++ .../testData/diagnostics/tests/when/kt9929.kt | 2 +- .../when/whenAndLambdaWithExpectedType.kt | 6 +- .../tests/when/whenWithNothingAndLambdas.kt | 6 +- .../checkers/DiagnosticsTestGenerated.java | 5 ++ .../DiagnosticsUsingJavacTestGenerated.java | 5 ++ 21 files changed, 172 insertions(+), 41 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/inference/regressions/kt32106.fir.kt create mode 100644 compiler/testData/diagnostics/tests/inference/regressions/kt32106.kt create mode 100644 compiler/testData/diagnostics/tests/inference/regressions/kt32106.txt diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/InferenceUtil.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/InferenceUtil.kt index 0822ab73b87..82fd5307d41 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/InferenceUtil.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/InferenceUtil.kt @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintInjecto import org.jetbrains.kotlin.resolve.calls.inference.components.ResultTypeResolver import org.jetbrains.kotlin.resolve.calls.inference.components.TrivialConstraintTypeInferenceOracle import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl +import org.jetbrains.kotlin.resolve.calls.tower.KotlinResolutionStatelessCallbacksImpl import org.jetbrains.kotlin.types.AbstractTypeApproximator import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner import org.jetbrains.kotlin.types.model.SimpleTypeMarker @@ -53,7 +54,7 @@ class InferenceComponents( val trivialConstraintTypeInferenceOracle = TrivialConstraintTypeInferenceOracle.create(ctx) private val incorporator = ConstraintIncorporator(approximator, trivialConstraintTypeInferenceOracle) private val injector = ConstraintInjector(incorporator, approximator, KotlinTypeRefiner.Default) - val resultTypeResolver = ResultTypeResolver(approximator, trivialConstraintTypeInferenceOracle) + val resultTypeResolver = ResultTypeResolver(approximator, trivialConstraintTypeInferenceOracle, null) fun createConstraintSystem(): NewConstraintSystemImpl { return NewConstraintSystemImpl(injector, ctx) diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java index c343843580d..563c3c35c99 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java @@ -10595,6 +10595,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte runTest("compiler/testData/diagnostics/tests/inference/nothingType/implicitNothingConstraintFromReturn.kt"); } + @TestMetadata("inferArgumentToNothingFromNullConstant.kt") + public void testInferArgumentToNothingFromNullConstant() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/nothingType/inferArgumentToNothingFromNullConstant.kt"); + } + @TestMetadata("kt24490.kt") public void testKt24490() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/nothingType/kt24490.kt"); @@ -10889,6 +10894,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte runTest("compiler/testData/diagnostics/tests/inference/regressions/kt3174.kt"); } + @TestMetadata("kt32106.kt") + public void testKt32106() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/regressions/kt32106.kt"); + } + @TestMetadata("kt32250.kt") public void testKt32250() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/regressions/kt32250.kt"); 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 d42045c16e4..32198514bcb 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt @@ -50,7 +50,7 @@ import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils import org.jetbrains.kotlin.types.typeUtil.makeNullable import org.jetbrains.kotlin.utils.addToStdlib.safeAs -private val SPECIAL_FUNCTION_NAMES = ResolveConstruct.values().map { it.specialFunctionName }.toSet() +val SPECIAL_FUNCTION_NAMES = ResolveConstruct.values().map { it.specialFunctionName }.toSet() class GenericCandidateResolver( private val argumentTypeResolver: ArgumentTypeResolver, diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ImplicitNothingAsTypeParameterCallChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ImplicitNothingAsTypeParameterCallChecker.kt index ba302f77e30..df7655ac009 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ImplicitNothingAsTypeParameterCallChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ImplicitNothingAsTypeParameterCallChecker.kt @@ -9,6 +9,7 @@ import com.intellij.psi.PsiElement import org.jetbrains.kotlin.builtins.isBuiltinFunctionalType import org.jetbrains.kotlin.builtins.isFunctionType import org.jetbrains.kotlin.diagnostics.Errors +import org.jetbrains.kotlin.resolve.calls.SPECIAL_FUNCTION_NAMES import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.types.DeferredType import org.jetbrains.kotlin.types.TypeUtils @@ -17,8 +18,6 @@ import org.jetbrains.kotlin.types.typeUtil.isNothing import org.jetbrains.kotlin.types.typeUtil.isTypeParameter object ImplicitNothingAsTypeParameterCallChecker : CallChecker { - private val SPECIAL_FUNCTION_NAMES = ControlStructureTypingUtils.ResolveConstruct.values().map { it.specialFunctionName }.toSet() - /* * The warning isn't reported in cases where there are lambda among the function arguments, * the return type of which is a type variable, that was inferred to Nothing. diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt index 253633c44b8..db3ce7b34f4 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.psi.psiUtil.getBinaryWithTypeParent import org.jetbrains.kotlin.psi.psiUtil.lastBlockStatementOrThis import org.jetbrains.kotlin.resolve.* import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver +import org.jetbrains.kotlin.resolve.calls.SPECIAL_FUNCTION_NAMES import org.jetbrains.kotlin.resolve.calls.components.InferenceSession import org.jetbrains.kotlin.resolve.calls.components.KotlinResolutionCallbacks import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionStatelessCallbacksImpl.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionStatelessCallbacksImpl.kt index 5034bc1257a..532ab51b610 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionStatelessCallbacksImpl.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionStatelessCallbacksImpl.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtSuperExpression import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isConventionCall @@ -39,6 +40,7 @@ import org.jetbrains.kotlin.resolve.calls.model.KotlinCallArgument import org.jetbrains.kotlin.resolve.calls.model.SimpleKotlinCallArgument import org.jetbrains.kotlin.resolve.calls.results.SimpleConstraintSystem import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver +import org.jetbrains.kotlin.types.expressions.ControlStructureTypingUtils import org.jetbrains.kotlin.utils.addToStdlib.safeAs class KotlinResolutionStatelessCallbacksImpl( @@ -95,4 +97,12 @@ class KotlinResolutionStatelessCallbacksImpl( else ConstraintSystemBuilderImpl.forSpecificity() } + + override fun isSpecialFunctionTypeParameterName(name: Name): Boolean { + return ControlStructureTypingUtils.ResolveConstruct.values().any { it.specialTypeParameterName == name } + } + + override fun isExclExclTypeParameterName(name: Name): Boolean { + return name == ControlStructureTypingUtils.ResolveConstruct.EXCL_EXCL.specialTypeParameterName + } } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt index c72bf42d617..5ec9f8ba7d9 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt @@ -12,12 +12,12 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintInjector import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.results.SimpleConstraintSystem import org.jetbrains.kotlin.resolve.calls.tower.ImplicitScopeTower -import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo import org.jetbrains.kotlin.types.StubType import org.jetbrains.kotlin.types.UnwrappedType @@ -40,6 +40,10 @@ interface KotlinResolutionStatelessCallbacks { fun createConstraintSystemForOverloadResolution( constraintInjector: ConstraintInjector, builtIns: KotlinBuiltIns ): SimpleConstraintSystem + + fun isSpecialFunctionTypeParameterName(name: Name): Boolean + + fun isExclExclTypeParameterName(name: Name): Boolean } // This components hold state (trace). Work with this carefully. diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/KotlinConstraintSystemCompleter.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/KotlinConstraintSystemCompleter.kt index 64ced81aa25..8f8d1b941c3 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/KotlinConstraintSystemCompleter.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/KotlinConstraintSystemCompleter.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.resolve.calls.inference.components +import org.jetbrains.kotlin.resolve.calls.components.KotlinResolutionStatelessCallbacks import org.jetbrains.kotlin.resolve.calls.inference.model.NotEnoughInformationForTypeParameter import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableFromCallableDescriptor import org.jetbrains.kotlin.resolve.calls.inference.model.VariableWithConstraints @@ -21,7 +22,8 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs class KotlinConstraintSystemCompleter( private val resultTypeResolver: ResultTypeResolver, - private val variableFixationFinder: VariableFixationFinder + private val variableFixationFinder: VariableFixationFinder, + private val statelessCallbacks: KotlinResolutionStatelessCallbacks ) { enum class ConstraintSystemCompletionMode { FULL, diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt index 0754fdb6489..651d3f33ce3 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt @@ -17,17 +17,21 @@ package org.jetbrains.kotlin.resolve.calls.inference.components import org.jetbrains.kotlin.resolve.calls.NewCommonSuperTypeCalculator +import org.jetbrains.kotlin.resolve.calls.components.KotlinResolutionStatelessCallbacks import org.jetbrains.kotlin.resolve.calls.inference.components.TypeVariableDirectionCalculator.ResolveDirection import org.jetbrains.kotlin.resolve.calls.inference.model.* import org.jetbrains.kotlin.types.AbstractTypeApproximator import org.jetbrains.kotlin.types.TypeApproximatorConfiguration import org.jetbrains.kotlin.types.model.KotlinTypeMarker +import org.jetbrains.kotlin.types.model.TypeVariableMarker +import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContext class ResultTypeResolver( val typeApproximator: AbstractTypeApproximator, - val trivialConstraintTypeInferenceOracle: TrivialConstraintTypeInferenceOracle + val trivialConstraintTypeInferenceOracle: TrivialConstraintTypeInferenceOracle, + private val statelessCallbacks: KotlinResolutionStatelessCallbacks? // TODO injection in FIR ) { interface Context : TypeSystemInferenceExtensionContext { fun isProperType(type: KotlinTypeMarker): Boolean @@ -43,18 +47,20 @@ class ResultTypeResolver( } } - fun findResultTypeOrNull(c: Context, variableWithConstraints: VariableWithConstraints, direction: ResolveDirection): KotlinTypeMarker? { + private fun findResultTypeOrNull( + c: Context, + variableWithConstraints: VariableWithConstraints, + direction: ResolveDirection + ): KotlinTypeMarker? { findResultIfThereIsEqualsConstraint(c, variableWithConstraints)?.let { return it } val subType = c.findSubType(variableWithConstraints) val superType = c.findSuperType(variableWithConstraints) - val result = if (direction == ResolveDirection.TO_SUBTYPE || direction == ResolveDirection.UNKNOWN) { + return if (direction == ResolveDirection.TO_SUBTYPE || direction == ResolveDirection.UNKNOWN) { c.resultType(subType, superType, variableWithConstraints) } else { c.resultType(superType, subType, variableWithConstraints) } - - return result } private fun Context.resultType( @@ -66,10 +72,10 @@ class ResultTypeResolver( if (isSuitableType(firstCandidate, variableWithConstraints)) return firstCandidate - if (isSuitableType(secondCandidate, variableWithConstraints)) { - return secondCandidate + return if (isSuitableType(secondCandidate, variableWithConstraints)) { + secondCandidate } else { - return firstCandidate + firstCandidate } } @@ -78,20 +84,21 @@ class ResultTypeResolver( if (!isProperType(constraint.type)) continue if (!checkConstraint(this, constraint.type, constraint.kind, resultType)) return false } - - /* - * If all upper constraints came from declared upper bounds we should accept Nothing - * as suitable type as OI does - */ if ( - variableWithConstraints.constraints.any { - it.kind == ConstraintKind.UPPER && it.position.from !is DeclaredUpperBoundConstraintPosition - } && !trivialConstraintTypeInferenceOracle.isSuitableResultedType(resultType) + !trivialConstraintTypeInferenceOracle.isSuitableResultedType(resultType) + && isNothingNotSuitableFor(variableWithConstraints.typeVariable) ) return false return true } + private fun isNothingNotSuitableFor(variable: TypeVariableMarker): Boolean { + val parameterName = variable.safeAs()?.originalTypeParameter?.name ?: return false + val isSpecialFunctionParameter = statelessCallbacks?.isSpecialFunctionTypeParameterName(parameterName) ?: false + val isBangBangParameter = isSpecialFunctionParameter && statelessCallbacks?.isExclExclTypeParameterName(parameterName) ?: false + return isSpecialFunctionParameter && !isBangBangParameter + } + private fun Context.findSubType(variableWithConstraints: VariableWithConstraints): KotlinTypeMarker? { val lowerConstraintTypes = prepareLowerConstraints(variableWithConstraints.constraints) @@ -163,22 +170,27 @@ class ResultTypeResolver( } private fun Context.findSuperType(variableWithConstraints: VariableWithConstraints): KotlinTypeMarker? { - val upperConstraints = variableWithConstraints.constraints.filter { it.kind == ConstraintKind.UPPER && this@findSuperType.isProperType(it.type) } + val upperConstraints = + variableWithConstraints.constraints.filter { it.kind == ConstraintKind.UPPER && this@findSuperType.isProperType(it.type) } if (upperConstraints.isNotEmpty()) { val upperType = intersectTypes(upperConstraints.map { it.type }) - return typeApproximator.approximateToSubType(upperType, TypeApproximatorConfiguration.CapturedAndIntegerLiteralsTypesApproximation) ?: upperType + return typeApproximator.approximateToSubType( + upperType, + TypeApproximatorConfiguration.CapturedAndIntegerLiteralsTypesApproximation + ) ?: upperType } return null } - fun findResultIfThereIsEqualsConstraint(c: Context, variableWithConstraints: VariableWithConstraints): KotlinTypeMarker? = with(c) { - val properEqualityConstraints = variableWithConstraints.constraints.filter { - it.kind == ConstraintKind.EQUALITY && c.isProperType(it.type) - } + private fun findResultIfThereIsEqualsConstraint(c: Context, variableWithConstraints: VariableWithConstraints): KotlinTypeMarker? = + with(c) { + val properEqualityConstraints = variableWithConstraints.constraints.filter { + it.kind == ConstraintKind.EQUALITY && c.isProperType(it.type) + } - return c.representativeFromEqualityConstraints(properEqualityConstraints) - } + return c.representativeFromEqualityConstraints(properEqualityConstraints) + } // Discriminate integer literal types as they are less specific than separate integer types (Int, Short...) private fun Context.representativeFromEqualityConstraints(constraints: List): KotlinTypeMarker? { diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TrivialConstraintTypeInferenceOracle.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TrivialConstraintTypeInferenceOracle.kt index 9d36037fec5..2174c009a62 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TrivialConstraintTypeInferenceOracle.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TrivialConstraintTypeInferenceOracle.kt @@ -23,6 +23,15 @@ class TrivialConstraintTypeInferenceOracle private constructor(context: TypeSyst return constraint.kind == ConstraintKind.LOWER && constraint.type.typeConstructor().isNothingConstructor() } + // This function controls the choice between sub and super result type + // Even that Nothing(?) is the most specific type for subtype, it doesn't bring valuable information to the user, + // therefore it is discriminated in favor of supertype + fun isSuitableResultedType( + resultType: KotlinTypeMarker + ): Boolean { + return !resultType.typeConstructor().isNothingConstructor() + } + // It's possible to generate Nothing-like constraints inside incorporation mechanism: // For instance, when two type variables are in subtyping relation `T <: K`, after incorporation // there will be constraint `approximation(out K) <: K` => `Nothing <: K`, which is innocent diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/throwInLambda.fir.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/throwInLambda.fir.kt index 40108a81c53..3a71250e7bf 100644 --- a/compiler/testData/diagnostics/tests/controlFlowAnalysis/throwInLambda.fir.kt +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/throwInLambda.fir.kt @@ -1,4 +1,3 @@ -// !WITH_NEW_INFERENCE // See KT-10913 Bogus unreachable code warning fun fn() : String? = null diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/throwInLambda.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/throwInLambda.kt index faa28f2353d..3c937e6f72e 100644 --- a/compiler/testData/diagnostics/tests/controlFlowAnalysis/throwInLambda.kt +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/throwInLambda.kt @@ -1,4 +1,3 @@ -// !WITH_NEW_INFERENCE // See KT-10913 Bogus unreachable code warning fun fn() : String? = null @@ -8,6 +7,6 @@ fun foo(): String { } fun bar(): String { val x = fn() ?: return "" - val y = x?.let { throw Exception() } ?: "unreachable" + val y = x?.let { throw Exception() } ?: "unreachable" return y } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/nothingType/lambdaNothingAndExpectedType.fir.kt b/compiler/testData/diagnostics/tests/inference/nothingType/lambdaNothingAndExpectedType.fir.kt index f2eec49bdec..ada20a74fa9 100644 --- a/compiler/testData/diagnostics/tests/inference/nothingType/lambdaNothingAndExpectedType.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/nothingType/lambdaNothingAndExpectedType.fir.kt @@ -1,4 +1,4 @@ -// !LANGUAGE: +NewInference +// !WITH_NEW_INFERENCE // !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE fun select2(x: K, y: K): K = TODO() diff --git a/compiler/testData/diagnostics/tests/inference/regressions/kt32106.fir.kt b/compiler/testData/diagnostics/tests/inference/regressions/kt32106.fir.kt new file mode 100644 index 00000000000..d21d725acbb --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/regressions/kt32106.fir.kt @@ -0,0 +1,22 @@ +// !LANGUAGE: +NewInference + +class Query private constructor( + private val result: T?, + private val error: Throwable?, + val inProgress: Boolean +) { + companion object { + val inProgress = Query(null, null, true) + fun forError(e: Throwable) = Query(null, e, false) + fun forResult(result: T) = Query(result, null, false) + } +} + +class MutableLiveData { + var value: Query = null!! +} + +fun main() { + val liveData = MutableLiveData>() + liveData.value = Query.inProgress // Type mismatch: inferred type is Query but Query was expected +} diff --git a/compiler/testData/diagnostics/tests/inference/regressions/kt32106.kt b/compiler/testData/diagnostics/tests/inference/regressions/kt32106.kt new file mode 100644 index 00000000000..d21d725acbb --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/regressions/kt32106.kt @@ -0,0 +1,22 @@ +// !LANGUAGE: +NewInference + +class Query private constructor( + private val result: T?, + private val error: Throwable?, + val inProgress: Boolean +) { + companion object { + val inProgress = Query(null, null, true) + fun forError(e: Throwable) = Query(null, e, false) + fun forResult(result: T) = Query(result, null, false) + } +} + +class MutableLiveData { + var value: Query = null!! +} + +fun main() { + val liveData = MutableLiveData>() + liveData.value = Query.inProgress // Type mismatch: inferred type is Query but Query was expected +} diff --git a/compiler/testData/diagnostics/tests/inference/regressions/kt32106.txt b/compiler/testData/diagnostics/tests/inference/regressions/kt32106.txt new file mode 100644 index 00000000000..0cb10d2ef39 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/regressions/kt32106.txt @@ -0,0 +1,31 @@ +package + +public fun main(): kotlin.Unit + +public final class MutableLiveData { + public constructor MutableLiveData() + public final var value: Query + 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 +} + +public final class Query { + private constructor Query(/*0*/ result: T?, /*1*/ error: kotlin.Throwable?, /*2*/ inProgress: kotlin.Boolean) + private final val error: kotlin.Throwable? + public final val inProgress: kotlin.Boolean + private final val result: T? + 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 + + public companion object Companion { + private constructor Companion() + public final val inProgress: Query + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun forError(/*0*/ e: kotlin.Throwable): Query + public final fun forResult(/*0*/ result: T): Query + 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/tests/when/kt9929.kt b/compiler/testData/diagnostics/tests/when/kt9929.kt index f1dc2682288..c94ac61f194 100644 --- a/compiler/testData/diagnostics/tests/when/kt9929.kt +++ b/compiler/testData/diagnostics/tests/when/kt9929.kt @@ -1,5 +1,5 @@ // !WITH_NEW_INFERENCE -val test: Int = if (true) { +val test: Int = if (true) { when (2) { 1 -> 1 else -> null diff --git a/compiler/testData/diagnostics/tests/when/whenAndLambdaWithExpectedType.kt b/compiler/testData/diagnostics/tests/when/whenAndLambdaWithExpectedType.kt index afa25e6ef56..4011f9bdcc4 100644 --- a/compiler/testData/diagnostics/tests/when/whenAndLambdaWithExpectedType.kt +++ b/compiler/testData/diagnostics/tests/when/whenAndLambdaWithExpectedType.kt @@ -7,19 +7,19 @@ val test1: (String) -> Boolean = val test2: (String) -> Boolean = when { - true -> {{ true }} + true -> {{ true }} else -> null!! } val test3: (String) -> Boolean = when { - true -> { s -> true } + true -> { s -> true } else -> null!! } val test4: (String) -> Boolean = when { - true -> { s1, s2 -> true } + true -> { s1, s2 -> true } else -> null!! } diff --git a/compiler/testData/diagnostics/tests/when/whenWithNothingAndLambdas.kt b/compiler/testData/diagnostics/tests/when/whenWithNothingAndLambdas.kt index 87fcc28d214..51c460c3797 100644 --- a/compiler/testData/diagnostics/tests/when/whenWithNothingAndLambdas.kt +++ b/compiler/testData/diagnostics/tests/when/whenWithNothingAndLambdas.kt @@ -6,7 +6,7 @@ val test1 = when { } val test1a: () -> Boolean = when { - true -> { { true } } + true -> { { true } } else -> TODO() } @@ -33,7 +33,7 @@ val test3 = when { } val test3a: () -> Boolean = when { - true -> { { true } } - true -> { { true } } + true -> { { true } } + true -> { { true } } else -> TODO() } \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index a177836d105..8b64711d43d 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -10901,6 +10901,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { runTest("compiler/testData/diagnostics/tests/inference/regressions/kt3174.kt"); } + @TestMetadata("kt32106.kt") + public void testKt32106() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/regressions/kt32106.kt"); + } + @TestMetadata("kt32250.kt") public void testKt32250() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/regressions/kt32250.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 8bba20adcd8..e831d6de918 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -10896,6 +10896,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/inference/regressions/kt3174.kt"); } + @TestMetadata("kt32106.kt") + public void testKt32106() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/regressions/kt32106.kt"); + } + @TestMetadata("kt32250.kt") public void testKt32250() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/regressions/kt32250.kt");